linux/fs/xfs
Dave Chinner 198dd8aede xfs: punching delalloc extents on write failure is racy
xfs_buffered_write_iomap_end() has a comment about the safety of
punching delalloc extents based holding the IOLOCK_EXCL. This
comment is wrong, and punching delalloc extents is not race free.

When we punch out a delalloc extent after a write failure in
xfs_buffered_write_iomap_end(), we punch out the page cache with
truncate_pagecache_range() before we punch out the delalloc extents.
At this point, we only hold the IOLOCK_EXCL, so there is nothing
stopping mmap() write faults racing with this cleanup operation,
reinstantiating a folio over the range we are about to punch and
hence requiring the delalloc extent to be kept.

If this race condition is hit, we can end up with a dirty page in
the page cache that has no delalloc extent or space reservation
backing it. This leads to bad things happening at writeback time.

To avoid this race condition, we need the page cache truncation to
be atomic w.r.t. the extent manipulation. We can do this by holding
the mapping->invalidate_lock exclusively across this operation -
this will prevent new pages from being inserted into the page cache
whilst we are removing the pages and the backing extent and space
reservation.

Taking the mapping->invalidate_lock exclusively in the buffered
write IO path is safe - it naturally nests inside the IOLOCK (see
truncate and fallocate paths). iomap_zero_range() can be called from
under the mapping->invalidate_lock (from the truncate path via
either xfs_zero_eof() or xfs_truncate_page(), but iomap_zero_iter()
will not instantiate new delalloc pages (because it skips holes) and
hence will not ever need to punch out delalloc extents on failure.

Fix the locking issue, and clean up the code logic a little to avoid
unnecessary work if we didn't allocate the delalloc extent or wrote
the entire region we allocated.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
2022-11-23 12:40:11 +11:00
..
libxfs xfs: rename XFS_REFC_COW_START to _COWFLAG 2022-10-31 08:58:22 -07:00
scrub xfs: check record domain when accessing refcount records 2022-10-31 08:58:21 -07:00
Kconfig
kmem.c mm: introduce memalloc_retry_wait() 2022-01-15 16:30:29 +02:00
kmem.h xfs: remove kmem_zone typedef 2021-10-22 16:00:31 -07:00
Makefile - The usual batches of cleanups from Baoquan He, Muchun Song, Miaohe 2022-08-05 16:32:45 -07:00
mrlock.h
xfs_acl.c xfs: move xfs_attr_use_log_assist usage out of libxfs 2022-05-27 10:34:04 +10:00
xfs_acl.h xfs: improve __xfs_set_acl 2022-04-26 13:34:42 +10:00
xfs_aops.c mm/migrate: Add filemap_migrate_folio() 2022-08-02 12:34:04 -04:00
xfs_aops.h
xfs_attr_inactive.c xfs: don't leak memory when attr fork loading fails 2022-07-20 16:40:39 -07:00
xfs_attr_item.c xfs: dump corrupt recovered log intent items to dmesg consistently 2022-10-31 08:58:20 -07:00
xfs_attr_item.h xfs: share xattr name and value buffers when logging xattr updates 2022-05-23 08:43:46 +10:00
xfs_attr_list.c xfs: use XFS_IFORK_Q to determine the presence of an xattr fork 2022-07-09 15:17:21 -07:00
xfs_bio_io.c fs/xfs: Use the enum req_op and blk_opf_t types 2022-07-14 12:14:33 -06:00
xfs_bmap_item.c xfs: dump corrupt recovered log intent items to dmesg consistently 2022-10-31 08:58:20 -07:00
xfs_bmap_item.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_bmap_util.c xfs: fix NULL pointer dereference in xfs_getbmap() 2022-07-31 09:21:27 -07:00
xfs_bmap_util.h xfs: kill the XFS_IOC_{ALLOC,FREE}SP* ioctls 2022-01-17 09:16:41 -08:00
xfs_buf_item_recover.c xfs: convert buf_cancel_table allocation to kmalloc_array 2022-05-27 10:27:19 +10:00
xfs_buf_item.c xfs: log items should have a xlog pointer, not a mount 2022-03-20 08:59:49 -07:00
xfs_buf_item.h xfs: convert buffer log item flags to unsigned. 2022-04-21 10:46:40 +10:00
xfs_buf.c - The usual batches of cleanups from Baoquan He, Muchun Song, Miaohe 2022-08-05 16:32:45 -07:00
xfs_buf.h xfs: xfs_buf cache destroy isn't RCU safe 2022-07-20 16:40:39 -07:00
xfs_dir2_readdir.c xfs: rearrange the logic and remove the broken comment for xfs_dir2_isxx 2022-10-04 16:39:58 +11:00
xfs_discard.c xfs: pass perag to xfs_alloc_read_agf() 2022-07-07 19:07:40 +10:00
xfs_discard.h
xfs_dquot_item_recover.c xfs: replace xfs_sb_version checks with feature flag checks 2021-08-19 10:07:12 -07:00
xfs_dquot_item.c xfs: remove support for disabling quota accounting on a mounted file system 2021-08-06 11:05:36 -07:00
xfs_dquot_item.h xfs: remove support for disabling quota accounting on a mounted file system 2021-08-06 11:05:36 -07:00
xfs_dquot.c xfs: Fix comment typo 2022-07-22 10:58:39 -07:00
xfs_dquot.h xfs: remove warning counters from struct xfs_dquot_res 2022-05-11 17:12:09 +10:00
xfs_error.c xfs: fix memory leak in xfs_errortag_init 2022-10-20 09:42:56 -07:00
xfs_error.h xfs: convert ptag flags to unsigned. 2022-04-21 10:47:25 +10:00
xfs_export.c xfs: convert remaining mount flags to state flags 2021-08-19 10:07:13 -07:00
xfs_export.h
xfs_extent_busy.c
xfs_extent_busy.h
xfs_extfree_item.c xfs: dump corrupt recovered log intent items to dmesg consistently 2022-10-31 08:58:20 -07:00
xfs_extfree_item.h xfs: refactor all the EFI/EFD log item sizeof logic 2022-10-31 08:58:20 -07:00
xfs_file.c xfs: write page faults in iomap are not buffered writes 2022-11-07 10:09:11 +11:00
xfs_filestream.c xfs: pass perag to xfs_alloc_read_agf() 2022-07-07 19:07:40 +10:00
xfs_filestream.h xfs: convert mount flags to features 2021-08-19 10:07:12 -07:00
xfs_fsmap.c xfs: pass perag to xfs_alloc_read_agf() 2022-07-07 19:07:40 +10:00
xfs_fsmap.h
xfs_fsops.c - The usual batches of cleanups from Baoquan He, Muchun Song, Miaohe 2022-08-05 16:32:45 -07:00
xfs_fsops.h
xfs_globals.c xfs: Add larp debug option 2022-05-11 17:01:22 +10:00
xfs_health.c xfs: replace XFS_FORCED_SHUTDOWN with xfs_is_shutdown 2021-08-19 10:07:13 -07:00
xfs_icache.c treewide: use get_random_u32() when possible 2022-10-11 17:42:58 -06:00
xfs_icache.h xfs: introduce xfs_inodegc_push() 2022-06-23 13:34:38 -07:00
xfs_icreate_item.c xfs: fix potential log item leak 2022-05-04 11:45:11 +10: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: clean up "%Ld/%Lu" which doesn't meet C standard 2022-09-19 06:47:14 +10:00
xfs_inode_item.c xfs: remove the redundant word in comment 2022-09-19 06:45:14 +10:00
xfs_inode_item.h xfs: aborting inodes on shutdown may need buffer lock 2022-03-29 18:21:59 -07:00
xfs_inode.c xfs: increase rename inode reservation 2022-10-26 13:02:24 -07:00
xfs_inode.h - The usual batches of cleanups from Baoquan He, Muchun Song, Miaohe 2022-08-05 16:32:45 -07:00
xfs_ioctl32.c xfs: Set up infrastructure for log attribute replay 2022-05-04 12:41:02 +10:00
xfs_ioctl32.h xfs: remove unused xfs_ioctl32.h declarations 2022-01-18 10:18:36 -08:00
xfs_ioctl.c xfs: convert XFS_IFORK_PTR to a static inline helper 2022-07-09 15:17:21 -07:00
xfs_ioctl.h xfs: kill the XFS_IOC_{ALLOC,FREE}SP* ioctls 2022-01-17 09:16:41 -08:00
xfs_iomap.c xfs: punching delalloc extents on write failure is racy 2022-11-23 12:40:11 +11:00
xfs_iomap.h xfs: write page faults in iomap are not buffered writes 2022-11-07 10:09:11 +11:00
xfs_iops.c xfs: changes for 6.1-rc1 2022-10-10 20:32:10 -07:00
xfs_iops.h xfs: remove xfs_setattr_time() declaration 2022-09-19 06:53:14 +10:00
xfs_itable.c xfs: port to vfs{g,u}id_t and associated helpers 2022-09-19 06:54:14 +10:00
xfs_itable.h xfs: Enable bulkstat ioctl to support 64-bit per-inode extent counters 2022-04-13 07:02:45 +00:00
xfs_iunlink_item.c xfs: add in-memory iunlink log item 2022-07-14 11:47:42 +10:00
xfs_iunlink_item.h xfs: add in-memory iunlink log item 2022-07-14 11:47:42 +10:00
xfs_iwalk.c xfs: avoid buffer deadlocks when walking fs inodes 2021-08-09 11:13:16 -07:00
xfs_iwalk.h xfs: Decouple XFS_IBULK flags from XFS_IWALK flags 2022-04-13 07:02:44 +00:00
xfs_linux.h fs/xfs: Use the enum req_op and blk_opf_t types 2022-07-14 12:14:33 -06:00
xfs_log_cil.c xfs: xlog_sync() manually adjusts grant head space 2022-07-07 18:56:09 +10:00
xfs_log_priv.h xfs: xlog_sync() manually adjusts grant head space 2022-07-07 18:56:09 +10:00
xfs_log_recover.c xfs: avoid a UAF when log intent item recovery fails 2022-10-18 14:39:29 -07:00
xfs_log.c treewide: use get_random_u32() when possible 2022-10-11 17:42:58 -06:00
xfs_log.h xfs: move CIL ordering to the logvec chain 2022-07-07 18:56:08 +10:00
xfs_message.c Merge branch 'guilt/xfs-unsigned-flags-5.18' into xfs-5.19-for-next 2022-04-21 16:45:03 +10:00
xfs_message.h xfs: implement per-mount warnings for scrub and shrink usage 2022-05-27 10:31:34 +10:00
xfs_mount.c xfs: simplify if-else condition in xfs_validate_new_dalign 2022-09-19 06:49:14 +10:00
xfs_mount.h - The usual batches of cleanups from Baoquan He, Muchun Song, Miaohe 2022-08-05 16:32:45 -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_notify_failure.c xfs: changes for 6.1-rc1 2022-10-10 20:32:10 -07:00
xfs_ondisk.h xfs: fix memcpy fortify errors in EFI log format copying 2022-10-31 08:58:20 -07:00
xfs_pnfs.c xfs: use setattr_copy to set vfs inode attributes 2022-03-14 10:23:16 -07:00
xfs_pnfs.h
xfs_pwork.c
xfs_pwork.h
xfs_qm_bhv.c xfs: replace xfs_sb_version checks with feature flag checks 2021-08-19 10:07:12 -07:00
xfs_qm_syscalls.c xfs: introduce xfs_inodegc_push() 2022-06-23 13:34:38 -07:00
xfs_qm.c New code for 6.0: 2022-08-13 13:50:11 -07:00
xfs_qm.h xfs: remove quota warning limit from struct xfs_quota_limits 2022-05-11 17:12:09 +10:00
xfs_quota.h xfs: queue inactivation immediately when quota is nearing enforcement 2021-08-09 10:52:18 -07:00
xfs_quotaops.c xfs: don't set quota warning values 2022-05-11 17:12:09 +10:00
xfs_refcount_item.c xfs: dump corrupt recovered log intent items to dmesg consistently 2022-10-31 08:58:20 -07:00
xfs_refcount_item.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_reflink.c xfs: simplify if-else condition in xfs_reflink_trim_around_shared 2022-09-19 06:50:14 +10:00
xfs_reflink.h xfs: pass perag to xfs_alloc_read_agf() 2022-07-07 19:07:40 +10:00
xfs_rmap_item.c xfs: dump corrupt recovered log intent items to dmesg consistently 2022-10-31 08:58:20 -07:00
xfs_rmap_item.h xfs: rename _zone variables to _cache 2021-10-22 16:04:20 -07:00
xfs_rtalloc.c Merge tag 'large-extent-counters-v9' of https://github.com/chandanr/linux into xfs-5.19-for-next 2022-04-21 16:46:17 +10:00
xfs_rtalloc.h xfs: recalculate free rt extents after log recovery 2022-04-12 06:49:42 +10:00
xfs_stats.c xfs: replace unnecessary seq_printf with seq_puts 2022-09-19 06:48:14 +10:00
xfs_stats.h
xfs_super.c xfs: refactor all the EFI/EFD log item sizeof logic 2022-10-31 08:58:20 -07:00
xfs_super.h xfs: implement ->notify_failure() for XFS 2022-07-17 17:14:30 -07:00
xfs_symlink.c xfs: replace inode fork size macros with functions 2022-07-12 11:17:27 -07:00
xfs_symlink.h
xfs_sysctl.c
xfs_sysctl.h xfs: Add larp debug option 2022-05-11 17:01:22 +10:00
xfs_sysfs.c xfs: Add larp debug option 2022-05-11 17:01:22 +10:00
xfs_sysfs.h xfs: Fix unreferenced object reported by kmemleak in xfs_sysfs_init() 2022-10-20 09:42:56 -07:00
xfs_trace.c xfs: add trace point for fs shutdown 2021-08-18 18:46:00 -07:00
xfs_trace.h xfs: report refcount domain in tracepoints 2022-10-31 08:58:21 -07:00
xfs_trans_ail.c xfs: remove redundant pointer lip 2022-10-20 09:42:56 -07:00
xfs_trans_buf.c xfs: introduce xfs_buf_daddr() 2021-08-19 10:07:14 -07:00
xfs_trans_dquot.c xfs: remove quota warning limit from struct xfs_quota_limits 2022-05-11 17:12:09 +10:00
xfs_trans_priv.h xfs: convert log vector chain to use list heads 2022-07-07 18:55:59 +10:00
xfs_trans.c xfs: introduce in-memory inode unlink log items 2022-07-14 09:21:42 -07:00
xfs_trans.h xfs: introduce in-memory inode unlink log items 2022-07-14 09:21:42 -07:00
xfs_xattr.c xfs: fix TOCTOU race involving the new logged xattrs control knob 2022-06-15 23:13:32 -07:00
xfs_xattr.h xfs: move xfs_attr_use_log_assist usage out of libxfs 2022-05-27 10:34:04 +10:00
xfs.h