diff options
author | Filipe Manana <fdmanana@suse.com> | 2023-09-12 13:04:29 +0100 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2023-10-12 16:44:07 +0200 |
commit | 50564b651d01c19ce732819c5b3c3fd60707188e (patch) | |
tree | f4687254f29f5db5433298da7648a2977246c703 /fs/btrfs/qgroup.c | |
parent | bc27d6f0aa0e4de184b617aceeaf25818cc646de (diff) | |
download | linux-50564b651d01c19ce732819c5b3c3fd60707188e.tar.gz linux-50564b651d01c19ce732819c5b3c3fd60707188e.tar.bz2 linux-50564b651d01c19ce732819c5b3c3fd60707188e.zip |
btrfs: abort transaction on generation mismatch when marking eb as dirty
When marking an extent buffer as dirty, at btrfs_mark_buffer_dirty(),
we check if its generation matches the running transaction and if not we
just print a warning. Such mismatch is an indicator that something really
went wrong and only printing a warning message (and stack trace) is not
enough to prevent a corruption. Allowing a transaction to commit with such
an extent buffer will trigger an error if we ever try to read it from disk
due to a generation mismatch with its parent generation.
So abort the current transaction with -EUCLEAN if we notice a generation
mismatch. For this we need to pass a transaction handle to
btrfs_mark_buffer_dirty() which is always available except in test code,
in which case we can pass NULL since it operates on dummy extent buffers
and all test roots have a single node/leaf (root node at level 0).
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/qgroup.c')
-rw-r--r-- | fs/btrfs/qgroup.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index d977c4f109fc..ae7e2d79209f 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -636,7 +636,7 @@ static int add_qgroup_relation_item(struct btrfs_trans_handle *trans, u64 src, ret = btrfs_insert_empty_item(trans, quota_root, path, &key, 0); - btrfs_mark_buffer_dirty(path->nodes[0]); + btrfs_mark_buffer_dirty(trans, path->nodes[0]); btrfs_free_path(path); return ret; @@ -714,7 +714,7 @@ static int add_qgroup_item(struct btrfs_trans_handle *trans, btrfs_set_qgroup_info_excl(leaf, qgroup_info, 0); btrfs_set_qgroup_info_excl_cmpr(leaf, qgroup_info, 0); - btrfs_mark_buffer_dirty(leaf); + btrfs_mark_buffer_dirty(trans, leaf); btrfs_release_path(path); @@ -733,7 +733,7 @@ static int add_qgroup_item(struct btrfs_trans_handle *trans, btrfs_set_qgroup_limit_rsv_rfer(leaf, qgroup_limit, 0); btrfs_set_qgroup_limit_rsv_excl(leaf, qgroup_limit, 0); - btrfs_mark_buffer_dirty(leaf); + btrfs_mark_buffer_dirty(trans, leaf); ret = 0; out: @@ -822,7 +822,7 @@ static int update_qgroup_limit_item(struct btrfs_trans_handle *trans, btrfs_set_qgroup_limit_rsv_rfer(l, qgroup_limit, qgroup->rsv_rfer); btrfs_set_qgroup_limit_rsv_excl(l, qgroup_limit, qgroup->rsv_excl); - btrfs_mark_buffer_dirty(l); + btrfs_mark_buffer_dirty(trans, l); out: btrfs_free_path(path); @@ -868,7 +868,7 @@ static int update_qgroup_info_item(struct btrfs_trans_handle *trans, btrfs_set_qgroup_info_excl(l, qgroup_info, qgroup->excl); btrfs_set_qgroup_info_excl_cmpr(l, qgroup_info, qgroup->excl_cmpr); - btrfs_mark_buffer_dirty(l); + btrfs_mark_buffer_dirty(trans, l); out: btrfs_free_path(path); @@ -910,7 +910,7 @@ static int update_qgroup_status_item(struct btrfs_trans_handle *trans) btrfs_set_qgroup_status_rescan(l, ptr, fs_info->qgroup_rescan_progress.objectid); - btrfs_mark_buffer_dirty(l); + btrfs_mark_buffer_dirty(trans, l); out: btrfs_free_path(path); @@ -1084,7 +1084,7 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info) BTRFS_QGROUP_STATUS_FLAGS_MASK); btrfs_set_qgroup_status_rescan(leaf, ptr, 0); - btrfs_mark_buffer_dirty(leaf); + btrfs_mark_buffer_dirty(trans, leaf); key.objectid = 0; key.type = BTRFS_ROOT_REF_KEY; |