]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ntfs: drop stale page-cache when shrinking a non-resident attr
authorNamjae Jeon <linkinjeon@kernel.org>
Mon, 13 Jul 2026 07:49:57 +0000 (16:49 +0900)
committerNamjae Jeon <linkinjeon@kernel.org>
Tue, 21 Jul 2026 09:48:24 +0000 (18:48 +0900)
ntfs_non_resident_attr_shrink() shrinks attribute sizes but fails to
trim the page cache. This leaves orphaned dirty folios beyond the new
end of the attribute, leading to writeback failures (-ENOENT), data
loss, and $EA chain corruption.

Fix this by truncating the page cache to the new size immediately after
updating the sizes, preventing writeback from flushing out-of-range folios.

Fixes: 495e90fa3348 ("ntfs: update attrib operations")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
fs/ntfs/attrib.c

index 239b7bcbaedf4c2d0bd51529a93c45bbd0eb0352..58f32aac5f614680fc3617f3b77d9a1e06d38ec0 100644 (file)
@@ -4293,6 +4293,16 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz
                ni->initialized_size = newsize;
                ctx->attr->data.non_resident.initialized_size = cpu_to_le64(newsize);
        }
+
+       /*
+        * Drop any page-cache folios that now lie beyond the shrunk
+        * attribute. The clusters backing them have just been freed and the
+        * runlist truncated, so leaving stale dirty folios around makes a
+        * later writeback map a vcn past the new allocation, which fails with
+        * -ENOENT and loses the write.
+        */
+       truncate_inode_pages(VFS_I(ni)->i_mapping, newsize);
+
        /* Update data size in the index. */
        if (ni->type == AT_DATA && ni->name == AT_UNNAMED)
                NInoSetFileNameDirty(ni);