diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-12-10 11:30:04 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-12-10 11:30:04 -0500 |
| commit | 51090c5d6de08cfc86b2d861775dedddd9a2c023 (patch) | |
| tree | 0f42af1f3251bea783e46ff61d7d433945844f1b | |
| parent | 9c02e0601b9ae76c2f5b783f9e6c2199921c2de5 (diff) | |
| parent | c8bcbfbd239ed60a6562964b58034ac8a25f4c31 (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.c | 18 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 12 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 2 |
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; |
