Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1568310
| From | Jiri Slaby <jslaby@suse.cz> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [PATCH 3.12 023/235] Btrfs: fix memory leak in reading btree blocks |
| Date | 2017-01-27 13:10 +0100 |
| Message-ID | <t4dvP-3YT-13@gated-at.bofh.it> (permalink) |
| References | <t4cq5-32y-3@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
From: Liu Bo <bo.li.liu@oracle.com>
3.12-stable review patch. If anyone has any objections, please let me know.
===============
commit 2571e739677f1e4c0c63f5ed49adcc0857923625 upstream.
So we can read a btree block via readahead or intentional read,
and we can end up with a memory leak when something happens as
follows,
1) readahead starts to read block A but does not wait for read
completion,
2) btree_readpage_end_io_hook finds that block A is corrupted,
and it needs to clear all block A's pages' uptodate bit.
3) meanwhile an intentional read kicks in and checks block A's
pages' uptodate to decide which page needs to be read.
4) when some pages have the uptodate bit during 3)'s check so
3) doesn't count them for eb->io_pages, but they are later
cleared by 2) so we has to readpage on the page, we get
the wrong eb->io_pages which results in a memory leak of
this block.
This fixes the problem by firstly getting all pages's locking and
then checking pages' uptodate bit.
t1(readahead) t2(readahead endio) t3(the following read)
read_extent_buffer_pages end_bio_extent_readpage
for pg in eb: for page 0,1,2 in eb:
if pg is uptodate: btree_readpage_end_io_hook(pg)
num_reads++ if uptodate:
eb->io_pages = num_reads SetPageUptodate(pg) _______________
for pg in eb: for page 3 in eb: read_extent_buffer_pages
if pg is NOT uptodate: btree_readpage_end_io_hook(pg) for pg in eb:
__extent_read_full_page(pg) sanity check reports something wrong if pg is uptodate:
clear_extent_buffer_uptodate(eb) num_reads++
for pg in eb: eb->io_pages = num_reads
ClearPageUptodate(page) _______________
for pg in eb:
if pg is NOT uptodate:
__extent_read_full_page(pg)
So t3's eb->io_pages is not consistent with the number of pages it's reading,
and during endio(), atomic_dec_and_test(&eb->io_pages) will get a negative
number so that we're not able to free the eb.
Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
fs/btrfs/extent_io.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 85bcb25384c0..854af9e95f4c 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4865,11 +4865,20 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
lock_page(page);
}
locked_pages++;
+ }
+ /*
+ * We need to firstly lock all pages to make sure that
+ * the uptodate bit of our pages won't be affected by
+ * clear_extent_buffer_uptodate().
+ */
+ for (i = start_i; i < num_pages; i++) {
+ page = eb->pages[i];
if (!PageUptodate(page)) {
num_reads++;
all_uptodate = 0;
}
}
+
if (all_uptodate) {
if (start_i == 0)
set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
--
2.11.0
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[PATCH 3.12 001/235] driver core: Delete an unnecessary check before the function call "put_device" Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 015/235] USB: serial: kl5kusb105: fix open error path Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 018/235] usb: gadget: composite: correctly initialize ep->maxpacket Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 023/235] Btrfs: fix memory leak in reading btree blocks Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 012/235] Btrfs: fix tree search logic when replaying directory entry deletes Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 010/235] hotplug: Make register and unregister notifier API symmetric Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 003/235] ext4: fix data exposure after a crash Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 019/235] USB: UHCI: report non-PME wakeup signalling for Intel hardware Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 024/235] block_dev: don't test bdev->bd_contains when it is not stable Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 004/235] locking/rtmutex: Prevent dequeue vs. unlock race Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 030/235] ext4: add sanity checking to count_overhead() Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 009/235] m68k: Fix ndelay() macro Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 008/235] can: peak: fix bad memory access and free sequence Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 014/235] USB: serial: option: add dlink dwm-158 Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 013/235] USB: serial: option: add support for Telit LE922A PIDs 0x1040, 0x1041 Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100 [PATCH 3.12 005/235] locking/rtmutex: Use READ_ONCE() in rt_mutex_owner() Jiri Slaby <jslaby@suse.cz> - 2017-01-27 13:10 +0100
csiph-web