Skip to content

Commit 5d2361d

Browse files
forrest1209masoncl
authored andcommitted
Btrfs: btrfs_release_extent_buffer_page didn't free pages of dummy extent
btrfs_release_extent_buffer_page() can't handle dummy extent that allocated by btrfs_clone_extent_buffer() properly. That is because reference count of pages that allocated by btrfs_clone_extent_buffer() was 2, 1 by alloc_page(), and another by attach_extent_buffer_page(). Running following command repeatly can check this memory leak problem btrfs inspect-internal inode-resolve 256 /mnt/btrfs Signed-off-by: Chien-Kuan Yeh <ckya@synology.com> Signed-off-by: Forrest Liu <forrestl@synology.com> Reviewed-by: Filipe Manana <fdmanana@suse.com> Tested-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
1 parent 6e17d30 commit 5d2361d

File tree

1 file changed

+26
-25
lines changed

1 file changed

+26
-25
lines changed

fs/btrfs/extent_io.c

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4560,36 +4560,37 @@ static void btrfs_release_extent_buffer_page(struct extent_buffer *eb)
45604560
do {
45614561
index--;
45624562
page = eb->pages[index];
4563-
if (page && mapped) {
4563+
if (!page)
4564+
continue;
4565+
if (mapped)
45644566
spin_lock(&page->mapping->private_lock);
4567+
/*
4568+
* We do this since we'll remove the pages after we've
4569+
* removed the eb from the radix tree, so we could race
4570+
* and have this page now attached to the new eb. So
4571+
* only clear page_private if it's still connected to
4572+
* this eb.
4573+
*/
4574+
if (PagePrivate(page) &&
4575+
page->private == (unsigned long)eb) {
4576+
BUG_ON(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
4577+
BUG_ON(PageDirty(page));
4578+
BUG_ON(PageWriteback(page));
45654579
/*
4566-
* We do this since we'll remove the pages after we've
4567-
* removed the eb from the radix tree, so we could race
4568-
* and have this page now attached to the new eb. So
4569-
* only clear page_private if it's still connected to
4570-
* this eb.
4580+
* We need to make sure we haven't be attached
4581+
* to a new eb.
45714582
*/
4572-
if (PagePrivate(page) &&
4573-
page->private == (unsigned long)eb) {
4574-
BUG_ON(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
4575-
BUG_ON(PageDirty(page));
4576-
BUG_ON(PageWriteback(page));
4577-
/*
4578-
* We need to make sure we haven't be attached
4579-
* to a new eb.
4580-
*/
4581-
ClearPagePrivate(page);
4582-
set_page_private(page, 0);
4583-
/* One for the page private */
4584-
page_cache_release(page);
4585-
}
4586-
spin_unlock(&page->mapping->private_lock);
4587-
4588-
}
4589-
if (page) {
4590-
/* One for when we alloced the page */
4583+
ClearPagePrivate(page);
4584+
set_page_private(page, 0);
4585+
/* One for the page private */
45914586
page_cache_release(page);
45924587
}
4588+
4589+
if (mapped)
4590+
spin_unlock(&page->mapping->private_lock);
4591+
4592+
/* One for when we alloced the page */
4593+
page_cache_release(page);
45934594
} while (index != 0);
45944595
}
45954596

0 commit comments

Comments
 (0)