aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/extent_io.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 3b9fb478b0d1..907ed0025dd4 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4184,6 +4184,7 @@ static inline void btrfs_release_extent_buffer(struct extent_buffer *eb)
4184 4184
4185static void check_buffer_tree_ref(struct extent_buffer *eb) 4185static void check_buffer_tree_ref(struct extent_buffer *eb)
4186{ 4186{
4187 int refs;
4187 /* the ref bit is tricky. We have to make sure it is set 4188 /* the ref bit is tricky. We have to make sure it is set
4188 * if we have the buffer dirty. Otherwise the 4189 * if we have the buffer dirty. Otherwise the
4189 * code to free a buffer can end up dropping a dirty 4190 * code to free a buffer can end up dropping a dirty
@@ -4204,6 +4205,10 @@ static void check_buffer_tree_ref(struct extent_buffer *eb)
4204 * So bump the ref count first, then set the bit. If someone 4205 * So bump the ref count first, then set the bit. If someone
4205 * beat us to it, drop the ref we added. 4206 * beat us to it, drop the ref we added.
4206 */ 4207 */
4208 refs = atomic_read(&eb->refs);
4209 if (refs >= 2 && test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags))
4210 return;
4211
4207 spin_lock(&eb->refs_lock); 4212 spin_lock(&eb->refs_lock);
4208 if (!test_and_set_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) 4213 if (!test_and_set_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags))
4209 atomic_inc(&eb->refs); 4214 atomic_inc(&eb->refs);
@@ -4405,9 +4410,20 @@ static int release_extent_buffer(struct extent_buffer *eb, gfp_t mask)
4405 4410
4406void free_extent_buffer(struct extent_buffer *eb) 4411void free_extent_buffer(struct extent_buffer *eb)
4407{ 4412{
4413 int refs;
4414 int old;
4408 if (!eb) 4415 if (!eb)
4409 return; 4416 return;
4410 4417
4418 while (1) {
4419 refs = atomic_read(&eb->refs);
4420 if (refs <= 3)
4421 break;
4422 old = atomic_cmpxchg(&eb->refs, refs, refs - 1);
4423 if (old == refs)
4424 return;
4425 }
4426
4411 spin_lock(&eb->refs_lock); 4427 spin_lock(&eb->refs_lock);
4412 if (atomic_read(&eb->refs) == 2 && 4428 if (atomic_read(&eb->refs) == 2 &&
4413 test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags)) 4429 test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags))