[PATCH 03/11] ntfs: punch all-zero compressed blocks

Namjae Jeon <[email protected]> Tue, 21 Jul 2026 18:54:23 +0900
Newsgroups dev.linux.lists.ntfs
Message-ID <[email protected]>
When a rewritten compression block consists entirely of zeroes,
ntfs_write_cb() returns without replacing its existing runlist mapping.
The old on-disk contents therefore remain visible after cache eviction.

Punch the compression unit so that reads resolve it as a sparse block and
release any clusters that held the previous contents.

Signed-off-by: Namjae Jeon <[email protected]>
---
 fs/ntfs/compress.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c
index 006b8831836c..33ed0456bf7e 100644
--- a/fs/ntfs/compress.c
+++ b/fs/ntfs/compress.c
@@ -1279,9 +1279,10 @@ static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages,
 	int i, err;
 	int pages_count = (round_up(ni->itype.compressed.block_size + 2 *
 		(ni->itype.compressed.block_size / NTFS_SB_SIZE) + 2, PAGE_SIZE)) / PAGE_SIZE;
+	u32 cb_clusters = ni->itype.compressed.block_clusters;
 	size_t new_rl_count;
 	struct bio *bio = NULL;
-	loff_t new_length;
+	loff_t cb_pos, new_length;
 	s64 new_vcn;
 
 	in_mapping = vmap(pages, pages_per_cb, VM_MAP, PAGE_KERNEL_RO);
@@ -1351,6 +1352,9 @@ static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages,
 		}
 	}
 
+	cb_pos = pos & ~((loff_t)ni->itype.compressed.block_size - 1);
+	new_vcn = ntfs_bytes_to_cluster(vol, cb_pos);
+
 	if (!fail && !allzeroes) {
 		outbuf[compsz++] = 0;
 		outbuf[compsz++] = 0;
@@ -1359,7 +1363,7 @@ static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages,
 		bio_size = rounded;
 		pages = pages_disk;
 	} else if (allzeroes) {
-		err = 0;
+		err = ntfs_non_resident_attr_punch_hole(ni, new_vcn, cb_clusters);
 		goto out;
 	} else {
 		memcpy(outbuf, inbuf, insz);
@@ -1367,8 +1371,6 @@ static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages,
 		pages = pages_disk;
 	}
 
-	new_vcn = ntfs_bytes_to_cluster(vol,
-			pos & ~((loff_t)ni->itype.compressed.block_size - 1));
 	new_length = ntfs_bytes_to_cluster(vol, round_up(bio_size, vol->cluster_size));
 
 	err = ntfs_non_resident_attr_punch_hole(ni, new_vcn, ni->itype.compressed.block_clusters);
-- 
2.34.1