diff options
author | Josef Bacik <jbacik@fusionio.com> | 2012-07-20 16:05:36 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-07-23 16:28:08 -0400 |
commit | e64860aa05048fa7a8483ca698b17c2caf5625cf (patch) | |
tree | 3bee3474a00fdbef80414a926c31187865392abe /fs/btrfs/extent_io.c | |
parent | a98cdb85b990765dbe80a215367ae007320bfeea (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.c | 9 |
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 */ |
4303 | static void release_extent_buffer(struct extent_buffer *eb, gfp_t mask) | 4303 | static 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 | ||
4329 | void free_extent_buffer(struct extent_buffer *eb) | 4331 | void 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 | } |