]> git.baikalelectronics.ru Git - kernel.git/commit
btrfs: reset last_reflink_trans after fsyncing inode
authorFilipe Manana <fdmanana@suse.com>
Thu, 17 Feb 2022 12:12:06 +0000 (12:12 +0000)
committerDavid Sterba <dsterba@suse.com>
Mon, 14 Mar 2022 12:13:52 +0000 (13:13 +0100)
commit5b0da33116e4a2017b459f9138f4131b1dfdc102
tree36d92c9e18fc718233b1e679d97c04f1e61133b2
parent862390faaf6feaf46d115c9a914df07ad25e36a9
btrfs: reset last_reflink_trans after fsyncing inode

When an inode has a last_reflink_trans matching the current transaction,
we have to take special care when logging its checksums in order to
avoid getting checksum items with overlapping ranges in a log tree,
which could result in missing checksums after log replay (more on that
in the changelogs of commit 2f2f8d0568e453 ("Btrfs: fix missing data
checksums after replaying a log tree") and commit 1b2a4374ffeb96 ("btrfs:
fix corrupt log due to concurrent fsync of inodes with shared extents")).
We also need to make sure a full fsync will copy all old file extent
items it finds in modified leaves, because they might have been copied
from some other inode.

However once we fsync an inode, we don't need to keep paying the price of
that extra special care in future fsyncs done in the same transaction,
unless the inode is used for another reflink operation or the full sync
flag is set on it (truncate, failure to allocate extent maps for holes,
and other exceptional and infrequent cases).

So after we fsync an inode reset its last_unlink_trans to zero. In case
another reflink happens, we continue to update the last_reflink_trans of
the inode, just as before. Also set last_reflink_trans to the generation
of the last transaction that modified the inode whenever we need to set
the full sync flag on the inode, just like when we need to load an inode
from disk after eviction.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/btrfs_inode.h
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/reflink.c
fs/btrfs/tree-log.c