Message ID | ffa14771bb6d672a2a74d92625bd024013b3f8ce.1627580467.git.fdmanana@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: avoid unnecessarily logging directories that had no changes | expand |
On Thu, Jul 29, 2021 at 06:52:46PM +0100, fdmanana@kernel.org wrote: > From: Filipe Manana <fdmanana@suse.com> > > 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> Added to misc-next, thanks.
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index d2039743ecf2..b4e820cde461 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -5610,6 +5610,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,