This is a note to let you know that I've just added the patch titled Btrfs: fix scrub_print_warning to handle skinny metadata extents to the 3.14-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: btrfs-fix-scrub_print_warning-to-handle-skinny-metadata-extents.patch and it can be found in the queue-3.14 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From 6eda71d0c030af0fc2f68aaa676e6d445600855b Mon Sep 17 00:00:00 2001 From: Liu Bo <bo.li.liu@xxxxxxxxxx> Date: Mon, 9 Jun 2014 10:54:07 +0800 Subject: Btrfs: fix scrub_print_warning to handle skinny metadata extents From: Liu Bo <bo.li.liu@xxxxxxxxxx> commit 6eda71d0c030af0fc2f68aaa676e6d445600855b upstream. The skinny extents are intepreted incorrectly in scrub_print_warning(), and end up hitting the BUG() in btrfs_extent_inline_ref_size. Reported-by: Konstantinos Skarlatos <k.skarlatos@xxxxxxxxx> Signed-off-by: Liu Bo <bo.li.liu@xxxxxxxxxx> Signed-off-by: Chris Mason <clm@xxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- fs/btrfs/backref.c | 30 +++++++++++++++++++----------- fs/btrfs/backref.h | 4 ++-- fs/btrfs/scrub.c | 5 +++-- 3 files changed, 24 insertions(+), 15 deletions(-) --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -1412,9 +1412,10 @@ int extent_from_logical(struct btrfs_fs_ * returns <0 on error */ static int __get_extent_inline_ref(unsigned long *ptr, struct extent_buffer *eb, - struct btrfs_extent_item *ei, u32 item_size, - struct btrfs_extent_inline_ref **out_eiref, - int *out_type) + struct btrfs_key *key, + struct btrfs_extent_item *ei, u32 item_size, + struct btrfs_extent_inline_ref **out_eiref, + int *out_type) { unsigned long end; u64 flags; @@ -1424,9 +1425,16 @@ static int __get_extent_inline_ref(unsig /* first call */ flags = btrfs_extent_flags(eb, ei); if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { - info = (struct btrfs_tree_block_info *)(ei + 1); - *out_eiref = - (struct btrfs_extent_inline_ref *)(info + 1); + if (key->type == BTRFS_METADATA_ITEM_KEY) { + /* a skinny metadata extent */ + *out_eiref = + (struct btrfs_extent_inline_ref *)(ei + 1); + } else { + WARN_ON(key->type != BTRFS_EXTENT_ITEM_KEY); + info = (struct btrfs_tree_block_info *)(ei + 1); + *out_eiref = + (struct btrfs_extent_inline_ref *)(info + 1); + } } else { *out_eiref = (struct btrfs_extent_inline_ref *)(ei + 1); } @@ -1436,7 +1444,7 @@ static int __get_extent_inline_ref(unsig } end = (unsigned long)ei + item_size; - *out_eiref = (struct btrfs_extent_inline_ref *)*ptr; + *out_eiref = (struct btrfs_extent_inline_ref *)(*ptr); *out_type = btrfs_extent_inline_ref_type(eb, *out_eiref); *ptr += btrfs_extent_inline_ref_size(*out_type); @@ -1455,8 +1463,8 @@ static int __get_extent_inline_ref(unsig * <0 on error. */ int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, - struct btrfs_extent_item *ei, u32 item_size, - u64 *out_root, u8 *out_level) + struct btrfs_key *key, struct btrfs_extent_item *ei, + u32 item_size, u64 *out_root, u8 *out_level) { int ret; int type; @@ -1467,8 +1475,8 @@ int tree_backref_for_extent(unsigned lon return 1; while (1) { - ret = __get_extent_inline_ref(ptr, eb, ei, item_size, - &eiref, &type); + ret = __get_extent_inline_ref(ptr, eb, key, ei, item_size, + &eiref, &type); if (ret < 0) return ret; --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h @@ -40,8 +40,8 @@ int extent_from_logical(struct btrfs_fs_ u64 *flags); int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, - struct btrfs_extent_item *ei, u32 item_size, - u64 *out_root, u8 *out_level); + struct btrfs_key *key, struct btrfs_extent_item *ei, + u32 item_size, u64 *out_root, u8 *out_level); int iterate_extent_inodes(struct btrfs_fs_info *fs_info, u64 extent_item_objectid, --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -577,8 +577,9 @@ static void scrub_print_warning(const ch if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { do { - ret = tree_backref_for_extent(&ptr, eb, ei, item_size, - &ref_root, &ref_level); + ret = tree_backref_for_extent(&ptr, eb, &found_key, ei, + item_size, &ref_root, + &ref_level); printk_in_rcu(KERN_WARNING "BTRFS: %s at logical %llu on dev %s, " "sector %llu: metadata %s (level %d) in tree " Patches currently in stable-queue which might be from bo.li.liu@xxxxxxxxxx are queue-3.14/btrfs-fix-null-pointer-crash-of-deleting-a-seed-device.patch queue-3.14/btrfs-fix-scrub_print_warning-to-handle-skinny-metadata-extents.patch queue-3.14/btrfs-use-right-type-to-get-real-comparison.patch queue-3.14/btrfs-mark-mapping-with-error-flag-to-report-errors-to-userspace.patch -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html