btrfs: avoid unnecessarily logging directories that had no changes
There are several cases where when logging an inode we need to log its parent directories or logging subdirectories when logging a directory. There are cases however where we end up logging a directory even if it was not changed in the current transaction, no dentries added or removed since the last transaction. While this is harmless from a functional point of view, it is a waste time as it brings no advantage. One example where this is triggered is the following: $ mkfs.btrfs -f /dev/sdc $ mount /dev/sdc /mnt $ mkdir /mnt/A $ mkdir /mnt/B $ mkdir /mnt/C $ touch /mnt/A/foo $ ln /mnt/A/foo /mnt/B/bar $ ln /mnt/A/foo /mnt/C/baz $ sync $ rm -f /mnt/A/foo $ xfs_io -c "fsync" /mnt/B/bar This last fsync ends up logging directories A, B and C, however we only need to log directory A, as B and C were not changed since the last transaction commit. So fix this by changing need_log_inode(), to return false in case the given inode is a directory and has a ->last_trans value smaller than the current transaction's ID. Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
5b9b26f5d0
commit
8be2ba2e0e
@ -5613,6 +5613,13 @@ out_unlock:
|
||||
static bool need_log_inode(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_inode *inode)
|
||||
{
|
||||
/*
|
||||
* If a directory was not modified, no dentries added or removed, we can
|
||||
* and should avoid logging it.
|
||||
*/
|
||||
if (S_ISDIR(inode->vfs_inode.i_mode) && inode->last_trans < trans->transid)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If this inode does not have new/updated/deleted xattrs since the last
|
||||
* time it was logged and is flagged as logged in the current transaction,
|
||||
|
Loading…
Reference in New Issue
Block a user