Skip to content

Commit 7664311

Browse files
morbidrsakdave
authored andcommitted
btrfs: fix deletion of a range spanning parts two RAID stripe extents
When a user requests the deletion of a range that spans multiple stripe extents and btrfs_search_slot() returns us the second RAID stripe extent, we need to pick the previous item and truncate it, if there's still a range to delete left, move on to the next item. The following diagram illustrates the operation: |--- RAID Stripe Extent ---||--- RAID Stripe Extent ---| |--- keep ---|--- drop ---| While at it, comment the trivial case of a whole item delete as well. Signed-off-by: Johannes Thumshirn <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 50cae2c commit 7664311

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

fs/btrfs/raid-stripe-tree.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,37 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
9999
found_end = found_start + key.offset;
100100
ret = 0;
101101

102+
/*
103+
* The stripe extent starts before the range we want to delete,
104+
* but the range spans more than one stripe extent:
105+
*
106+
* |--- RAID Stripe Extent ---||--- RAID Stripe Extent ---|
107+
* |--- keep ---|--- drop ---|
108+
*
109+
* This means we have to get the previous item, truncate its
110+
* length and then restart the search.
111+
*/
112+
if (found_start > start) {
113+
if (slot == 0) {
114+
ret = btrfs_previous_item(stripe_root, path, start,
115+
BTRFS_RAID_STRIPE_KEY);
116+
if (ret) {
117+
if (ret > 0)
118+
ret = -ENOENT;
119+
break;
120+
}
121+
} else {
122+
path->slots[0]--;
123+
}
124+
125+
leaf = path->nodes[0];
126+
slot = path->slots[0];
127+
btrfs_item_key_to_cpu(leaf, &key, slot);
128+
found_start = key.objectid;
129+
found_end = found_start + key.offset;
130+
ASSERT(found_start <= start);
131+
}
132+
102133
if (key.type != BTRFS_RAID_STRIPE_KEY)
103134
break;
104135

@@ -152,6 +183,7 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
152183
break;
153184
}
154185

186+
/* Finally we can delete the whole item, no more special cases. */
155187
ret = btrfs_del_item(trans, stripe_root, path);
156188
if (ret)
157189
break;

0 commit comments

Comments
 (0)