Message ID | 038e3971d12f2f8aef69a96c999916f37165f12b.1733989299.git.jth@kernel.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | btrfs: more RST delete fixes | expand |
On Thu, Dec 12, 2024 at 7:56 AM Johannes Thumshirn <jth@kernel.org> wrote: > > From: Johannes Thumshirn <johannes.thumshirn@wdc.com> > > If the stripe extent we want to delete starts before the range we want to > delete and ends after the range we want to delete we're punching a > hole in the stripe extent: > > |--- RAID Stripe Extent ---| > | keep |--- drop ---| keep | > > This means we need to a) truncate the existing item and b) > create a second item for the remaining range. > > Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> > --- > fs/btrfs/ctree.c | 1 + > fs/btrfs/raid-stripe-tree.c | 54 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 55 insertions(+) > > diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c > index 693dc27ffb89..5682692b5ba5 100644 > --- a/fs/btrfs/ctree.c > +++ b/fs/btrfs/ctree.c > @@ -3903,6 +3903,7 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, > btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); > > BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY && > + key.type != BTRFS_RAID_STRIPE_KEY && > key.type != BTRFS_EXTENT_CSUM_KEY); > > if (btrfs_leaf_free_space(leaf) >= ins_len) > diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c > index ccf455b30314..6ec72732c4ad 100644 > --- a/fs/btrfs/raid-stripe-tree.c > +++ b/fs/btrfs/raid-stripe-tree.c > @@ -138,6 +138,60 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le > trace_btrfs_raid_extent_delete(fs_info, start, end, > found_start, found_end); > > + /* > + * The stripe extent starts before the range we want to delete > + * and ends after the range we want to delete, i.e. we're > + * punching a hole in the stripe extent: > + * > + * |--- RAID Stripe Extent ---| > + * | keep |--- drop ---| keep | > + * > + * This means we need to a) truncate the existing item and b) > + * create a second item for the remaining range. > + */ > + if (found_start < start && found_end > end) { > + size_t item_size; > + u64 diff_start = start - found_start; > + u64 diff_end = found_end - end; > + struct btrfs_stripe_extent *extent; > + struct btrfs_key newkey = { > + .objectid = end, > + .type = BTRFS_RAID_STRIPE_KEY, > + .offset = diff_end, > + }; > + > + /* "right" item */ > + ret = btrfs_duplicate_item(trans, stripe_root, path, > + &newkey); > + if (ret) > + break; > + > + item_size = btrfs_item_size(leaf, path->slots[0]); > + extent = btrfs_item_ptr(leaf, path->slots[0], > + struct btrfs_stripe_extent); > + > + for (int i = 0; i < btrfs_num_raid_stripes(item_size); > + i++) { We can place this in a single line, nowadays we tolerate more than 80 characters, anything up to 90 is fine. It makes things more readable. > + struct btrfs_raid_stride *stride = > + &extent->strides[i]; Same here. > + u64 phys; > + > + phys = btrfs_raid_stride_physical(leaf, stride); > + phys += diff_start + length; > + btrfs_set_raid_stride_physical(leaf, stride, > + phys); Same here. > + } > + btrfs_mark_buffer_dirty(trans, leaf); Not needed, already done down the call chain of btrfs_duplicate_item(). > + > + /* "left" item */ > + path->slots[0]--; > + btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); > + btrfs_partially_delete_raid_extent(trans, path, &key, > + diff_start, 0); > + length = 0; > + break; There's the 'break', no need to assign 0 to the length as it's not used anymore after breaking out of the loop. Otherwise it looks good, thanks. > + } > + > /* > * The stripe extent starts before the range we want to delete: > * > -- > 2.43.0 > >
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 693dc27ffb89..5682692b5ba5 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -3903,6 +3903,7 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY && + key.type != BTRFS_RAID_STRIPE_KEY && key.type != BTRFS_EXTENT_CSUM_KEY); if (btrfs_leaf_free_space(leaf) >= ins_len) diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c index ccf455b30314..6ec72732c4ad 100644 --- a/fs/btrfs/raid-stripe-tree.c +++ b/fs/btrfs/raid-stripe-tree.c @@ -138,6 +138,60 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le trace_btrfs_raid_extent_delete(fs_info, start, end, found_start, found_end); + /* + * The stripe extent starts before the range we want to delete + * and ends after the range we want to delete, i.e. we're + * punching a hole in the stripe extent: + * + * |--- RAID Stripe Extent ---| + * | keep |--- drop ---| keep | + * + * This means we need to a) truncate the existing item and b) + * create a second item for the remaining range. + */ + if (found_start < start && found_end > end) { + size_t item_size; + u64 diff_start = start - found_start; + u64 diff_end = found_end - end; + struct btrfs_stripe_extent *extent; + struct btrfs_key newkey = { + .objectid = end, + .type = BTRFS_RAID_STRIPE_KEY, + .offset = diff_end, + }; + + /* "right" item */ + ret = btrfs_duplicate_item(trans, stripe_root, path, + &newkey); + if (ret) + break; + + item_size = btrfs_item_size(leaf, path->slots[0]); + extent = btrfs_item_ptr(leaf, path->slots[0], + struct btrfs_stripe_extent); + + for (int i = 0; i < btrfs_num_raid_stripes(item_size); + i++) { + struct btrfs_raid_stride *stride = + &extent->strides[i]; + u64 phys; + + phys = btrfs_raid_stride_physical(leaf, stride); + phys += diff_start + length; + btrfs_set_raid_stride_physical(leaf, stride, + phys); + } + btrfs_mark_buffer_dirty(trans, leaf); + + /* "left" item */ + path->slots[0]--; + btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); + btrfs_partially_delete_raid_extent(trans, path, &key, + diff_start, 0); + length = 0; + break; + } + /* * The stripe extent starts before the range we want to delete: *