diff options
author | Boris Burkov <boris@bur.io> | 2023-12-01 22:00:13 +0100 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2023-12-06 22:32:57 +0100 |
commit | e85a0adacf170634878fffcbf34b725aff3f49ed (patch) | |
tree | 02caac7c49f9d78102d52934161d57657e2b05ea /fs/btrfs/qgroup.h | |
parent | btrfs: don't clear qgroup reserved bit in release_folio (diff) | |
download | linux-e85a0adacf170634878fffcbf34b725aff3f49ed.tar.xz linux-e85a0adacf170634878fffcbf34b725aff3f49ed.zip |
btrfs: ensure releasing squota reserve on head refs
A reservation goes through a 3 step lifetime:
- generated during delalloc
- released/counted by ordered_extent allocation
- freed by running delayed ref
That third step depends on must_insert_reserved on the head ref, so the
head ref with that field set owns the reservation. Once you prepare to
run the head ref, must_insert_reserved is unset, which means that
running the ref must free the reservation, whether or not it succeeds,
or else the reservation is leaked. That results in either a risk of
spurious ENOSPC if the fs stays writeable or a warning on unmount if it
is readonly.
The existing squota code was aware of these invariants, but missed a few
cases. Improve it by adding a helper function to use in the cleanup
paths and call it from the existing early returns in running delayed
refs. This also simplifies btrfs_record_squota_delta and struct
btrfs_quota_delta.
This fixes (or at least improves the reliability of) generic/475 with
"mkfs -O squota". On my machine, that test failed ~4/10 times without
this patch and passed 100/100 times with it.
Signed-off-by: Boris Burkov <boris@bur.io>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/qgroup.h')
-rw-r--r-- | fs/btrfs/qgroup.h | 3 |
1 files changed, 1 insertions, 2 deletions
diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h index 15b485506104..be18c862e64e 100644 --- a/fs/btrfs/qgroup.h +++ b/fs/btrfs/qgroup.h @@ -274,8 +274,6 @@ struct btrfs_squota_delta { u64 root; /* The number of bytes in the extent being counted. */ u64 num_bytes; - /* The number of bytes reserved for this extent. */ - u64 rsv_bytes; /* The generation the extent was created in. */ u64 generation; /* Whether we are using or freeing the extent. */ @@ -422,6 +420,7 @@ int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *eb); void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans); bool btrfs_check_quota_leak(struct btrfs_fs_info *fs_info); +void btrfs_free_squota_rsv(struct btrfs_fs_info *fs_info, u64 root, u64 rsv_bytes); int btrfs_record_squota_delta(struct btrfs_fs_info *fs_info, struct btrfs_squota_delta *delta); |