Skip to content

Commit 643e2e2

Browse files
committed
Merge tag 'for-6.13-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A few more fixes. Besides the one-liners in Btrfs there's fix to the io_uring and encoded read integration (added in this development cycle). The update to io_uring provides more space for the ongoing command that is then used in Btrfs to handle some cases. - io_uring and encoded read: - provide stable storage for io_uring command data - make a copy of encoded read ioctl call, reuse that in case the call would block and will be called again - properly initialize zlib context for hardware compression on s390 - fix max extent size calculation on filesystems with non-zoned devices - fix crash in scrub on crafted image due to invalid extent tree" * tag 'for-6.13-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: zlib: fix avail_in bytes for s390 zlib HW compression path btrfs: zoned: calculate max_extent_size properly on non-zoned setup btrfs: avoid NULL pointer dereference if no valid extent tree btrfs: don't read from userspace twice in btrfs_uring_encoded_read() io_uring: add io_uring_cmd_get_async_data helper io_uring/cmd: add per-op data to struct io_uring_cmd_data io_uring/cmd: rename struct uring_cache to io_uring_cmd_data
2 parents eea6e4b + 0ee4736 commit 643e2e2

File tree

9 files changed

+103
-74
lines changed

9 files changed

+103
-74
lines changed

fs/btrfs/ioctl.c

Lines changed: 65 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4878,25 +4878,29 @@ static int btrfs_uring_read_extent(struct kiocb *iocb, struct iov_iter *iter,
48784878
return ret;
48794879
}
48804880

4881+
struct btrfs_uring_encoded_data {
4882+
struct btrfs_ioctl_encoded_io_args args;
4883+
struct iovec iovstack[UIO_FASTIOV];
4884+
struct iovec *iov;
4885+
struct iov_iter iter;
4886+
};
4887+
48814888
static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue_flags)
48824889
{
48834890
size_t copy_end_kernel = offsetofend(struct btrfs_ioctl_encoded_io_args, flags);
48844891
size_t copy_end;
4885-
struct btrfs_ioctl_encoded_io_args args = { 0 };
48864892
int ret;
48874893
u64 disk_bytenr, disk_io_size;
48884894
struct file *file;
48894895
struct btrfs_inode *inode;
48904896
struct btrfs_fs_info *fs_info;
48914897
struct extent_io_tree *io_tree;
4892-
struct iovec iovstack[UIO_FASTIOV];
4893-
struct iovec *iov = iovstack;
4894-
struct iov_iter iter;
48954898
loff_t pos;
48964899
struct kiocb kiocb;
48974900
struct extent_state *cached_state = NULL;
48984901
u64 start, lockend;
48994902
void __user *sqe_addr;
4903+
struct btrfs_uring_encoded_data *data = io_uring_cmd_get_async_data(cmd)->op_data;
49004904

49014905
if (!capable(CAP_SYS_ADMIN)) {
49024906
ret = -EPERM;
@@ -4910,43 +4914,64 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
49104914

49114915
if (issue_flags & IO_URING_F_COMPAT) {
49124916
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
4913-
struct btrfs_ioctl_encoded_io_args_32 args32;
4914-
49154917
copy_end = offsetofend(struct btrfs_ioctl_encoded_io_args_32, flags);
4916-
if (copy_from_user(&args32, sqe_addr, copy_end)) {
4917-
ret = -EFAULT;
4918-
goto out_acct;
4919-
}
4920-
args.iov = compat_ptr(args32.iov);
4921-
args.iovcnt = args32.iovcnt;
4922-
args.offset = args32.offset;
4923-
args.flags = args32.flags;
49244918
#else
49254919
return -ENOTTY;
49264920
#endif
49274921
} else {
49284922
copy_end = copy_end_kernel;
4929-
if (copy_from_user(&args, sqe_addr, copy_end)) {
4930-
ret = -EFAULT;
4923+
}
4924+
4925+
if (!data) {
4926+
data = kzalloc(sizeof(*data), GFP_NOFS);
4927+
if (!data) {
4928+
ret = -ENOMEM;
49314929
goto out_acct;
49324930
}
4933-
}
49344931

4935-
if (args.flags != 0)
4936-
return -EINVAL;
4932+
io_uring_cmd_get_async_data(cmd)->op_data = data;
49374933

4938-
ret = import_iovec(ITER_DEST, args.iov, args.iovcnt, ARRAY_SIZE(iovstack),
4939-
&iov, &iter);
4940-
if (ret < 0)
4941-
goto out_acct;
4934+
if (issue_flags & IO_URING_F_COMPAT) {
4935+
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
4936+
struct btrfs_ioctl_encoded_io_args_32 args32;
49424937

4943-
if (iov_iter_count(&iter) == 0) {
4944-
ret = 0;
4945-
goto out_free;
4938+
if (copy_from_user(&args32, sqe_addr, copy_end)) {
4939+
ret = -EFAULT;
4940+
goto out_acct;
4941+
}
4942+
4943+
data->args.iov = compat_ptr(args32.iov);
4944+
data->args.iovcnt = args32.iovcnt;
4945+
data->args.offset = args32.offset;
4946+
data->args.flags = args32.flags;
4947+
#endif
4948+
} else {
4949+
if (copy_from_user(&data->args, sqe_addr, copy_end)) {
4950+
ret = -EFAULT;
4951+
goto out_acct;
4952+
}
4953+
}
4954+
4955+
if (data->args.flags != 0) {
4956+
ret = -EINVAL;
4957+
goto out_acct;
4958+
}
4959+
4960+
data->iov = data->iovstack;
4961+
ret = import_iovec(ITER_DEST, data->args.iov, data->args.iovcnt,
4962+
ARRAY_SIZE(data->iovstack), &data->iov,
4963+
&data->iter);
4964+
if (ret < 0)
4965+
goto out_acct;
4966+
4967+
if (iov_iter_count(&data->iter) == 0) {
4968+
ret = 0;
4969+
goto out_free;
4970+
}
49464971
}
49474972

4948-
pos = args.offset;
4949-
ret = rw_verify_area(READ, file, &pos, args.len);
4973+
pos = data->args.offset;
4974+
ret = rw_verify_area(READ, file, &pos, data->args.len);
49504975
if (ret < 0)
49514976
goto out_free;
49524977

@@ -4959,15 +4984,16 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
49594984
start = ALIGN_DOWN(pos, fs_info->sectorsize);
49604985
lockend = start + BTRFS_MAX_UNCOMPRESSED - 1;
49614986

4962-
ret = btrfs_encoded_read(&kiocb, &iter, &args, &cached_state,
4987+
ret = btrfs_encoded_read(&kiocb, &data->iter, &data->args, &cached_state,
49634988
&disk_bytenr, &disk_io_size);
49644989
if (ret < 0 && ret != -EIOCBQUEUED)
49654990
goto out_free;
49664991

49674992
file_accessed(file);
49684993

4969-
if (copy_to_user(sqe_addr + copy_end, (const char *)&args + copy_end_kernel,
4970-
sizeof(args) - copy_end_kernel)) {
4994+
if (copy_to_user(sqe_addr + copy_end,
4995+
(const char *)&data->args + copy_end_kernel,
4996+
sizeof(data->args) - copy_end_kernel)) {
49714997
if (ret == -EIOCBQUEUED) {
49724998
unlock_extent(io_tree, start, lockend, &cached_state);
49734999
btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
@@ -4977,40 +5003,22 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
49775003
}
49785004

49795005
if (ret == -EIOCBQUEUED) {
4980-
u64 count;
4981-
4982-
/*
4983-
* If we've optimized things by storing the iovecs on the stack,
4984-
* undo this.
4985-
*/
4986-
if (!iov) {
4987-
iov = kmalloc(sizeof(struct iovec) * args.iovcnt, GFP_NOFS);
4988-
if (!iov) {
4989-
unlock_extent(io_tree, start, lockend, &cached_state);
4990-
btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
4991-
ret = -ENOMEM;
4992-
goto out_acct;
4993-
}
4994-
4995-
memcpy(iov, iovstack, sizeof(struct iovec) * args.iovcnt);
4996-
}
4997-
4998-
count = min_t(u64, iov_iter_count(&iter), disk_io_size);
5006+
u64 count = min_t(u64, iov_iter_count(&data->iter), disk_io_size);
49995007

50005008
/* Match ioctl by not returning past EOF if uncompressed. */
5001-
if (!args.compression)
5002-
count = min_t(u64, count, args.len);
5009+
if (!data->args.compression)
5010+
count = min_t(u64, count, data->args.len);
50035011

5004-
ret = btrfs_uring_read_extent(&kiocb, &iter, start, lockend,
5005-
cached_state, disk_bytenr,
5006-
disk_io_size, count,
5007-
args.compression, iov, cmd);
5012+
ret = btrfs_uring_read_extent(&kiocb, &data->iter, start, lockend,
5013+
cached_state, disk_bytenr, disk_io_size,
5014+
count, data->args.compression,
5015+
data->iov, cmd);
50085016

50095017
goto out_acct;
50105018
}
50115019

50125020
out_free:
5013-
kfree(iov);
5021+
kfree(data->iov);
50145022

50155023
out_acct:
50165024
if (ret > 0)

fs/btrfs/scrub.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,10 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
15411541
u64 extent_gen;
15421542
int ret;
15431543

1544+
if (unlikely(!extent_root)) {
1545+
btrfs_err(fs_info, "no valid extent root for scrub");
1546+
return -EUCLEAN;
1547+
}
15441548
memset(stripe->sectors, 0, sizeof(struct scrub_sector_verification) *
15451549
stripe->nr_sectors);
15461550
scrub_stripe_reset_bitmaps(stripe);

fs/btrfs/zlib.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,10 @@ int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
174174
copy_page(workspace->buf + i * PAGE_SIZE,
175175
data_in);
176176
start += PAGE_SIZE;
177-
workspace->strm.avail_in =
178-
(in_buf_folios << PAGE_SHIFT);
179177
}
180178
workspace->strm.next_in = workspace->buf;
179+
workspace->strm.avail_in = min(bytes_left,
180+
in_buf_folios << PAGE_SHIFT);
181181
} else {
182182
unsigned int pg_off;
183183
unsigned int cur_len;

fs/btrfs/zoned.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -748,8 +748,9 @@ int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info)
748748
(u64)lim->max_segments << PAGE_SHIFT),
749749
fs_info->sectorsize);
750750
fs_info->fs_devices->chunk_alloc_policy = BTRFS_CHUNK_ALLOC_ZONED;
751-
if (fs_info->max_zone_append_size < fs_info->max_extent_size)
752-
fs_info->max_extent_size = fs_info->max_zone_append_size;
751+
752+
fs_info->max_extent_size = min_not_zero(fs_info->max_extent_size,
753+
fs_info->max_zone_append_size);
753754

754755
/*
755756
* Check mount options here, because we might change fs_info->zoned

include/linux/io_uring/cmd.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ struct io_uring_cmd {
1818
u8 pdu[32]; /* available inline for free use */
1919
};
2020

21+
struct io_uring_cmd_data {
22+
struct io_uring_sqe sqes[2];
23+
void *op_data;
24+
};
25+
2126
static inline const void *io_uring_sqe_cmd(const struct io_uring_sqe *sqe)
2227
{
2328
return sqe->cmd;
@@ -113,4 +118,9 @@ static inline struct task_struct *io_uring_cmd_get_task(struct io_uring_cmd *cmd
113118
return cmd_to_io_kiocb(cmd)->tctx->task;
114119
}
115120

121+
static inline struct io_uring_cmd_data *io_uring_cmd_get_async_data(struct io_uring_cmd *cmd)
122+
{
123+
return cmd_to_io_kiocb(cmd)->async_data;
124+
}
125+
116126
#endif /* _LINUX_IO_URING_CMD_H */

io_uring/io_uring.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
320320
ret |= io_alloc_cache_init(&ctx->rw_cache, IO_ALLOC_CACHE_MAX,
321321
sizeof(struct io_async_rw));
322322
ret |= io_alloc_cache_init(&ctx->uring_cache, IO_ALLOC_CACHE_MAX,
323-
sizeof(struct uring_cache));
323+
sizeof(struct io_uring_cmd_data));
324324
spin_lock_init(&ctx->msg_lock);
325325
ret |= io_alloc_cache_init(&ctx->msg_cache, IO_ALLOC_CACHE_MAX,
326326
sizeof(struct io_kiocb));

io_uring/opdef.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/fs.h>
88
#include <linux/file.h>
99
#include <linux/io_uring.h>
10+
#include <linux/io_uring/cmd.h>
1011

1112
#include "io_uring.h"
1213
#include "opdef.h"
@@ -414,7 +415,7 @@ const struct io_issue_def io_issue_defs[] = {
414415
.plug = 1,
415416
.iopoll = 1,
416417
.iopoll_queue = 1,
417-
.async_size = 2 * sizeof(struct io_uring_sqe),
418+
.async_size = sizeof(struct io_uring_cmd_data),
418419
.prep = io_uring_cmd_prep,
419420
.issue = io_uring_cmd,
420421
},

io_uring/uring_cmd.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,35 @@
1616
#include "rsrc.h"
1717
#include "uring_cmd.h"
1818

19-
static struct uring_cache *io_uring_async_get(struct io_kiocb *req)
19+
static struct io_uring_cmd_data *io_uring_async_get(struct io_kiocb *req)
2020
{
2121
struct io_ring_ctx *ctx = req->ctx;
22-
struct uring_cache *cache;
22+
struct io_uring_cmd_data *cache;
2323

2424
cache = io_alloc_cache_get(&ctx->uring_cache);
2525
if (cache) {
26+
cache->op_data = NULL;
2627
req->flags |= REQ_F_ASYNC_DATA;
2728
req->async_data = cache;
2829
return cache;
2930
}
30-
if (!io_alloc_async_data(req))
31-
return req->async_data;
31+
if (!io_alloc_async_data(req)) {
32+
cache = req->async_data;
33+
cache->op_data = NULL;
34+
return cache;
35+
}
3236
return NULL;
3337
}
3438

3539
static void io_req_uring_cleanup(struct io_kiocb *req, unsigned int issue_flags)
3640
{
3741
struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
38-
struct uring_cache *cache = req->async_data;
42+
struct io_uring_cmd_data *cache = req->async_data;
43+
44+
if (cache->op_data) {
45+
kfree(cache->op_data);
46+
cache->op_data = NULL;
47+
}
3948

4049
if (issue_flags & IO_URING_F_UNLOCKED)
4150
return;
@@ -183,7 +192,7 @@ static int io_uring_cmd_prep_setup(struct io_kiocb *req,
183192
const struct io_uring_sqe *sqe)
184193
{
185194
struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
186-
struct uring_cache *cache;
195+
struct io_uring_cmd_data *cache;
187196

188197
cache = io_uring_async_get(req);
189198
if (unlikely(!cache))
@@ -260,7 +269,7 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
260269

261270
ret = file->f_op->uring_cmd(ioucmd, issue_flags);
262271
if (ret == -EAGAIN) {
263-
struct uring_cache *cache = req->async_data;
272+
struct io_uring_cmd_data *cache = req->async_data;
264273

265274
if (ioucmd->sqe != (void *) cache)
266275
memcpy(cache, ioucmd->sqe, uring_sqe_size(req->ctx));

io_uring/uring_cmd.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
// SPDX-License-Identifier: GPL-2.0
22

3-
struct uring_cache {
4-
struct io_uring_sqe sqes[2];
5-
};
6-
73
int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags);
84
int io_uring_cmd_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
95

0 commit comments

Comments
 (0)