linux/fs/xfs
Darrick J. Wong 089558bc7b xfs: remove all COW fork extents when remounting readonly
As part of multiple customer escalations due to file data corruption
after copy on write operations, I wrote some fstests that use fsstress
to hammer on COW to shake things loose.  Regrettably, I caught some
filesystem shutdowns due to incorrect rmap operations with the following
loop:

mount <filesystem>				# (0)
fsstress <run only readonly ops> &		# (1)
while true; do
	fsstress <run all ops>
	mount -o remount,ro			# (2)
	fsstress <run only readonly ops>
	mount -o remount,rw			# (3)
done

When (2) happens, notice that (1) is still running.  xfs_remount_ro will
call xfs_blockgc_stop to walk the inode cache to free all the COW
extents, but the blockgc mechanism races with (1)'s reader threads to
take IOLOCKs and loses, which means that it doesn't clean them all out.
Call such a file (A).

When (3) happens, xfs_remount_rw calls xfs_reflink_recover_cow, which
walks the ondisk refcount btree and frees any COW extent that it finds.
This function does not check the inode cache, which means that incore
COW forks of inode (A) is now inconsistent with the ondisk metadata.  If
one of those former COW extents are allocated and mapped into another
file (B) and someone triggers a COW to the stale reservation in (A), A's
dirty data will be written into (B) and once that's done, those blocks
will be transferred to (A)'s data fork without bumping the refcount.

The results are catastrophic -- file (B) and the refcount btree are now
corrupt.  Solve this race by forcing the xfs_blockgc_free_space to run
synchronously, which causes xfs_icwalk to return to inodes that were
skipped because the blockgc code couldn't take the IOLOCK.  This is safe
to do here because the VFS has already prohibited new writer threads.

Fixes: 10ddf64e42 ("xfs: remove leftover CoW reservations when remounting ro")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Chandan Babu R <chandan.babu@oracle.com>
2021-12-07 10:17:29 -08:00
..
libxfs xfs: Fix the free logic of state in xfs_attr_node_hasname 2021-11-24 10:06:02 -08:00
scrub xfs: rename m_ag_maxlevels to m_allocbt_maxlevels 2021-10-19 11:45:15 -07:00
Kconfig
kmem.c
kmem.h xfs: remove kmem_zone typedef 2021-10-22 16:00:31 -07:00
Makefile
mrlock.h
xfs_acl.c overlayfs update for 5.15 2021-09-02 09:21:27 -07:00
xfs_acl.h
xfs_aops.c xfs: punch out data fork delalloc blocks on COW writeback failure 2021-10-22 16:04:36 -07:00
xfs_aops.h
xfs_attr_inactive.c xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_attr_list.c
xfs_bio_io.c
xfs_bmap_item.c xfs: create slab caches for frequently-used deferred items 2021-10-22 16:04:36 -07:00
xfs_bmap_item.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_bmap_util.c New code for 5.15: 2021-09-02 08:26:03 -07:00
xfs_bmap_util.h
xfs_buf_item_recover.c xfs: remove the xfs_dinode_t typedef 2021-10-14 09:19:33 -07:00
xfs_buf_item.c xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_buf_item.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_buf.c xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_buf.h
xfs_dir2_readdir.c
xfs_discard.c
xfs_discard.h
xfs_dquot_item_recover.c
xfs_dquot_item.c
xfs_dquot_item.h
xfs_dquot.c xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_dquot.h
xfs_error.c
xfs_error.h
xfs_export.c
xfs_export.h
xfs_extent_busy.c
xfs_extent_busy.h
xfs_extfree_item.c xfs: reduce the size of struct xfs_extent_free_item 2021-10-22 16:04:36 -07:00
xfs_extfree_item.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_file.c gfs2: Fix mmap + page fault deadlocks 2021-11-02 12:25:03 -07:00
xfs_filestream.c
xfs_filestream.h
xfs_fsmap.c
xfs_fsmap.h
xfs_fsops.c
xfs_fsops.h
xfs_globals.c
xfs_health.c
xfs_icache.c xfs: remove xfs_inew_wait 2021-11-24 10:06:02 -08:00
xfs_icache.h
xfs_icreate_item.c xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_icreate_item.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_inode_item_recover.c
xfs_inode_item.c xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_inode_item.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_inode.c xfs: remove incorrect ASSERT in xfs_rename 2021-12-01 17:27:48 -08:00
xfs_inode.h xfs: remove xfs_inew_wait 2021-11-24 10:06:02 -08:00
xfs_ioctl32.c
xfs_ioctl32.h
xfs_ioctl.c xfs: Use kvcalloc() instead of kvzalloc() 2021-10-20 18:14:12 -05:00
xfs_ioctl.h
xfs_iomap.c
xfs_iomap.h
xfs_iops.c
xfs_iops.h
xfs_itable.c
xfs_itable.h
xfs_iwalk.c
xfs_iwalk.h
xfs_linux.h
xfs_log_cil.c
xfs_log_priv.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_log_recover.c xfs: port the defer ops capture and continue to resource capture 2021-10-14 09:19:31 -07:00
xfs_log.c xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_log.h
xfs_message.c
xfs_message.h
xfs_mount.c xfs: compute maximum AG btree height for critical reservation calculation 2021-10-19 11:45:15 -07:00
xfs_mount.h xfs: compute maximum AG btree height for critical reservation calculation 2021-10-19 11:45:15 -07:00
xfs_mru_cache.c xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_mru_cache.h
xfs_ondisk.h
xfs_pnfs.c
xfs_pnfs.h
xfs_pwork.c
xfs_pwork.h
xfs_qm_bhv.c
xfs_qm_syscalls.c
xfs_qm.c xfs: remove the xfs_dqblk_t typedef 2021-10-14 09:19:33 -07:00
xfs_qm.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_quota.h
xfs_quotaops.c
xfs_refcount_item.c xfs: create slab caches for frequently-used deferred items 2021-10-22 16:04:36 -07:00
xfs_refcount_item.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_reflink.c xfs: rename xfs_bmap_add_free to xfs_free_extent_later 2021-10-22 16:04:36 -07:00
xfs_reflink.h
xfs_rmap_item.c xfs: create slab caches for frequently-used deferred items 2021-10-22 16:04:36 -07:00
xfs_rmap_item.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_rtalloc.c
xfs_rtalloc.h
xfs_stats.c
xfs_stats.h
xfs_super.c xfs: remove all COW fork extents when remounting readonly 2021-12-07 10:17:29 -08:00
xfs_super.h
xfs_symlink.c
xfs_symlink.h
xfs_sysctl.c
xfs_sysctl.h
xfs_sysfs.c xfs: replace snprintf in show functions with sysfs_emit 2021-10-19 11:45:12 -07:00
xfs_sysfs.h
xfs_trace.c
xfs_trace.h xfs: prepare xfs_btree_cur for dynamic cursor heights 2021-10-19 11:45:14 -07:00
xfs_trans_ail.c
xfs_trans_buf.c
xfs_trans_dquot.c xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_trans_priv.h
xfs_trans.c xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_trans.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_xattr.c
xfs.h