aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-12-10 11:30:04 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-12-10 11:30:04 -0500
commit51090c5d6de08cfc86b2d861775dedddd9a2c023 (patch)
tree0f42af1f3251bea783e46ff61d7d433945844f1b
parent9c02e0601b9ae76c2f5b783f9e6c2199921c2de5 (diff)
parentc8bcbfbd239ed60a6562964b58034ac8a25f4c31 (diff)
Merge tag 'for-4.15-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "This contains a few fixes (error handling, quota leak, FUA vs nobarrier mount option). There's one one worth mentioning separately - an off-by-one fix that leads to overwriting first byte of an adjacent page with 0, out of bounds of the memory allocated by an ioctl. This is under a privileged part of the ioctl, can be triggerd in some subvolume layouts" * tag 'for-4.15-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: Fix possible off-by-one in btrfs_search_path_in_tree Btrfs: disable FUA if mounted with nobarrier btrfs: fix missing error return in btrfs_drop_snapshot btrfs: handle errors while updating refcounts in update_ref_for_cow btrfs: Fix quota reservation leak on preallocated files
-rw-r--r--fs/btrfs/ctree.c18
-rw-r--r--fs/btrfs/disk-io.c12
-rw-r--r--fs/btrfs/extent-tree.c1
-rw-r--r--fs/btrfs/inode.c2
-rw-r--r--fs/btrfs/ioctl.c2
5 files changed, 21 insertions, 14 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 531e0a8645b0..1e74cf826532 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1032,14 +1032,17 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
1032 root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && 1032 root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) &&
1033 !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) { 1033 !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) {
1034 ret = btrfs_inc_ref(trans, root, buf, 1); 1034 ret = btrfs_inc_ref(trans, root, buf, 1);
1035 BUG_ON(ret); /* -ENOMEM */ 1035 if (ret)
1036 return ret;
1036 1037
1037 if (root->root_key.objectid == 1038 if (root->root_key.objectid ==
1038 BTRFS_TREE_RELOC_OBJECTID) { 1039 BTRFS_TREE_RELOC_OBJECTID) {
1039 ret = btrfs_dec_ref(trans, root, buf, 0); 1040 ret = btrfs_dec_ref(trans, root, buf, 0);
1040 BUG_ON(ret); /* -ENOMEM */ 1041 if (ret)
1042 return ret;
1041 ret = btrfs_inc_ref(trans, root, cow, 1); 1043 ret = btrfs_inc_ref(trans, root, cow, 1);
1042 BUG_ON(ret); /* -ENOMEM */ 1044 if (ret)
1045 return ret;
1043 } 1046 }
1044 new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF; 1047 new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
1045 } else { 1048 } else {
@@ -1049,7 +1052,8 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
1049 ret = btrfs_inc_ref(trans, root, cow, 1); 1052 ret = btrfs_inc_ref(trans, root, cow, 1);
1050 else 1053 else
1051 ret = btrfs_inc_ref(trans, root, cow, 0); 1054 ret = btrfs_inc_ref(trans, root, cow, 0);
1052 BUG_ON(ret); /* -ENOMEM */ 1055 if (ret)
1056 return ret;
1053 } 1057 }
1054 if (new_flags != 0) { 1058 if (new_flags != 0) {
1055 int level = btrfs_header_level(buf); 1059 int level = btrfs_header_level(buf);
@@ -1068,9 +1072,11 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
1068 ret = btrfs_inc_ref(trans, root, cow, 1); 1072 ret = btrfs_inc_ref(trans, root, cow, 1);
1069 else 1073 else
1070 ret = btrfs_inc_ref(trans, root, cow, 0); 1074 ret = btrfs_inc_ref(trans, root, cow, 0);
1071 BUG_ON(ret); /* -ENOMEM */ 1075 if (ret)
1076 return ret;
1072 ret = btrfs_dec_ref(trans, root, buf, 1); 1077 ret = btrfs_dec_ref(trans, root, buf, 1);
1073 BUG_ON(ret); /* -ENOMEM */ 1078 if (ret)
1079 return ret;
1074 } 1080 }
1075 clean_tree_block(fs_info, buf); 1081 clean_tree_block(fs_info, buf);
1076 *last_ref = 1; 1082 *last_ref = 1;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 10a2a579cc7f..a8ecccfc36de 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3231,6 +3231,7 @@ static int write_dev_supers(struct btrfs_device *device,
3231 int errors = 0; 3231 int errors = 0;
3232 u32 crc; 3232 u32 crc;
3233 u64 bytenr; 3233 u64 bytenr;
3234 int op_flags;
3234 3235
3235 if (max_mirrors == 0) 3236 if (max_mirrors == 0)
3236 max_mirrors = BTRFS_SUPER_MIRROR_MAX; 3237 max_mirrors = BTRFS_SUPER_MIRROR_MAX;
@@ -3273,13 +3274,10 @@ static int write_dev_supers(struct btrfs_device *device,
3273 * we fua the first super. The others we allow 3274 * we fua the first super. The others we allow
3274 * to go down lazy. 3275 * to go down lazy.
3275 */ 3276 */
3276 if (i == 0) { 3277 op_flags = REQ_SYNC | REQ_META | REQ_PRIO;
3277 ret = btrfsic_submit_bh(REQ_OP_WRITE, 3278 if (i == 0 && !btrfs_test_opt(device->fs_info, NOBARRIER))
3278 REQ_SYNC | REQ_FUA | REQ_META | REQ_PRIO, bh); 3279 op_flags |= REQ_FUA;
3279 } else { 3280 ret = btrfsic_submit_bh(REQ_OP_WRITE, op_flags, bh);
3280 ret = btrfsic_submit_bh(REQ_OP_WRITE,
3281 REQ_SYNC | REQ_META | REQ_PRIO, bh);
3282 }
3283 if (ret) 3281 if (ret)
3284 errors++; 3282 errors++;
3285 } 3283 }
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 4497f937e8fb..2f4328511ac8 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -9206,6 +9206,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
9206 ret = btrfs_del_root(trans, fs_info, &root->root_key); 9206 ret = btrfs_del_root(trans, fs_info, &root->root_key);
9207 if (ret) { 9207 if (ret) {
9208 btrfs_abort_transaction(trans, ret); 9208 btrfs_abort_transaction(trans, ret);
9209 err = ret;
9209 goto out_end_trans; 9210 goto out_end_trans;
9210 } 9211 }
9211 9212
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 993061f83067..e1a7f3cb5be9 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3005,6 +3005,8 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
3005 compress_type = ordered_extent->compress_type; 3005 compress_type = ordered_extent->compress_type;
3006 if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { 3006 if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
3007 BUG_ON(compress_type); 3007 BUG_ON(compress_type);
3008 btrfs_qgroup_free_data(inode, NULL, ordered_extent->file_offset,
3009 ordered_extent->len);
3008 ret = btrfs_mark_extent_written(trans, BTRFS_I(inode), 3010 ret = btrfs_mark_extent_written(trans, BTRFS_I(inode),
3009 ordered_extent->file_offset, 3011 ordered_extent->file_offset,
3010 ordered_extent->file_offset + 3012 ordered_extent->file_offset +
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index d748ad1c3620..2ef8acaac688 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2206,7 +2206,7 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,
2206 if (!path) 2206 if (!path)
2207 return -ENOMEM; 2207 return -ENOMEM;
2208 2208
2209 ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX]; 2209 ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX - 1];
2210 2210
2211 key.objectid = tree_id; 2211 key.objectid = tree_id;
2212 key.type = BTRFS_ROOT_ITEM_KEY; 2212 key.type = BTRFS_ROOT_ITEM_KEY;