Commit fe3f566c authored by Li Zefan's avatar Li Zefan Committed by Chris Mason

Btrfs: Fix oops for defrag with compression turned on

When we defrag a file, whose size can be fit into an inline extent,
with compression enabled, the compress type is set to be
fs_info->compress_type, which is 0 if the btrfs filesystem is mounted
without compress option. This leads to oops.
Reported-by: default avatarDaniel Blueman <daniel.blueman@gmail.com>
Signed-off-by: default avatarLi Zefan <lizf@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 200da64e
...@@ -111,6 +111,7 @@ static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, ...@@ -111,6 +111,7 @@ static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode, struct btrfs_root *root, struct inode *inode,
u64 start, size_t size, size_t compressed_size, u64 start, size_t size, size_t compressed_size,
int compress_type,
struct page **compressed_pages) struct page **compressed_pages)
{ {
struct btrfs_key key; struct btrfs_key key;
...@@ -125,12 +126,9 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -125,12 +126,9 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
size_t cur_size = size; size_t cur_size = size;
size_t datasize; size_t datasize;
unsigned long offset; unsigned long offset;
int compress_type = BTRFS_COMPRESS_NONE;
if (compressed_size && compressed_pages) { if (compressed_size && compressed_pages)
compress_type = root->fs_info->compress_type;
cur_size = compressed_size; cur_size = compressed_size;
}
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
...@@ -220,7 +218,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -220,7 +218,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct inode *inode, u64 start, u64 end, struct inode *inode, u64 start, u64 end,
size_t compressed_size, size_t compressed_size, int compress_type,
struct page **compressed_pages) struct page **compressed_pages)
{ {
u64 isize = i_size_read(inode); u64 isize = i_size_read(inode);
...@@ -253,7 +251,7 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, ...@@ -253,7 +251,7 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans,
inline_len = min_t(u64, isize, actual_end); inline_len = min_t(u64, isize, actual_end);
ret = insert_inline_extent(trans, root, inode, start, ret = insert_inline_extent(trans, root, inode, start,
inline_len, compressed_size, inline_len, compressed_size,
compressed_pages); compress_type, compressed_pages);
BUG_ON(ret); BUG_ON(ret);
btrfs_delalloc_release_metadata(inode, end + 1 - start); btrfs_delalloc_release_metadata(inode, end + 1 - start);
btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0); btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0);
...@@ -432,12 +430,13 @@ static noinline int compress_file_range(struct inode *inode, ...@@ -432,12 +430,13 @@ static noinline int compress_file_range(struct inode *inode,
* to make an uncompressed inline extent. * to make an uncompressed inline extent.
*/ */
ret = cow_file_range_inline(trans, root, inode, ret = cow_file_range_inline(trans, root, inode,
start, end, 0, NULL); start, end, 0, 0, NULL);
} else { } else {
/* try making a compressed inline extent */ /* try making a compressed inline extent */
ret = cow_file_range_inline(trans, root, inode, ret = cow_file_range_inline(trans, root, inode,
start, end, start, end,
total_compressed, pages); total_compressed,
compress_type, pages);
} }
if (ret == 0) { if (ret == 0) {
/* /*
...@@ -791,7 +790,7 @@ static noinline int cow_file_range(struct inode *inode, ...@@ -791,7 +790,7 @@ static noinline int cow_file_range(struct inode *inode,
if (start == 0) { if (start == 0) {
/* lets try to make an inline extent */ /* lets try to make an inline extent */
ret = cow_file_range_inline(trans, root, inode, ret = cow_file_range_inline(trans, root, inode,
start, end, 0, NULL); start, end, 0, 0, NULL);
if (ret == 0) { if (ret == 0) {
extent_clear_unlock_delalloc(inode, extent_clear_unlock_delalloc(inode,
&BTRFS_I(inode)->io_tree, &BTRFS_I(inode)->io_tree,
......
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