linux/include
Long Li 51d20d1dac
iomap: fix zero padding data issue in concurrent append writes
During concurrent append writes to XFS filesystem, zero padding data
may appear in the file after power failure. This happens due to imprecise
disk size updates when handling write completion.

Consider this scenario with concurrent append writes same file:

  Thread 1:                  Thread 2:
  ------------               -----------
  write [A, A+B]
  update inode size to A+B
  submit I/O [A, A+BS]
                             write [A+B, A+B+C]
                             update inode size to A+B+C
  <I/O completes, updates disk size to min(A+B+C, A+BS)>
  <power failure>

After reboot:
  1) with A+B+C < A+BS, the file has zero padding in range [A+B, A+B+C]

  |<         Block Size (BS)      >|
  |DDDDDDDDDDDDDDDD0000000000000000|
  ^               ^        ^
  A              A+B     A+B+C
                         (EOF)

  2) with A+B+C > A+BS, the file has zero padding in range [A+B, A+BS]

  |<         Block Size (BS)      >|<           Block Size (BS)    >|
  |DDDDDDDDDDDDDDDD0000000000000000|00000000000000000000000000000000|
  ^               ^                ^               ^
  A              A+B              A+BS           A+B+C
                                  (EOF)

  D = Valid Data
  0 = Zero Padding

The issue stems from disk size being set to min(io_offset + io_size,
inode->i_size) at I/O completion. Since io_offset+io_size is block
size granularity, it may exceed the actual valid file data size. In
the case of concurrent append writes, inode->i_size may be larger
than the actual range of valid file data written to disk, leading to
inaccurate disk size updates.

This patch modifies the meaning of io_size to represent the size of
valid data within EOF in an ioend. If the ioend spans beyond i_size,
io_size will be trimmed to provide the file with more accurate size
information. This is particularly useful for on-disk size updates
at completion time.

After this change, ioends that span i_size will not grow or merge with
other ioends in concurrent scenarios. However, these cases that need
growth/merging rarely occur and it seems no noticeable performance impact.
Although rounding up io_size could enable ioend growth/merging in these
scenarios, we decided to keep the code simple after discussion [1].

Another benefit is that it makes the xfs_ioend_is_append() check more
accurate, which can reduce unnecessary end bio callbacks of xfs_end_bio()
in certain scenarios, such as repeated writes at the file tail without
extending the file size.

Link [1]: https://patchwork.kernel.org/project/xfs/patch/20241113091907.56937-1-leo.lilong@huawei.com

Fixes: ae259a9c85 ("fs: introduce iomap infrastructure") # goes further back than this
Signed-off-by: Long Li <leo.lilong@huawei.com>
Link: https://lore.kernel.org/r/20241209114241.3725722-3-leo.lilong@huawei.com
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <brauner@kernel.org>
History 2024-12-11 11:09:05 +01:00
..
acpi common: switch back from remove_new() to remove() callback 2024-11-25 17:31:39 -08:00
asm-generic - Fix a case where posix timers with a thread-group-wide target would miss 2024-12-01 12:41:21 -08:00
clocksource pwm: xilinx: Fix u32 overflow issue in 32-bit width PWM mode. 2024-06-03 13:07:56 +02:00
crypto This update includes the following changes: 2024-11-19 10:28:41 -08:00
cxl cxl: Move mailbox related bits to the same context 2024-09-12 08:38:01 -07:00
drm drm for 6.13-rc1 2024-11-21 14:56:17 -08:00
dt-bindings Char/Misc/IIO/Whatever driver subsystem updates for 6.13-rc1 2024-11-29 11:58:27 -08:00
keys KEYS: Remove unused declarations 2024-09-20 18:28:26 +03:00
kunit The core framework gained a clk provider helper, a clk consumer helper, and 2024-11-22 17:02:25 -08:00
kvm KVM: arm64: vgic: Kill VGIC_MAX_PRIVATE definition 2024-11-20 17:21:08 -08:00
linux iomap: fix zero padding data issue in concurrent append writes 2024-12-11 11:09:05 +01:00
math-emu powerpc/math-emu: Remove -w build flag and fix warnings 2022-09-05 17:28:25 +10:00
media media: replace obsolete hans.verkuil@cisco.com alias 2024-11-08 13:38:09 +01:00
memory memory: renesas-rpc-if: Remove Runtime PM wrappers 2023-01-23 11:48:00 +01:00
misc cxl: fix typo in comment 2022-11-24 23:12:19 +11:00
net Kbuild updates for v6.13 2024-11-30 13:41:50 -08:00
pcmcia ARM: pxa/sa1100: move I/O space to PCI_IOBASE 2022-05-07 22:56:17 +02:00
ras mm/memory-failure: remove obsolete MF_MSG_DIFFERENT_COMPOUND 2024-07-12 15:52:22 -07:00
rdma RDMA/core: Move ib_uverbs_file struct to uverbs_types.h 2024-11-04 06:57:21 -05:00
rv rv: Set variable 'da_mon_##name' to static 2023-09-01 21:00:00 -04:00
scsi Random number generator updates for Linux 6.13-rc1. 2024-11-19 10:43:44 -08:00
soc The core framework gained a clk provider helper, a clk consumer helper, and 2024-11-22 17:02:25 -08:00
sound ALSA: hda/tas2781: Add speaker id check for ASUS projects 2024-11-26 08:54:08 +01:00
target move asm/unaligned.h to linux/unaligned.h 2024-10-02 17:23:23 -04:00
trace NFS client updates for Linux 6.13 2024-11-30 10:17:53 -08:00
uapi io_uring-6.13-20242901 2024-11-30 15:43:02 -08:00
ufs scsi: ufs: ufs-mediatek: Configure individual LU queue flags 2024-11-06 20:42:17 -05:00
vdso vdso: Rename struct arch_vdso_data to arch_vdso_time_data 2024-11-02 12:37:36 +01:00
video - Improved handling of LCD power states and interactions with the fbdev subsystem. 2024-11-22 16:29:57 -08:00
xen xen: Remove dependency between pciback and privcmd 2024-10-18 11:59:04 +02:00