mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-16 18:26:42 +00:00
for-5.4-rc6-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAl3GwvEACgkQxWXV+ddt WDvsfQ//UQ/TND1roMW3EmN+PLTRTUQS75Hb737r5Q66j0j94gFnBxB03R+tU8lP bH5XVpateb1wDmmdscqVQ1WM9O82bQdDNiYeLDr86+kzpLgy61rZHswZfNlDtl5M wDwyaxsrd7HndDeUZnIuaakYI9MXz9WIaNXkt0o8hSHctt0N18y23DSBFTVSh/4q T3cn4odkoBKtQ4mIn2OSmQvkl69nWRBVpjPJZIvsNszKjOo9aZTuGHrOWUV5RPiE Ho9UBkr+IjEDo8OH88vXAsHeYFIoYhEeUltjLHyF6Agwk1/Ajwp5sxXSubbfHUMQ l1YdmrTZf+l1Dxdj0sCdyK1npcgGI5IuZmIICpNUEAny9AbTtpSE3GNwtnIHAEAr cpki+1Z3lfaVSwNMYUz9Esbsb72C+f08WJHGHBMaOhjrBIwQUeWeYzTx6N7uDwNg GjaDRxjqFV2o7373isQaz7WOTatUMNtL1xvhkeceONI9NBXQRjW5rq5zECmr1ix7 lSTKDzn7yAd6eGBW0T6iYdRl4Bta/zxPiDEF5KDNPugvv23yx17LAOdS4qAiHzbx oglra/kz9D4xmKVqH7hpFaaHrzL38G4mz6aMdwBu0M7dkn9AwsXiXWSDb0n7jnK0 o96gkUBZjUSFBseUFD2s34MikFtrDynEJzPq96JHuWLguaByMcc= =CZxY -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
00aff68362
@ -474,6 +474,7 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
|
|||||||
u64 start = async_chunk->start;
|
u64 start = async_chunk->start;
|
||||||
u64 end = async_chunk->end;
|
u64 end = async_chunk->end;
|
||||||
u64 actual_end;
|
u64 actual_end;
|
||||||
|
u64 i_size;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct page **pages = NULL;
|
struct page **pages = NULL;
|
||||||
unsigned long nr_pages;
|
unsigned long nr_pages;
|
||||||
@ -488,7 +489,19 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
|
|||||||
inode_should_defrag(BTRFS_I(inode), start, end, end - start + 1,
|
inode_should_defrag(BTRFS_I(inode), start, end, end - start + 1,
|
||||||
SZ_16K);
|
SZ_16K);
|
||||||
|
|
||||||
actual_end = min_t(u64, i_size_read(inode), end + 1);
|
/*
|
||||||
|
* We need to save i_size before now because it could change in between
|
||||||
|
* us evaluating the size and assigning it. This is because we lock and
|
||||||
|
* unlock the page in truncate and fallocate, and then modify the i_size
|
||||||
|
* later on.
|
||||||
|
*
|
||||||
|
* The barriers are to emulate READ_ONCE, remove that once i_size_read
|
||||||
|
* does that for us.
|
||||||
|
*/
|
||||||
|
barrier();
|
||||||
|
i_size = i_size_read(inode);
|
||||||
|
barrier();
|
||||||
|
actual_end = min_t(u64, i_size, end + 1);
|
||||||
again:
|
again:
|
||||||
will_compress = 0;
|
will_compress = 0;
|
||||||
nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
|
nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
|
||||||
|
@ -4195,9 +4195,6 @@ static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
|
|||||||
u64 transid;
|
u64 transid;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
btrfs_warn(root->fs_info,
|
|
||||||
"START_SYNC ioctl is deprecated and will be removed in kernel 5.7");
|
|
||||||
|
|
||||||
trans = btrfs_attach_transaction_barrier(root);
|
trans = btrfs_attach_transaction_barrier(root);
|
||||||
if (IS_ERR(trans)) {
|
if (IS_ERR(trans)) {
|
||||||
if (PTR_ERR(trans) != -ENOENT)
|
if (PTR_ERR(trans) != -ENOENT)
|
||||||
@ -4225,9 +4222,6 @@ static noinline long btrfs_ioctl_wait_sync(struct btrfs_fs_info *fs_info,
|
|||||||
{
|
{
|
||||||
u64 transid;
|
u64 transid;
|
||||||
|
|
||||||
btrfs_warn(fs_info,
|
|
||||||
"WAIT_SYNC ioctl is deprecated and will be removed in kernel 5.7");
|
|
||||||
|
|
||||||
if (argp) {
|
if (argp) {
|
||||||
if (copy_from_user(&transid, argp, sizeof(transid)))
|
if (copy_from_user(&transid, argp, sizeof(transid)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -893,6 +893,15 @@ static void wait_reserve_ticket(struct btrfs_fs_info *fs_info,
|
|||||||
while (ticket->bytes > 0 && ticket->error == 0) {
|
while (ticket->bytes > 0 && ticket->error == 0) {
|
||||||
ret = prepare_to_wait_event(&ticket->wait, &wait, TASK_KILLABLE);
|
ret = prepare_to_wait_event(&ticket->wait, &wait, TASK_KILLABLE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
/*
|
||||||
|
* Delete us from the list. After we unlock the space
|
||||||
|
* info, we don't want the async reclaim job to reserve
|
||||||
|
* space for this ticket. If that would happen, then the
|
||||||
|
* ticket's task would not known that space was reserved
|
||||||
|
* despite getting an error, resulting in a space leak
|
||||||
|
* (bytes_may_use counter of our space_info).
|
||||||
|
*/
|
||||||
|
list_del_init(&ticket->list);
|
||||||
ticket->error = -EINTR;
|
ticket->error = -EINTR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -945,12 +954,24 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info,
|
|||||||
spin_lock(&space_info->lock);
|
spin_lock(&space_info->lock);
|
||||||
ret = ticket->error;
|
ret = ticket->error;
|
||||||
if (ticket->bytes || ticket->error) {
|
if (ticket->bytes || ticket->error) {
|
||||||
|
/*
|
||||||
|
* Need to delete here for priority tickets. For regular tickets
|
||||||
|
* either the async reclaim job deletes the ticket from the list
|
||||||
|
* or we delete it ourselves at wait_reserve_ticket().
|
||||||
|
*/
|
||||||
list_del_init(&ticket->list);
|
list_del_init(&ticket->list);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = -ENOSPC;
|
ret = -ENOSPC;
|
||||||
}
|
}
|
||||||
spin_unlock(&space_info->lock);
|
spin_unlock(&space_info->lock);
|
||||||
ASSERT(list_empty(&ticket->list));
|
ASSERT(list_empty(&ticket->list));
|
||||||
|
/*
|
||||||
|
* Check that we can't have an error set if the reservation succeeded,
|
||||||
|
* as that would confuse tasks and lead them to error out without
|
||||||
|
* releasing reserved space (if an error happens the expectation is that
|
||||||
|
* space wasn't reserved at all).
|
||||||
|
*/
|
||||||
|
ASSERT(!(ticket->bytes == 0 && ticket->error));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,9 +686,7 @@ static void dev_item_err(const struct extent_buffer *eb, int slot,
|
|||||||
static int check_dev_item(struct extent_buffer *leaf,
|
static int check_dev_item(struct extent_buffer *leaf,
|
||||||
struct btrfs_key *key, int slot)
|
struct btrfs_key *key, int slot)
|
||||||
{
|
{
|
||||||
struct btrfs_fs_info *fs_info = leaf->fs_info;
|
|
||||||
struct btrfs_dev_item *ditem;
|
struct btrfs_dev_item *ditem;
|
||||||
u64 max_devid = max(BTRFS_MAX_DEVS(fs_info), BTRFS_MAX_DEVS_SYS_CHUNK);
|
|
||||||
|
|
||||||
if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) {
|
if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) {
|
||||||
dev_item_err(leaf, slot,
|
dev_item_err(leaf, slot,
|
||||||
@ -696,12 +694,6 @@ static int check_dev_item(struct extent_buffer *leaf,
|
|||||||
key->objectid, BTRFS_DEV_ITEMS_OBJECTID);
|
key->objectid, BTRFS_DEV_ITEMS_OBJECTID);
|
||||||
return -EUCLEAN;
|
return -EUCLEAN;
|
||||||
}
|
}
|
||||||
if (key->offset > max_devid) {
|
|
||||||
dev_item_err(leaf, slot,
|
|
||||||
"invalid devid: has=%llu expect=[0, %llu]",
|
|
||||||
key->offset, max_devid);
|
|
||||||
return -EUCLEAN;
|
|
||||||
}
|
|
||||||
ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item);
|
ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item);
|
||||||
if (btrfs_device_id(leaf, ditem) != key->offset) {
|
if (btrfs_device_id(leaf, ditem) != key->offset) {
|
||||||
dev_item_err(leaf, slot,
|
dev_item_err(leaf, slot,
|
||||||
|
@ -4967,6 +4967,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
|||||||
} else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
|
} else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
|
||||||
max_stripe_size = SZ_32M;
|
max_stripe_size = SZ_32M;
|
||||||
max_chunk_size = 2 * max_stripe_size;
|
max_chunk_size = 2 * max_stripe_size;
|
||||||
|
devs_max = min_t(int, devs_max, BTRFS_MAX_DEVS_SYS_CHUNK);
|
||||||
} else {
|
} else {
|
||||||
btrfs_err(info, "invalid chunk type 0x%llx requested",
|
btrfs_err(info, "invalid chunk type 0x%llx requested",
|
||||||
type);
|
type);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user