btrfs: avoid unnecessarily logging directories that had no changes
authorFilipe Manana <fdmanana@suse.com>
Thu, 29 Jul 2021 17:52:46 +0000 (18:52 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 23 Aug 2021 11:19:15 +0000 (13:19 +0200)
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>
fs/btrfs/tree-log.c

index 1ce7e44..a1aaa1b 100644 (file)
@@ -5614,6 +5614,13 @@ 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,
         * we can skip logging it. As for new/deleted names, those are updated in