diff options
author | Chandra Seetharaman <sekharan@us.ibm.com> | 2013-10-07 11:45:25 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-11-11 21:59:11 -0500 |
commit | 452c75c3d2187089f6e846710e6ea7883bf30f8a (patch) | |
tree | 0747512f55c254c1102fd878c9fca20c0138ea33 /fs/btrfs/extent_io.c | |
parent | 7f4ca37c486733da008778a1f4058fbc194a4fdd (diff) |
Btrfs: Simplify the logic in alloc_extent_buffer() for existing extent buffer case
alloc_extent_buffer() uses radix_tree_lookup() when radix_tree_insert()
fails with EEXIST. That part of the code is very similar to the code in
find_extent_buffer(). This patch replaces radix_tree_lookup() and
surrounding code in alloc_extent_buffer() with find_extent_buffer().
Note that radix_tree_lookup() does not need to be protected by
tree->buffer_lock. It is protected by eb->refs.
While at it, this patch
- changes the other usage of radix_tree_lookup() in alloc_extent_buffer()
with find_extent_buffer() to reduce redundancy.
- removes the unused argument 'len' to find_extent_buffer().
Signed-Off-by: Chandra Seetharaman <sekharan@us.ibm.com>
Reviewed-by: Zach Brown <zab@redhat.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 63 |
1 files changed, 26 insertions, 37 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index c10291cc4fd1..5439f24ab06b 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -4486,6 +4486,23 @@ static void mark_extent_buffer_accessed(struct extent_buffer *eb) | |||
4486 | } | 4486 | } |
4487 | } | 4487 | } |
4488 | 4488 | ||
4489 | struct extent_buffer *find_extent_buffer(struct extent_io_tree *tree, | ||
4490 | u64 start) | ||
4491 | { | ||
4492 | struct extent_buffer *eb; | ||
4493 | |||
4494 | rcu_read_lock(); | ||
4495 | eb = radix_tree_lookup(&tree->buffer, start >> PAGE_CACHE_SHIFT); | ||
4496 | if (eb && atomic_inc_not_zero(&eb->refs)) { | ||
4497 | rcu_read_unlock(); | ||
4498 | mark_extent_buffer_accessed(eb); | ||
4499 | return eb; | ||
4500 | } | ||
4501 | rcu_read_unlock(); | ||
4502 | |||
4503 | return NULL; | ||
4504 | } | ||
4505 | |||
4489 | struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, | 4506 | struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, |
4490 | u64 start, unsigned long len) | 4507 | u64 start, unsigned long len) |
4491 | { | 4508 | { |
@@ -4499,14 +4516,10 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, | |||
4499 | int uptodate = 1; | 4516 | int uptodate = 1; |
4500 | int ret; | 4517 | int ret; |
4501 | 4518 | ||
4502 | rcu_read_lock(); | 4519 | |
4503 | eb = radix_tree_lookup(&tree->buffer, start >> PAGE_CACHE_SHIFT); | 4520 | eb = find_extent_buffer(tree, start); |
4504 | if (eb && atomic_inc_not_zero(&eb->refs)) { | 4521 | if (eb) |
4505 | rcu_read_unlock(); | ||
4506 | mark_extent_buffer_accessed(eb); | ||
4507 | return eb; | 4522 | return eb; |
4508 | } | ||
4509 | rcu_read_unlock(); | ||
4510 | 4523 | ||
4511 | eb = __alloc_extent_buffer(tree, start, len, GFP_NOFS); | 4524 | eb = __alloc_extent_buffer(tree, start, len, GFP_NOFS); |
4512 | if (!eb) | 4525 | if (!eb) |
@@ -4565,24 +4578,17 @@ again: | |||
4565 | 4578 | ||
4566 | spin_lock(&tree->buffer_lock); | 4579 | spin_lock(&tree->buffer_lock); |
4567 | ret = radix_tree_insert(&tree->buffer, start >> PAGE_CACHE_SHIFT, eb); | 4580 | ret = radix_tree_insert(&tree->buffer, start >> PAGE_CACHE_SHIFT, eb); |
4581 | spin_unlock(&tree->buffer_lock); | ||
4582 | radix_tree_preload_end(); | ||
4568 | if (ret == -EEXIST) { | 4583 | if (ret == -EEXIST) { |
4569 | exists = radix_tree_lookup(&tree->buffer, | 4584 | exists = find_extent_buffer(tree, start); |
4570 | start >> PAGE_CACHE_SHIFT); | 4585 | if (exists) |
4571 | if (!atomic_inc_not_zero(&exists->refs)) { | 4586 | goto free_eb; |
4572 | spin_unlock(&tree->buffer_lock); | 4587 | else |
4573 | radix_tree_preload_end(); | ||
4574 | exists = NULL; | ||
4575 | goto again; | 4588 | goto again; |
4576 | } | ||
4577 | spin_unlock(&tree->buffer_lock); | ||
4578 | radix_tree_preload_end(); | ||
4579 | mark_extent_buffer_accessed(exists); | ||
4580 | goto free_eb; | ||
4581 | } | 4589 | } |
4582 | /* add one reference for the tree */ | 4590 | /* add one reference for the tree */ |
4583 | check_buffer_tree_ref(eb); | 4591 | check_buffer_tree_ref(eb); |
4584 | spin_unlock(&tree->buffer_lock); | ||
4585 | radix_tree_preload_end(); | ||
4586 | 4592 | ||
4587 | /* | 4593 | /* |
4588 | * there is a race where release page may have | 4594 | * there is a race where release page may have |
@@ -4613,23 +4619,6 @@ free_eb: | |||
4613 | return exists; | 4619 | return exists; |
4614 | } | 4620 | } |
4615 | 4621 | ||
4616 | struct extent_buffer *find_extent_buffer(struct extent_io_tree *tree, | ||
4617 | u64 start, unsigned long len) | ||
4618 | { | ||
4619 | struct extent_buffer *eb; | ||
4620 | |||
4621 | rcu_read_lock(); | ||
4622 | eb = radix_tree_lookup(&tree->buffer, start >> PAGE_CACHE_SHIFT); | ||
4623 | if (eb && atomic_inc_not_zero(&eb->refs)) { | ||
4624 | rcu_read_unlock(); | ||
4625 | mark_extent_buffer_accessed(eb); | ||
4626 | return eb; | ||
4627 | } | ||
4628 | rcu_read_unlock(); | ||
4629 | |||
4630 | return NULL; | ||
4631 | } | ||
4632 | |||
4633 | static inline void btrfs_release_extent_buffer_rcu(struct rcu_head *head) | 4622 | static inline void btrfs_release_extent_buffer_rcu(struct rcu_head *head) |
4634 | { | 4623 | { |
4635 | struct extent_buffer *eb = | 4624 | struct extent_buffer *eb = |