From: Christian Brauner Date: Mon, 27 Jul 2026 15:15:40 +0000 (+0200) Subject: fat: Fix lost inode update in do_msdos_rename() with DIRSYNC X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=d7de16e240daae88d910b425951a5dd644f01006;p=thirdparty%2Flinux.git fat: Fix lost inode update in do_msdos_rename() with DIRSYNC Commit e668e0668181 ("fat: Replace fat_sync_inode() with sync_inode_metadata()") hoisted mark_inode_dirty() in front of the IS_DIRSYNC conditional in all converted callers except for the main rename path of do_msdos_rename(). There old_inode is generally still clean when the target directory has DIRSYNC set and, unlike fat_sync_inode(), sync_inode_metadata() does nothing for a clean inode. Thus the directory entry at the new location is never updated with the contents of old_inode: it stays the way msdos_add_entry() created it, with start cluster 0 and size 0 (or, when the rename replaced an existing target, it keeps describing the deleted target). Since old_inode is also never marked dirty, later writeback doesn't update the entry either and the stale directory entry ends up on disk even on a clean unmount, so the renamed file loses its contents. Mark old_inode dirty before calling sync_inode_metadata() like all the other call sites do. Fixes: e668e0668181 ("fat: Replace fat_sync_inode() with sync_inode_metadata()") Reported-by: Sashiko Signed-off-by: Christian Brauner (Amutable) --- diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index 91b8d2fc9407..94f9df06a784 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c @@ -516,12 +516,12 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN; else MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN; + mark_inode_dirty(old_inode); if (IS_DIRSYNC(new_dir)) { err = sync_inode_metadata(old_inode, 1); if (err) goto error_inode; - } else - mark_inode_dirty(old_inode); + } if (update_dotdot) { fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart);