From: Viacheslav Dubeyko The generic/639 xfstest fails for Ceph msgr2 protocol: Ubuntu 22.04.5 LTS (GNU/Linux 6.17.0-rc7+ x86_64) sudo mount -t ceph :/ /mnt/cephfs/ -o name=admin,fs=cephfs,ms_mode=secure sudo ./check generic/639 FSTYP -- ceph PLATFORM -- Linux/x86_64 ceph-0005 6.17.0-rc7+ #16 SMP PREEMPT_DYNAMIC Wed Nov 12 11:01:48 PST 2025 MKFS_OPTIONS -- 192.168.1.213:3300:/scratch MOUNT_OPTIONS -- -o name=admin,ms_mode=secure 192.168.1.213:3300:/scratch /mnt/cephfs/scratch generic/639 - output mismatch (see /home/slavad/XFSTESTS-2/xfstests-dev/results//generic/639.out.bad) The simple way to reproduce the issue simply running these steps: mount -t ceph :/ /mnt/cephfs/ -o name=admin,fs=cephfs,ms_mode=secure xfs_io -f -c "pwrite -q 0 32" ./testfile251125-0004 umount /mnt/cephfs/ mount -t ceph :/ /mnt/cephfs/ -o name=admin,fs=cephfs,ms_mode=secure xfs_io -c "pwrite -q 32 32" ./testfile251125-0004 Finally, we have the unexpected content of the file: hexdump ./testfile251125-0004 0000000 0000 0000 0000 0000 0000 0000 0000 0000 * 0000020 cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd * 0000040 Initial analysis has shown that if we try to write out of end of file, then ceph_write_begin() is responsible for the issue because it calls netfs_write_begin() and we have such logic: int netfs_write_begin(struct netfs_inode *ctx, struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, struct folio **_folio, void **_fsdata) { folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, mapping_gfp_mask(mapping)); if (folio_test_uptodate(folio)) goto have_folio; } The reason of the issue that somehow we have folio in uptodate state and netfs_write_begin() simply skips the logic of reading existing file's content. Futher analysis revealed that we call ceph_fill_inode() and ceph_fill_inline_data() before ceph_write_begin(). void ceph_fill_inline_data(struct inode *inode, struct page *locked_page, char *data, size_t len) { if (page != locked_page) { if (len < PAGE_SIZE) zero_user_segment(page, len, PAGE_SIZE); else flush_dcache_page(page); SetPageUptodate(page); <--- We set page uptodate if len == 0!!!! unlock_page(page); put_page(page); } } This patch fixes the issue by checking the len argument and setting memory page uptodate only if len > 0. sudo ./check generic/639 FSTYP -- ceph PLATFORM -- Linux/x86_64 ceph-0005 6.19.0-rc5+ #2 SMP PREEMPT_DYNAMIC Thu Feb 5 15:43:51 PST 2026 MKFS_OPTIONS -- 192.168.1.213:3300:/scratch MOUNT_OPTIONS -- -o name=admin,ms_mode=secure 192.168.1.213:3300:/scratch /mnt/cephfs/scratch generic/639 6s ... 6s Ran: generic/639 Passed all 1 tests [1] https://tracker.ceph.com/issues/73829 Signed-off-by: Viacheslav Dubeyko cc: Alex Markuze cc: Ilya Dryomov cc: Patrick Donnelly cc: Ceph Development --- fs/ceph/addr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 63b75d214210..436a287fd311 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -2184,7 +2184,9 @@ void ceph_fill_inline_data(struct inode *inode, struct page *locked_page, else flush_dcache_page(page); - SetPageUptodate(page); + if (len > 0) + SetPageUptodate(page); + unlock_page(page); put_page(page); } -- 2.53.0