Skip to content

Commit 5d8ea6d

Browse files
fdmananakdave
authored andcommitted
btrfs: do not set mtime/ctime to current time when unlinking for log replay
If we are doing an unlink for log replay, we are updating the directory's mtime and ctime to the current time, and this is incorrect since it should stay with the mtime and ctime that were set when the directory was logged. This is the same as when adding a link to an inode during log replay (with btrfs_add_link()), where we want the mtime and ctime to be the values that were in place when the inode was logged. This was found with generic/547 using LOAD_FACTOR=20 and TIME_FACTOR=20, where due to large log trees we have longer log replay times and fssum could detect a mismatch of the mtime and ctime of a directory. Fix this by skipping the mtime and ctime update at __btrfs_unlink_inode() if we are in log replay context (just like btrfs_add_link()). Reviewed-by: Boris Burkov <[email protected]> Signed-off-by: Filipe Manana <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent bcb5361 commit 5d8ea6d

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

fs/btrfs/inode.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4192,6 +4192,23 @@ int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
41924192
return ret;
41934193
}
41944194

4195+
static void update_time_after_link_or_unlink(struct btrfs_inode *dir)
4196+
{
4197+
struct timespec64 now;
4198+
4199+
/*
4200+
* If we are replaying a log tree, we do not want to update the mtime
4201+
* and ctime of the parent directory with the current time, since the
4202+
* log replay procedure is responsible for setting them to their correct
4203+
* values (the ones it had when the fsync was done).
4204+
*/
4205+
if (test_bit(BTRFS_FS_LOG_RECOVERING, &dir->root->fs_info->flags))
4206+
return;
4207+
4208+
now = inode_set_ctime_current(&dir->vfs_inode);
4209+
inode_set_mtime_to_ts(&dir->vfs_inode, now);
4210+
}
4211+
41954212
/*
41964213
* unlink helper that gets used here in inode.c and in the tree logging
41974214
* recovery code. It remove a link in a directory with a given name, and
@@ -4292,7 +4309,7 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans,
42924309
inode_inc_iversion(&inode->vfs_inode);
42934310
inode_set_ctime_current(&inode->vfs_inode);
42944311
inode_inc_iversion(&dir->vfs_inode);
4295-
inode_set_mtime_to_ts(&dir->vfs_inode, inode_set_ctime_current(&dir->vfs_inode));
4312+
update_time_after_link_or_unlink(dir);
42964313

42974314
return btrfs_update_inode(trans, dir);
42984315
}
@@ -6686,15 +6703,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
66866703
btrfs_i_size_write(parent_inode, parent_inode->vfs_inode.i_size +
66876704
name->len * 2);
66886705
inode_inc_iversion(&parent_inode->vfs_inode);
6689-
/*
6690-
* If we are replaying a log tree, we do not want to update the mtime
6691-
* and ctime of the parent directory with the current time, since the
6692-
* log replay procedure is responsible for setting them to their correct
6693-
* values (the ones it had when the fsync was done).
6694-
*/
6695-
if (!test_bit(BTRFS_FS_LOG_RECOVERING, &root->fs_info->flags))
6696-
inode_set_mtime_to_ts(&parent_inode->vfs_inode,
6697-
inode_set_ctime_current(&parent_inode->vfs_inode));
6706+
update_time_after_link_or_unlink(parent_inode);
66986707

66996708
ret = btrfs_update_inode(trans, parent_inode);
67006709
if (ret)

0 commit comments

Comments
 (0)