c95356ca88
While fuzzing the data fork extent count on a btree-format directory with xfs/375, I observed the following (excerpted) splat: XFS: Assertion failed: xfs_isilocked(ip, XFS_ILOCK_EXCL), file: fs/xfs/libxfs/xfs_bmap.c, line: 1208 ------------[ cut here ]------------ WARNING: CPU: 0 PID: 43192 at fs/xfs/xfs_message.c:104 assfail+0x46/0x4a [xfs] Call Trace: <TASK> xfs_iread_extents+0x1af/0x210 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd] xchk_dir_walk+0xb8/0x190 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd] xchk_parent_count_parent_dentries+0x41/0x80 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd] xchk_parent_validate+0x199/0x2e0 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd] xchk_parent+0xdf/0x130 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd] xfs_scrub_metadata+0x2b8/0x730 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd] xfs_scrubv_metadata+0x38b/0x4d0 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd] xfs_ioc_scrubv_metadata+0x111/0x160 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd] xfs_file_ioctl+0x367/0xf50 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd] __x64_sys_ioctl+0x82/0xa0 do_syscall_64+0x2b/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 The cause of this is a race condition in xfs_ilock_data_map_shared, which performs an unlocked access to the data fork to guess which lock mode it needs: Thread 0 Thread 1 xfs_need_iread_extents <observe no iext tree> xfs_ilock(..., ILOCK_EXCL) xfs_iread_extents <observe no iext tree> <check ILOCK_EXCL> <load bmbt extents into iext> <notice iext size doesn't match nextents> xfs_need_iread_extents <observe iext tree> xfs_ilock(..., ILOCK_SHARED) <tear down iext tree> xfs_iunlock(..., ILOCK_EXCL) xfs_iread_extents <observe no iext tree> <check ILOCK_EXCL> *BOOM* Fix this race by adding a flag to the xfs_ifork structure to indicate that we have not yet read in the extent records and changing the predicate to look at the flag state, not if_height. The memory barrier ensures that the flag will not be set until the very end of the function. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com> |
||
---|---|---|
.. | ||
libxfs | ||
scrub | ||
Kconfig | ||
kmem.c | ||
kmem.h | ||
Makefile | ||
mrlock.h | ||
xfs_acl.c | ||
xfs_acl.h | ||
xfs_aops.c | ||
xfs_aops.h | ||
xfs_attr_inactive.c | ||
xfs_attr_item.c | ||
xfs_attr_item.h | ||
xfs_attr_list.c | ||
xfs_bio_io.c | ||
xfs_bmap_item.c | ||
xfs_bmap_item.h | ||
xfs_bmap_util.c | ||
xfs_bmap_util.h | ||
xfs_buf_item_recover.c | ||
xfs_buf_item.c | ||
xfs_buf_item.h | ||
xfs_buf.c | ||
xfs_buf.h | ||
xfs_dahash_test.c | ||
xfs_dahash_test.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_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_extfree_item.h | ||
xfs_file.c | ||
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_icache.h | ||
xfs_icreate_item.c | ||
xfs_icreate_item.h | ||
xfs_inode_item_recover.c | ||
xfs_inode_item.c | ||
xfs_inode_item.h | ||
xfs_inode.c | ||
xfs_inode.h | ||
xfs_ioctl32.c | ||
xfs_ioctl32.h | ||
xfs_ioctl.c | ||
xfs_ioctl.h | ||
xfs_iomap.c | ||
xfs_iomap.h | ||
xfs_iops.c | ||
xfs_iops.h | ||
xfs_itable.c | ||
xfs_itable.h | ||
xfs_iunlink_item.c | ||
xfs_iunlink_item.h | ||
xfs_iwalk.c | ||
xfs_iwalk.h | ||
xfs_linux.h | ||
xfs_log_cil.c | ||
xfs_log_priv.h | ||
xfs_log_recover.c | ||
xfs_log.c | ||
xfs_log.h | ||
xfs_message.c | ||
xfs_message.h | ||
xfs_mount.c | ||
xfs_mount.h | ||
xfs_mru_cache.c | ||
xfs_mru_cache.h | ||
xfs_notify_failure.c | ||
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_qm.h | ||
xfs_quota.h | ||
xfs_quotaops.c | ||
xfs_refcount_item.c | ||
xfs_refcount_item.h | ||
xfs_reflink.c | ||
xfs_reflink.h | ||
xfs_rmap_item.c | ||
xfs_rmap_item.h | ||
xfs_rtalloc.c | ||
xfs_rtalloc.h | ||
xfs_stats.c | ||
xfs_stats.h | ||
xfs_super.c | ||
xfs_super.h | ||
xfs_symlink.c | ||
xfs_symlink.h | ||
xfs_sysctl.c | ||
xfs_sysctl.h | ||
xfs_sysfs.c | ||
xfs_sysfs.h | ||
xfs_trace.c | ||
xfs_trace.h | ||
xfs_trans_ail.c | ||
xfs_trans_buf.c | ||
xfs_trans_dquot.c | ||
xfs_trans_priv.h | ||
xfs_trans.c | ||
xfs_trans.h | ||
xfs_xattr.c | ||
xfs_xattr.h | ||
xfs.h |