From: Greg Kroah-Hartman Date: Sun, 5 Jun 2016 21:47:56 +0000 (-0700) Subject: 4.5-stable patches X-Git-Tag: v3.14.72~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9c28119d662a2c38e2a381f5602f19724e2cc13a;p=thirdparty%2Fkernel%2Fstable-queue.git 4.5-stable patches added patches: btrfs-add-check-to-sysfs-handler-of-label.patch btrfs-add-read-only-check-to-sysfs-handler-of-features.patch btrfs-add-write-protection-to-set_features-ioctl.patch btrfs-allow-balancing-to-dup-with-multi-device.patch btrfs-avoid-overflowing-f_bfree.patch btrfs-bugfix-handle-fs_ioc32_-getflags-setflags-getversion-in-btrfs_ioctl.patch btrfs-do-not-create-empty-block-group-if-we-have-allocated-data.patch btrfs-fix-divide-error-upon-chunk-s-stripe_len.patch btrfs-fix-empty-symlink-after-creating-symlink-and-fsync-parent-dir.patch btrfs-fix-for-incorrect-directory-entries-after-fsync-log-replay.patch btrfs-fix-fspath-error-deallocation.patch btrfs-fix-int32-overflow-in-shrink_delalloc.patch btrfs-fix-lock-dep-warning-move-scratch-dev-out-of-device_list_mutex-and-uuid_mutex.patch btrfs-fix-lock-dep-warning-move-scratch-super-outside-of-chunk_mutex.patch btrfs-fix-memory-leak-during-raid-5-6-device-replacement.patch btrfs-fix-mixed-block-count-of-available-space.patch btrfs-fix-unexpected-return-value-of-fiemap.patch btrfs-make-state-preallocation-more-speculative-in-__set_extent_bit.patch btrfs-pass-the-right-error-code-to-the-btrfs_std_error.patch btrfs-remove-bug_on-s-in-btrfs_map_block.patch btrfs-scrub-set-bbio-to-null-before-calling-btrfs_map_block.patch --- diff --git a/queue-4.5/btrfs-add-check-to-sysfs-handler-of-label.patch b/queue-4.5/btrfs-add-check-to-sysfs-handler-of-label.patch new file mode 100644 index 00000000000..4977431d3bc --- /dev/null +++ b/queue-4.5/btrfs-add-check-to-sysfs-handler-of-label.patch @@ -0,0 +1,31 @@ +From 66ac9fe7bacf9fa76c472efc7a7aaa590c7bce6a Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Tue, 26 Apr 2016 16:03:57 +0200 +Subject: btrfs: add check to sysfs handler of label + +From: David Sterba + +commit 66ac9fe7bacf9fa76c472efc7a7aaa590c7bce6a upstream. + +Add a sanity check for the fs_info as we will dereference it, similar to +what the 'store features' handler does. + +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/sysfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/btrfs/sysfs.c ++++ b/fs/btrfs/sysfs.c +@@ -377,6 +377,9 @@ static ssize_t btrfs_label_store(struct + struct btrfs_fs_info *fs_info = to_fs_info(kobj); + size_t p_len; + ++ if (!fs_info) ++ return -EPERM; ++ + if (fs_info->sb->s_flags & MS_RDONLY) + return -EROFS; + diff --git a/queue-4.5/btrfs-add-read-only-check-to-sysfs-handler-of-features.patch b/queue-4.5/btrfs-add-read-only-check-to-sysfs-handler-of-features.patch new file mode 100644 index 00000000000..d7f853df123 --- /dev/null +++ b/queue-4.5/btrfs-add-read-only-check-to-sysfs-handler-of-features.patch @@ -0,0 +1,31 @@ +From ee6111386a1b304f8bf589d36810d53e3b27ee20 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jan 2015 18:43:31 +0100 +Subject: btrfs: add read-only check to sysfs handler of features + +From: David Sterba + +commit ee6111386a1b304f8bf589d36810d53e3b27ee20 upstream. + +We don't want to trigger the change on a read-only filesystem, similar +to what the label handler does. + +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/sysfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/btrfs/sysfs.c ++++ b/fs/btrfs/sysfs.c +@@ -120,6 +120,9 @@ static ssize_t btrfs_feature_attr_store( + if (!fs_info) + return -EPERM; + ++ if (fs_info->sb->s_flags & MS_RDONLY) ++ return -EROFS; ++ + ret = kstrtoul(skip_spaces(buf), 0, &val); + if (ret) + return ret; diff --git a/queue-4.5/btrfs-add-write-protection-to-set_features-ioctl.patch b/queue-4.5/btrfs-add-write-protection-to-set_features-ioctl.patch new file mode 100644 index 00000000000..b4fce03abc3 --- /dev/null +++ b/queue-4.5/btrfs-add-write-protection-to-set_features-ioctl.patch @@ -0,0 +1,51 @@ +From 7ab19625a911f7568ec85302e3aa7a64186006c8 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Wed, 4 May 2016 11:32:00 +0200 +Subject: btrfs: add write protection to SET_FEATURES ioctl + +From: David Sterba + +commit 7ab19625a911f7568ec85302e3aa7a64186006c8 upstream. + +Perform the want_write check if we get far enough to do any writes. + +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/ioctl.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -5397,9 +5397,15 @@ static int btrfs_ioctl_set_features(stru + if (ret) + return ret; + ++ ret = mnt_want_write_file(file); ++ if (ret) ++ return ret; ++ + trans = btrfs_start_transaction(root, 0); +- if (IS_ERR(trans)) +- return PTR_ERR(trans); ++ if (IS_ERR(trans)) { ++ ret = PTR_ERR(trans); ++ goto out_drop_write; ++ } + + spin_lock(&root->fs_info->super_lock); + newflags = btrfs_super_compat_flags(super_block); +@@ -5418,7 +5424,11 @@ static int btrfs_ioctl_set_features(stru + btrfs_set_super_incompat_flags(super_block, newflags); + spin_unlock(&root->fs_info->super_lock); + +- return btrfs_commit_transaction(trans, root); ++ ret = btrfs_commit_transaction(trans, root); ++out_drop_write: ++ mnt_drop_write_file(file); ++ ++ return ret; + } + + long btrfs_ioctl(struct file *file, unsigned int diff --git a/queue-4.5/btrfs-allow-balancing-to-dup-with-multi-device.patch b/queue-4.5/btrfs-allow-balancing-to-dup-with-multi-device.patch new file mode 100644 index 00000000000..8a40f969524 --- /dev/null +++ b/queue-4.5/btrfs-allow-balancing-to-dup-with-multi-device.patch @@ -0,0 +1,45 @@ +From 88be159c905a2b4f6d59afa352bef410afb6af02 Mon Sep 17 00:00:00 2001 +From: "Austin S. Hemmelgarn" +Date: Wed, 23 Mar 2016 14:22:59 -0400 +Subject: btrfs: allow balancing to dup with multi-device + +From: Austin S. Hemmelgarn + +commit 88be159c905a2b4f6d59afa352bef410afb6af02 upstream. + +Currently, we don't allow the user to try and rebalance to a dup profile +on a multi-device filesystem. In most cases, this is a perfectly sensible +restriction as raid1 uses the same amount of space and provides better +protection. + +However, when reshaping a multi-device filesystem down to a single device +filesystem, this requires the user to convert metadata and system chunks +to single profile before deleting devices, and then convert again to dup, +which leaves a period of time where metadata integrity is reduced. + +This patch removes the single-device-only restriction from converting to +dup profile to remove this potential data integrity reduction. + +Signed-off-by: Austin S. Hemmelgarn +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/volumes.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -3699,10 +3699,8 @@ int btrfs_balance(struct btrfs_balance_c + num_devices--; + } + btrfs_dev_replace_unlock(&fs_info->dev_replace); +- allowed = BTRFS_AVAIL_ALLOC_BIT_SINGLE; +- if (num_devices == 1) +- allowed |= BTRFS_BLOCK_GROUP_DUP; +- else if (num_devices > 1) ++ allowed = BTRFS_AVAIL_ALLOC_BIT_SINGLE | BTRFS_BLOCK_GROUP_DUP; ++ if (num_devices > 1) + allowed |= (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1); + if (num_devices > 2) + allowed |= BTRFS_BLOCK_GROUP_RAID5; diff --git a/queue-4.5/btrfs-avoid-overflowing-f_bfree.patch b/queue-4.5/btrfs-avoid-overflowing-f_bfree.patch new file mode 100644 index 00000000000..63ea546f2f4 --- /dev/null +++ b/queue-4.5/btrfs-avoid-overflowing-f_bfree.patch @@ -0,0 +1,36 @@ +From 41b34accb265e3a20211a7a8ef3625678f1c6ec7 Mon Sep 17 00:00:00 2001 +From: Luis de Bethencourt +Date: Wed, 30 Mar 2016 23:18:14 +0100 +Subject: btrfs: avoid overflowing f_bfree + +From: Luis de Bethencourt + +commit 41b34accb265e3a20211a7a8ef3625678f1c6ec7 upstream. + +Since mixed block groups accounting isn't byte-accurate and f_bree is an +unsigned integer, it could overflow. Avoid this. + +Signed-off-by: Luis de Bethencourt +Suggested-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/super.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -2073,7 +2073,11 @@ static int btrfs_statfs(struct dentry *d + + /* Account global block reserve as used, it's in logical size already */ + spin_lock(&block_rsv->lock); +- buf->f_bfree -= block_rsv->size >> bits; ++ /* Mixed block groups accounting is not byte-accurate, avoid overflow */ ++ if (buf->f_bfree >= block_rsv->size >> bits) ++ buf->f_bfree -= block_rsv->size >> bits; ++ else ++ buf->f_bfree = 0; + spin_unlock(&block_rsv->lock); + + buf->f_bavail = div_u64(total_free_data, factor); diff --git a/queue-4.5/btrfs-bugfix-handle-fs_ioc32_-getflags-setflags-getversion-in-btrfs_ioctl.patch b/queue-4.5/btrfs-bugfix-handle-fs_ioc32_-getflags-setflags-getversion-in-btrfs_ioctl.patch new file mode 100644 index 00000000000..b09033bddef --- /dev/null +++ b/queue-4.5/btrfs-bugfix-handle-fs_ioc32_-getflags-setflags-getversion-in-btrfs_ioctl.patch @@ -0,0 +1,85 @@ +From 4c63c2454eff996c5e27991221106eb511f7db38 Mon Sep 17 00:00:00 2001 +From: Luke Dashjr +Date: Thu, 29 Oct 2015 08:22:21 +0000 +Subject: btrfs: bugfix: handle FS_IOC32_{GETFLAGS,SETFLAGS,GETVERSION} in btrfs_ioctl + +From: Luke Dashjr + +commit 4c63c2454eff996c5e27991221106eb511f7db38 upstream. + +32-bit ioctl uses these rather than the regular FS_IOC_* versions. They can +be handled in btrfs using the same code. Without this, 32-bit {ch,ls}attr +fail. + +Signed-off-by: Luke Dashjr +Reviewed-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/ctree.h | 1 + + fs/btrfs/file.c | 2 +- + fs/btrfs/inode.c | 2 +- + fs/btrfs/ioctl.c | 21 +++++++++++++++++++++ + 4 files changed, 24 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -4089,6 +4089,7 @@ void btrfs_test_inode_set_ops(struct ino + + /* ioctl.c */ + long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); ++long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); + void btrfs_update_iflags(struct inode *inode); + void btrfs_inherit_iflags(struct inode *inode, struct inode *dir); + int btrfs_is_empty_uuid(u8 *uuid); +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -2931,7 +2931,7 @@ const struct file_operations btrfs_file_ + .fallocate = btrfs_fallocate, + .unlocked_ioctl = btrfs_ioctl, + #ifdef CONFIG_COMPAT +- .compat_ioctl = btrfs_ioctl, ++ .compat_ioctl = btrfs_compat_ioctl, + #endif + .copy_file_range = btrfs_copy_file_range, + .clone_file_range = btrfs_clone_file_range, +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -10088,7 +10088,7 @@ static const struct file_operations btrf + .iterate = btrfs_real_readdir, + .unlocked_ioctl = btrfs_ioctl, + #ifdef CONFIG_COMPAT +- .compat_ioctl = btrfs_ioctl, ++ .compat_ioctl = btrfs_compat_ioctl, + #endif + .release = btrfs_release_file, + .fsync = btrfs_sync_file, +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -5555,3 +5555,24 @@ long btrfs_ioctl(struct file *file, unsi + + return -ENOTTY; + } ++ ++#ifdef CONFIG_COMPAT ++long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ switch (cmd) { ++ case FS_IOC32_GETFLAGS: ++ cmd = FS_IOC_GETFLAGS; ++ break; ++ case FS_IOC32_SETFLAGS: ++ cmd = FS_IOC_SETFLAGS; ++ break; ++ case FS_IOC32_GETVERSION: ++ cmd = FS_IOC_GETVERSION; ++ break; ++ default: ++ return -ENOIOCTLCMD; ++ } ++ ++ return btrfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); ++} ++#endif diff --git a/queue-4.5/btrfs-do-not-create-empty-block-group-if-we-have-allocated-data.patch b/queue-4.5/btrfs-do-not-create-empty-block-group-if-we-have-allocated-data.patch new file mode 100644 index 00000000000..ebabb0b169c --- /dev/null +++ b/queue-4.5/btrfs-do-not-create-empty-block-group-if-we-have-allocated-data.patch @@ -0,0 +1,61 @@ +From cf25ce518e8ef9d59b292e51193bed2b023a32da Mon Sep 17 00:00:00 2001 +From: Liu Bo +Date: Mon, 14 Dec 2015 18:29:32 -0800 +Subject: Btrfs: do not create empty block group if we have allocated data + +From: Liu Bo + +commit cf25ce518e8ef9d59b292e51193bed2b023a32da upstream. + +Now we force to create empty block group to keep data profile alive, +however, in the below example, we eventually get an empty block group +while we're trying to get more space for other types (metadata/system), + +- Before, +block group "A": size=2G, used=1.2G +block group "B": size=2G, used=512M + +- After "btrfs balance start -dusage=50 mount_point", +block group "A": size=2G, used=(1.2+0.5)G +block group "C": size=2G, used=0 + +Since there is no data in block group C, it won't be deleted +automatically and we have to get the unused 2G until the next mount. + +Balance itself just moves data and doesn't remove data, so it's safe +to not create such a empty block group if we already have data + allocated in other block groups. + +Signed-off-by: Liu Bo +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/volumes.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -3401,6 +3401,7 @@ static int __btrfs_balance(struct btrfs_ + u32 count_meta = 0; + u32 count_sys = 0; + int chunk_reserved = 0; ++ u64 bytes_used = 0; + + /* step one make some room on all the devices */ + devices = &fs_info->fs_devices->devices; +@@ -3539,7 +3540,13 @@ again: + goto loop; + } + +- if ((chunk_type & BTRFS_BLOCK_GROUP_DATA) && !chunk_reserved) { ++ ASSERT(fs_info->data_sinfo); ++ spin_lock(&fs_info->data_sinfo->lock); ++ bytes_used = fs_info->data_sinfo->bytes_used; ++ spin_unlock(&fs_info->data_sinfo->lock); ++ ++ if ((chunk_type & BTRFS_BLOCK_GROUP_DATA) && ++ !chunk_reserved && !bytes_used) { + trans = btrfs_start_transaction(chunk_root, 0); + if (IS_ERR(trans)) { + mutex_unlock(&fs_info->delete_unused_bgs_mutex); diff --git a/queue-4.5/btrfs-fix-divide-error-upon-chunk-s-stripe_len.patch b/queue-4.5/btrfs-fix-divide-error-upon-chunk-s-stripe_len.patch new file mode 100644 index 00000000000..297186506bd --- /dev/null +++ b/queue-4.5/btrfs-fix-divide-error-upon-chunk-s-stripe_len.patch @@ -0,0 +1,65 @@ +From 3d8da67817606380fdadfa483d4dba5c3a5446c6 Mon Sep 17 00:00:00 2001 +From: Liu Bo +Date: Tue, 26 Apr 2016 17:53:31 -0700 +Subject: Btrfs: fix divide error upon chunk's stripe_len + +From: Liu Bo + +commit 3d8da67817606380fdadfa483d4dba5c3a5446c6 upstream. + +The struct 'map_lookup' uses type int for @stripe_len, while +btrfs_chunk_stripe_len() can return a u64 value, and it may end up with +@stripe_len being undefined value and it can lead to 'divide error' in + __btrfs_map_block(). + +This changes 'map_lookup' to use type u64 for stripe_len, also right now +we only use BTRFS_STRIPE_LEN for stripe_len, so this adds a valid checker for +BTRFS_STRIPE_LEN. + +Reported-by: Vegard Nossum +Reported-by: Quentin Casasnovas +Signed-off-by: Liu Bo +Reviewed-by: David Sterba +[ folded division fix to scrub_raid56_parity ] +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/scrub.c | 2 +- + fs/btrfs/volumes.c | 2 +- + fs/btrfs/volumes.h | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -2858,7 +2858,7 @@ static noinline_for_stack int scrub_raid + int extent_mirror_num; + int stop_loop = 0; + +- nsectors = map->stripe_len / root->sectorsize; ++ nsectors = div_u64(map->stripe_len, root->sectorsize); + bitmap_len = scrub_calc_parity_bitmap_len(nsectors); + sparity = kzalloc(sizeof(struct scrub_parity) + 2 * bitmap_len, + GFP_NOFS); +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -6249,7 +6249,7 @@ static int read_one_chunk(struct btrfs_r + "invalid chunk length %llu", length); + return -EIO; + } +- if (!is_power_of_2(stripe_len)) { ++ if (!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN) { + btrfs_err(root->fs_info, "invalid chunk stripe length: %llu", + stripe_len); + return -EIO; +--- a/fs/btrfs/volumes.h ++++ b/fs/btrfs/volumes.h +@@ -347,7 +347,7 @@ struct map_lookup { + u64 type; + int io_align; + int io_width; +- int stripe_len; ++ u64 stripe_len; + int sector_size; + int num_stripes; + int sub_stripes; diff --git a/queue-4.5/btrfs-fix-empty-symlink-after-creating-symlink-and-fsync-parent-dir.patch b/queue-4.5/btrfs-fix-empty-symlink-after-creating-symlink-and-fsync-parent-dir.patch new file mode 100644 index 00000000000..b4355b7c7d6 --- /dev/null +++ b/queue-4.5/btrfs-fix-empty-symlink-after-creating-symlink-and-fsync-parent-dir.patch @@ -0,0 +1,49 @@ +From 3f9749f6e9edcf8ec569fb542efc3be35e06e84a Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Mon, 25 Apr 2016 04:45:02 +0100 +Subject: Btrfs: fix empty symlink after creating symlink and fsync parent dir + +From: Filipe Manana + +commit 3f9749f6e9edcf8ec569fb542efc3be35e06e84a upstream. + +If we create a symlink, fsync its parent directory, crash/power fail and +mount the filesystem, we end up with an empty symlink, which not only is +useless it's also not allowed in linux (the man page symlink(2) is well +explicit about that). So we just need to make sure to fully log an inode +if it's a symlink, to ensure its inline extent gets logged, ensuring the +same behaviour as ext3, ext4, xfs, reiserfs, f2fs, nilfs2, etc. + +Example reproducer: + + $ mkfs.btrfs -f /dev/sdb + $ mount /dev/sdb /mnt + $ mkdir /mnt/testdir + $ sync + $ ln -s /mnt/foo /mnt/testdir/bar + $ xfs_io -c fsync /mnt/testdir + + $ mount /dev/sdb /mnt + $ readlink /mnt/testdir/bar + + +A test case for fstests follows soon. + +Signed-off-by: Filipe Manana +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-log.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -5157,7 +5157,7 @@ process_leaf: + } + + ctx->log_new_dentries = false; +- if (type == BTRFS_FT_DIR) ++ if (type == BTRFS_FT_DIR || type == BTRFS_FT_SYMLINK) + log_mode = LOG_INODE_ALL; + btrfs_release_path(path); + ret = btrfs_log_inode(trans, root, di_inode, diff --git a/queue-4.5/btrfs-fix-for-incorrect-directory-entries-after-fsync-log-replay.patch b/queue-4.5/btrfs-fix-for-incorrect-directory-entries-after-fsync-log-replay.patch new file mode 100644 index 00000000000..a5b6522f75d --- /dev/null +++ b/queue-4.5/btrfs-fix-for-incorrect-directory-entries-after-fsync-log-replay.patch @@ -0,0 +1,128 @@ +From 657ed1aa4898c8304500e0d13f240d5a67e8be5f Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Wed, 6 Apr 2016 17:11:56 +0100 +Subject: Btrfs: fix for incorrect directory entries after fsync log replay +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Filipe Manana + +commit 657ed1aa4898c8304500e0d13f240d5a67e8be5f upstream. + +If we move a directory to a new parent and later log that parent and don't +explicitly log the old parent, when we replay the log we can end up with +entries for the moved directory in both the old and new parent directories. +Besides being ilegal to have directories with multiple hard links in linux, +it also resulted in the leaving the inode item with a link count of 1. +A similar issue also happens if we move a regular file - after the log tree +is replayed the file has a link in both the old and new parent directories, +when it should be only at the new directory. + +Sample reproducer: + + $ mkfs.btrfs -f /dev/sdc + $ mount /dev/sdc /mnt + $ mkdir /mnt/x + $ mkdir /mnt/y + $ touch /mnt/x/foo + $ mkdir /mnt/y/z + $ sync + $ ln /mnt/x/foo /mnt/x/bar + $ mv /mnt/y/z /mnt/x/z + < power fail > + $ mount /dev/sdc /mnt + $ ls -1Ri /mnt + /mnt: + 257 x + 258 y + + /mnt/x: + 259 bar + 259 foo + 260 z + + /mnt/x/z: + + /mnt/y: + 260 z + + /mnt/y/z: + + $ umount /dev/sdc + $ btrfs check /dev/sdc + Checking filesystem on /dev/sdc + UUID: a67e2c4a-a4b4-4fdc-b015-9d9af1e344be + checking extents + checking free space cache + checking fs roots + root 5 inode 260 errors 2000, link count wrong + unresolved ref dir 257 index 4 namelen 1 name z filetype 2 errors 0 + unresolved ref dir 258 index 2 namelen 1 name z filetype 2 errors 0 + (...) + +Attempting to remove the directory becomes impossible: + + $ mount /dev/sdc /mnt + $ rmdir /mnt/y/z + $ ls -lh /mnt/y + ls: cannot access /mnt/y/z: No such file or directory + total 0 + d????????? ? ? ? ? ? z + $ rmdir /mnt/x/z + rmdir: failed to remove ‘/mnt/x/z’: Stale file handle + $ ls -lh /mnt/x + ls: cannot access /mnt/x/z: Stale file handle + total 0 + -rw-r--r-- 2 root root 0 Apr 6 18:06 bar + -rw-r--r-- 2 root root 0 Apr 6 18:06 foo + d????????? ? ? ? ? ? z + +So make sure that on rename we set the last_unlink_trans value for our +inode, even if it's a directory, to the value of the current transaction's +ID and that if the new parent directory is logged that we fallback to a +transaction commit. + +A test case for fstests is being submitted as well. + +Signed-off-by: Filipe Manana +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-log.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -5277,11 +5277,16 @@ static int btrfs_log_all_parents(struct + if (IS_ERR(dir_inode)) + continue; + ++ if (ctx) ++ ctx->log_new_dentries = false; + ret = btrfs_log_inode(trans, root, dir_inode, + LOG_INODE_ALL, 0, LLONG_MAX, ctx); + if (!ret && + btrfs_must_commit_transaction(trans, dir_inode)) + ret = 1; ++ if (!ret && ctx && ctx->log_new_dentries) ++ ret = log_new_dir_dentries(trans, root, ++ dir_inode, ctx); + iput(dir_inode); + if (ret) + goto out; +@@ -5651,11 +5656,9 @@ void btrfs_record_unlink_dir(struct btrf + * into the file. When the file is logged we check it and + * don't log the parents if the file is fully on disk. + */ +- if (S_ISREG(inode->i_mode)) { +- mutex_lock(&BTRFS_I(inode)->log_mutex); +- BTRFS_I(inode)->last_unlink_trans = trans->transid; +- mutex_unlock(&BTRFS_I(inode)->log_mutex); +- } ++ mutex_lock(&BTRFS_I(inode)->log_mutex); ++ BTRFS_I(inode)->last_unlink_trans = trans->transid; ++ mutex_unlock(&BTRFS_I(inode)->log_mutex); + + /* + * if this directory was already logged any new diff --git a/queue-4.5/btrfs-fix-fspath-error-deallocation.patch b/queue-4.5/btrfs-fix-fspath-error-deallocation.patch new file mode 100644 index 00000000000..01394eb678a --- /dev/null +++ b/queue-4.5/btrfs-fix-fspath-error-deallocation.patch @@ -0,0 +1,39 @@ +From 72928f2476d08c79f132b4f44a17c9a011dd98e3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Vincent=20Stehl=C3=A9?= +Date: Tue, 10 May 2016 14:56:20 +0200 +Subject: Btrfs: fix fspath error deallocation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Vincent Stehlé + +commit 72928f2476d08c79f132b4f44a17c9a011dd98e3 upstream. + +Make sure to deallocate fspath with vfree() in case of error in +init_ipath(). + +fspath is allocated with vmalloc() in init_data_container() since +commit 425d17a290c0 ("Btrfs: use larger limit for translation of logical to +inode"). + +Signed-off-by: Vincent Stehlé +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/backref.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/backref.c ++++ b/fs/btrfs/backref.c +@@ -1995,7 +1995,7 @@ struct inode_fs_paths *init_ipath(s32 to + + ifp = kmalloc(sizeof(*ifp), GFP_NOFS); + if (!ifp) { +- kfree(fspath); ++ vfree(fspath); + return ERR_PTR(-ENOMEM); + } + diff --git a/queue-4.5/btrfs-fix-int32-overflow-in-shrink_delalloc.patch b/queue-4.5/btrfs-fix-int32-overflow-in-shrink_delalloc.patch new file mode 100644 index 00000000000..d82ca3b8e07 --- /dev/null +++ b/queue-4.5/btrfs-fix-int32-overflow-in-shrink_delalloc.patch @@ -0,0 +1,37 @@ +From 8eb0dfdbda3f56bf7d248ed87fcc383df114ecbb Mon Sep 17 00:00:00 2001 +From: Adam Borowski +Date: Sun, 8 May 2016 15:08:00 +0200 +Subject: btrfs: fix int32 overflow in shrink_delalloc(). + +From: Adam Borowski + +commit 8eb0dfdbda3f56bf7d248ed87fcc383df114ecbb upstream. + +UBSAN: Undefined behaviour in fs/btrfs/extent-tree.c:4623:21 +signed integer overflow: +10808 * 262144 cannot be represented in type 'int [8]' + +If 8192<=items<16384, we request a writeback of an insane number of pages +which is benign (everything will be written). But if items>=16384, the +space reservation won't be enough. + +Signed-off-by: Adam Borowski +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/extent-tree.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4620,7 +4620,7 @@ static void shrink_delalloc(struct btrfs + + /* Calc the number of the pages we need flush for space reservation */ + items = calc_reclaim_items_nr(root, to_reclaim); +- to_reclaim = items * EXTENT_SIZE_PER_ITEM; ++ to_reclaim = (u64)items * EXTENT_SIZE_PER_ITEM; + + trans = (struct btrfs_trans_handle *)current->journal_info; + block_rsv = &root->fs_info->delalloc_block_rsv; diff --git a/queue-4.5/btrfs-fix-lock-dep-warning-move-scratch-dev-out-of-device_list_mutex-and-uuid_mutex.patch b/queue-4.5/btrfs-fix-lock-dep-warning-move-scratch-dev-out-of-device_list_mutex-and-uuid_mutex.patch new file mode 100644 index 00000000000..d4921df334d --- /dev/null +++ b/queue-4.5/btrfs-fix-lock-dep-warning-move-scratch-dev-out-of-device_list_mutex-and-uuid_mutex.patch @@ -0,0 +1,191 @@ +From 779bf3fefa835cb52a07457c8acac6f2f66f2493 Mon Sep 17 00:00:00 2001 +From: Anand Jain +Date: Mon, 18 Apr 2016 16:51:23 +0800 +Subject: btrfs: fix lock dep warning, move scratch dev out of device_list_mutex and uuid_mutex + +From: Anand Jain + +commit 779bf3fefa835cb52a07457c8acac6f2f66f2493 upstream. + +When the replace target fails, the target device will be taken +out of fs device list, scratch + update_dev_time and freed. However +we could do the scratch + update_dev_time and free part after the +device has been taken out of device list, so that we don't have to +hold the device_list_mutex and uuid_mutex locks. + +Reported issue: + +[ 5375.718845] ====================================================== +[ 5375.718846] [ INFO: possible circular locking dependency detected ] +[ 5375.718849] 4.4.5-scst31x-debug-11+ #40 Not tainted +[ 5375.718849] ------------------------------------------------------- +[ 5375.718851] btrfs-health/4662 is trying to acquire lock: +[ 5375.718861] (sb_writers){.+.+.+}, at: [] __sb_start_write+0xb7/0xf0 +[ 5375.718862] +[ 5375.718862] but task is already holding lock: +[ 5375.718907] (&fs_devs->device_list_mutex){+.+.+.}, at: [] btrfs_destroy_dev_replace_tgtdev+0x3c/0x150 [btrfs] +[ 5375.718907] +[ 5375.718907] which lock already depends on the new lock. +[ 5375.718907] +[ 5375.718908] +[ 5375.718908] the existing dependency chain (in reverse order) is: +[ 5375.718911] +[ 5375.718911] -> #3 (&fs_devs->device_list_mutex){+.+.+.}: +[ 5375.718917] [] lock_acquire+0xce/0x1e0 +[ 5375.718921] [] mutex_lock_nested+0x69/0x3c0 +[ 5375.718940] [] btrfs_show_devname+0x36/0x210 [btrfs] +[ 5375.718945] [] show_vfsmnt+0x49/0x150 +[ 5375.718948] [] m_show+0x17/0x20 +[ 5375.718951] [] seq_read+0x2d8/0x3b0 +[ 5375.718955] [] __vfs_read+0x28/0xd0 +[ 5375.718959] [] vfs_read+0x86/0x130 +[ 5375.718962] [] SyS_read+0x49/0xa0 +[ 5375.718966] [] entry_SYSCALL_64_fastpath+0x16/0x7a +[ 5375.718968] +[ 5375.718968] -> #2 (namespace_sem){+++++.}: +[ 5375.718971] [] lock_acquire+0xce/0x1e0 +[ 5375.718974] [] down_write+0x49/0x80 +[ 5375.718977] [] lock_mount+0x43/0x1c0 +[ 5375.718979] [] do_add_mount+0x23/0xd0 +[ 5375.718982] [] do_mount+0x27b/0xe30 +[ 5375.718985] [] SyS_mount+0x8c/0xd0 +[ 5375.718988] [] entry_SYSCALL_64_fastpath+0x16/0x7a +[ 5375.718991] +[ 5375.718991] -> #1 (&sb->s_type->i_mutex_key#5){+.+.+.}: +[ 5375.718994] [] lock_acquire+0xce/0x1e0 +[ 5375.718996] [] mutex_lock_nested+0x69/0x3c0 +[ 5375.719001] [] path_openat+0x468/0x1360 +[ 5375.719004] [] do_filp_open+0x7e/0xe0 +[ 5375.719007] [] do_sys_open+0x12b/0x210 +[ 5375.719010] [] SyS_open+0x1e/0x20 +[ 5375.719013] [] entry_SYSCALL_64_fastpath+0x16/0x7a +[ 5375.719015] +[ 5375.719015] -> #0 (sb_writers){.+.+.+}: +[ 5375.719018] [] __lock_acquire+0x17ba/0x1ae0 +[ 5375.719021] [] lock_acquire+0xce/0x1e0 +[ 5375.719026] [] percpu_down_read+0x4f/0xa0 +[ 5375.719028] [] __sb_start_write+0xb7/0xf0 +[ 5375.719031] [] mnt_want_write+0x24/0x50 +[ 5375.719035] [] path_openat+0xd32/0x1360 +[ 5375.719037] [] do_filp_open+0x7e/0xe0 +[ 5375.719040] [] file_open_name+0xe4/0x130 +[ 5375.719043] [] filp_open+0x33/0x60 +[ 5375.719073] [] update_dev_time+0x16/0x40 [btrfs] +[ 5375.719099] [] btrfs_scratch_superblocks+0x4e/0x90 [btrfs] +[ 5375.719123] [] btrfs_destroy_dev_replace_tgtdev+0x65/0x150 [btrfs] +[ 5375.719150] [] btrfs_dev_replace_finishing+0x6b0/0x990 [btrfs] +[ 5375.719175] [] btrfs_dev_replace_start+0x33e/0x540 [btrfs] +[ 5375.719199] [] btrfs_auto_replace_start+0xf8/0x140 [btrfs] +[ 5375.719222] [] health_kthread+0x246/0x490 [btrfs] +[ 5375.719225] [] kthread+0xef/0x110 +[ 5375.719229] [] ret_from_fork+0x3f/0x70 +[ 5375.719230] +[ 5375.719230] other info that might help us debug this: +[ 5375.719230] +[ 5375.719233] Chain exists of: +[ 5375.719233] sb_writers --> namespace_sem --> &fs_devs->device_list_mutex +[ 5375.719233] +[ 5375.719234] Possible unsafe locking scenario: +[ 5375.719234] +[ 5375.719234] CPU0 CPU1 +[ 5375.719235] ---- ---- +[ 5375.719236] lock(&fs_devs->device_list_mutex); +[ 5375.719238] lock(namespace_sem); +[ 5375.719239] lock(&fs_devs->device_list_mutex); +[ 5375.719241] lock(sb_writers); +[ 5375.719241] +[ 5375.719241] *** DEADLOCK *** +[ 5375.719241] +[ 5375.719243] 4 locks held by btrfs-health/4662: +[ 5375.719266] #0: (&fs_info->health_mutex){+.+.+.}, at: [] health_kthread+0x63/0x490 [btrfs] +[ 5375.719293] #1: (&fs_info->dev_replace.lock_finishing_cancel_unmount){+.+.+.}, at: [] btrfs_dev_replace_finishing+0x41/0x990 [btrfs] +[ 5375.719319] #2: (uuid_mutex){+.+.+.}, at: [] btrfs_destroy_dev_replace_tgtdev+0x20/0x150 [btrfs] +[ 5375.719343] #3: (&fs_devs->device_list_mutex){+.+.+.}, at: [] btrfs_destroy_dev_replace_tgtdev+0x3c/0x150 [btrfs] +[ 5375.719343] +[ 5375.719343] stack backtrace: +[ 5375.719347] CPU: 2 PID: 4662 Comm: btrfs-health Not tainted 4.4.5-scst31x-debug-11+ #40 +[ 5375.719348] Hardware name: Supermicro SYS-6018R-WTRT/X10DRW-iT, BIOS 1.0c 01/07/2015 +[ 5375.719352] 0000000000000000 ffff880856f73880 ffffffff813529e3 ffffffff826182a0 +[ 5375.719354] ffffffff8260c090 ffff880856f738c0 ffffffff810d667c ffff880856f73930 +[ 5375.719357] ffff880861f32b40 ffff880861f32b68 0000000000000003 0000000000000004 +[ 5375.719357] Call Trace: +[ 5375.719363] [] dump_stack+0x85/0xc2 +[ 5375.719366] [] print_circular_bug+0x1ec/0x260 +[ 5375.719369] [] __lock_acquire+0x17ba/0x1ae0 +[ 5375.719373] [] ? debug_lockdep_rcu_enabled+0x1d/0x20 +[ 5375.719376] [] lock_acquire+0xce/0x1e0 +[ 5375.719378] [] ? __sb_start_write+0xb7/0xf0 +[ 5375.719383] [] percpu_down_read+0x4f/0xa0 +[ 5375.719385] [] ? __sb_start_write+0xb7/0xf0 +[ 5375.719387] [] __sb_start_write+0xb7/0xf0 +[ 5375.719389] [] mnt_want_write+0x24/0x50 +[ 5375.719393] [] path_openat+0xd32/0x1360 +[ 5375.719415] [] ? btrfs_congested_fn+0x180/0x180 [btrfs] +[ 5375.719418] [] ? debug_lockdep_rcu_enabled+0x1d/0x20 +[ 5375.719420] [] do_filp_open+0x7e/0xe0 +[ 5375.719423] [] ? rcu_read_lock_sched_held+0x6d/0x80 +[ 5375.719426] [] ? kmem_cache_alloc+0x26b/0x5d0 +[ 5375.719430] [] ? getname_kernel+0x34/0x120 +[ 5375.719433] [] file_open_name+0xe4/0x130 +[ 5375.719436] [] filp_open+0x33/0x60 +[ 5375.719462] [] update_dev_time+0x16/0x40 [btrfs] +[ 5375.719485] [] btrfs_scratch_superblocks+0x4e/0x90 [btrfs] +[ 5375.719506] [] btrfs_destroy_dev_replace_tgtdev+0x65/0x150 [btrfs] +[ 5375.719530] [] btrfs_dev_replace_finishing+0x6b0/0x990 [btrfs] +[ 5375.719554] [] ? btrfs_dev_replace_finishing+0x553/0x990 [btrfs] +[ 5375.719576] [] btrfs_dev_replace_start+0x33e/0x540 [btrfs] +[ 5375.719598] [] btrfs_auto_replace_start+0xf8/0x140 [btrfs] +[ 5375.719621] [] health_kthread+0x246/0x490 [btrfs] +[ 5375.719641] [] ? health_kthread+0x138/0x490 [btrfs] +[ 5375.719661] [] ? btrfs_congested_fn+0x180/0x180 [btrfs] +[ 5375.719663] [] kthread+0xef/0x110 +[ 5375.719666] [] ? kthread_create_on_node+0x200/0x200 +[ 5375.719669] [] ret_from_fork+0x3f/0x70 +[ 5375.719672] [] ? kthread_create_on_node+0x200/0x200 +[ 5375.719697] ------------[ cut here ]------------ + +Signed-off-by: Anand Jain +Reported-by: Yauhen Kharuzhy +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/volumes.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -2023,10 +2023,9 @@ void btrfs_destroy_dev_replace_tgtdev(st + + btrfs_sysfs_rm_device_link(fs_info->fs_devices, tgtdev); + +- if (tgtdev->bdev) { +- btrfs_scratch_superblocks(tgtdev->bdev, tgtdev->name->str); ++ if (tgtdev->bdev) + fs_info->fs_devices->open_devices--; +- } ++ + fs_info->fs_devices->num_devices--; + + next_device = list_entry(fs_info->fs_devices->devices.next, +@@ -2037,10 +2036,18 @@ void btrfs_destroy_dev_replace_tgtdev(st + fs_info->fs_devices->latest_bdev = next_device->bdev; + list_del_rcu(&tgtdev->dev_list); + +- call_rcu(&tgtdev->rcu, free_device); +- + mutex_unlock(&fs_info->fs_devices->device_list_mutex); + mutex_unlock(&uuid_mutex); ++ ++ /* ++ * The update_dev_time() with in btrfs_scratch_superblocks() ++ * may lead to a call to btrfs_show_devname() which will try ++ * to hold device_list_mutex. And here this device ++ * is already out of device list, so we don't have to hold ++ * the device_list_mutex lock. ++ */ ++ btrfs_scratch_superblocks(tgtdev->bdev, tgtdev->name->str); ++ call_rcu(&tgtdev->rcu, free_device); + } + + static int btrfs_find_device_by_path(struct btrfs_root *root, char *device_path, diff --git a/queue-4.5/btrfs-fix-lock-dep-warning-move-scratch-super-outside-of-chunk_mutex.patch b/queue-4.5/btrfs-fix-lock-dep-warning-move-scratch-super-outside-of-chunk_mutex.patch new file mode 100644 index 00000000000..5f743eeabe3 --- /dev/null +++ b/queue-4.5/btrfs-fix-lock-dep-warning-move-scratch-super-outside-of-chunk_mutex.patch @@ -0,0 +1,81 @@ +From 48b3b9d401ec86899a52003b37331190a35a81a6 Mon Sep 17 00:00:00 2001 +From: Anand Jain +Date: Tue, 12 Apr 2016 21:36:16 +0800 +Subject: btrfs: fix lock dep warning move scratch super outside of chunk_mutex + +From: Anand Jain + +commit 48b3b9d401ec86899a52003b37331190a35a81a6 upstream. + +Move scratch super outside of the chunk lock to avoid below +lockdep warning. The better place to scratch super is in +the function btrfs_rm_dev_replace_free_srcdev() just before +free_device, which is outside of the chunk lock as well. + +To reproduce: + (fresh boot) + mkfs.btrfs -f -draid5 -mraid5 /dev/sdc /dev/sdd /dev/sde + mount /dev/sdc /btrfs + dd if=/dev/zero of=/btrfs/tf1 bs=4096 count=100 + (get devmgt from https://github.com/asj/devmgt.git) + devmgt detach /dev/sde + dd if=/dev/zero of=/btrfs/tf1 bs=4096 count=100 + sync + btrfs replace start -Brf 3 /dev/sdf /btrfs <-- + devmgt attach host7 + +====================================================== +[ INFO: possible circular locking dependency detected ] +4.6.0-rc2asj+ #1 Not tainted +--------------------------------------------------- + +btrfs/2174 is trying to acquire lock: +(sb_writers){.+.+.+}, at: +[] __sb_start_write+0xb4/0xf0 + +but task is already holding lock: +(&fs_info->chunk_mutex){+.+.+.}, at: +[] btrfs_dev_replace_finishing+0x145/0x980 [btrfs] + +which lock already depends on the new lock. + +Chain exists of: +sb_writers --> &fs_devs->device_list_mutex --> &fs_info->chunk_mutex +Possible unsafe locking scenario: +CPU0 CPU1 +---- ---- +lock(&fs_info->chunk_mutex); + lock(&fs_devs->device_list_mutex); + lock(&fs_info->chunk_mutex); +lock(sb_writers); + +--- + fs/btrfs/volumes.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -1971,11 +1971,8 @@ void btrfs_rm_dev_replace_remove_srcdev( + if (srcdev->missing) + fs_devices->missing_devices--; + +- if (srcdev->writeable) { ++ if (srcdev->writeable) + fs_devices->rw_devices--; +- /* zero out the old super if it is writable */ +- btrfs_scratch_superblocks(srcdev->bdev, srcdev->name->str); +- } + + if (srcdev->bdev) + fs_devices->open_devices--; +@@ -1986,6 +1983,10 @@ void btrfs_rm_dev_replace_free_srcdev(st + { + struct btrfs_fs_devices *fs_devices = srcdev->fs_devices; + ++ if (srcdev->writeable) { ++ /* zero out the old super if it is writable */ ++ btrfs_scratch_superblocks(srcdev->bdev, srcdev->name->str); ++ } + call_rcu(&srcdev->rcu, free_device); + + /* diff --git a/queue-4.5/btrfs-fix-memory-leak-during-raid-5-6-device-replacement.patch b/queue-4.5/btrfs-fix-memory-leak-during-raid-5-6-device-replacement.patch new file mode 100644 index 00000000000..e521d837f11 --- /dev/null +++ b/queue-4.5/btrfs-fix-memory-leak-during-raid-5-6-device-replacement.patch @@ -0,0 +1,31 @@ +From 4673272f43ae790ab9ec04e38a7542f82bb8f020 Mon Sep 17 00:00:00 2001 +From: Scott Talbert +Date: Mon, 9 May 2016 09:14:28 -0400 +Subject: btrfs: fix memory leak during RAID 5/6 device replacement + +From: Scott Talbert + +commit 4673272f43ae790ab9ec04e38a7542f82bb8f020 upstream. + +A 'struct bio' is allocated in scrub_missing_raid56_pages(), but it was never +freed anywhere. + +Signed-off-by: Scott Talbert +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/scrub.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -2125,6 +2125,8 @@ static void scrub_missing_raid56_end_io( + if (bio->bi_error) + sblock->no_io_error_seen = 0; + ++ bio_put(bio); ++ + btrfs_queue_work(fs_info->scrub_workers, &sblock->work); + } + diff --git a/queue-4.5/btrfs-fix-mixed-block-count-of-available-space.patch b/queue-4.5/btrfs-fix-mixed-block-count-of-available-space.patch new file mode 100644 index 00000000000..d703fadec88 --- /dev/null +++ b/queue-4.5/btrfs-fix-mixed-block-count-of-available-space.patch @@ -0,0 +1,60 @@ +From ae02d1bd070767e109f4a6f1bb1f466e9698a355 Mon Sep 17 00:00:00 2001 +From: Luis de Bethencourt +Date: Wed, 30 Mar 2016 21:53:38 +0100 +Subject: btrfs: fix mixed block count of available space + +From: Luis de Bethencourt + +commit ae02d1bd070767e109f4a6f1bb1f466e9698a355 upstream. + +Metadata for mixed block is already accounted in total data and should not +be counted as part of the free metadata space. + +Signed-off-by: Luis de Bethencourt +Link: https://bugzilla.kernel.org/show_bug.cgi?id=114281 +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/super.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -2024,6 +2024,7 @@ static int btrfs_statfs(struct dentry *d + struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; + int ret; + u64 thresh = 0; ++ int mixed = 0; + + /* + * holding chunk_muext to avoid allocating new chunks, holding +@@ -2049,8 +2050,17 @@ static int btrfs_statfs(struct dentry *d + } + } + } +- if (found->flags & BTRFS_BLOCK_GROUP_METADATA) +- total_free_meta += found->disk_total - found->disk_used; ++ ++ /* ++ * Metadata in mixed block goup profiles are accounted in data ++ */ ++ if (!mixed && found->flags & BTRFS_BLOCK_GROUP_METADATA) { ++ if (found->flags & BTRFS_BLOCK_GROUP_DATA) ++ mixed = 1; ++ else ++ total_free_meta += found->disk_total - ++ found->disk_used; ++ } + + total_used += found->disk_used; + } +@@ -2088,7 +2098,7 @@ static int btrfs_statfs(struct dentry *d + */ + thresh = 4 * 1024 * 1024; + +- if (total_free_meta - thresh < block_rsv->size) ++ if (!mixed && total_free_meta - thresh < block_rsv->size) + buf->f_bavail = 0; + + buf->f_type = BTRFS_SUPER_MAGIC; diff --git a/queue-4.5/btrfs-fix-unexpected-return-value-of-fiemap.patch b/queue-4.5/btrfs-fix-unexpected-return-value-of-fiemap.patch new file mode 100644 index 00000000000..bd896c99464 --- /dev/null +++ b/queue-4.5/btrfs-fix-unexpected-return-value-of-fiemap.patch @@ -0,0 +1,44 @@ +From 2d324f59f343967a03eeb2690f0ff178304d0687 Mon Sep 17 00:00:00 2001 +From: Liu Bo +Date: Tue, 17 May 2016 17:21:48 -0700 +Subject: Btrfs: fix unexpected return value of fiemap + +From: Liu Bo + +commit 2d324f59f343967a03eeb2690f0ff178304d0687 upstream. + +btrfs's fiemap is supposed to return 0 on success and return < 0 on +error. however, ret becomes 1 after looking up the last file extent: + + btrfs_lookup_file_extent -> + btrfs_search_slot(..., ins_len=0, cow=0) + +and if the offset is beyond EOF, we'll get 'path' pointed to the place +of potentail insertion, and ret == 1. + +This may confuse applications using ioctl(FIEL_IOC_FIEMAP). + +Signed-off-by: Liu Bo +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/extent_io.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4385,8 +4385,12 @@ int extent_fiemap(struct inode *inode, s + if (ret < 0) { + btrfs_free_path(path); + return ret; ++ } else { ++ WARN_ON(!ret); ++ if (ret == 1) ++ ret = 0; + } +- WARN_ON(!ret); ++ + path->slots[0]--; + btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]); + found_type = found_key.type; diff --git a/queue-4.5/btrfs-make-state-preallocation-more-speculative-in-__set_extent_bit.patch b/queue-4.5/btrfs-make-state-preallocation-more-speculative-in-__set_extent_bit.patch new file mode 100644 index 00000000000..96e98ad4419 --- /dev/null +++ b/queue-4.5/btrfs-make-state-preallocation-more-speculative-in-__set_extent_bit.patch @@ -0,0 +1,37 @@ +From 059f791c6bbaba72dc3c1bd6e2657aacc8552849 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Wed, 27 Apr 2016 01:03:45 +0200 +Subject: btrfs: make state preallocation more speculative in __set_extent_bit + +From: David Sterba + +commit 059f791c6bbaba72dc3c1bd6e2657aacc8552849 upstream. + +Similar to __clear_extent_bit, do not fail if the state preallocation +fails as we might not need it. One less BUG_ON. + +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/extent_io.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -875,8 +875,14 @@ __set_extent_bit(struct extent_io_tree * + bits |= EXTENT_FIRST_DELALLOC; + again: + if (!prealloc && gfpflags_allow_blocking(mask)) { ++ /* ++ * Don't care for allocation failure here because we might end ++ * up not needing the pre-allocated extent state at all, which ++ * is the case if we only have in the tree extent states that ++ * cover our input range and don't cover too any other range. ++ * If we end up needing a new extent state we allocate it later. ++ */ + prealloc = alloc_extent_state(mask); +- BUG_ON(!prealloc); + } + + spin_lock(&tree->lock); diff --git a/queue-4.5/btrfs-pass-the-right-error-code-to-the-btrfs_std_error.patch b/queue-4.5/btrfs-pass-the-right-error-code-to-the-btrfs_std_error.patch new file mode 100644 index 00000000000..6f68bc58e97 --- /dev/null +++ b/queue-4.5/btrfs-pass-the-right-error-code-to-the-btrfs_std_error.patch @@ -0,0 +1,33 @@ +From ad8403df054c9b5dc3175a26c6179571b9cafa4e Mon Sep 17 00:00:00 2001 +From: Anand Jain +Date: Thu, 10 Mar 2016 12:22:15 +0800 +Subject: btrfs: pass the right error code to the btrfs_std_error + +From: Anand Jain + +commit ad8403df054c9b5dc3175a26c6179571b9cafa4e upstream. + +Also drop the newline from the message. + +Signed-off-by: Anand Jain +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + + +--- + fs/btrfs/ioctl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -4849,8 +4849,8 @@ static long btrfs_ioctl_qgroup_assign(st + /* update qgroup status and info */ + err = btrfs_run_qgroups(trans, root->fs_info); + if (err < 0) +- btrfs_std_error(root->fs_info, ret, +- "failed to update qgroup status and info\n"); ++ btrfs_std_error(root->fs_info, err, ++ "failed to update qgroup status and info"); + err = btrfs_end_transaction(trans, root); + if (err && !ret) + ret = err; diff --git a/queue-4.5/btrfs-remove-bug_on-s-in-btrfs_map_block.patch b/queue-4.5/btrfs-remove-bug_on-s-in-btrfs_map_block.patch new file mode 100644 index 00000000000..f88526063db --- /dev/null +++ b/queue-4.5/btrfs-remove-bug_on-s-in-btrfs_map_block.patch @@ -0,0 +1,55 @@ +From e042d1ec4417981dfe9331e47b76f17929bc2ffe Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Tue, 12 Apr 2016 12:54:40 -0400 +Subject: Btrfs: remove BUG_ON()'s in btrfs_map_block + +From: Josef Bacik + +commit e042d1ec4417981dfe9331e47b76f17929bc2ffe upstream. + +btrfs_map_block can go horribly wrong in the face of fs corruption, lets agree +to not be assholes and panic at any possible chance things are all fucked up. + +Signed-off-by: Josef Bacik +[ removed type casts ] +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/volumes.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -5289,7 +5289,15 @@ static int __btrfs_map_block(struct btrf + stripe_nr = div64_u64(stripe_nr, stripe_len); + + stripe_offset = stripe_nr * stripe_len; +- BUG_ON(offset < stripe_offset); ++ if (offset < stripe_offset) { ++ btrfs_crit(fs_info, "stripe math has gone wrong, " ++ "stripe_offset=%llu, offset=%llu, start=%llu, " ++ "logical=%llu, stripe_len=%llu", ++ stripe_offset, offset, em->start, logical, ++ stripe_len); ++ free_extent_map(em); ++ return -EINVAL; ++ } + + /* stripe_offset is the offset of this block in its stripe*/ + stripe_offset = offset - stripe_offset; +@@ -5528,7 +5536,13 @@ static int __btrfs_map_block(struct btrf + &stripe_index); + mirror_num = stripe_index + 1; + } +- BUG_ON(stripe_index >= map->num_stripes); ++ if (stripe_index >= map->num_stripes) { ++ btrfs_crit(fs_info, "stripe index math went horribly wrong, " ++ "got stripe_index=%u, num_stripes=%u", ++ stripe_index, map->num_stripes); ++ ret = -EINVAL; ++ goto out; ++ } + + num_alloc_stripes = num_stripes; + if (dev_replace_is_ongoing) { diff --git a/queue-4.5/btrfs-scrub-set-bbio-to-null-before-calling-btrfs_map_block.patch b/queue-4.5/btrfs-scrub-set-bbio-to-null-before-calling-btrfs_map_block.patch new file mode 100644 index 00000000000..6761dd6443c --- /dev/null +++ b/queue-4.5/btrfs-scrub-set-bbio-to-null-before-calling-btrfs_map_block.patch @@ -0,0 +1,46 @@ +From f1fee6534dcfbf468a159789aa202db2bce8c200 Mon Sep 17 00:00:00 2001 +From: Zhao Lei +Date: Tue, 17 May 2016 17:37:38 +0800 +Subject: btrfs: scrub: Set bbio to NULL before calling btrfs_map_block + +From: Zhao Lei + +commit f1fee6534dcfbf468a159789aa202db2bce8c200 upstream. + +We usually call btrfs_put_bbio() when btrfs_map_block() failed, +btrfs_put_bbio() works right whether bbio is a valid value, or NULL. + +But there is a exception, in some case, btrfs_map_block() will return +fail without touching *bbio(keeping its original value), and if bbio +was not initialized yet, invalid memory accessing will happened. + +Above case is in scrub_missing_raid56_pages(), and similar case in +scrub_raid56_parity(). + +Signed-off-by: Zhao Lei +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/scrub.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -2179,7 +2179,7 @@ static void scrub_missing_raid56_pages(s + struct btrfs_fs_info *fs_info = sctx->dev_root->fs_info; + u64 length = sblock->page_count * PAGE_SIZE; + u64 logical = sblock->pagev[0]->logical; +- struct btrfs_bio *bbio; ++ struct btrfs_bio *bbio = NULL; + struct bio *bio; + struct btrfs_raid_bio *rbio; + int ret; +@@ -2980,6 +2980,7 @@ again: + extent_len); + + mapped_length = extent_len; ++ bbio = NULL; + ret = btrfs_map_block(fs_info, READ, extent_logical, + &mapped_length, &bbio, 0); + if (!ret) { diff --git a/queue-4.5/series b/queue-4.5/series index 71507785bc0..11bbc701f0f 100644 --- a/queue-4.5/series +++ b/queue-4.5/series @@ -105,3 +105,24 @@ xfs-don-t-wrap-growfs-agfl-indexes.patch xfs-xfs_iflush_cluster-fails-to-abort-on-error.patch xfs-fix-inode-validity-check-in-xfs_iflush_cluster.patch xfs-skip-stale-inodes-in-xfs_iflush_cluster.patch +btrfs-bugfix-handle-fs_ioc32_-getflags-setflags-getversion-in-btrfs_ioctl.patch +btrfs-do-not-create-empty-block-group-if-we-have-allocated-data.patch +btrfs-allow-balancing-to-dup-with-multi-device.patch +btrfs-fix-mixed-block-count-of-available-space.patch +btrfs-avoid-overflowing-f_bfree.patch +btrfs-fix-lock-dep-warning-move-scratch-dev-out-of-device_list_mutex-and-uuid_mutex.patch +btrfs-add-read-only-check-to-sysfs-handler-of-features.patch +btrfs-add-check-to-sysfs-handler-of-label.patch +btrfs-fix-divide-error-upon-chunk-s-stripe_len.patch +btrfs-remove-bug_on-s-in-btrfs_map_block.patch +btrfs-fix-lock-dep-warning-move-scratch-super-outside-of-chunk_mutex.patch +btrfs-add-write-protection-to-set_features-ioctl.patch +btrfs-fix-int32-overflow-in-shrink_delalloc.patch +btrfs-fix-fspath-error-deallocation.patch +btrfs-fix-memory-leak-during-raid-5-6-device-replacement.patch +btrfs-pass-the-right-error-code-to-the-btrfs_std_error.patch +btrfs-fix-for-incorrect-directory-entries-after-fsync-log-replay.patch +btrfs-fix-empty-symlink-after-creating-symlink-and-fsync-parent-dir.patch +btrfs-fix-unexpected-return-value-of-fiemap.patch +btrfs-scrub-set-bbio-to-null-before-calling-btrfs_map_block.patch +btrfs-make-state-preallocation-more-speculative-in-__set_extent_bit.patch