From: Darrick J. Wong Date: Mon, 2 Mar 2026 20:46:56 +0000 (-0800) Subject: mkfs: fix protofile data corruption when in/out file block sizes don't match X-Git-Tag: v6.19.0~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ca34529677786e1366cbea1268cc62ae6556be68;p=xfsprogs-dev.git mkfs: fix protofile data corruption when in/out file block sizes don't match As written in 73fb78e5ee8940, if libxfs_file_write is passed an unaligned file range to write, it will zero the unaligned regions at the head and tail of the block. This is what we want for a newly allocated (and hence unwritten) block, but this is definitely not what we want if some other part of the block has already been written. Fix this by extending the data/hole_pos range to be aligned to the block size of the new filesystem. This means we read slightly more, but we never rewrite blocks in the new filesystem, sidestepping the behavior. Found by xfs/841 when the test filesystem has a 1k fsblock size. Cc: # v6.13.0 Fixes: 73fb78e5ee8940 ("mkfs: support copying in large or sparse files") Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- diff --git a/mkfs/proto.c b/mkfs/proto.c index 3241a066..a460aebd 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -374,6 +374,17 @@ writefile( break; } + /* + * If we pass an unaligned range to libxfs_file_write, it will + * zero the unaligned head and tail parts of each block. If + * the fd filesystem has a smaller blocksize, then we can end + * up writing to the same block twice, causing unwanted zeroing + * and hence data corruption. + */ + data_pos = rounddown_64(data_pos, mp->m_sb.sb_blocksize); + hole_pos = min(roundup_64(hole_pos, mp->m_sb.sb_blocksize), + statbuf.st_size); + writefile_range(ip, fname, fd, data_pos, hole_pos - data_pos); data_pos = lseek(fd, hole_pos, SEEK_DATA); }