diff options
Diffstat (limited to 'fs/btrfs/delayed-ref.c')
| -rw-r--r-- | fs/btrfs/delayed-ref.c | 102 |
1 files changed, 1 insertions, 101 deletions
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index 84e6781413b1..e807b143b857 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
| 20 | #include <linux/slab.h> | ||
| 20 | #include <linux/sort.h> | 21 | #include <linux/sort.h> |
| 21 | #include "ctree.h" | 22 | #include "ctree.h" |
| 22 | #include "delayed-ref.h" | 23 | #include "delayed-ref.h" |
| @@ -318,107 +319,6 @@ out: | |||
| 318 | } | 319 | } |
| 319 | 320 | ||
| 320 | /* | 321 | /* |
| 321 | * helper function to lookup reference count and flags of extent. | ||
| 322 | * | ||
| 323 | * the head node for delayed ref is used to store the sum of all the | ||
| 324 | * reference count modifications queued up in the rbtree. the head | ||
| 325 | * node may also store the extent flags to set. This way you can check | ||
| 326 | * to see what the reference count and extent flags would be if all of | ||
| 327 | * the delayed refs are not processed. | ||
| 328 | */ | ||
| 329 | int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, | ||
| 330 | struct btrfs_root *root, u64 bytenr, | ||
| 331 | u64 num_bytes, u64 *refs, u64 *flags) | ||
| 332 | { | ||
| 333 | struct btrfs_delayed_ref_node *ref; | ||
| 334 | struct btrfs_delayed_ref_head *head; | ||
| 335 | struct btrfs_delayed_ref_root *delayed_refs; | ||
| 336 | struct btrfs_path *path; | ||
| 337 | struct btrfs_extent_item *ei; | ||
| 338 | struct extent_buffer *leaf; | ||
| 339 | struct btrfs_key key; | ||
| 340 | u32 item_size; | ||
| 341 | u64 num_refs; | ||
| 342 | u64 extent_flags; | ||
| 343 | int ret; | ||
| 344 | |||
| 345 | path = btrfs_alloc_path(); | ||
| 346 | if (!path) | ||
| 347 | return -ENOMEM; | ||
| 348 | |||
| 349 | key.objectid = bytenr; | ||
| 350 | key.type = BTRFS_EXTENT_ITEM_KEY; | ||
| 351 | key.offset = num_bytes; | ||
| 352 | delayed_refs = &trans->transaction->delayed_refs; | ||
| 353 | again: | ||
| 354 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, | ||
| 355 | &key, path, 0, 0); | ||
| 356 | if (ret < 0) | ||
| 357 | goto out; | ||
| 358 | |||
| 359 | if (ret == 0) { | ||
| 360 | leaf = path->nodes[0]; | ||
| 361 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); | ||
| 362 | if (item_size >= sizeof(*ei)) { | ||
| 363 | ei = btrfs_item_ptr(leaf, path->slots[0], | ||
| 364 | struct btrfs_extent_item); | ||
| 365 | num_refs = btrfs_extent_refs(leaf, ei); | ||
| 366 | extent_flags = btrfs_extent_flags(leaf, ei); | ||
| 367 | } else { | ||
| 368 | #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 | ||
| 369 | struct btrfs_extent_item_v0 *ei0; | ||
| 370 | BUG_ON(item_size != sizeof(*ei0)); | ||
| 371 | ei0 = btrfs_item_ptr(leaf, path->slots[0], | ||
| 372 | struct btrfs_extent_item_v0); | ||
| 373 | num_refs = btrfs_extent_refs_v0(leaf, ei0); | ||
| 374 | /* FIXME: this isn't correct for data */ | ||
| 375 | extent_flags = BTRFS_BLOCK_FLAG_FULL_BACKREF; | ||
| 376 | #else | ||
| 377 | BUG(); | ||
| 378 | #endif | ||
| 379 | } | ||
| 380 | BUG_ON(num_refs == 0); | ||
| 381 | } else { | ||
| 382 | num_refs = 0; | ||
| 383 | extent_flags = 0; | ||
| 384 | ret = 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | spin_lock(&delayed_refs->lock); | ||
| 388 | ref = find_ref_head(&delayed_refs->root, bytenr, NULL); | ||
| 389 | if (ref) { | ||
| 390 | head = btrfs_delayed_node_to_head(ref); | ||
| 391 | if (!mutex_trylock(&head->mutex)) { | ||
| 392 | atomic_inc(&ref->refs); | ||
| 393 | spin_unlock(&delayed_refs->lock); | ||
| 394 | |||
| 395 | btrfs_release_path(root->fs_info->extent_root, path); | ||
| 396 | |||
| 397 | mutex_lock(&head->mutex); | ||
| 398 | mutex_unlock(&head->mutex); | ||
| 399 | btrfs_put_delayed_ref(ref); | ||
| 400 | goto again; | ||
| 401 | } | ||
| 402 | if (head->extent_op && head->extent_op->update_flags) | ||
| 403 | extent_flags |= head->extent_op->flags_to_set; | ||
| 404 | else | ||
| 405 | BUG_ON(num_refs == 0); | ||
| 406 | |||
| 407 | num_refs += ref->ref_mod; | ||
| 408 | mutex_unlock(&head->mutex); | ||
| 409 | } | ||
| 410 | WARN_ON(num_refs == 0); | ||
| 411 | if (refs) | ||
| 412 | *refs = num_refs; | ||
| 413 | if (flags) | ||
| 414 | *flags = extent_flags; | ||
| 415 | out: | ||
| 416 | spin_unlock(&delayed_refs->lock); | ||
| 417 | btrfs_free_path(path); | ||
| 418 | return ret; | ||
| 419 | } | ||
| 420 | |||
| 421 | /* | ||
| 422 | * helper function to update an extent delayed ref in the | 322 | * helper function to update an extent delayed ref in the |
| 423 | * rbtree. existing and update must both have the same | 323 | * rbtree. existing and update must both have the same |
| 424 | * bytenr and parent | 324 | * bytenr and parent |
