From fa5489ebc8bc7c663311b0f35943fe7edd0dfe56 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Tue, 22 Sep 2026 06:33:01 +0200 Subject: [PATCH] ntfs: include the final partial cluster in sync writes ntfs_attrlist_repack() synchronously writes the replacement attribute list before updating its mapping pairs and freeing the old run. With 512-byte clusters, a 544-byte list submits a 512-byte bio, but the write returns 544 and repack accepts it as complete. If the later buffered update does not reach disk, the replacement list lacks its final 32 bytes. __ntfs_inode_non_resident_attr_pwrite() converts attr_len to clusters with ntfs_bytes_to_cluster(), which rounds down. Before repack, its synchronous callers used either cluster-aligned lengths or lengths smaller than one cluster, where max_t() selects one. Round attr_len up so repack writes the final partial cluster before publishing the new mapping pairs. Fixes: b1d732e62a5b ("ntfs: repack $MFT/$ATTRIBUTE LIST") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Karl Mehltretter Signed-off-by: Namjae Jeon --- fs/ntfs/inode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index cadf623d54d4..d8d3a7b7b8a9 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -3761,7 +3761,9 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi, struct runlist_element *rl; int bio_err; - lcn_count = max_t(s64, 1, ntfs_bytes_to_cluster(vol, attr_len)); + lcn_count = max_t(s64, 1, + ntfs_bytes_to_cluster(vol, attr_len + + vol->cluster_size - 1)); vcn = ntfs_pidx_to_cluster(vol, folio->index); do {