diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2011-03-28 04:30:38 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2011-04-05 01:19:42 -0400 |
commit | fe3f566cd19bb6d787c92b2e202c85f929abf3ac (patch) | |
tree | 216c33bb0ed94e7791141939ea763620576d82b0 /fs | |
parent | 200da64e0b039f873f0f20481e6a7d056e7cc6c9 (diff) |
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: Daniel Blueman <daniel.blueman@gmail.com>
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/inode.c | 17 |
1 files changed, 8 insertions, 9 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 06274186b290..62ae9d5da806 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -111,6 +111,7 @@ static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | |||
111 | static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | 111 | static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, |
112 | struct btrfs_root *root, struct inode *inode, | 112 | struct btrfs_root *root, struct inode *inode, |
113 | u64 start, size_t size, size_t compressed_size, | 113 | u64 start, size_t size, size_t compressed_size, |
114 | int compress_type, | ||
114 | struct page **compressed_pages) | 115 | struct page **compressed_pages) |
115 | { | 116 | { |
116 | struct btrfs_key key; | 117 | struct btrfs_key key; |
@@ -125,12 +126,9 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
125 | size_t cur_size = size; | 126 | size_t cur_size = size; |
126 | size_t datasize; | 127 | size_t datasize; |
127 | unsigned long offset; | 128 | unsigned long offset; |
128 | int compress_type = BTRFS_COMPRESS_NONE; | ||
129 | 129 | ||
130 | if (compressed_size && compressed_pages) { | 130 | if (compressed_size && compressed_pages) |
131 | compress_type = root->fs_info->compress_type; | ||
132 | cur_size = compressed_size; | 131 | cur_size = compressed_size; |
133 | } | ||
134 | 132 | ||
135 | path = btrfs_alloc_path(); | 133 | path = btrfs_alloc_path(); |
136 | if (!path) | 134 | if (!path) |
@@ -220,7 +218,7 @@ fail: | |||
220 | static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, | 218 | static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, |
221 | struct btrfs_root *root, | 219 | struct btrfs_root *root, |
222 | struct inode *inode, u64 start, u64 end, | 220 | struct inode *inode, u64 start, u64 end, |
223 | size_t compressed_size, | 221 | size_t compressed_size, int compress_type, |
224 | struct page **compressed_pages) | 222 | struct page **compressed_pages) |
225 | { | 223 | { |
226 | u64 isize = i_size_read(inode); | 224 | u64 isize = i_size_read(inode); |
@@ -253,7 +251,7 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, | |||
253 | inline_len = min_t(u64, isize, actual_end); | 251 | inline_len = min_t(u64, isize, actual_end); |
254 | ret = insert_inline_extent(trans, root, inode, start, | 252 | ret = insert_inline_extent(trans, root, inode, start, |
255 | inline_len, compressed_size, | 253 | inline_len, compressed_size, |
256 | compressed_pages); | 254 | compress_type, compressed_pages); |
257 | BUG_ON(ret); | 255 | BUG_ON(ret); |
258 | btrfs_delalloc_release_metadata(inode, end + 1 - start); | 256 | btrfs_delalloc_release_metadata(inode, end + 1 - start); |
259 | btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0); | 257 | btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0); |
@@ -432,12 +430,13 @@ again: | |||
432 | * to make an uncompressed inline extent. | 430 | * to make an uncompressed inline extent. |
433 | */ | 431 | */ |
434 | ret = cow_file_range_inline(trans, root, inode, | 432 | ret = cow_file_range_inline(trans, root, inode, |
435 | start, end, 0, NULL); | 433 | start, end, 0, 0, NULL); |
436 | } else { | 434 | } else { |
437 | /* try making a compressed inline extent */ | 435 | /* try making a compressed inline extent */ |
438 | ret = cow_file_range_inline(trans, root, inode, | 436 | ret = cow_file_range_inline(trans, root, inode, |
439 | start, end, | 437 | start, end, |
440 | total_compressed, pages); | 438 | total_compressed, |
439 | compress_type, pages); | ||
441 | } | 440 | } |
442 | if (ret == 0) { | 441 | if (ret == 0) { |
443 | /* | 442 | /* |
@@ -791,7 +790,7 @@ static noinline int cow_file_range(struct inode *inode, | |||
791 | if (start == 0) { | 790 | if (start == 0) { |
792 | /* lets try to make an inline extent */ | 791 | /* lets try to make an inline extent */ |
793 | ret = cow_file_range_inline(trans, root, inode, | 792 | ret = cow_file_range_inline(trans, root, inode, |
794 | start, end, 0, NULL); | 793 | start, end, 0, 0, NULL); |
795 | if (ret == 0) { | 794 | if (ret == 0) { |
796 | extent_clear_unlock_delalloc(inode, | 795 | extent_clear_unlock_delalloc(inode, |
797 | &BTRFS_I(inode)->io_tree, | 796 | &BTRFS_I(inode)->io_tree, |