]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Btrfs: don't use ram_bytes for uncompressed inline items
authorChris Mason <clm@fb.com>
Sat, 4 Jan 2014 05:07:00 +0000 (21:07 -0800)
committerChris Mason <clm@fb.com>
Wed, 29 Jan 2014 15:06:29 +0000 (07:06 -0800)
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
fs/btrfs/ctree.h
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/print-tree.c
fs/btrfs/send.c
fs/btrfs/tree-log.c

index 84d4c052fcd9bc867421554e3975bdc148eb19c5..fceddbdfdd3d0377cb6d5d4c92eadf381f978740 100644 (file)
@@ -2990,15 +2990,6 @@ BTRFS_SETGET_FUNCS(file_extent_encryption, struct btrfs_file_extent_item,
 BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
                   other_encoding, 16);
 
-/* this returns the number of file bytes represented by the inline item.
- * If an item is compressed, this is the uncompressed size
- */
-static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
-                                              struct btrfs_file_extent_item *e)
-{
-       return btrfs_file_extent_ram_bytes(eb, e);
-}
-
 /*
  * this returns the number of bytes used by the item on disk, minus the
  * 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,
        return btrfs_item_size(eb, e) - offset;
 }
 
+/* this returns the number of file bytes represented by the inline item.
+ * If an item is compressed, this is the uncompressed size
+ */
+static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
+                                              int slot,
+                                              struct btrfs_file_extent_item *fi)
+{
+       struct btrfs_map_token token;
+
+       btrfs_init_map_token(&token);
+       /*
+        * return the space used on disk if this item isn't
+        * compressed or encoded
+        */
+       if (btrfs_token_file_extent_compression(eb, fi, &token) == 0 &&
+           btrfs_token_file_extent_encryption(eb, fi, &token) == 0 &&
+           btrfs_token_file_extent_other_encoding(eb, fi, &token) == 0) {
+               return btrfs_file_extent_inline_item_len(eb,
+                                                        btrfs_item_nr(slot));
+       }
+
+       /* otherwise use the ram bytes field */
+       return btrfs_token_file_extent_ram_bytes(eb, fi, &token);
+}
+
+
 /* btrfs_dev_stats_item */
 static inline u64 btrfs_dev_stats_value(struct extent_buffer *eb,
                                        struct btrfs_dev_stats_item *ptr,
index 3dfd8db0e2439b3eb9b2cd387fb7f78a2bafeddc..0165b8672f099c49f96400fc0c87cc0b7cfc4532 100644 (file)
@@ -772,7 +772,8 @@ next_slot:
                                btrfs_file_extent_num_bytes(leaf, fi);
                } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                        extent_end = key.offset +
-                               btrfs_file_extent_inline_len(leaf, fi);
+                               btrfs_file_extent_inline_len(leaf,
+                                                    path->slots[0], fi);
                } else {
                        WARN_ON(1);
                        extent_end = search_start;
index 3b6598783be9e6dda1c6e9d4478cbbe212e41893..ad961a598c99b38660a802d3afc8fd8839619ac8 100644 (file)
@@ -1281,7 +1281,8 @@ next_slot:
                        nocow = 1;
                } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                        extent_end = found_key.offset +
-                               btrfs_file_extent_inline_len(leaf, fi);
+                               btrfs_file_extent_inline_len(leaf,
+                                                    path->slots[0], fi);
                        extent_end = ALIGN(extent_end, root->sectorsize);
                } else {
                        BUG_ON(1);
@@ -4023,7 +4024,7 @@ search_again:
                                    btrfs_file_extent_num_bytes(leaf, fi);
                        } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                item_end += btrfs_file_extent_inline_len(leaf,
-                                                                        fi);
+                                                        path->slots[0], fi);
                        }
                        item_end--;
                }
@@ -4093,6 +4094,12 @@ search_again:
                                        inode_sub_bytes(inode, item_end + 1 -
                                                        new_size);
                                }
+
+                               /*
+                                * update the ram bytes to properly reflect
+                                * the new size of our item
+                                */
+                               btrfs_set_file_extent_ram_bytes(leaf, fi, size);
                                size =
                                    btrfs_file_extent_calc_inline_size(size);
                                btrfs_truncate_item(root, path, size, 1);
@@ -6162,7 +6169,7 @@ again:
                       btrfs_file_extent_num_bytes(leaf, item);
        } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
                size_t size;
-               size = btrfs_file_extent_inline_len(leaf, item);
+               size = btrfs_file_extent_inline_len(leaf, path->slots[0], item);
                extent_end = ALIGN(extent_start + size, root->sectorsize);
        }
 next:
@@ -6231,7 +6238,7 @@ next:
                        goto out;
                }
 
-               size = btrfs_file_extent_inline_len(leaf, item);
+               size = btrfs_file_extent_inline_len(leaf, path->slots[0], item);
                extent_offset = page_offset(page) + pg_offset - extent_start;
                copy_size = min_t(u64, PAGE_CACHE_SIZE - pg_offset,
                                size - extent_offset);
index 4eed002b7cf66ec9eeb81cba380f96f647750e4f..6efd70d3b64f785e23d0bb3323d4905825406c62 100644 (file)
@@ -249,7 +249,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
                            BTRFS_FILE_EXTENT_INLINE) {
                                printk(KERN_INFO "\t\tinline extent data "
                                       "size %u\n",
-                                      btrfs_file_extent_inline_len(l, fi));
+                                      btrfs_file_extent_inline_len(l, i, fi));
                                break;
                        }
                        printk(KERN_INFO "\t\textent data disk bytenr %llu "
index 85259cba784aaed6a4f31501e2c5ece102028d7d..730dce395858a6e4c86a43b4a8fa41779d719e0d 100644 (file)
@@ -1377,7 +1377,7 @@ static int read_symlink(struct btrfs_root *root,
        BUG_ON(compression);
 
        off = btrfs_file_extent_inline_start(ei);
-       len = btrfs_file_extent_inline_len(path->nodes[0], ei);
+       len = btrfs_file_extent_inline_len(path->nodes[0], path->slots[0], ei);
 
        ret = fs_path_add_from_extent_buffer(dest, path->nodes[0], off, len);
 
@@ -4207,7 +4207,8 @@ static int send_write_or_clone(struct send_ctx *sctx,
                        struct btrfs_file_extent_item);
        type = btrfs_file_extent_type(path->nodes[0], ei);
        if (type == BTRFS_FILE_EXTENT_INLINE) {
-               len = btrfs_file_extent_inline_len(path->nodes[0], ei);
+               len = btrfs_file_extent_inline_len(path->nodes[0],
+                                                  path->slots[0], ei);
                /*
                 * it is possible the inline item won't cover the whole page,
                 * but there may be items after this page.  Make
@@ -4448,7 +4449,8 @@ static int get_last_extent(struct send_ctx *sctx, u64 offset)
                            struct btrfs_file_extent_item);
        type = btrfs_file_extent_type(path->nodes[0], fi);
        if (type == BTRFS_FILE_EXTENT_INLINE) {
-               u64 size = btrfs_file_extent_inline_len(path->nodes[0], fi);
+               u64 size = btrfs_file_extent_inline_len(path->nodes[0],
+                                                       path->slots[0], fi);
                extent_end = ALIGN(key.offset + size,
                                   sctx->send_root->sectorsize);
        } else {
@@ -4482,7 +4484,8 @@ static int maybe_send_hole(struct send_ctx *sctx, struct btrfs_path *path,
                            struct btrfs_file_extent_item);
        type = btrfs_file_extent_type(path->nodes[0], fi);
        if (type == BTRFS_FILE_EXTENT_INLINE) {
-               u64 size = btrfs_file_extent_inline_len(path->nodes[0], fi);
+               u64 size = btrfs_file_extent_inline_len(path->nodes[0],
+                                                       path->slots[0], fi);
                extent_end = ALIGN(key->offset + size,
                                   sctx->send_root->sectorsize);
        } else {
index b142b6dc96c3bee7c9535f941a73afba18808d66..39d83da03e0398db90428e52b98524982da469b5 100644 (file)
@@ -570,7 +570,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
                if (btrfs_file_extent_disk_bytenr(eb, item) == 0)
                        nbytes = 0;
        } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
-               size = btrfs_file_extent_inline_len(eb, item);
+               size = btrfs_file_extent_inline_len(eb, slot, item);
                nbytes = btrfs_file_extent_ram_bytes(eb, item);
                extent_end = ALIGN(start + size, root->sectorsize);
        } else {
@@ -3367,7 +3367,9 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
                                        struct btrfs_file_extent_item);
                if (btrfs_file_extent_type(src, extent) ==
                    BTRFS_FILE_EXTENT_INLINE) {
-                       len = btrfs_file_extent_inline_len(src, extent);
+                       len = btrfs_file_extent_inline_len(src,
+                                                          src_path->slots[0],
+                                                          extent);
                        *last_extent = ALIGN(key.offset + len,
                                             log->sectorsize);
                } else {
@@ -3431,7 +3433,7 @@ fill_holes:
                extent = btrfs_item_ptr(src, i, struct btrfs_file_extent_item);
                if (btrfs_file_extent_type(src, extent) ==
                    BTRFS_FILE_EXTENT_INLINE) {
-                       len = btrfs_file_extent_inline_len(src, extent);
+                       len = btrfs_file_extent_inline_len(src, i, extent);
                        extent_end = ALIGN(key.offset + len, log->sectorsize);
                } else {
                        len = btrfs_file_extent_num_bytes(src, extent);