From: Christian Brauner <brauner@kernel.org>
To: linux-fsdevel@vger.kernel.org, Jan Kara <jack@suse.cz>
Cc: Josef Bacik <josef@toxicpanda.com>,
Chris Mason <mason@kernel.org>,
linux-ext4@vger.kernel.org,
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>,
Andreas Dilger <adilger.kernel@dilger.ca>,
Baokun Li <libaokun@linux.alibaba.com>,
Ojaswin Mujoo <ojaswin@linux.ibm.com>,
"Ritesh Harjani (IBM)" <ritesh.list@gmail.com>,
Namjae Jeon <namjae.jeon@samsung.com>,
"Christian Brauner (Amutable)" <brauner@kernel.org>,
stable@vger.kernel.org
Subject: [PATCH RFC 8/9] fat: sync the inode in fat_free_eofblocks()
Date: Thu, 29 Oct 2026 14:28:23 +0100 [thread overview]
Message-ID: <20261029-work-inode-metadata_writeback-v1-8-7d6c678a585d@kernel.org> (raw)
In-Reply-To: <20261029-work-inode-metadata_writeback-v1-0-7d6c678a585d@kernel.org>
fat_evict_inode() calls fat_free_eofblocks() for a linked inode to give
back the clusters that were fallocated past the initialized size. For an
empty file that also resets the start cluster in the directory entry. It
truncates the clusters and writes the inode with:
sync_inode_metadata(inode, inode_needs_sync(inode));
Unless the inode is IS_SYNC that is WB_SYNC_NONE writeback. It copies
the inode into the directory entry buffer, marks the buffer dirty and
sets I_METADATA_WRITEBACK. Then the inode goes away and with it the only
thing that would have told a later fsync() that the directory entry
still has to be written.
FAT doesn't have that problem. Its buffers are tracked on the FAT inode
and fat_file_fsync() writes them out on every fsync() of any file on the
filesystem.
So after the next fsync() the clusters are free on disk while the
directory entry of the empty file still points at them. If another file
reuses them and the machine crashes before the directory entry makes it
to disk, the two files share clusters. That's the corruption the comment
in fat_free_eofblocks() is about.
So wait for the directory entry to reach the disk before the inode goes
away.
Reproducer. The image file shows what reached the disk. The flusher is
turned off so that it doesn't write the directory entry before fsck.fat
looks at the image:
img=/tmp/fat.img
truncate -s 64M $img
mkfs.vfat $img > /dev/null
dev=$(losetup -f --show $img)
mount -t vfat $dev /mnt
echo 0 > /proc/sys/vm/dirty_writeback_centisecs
xfs_io -f -c 'falloc -k 0 1m' -c fsync /mnt/a
echo 3 > /proc/sys/vm/drop_caches
echo 3 > /proc/sys/vm/drop_caches
xfs_io -c fsync /mnt/a
fsck.fat -n $img | grep -A1 '^/a'
umount /mnt
losetup -d $dev
On v7.3-17318-g65ba8f34ec88 in a KASAN and lockdep vng guest this
prints:
/a
Contains a free cluster (3). Assuming EOF.
With this patch fsck.fat finds nothing wrong with /a.
The stable tag is narrower than the Fixes tag. Before v7.3
fat_free_eofblocks() called __fat_write_inode() directly and the fix
there is to pass 1 for wait.
Fixes: b13bb33eacb7 ("fat: add fat_fallocate operation")
Cc: stable@vger.kernel.org # v7.3
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
fs/fat/inode.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index d85c8fbdcca4..fc571ee2b174 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -675,7 +675,7 @@ static void fat_free_eofblocks(struct inode *inode)
* any corruption on the next access to the cluster
* chain for the file.
*/
- err = sync_inode_metadata(inode, inode_needs_sync(inode));
+ err = sync_inode_metadata(inode, 1);
if (err) {
fat_msg(inode->i_sb, KERN_WARNING, "Failed to "
"update on disk inode for unused "
--
2.53.0
next prev parent reply other threads:[~2026-10-29 13:29 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-29 13:28 [PATCH RFC 0/9] fs: reclaim inodes with I_METADATA_WRITEBACK Christian Brauner
2026-10-29 13:28 ` [PATCH RFC 1/9] ext2: add ext2_inode_block() helper Christian Brauner
2026-10-29 13:28 ` [PATCH RFC 2/9] ext2: don't read the inode block in ext2_sync_inode_metadata() Christian Brauner
2026-10-29 13:28 ` [PATCH RFC 3/9] ext4: add ext4_inode_loc_block() helper Christian Brauner
2026-10-29 13:28 ` [PATCH RFC 4/9] ext4: don't read the inode block in ext4_sync_inode_metadata() Christian Brauner
2026-10-29 13:28 ` [PATCH RFC 5/9] minix: add minix_inode_block() helper Christian Brauner
2026-10-29 13:28 ` [PATCH RFC 6/9] minix: don't read the inode block in minix_sync_inode_metadata() Christian Brauner
2026-10-29 13:28 ` [PATCH RFC 7/9] udf: don't allocate the inode block in udf_sync_inode_metadata() Christian Brauner
2026-10-29 13:28 ` Christian Brauner [this message]
2026-10-29 13:28 ` [PATCH RFC 9/9] fs: don't strand I_METADATA_WRITEBACK inodes outside the LRU Christian Brauner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261029-work-inode-metadata_writeback-v1-8-7d6c678a585d@kernel.org \
--to=brauner@kernel.org \
--cc=adilger.kernel@dilger.ca \
--cc=hirofumi@mail.parknet.co.jp \
--cc=jack@suse.cz \
--cc=josef@toxicpanda.com \
--cc=libaokun@linux.alibaba.com \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=mason@kernel.org \
--cc=namjae.jeon@samsung.com \
--cc=ojaswin@linux.ibm.com \
--cc=ritesh.list@gmail.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox