Btrfs: fix page leak when allocing extent buffers
authorJosef Bacik <josef@redhat.com>
Fri, 4 May 2012 19:16:06 +0000 (15:16 -0400)
committerChris Mason <chris.mason@oracle.com>
Fri, 4 May 2012 19:16:06 +0000 (15:16 -0400)
If we happen to alloc a extent buffer and then alloc a page and notice that
page is already attached to an extent buffer, we will only unlock it and
free our existing eb.  Any pages currently attached to that eb will be
properly freed, but we don't do the page_cache_release() on the page where
we noticed the other extent buffer which can cause us to leak pages and I
hope cause the weird issues we've been seeing in this area.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/extent_io.c

index 0c23e57077c6f78ad2e79819612e7da90adac408..2fb52c26c677d22867cbe96e46e230813fe03053 100644 (file)
@@ -4120,6 +4120,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
                        if (atomic_inc_not_zero(&exists->refs)) {
                                spin_unlock(&mapping->private_lock);
                                unlock_page(p);
+                               page_cache_release(p);
                                mark_extent_buffer_accessed(exists);
                                goto free_eb;
                        }
@@ -4199,8 +4200,7 @@ free_eb:
                        unlock_page(eb->pages[i]);
        }
 
-       if (!atomic_dec_and_test(&eb->refs))
-               return exists;
+       WARN_ON(!atomic_dec_and_test(&eb->refs));
        btrfs_release_extent_buffer(eb);
        return exists;
 }