Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nilfs2: do not update mtime of renamed directory that is not moved

A minor issue with nilfs_rename, originating from an old ext2
implementation, is that the mtime is updated even if the rename target is
a directory and it is renamed within the same directory, rather than moved
to a different directory.

In this case, the child directory being renamed does not change in any
way, so changing its mtime is unnecessary according to the specification,
and can unnecessarily confuse backup tools.

In ext2, this issue was fixed by commit 39fe7557b4d6 ("ext2: Do not update
mtime of a moved directory") and a few subsequent fixes, but it remained
in nilfs2.

Fix this issue by not calling nilfs_set_link(), which rewrites the inode
number of the directory entry that refers to the parent directory, when
the move target is a directory and the source and destination are the same
directory.

Here, the directory to be moved only needs to be read if the inode number
of the parent directory is rewritten with nilfs_set_link, so also adjust
the execution conditions of the preparation work to avoid unnecessary
directory reads.

Link: https://lkml.kernel.org/r/20250111143518.7901-3-konishi.ryusuke@gmail.com
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Ryusuke Konishi and committed by
Andrew Morton
e30ccbb9 ee70999a

+9 -7
+9 -7
fs/nilfs2/namei.c
··· 370 370 struct folio *old_folio; 371 371 struct nilfs_dir_entry *old_de; 372 372 struct nilfs_transaction_info ti; 373 + bool old_is_dir = S_ISDIR(old_inode->i_mode); 373 374 int err; 374 375 375 376 if (flags & ~RENAME_NOREPLACE) ··· 386 385 goto out; 387 386 } 388 387 389 - if (S_ISDIR(old_inode->i_mode)) { 388 + if (old_is_dir && old_dir != new_dir) { 390 389 err = -EIO; 391 390 dir_de = nilfs_dotdot(old_inode, &dir_folio); 392 391 if (!dir_de) ··· 398 397 struct nilfs_dir_entry *new_de; 399 398 400 399 err = -ENOTEMPTY; 401 - if (dir_de && !nilfs_empty_dir(new_inode)) 400 + if (old_is_dir && !nilfs_empty_dir(new_inode)) 402 401 goto out_dir; 403 402 404 403 new_de = nilfs_find_entry(new_dir, &new_dentry->d_name, ··· 413 412 goto out_dir; 414 413 nilfs_mark_inode_dirty(new_dir); 415 414 inode_set_ctime_current(new_inode); 416 - if (dir_de) 415 + if (old_is_dir) 417 416 drop_nlink(new_inode); 418 417 drop_nlink(new_inode); 419 418 nilfs_mark_inode_dirty(new_inode); ··· 421 420 err = nilfs_add_link(new_dentry, old_inode); 422 421 if (err) 423 422 goto out_dir; 424 - if (dir_de) { 423 + if (old_is_dir) { 425 424 inc_nlink(new_dir); 426 425 nilfs_mark_inode_dirty(new_dir); 427 426 } ··· 435 434 436 435 err = nilfs_delete_entry(old_de, old_folio); 437 436 if (likely(!err)) { 438 - if (dir_de) { 439 - err = nilfs_set_link(old_inode, dir_de, dir_folio, 440 - new_dir); 437 + if (old_is_dir) { 438 + if (old_dir != new_dir) 439 + err = nilfs_set_link(old_inode, dir_de, 440 + dir_folio, new_dir); 441 441 drop_nlink(old_dir); 442 442 } 443 443 nilfs_mark_inode_dirty(old_dir);