Blame view
fs/btrfs/delayed-ref.c
26 KB
56bec294d Btrfs: do extent ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* * Copyright (C) 2009 Oracle. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */ #include <linux/sched.h> |
5a0e3ad6a include cleanup: ... |
20 |
#include <linux/slab.h> |
56bec294d Btrfs: do extent ... |
21 |
#include <linux/sort.h> |
56bec294d Btrfs: do extent ... |
22 23 24 |
#include "ctree.h" #include "delayed-ref.h" #include "transaction.h" |
3368d001b btrfs: qgroup: Re... |
25 |
#include "qgroup.h" |
56bec294d Btrfs: do extent ... |
26 |
|
78a6184a3 Btrfs: use slabs ... |
27 28 29 30 |
struct kmem_cache *btrfs_delayed_ref_head_cachep; struct kmem_cache *btrfs_delayed_tree_ref_cachep; struct kmem_cache *btrfs_delayed_data_ref_cachep; struct kmem_cache *btrfs_delayed_extent_op_cachep; |
56bec294d Btrfs: do extent ... |
31 32 33 34 35 36 37 |
/* * delayed back reference update tracking. For subvolume trees * we queue up extent allocations and backref maintenance for * delayed processing. This avoids deep call chains where we * add extents in the middle of btrfs_search_slot, and it allows * us to buffer up frequently modified backrefs in an rb tree instead * of hammering updates on the extent allocation tree. |
56bec294d Btrfs: do extent ... |
38 39 40 |
*/ /* |
5d4f98a28 Btrfs: Mixed back... |
41 42 |
* compare two delayed tree backrefs with same bytenr and type */ |
c7ad7c843 btrfs: switch arg... |
43 44 |
static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref1, struct btrfs_delayed_tree_ref *ref2) |
5d4f98a28 Btrfs: Mixed back... |
45 |
{ |
3b60d436a btrfs: remove typ... |
46 |
if (ref1->node.type == BTRFS_TREE_BLOCK_REF_KEY) { |
41b0fc428 Btrfs: compare re... |
47 48 49 50 51 52 53 54 55 56 |
if (ref1->root < ref2->root) return -1; if (ref1->root > ref2->root) return 1; } else { if (ref1->parent < ref2->parent) return -1; if (ref1->parent > ref2->parent) return 1; } |
5d4f98a28 Btrfs: Mixed back... |
57 58 59 60 61 |
return 0; } /* * compare two delayed data backrefs with same bytenr and type |
56bec294d Btrfs: do extent ... |
62 |
*/ |
c7ad7c843 btrfs: switch arg... |
63 64 |
static int comp_data_refs(struct btrfs_delayed_data_ref *ref1, struct btrfs_delayed_data_ref *ref2) |
56bec294d Btrfs: do extent ... |
65 |
{ |
5d4f98a28 Btrfs: Mixed back... |
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
if (ref1->node.type == BTRFS_EXTENT_DATA_REF_KEY) { if (ref1->root < ref2->root) return -1; if (ref1->root > ref2->root) return 1; if (ref1->objectid < ref2->objectid) return -1; if (ref1->objectid > ref2->objectid) return 1; if (ref1->offset < ref2->offset) return -1; if (ref1->offset > ref2->offset) return 1; } else { if (ref1->parent < ref2->parent) return -1; if (ref1->parent > ref2->parent) return 1; } return 0; } |
1d148e593 btrfs: add a comp... |
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
static int comp_refs(struct btrfs_delayed_ref_node *ref1, struct btrfs_delayed_ref_node *ref2, bool check_seq) { int ret = 0; if (ref1->type < ref2->type) return -1; if (ref1->type > ref2->type) return 1; if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY || ref1->type == BTRFS_SHARED_BLOCK_REF_KEY) ret = comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref1), btrfs_delayed_node_to_tree_ref(ref2)); else ret = comp_data_refs(btrfs_delayed_node_to_data_ref(ref1), btrfs_delayed_node_to_data_ref(ref2)); if (ret) return ret; if (check_seq) { if (ref1->seq < ref2->seq) return -1; if (ref1->seq > ref2->seq) return 1; } return 0; } |
c46effa60 Btrfs: introduce ... |
114 115 116 117 118 119 120 121 122 123 124 |
/* insert a new ref to head ref rbtree */ static struct btrfs_delayed_ref_head *htree_insert(struct rb_root *root, struct rb_node *node) { struct rb_node **p = &root->rb_node; struct rb_node *parent_node = NULL; struct btrfs_delayed_ref_head *entry; struct btrfs_delayed_ref_head *ins; u64 bytenr; ins = rb_entry(node, struct btrfs_delayed_ref_head, href_node); |
d278850ef btrfs: remove del... |
125 |
bytenr = ins->bytenr; |
c46effa60 Btrfs: introduce ... |
126 127 128 129 |
while (*p) { parent_node = *p; entry = rb_entry(parent_node, struct btrfs_delayed_ref_head, href_node); |
d278850ef btrfs: remove del... |
130 |
if (bytenr < entry->bytenr) |
c46effa60 Btrfs: introduce ... |
131 |
p = &(*p)->rb_left; |
d278850ef btrfs: remove del... |
132 |
else if (bytenr > entry->bytenr) |
c46effa60 Btrfs: introduce ... |
133 134 135 136 137 138 139 140 141 |
p = &(*p)->rb_right; else return entry; } rb_link_node(node, parent_node, p); rb_insert_color(node, root); return NULL; } |
0e0adbcfd btrfs: track refs... |
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
static struct btrfs_delayed_ref_node* tree_insert(struct rb_root *root, struct btrfs_delayed_ref_node *ins) { struct rb_node **p = &root->rb_node; struct rb_node *node = &ins->ref_node; struct rb_node *parent_node = NULL; struct btrfs_delayed_ref_node *entry; while (*p) { int comp; parent_node = *p; entry = rb_entry(parent_node, struct btrfs_delayed_ref_node, ref_node); comp = comp_refs(ins, entry, true); if (comp < 0) p = &(*p)->rb_left; else if (comp > 0) p = &(*p)->rb_right; else return entry; } rb_link_node(node, parent_node, p); rb_insert_color(node, root); return NULL; } |
56bec294d Btrfs: do extent ... |
169 |
/* |
5d4f98a28 Btrfs: Mixed back... |
170 |
* find an head entry based on bytenr. This returns the delayed ref |
d1270cd91 Btrfs: put back d... |
171 172 173 |
* head if it was able to find one, or NULL if nothing was in that spot. * If return_bigger is given, the next bigger entry is returned if no exact * match is found. |
56bec294d Btrfs: do extent ... |
174 |
*/ |
c46effa60 Btrfs: introduce ... |
175 176 |
static struct btrfs_delayed_ref_head * find_ref_head(struct rb_root *root, u64 bytenr, |
85fdfdf61 Btrfs: cleanup de... |
177 |
int return_bigger) |
56bec294d Btrfs: do extent ... |
178 |
{ |
d1270cd91 Btrfs: put back d... |
179 |
struct rb_node *n; |
c46effa60 Btrfs: introduce ... |
180 |
struct btrfs_delayed_ref_head *entry; |
56bec294d Btrfs: do extent ... |
181 |
|
d1270cd91 Btrfs: put back d... |
182 183 |
n = root->rb_node; entry = NULL; |
56bec294d Btrfs: do extent ... |
184 |
while (n) { |
c46effa60 Btrfs: introduce ... |
185 |
entry = rb_entry(n, struct btrfs_delayed_ref_head, href_node); |
56bec294d Btrfs: do extent ... |
186 |
|
d278850ef btrfs: remove del... |
187 |
if (bytenr < entry->bytenr) |
56bec294d Btrfs: do extent ... |
188 |
n = n->rb_left; |
d278850ef btrfs: remove del... |
189 |
else if (bytenr > entry->bytenr) |
56bec294d Btrfs: do extent ... |
190 191 192 193 |
n = n->rb_right; else return entry; } |
d1270cd91 Btrfs: put back d... |
194 |
if (entry && return_bigger) { |
d278850ef btrfs: remove del... |
195 |
if (bytenr > entry->bytenr) { |
c46effa60 Btrfs: introduce ... |
196 |
n = rb_next(&entry->href_node); |
d1270cd91 Btrfs: put back d... |
197 198 |
if (!n) n = rb_first(root); |
c46effa60 Btrfs: introduce ... |
199 200 |
entry = rb_entry(n, struct btrfs_delayed_ref_head, href_node); |
6103fb43f Btrfs: remove unn... |
201 |
return entry; |
d1270cd91 Btrfs: put back d... |
202 203 204 |
} return entry; } |
56bec294d Btrfs: do extent ... |
205 206 |
return NULL; } |
c3e69d58e Btrfs: process th... |
207 208 |
int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans, struct btrfs_delayed_ref_head *head) |
56bec294d Btrfs: do extent ... |
209 |
{ |
c3e69d58e Btrfs: process th... |
210 211 212 213 214 215 |
struct btrfs_delayed_ref_root *delayed_refs; delayed_refs = &trans->transaction->delayed_refs; assert_spin_locked(&delayed_refs->lock); if (mutex_trylock(&head->mutex)) return 0; |
d278850ef btrfs: remove del... |
216 |
refcount_inc(&head->refs); |
c3e69d58e Btrfs: process th... |
217 218 219 220 |
spin_unlock(&delayed_refs->lock); mutex_lock(&head->mutex); spin_lock(&delayed_refs->lock); |
d278850ef btrfs: remove del... |
221 |
if (RB_EMPTY_NODE(&head->href_node)) { |
c3e69d58e Btrfs: process th... |
222 |
mutex_unlock(&head->mutex); |
d278850ef btrfs: remove del... |
223 |
btrfs_put_delayed_ref_head(head); |
c3e69d58e Btrfs: process th... |
224 225 |
return -EAGAIN; } |
d278850ef btrfs: remove del... |
226 |
btrfs_put_delayed_ref_head(head); |
c3e69d58e Btrfs: process th... |
227 228 |
return 0; } |
35a3621be Btrfs: get rid of... |
229 |
static inline void drop_delayed_ref(struct btrfs_trans_handle *trans, |
ae1e206b8 Btrfs: allow dela... |
230 |
struct btrfs_delayed_ref_root *delayed_refs, |
d7df2c796 Btrfs: attach del... |
231 |
struct btrfs_delayed_ref_head *head, |
ae1e206b8 Btrfs: allow dela... |
232 233 |
struct btrfs_delayed_ref_node *ref) { |
d278850ef btrfs: remove del... |
234 |
assert_spin_locked(&head->lock); |
0e0adbcfd btrfs: track refs... |
235 236 |
rb_erase(&ref->ref_node, &head->ref_tree); RB_CLEAR_NODE(&ref->ref_node); |
d278850ef btrfs: remove del... |
237 238 |
if (!list_empty(&ref->add_list)) list_del(&ref->add_list); |
ae1e206b8 Btrfs: allow dela... |
239 240 |
ref->in_tree = 0; btrfs_put_delayed_ref(ref); |
d7df2c796 Btrfs: attach del... |
241 |
atomic_dec(&delayed_refs->num_entries); |
ae1e206b8 Btrfs: allow dela... |
242 243 244 |
if (trans->delayed_ref_updates) trans->delayed_ref_updates--; } |
2c3cf7d5f Btrfs: fix regres... |
245 246 247 248 249 250 251 |
static bool merge_ref(struct btrfs_trans_handle *trans, struct btrfs_delayed_ref_root *delayed_refs, struct btrfs_delayed_ref_head *head, struct btrfs_delayed_ref_node *ref, u64 seq) { struct btrfs_delayed_ref_node *next; |
0e0adbcfd btrfs: track refs... |
252 |
struct rb_node *node = rb_next(&ref->ref_node); |
2c3cf7d5f Btrfs: fix regres... |
253 |
bool done = false; |
0e0adbcfd btrfs: track refs... |
254 |
while (!done && node) { |
2c3cf7d5f Btrfs: fix regres... |
255 |
int mod; |
2c3cf7d5f Btrfs: fix regres... |
256 |
|
0e0adbcfd btrfs: track refs... |
257 258 |
next = rb_entry(node, struct btrfs_delayed_ref_node, ref_node); node = rb_next(node); |
2c3cf7d5f Btrfs: fix regres... |
259 |
if (seq && next->seq >= seq) |
0e0adbcfd btrfs: track refs... |
260 |
break; |
1d148e593 btrfs: add a comp... |
261 |
if (comp_refs(ref, next, false)) |
0e0adbcfd btrfs: track refs... |
262 |
break; |
2c3cf7d5f Btrfs: fix regres... |
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
if (ref->action == next->action) { mod = next->ref_mod; } else { if (ref->ref_mod < next->ref_mod) { swap(ref, next); done = true; } mod = -next->ref_mod; } drop_delayed_ref(trans, delayed_refs, head, next); ref->ref_mod += mod; if (ref->ref_mod == 0) { drop_delayed_ref(trans, delayed_refs, head, ref); done = true; } else { /* * Can't have multiples of the same ref on a tree block. */ WARN_ON(ref->type == BTRFS_TREE_BLOCK_REF_KEY || ref->type == BTRFS_SHARED_BLOCK_REF_KEY); } |
2c3cf7d5f Btrfs: fix regres... |
286 287 288 289 290 291 292 293 294 295 296 |
} return done; } void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct btrfs_delayed_ref_root *delayed_refs, struct btrfs_delayed_ref_head *head) { struct btrfs_delayed_ref_node *ref; |
0e0adbcfd btrfs: track refs... |
297 |
struct rb_node *node; |
2c3cf7d5f Btrfs: fix regres... |
298 299 300 |
u64 seq = 0; assert_spin_locked(&head->lock); |
0e0adbcfd btrfs: track refs... |
301 |
if (RB_EMPTY_ROOT(&head->ref_tree)) |
2c3cf7d5f Btrfs: fix regres... |
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
return; /* We don't have too many refs to merge for data. */ if (head->is_data) return; spin_lock(&fs_info->tree_mod_seq_lock); if (!list_empty(&fs_info->tree_mod_seq_list)) { struct seq_list *elem; elem = list_first_entry(&fs_info->tree_mod_seq_list, struct seq_list, list); seq = elem->seq; } spin_unlock(&fs_info->tree_mod_seq_lock); |
0e0adbcfd btrfs: track refs... |
317 318 319 |
again: for (node = rb_first(&head->ref_tree); node; node = rb_next(node)) { ref = rb_entry(node, struct btrfs_delayed_ref_node, ref_node); |
2c3cf7d5f Btrfs: fix regres... |
320 |
if (seq && ref->seq >= seq) |
2c3cf7d5f Btrfs: fix regres... |
321 |
continue; |
0e0adbcfd btrfs: track refs... |
322 323 |
if (merge_ref(trans, delayed_refs, head, ref, seq)) goto again; |
2c3cf7d5f Btrfs: fix regres... |
324 325 |
} } |
097b8a7c9 Btrfs: join tree ... |
326 327 |
int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, struct btrfs_delayed_ref_root *delayed_refs, |
00f04b887 Btrfs: add sequen... |
328 329 330 |
u64 seq) { struct seq_list *elem; |
097b8a7c9 Btrfs: join tree ... |
331 332 333 334 335 336 337 |
int ret = 0; spin_lock(&fs_info->tree_mod_seq_lock); if (!list_empty(&fs_info->tree_mod_seq_list)) { elem = list_first_entry(&fs_info->tree_mod_seq_list, struct seq_list, list); if (seq >= elem->seq) { |
ab8d0fc48 btrfs: convert pr... |
338 339 340 341 342 |
btrfs_debug(fs_info, "holding back delayed_ref %#x.%x, lowest is %#x.%x (%p)", (u32)(seq >> 32), (u32)seq, (u32)(elem->seq >> 32), (u32)elem->seq, delayed_refs); |
097b8a7c9 Btrfs: join tree ... |
343 344 |
ret = 1; } |
00f04b887 Btrfs: add sequen... |
345 |
} |
097b8a7c9 Btrfs: join tree ... |
346 347 348 |
spin_unlock(&fs_info->tree_mod_seq_lock); return ret; |
00f04b887 Btrfs: add sequen... |
349 |
} |
d7df2c796 Btrfs: attach del... |
350 351 |
struct btrfs_delayed_ref_head * btrfs_select_ref_head(struct btrfs_trans_handle *trans) |
c3e69d58e Btrfs: process th... |
352 |
{ |
c3e69d58e Btrfs: process th... |
353 |
struct btrfs_delayed_ref_root *delayed_refs; |
d7df2c796 Btrfs: attach del... |
354 355 356 |
struct btrfs_delayed_ref_head *head; u64 start; bool loop = false; |
56bec294d Btrfs: do extent ... |
357 |
|
c3e69d58e Btrfs: process th... |
358 |
delayed_refs = &trans->transaction->delayed_refs; |
c46effa60 Btrfs: introduce ... |
359 |
|
c3e69d58e Btrfs: process th... |
360 |
again: |
d7df2c796 Btrfs: attach del... |
361 |
start = delayed_refs->run_delayed_start; |
85fdfdf61 Btrfs: cleanup de... |
362 |
head = find_ref_head(&delayed_refs->href_root, start, 1); |
d7df2c796 Btrfs: attach del... |
363 364 |
if (!head && !loop) { delayed_refs->run_delayed_start = 0; |
c3e69d58e Btrfs: process th... |
365 |
start = 0; |
d7df2c796 Btrfs: attach del... |
366 |
loop = true; |
85fdfdf61 Btrfs: cleanup de... |
367 |
head = find_ref_head(&delayed_refs->href_root, start, 1); |
d7df2c796 Btrfs: attach del... |
368 369 370 371 |
if (!head) return NULL; } else if (!head && loop) { return NULL; |
c3e69d58e Btrfs: process th... |
372 |
} |
56bec294d Btrfs: do extent ... |
373 |
|
d7df2c796 Btrfs: attach del... |
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
while (head->processing) { struct rb_node *node; node = rb_next(&head->href_node); if (!node) { if (loop) return NULL; delayed_refs->run_delayed_start = 0; start = 0; loop = true; goto again; } head = rb_entry(node, struct btrfs_delayed_ref_head, href_node); } |
093486c45 Btrfs: make delay... |
389 |
|
d7df2c796 Btrfs: attach del... |
390 391 392 |
head->processing = 1; WARN_ON(delayed_refs->num_heads_ready == 0); delayed_refs->num_heads_ready--; |
d278850ef btrfs: remove del... |
393 394 |
delayed_refs->run_delayed_start = head->bytenr + head->num_bytes; |
d7df2c796 Btrfs: attach del... |
395 |
return head; |
093486c45 Btrfs: make delay... |
396 |
} |
56bec294d Btrfs: do extent ... |
397 |
/* |
c6fc24549 btrfs: delayed-re... |
398 399 400 401 402 |
* Helper to insert the ref_node to the tail or merge with tail. * * Return 0 for insert. * Return >0 for merge. */ |
0e0adbcfd btrfs: track refs... |
403 404 405 406 |
static int insert_delayed_ref(struct btrfs_trans_handle *trans, struct btrfs_delayed_ref_root *root, struct btrfs_delayed_ref_head *href, struct btrfs_delayed_ref_node *ref) |
c6fc24549 btrfs: delayed-re... |
407 408 409 410 411 412 |
{ struct btrfs_delayed_ref_node *exist; int mod; int ret = 0; spin_lock(&href->lock); |
0e0adbcfd btrfs: track refs... |
413 414 415 |
exist = tree_insert(&href->ref_tree, ref); if (!exist) goto inserted; |
c6fc24549 btrfs: delayed-re... |
416 417 418 419 420 421 422 423 424 425 426 |
/* Now we are sure we can merge */ ret = 1; if (exist->action == ref->action) { mod = ref->ref_mod; } else { /* Need to change action */ if (exist->ref_mod < ref->ref_mod) { exist->action = ref->action; mod = -exist->ref_mod; exist->ref_mod = ref->ref_mod; |
1d57ee941 btrfs: improve de... |
427 428 429 430 431 432 433 434 435 |
if (ref->action == BTRFS_ADD_DELAYED_REF) list_add_tail(&exist->add_list, &href->ref_add_list); else if (ref->action == BTRFS_DROP_DELAYED_REF) { ASSERT(!list_empty(&exist->add_list)); list_del(&exist->add_list); } else { ASSERT(0); } |
c6fc24549 btrfs: delayed-re... |
436 437 438 439 440 441 442 443 444 445 |
} else mod = -ref->ref_mod; } exist->ref_mod += mod; /* remove existing tail if its ref_mod is zero */ if (exist->ref_mod == 0) drop_delayed_ref(trans, root, href, exist); spin_unlock(&href->lock); return ret; |
0e0adbcfd btrfs: track refs... |
446 |
inserted: |
1d57ee941 btrfs: improve de... |
447 448 |
if (ref->action == BTRFS_ADD_DELAYED_REF) list_add_tail(&ref->add_list, &href->ref_add_list); |
c6fc24549 btrfs: delayed-re... |
449 450 451 452 453 454 455 |
atomic_inc(&root->num_entries); trans->delayed_ref_updates++; spin_unlock(&href->lock); return ret; } /* |
56bec294d Btrfs: do extent ... |
456 457 458 459 |
* helper function to update the accounting in the head ref * existing and update must have the same bytenr */ static noinline void |
1262133b8 Btrfs: account fo... |
460 |
update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs, |
d278850ef btrfs: remove del... |
461 462 |
struct btrfs_delayed_ref_head *existing, struct btrfs_delayed_ref_head *update, |
7be07912b Btrfs: return old... |
463 |
int *old_ref_mod_ret) |
56bec294d Btrfs: do extent ... |
464 |
{ |
1262133b8 Btrfs: account fo... |
465 |
int old_ref_mod; |
56bec294d Btrfs: do extent ... |
466 |
|
d278850ef btrfs: remove del... |
467 |
BUG_ON(existing->is_data != update->is_data); |
56bec294d Btrfs: do extent ... |
468 |
|
d278850ef btrfs: remove del... |
469 470 |
spin_lock(&existing->lock); if (update->must_insert_reserved) { |
56bec294d Btrfs: do extent ... |
471 472 473 474 475 476 477 |
/* if the extent was freed and then * reallocated before the delayed ref * entries were processed, we can end up * with an existing head ref without * the must_insert_reserved flag set. * Set it again here */ |
d278850ef btrfs: remove del... |
478 |
existing->must_insert_reserved = update->must_insert_reserved; |
56bec294d Btrfs: do extent ... |
479 480 481 482 483 484 485 486 |
/* * update the num_bytes so we make sure the accounting * is done correctly */ existing->num_bytes = update->num_bytes; } |
d278850ef btrfs: remove del... |
487 488 489 |
if (update->extent_op) { if (!existing->extent_op) { existing->extent_op = update->extent_op; |
5d4f98a28 Btrfs: Mixed back... |
490 |
} else { |
d278850ef btrfs: remove del... |
491 492 493 494 495 |
if (update->extent_op->update_key) { memcpy(&existing->extent_op->key, &update->extent_op->key, sizeof(update->extent_op->key)); existing->extent_op->update_key = true; |
5d4f98a28 Btrfs: Mixed back... |
496 |
} |
d278850ef btrfs: remove del... |
497 498 499 500 |
if (update->extent_op->update_flags) { existing->extent_op->flags_to_set |= update->extent_op->flags_to_set; existing->extent_op->update_flags = true; |
5d4f98a28 Btrfs: Mixed back... |
501 |
} |
d278850ef btrfs: remove del... |
502 |
btrfs_free_delayed_extent_op(update->extent_op); |
5d4f98a28 Btrfs: Mixed back... |
503 504 |
} } |
56bec294d Btrfs: do extent ... |
505 |
/* |
d7df2c796 Btrfs: attach del... |
506 507 508 |
* update the reference mod on the head to reflect this new operation, * only need the lock for this case cause we could be processing it * currently, for refs we just added we know we're a-ok. |
56bec294d Btrfs: do extent ... |
509 |
*/ |
d278850ef btrfs: remove del... |
510 |
old_ref_mod = existing->total_ref_mod; |
7be07912b Btrfs: return old... |
511 512 |
if (old_ref_mod_ret) *old_ref_mod_ret = old_ref_mod; |
56bec294d Btrfs: do extent ... |
513 |
existing->ref_mod += update->ref_mod; |
d278850ef btrfs: remove del... |
514 |
existing->total_ref_mod += update->ref_mod; |
1262133b8 Btrfs: account fo... |
515 516 517 518 519 |
/* * If we are going to from a positive ref mod to a negative or vice * versa we need to make sure to adjust pending_csums accordingly. */ |
d278850ef btrfs: remove del... |
520 521 |
if (existing->is_data) { if (existing->total_ref_mod >= 0 && old_ref_mod < 0) |
1262133b8 Btrfs: account fo... |
522 |
delayed_refs->pending_csums -= existing->num_bytes; |
d278850ef btrfs: remove del... |
523 |
if (existing->total_ref_mod < 0 && old_ref_mod >= 0) |
1262133b8 Btrfs: account fo... |
524 525 |
delayed_refs->pending_csums += existing->num_bytes; } |
d278850ef btrfs: remove del... |
526 |
spin_unlock(&existing->lock); |
56bec294d Btrfs: do extent ... |
527 528 529 |
} /* |
5d4f98a28 Btrfs: Mixed back... |
530 |
* helper function to actually insert a head node into the rbtree. |
56bec294d Btrfs: do extent ... |
531 |
* this does all the dirty work in terms of maintaining the correct |
5d4f98a28 Btrfs: Mixed back... |
532 |
* overall modification count. |
56bec294d Btrfs: do extent ... |
533 |
*/ |
d7df2c796 Btrfs: attach del... |
534 535 536 |
static noinline struct btrfs_delayed_ref_head * add_delayed_ref_head(struct btrfs_fs_info *fs_info, struct btrfs_trans_handle *trans, |
d278850ef btrfs: remove del... |
537 |
struct btrfs_delayed_ref_head *head_ref, |
3368d001b btrfs: qgroup: Re... |
538 |
struct btrfs_qgroup_extent_record *qrecord, |
5846a3c26 btrfs: qgroup: Fi... |
539 |
u64 bytenr, u64 num_bytes, u64 ref_root, u64 reserved, |
7be07912b Btrfs: return old... |
540 541 |
int action, int is_data, int *qrecord_inserted_ret, int *old_ref_mod, int *new_ref_mod) |
56bec294d Btrfs: do extent ... |
542 |
{ |
d7df2c796 Btrfs: attach del... |
543 |
struct btrfs_delayed_ref_head *existing; |
56bec294d Btrfs: do extent ... |
544 545 546 |
struct btrfs_delayed_ref_root *delayed_refs; int count_mod = 1; int must_insert_reserved = 0; |
fb235dc06 btrfs: qgroup: Mo... |
547 |
int qrecord_inserted = 0; |
56bec294d Btrfs: do extent ... |
548 |
|
5846a3c26 btrfs: qgroup: Fi... |
549 550 |
/* If reserved is provided, it must be a data extent. */ BUG_ON(!is_data && reserved); |
56bec294d Btrfs: do extent ... |
551 552 553 554 |
/* * the head node stores the sum of all the mods, so dropping a ref * should drop the sum in the head node by one. */ |
5d4f98a28 Btrfs: Mixed back... |
555 556 557 558 |
if (action == BTRFS_UPDATE_DELAYED_HEAD) count_mod = 0; else if (action == BTRFS_DROP_DELAYED_REF) count_mod = -1; |
56bec294d Btrfs: do extent ... |
559 560 561 562 563 564 565 566 567 568 569 570 |
/* * BTRFS_ADD_DELAYED_EXTENT means that we need to update * the reserved accounting when the extent is finally added, or * if a later modification deletes the delayed ref without ever * inserting the extent into the extent allocation tree. * ref->must_insert_reserved is the flag used to record * that accounting mods are required. * * Once we record must_insert_reserved, switch the action to * BTRFS_ADD_DELAYED_REF because other special casing is not required. */ |
5d4f98a28 Btrfs: Mixed back... |
571 |
if (action == BTRFS_ADD_DELAYED_EXTENT) |
56bec294d Btrfs: do extent ... |
572 |
must_insert_reserved = 1; |
5d4f98a28 Btrfs: Mixed back... |
573 |
else |
56bec294d Btrfs: do extent ... |
574 |
must_insert_reserved = 0; |
56bec294d Btrfs: do extent ... |
575 576 |
delayed_refs = &trans->transaction->delayed_refs; |
d278850ef btrfs: remove del... |
577 578 579 580 |
refcount_set(&head_ref->refs, 1); head_ref->bytenr = bytenr; head_ref->num_bytes = num_bytes; head_ref->ref_mod = count_mod; |
5d4f98a28 Btrfs: Mixed back... |
581 582 |
head_ref->must_insert_reserved = must_insert_reserved; head_ref->is_data = is_data; |
0e0adbcfd btrfs: track refs... |
583 |
head_ref->ref_tree = RB_ROOT; |
1d57ee941 btrfs: improve de... |
584 |
INIT_LIST_HEAD(&head_ref->ref_add_list); |
d278850ef btrfs: remove del... |
585 |
RB_CLEAR_NODE(&head_ref->href_node); |
d7df2c796 Btrfs: attach del... |
586 |
head_ref->processing = 0; |
1262133b8 Btrfs: account fo... |
587 |
head_ref->total_ref_mod = count_mod; |
f64d5ca86 btrfs: delayed_re... |
588 589 |
head_ref->qgroup_reserved = 0; head_ref->qgroup_ref_root = 0; |
d278850ef btrfs: remove del... |
590 591 |
spin_lock_init(&head_ref->lock); mutex_init(&head_ref->mutex); |
5d4f98a28 Btrfs: Mixed back... |
592 |
|
3368d001b btrfs: qgroup: Re... |
593 594 |
/* Record qgroup extent info if provided */ if (qrecord) { |
5846a3c26 btrfs: qgroup: Fi... |
595 596 597 598 |
if (ref_root && reserved) { head_ref->qgroup_ref_root = ref_root; head_ref->qgroup_reserved = reserved; } |
3368d001b btrfs: qgroup: Re... |
599 600 601 |
qrecord->bytenr = bytenr; qrecord->num_bytes = num_bytes; qrecord->old_roots = NULL; |
50b3e040b btrfs: qgroup: Re... |
602 |
if(btrfs_qgroup_trace_extent_nolock(fs_info, |
cb93b52cc btrfs: qgroup: Re... |
603 |
delayed_refs, qrecord)) |
3368d001b btrfs: qgroup: Re... |
604 |
kfree(qrecord); |
fb235dc06 btrfs: qgroup: Mo... |
605 606 |
else qrecord_inserted = 1; |
3368d001b btrfs: qgroup: Re... |
607 |
} |
d278850ef btrfs: remove del... |
608 |
trace_add_delayed_ref_head(fs_info, head_ref, action); |
1abe9b8a1 Btrfs: add initia... |
609 |
|
d7df2c796 Btrfs: attach del... |
610 611 |
existing = htree_insert(&delayed_refs->href_root, &head_ref->href_node); |
5d4f98a28 Btrfs: Mixed back... |
612 |
if (existing) { |
5846a3c26 btrfs: qgroup: Fi... |
613 614 |
WARN_ON(ref_root && reserved && existing->qgroup_ref_root && existing->qgroup_reserved); |
d278850ef btrfs: remove del... |
615 |
update_existing_head_ref(delayed_refs, existing, head_ref, |
7be07912b Btrfs: return old... |
616 |
old_ref_mod); |
5d4f98a28 Btrfs: Mixed back... |
617 618 619 620 |
/* * we've updated the existing ref, free the newly * allocated ref */ |
78a6184a3 Btrfs: use slabs ... |
621 |
kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref); |
d7df2c796 Btrfs: attach del... |
622 |
head_ref = existing; |
5d4f98a28 Btrfs: Mixed back... |
623 |
} else { |
7be07912b Btrfs: return old... |
624 625 |
if (old_ref_mod) *old_ref_mod = 0; |
1262133b8 Btrfs: account fo... |
626 627 |
if (is_data && count_mod < 0) delayed_refs->pending_csums += num_bytes; |
5d4f98a28 Btrfs: Mixed back... |
628 629 |
delayed_refs->num_heads++; delayed_refs->num_heads_ready++; |
d7df2c796 Btrfs: attach del... |
630 |
atomic_inc(&delayed_refs->num_entries); |
5d4f98a28 Btrfs: Mixed back... |
631 632 |
trans->delayed_ref_updates++; } |
fb235dc06 btrfs: qgroup: Mo... |
633 634 |
if (qrecord_inserted_ret) *qrecord_inserted_ret = qrecord_inserted; |
7be07912b Btrfs: return old... |
635 636 |
if (new_ref_mod) *new_ref_mod = head_ref->total_ref_mod; |
d7df2c796 Btrfs: attach del... |
637 |
return head_ref; |
5d4f98a28 Btrfs: Mixed back... |
638 639 640 641 642 |
} /* * helper to insert a delayed tree ref into the rbtree. */ |
d7df2c796 Btrfs: attach del... |
643 644 645 646 647 648 |
static noinline void add_delayed_tree_ref(struct btrfs_fs_info *fs_info, struct btrfs_trans_handle *trans, struct btrfs_delayed_ref_head *head_ref, struct btrfs_delayed_ref_node *ref, u64 bytenr, u64 num_bytes, u64 parent, u64 ref_root, int level, |
b06c4bf5c Btrfs: fix regres... |
649 |
int action) |
5d4f98a28 Btrfs: Mixed back... |
650 |
{ |
5d4f98a28 Btrfs: Mixed back... |
651 652 |
struct btrfs_delayed_tree_ref *full_ref; struct btrfs_delayed_ref_root *delayed_refs; |
00f04b887 Btrfs: add sequen... |
653 |
u64 seq = 0; |
c6fc24549 btrfs: delayed-re... |
654 |
int ret; |
5d4f98a28 Btrfs: Mixed back... |
655 656 657 |
if (action == BTRFS_ADD_DELAYED_EXTENT) action = BTRFS_ADD_DELAYED_REF; |
fcebe4562 Btrfs: rework qgr... |
658 659 |
if (is_fstree(ref_root)) seq = atomic64_read(&fs_info->tree_mod_seq); |
5d4f98a28 Btrfs: Mixed back... |
660 661 662 |
delayed_refs = &trans->transaction->delayed_refs; /* first set the basic ref node struct up */ |
6df8cdf5b btrfs: convert bt... |
663 |
refcount_set(&ref->refs, 1); |
5d4f98a28 Btrfs: Mixed back... |
664 |
ref->bytenr = bytenr; |
56bec294d Btrfs: do extent ... |
665 |
ref->num_bytes = num_bytes; |
5d4f98a28 Btrfs: Mixed back... |
666 667 668 669 |
ref->ref_mod = 1; ref->action = action; ref->is_head = 0; ref->in_tree = 1; |
00f04b887 Btrfs: add sequen... |
670 |
ref->seq = seq; |
0e0adbcfd btrfs: track refs... |
671 |
RB_CLEAR_NODE(&ref->ref_node); |
1d57ee941 btrfs: improve de... |
672 |
INIT_LIST_HEAD(&ref->add_list); |
00f04b887 Btrfs: add sequen... |
673 |
|
5d4f98a28 Btrfs: Mixed back... |
674 |
full_ref = btrfs_delayed_node_to_tree_ref(ref); |
eebe063b7 Btrfs: always sav... |
675 676 677 |
full_ref->parent = parent; full_ref->root = ref_root; if (parent) |
5d4f98a28 Btrfs: Mixed back... |
678 |
ref->type = BTRFS_SHARED_BLOCK_REF_KEY; |
eebe063b7 Btrfs: always sav... |
679 |
else |
5d4f98a28 Btrfs: Mixed back... |
680 |
ref->type = BTRFS_TREE_BLOCK_REF_KEY; |
5d4f98a28 Btrfs: Mixed back... |
681 |
full_ref->level = level; |
56bec294d Btrfs: do extent ... |
682 |
|
bc074524e btrfs: prefix fsi... |
683 |
trace_add_delayed_tree_ref(fs_info, ref, full_ref, action); |
1abe9b8a1 Btrfs: add initia... |
684 |
|
0e0adbcfd btrfs: track refs... |
685 |
ret = insert_delayed_ref(trans, delayed_refs, head_ref, ref); |
c6fc24549 btrfs: delayed-re... |
686 687 688 689 690 691 |
/* * XXX: memory should be freed at the same level allocated. * But bad practice is anywhere... Follow it now. Need cleanup. */ if (ret > 0) |
78a6184a3 Btrfs: use slabs ... |
692 |
kmem_cache_free(btrfs_delayed_tree_ref_cachep, full_ref); |
5d4f98a28 Btrfs: Mixed back... |
693 694 695 696 697 |
} /* * helper to insert a delayed data ref into the rbtree. */ |
d7df2c796 Btrfs: attach del... |
698 699 700 701 702 703 |
static noinline void add_delayed_data_ref(struct btrfs_fs_info *fs_info, struct btrfs_trans_handle *trans, struct btrfs_delayed_ref_head *head_ref, struct btrfs_delayed_ref_node *ref, u64 bytenr, u64 num_bytes, u64 parent, u64 ref_root, u64 owner, |
b06c4bf5c Btrfs: fix regres... |
704 |
u64 offset, int action) |
5d4f98a28 Btrfs: Mixed back... |
705 |
{ |
5d4f98a28 Btrfs: Mixed back... |
706 707 |
struct btrfs_delayed_data_ref *full_ref; struct btrfs_delayed_ref_root *delayed_refs; |
00f04b887 Btrfs: add sequen... |
708 |
u64 seq = 0; |
c6fc24549 btrfs: delayed-re... |
709 |
int ret; |
5d4f98a28 Btrfs: Mixed back... |
710 711 712 713 714 |
if (action == BTRFS_ADD_DELAYED_EXTENT) action = BTRFS_ADD_DELAYED_REF; delayed_refs = &trans->transaction->delayed_refs; |
fcebe4562 Btrfs: rework qgr... |
715 716 |
if (is_fstree(ref_root)) seq = atomic64_read(&fs_info->tree_mod_seq); |
5d4f98a28 Btrfs: Mixed back... |
717 |
/* first set the basic ref node struct up */ |
6df8cdf5b btrfs: convert bt... |
718 |
refcount_set(&ref->refs, 1); |
5d4f98a28 Btrfs: Mixed back... |
719 720 721 722 723 724 |
ref->bytenr = bytenr; ref->num_bytes = num_bytes; ref->ref_mod = 1; ref->action = action; ref->is_head = 0; ref->in_tree = 1; |
00f04b887 Btrfs: add sequen... |
725 |
ref->seq = seq; |
0e0adbcfd btrfs: track refs... |
726 |
RB_CLEAR_NODE(&ref->ref_node); |
1d57ee941 btrfs: improve de... |
727 |
INIT_LIST_HEAD(&ref->add_list); |
00f04b887 Btrfs: add sequen... |
728 |
|
5d4f98a28 Btrfs: Mixed back... |
729 |
full_ref = btrfs_delayed_node_to_data_ref(ref); |
eebe063b7 Btrfs: always sav... |
730 731 732 |
full_ref->parent = parent; full_ref->root = ref_root; if (parent) |
5d4f98a28 Btrfs: Mixed back... |
733 |
ref->type = BTRFS_SHARED_DATA_REF_KEY; |
eebe063b7 Btrfs: always sav... |
734 |
else |
5d4f98a28 Btrfs: Mixed back... |
735 |
ref->type = BTRFS_EXTENT_DATA_REF_KEY; |
66d7e7f09 Btrfs: mark delay... |
736 |
|
5d4f98a28 Btrfs: Mixed back... |
737 738 |
full_ref->objectid = owner; full_ref->offset = offset; |
56bec294d Btrfs: do extent ... |
739 |
|
bc074524e btrfs: prefix fsi... |
740 |
trace_add_delayed_data_ref(fs_info, ref, full_ref, action); |
1abe9b8a1 Btrfs: add initia... |
741 |
|
0e0adbcfd btrfs: track refs... |
742 |
ret = insert_delayed_ref(trans, delayed_refs, head_ref, ref); |
c6fc24549 btrfs: delayed-re... |
743 |
if (ret > 0) |
78a6184a3 Btrfs: use slabs ... |
744 |
kmem_cache_free(btrfs_delayed_data_ref_cachep, full_ref); |
56bec294d Btrfs: do extent ... |
745 746 747 |
} /* |
5d4f98a28 Btrfs: Mixed back... |
748 |
* add a delayed tree ref. This does all of the accounting required |
56bec294d Btrfs: do extent ... |
749 750 751 |
* to make sure the delayed ref is eventually processed before this * transaction commits. */ |
66d7e7f09 Btrfs: mark delay... |
752 753 |
int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info, struct btrfs_trans_handle *trans, |
5d4f98a28 Btrfs: Mixed back... |
754 755 |
u64 bytenr, u64 num_bytes, u64 parent, u64 ref_root, int level, int action, |
7be07912b Btrfs: return old... |
756 757 |
struct btrfs_delayed_extent_op *extent_op, int *old_ref_mod, int *new_ref_mod) |
56bec294d Btrfs: do extent ... |
758 |
{ |
5d4f98a28 Btrfs: Mixed back... |
759 |
struct btrfs_delayed_tree_ref *ref; |
56bec294d Btrfs: do extent ... |
760 761 |
struct btrfs_delayed_ref_head *head_ref; struct btrfs_delayed_ref_root *delayed_refs; |
3368d001b btrfs: qgroup: Re... |
762 |
struct btrfs_qgroup_extent_record *record = NULL; |
fb235dc06 btrfs: qgroup: Mo... |
763 |
int qrecord_inserted; |
56bec294d Btrfs: do extent ... |
764 |
|
5d4f98a28 Btrfs: Mixed back... |
765 |
BUG_ON(extent_op && extent_op->is_data); |
78a6184a3 Btrfs: use slabs ... |
766 |
ref = kmem_cache_alloc(btrfs_delayed_tree_ref_cachep, GFP_NOFS); |
56bec294d Btrfs: do extent ... |
767 768 |
if (!ref) return -ENOMEM; |
78a6184a3 Btrfs: use slabs ... |
769 |
head_ref = kmem_cache_alloc(btrfs_delayed_ref_head_cachep, GFP_NOFS); |
5a5003df9 btrfs: delayed-re... |
770 771 |
if (!head_ref) goto free_ref; |
5d4f98a28 Btrfs: Mixed back... |
772 |
|
afcdd129e Btrfs: add a flag... |
773 774 |
if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) && is_fstree(ref_root)) { |
3368d001b btrfs: qgroup: Re... |
775 |
record = kmalloc(sizeof(*record), GFP_NOFS); |
5a5003df9 btrfs: delayed-re... |
776 777 |
if (!record) goto free_head_ref; |
3368d001b btrfs: qgroup: Re... |
778 |
} |
5d4f98a28 Btrfs: Mixed back... |
779 780 781 782 |
head_ref->extent_op = extent_op; delayed_refs = &trans->transaction->delayed_refs; spin_lock(&delayed_refs->lock); |
56bec294d Btrfs: do extent ... |
783 |
/* |
5d4f98a28 Btrfs: Mixed back... |
784 785 |
* insert both the head node and the new ref without dropping * the spin lock |
56bec294d Btrfs: do extent ... |
786 |
*/ |
d278850ef btrfs: remove del... |
787 |
head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record, |
fb235dc06 btrfs: qgroup: Mo... |
788 |
bytenr, num_bytes, 0, 0, action, 0, |
7be07912b Btrfs: return old... |
789 790 |
&qrecord_inserted, old_ref_mod, new_ref_mod); |
5d4f98a28 Btrfs: Mixed back... |
791 |
|
d7df2c796 Btrfs: attach del... |
792 |
add_delayed_tree_ref(fs_info, trans, head_ref, &ref->node, bytenr, |
b06c4bf5c Btrfs: fix regres... |
793 |
num_bytes, parent, ref_root, level, action); |
5d4f98a28 Btrfs: Mixed back... |
794 |
spin_unlock(&delayed_refs->lock); |
95a06077f Btrfs: use delaye... |
795 |
|
fb235dc06 btrfs: qgroup: Mo... |
796 797 |
if (qrecord_inserted) return btrfs_qgroup_trace_extent_post(fs_info, record); |
5d4f98a28 Btrfs: Mixed back... |
798 |
return 0; |
5a5003df9 btrfs: delayed-re... |
799 800 801 802 803 804 805 |
free_head_ref: kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref); free_ref: kmem_cache_free(btrfs_delayed_tree_ref_cachep, ref); return -ENOMEM; |
5d4f98a28 Btrfs: Mixed back... |
806 807 808 809 810 |
} /* * add a delayed data ref. it's similar to btrfs_add_delayed_tree_ref. */ |
66d7e7f09 Btrfs: mark delay... |
811 812 |
int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info, struct btrfs_trans_handle *trans, |
5d4f98a28 Btrfs: Mixed back... |
813 814 |
u64 bytenr, u64 num_bytes, u64 parent, u64 ref_root, |
7be07912b Btrfs: return old... |
815 816 |
u64 owner, u64 offset, u64 reserved, int action, int *old_ref_mod, int *new_ref_mod) |
5d4f98a28 Btrfs: Mixed back... |
817 818 819 820 |
{ struct btrfs_delayed_data_ref *ref; struct btrfs_delayed_ref_head *head_ref; struct btrfs_delayed_ref_root *delayed_refs; |
3368d001b btrfs: qgroup: Re... |
821 |
struct btrfs_qgroup_extent_record *record = NULL; |
fb235dc06 btrfs: qgroup: Mo... |
822 |
int qrecord_inserted; |
5d4f98a28 Btrfs: Mixed back... |
823 |
|
78a6184a3 Btrfs: use slabs ... |
824 |
ref = kmem_cache_alloc(btrfs_delayed_data_ref_cachep, GFP_NOFS); |
5d4f98a28 Btrfs: Mixed back... |
825 826 |
if (!ref) return -ENOMEM; |
56bec294d Btrfs: do extent ... |
827 |
|
78a6184a3 Btrfs: use slabs ... |
828 |
head_ref = kmem_cache_alloc(btrfs_delayed_ref_head_cachep, GFP_NOFS); |
56bec294d Btrfs: do extent ... |
829 |
if (!head_ref) { |
78a6184a3 Btrfs: use slabs ... |
830 |
kmem_cache_free(btrfs_delayed_data_ref_cachep, ref); |
56bec294d Btrfs: do extent ... |
831 832 |
return -ENOMEM; } |
5d4f98a28 Btrfs: Mixed back... |
833 |
|
afcdd129e Btrfs: add a flag... |
834 835 |
if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) && is_fstree(ref_root)) { |
3368d001b btrfs: qgroup: Re... |
836 837 838 839 840 841 842 843 |
record = kmalloc(sizeof(*record), GFP_NOFS); if (!record) { kmem_cache_free(btrfs_delayed_data_ref_cachep, ref); kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref); return -ENOMEM; } } |
fef394f75 btrfs: drop unuse... |
844 |
head_ref->extent_op = NULL; |
5d4f98a28 Btrfs: Mixed back... |
845 |
|
56bec294d Btrfs: do extent ... |
846 847 848 849 850 851 852 |
delayed_refs = &trans->transaction->delayed_refs; spin_lock(&delayed_refs->lock); /* * insert both the head node and the new ref without dropping * the spin lock */ |
d278850ef btrfs: remove del... |
853 |
head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record, |
5846a3c26 btrfs: qgroup: Fi... |
854 |
bytenr, num_bytes, ref_root, reserved, |
7be07912b Btrfs: return old... |
855 856 |
action, 1, &qrecord_inserted, old_ref_mod, new_ref_mod); |
56bec294d Btrfs: do extent ... |
857 |
|
d7df2c796 Btrfs: attach del... |
858 |
add_delayed_data_ref(fs_info, trans, head_ref, &ref->node, bytenr, |
66d7e7f09 Btrfs: mark delay... |
859 |
num_bytes, parent, ref_root, owner, offset, |
b06c4bf5c Btrfs: fix regres... |
860 |
action); |
5d4f98a28 Btrfs: Mixed back... |
861 |
spin_unlock(&delayed_refs->lock); |
95a06077f Btrfs: use delaye... |
862 |
|
fb235dc06 btrfs: qgroup: Mo... |
863 864 |
if (qrecord_inserted) return btrfs_qgroup_trace_extent_post(fs_info, record); |
5d4f98a28 Btrfs: Mixed back... |
865 866 |
return 0; } |
66d7e7f09 Btrfs: mark delay... |
867 868 |
int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info, struct btrfs_trans_handle *trans, |
5d4f98a28 Btrfs: Mixed back... |
869 870 871 872 873 |
u64 bytenr, u64 num_bytes, struct btrfs_delayed_extent_op *extent_op) { struct btrfs_delayed_ref_head *head_ref; struct btrfs_delayed_ref_root *delayed_refs; |
5d4f98a28 Btrfs: Mixed back... |
874 |
|
78a6184a3 Btrfs: use slabs ... |
875 |
head_ref = kmem_cache_alloc(btrfs_delayed_ref_head_cachep, GFP_NOFS); |
5d4f98a28 Btrfs: Mixed back... |
876 877 878 879 880 881 882 |
if (!head_ref) return -ENOMEM; head_ref->extent_op = extent_op; delayed_refs = &trans->transaction->delayed_refs; spin_lock(&delayed_refs->lock); |
d278850ef btrfs: remove del... |
883 |
add_delayed_ref_head(fs_info, trans, head_ref, NULL, bytenr, |
5846a3c26 btrfs: qgroup: Fi... |
884 |
num_bytes, 0, 0, BTRFS_UPDATE_DELAYED_HEAD, |
7be07912b Btrfs: return old... |
885 |
extent_op->is_data, NULL, NULL, NULL); |
5d4f98a28 Btrfs: Mixed back... |
886 |
|
56bec294d Btrfs: do extent ... |
887 888 889 890 891 |
spin_unlock(&delayed_refs->lock); return 0; } /* |
1887be66d Btrfs: try to cle... |
892 893 894 895 896 |
* this does a simple search for the head node for a given extent. * It must be called with the delayed ref spinlock held, and it returns * the head node if any where found, or NULL if not. */ struct btrfs_delayed_ref_head * |
f72ad18e9 Btrfs: pass delay... |
897 |
btrfs_find_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs, u64 bytenr) |
1887be66d Btrfs: try to cle... |
898 |
{ |
85fdfdf61 Btrfs: cleanup de... |
899 |
return find_ref_head(&delayed_refs->href_root, bytenr, 0); |
1887be66d Btrfs: try to cle... |
900 |
} |
78a6184a3 Btrfs: use slabs ... |
901 902 903 |
void btrfs_delayed_ref_exit(void) { |
5598e9005 btrfs: drop null ... |
904 905 906 907 |
kmem_cache_destroy(btrfs_delayed_ref_head_cachep); kmem_cache_destroy(btrfs_delayed_tree_ref_cachep); kmem_cache_destroy(btrfs_delayed_data_ref_cachep); kmem_cache_destroy(btrfs_delayed_extent_op_cachep); |
78a6184a3 Btrfs: use slabs ... |
908 909 910 911 912 913 914 |
} int btrfs_delayed_ref_init(void) { btrfs_delayed_ref_head_cachep = kmem_cache_create( "btrfs_delayed_ref_head", sizeof(struct btrfs_delayed_ref_head), 0, |
fba4b6977 btrfs: Fix slab a... |
915 |
SLAB_MEM_SPREAD, NULL); |
78a6184a3 Btrfs: use slabs ... |
916 917 918 919 920 921 |
if (!btrfs_delayed_ref_head_cachep) goto fail; btrfs_delayed_tree_ref_cachep = kmem_cache_create( "btrfs_delayed_tree_ref", sizeof(struct btrfs_delayed_tree_ref), 0, |
fba4b6977 btrfs: Fix slab a... |
922 |
SLAB_MEM_SPREAD, NULL); |
78a6184a3 Btrfs: use slabs ... |
923 924 925 926 927 928 |
if (!btrfs_delayed_tree_ref_cachep) goto fail; btrfs_delayed_data_ref_cachep = kmem_cache_create( "btrfs_delayed_data_ref", sizeof(struct btrfs_delayed_data_ref), 0, |
fba4b6977 btrfs: Fix slab a... |
929 |
SLAB_MEM_SPREAD, NULL); |
78a6184a3 Btrfs: use slabs ... |
930 931 932 933 934 935 |
if (!btrfs_delayed_data_ref_cachep) goto fail; btrfs_delayed_extent_op_cachep = kmem_cache_create( "btrfs_delayed_extent_op", sizeof(struct btrfs_delayed_extent_op), 0, |
fba4b6977 btrfs: Fix slab a... |
936 |
SLAB_MEM_SPREAD, NULL); |
78a6184a3 Btrfs: use slabs ... |
937 938 939 940 941 942 943 944 |
if (!btrfs_delayed_extent_op_cachep) goto fail; return 0; fail: btrfs_delayed_ref_exit(); return -ENOMEM; } |