Commit 6b82ce8d authored by liubo's avatar liubo Committed by Chris Mason

btrfs: fix uncheck memory allocation in btrfs_submit_compressed_read

btrfs_submit_compressed_read() is lack of memory allocation checks and
corresponding error route.

After this fix, if it comes to "no memory" case, errno will be returned
to userland step by step, and tell users this operation cannot go on.
Signed-off-by: default avatarLiu Bo <liubo2009@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent eab49bec
...@@ -562,7 +562,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -562,7 +562,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
u64 em_len; u64 em_len;
u64 em_start; u64 em_start;
struct extent_map *em; struct extent_map *em;
int ret; int ret = -ENOMEM;
u32 *sums; u32 *sums;
tree = &BTRFS_I(inode)->io_tree; tree = &BTRFS_I(inode)->io_tree;
...@@ -577,6 +577,9 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -577,6 +577,9 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
compressed_len = em->block_len; compressed_len = em->block_len;
cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS); cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS);
if (!cb)
goto out;
atomic_set(&cb->pending_bios, 0); atomic_set(&cb->pending_bios, 0);
cb->errors = 0; cb->errors = 0;
cb->inode = inode; cb->inode = inode;
...@@ -597,13 +600,18 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -597,13 +600,18 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
nr_pages = (compressed_len + PAGE_CACHE_SIZE - 1) / nr_pages = (compressed_len + PAGE_CACHE_SIZE - 1) /
PAGE_CACHE_SIZE; PAGE_CACHE_SIZE;
cb->compressed_pages = kmalloc(sizeof(struct page *) * nr_pages, cb->compressed_pages = kzalloc(sizeof(struct page *) * nr_pages,
GFP_NOFS); GFP_NOFS);
if (!cb->compressed_pages)
goto fail1;
bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev;
for (page_index = 0; page_index < nr_pages; page_index++) { for (page_index = 0; page_index < nr_pages; page_index++) {
cb->compressed_pages[page_index] = alloc_page(GFP_NOFS | cb->compressed_pages[page_index] = alloc_page(GFP_NOFS |
__GFP_HIGHMEM); __GFP_HIGHMEM);
if (!cb->compressed_pages[page_index])
goto fail2;
} }
cb->nr_pages = nr_pages; cb->nr_pages = nr_pages;
...@@ -614,6 +622,8 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -614,6 +622,8 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
cb->len = uncompressed_len; cb->len = uncompressed_len;
comp_bio = compressed_bio_alloc(bdev, cur_disk_byte, GFP_NOFS); comp_bio = compressed_bio_alloc(bdev, cur_disk_byte, GFP_NOFS);
if (!comp_bio)
goto fail2;
comp_bio->bi_private = cb; comp_bio->bi_private = cb;
comp_bio->bi_end_io = end_compressed_bio_read; comp_bio->bi_end_io = end_compressed_bio_read;
atomic_inc(&cb->pending_bios); atomic_inc(&cb->pending_bios);
...@@ -681,6 +691,17 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -681,6 +691,17 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
bio_put(comp_bio); bio_put(comp_bio);
return 0; return 0;
fail2:
for (page_index = 0; page_index < nr_pages; page_index++)
free_page((unsigned long)cb->compressed_pages[page_index]);
kfree(cb->compressed_pages);
fail1:
kfree(cb);
out:
free_extent_map(em);
return ret;
} }
static struct list_head comp_idle_workspace[BTRFS_COMPRESS_TYPES]; static struct list_head comp_idle_workspace[BTRFS_COMPRESS_TYPES];
......
...@@ -1865,7 +1865,7 @@ static int submit_one_bio(int rw, struct bio *bio, int mirror_num, ...@@ -1865,7 +1865,7 @@ static int submit_one_bio(int rw, struct bio *bio, int mirror_num,
bio_get(bio); bio_get(bio);
if (tree->ops && tree->ops->submit_bio_hook) if (tree->ops && tree->ops->submit_bio_hook)
tree->ops->submit_bio_hook(page->mapping->host, rw, bio, ret = tree->ops->submit_bio_hook(page->mapping->host, rw, bio,
mirror_num, bio_flags, start); mirror_num, bio_flags, start);
else else
submit_bio(rw, bio); submit_bio(rw, bio);
...@@ -2126,7 +2126,7 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page, ...@@ -2126,7 +2126,7 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
ret = __extent_read_full_page(tree, page, get_extent, &bio, 0, ret = __extent_read_full_page(tree, page, get_extent, &bio, 0,
&bio_flags); &bio_flags);
if (bio) if (bio)
submit_one_bio(READ, bio, 0, bio_flags); ret = submit_one_bio(READ, bio, 0, bio_flags);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment