diff options
Diffstat (limited to 'fs/btrfs/delayed-ref.c')
-rw-r--r-- | fs/btrfs/delayed-ref.c | 29 |
1 files changed, 8 insertions, 21 deletions
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index f3bff89eecf0..31299646024d 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c | |||
@@ -199,44 +199,31 @@ static struct btrfs_delayed_ref_head *htree_insert(struct rb_root *root, | |||
199 | */ | 199 | */ |
200 | static struct btrfs_delayed_ref_head * | 200 | static struct btrfs_delayed_ref_head * |
201 | find_ref_head(struct rb_root *root, u64 bytenr, | 201 | find_ref_head(struct rb_root *root, u64 bytenr, |
202 | struct btrfs_delayed_ref_head **last, int return_bigger) | 202 | int return_bigger) |
203 | { | 203 | { |
204 | struct rb_node *n; | 204 | struct rb_node *n; |
205 | struct btrfs_delayed_ref_head *entry; | 205 | struct btrfs_delayed_ref_head *entry; |
206 | int cmp = 0; | ||
207 | 206 | ||
208 | again: | ||
209 | n = root->rb_node; | 207 | n = root->rb_node; |
210 | entry = NULL; | 208 | entry = NULL; |
211 | while (n) { | 209 | while (n) { |
212 | entry = rb_entry(n, struct btrfs_delayed_ref_head, href_node); | 210 | entry = rb_entry(n, struct btrfs_delayed_ref_head, href_node); |
213 | if (last) | ||
214 | *last = entry; | ||
215 | 211 | ||
216 | if (bytenr < entry->node.bytenr) | 212 | if (bytenr < entry->node.bytenr) |
217 | cmp = -1; | ||
218 | else if (bytenr > entry->node.bytenr) | ||
219 | cmp = 1; | ||
220 | else | ||
221 | cmp = 0; | ||
222 | |||
223 | if (cmp < 0) | ||
224 | n = n->rb_left; | 213 | n = n->rb_left; |
225 | else if (cmp > 0) | 214 | else if (bytenr > entry->node.bytenr) |
226 | n = n->rb_right; | 215 | n = n->rb_right; |
227 | else | 216 | else |
228 | return entry; | 217 | return entry; |
229 | } | 218 | } |
230 | if (entry && return_bigger) { | 219 | if (entry && return_bigger) { |
231 | if (cmp > 0) { | 220 | if (bytenr > entry->node.bytenr) { |
232 | n = rb_next(&entry->href_node); | 221 | n = rb_next(&entry->href_node); |
233 | if (!n) | 222 | if (!n) |
234 | n = rb_first(root); | 223 | n = rb_first(root); |
235 | entry = rb_entry(n, struct btrfs_delayed_ref_head, | 224 | entry = rb_entry(n, struct btrfs_delayed_ref_head, |
236 | href_node); | 225 | href_node); |
237 | bytenr = entry->node.bytenr; | 226 | return entry; |
238 | return_bigger = 0; | ||
239 | goto again; | ||
240 | } | 227 | } |
241 | return entry; | 228 | return entry; |
242 | } | 229 | } |
@@ -415,12 +402,12 @@ btrfs_select_ref_head(struct btrfs_trans_handle *trans) | |||
415 | 402 | ||
416 | again: | 403 | again: |
417 | start = delayed_refs->run_delayed_start; | 404 | start = delayed_refs->run_delayed_start; |
418 | head = find_ref_head(&delayed_refs->href_root, start, NULL, 1); | 405 | head = find_ref_head(&delayed_refs->href_root, start, 1); |
419 | if (!head && !loop) { | 406 | if (!head && !loop) { |
420 | delayed_refs->run_delayed_start = 0; | 407 | delayed_refs->run_delayed_start = 0; |
421 | start = 0; | 408 | start = 0; |
422 | loop = true; | 409 | loop = true; |
423 | head = find_ref_head(&delayed_refs->href_root, start, NULL, 1); | 410 | head = find_ref_head(&delayed_refs->href_root, start, 1); |
424 | if (!head) | 411 | if (!head) |
425 | return NULL; | 412 | return NULL; |
426 | } else if (!head && loop) { | 413 | } else if (!head && loop) { |
@@ -508,6 +495,7 @@ update_existing_head_ref(struct btrfs_delayed_ref_node *existing, | |||
508 | ref = btrfs_delayed_node_to_head(update); | 495 | ref = btrfs_delayed_node_to_head(update); |
509 | BUG_ON(existing_ref->is_data != ref->is_data); | 496 | BUG_ON(existing_ref->is_data != ref->is_data); |
510 | 497 | ||
498 | spin_lock(&existing_ref->lock); | ||
511 | if (ref->must_insert_reserved) { | 499 | if (ref->must_insert_reserved) { |
512 | /* if the extent was freed and then | 500 | /* if the extent was freed and then |
513 | * reallocated before the delayed ref | 501 | * reallocated before the delayed ref |
@@ -549,7 +537,6 @@ update_existing_head_ref(struct btrfs_delayed_ref_node *existing, | |||
549 | * only need the lock for this case cause we could be processing it | 537 | * only need the lock for this case cause we could be processing it |
550 | * currently, for refs we just added we know we're a-ok. | 538 | * currently, for refs we just added we know we're a-ok. |
551 | */ | 539 | */ |
552 | spin_lock(&existing_ref->lock); | ||
553 | existing->ref_mod += update->ref_mod; | 540 | existing->ref_mod += update->ref_mod; |
554 | spin_unlock(&existing_ref->lock); | 541 | spin_unlock(&existing_ref->lock); |
555 | } | 542 | } |
@@ -898,7 +885,7 @@ btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr) | |||
898 | struct btrfs_delayed_ref_root *delayed_refs; | 885 | struct btrfs_delayed_ref_root *delayed_refs; |
899 | 886 | ||
900 | delayed_refs = &trans->transaction->delayed_refs; | 887 | delayed_refs = &trans->transaction->delayed_refs; |
901 | return find_ref_head(&delayed_refs->href_root, bytenr, NULL, 0); | 888 | return find_ref_head(&delayed_refs->href_root, bytenr, 0); |
902 | } | 889 | } |
903 | 890 | ||
904 | void btrfs_delayed_ref_exit(void) | 891 | void btrfs_delayed_ref_exit(void) |