aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent_io.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2012-07-20 16:05:36 -0400
committerChris Mason <chris.mason@fusionio.com>2012-07-23 16:28:08 -0400
commite64860aa05048fa7a8483ca698b17c2caf5625cf (patch)
tree3bee3474a00fdbef80414a926c31187865392abe /fs/btrfs/extent_io.c
parenta98cdb85b990765dbe80a215367ae007320bfeea (diff)
Btrfs: don't return true in releasepage unless we actually freed the eb
I noticed while looking at an extent_buffer race that we will unconditionally return 1 if we get down to release_extent_buffer after clearing the tree ref. However we can easily race in here and get a ref on the eb and not actually free the eb. So make release_extent_buffer return 1 if it free'd the eb and 0 if not so we can be a little kinder to the vm. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r--fs/btrfs/extent_io.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index f08206fcfb22..e6243f787434 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4300,7 +4300,7 @@ static inline void btrfs_release_extent_buffer_rcu(struct rcu_head *head)
4300} 4300}
4301 4301
4302/* Expects to have eb->eb_lock already held */ 4302/* Expects to have eb->eb_lock already held */
4303static void release_extent_buffer(struct extent_buffer *eb, gfp_t mask) 4303static int release_extent_buffer(struct extent_buffer *eb, gfp_t mask)
4304{ 4304{
4305 WARN_ON(atomic_read(&eb->refs) == 0); 4305 WARN_ON(atomic_read(&eb->refs) == 0);
4306 if (atomic_dec_and_test(&eb->refs)) { 4306 if (atomic_dec_and_test(&eb->refs)) {
@@ -4321,9 +4321,11 @@ static void release_extent_buffer(struct extent_buffer *eb, gfp_t mask)
4321 btrfs_release_extent_buffer_page(eb, 0); 4321 btrfs_release_extent_buffer_page(eb, 0);
4322 4322
4323 call_rcu(&eb->rcu_head, btrfs_release_extent_buffer_rcu); 4323 call_rcu(&eb->rcu_head, btrfs_release_extent_buffer_rcu);
4324 return; 4324 return 1;
4325 } 4325 }
4326 spin_unlock(&eb->refs_lock); 4326 spin_unlock(&eb->refs_lock);
4327
4328 return 0;
4327} 4329}
4328 4330
4329void free_extent_buffer(struct extent_buffer *eb) 4331void free_extent_buffer(struct extent_buffer *eb)
@@ -4962,7 +4964,6 @@ int try_release_extent_buffer(struct page *page, gfp_t mask)
4962 spin_unlock(&eb->refs_lock); 4964 spin_unlock(&eb->refs_lock);
4963 return 0; 4965 return 0;
4964 } 4966 }
4965 release_extent_buffer(eb, mask);
4966 4967
4967 return 1; 4968 return release_extent_buffer(eb, mask);
4968} 4969}