Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+36 -15
+14 -1
fs/btrfs/inode.c
··· 474 474 u64 start = async_chunk->start; 475 475 u64 end = async_chunk->end; 476 476 u64 actual_end; 477 + u64 i_size; 477 478 int ret = 0; 478 479 struct page **pages = NULL; 479 480 unsigned long nr_pages; ··· 489 488 inode_should_defrag(BTRFS_I(inode), start, end, end - start + 1, 490 489 SZ_16K); 491 490 492 - actual_end = min_t(u64, i_size_read(inode), end + 1); 491 + /* 492 + * We need to save i_size before now because it could change in between 493 + * us evaluating the size and assigning it. This is because we lock and 494 + * unlock the page in truncate and fallocate, and then modify the i_size 495 + * later on. 496 + * 497 + * The barriers are to emulate READ_ONCE, remove that once i_size_read 498 + * does that for us. 499 + */ 500 + barrier(); 501 + i_size = i_size_read(inode); 502 + barrier(); 503 + actual_end = min_t(u64, i_size, end + 1); 493 504 again: 494 505 will_compress = 0; 495 506 nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
-6
fs/btrfs/ioctl.c
··· 4195 4195 u64 transid; 4196 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 4198 trans = btrfs_attach_transaction_barrier(root); 4202 4199 if (IS_ERR(trans)) { 4203 4200 if (PTR_ERR(trans) != -ENOENT) ··· 4221 4224 void __user *argp) 4222 4225 { 4223 4226 u64 transid; 4224 - 4225 - btrfs_warn(fs_info, 4226 - "WAIT_SYNC ioctl is deprecated and will be removed in kernel 5.7"); 4227 4227 4228 4228 if (argp) { 4229 4229 if (copy_from_user(&transid, argp, sizeof(transid)))
+21
fs/btrfs/space-info.c
··· 893 893 while (ticket->bytes > 0 && ticket->error == 0) { 894 894 ret = prepare_to_wait_event(&ticket->wait, &wait, TASK_KILLABLE); 895 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 905 ticket->error = -EINTR; 897 906 break; 898 907 } ··· 954 945 spin_lock(&space_info->lock); 955 946 ret = ticket->error; 956 947 if (ticket->bytes || ticket->error) { 948 + /* 949 + * Need to delete here for priority tickets. For regular tickets 950 + * either the async reclaim job deletes the ticket from the list 951 + * or we delete it ourselves at wait_reserve_ticket(). 952 + */ 957 953 list_del_init(&ticket->list); 958 954 if (!ret) 959 955 ret = -ENOSPC; 960 956 } 961 957 spin_unlock(&space_info->lock); 962 958 ASSERT(list_empty(&ticket->list)); 959 + /* 960 + * Check that we can't have an error set if the reservation succeeded, 961 + * as that would confuse tasks and lead them to error out without 962 + * releasing reserved space (if an error happens the expectation is that 963 + * space wasn't reserved at all). 964 + */ 965 + ASSERT(!(ticket->bytes == 0 && ticket->error)); 963 966 return ret; 964 967 } 965 968
-8
fs/btrfs/tree-checker.c
··· 686 686 static int check_dev_item(struct extent_buffer *leaf, 687 687 struct btrfs_key *key, int slot) 688 688 { 689 - struct btrfs_fs_info *fs_info = leaf->fs_info; 690 689 struct btrfs_dev_item *ditem; 691 - u64 max_devid = max(BTRFS_MAX_DEVS(fs_info), BTRFS_MAX_DEVS_SYS_CHUNK); 692 690 693 691 if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) { 694 692 dev_item_err(leaf, slot, 695 693 "invalid objectid: has=%llu expect=%llu", 696 694 key->objectid, BTRFS_DEV_ITEMS_OBJECTID); 697 - return -EUCLEAN; 698 - } 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 695 return -EUCLEAN; 704 696 } 705 697 ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item);
+1
fs/btrfs/volumes.c
··· 4967 4967 } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) { 4968 4968 max_stripe_size = SZ_32M; 4969 4969 max_chunk_size = 2 * max_stripe_size; 4970 + devs_max = min_t(int, devs_max, BTRFS_MAX_DEVS_SYS_CHUNK); 4970 4971 } else { 4971 4972 btrfs_err(info, "invalid chunk type 0x%llx requested", 4972 4973 type);