diff options
Diffstat (limited to 'fs/btrfs/delayed-ref.c')
-rw-r--r-- | fs/btrfs/delayed-ref.c | 163 |
1 files changed, 128 insertions, 35 deletions
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index da7419ed01bb..ae9411773397 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c | |||
@@ -38,17 +38,14 @@ | |||
38 | static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref2, | 38 | static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref2, |
39 | struct btrfs_delayed_tree_ref *ref1) | 39 | struct btrfs_delayed_tree_ref *ref1) |
40 | { | 40 | { |
41 | if (ref1->node.type == BTRFS_TREE_BLOCK_REF_KEY) { | 41 | if (ref1->root < ref2->root) |
42 | if (ref1->root < ref2->root) | 42 | return -1; |
43 | return -1; | 43 | if (ref1->root > ref2->root) |
44 | if (ref1->root > ref2->root) | 44 | return 1; |
45 | return 1; | 45 | if (ref1->parent < ref2->parent) |
46 | } else { | 46 | return -1; |
47 | if (ref1->parent < ref2->parent) | 47 | if (ref1->parent > ref2->parent) |
48 | return -1; | 48 | return 1; |
49 | if (ref1->parent > ref2->parent) | ||
50 | return 1; | ||
51 | } | ||
52 | return 0; | 49 | return 0; |
53 | } | 50 | } |
54 | 51 | ||
@@ -85,7 +82,8 @@ static int comp_data_refs(struct btrfs_delayed_data_ref *ref2, | |||
85 | * type of the delayed backrefs and content of delayed backrefs. | 82 | * type of the delayed backrefs and content of delayed backrefs. |
86 | */ | 83 | */ |
87 | static int comp_entry(struct btrfs_delayed_ref_node *ref2, | 84 | static int comp_entry(struct btrfs_delayed_ref_node *ref2, |
88 | struct btrfs_delayed_ref_node *ref1) | 85 | struct btrfs_delayed_ref_node *ref1, |
86 | bool compare_seq) | ||
89 | { | 87 | { |
90 | if (ref1->bytenr < ref2->bytenr) | 88 | if (ref1->bytenr < ref2->bytenr) |
91 | return -1; | 89 | return -1; |
@@ -102,10 +100,12 @@ static int comp_entry(struct btrfs_delayed_ref_node *ref2, | |||
102 | if (ref1->type > ref2->type) | 100 | if (ref1->type > ref2->type) |
103 | return 1; | 101 | return 1; |
104 | /* merging of sequenced refs is not allowed */ | 102 | /* merging of sequenced refs is not allowed */ |
105 | if (ref1->seq < ref2->seq) | 103 | if (compare_seq) { |
106 | return -1; | 104 | if (ref1->seq < ref2->seq) |
107 | if (ref1->seq > ref2->seq) | 105 | return -1; |
108 | return 1; | 106 | if (ref1->seq > ref2->seq) |
107 | return 1; | ||
108 | } | ||
109 | if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY || | 109 | if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY || |
110 | ref1->type == BTRFS_SHARED_BLOCK_REF_KEY) { | 110 | ref1->type == BTRFS_SHARED_BLOCK_REF_KEY) { |
111 | return comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref2), | 111 | return comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref2), |
@@ -139,7 +139,7 @@ static struct btrfs_delayed_ref_node *tree_insert(struct rb_root *root, | |||
139 | entry = rb_entry(parent_node, struct btrfs_delayed_ref_node, | 139 | entry = rb_entry(parent_node, struct btrfs_delayed_ref_node, |
140 | rb_node); | 140 | rb_node); |
141 | 141 | ||
142 | cmp = comp_entry(entry, ins); | 142 | cmp = comp_entry(entry, ins, 1); |
143 | if (cmp < 0) | 143 | if (cmp < 0) |
144 | p = &(*p)->rb_left; | 144 | p = &(*p)->rb_left; |
145 | else if (cmp > 0) | 145 | else if (cmp > 0) |
@@ -233,6 +233,114 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans, | |||
233 | return 0; | 233 | return 0; |
234 | } | 234 | } |
235 | 235 | ||
236 | static void inline drop_delayed_ref(struct btrfs_trans_handle *trans, | ||
237 | struct btrfs_delayed_ref_root *delayed_refs, | ||
238 | struct btrfs_delayed_ref_node *ref) | ||
239 | { | ||
240 | rb_erase(&ref->rb_node, &delayed_refs->root); | ||
241 | ref->in_tree = 0; | ||
242 | btrfs_put_delayed_ref(ref); | ||
243 | delayed_refs->num_entries--; | ||
244 | if (trans->delayed_ref_updates) | ||
245 | trans->delayed_ref_updates--; | ||
246 | } | ||
247 | |||
248 | static int merge_ref(struct btrfs_trans_handle *trans, | ||
249 | struct btrfs_delayed_ref_root *delayed_refs, | ||
250 | struct btrfs_delayed_ref_node *ref, u64 seq) | ||
251 | { | ||
252 | struct rb_node *node; | ||
253 | int merged = 0; | ||
254 | int mod = 0; | ||
255 | int done = 0; | ||
256 | |||
257 | node = rb_prev(&ref->rb_node); | ||
258 | while (node) { | ||
259 | struct btrfs_delayed_ref_node *next; | ||
260 | |||
261 | next = rb_entry(node, struct btrfs_delayed_ref_node, rb_node); | ||
262 | node = rb_prev(node); | ||
263 | if (next->bytenr != ref->bytenr) | ||
264 | break; | ||
265 | if (seq && next->seq >= seq) | ||
266 | break; | ||
267 | if (comp_entry(ref, next, 0)) | ||
268 | continue; | ||
269 | |||
270 | if (ref->action == next->action) { | ||
271 | mod = next->ref_mod; | ||
272 | } else { | ||
273 | if (ref->ref_mod < next->ref_mod) { | ||
274 | struct btrfs_delayed_ref_node *tmp; | ||
275 | |||
276 | tmp = ref; | ||
277 | ref = next; | ||
278 | next = tmp; | ||
279 | done = 1; | ||
280 | } | ||
281 | mod = -next->ref_mod; | ||
282 | } | ||
283 | |||
284 | merged++; | ||
285 | drop_delayed_ref(trans, delayed_refs, next); | ||
286 | ref->ref_mod += mod; | ||
287 | if (ref->ref_mod == 0) { | ||
288 | drop_delayed_ref(trans, delayed_refs, ref); | ||
289 | break; | ||
290 | } else { | ||
291 | /* | ||
292 | * You can't have multiples of the same ref on a tree | ||
293 | * block. | ||
294 | */ | ||
295 | WARN_ON(ref->type == BTRFS_TREE_BLOCK_REF_KEY || | ||
296 | ref->type == BTRFS_SHARED_BLOCK_REF_KEY); | ||
297 | } | ||
298 | |||
299 | if (done) | ||
300 | break; | ||
301 | node = rb_prev(&ref->rb_node); | ||
302 | } | ||
303 | |||
304 | return merged; | ||
305 | } | ||
306 | |||
307 | void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans, | ||
308 | struct btrfs_fs_info *fs_info, | ||
309 | struct btrfs_delayed_ref_root *delayed_refs, | ||
310 | struct btrfs_delayed_ref_head *head) | ||
311 | { | ||
312 | struct rb_node *node; | ||
313 | u64 seq = 0; | ||
314 | |||
315 | spin_lock(&fs_info->tree_mod_seq_lock); | ||
316 | if (!list_empty(&fs_info->tree_mod_seq_list)) { | ||
317 | struct seq_list *elem; | ||
318 | |||
319 | elem = list_first_entry(&fs_info->tree_mod_seq_list, | ||
320 | struct seq_list, list); | ||
321 | seq = elem->seq; | ||
322 | } | ||
323 | spin_unlock(&fs_info->tree_mod_seq_lock); | ||
324 | |||
325 | node = rb_prev(&head->node.rb_node); | ||
326 | while (node) { | ||
327 | struct btrfs_delayed_ref_node *ref; | ||
328 | |||
329 | ref = rb_entry(node, struct btrfs_delayed_ref_node, | ||
330 | rb_node); | ||
331 | if (ref->bytenr != head->node.bytenr) | ||
332 | break; | ||
333 | |||
334 | /* We can't merge refs that are outside of our seq count */ | ||
335 | if (seq && ref->seq >= seq) | ||
336 | break; | ||
337 | if (merge_ref(trans, delayed_refs, ref, seq)) | ||
338 | node = rb_prev(&head->node.rb_node); | ||
339 | else | ||
340 | node = rb_prev(node); | ||
341 | } | ||
342 | } | ||
343 | |||
236 | int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, | 344 | int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, |
237 | struct btrfs_delayed_ref_root *delayed_refs, | 345 | struct btrfs_delayed_ref_root *delayed_refs, |
238 | u64 seq) | 346 | u64 seq) |
@@ -336,18 +444,11 @@ update_existing_ref(struct btrfs_trans_handle *trans, | |||
336 | * every changing the extent allocation tree. | 444 | * every changing the extent allocation tree. |
337 | */ | 445 | */ |
338 | existing->ref_mod--; | 446 | existing->ref_mod--; |
339 | if (existing->ref_mod == 0) { | 447 | if (existing->ref_mod == 0) |
340 | rb_erase(&existing->rb_node, | 448 | drop_delayed_ref(trans, delayed_refs, existing); |
341 | &delayed_refs->root); | 449 | else |
342 | existing->in_tree = 0; | ||
343 | btrfs_put_delayed_ref(existing); | ||
344 | delayed_refs->num_entries--; | ||
345 | if (trans->delayed_ref_updates) | ||
346 | trans->delayed_ref_updates--; | ||
347 | } else { | ||
348 | WARN_ON(existing->type == BTRFS_TREE_BLOCK_REF_KEY || | 450 | WARN_ON(existing->type == BTRFS_TREE_BLOCK_REF_KEY || |
349 | existing->type == BTRFS_SHARED_BLOCK_REF_KEY); | 451 | existing->type == BTRFS_SHARED_BLOCK_REF_KEY); |
350 | } | ||
351 | } else { | 452 | } else { |
352 | WARN_ON(existing->type == BTRFS_TREE_BLOCK_REF_KEY || | 453 | WARN_ON(existing->type == BTRFS_TREE_BLOCK_REF_KEY || |
353 | existing->type == BTRFS_SHARED_BLOCK_REF_KEY); | 454 | existing->type == BTRFS_SHARED_BLOCK_REF_KEY); |
@@ -662,9 +763,6 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info, | |||
662 | add_delayed_tree_ref(fs_info, trans, &ref->node, bytenr, | 763 | add_delayed_tree_ref(fs_info, trans, &ref->node, bytenr, |
663 | num_bytes, parent, ref_root, level, action, | 764 | num_bytes, parent, ref_root, level, action, |
664 | for_cow); | 765 | for_cow); |
665 | if (!need_ref_seq(for_cow, ref_root) && | ||
666 | waitqueue_active(&fs_info->tree_mod_seq_wait)) | ||
667 | wake_up(&fs_info->tree_mod_seq_wait); | ||
668 | spin_unlock(&delayed_refs->lock); | 766 | spin_unlock(&delayed_refs->lock); |
669 | if (need_ref_seq(for_cow, ref_root)) | 767 | if (need_ref_seq(for_cow, ref_root)) |
670 | btrfs_qgroup_record_ref(trans, &ref->node, extent_op); | 768 | btrfs_qgroup_record_ref(trans, &ref->node, extent_op); |
@@ -713,9 +811,6 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info, | |||
713 | add_delayed_data_ref(fs_info, trans, &ref->node, bytenr, | 811 | add_delayed_data_ref(fs_info, trans, &ref->node, bytenr, |
714 | num_bytes, parent, ref_root, owner, offset, | 812 | num_bytes, parent, ref_root, owner, offset, |
715 | action, for_cow); | 813 | action, for_cow); |
716 | if (!need_ref_seq(for_cow, ref_root) && | ||
717 | waitqueue_active(&fs_info->tree_mod_seq_wait)) | ||
718 | wake_up(&fs_info->tree_mod_seq_wait); | ||
719 | spin_unlock(&delayed_refs->lock); | 814 | spin_unlock(&delayed_refs->lock); |
720 | if (need_ref_seq(for_cow, ref_root)) | 815 | if (need_ref_seq(for_cow, ref_root)) |
721 | btrfs_qgroup_record_ref(trans, &ref->node, extent_op); | 816 | btrfs_qgroup_record_ref(trans, &ref->node, extent_op); |
@@ -744,8 +839,6 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info, | |||
744 | num_bytes, BTRFS_UPDATE_DELAYED_HEAD, | 839 | num_bytes, BTRFS_UPDATE_DELAYED_HEAD, |
745 | extent_op->is_data); | 840 | extent_op->is_data); |
746 | 841 | ||
747 | if (waitqueue_active(&fs_info->tree_mod_seq_wait)) | ||
748 | wake_up(&fs_info->tree_mod_seq_wait); | ||
749 | spin_unlock(&delayed_refs->lock); | 842 | spin_unlock(&delayed_refs->lock); |
750 | return 0; | 843 | return 0; |
751 | } | 844 | } |