aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <clm@fb.com>2014-01-04 00:07:00 -0500
committerChris Mason <clm@fb.com>2014-01-29 10:06:29 -0500
commit514ac8ad8793a097c0c9d89202c642479d6dfa34 (patch)
tree7b94b18dce144eb4be4e45102c00071c02c6e2b3
parent23c6bf6a91e96c17a452e07b12b38ed66504e799 (diff)
Btrfs: don't use ram_bytes for uncompressed inline items
If we truncate an uncompressed inline item, ram_bytes isn't updated to reflect the new size. The fixe uses the size directly from the item header when reading uncompressed inlines, and also fixes truncate to update the size as it goes. Reported-by: Jens Axboe <axboe@fb.com> Signed-off-by: Chris Mason <clm@fb.com> CC: stable@vger.kernel.org
-rw-r--r--fs/btrfs/ctree.h35
-rw-r--r--fs/btrfs/file.c3
-rw-r--r--fs/btrfs/inode.c15
-rw-r--r--fs/btrfs/print-tree.c2
-rw-r--r--fs/btrfs/send.c11
-rw-r--r--fs/btrfs/tree-log.c8
6 files changed, 52 insertions, 22 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 84d4c052fcd9..fceddbdfdd3d 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2990,15 +2990,6 @@ BTRFS_SETGET_FUNCS(file_extent_encryption, struct btrfs_file_extent_item,
2990BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item, 2990BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
2991 other_encoding, 16); 2991 other_encoding, 16);
2992 2992
2993/* this returns the number of file bytes represented by the inline item.
2994 * If an item is compressed, this is the uncompressed size
2995 */
2996static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
2997 struct btrfs_file_extent_item *e)
2998{
2999 return btrfs_file_extent_ram_bytes(eb, e);
3000}
3001
3002/* 2993/*
3003 * this returns the number of bytes used by the item on disk, minus the 2994 * this returns the number of bytes used by the item on disk, minus the
3004 * size of any extent headers. If a file is compressed on disk, this is 2995 * size of any extent headers. If a file is compressed on disk, this is
@@ -3012,6 +3003,32 @@ static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
3012 return btrfs_item_size(eb, e) - offset; 3003 return btrfs_item_size(eb, e) - offset;
3013} 3004}
3014 3005
3006/* this returns the number of file bytes represented by the inline item.
3007 * If an item is compressed, this is the uncompressed size
3008 */
3009static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
3010 int slot,
3011 struct btrfs_file_extent_item *fi)
3012{
3013 struct btrfs_map_token token;
3014
3015 btrfs_init_map_token(&token);
3016 /*
3017 * return the space used on disk if this item isn't
3018 * compressed or encoded
3019 */
3020 if (btrfs_token_file_extent_compression(eb, fi, &token) == 0 &&
3021 btrfs_token_file_extent_encryption(eb, fi, &token) == 0 &&
3022 btrfs_token_file_extent_other_encoding(eb, fi, &token) == 0) {
3023 return btrfs_file_extent_inline_item_len(eb,
3024 btrfs_item_nr(slot));
3025 }
3026
3027 /* otherwise use the ram bytes field */
3028 return btrfs_token_file_extent_ram_bytes(eb, fi, &token);
3029}
3030
3031
3015/* btrfs_dev_stats_item */ 3032/* btrfs_dev_stats_item */
3016static inline u64 btrfs_dev_stats_value(struct extent_buffer *eb, 3033static inline u64 btrfs_dev_stats_value(struct extent_buffer *eb,
3017 struct btrfs_dev_stats_item *ptr, 3034 struct btrfs_dev_stats_item *ptr,
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 3dfd8db0e243..0165b8672f09 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -772,7 +772,8 @@ next_slot:
772 btrfs_file_extent_num_bytes(leaf, fi); 772 btrfs_file_extent_num_bytes(leaf, fi);
773 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { 773 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
774 extent_end = key.offset + 774 extent_end = key.offset +
775 btrfs_file_extent_inline_len(leaf, fi); 775 btrfs_file_extent_inline_len(leaf,
776 path->slots[0], fi);
776 } else { 777 } else {
777 WARN_ON(1); 778 WARN_ON(1);
778 extent_end = search_start; 779 extent_end = search_start;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3b6598783be9..ad961a598c99 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1281,7 +1281,8 @@ next_slot:
1281 nocow = 1; 1281 nocow = 1;
1282 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { 1282 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
1283 extent_end = found_key.offset + 1283 extent_end = found_key.offset +
1284 btrfs_file_extent_inline_len(leaf, fi); 1284 btrfs_file_extent_inline_len(leaf,
1285 path->slots[0], fi);
1285 extent_end = ALIGN(extent_end, root->sectorsize); 1286 extent_end = ALIGN(extent_end, root->sectorsize);
1286 } else { 1287 } else {
1287 BUG_ON(1); 1288 BUG_ON(1);
@@ -4023,7 +4024,7 @@ search_again:
4023 btrfs_file_extent_num_bytes(leaf, fi); 4024 btrfs_file_extent_num_bytes(leaf, fi);
4024 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { 4025 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
4025 item_end += btrfs_file_extent_inline_len(leaf, 4026 item_end += btrfs_file_extent_inline_len(leaf,
4026 fi); 4027 path->slots[0], fi);
4027 } 4028 }
4028 item_end--; 4029 item_end--;
4029 } 4030 }
@@ -4093,6 +4094,12 @@ search_again:
4093 inode_sub_bytes(inode, item_end + 1 - 4094 inode_sub_bytes(inode, item_end + 1 -
4094 new_size); 4095 new_size);
4095 } 4096 }
4097
4098 /*
4099 * update the ram bytes to properly reflect
4100 * the new size of our item
4101 */
4102 btrfs_set_file_extent_ram_bytes(leaf, fi, size);
4096 size = 4103 size =
4097 btrfs_file_extent_calc_inline_size(size); 4104 btrfs_file_extent_calc_inline_size(size);
4098 btrfs_truncate_item(root, path, size, 1); 4105 btrfs_truncate_item(root, path, size, 1);
@@ -6162,7 +6169,7 @@ again:
6162 btrfs_file_extent_num_bytes(leaf, item); 6169 btrfs_file_extent_num_bytes(leaf, item);
6163 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { 6170 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
6164 size_t size; 6171 size_t size;
6165 size = btrfs_file_extent_inline_len(leaf, item); 6172 size = btrfs_file_extent_inline_len(leaf, path->slots[0], item);
6166 extent_end = ALIGN(extent_start + size, root->sectorsize); 6173 extent_end = ALIGN(extent_start + size, root->sectorsize);
6167 } 6174 }
6168next: 6175next:
@@ -6231,7 +6238,7 @@ next:
6231 goto out; 6238 goto out;
6232 } 6239 }
6233 6240
6234 size = btrfs_file_extent_inline_len(leaf, item); 6241 size = btrfs_file_extent_inline_len(leaf, path->slots[0], item);
6235 extent_offset = page_offset(page) + pg_offset - extent_start; 6242 extent_offset = page_offset(page) + pg_offset - extent_start;
6236 copy_size = min_t(u64, PAGE_CACHE_SIZE - pg_offset, 6243 copy_size = min_t(u64, PAGE_CACHE_SIZE - pg_offset,
6237 size - extent_offset); 6244 size - extent_offset);
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c
index 4eed002b7cf6..6efd70d3b64f 100644
--- a/fs/btrfs/print-tree.c
+++ b/fs/btrfs/print-tree.c
@@ -249,7 +249,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
249 BTRFS_FILE_EXTENT_INLINE) { 249 BTRFS_FILE_EXTENT_INLINE) {
250 printk(KERN_INFO "\t\tinline extent data " 250 printk(KERN_INFO "\t\tinline extent data "
251 "size %u\n", 251 "size %u\n",
252 btrfs_file_extent_inline_len(l, fi)); 252 btrfs_file_extent_inline_len(l, i, fi));
253 break; 253 break;
254 } 254 }
255 printk(KERN_INFO "\t\textent data disk bytenr %llu " 255 printk(KERN_INFO "\t\textent data disk bytenr %llu "
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 85259cba784a..730dce395858 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -1377,7 +1377,7 @@ static int read_symlink(struct btrfs_root *root,
1377 BUG_ON(compression); 1377 BUG_ON(compression);
1378 1378
1379 off = btrfs_file_extent_inline_start(ei); 1379 off = btrfs_file_extent_inline_start(ei);
1380 len = btrfs_file_extent_inline_len(path->nodes[0], ei); 1380 len = btrfs_file_extent_inline_len(path->nodes[0], path->slots[0], ei);
1381 1381
1382 ret = fs_path_add_from_extent_buffer(dest, path->nodes[0], off, len); 1382 ret = fs_path_add_from_extent_buffer(dest, path->nodes[0], off, len);
1383 1383
@@ -4207,7 +4207,8 @@ static int send_write_or_clone(struct send_ctx *sctx,
4207 struct btrfs_file_extent_item); 4207 struct btrfs_file_extent_item);
4208 type = btrfs_file_extent_type(path->nodes[0], ei); 4208 type = btrfs_file_extent_type(path->nodes[0], ei);
4209 if (type == BTRFS_FILE_EXTENT_INLINE) { 4209 if (type == BTRFS_FILE_EXTENT_INLINE) {
4210 len = btrfs_file_extent_inline_len(path->nodes[0], ei); 4210 len = btrfs_file_extent_inline_len(path->nodes[0],
4211 path->slots[0], ei);
4211 /* 4212 /*
4212 * it is possible the inline item won't cover the whole page, 4213 * it is possible the inline item won't cover the whole page,
4213 * but there may be items after this page. Make 4214 * but there may be items after this page. Make
@@ -4448,7 +4449,8 @@ static int get_last_extent(struct send_ctx *sctx, u64 offset)
4448 struct btrfs_file_extent_item); 4449 struct btrfs_file_extent_item);
4449 type = btrfs_file_extent_type(path->nodes[0], fi); 4450 type = btrfs_file_extent_type(path->nodes[0], fi);
4450 if (type == BTRFS_FILE_EXTENT_INLINE) { 4451 if (type == BTRFS_FILE_EXTENT_INLINE) {
4451 u64 size = btrfs_file_extent_inline_len(path->nodes[0], fi); 4452 u64 size = btrfs_file_extent_inline_len(path->nodes[0],
4453 path->slots[0], fi);
4452 extent_end = ALIGN(key.offset + size, 4454 extent_end = ALIGN(key.offset + size,
4453 sctx->send_root->sectorsize); 4455 sctx->send_root->sectorsize);
4454 } else { 4456 } else {
@@ -4482,7 +4484,8 @@ static int maybe_send_hole(struct send_ctx *sctx, struct btrfs_path *path,
4482 struct btrfs_file_extent_item); 4484 struct btrfs_file_extent_item);
4483 type = btrfs_file_extent_type(path->nodes[0], fi); 4485 type = btrfs_file_extent_type(path->nodes[0], fi);
4484 if (type == BTRFS_FILE_EXTENT_INLINE) { 4486 if (type == BTRFS_FILE_EXTENT_INLINE) {
4485 u64 size = btrfs_file_extent_inline_len(path->nodes[0], fi); 4487 u64 size = btrfs_file_extent_inline_len(path->nodes[0],
4488 path->slots[0], fi);
4486 extent_end = ALIGN(key->offset + size, 4489 extent_end = ALIGN(key->offset + size,
4487 sctx->send_root->sectorsize); 4490 sctx->send_root->sectorsize);
4488 } else { 4491 } else {
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index b142b6dc96c3..39d83da03e03 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -570,7 +570,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
570 if (btrfs_file_extent_disk_bytenr(eb, item) == 0) 570 if (btrfs_file_extent_disk_bytenr(eb, item) == 0)
571 nbytes = 0; 571 nbytes = 0;
572 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { 572 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
573 size = btrfs_file_extent_inline_len(eb, item); 573 size = btrfs_file_extent_inline_len(eb, slot, item);
574 nbytes = btrfs_file_extent_ram_bytes(eb, item); 574 nbytes = btrfs_file_extent_ram_bytes(eb, item);
575 extent_end = ALIGN(start + size, root->sectorsize); 575 extent_end = ALIGN(start + size, root->sectorsize);
576 } else { 576 } else {
@@ -3367,7 +3367,9 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
3367 struct btrfs_file_extent_item); 3367 struct btrfs_file_extent_item);
3368 if (btrfs_file_extent_type(src, extent) == 3368 if (btrfs_file_extent_type(src, extent) ==
3369 BTRFS_FILE_EXTENT_INLINE) { 3369 BTRFS_FILE_EXTENT_INLINE) {
3370 len = btrfs_file_extent_inline_len(src, extent); 3370 len = btrfs_file_extent_inline_len(src,
3371 src_path->slots[0],
3372 extent);
3371 *last_extent = ALIGN(key.offset + len, 3373 *last_extent = ALIGN(key.offset + len,
3372 log->sectorsize); 3374 log->sectorsize);
3373 } else { 3375 } else {
@@ -3431,7 +3433,7 @@ fill_holes:
3431 extent = btrfs_item_ptr(src, i, struct btrfs_file_extent_item); 3433 extent = btrfs_item_ptr(src, i, struct btrfs_file_extent_item);
3432 if (btrfs_file_extent_type(src, extent) == 3434 if (btrfs_file_extent_type(src, extent) ==
3433 BTRFS_FILE_EXTENT_INLINE) { 3435 BTRFS_FILE_EXTENT_INLINE) {
3434 len = btrfs_file_extent_inline_len(src, extent); 3436 len = btrfs_file_extent_inline_len(src, i, extent);
3435 extent_end = ALIGN(key.offset + len, log->sectorsize); 3437 extent_end = ALIGN(key.offset + len, log->sectorsize);
3436 } else { 3438 } else {
3437 len = btrfs_file_extent_num_bytes(src, extent); 3439 len = btrfs_file_extent_num_bytes(src, extent);