Commit 8be2ba2e authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba
Browse files

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: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 5b9b26f5
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -5613,6 +5613,13 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
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,