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) | 
