aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-11-09 11:51:37 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2019-11-09 11:51:37 -0500
commit00aff6836241ae5654895dcea10e6d4fc5878ca6 (patch)
treed28b74f641c5e3f380f664acee8a7996fd2e07e8 /fs
parent4aba1a7ed563d1c0b153377f57f4d213776ea573 (diff)
parenta5009d3a318e9f02ddc9aa3d55e2c64d6285c4b9 (diff)
Merge tag 'for-5.4-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A few regressions and fixes for stable. Regressions: - fix a race leading to metadata space leak after task received a signal - un-deprecate 2 ioctls, marked as deprecated by mistake Fixes: - fix limit check for number of devices during chunk allocation - fix a race due to double evaluation of i_size_read inside max() macro, can cause a crash - remove wrong device id check in tree-checker" * tag 'for-5.4-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: un-deprecate ioctls START_SYNC and WAIT_SYNC btrfs: save i_size to avoid double evaluation of i_size_read in compress_file_range Btrfs: fix race leading to metadata space leak after task received signal btrfs: tree-checker: Fix wrong check on max devid btrfs: Consider system chunk array size for new SYSTEM chunks
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/inode.c15
-rw-r--r--fs/btrfs/ioctl.c6
-rw-r--r--fs/btrfs/space-info.c21
-rw-r--r--fs/btrfs/tree-checker.c8
-rw-r--r--fs/btrfs/volumes.c1
5 files changed, 36 insertions, 15 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c3f386b7cc0b..c6dc4dd16cf7 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -474,6 +474,7 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
474 u64 start = async_chunk->start; 474 u64 start = async_chunk->start;
475 u64 end = async_chunk->end; 475 u64 end = async_chunk->end;
476 u64 actual_end; 476 u64 actual_end;
477 u64 i_size;
477 int ret = 0; 478 int ret = 0;
478 struct page **pages = NULL; 479 struct page **pages = NULL;
479 unsigned long nr_pages; 480 unsigned long nr_pages;
@@ -488,7 +489,19 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
488 inode_should_defrag(BTRFS_I(inode), start, end, end - start + 1, 489 inode_should_defrag(BTRFS_I(inode), start, end, end - start + 1,
489 SZ_16K); 490 SZ_16K);
490 491
491 actual_end = min_t(u64, i_size_read(inode), end + 1); 492 /*
493 * We need to save i_size before now because it could change in between
494 * us evaluating the size and assigning it. This is because we lock and
495 * unlock the page in truncate and fallocate, and then modify the i_size
496 * later on.
497 *
498 * The barriers are to emulate READ_ONCE, remove that once i_size_read
499 * does that for us.
500 */
501 barrier();
502 i_size = i_size_read(inode);
503 barrier();
504 actual_end = min_t(u64, i_size, end + 1);
492again: 505again:
493 will_compress = 0; 506 will_compress = 0;
494 nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1; 507 nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 7c145a41decd..23272d9154f3 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4195,9 +4195,6 @@ static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
4195 u64 transid; 4195 u64 transid;
4196 int ret; 4196 int ret;
4197 4197
4198 btrfs_warn(root->fs_info,
4199 "START_SYNC ioctl is deprecated and will be removed in kernel 5.7");
4200
4201 trans = btrfs_attach_transaction_barrier(root); 4198 trans = btrfs_attach_transaction_barrier(root);
4202 if (IS_ERR(trans)) { 4199 if (IS_ERR(trans)) {
4203 if (PTR_ERR(trans) != -ENOENT) 4200 if (PTR_ERR(trans) != -ENOENT)
@@ -4225,9 +4222,6 @@ static noinline long btrfs_ioctl_wait_sync(struct btrfs_fs_info *fs_info,
4225{ 4222{
4226 u64 transid; 4223 u64 transid;
4227 4224
4228 btrfs_warn(fs_info,
4229 "WAIT_SYNC ioctl is deprecated and will be removed in kernel 5.7");
4230
4231 if (argp) { 4225 if (argp) {
4232 if (copy_from_user(&transid, argp, sizeof(transid))) 4226 if (copy_from_user(&transid, argp, sizeof(transid)))
4233 return -EFAULT; 4227 return -EFAULT;
diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c
index 98dc092a905e..e8a4b0ebe97f 100644
--- a/fs/btrfs/space-info.c
+++ b/fs/btrfs/space-info.c
@@ -893,6 +893,15 @@ static void wait_reserve_ticket(struct btrfs_fs_info *fs_info,
893 while (ticket->bytes > 0 && ticket->error == 0) { 893 while (ticket->bytes > 0 && ticket->error == 0) {
894 ret = prepare_to_wait_event(&ticket->wait, &wait, TASK_KILLABLE); 894 ret = prepare_to_wait_event(&ticket->wait, &wait, TASK_KILLABLE);
895 if (ret) { 895 if (ret) {
896 /*
897 * Delete us from the list. After we unlock the space
898 * info, we don't want the async reclaim job to reserve
899 * space for this ticket. If that would happen, then the
900 * ticket's task would not known that space was reserved
901 * despite getting an error, resulting in a space leak
902 * (bytes_may_use counter of our space_info).
903 */
904 list_del_init(&ticket->list);
896 ticket->error = -EINTR; 905 ticket->error = -EINTR;
897 break; 906 break;
898 } 907 }
@@ -945,12 +954,24 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info,
945 spin_lock(&space_info->lock); 954 spin_lock(&space_info->lock);
946 ret = ticket->error; 955 ret = ticket->error;
947 if (ticket->bytes || ticket->error) { 956 if (ticket->bytes || ticket->error) {
957 /*
958 * Need to delete here for priority tickets. For regular tickets
959 * either the async reclaim job deletes the ticket from the list
960 * or we delete it ourselves at wait_reserve_ticket().
961 */
948 list_del_init(&ticket->list); 962 list_del_init(&ticket->list);
949 if (!ret) 963 if (!ret)
950 ret = -ENOSPC; 964 ret = -ENOSPC;
951 } 965 }
952 spin_unlock(&space_info->lock); 966 spin_unlock(&space_info->lock);
953 ASSERT(list_empty(&ticket->list)); 967 ASSERT(list_empty(&ticket->list));
968 /*
969 * Check that we can't have an error set if the reservation succeeded,
970 * as that would confuse tasks and lead them to error out without
971 * releasing reserved space (if an error happens the expectation is that
972 * space wasn't reserved at all).
973 */
974 ASSERT(!(ticket->bytes == 0 && ticket->error));
954 return ret; 975 return ret;
955} 976}
956 977
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index 43e488f5d063..076d5b8014fb 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -686,9 +686,7 @@ static void dev_item_err(const struct extent_buffer *eb, int slot,
686static int check_dev_item(struct extent_buffer *leaf, 686static int check_dev_item(struct extent_buffer *leaf,
687 struct btrfs_key *key, int slot) 687 struct btrfs_key *key, int slot)
688{ 688{
689 struct btrfs_fs_info *fs_info = leaf->fs_info;
690 struct btrfs_dev_item *ditem; 689 struct btrfs_dev_item *ditem;
691 u64 max_devid = max(BTRFS_MAX_DEVS(fs_info), BTRFS_MAX_DEVS_SYS_CHUNK);
692 690
693 if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) { 691 if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) {
694 dev_item_err(leaf, slot, 692 dev_item_err(leaf, slot,
@@ -696,12 +694,6 @@ static int check_dev_item(struct extent_buffer *leaf,
696 key->objectid, BTRFS_DEV_ITEMS_OBJECTID); 694 key->objectid, BTRFS_DEV_ITEMS_OBJECTID);
697 return -EUCLEAN; 695 return -EUCLEAN;
698 } 696 }
699 if (key->offset > max_devid) {
700 dev_item_err(leaf, slot,
701 "invalid devid: has=%llu expect=[0, %llu]",
702 key->offset, max_devid);
703 return -EUCLEAN;
704 }
705 ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); 697 ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item);
706 if (btrfs_device_id(leaf, ditem) != key->offset) { 698 if (btrfs_device_id(leaf, ditem) != key->offset) {
707 dev_item_err(leaf, slot, 699 dev_item_err(leaf, slot,
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index bdfe4493e43a..e04409f85063 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4967,6 +4967,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
4967 } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) { 4967 } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
4968 max_stripe_size = SZ_32M; 4968 max_stripe_size = SZ_32M;
4969 max_chunk_size = 2 * max_stripe_size; 4969 max_chunk_size = 2 * max_stripe_size;
4970 devs_max = min_t(int, devs_max, BTRFS_MAX_DEVS_SYS_CHUNK);
4970 } else { 4971 } else {
4971 btrfs_err(info, "invalid chunk type 0x%llx requested", 4972 btrfs_err(info, "invalid chunk type 0x%llx requested",
4972 type); 4973 type);