* [RFC PATCH 0/2] introduce io_uring_cmd_import_fixed_vec
@ 2025-03-11 11:40 Sidong Yang
2025-03-11 11:40 ` [RFC PATCH 1/2] io_uring: cmd: " Sidong Yang
2025-03-11 11:40 ` [RFC PATCH 2/2] btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED Sidong Yang
0 siblings, 2 replies; 10+ messages in thread
From: Sidong Yang @ 2025-03-11 11:40 UTC (permalink / raw)
To: Jens Axboe, Pavel Begunkov, Josef Bacik, David Sterba
Cc: Sidong Yang, io-uring, linux-kernel, linux-btrfs
This patche series introduce io_uring_cmd_import_vec. With this function,
Multiple fixed buffer could be used in uring cmd. It's vectored version
for io_uring_cmd_import_fixed(). Also this patch series includes a usage
for new api for encoded read in btrfs by using uring cmd.
Sidong Yang (2):
io_uring: cmd: introduce io_uring_cmd_import_fixed_vec
btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED
fs/btrfs/ioctl.c | 26 +++++++++++++++++++++-----
include/linux/io_uring/cmd.h | 14 ++++++++++++++
io_uring/uring_cmd.c | 29 +++++++++++++++++++++++++++++
3 files changed, 64 insertions(+), 5 deletions(-)
---
Recently, I've found that io_import_reg_vec() was added for io-uring. I think
it could be used for io-uring cmd. I've tested for btrfs encoded read and it
works. But it seems that there is no performance improvements and I'll keep
find why.
If there is no need to use fixed buffer for btrfs, I think it's good to use
for nvme.
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC PATCH 1/2] io_uring: cmd: introduce io_uring_cmd_import_fixed_vec
2025-03-11 11:40 [RFC PATCH 0/2] introduce io_uring_cmd_import_fixed_vec Sidong Yang
@ 2025-03-11 11:40 ` Sidong Yang
2025-03-11 13:08 ` Pavel Begunkov
` (2 more replies)
2025-03-11 11:40 ` [RFC PATCH 2/2] btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED Sidong Yang
1 sibling, 3 replies; 10+ messages in thread
From: Sidong Yang @ 2025-03-11 11:40 UTC (permalink / raw)
To: Jens Axboe, Pavel Begunkov, Josef Bacik, David Sterba
Cc: Sidong Yang, io-uring, linux-kernel, linux-btrfs
io_uring_cmd_import_fixed_vec() could be used for using multiple
fixed buffer in uring_cmd callback.
Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
---
include/linux/io_uring/cmd.h | 14 ++++++++++++++
io_uring/uring_cmd.c | 29 +++++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/include/linux/io_uring/cmd.h b/include/linux/io_uring/cmd.h
index 598cacda4aa3..75cf25c1e730 100644
--- a/include/linux/io_uring/cmd.h
+++ b/include/linux/io_uring/cmd.h
@@ -44,6 +44,13 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
struct io_uring_cmd *ioucmd,
unsigned int issue_flags);
+int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
+ unsigned long nr_segs, int rw,
+ struct iov_iter *iter,
+ struct io_uring_cmd *ioucmd,
+ struct iou_vec *iou_vec, bool compat,
+ unsigned int issue_flags);
+
/*
* Completes the request, i.e. posts an io_uring CQE and deallocates @ioucmd
* and the corresponding io_uring request.
@@ -76,6 +83,13 @@ io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
{
return -EOPNOTSUPP;
}
+int io_uring_cmd_import_fixed_vec(int rw, struct iov_iter *iter,
+ struct io_uring_cmd *ioucmd,
+ struct iou_vec *vec, unsigned nr_iovs,
+ unsigned iovec_off, unsigned int issue_flags)
+{
+ return -EOPNOTSUPP;
+}
static inline void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret,
u64 ret2, unsigned issue_flags)
{
diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
index de39b602aa82..58e2932f29e7 100644
--- a/io_uring/uring_cmd.c
+++ b/io_uring/uring_cmd.c
@@ -255,6 +255,35 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
}
EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed);
+int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
+ unsigned long nr_segs, int rw,
+ struct iov_iter *iter,
+ struct io_uring_cmd *ioucmd,
+ struct iou_vec *iou_vec, bool compat,
+ unsigned int issue_flags)
+{
+ struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
+ struct iovec *iov;
+ int ret;
+
+ iov = iovec_from_user(uiovec, nr_segs, 0, NULL, compat);
+ if (IS_ERR(iov))
+ return PTR_ERR(iov);
+
+ ret = io_vec_realloc(iou_vec, nr_segs);
+ if (ret) {
+ kfree(iov);
+ return ret;
+ }
+ memcpy(iou_vec->iovec, iov, sizeof(*iov) * nr_segs);
+ kfree(iov);
+
+ ret = io_import_reg_vec(rw, iter, req, iou_vec, iou_vec->nr, 0,
+ issue_flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed_vec);
+
void io_uring_cmd_issue_blocking(struct io_uring_cmd *ioucmd)
{
struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH 2/2] btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED
2025-03-11 11:40 [RFC PATCH 0/2] introduce io_uring_cmd_import_fixed_vec Sidong Yang
2025-03-11 11:40 ` [RFC PATCH 1/2] io_uring: cmd: " Sidong Yang
@ 2025-03-11 11:40 ` Sidong Yang
2025-03-11 12:55 ` Pavel Begunkov
2025-03-12 11:11 ` kernel test robot
1 sibling, 2 replies; 10+ messages in thread
From: Sidong Yang @ 2025-03-11 11:40 UTC (permalink / raw)
To: Jens Axboe, Pavel Begunkov, Josef Bacik, David Sterba
Cc: Sidong Yang, io-uring, linux-kernel, linux-btrfs
This patch supports IORING_URING_CMD_FIXED flags in io-uring cmd. It
means that user provided buf_index in sqe that is registered before
submitting requests. In this patch, btrfs_uring_encoded_read() makes
iov_iter bvec type by checking the io-uring cmd flag. And there is
additional iou_vec field in btrfs_uring_priv for remaining bvecs
lifecycle.
Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
---
fs/btrfs/ioctl.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 6c18bad53cd3..586671eea622 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4643,6 +4643,7 @@ struct btrfs_uring_priv {
struct page **pages;
unsigned long nr_pages;
struct kiocb iocb;
+ struct iou_vec iou_vec;
struct iovec *iov;
struct iov_iter iter;
struct extent_state *cached_state;
@@ -4711,6 +4712,8 @@ static void btrfs_uring_read_finished(struct io_uring_cmd *cmd, unsigned int iss
kfree(priv->pages);
kfree(priv->iov);
+ if (priv->iou_vec.iovec)
+ kfree(priv->iou_vec.iovec);
kfree(priv);
}
@@ -4730,7 +4733,8 @@ static int btrfs_uring_read_extent(struct kiocb *iocb, struct iov_iter *iter,
struct extent_state *cached_state,
u64 disk_bytenr, u64 disk_io_size,
size_t count, bool compressed,
- struct iovec *iov, struct io_uring_cmd *cmd)
+ struct iovec *iov, struct io_uring_cmd *cmd,
+ struct iou_vec *iou_vec)
{
struct btrfs_inode *inode = BTRFS_I(file_inode(iocb->ki_filp));
struct extent_io_tree *io_tree = &inode->io_tree;
@@ -4767,6 +4771,7 @@ static int btrfs_uring_read_extent(struct kiocb *iocb, struct iov_iter *iter,
priv->start = start;
priv->lockend = lockend;
priv->err = 0;
+ priv->iou_vec = *iou_vec;
ret = btrfs_encoded_read_regular_fill_pages(inode, disk_bytenr,
disk_io_size, pages, priv);
@@ -4818,6 +4823,7 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
u64 start, lockend;
void __user *sqe_addr;
struct btrfs_uring_encoded_data *data = io_uring_cmd_get_async_data(cmd)->op_data;
+ struct iou_vec iou_vec = {};
if (!capable(CAP_SYS_ADMIN)) {
ret = -EPERM;
@@ -4875,9 +4881,19 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
}
data->iov = data->iovstack;
- ret = import_iovec(ITER_DEST, data->args.iov, data->args.iovcnt,
- ARRAY_SIZE(data->iovstack), &data->iov,
- &data->iter);
+
+ if (cmd && (cmd->flags & IORING_URING_CMD_FIXED)) {
+ ret = io_uring_cmd_import_fixed_vec(
+ data->args.iov, data->args.iovcnt, ITER_DEST,
+ &data->iter, cmd, &iou_vec, false, issue_flags);
+ data->iov = NULL;
+ } else {
+ ret = import_iovec(ITER_DEST, data->args.iov,
+ data->args.iovcnt,
+ ARRAY_SIZE(data->iovstack),
+ &data->iov, &data->iter);
+ }
+
if (ret < 0)
goto out_acct;
@@ -4929,7 +4945,7 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
ret = btrfs_uring_read_extent(&kiocb, &data->iter, start, lockend,
cached_state, disk_bytenr, disk_io_size,
count, data->args.compression,
- data->iov, cmd);
+ data->iov, cmd, &iou_vec);
goto out_acct;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 2/2] btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED
2025-03-11 11:40 ` [RFC PATCH 2/2] btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED Sidong Yang
@ 2025-03-11 12:55 ` Pavel Begunkov
2025-03-12 3:05 ` Sidong Yang
2025-03-12 11:11 ` kernel test robot
1 sibling, 1 reply; 10+ messages in thread
From: Pavel Begunkov @ 2025-03-11 12:55 UTC (permalink / raw)
To: Sidong Yang, Jens Axboe, Josef Bacik, David Sterba
Cc: io-uring, linux-kernel, linux-btrfs
On 3/11/25 11:40, Sidong Yang wrote:
> This patch supports IORING_URING_CMD_FIXED flags in io-uring cmd. It
> means that user provided buf_index in sqe that is registered before
> submitting requests. In this patch, btrfs_uring_encoded_read() makes
> iov_iter bvec type by checking the io-uring cmd flag. And there is
> additional iou_vec field in btrfs_uring_priv for remaining bvecs
> lifecycle.
>
> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> ---
> fs/btrfs/ioctl.c | 26 +++++++++++++++++++++-----
> 1 file changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6c18bad53cd3..586671eea622 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -4643,6 +4643,7 @@ struct btrfs_uring_priv {
> struct page **pages;
> unsigned long nr_pages;
> struct kiocb iocb;
> + struct iou_vec iou_vec;
This structure should not be leaked out of core io_uring ...
> struct iovec *iov;
> struct iov_iter iter;
> struct extent_state *cached_state;
> @@ -4711,6 +4712,8 @@ static void btrfs_uring_read_finished(struct io_uring_cmd *cmd, unsigned int iss
>
> kfree(priv->pages);
> kfree(priv->iov);
> + if (priv->iou_vec.iovec)
> + kfree(priv->iou_vec.iovec);
... exactly because if this. This line relies on details it
shouldn't.
--
Pavel Begunkov
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 1/2] io_uring: cmd: introduce io_uring_cmd_import_fixed_vec
2025-03-11 11:40 ` [RFC PATCH 1/2] io_uring: cmd: " Sidong Yang
@ 2025-03-11 13:08 ` Pavel Begunkov
2025-03-12 3:08 ` Sidong Yang
2025-03-12 9:59 ` kernel test robot
2025-03-12 10:10 ` kernel test robot
2 siblings, 1 reply; 10+ messages in thread
From: Pavel Begunkov @ 2025-03-11 13:08 UTC (permalink / raw)
To: Sidong Yang, Jens Axboe, Josef Bacik, David Sterba
Cc: io-uring, linux-kernel, linux-btrfs
On 3/11/25 11:40, Sidong Yang wrote:
> io_uring_cmd_import_fixed_vec() could be used for using multiple
> fixed buffer in uring_cmd callback.
>
> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> ---
> include/linux/io_uring/cmd.h | 14 ++++++++++++++
> io_uring/uring_cmd.c | 29 +++++++++++++++++++++++++++++
> 2 files changed, 43 insertions(+)
>
> diff --git a/include/linux/io_uring/cmd.h b/include/linux/io_uring/cmd.h
> index 598cacda4aa3..75cf25c1e730 100644
> --- a/include/linux/io_uring/cmd.h
> +++ b/include/linux/io_uring/cmd.h
> @@ -44,6 +44,13 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
> struct io_uring_cmd *ioucmd,
> unsigned int issue_flags);
>
> +int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
> + unsigned long nr_segs, int rw,
> + struct iov_iter *iter,
> + struct io_uring_cmd *ioucmd,
nit: it's better to be the first arg
> + struct iou_vec *iou_vec, bool compat,
Same comment, iou_vec should not be exposed. And why do we
need to pass compat here? Instead of io_is_compat() inside
the helper.
> + unsigned int issue_flags);
> +
> /*
> * Completes the request, i.e. posts an io_uring CQE and deallocates @ioucmd
> * and the corresponding io_uring request.
> @@ -76,6 +83,13 @@ io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
> {
> return -EOPNOTSUPP;
> }
> +int io_uring_cmd_import_fixed_vec(int rw, struct iov_iter *iter,
> + struct io_uring_cmd *ioucmd,
> + struct iou_vec *vec, unsigned nr_iovs,
> + unsigned iovec_off, unsigned int issue_flags)
> +{
> + return -EOPNOTSUPP;
> +}
> static inline void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret,
> u64 ret2, unsigned issue_flags)
> {
> diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
> index de39b602aa82..58e2932f29e7 100644
> --- a/io_uring/uring_cmd.c
> +++ b/io_uring/uring_cmd.c
> @@ -255,6 +255,35 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
> }
> EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed);
>
> +int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
> + unsigned long nr_segs, int rw,
> + struct iov_iter *iter,
> + struct io_uring_cmd *ioucmd,
> + struct iou_vec *iou_vec, bool compat,
> + unsigned int issue_flags)
> +{
> + struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
> + struct iovec *iov;
> + int ret;
> +
> + iov = iovec_from_user(uiovec, nr_segs, 0, NULL, compat);
> + if (IS_ERR(iov))
> + return PTR_ERR(iov);
That's one allocation
> +
> + ret = io_vec_realloc(iou_vec, nr_segs);
That's a second one
> + if (ret) {
> + kfree(iov);
> + return ret;
> + }
> + memcpy(iou_vec->iovec, iov, sizeof(*iov) * nr_segs);
> + kfree(iov);
> +
> + ret = io_import_reg_vec(rw, iter, req, iou_vec, iou_vec->nr, 0,
It's slightly out of date, the import side should use io_prep_reg_iovec(),
it abstracts from iovec placement questions.
> + issue_flags);
And there will likely be a 3rd one. That's pretty likely why
performance is not up to expectations, unlike the rw/net
side which cache it to eventually 0 realloctions.
The first one can be easily removed, but it'll need better
abstractions for cmds not to expose iou_vec. Let me think
what would be a good approach here.
--
Pavel Begunkov
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 2/2] btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED
2025-03-11 12:55 ` Pavel Begunkov
@ 2025-03-12 3:05 ` Sidong Yang
0 siblings, 0 replies; 10+ messages in thread
From: Sidong Yang @ 2025-03-12 3:05 UTC (permalink / raw)
To: Pavel Begunkov
Cc: Jens Axboe, Josef Bacik, David Sterba, io-uring, linux-kernel,
linux-btrfs
On Tue, Mar 11, 2025 at 12:55:48PM +0000, Pavel Begunkov wrote:
Hi Pavel,
> On 3/11/25 11:40, Sidong Yang wrote:
> > This patch supports IORING_URING_CMD_FIXED flags in io-uring cmd. It
> > means that user provided buf_index in sqe that is registered before
> > submitting requests. In this patch, btrfs_uring_encoded_read() makes
> > iov_iter bvec type by checking the io-uring cmd flag. And there is
> > additional iou_vec field in btrfs_uring_priv for remaining bvecs
> > lifecycle.
> >
> > Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> > ---
> > fs/btrfs/ioctl.c | 26 +++++++++++++++++++++-----
> > 1 file changed, 21 insertions(+), 5 deletions(-)
> >
> > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> > index 6c18bad53cd3..586671eea622 100644
> > --- a/fs/btrfs/ioctl.c
> > +++ b/fs/btrfs/ioctl.c
> > @@ -4643,6 +4643,7 @@ struct btrfs_uring_priv {
> > struct page **pages;
> > unsigned long nr_pages;
> > struct kiocb iocb;
> > + struct iou_vec iou_vec;
>
> This structure should not be leaked out of core io_uring ...
Agreed, but this was needed that priv needs to have bvec than iovec.
Thinking about this, just adding bvec or make union with iov is
simple way to do this.
>
> > struct iovec *iov;
> > struct iov_iter iter;
> > struct extent_state *cached_state;
> > @@ -4711,6 +4712,8 @@ static void btrfs_uring_read_finished(struct io_uring_cmd *cmd, unsigned int iss
> > kfree(priv->pages);
> > kfree(priv->iov);
> > + if (priv->iou_vec.iovec)
> > + kfree(priv->iou_vec.iovec);
>
> ... exactly because if this. This line relies on details it
> shouldn't.
Yes, we don't need this.
Thanks,
Sidong
>
> --
> Pavel Begunkov
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 1/2] io_uring: cmd: introduce io_uring_cmd_import_fixed_vec
2025-03-11 13:08 ` Pavel Begunkov
@ 2025-03-12 3:08 ` Sidong Yang
0 siblings, 0 replies; 10+ messages in thread
From: Sidong Yang @ 2025-03-12 3:08 UTC (permalink / raw)
To: Pavel Begunkov
Cc: Jens Axboe, Josef Bacik, David Sterba, io-uring, linux-kernel,
linux-btrfs
On Tue, Mar 11, 2025 at 01:08:14PM +0000, Pavel Begunkov wrote:
> On 3/11/25 11:40, Sidong Yang wrote:
> > io_uring_cmd_import_fixed_vec() could be used for using multiple
> > fixed buffer in uring_cmd callback.
> >
> > Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> > ---
> > include/linux/io_uring/cmd.h | 14 ++++++++++++++
> > io_uring/uring_cmd.c | 29 +++++++++++++++++++++++++++++
> > 2 files changed, 43 insertions(+)
> >
> > diff --git a/include/linux/io_uring/cmd.h b/include/linux/io_uring/cmd.h
> > index 598cacda4aa3..75cf25c1e730 100644
> > --- a/include/linux/io_uring/cmd.h
> > +++ b/include/linux/io_uring/cmd.h
> > @@ -44,6 +44,13 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
> > struct io_uring_cmd *ioucmd,
> > unsigned int issue_flags);
> > +int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
> > + unsigned long nr_segs, int rw,
> > + struct iov_iter *iter,
> > + struct io_uring_cmd *ioucmd,
>
> nit: it's better to be the first arg
Thanks for tip.
>
> > + struct iou_vec *iou_vec, bool compat,
>
> Same comment, iou_vec should not be exposed. And why do we
> need to pass compat here? Instead of io_is_compat() inside
> the helper.
Actually I don't know about io_is_compat(). Thanks.
>
> > + unsigned int issue_flags);
> > +
> > /*
> > * Completes the request, i.e. posts an io_uring CQE and deallocates @ioucmd
> > * and the corresponding io_uring request.
> > @@ -76,6 +83,13 @@ io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
> > {
> > return -EOPNOTSUPP;
> > }
> > +int io_uring_cmd_import_fixed_vec(int rw, struct iov_iter *iter,
> > + struct io_uring_cmd *ioucmd,
> > + struct iou_vec *vec, unsigned nr_iovs,
> > + unsigned iovec_off, unsigned int issue_flags)
> > +{
> > + return -EOPNOTSUPP;
> > +}
> > static inline void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret,
> > u64 ret2, unsigned issue_flags)
> > {
> > diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
> > index de39b602aa82..58e2932f29e7 100644
> > --- a/io_uring/uring_cmd.c
> > +++ b/io_uring/uring_cmd.c
> > @@ -255,6 +255,35 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
> > }
> > EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed);
> > +int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
> > + unsigned long nr_segs, int rw,
> > + struct iov_iter *iter,
> > + struct io_uring_cmd *ioucmd,
> > + struct iou_vec *iou_vec, bool compat,
> > + unsigned int issue_flags)
> > +{
> > + struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
> > + struct iovec *iov;
> > + int ret;
> > +
> > + iov = iovec_from_user(uiovec, nr_segs, 0, NULL, compat);
> > + if (IS_ERR(iov))
> > + return PTR_ERR(iov);
>
> That's one allocation
>
> > +
> > + ret = io_vec_realloc(iou_vec, nr_segs);
>
> That's a second one
>
> > + if (ret) {
> > + kfree(iov);
> > + return ret;
> > + }
> > + memcpy(iou_vec->iovec, iov, sizeof(*iov) * nr_segs);
> > + kfree(iov);
> > +
> > + ret = io_import_reg_vec(rw, iter, req, iou_vec, iou_vec->nr, 0,
>
> It's slightly out of date, the import side should use io_prep_reg_iovec(),
> it abstracts from iovec placement questions.
>
> > + issue_flags);
>
> And there will likely be a 3rd one. That's pretty likely why
> performance is not up to expectations, unlike the rw/net
> side which cache it to eventually 0 realloctions.
>
> The first one can be easily removed, but it'll need better
> abstractions for cmds not to expose iou_vec. Let me think
> what would be a good approach here.
Totally agreed, There is too many allocation for this. It should be done
allocation.
Thanks,
Sidong
>
> --
> Pavel Begunkov
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 1/2] io_uring: cmd: introduce io_uring_cmd_import_fixed_vec
2025-03-11 11:40 ` [RFC PATCH 1/2] io_uring: cmd: " Sidong Yang
2025-03-11 13:08 ` Pavel Begunkov
@ 2025-03-12 9:59 ` kernel test robot
2025-03-12 10:10 ` kernel test robot
2 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2025-03-12 9:59 UTC (permalink / raw)
To: Sidong Yang; +Cc: llvm, oe-kbuild-all
Hi Sidong,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build warnings:
[auto build test WARNING on next-20250307]
[also build test WARNING on v6.14-rc6]
[cannot apply to kdave/for-next linus/master v6.14-rc6 v6.14-rc5 v6.14-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sidong-Yang/io_uring-cmd-introduce-io_uring_cmd_import_fixed_vec/20250311-194620
base: next-20250307
patch link: https://lore.kernel.org/r/20250311114053.216359-2-sidong.yang%40furiosa.ai
patch subject: [RFC PATCH 1/2] io_uring: cmd: introduce io_uring_cmd_import_fixed_vec
config: i386-buildonly-randconfig-003-20250312 (https://download.01.org/0day-ci/archive/20250312/202503121708.ZioDSAXU-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250312/202503121708.ZioDSAXU-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503121708.ZioDSAXU-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from io_uring/uring_cmd.c:5:
include/linux/io_uring/cmd.h:51:42: warning: 'struct iou_vec' declared inside parameter list will not be visible outside of this definition or declaration
51 | struct iou_vec *iou_vec, bool compat,
| ^~~~~~~
>> io_uring/uring_cmd.c:262:42: warning: 'struct iou_vec' declared inside parameter list will not be visible outside of this definition or declaration
262 | struct iou_vec *iou_vec, bool compat,
| ^~~~~~~
io_uring/uring_cmd.c:258:5: error: conflicting types for 'io_uring_cmd_import_fixed_vec'; have 'int(const struct iovec *, long unsigned int, int, struct iov_iter *, struct io_uring_cmd *, struct iou_vec *, bool, unsigned int)' {aka 'int(const struct iovec *, long unsigned int, int, struct iov_iter *, struct io_uring_cmd *, struct iou_vec *, _Bool, unsigned int)'}
258 | int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/io_uring/cmd.h:47:5: note: previous declaration of 'io_uring_cmd_import_fixed_vec' with type 'int(const struct iovec *, long unsigned int, int, struct iov_iter *, struct io_uring_cmd *, struct iou_vec *, bool, unsigned int)' {aka 'int(const struct iovec *, long unsigned int, int, struct iov_iter *, struct io_uring_cmd *, struct iou_vec *, _Bool, unsigned int)'}
47 | int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
io_uring/uring_cmd.c: In function 'io_uring_cmd_import_fixed_vec':
io_uring/uring_cmd.c:273:15: error: implicit declaration of function 'io_vec_realloc' [-Werror=implicit-function-declaration]
273 | ret = io_vec_realloc(iou_vec, nr_segs);
| ^~~~~~~~~~~~~~
In file included from arch/x86/include/asm/string.h:3,
from include/linux/string.h:65,
from arch/x86/include/asm/page_32.h:18,
from arch/x86/include/asm/page.h:14,
from arch/x86/include/asm/thread_info.h:12,
from include/linux/thread_info.h:60,
from include/linux/spinlock.h:60,
from include/linux/wait.h:9,
from include/linux/wait_bit.h:8,
from include/linux/fs.h:7,
from include/uapi/linux/io_uring.h:11,
from include/linux/io_uring/cmd.h:5:
io_uring/uring_cmd.c:278:23: error: invalid use of undefined type 'struct iou_vec'
278 | memcpy(iou_vec->iovec, iov, sizeof(*iov) * nr_segs);
| ^~
arch/x86/include/asm/string_32.h:150:42: note: in definition of macro 'memcpy'
150 | #define memcpy(t, f, n) __builtin_memcpy(t, f, n)
| ^
io_uring/uring_cmd.c:281:15: error: implicit declaration of function 'io_import_reg_vec'; did you mean 'io_import_reg_buf'? [-Werror=implicit-function-declaration]
281 | ret = io_import_reg_vec(rw, iter, req, iou_vec, iou_vec->nr, 0,
| ^~~~~~~~~~~~~~~~~
| io_import_reg_buf
io_uring/uring_cmd.c:281:64: error: invalid use of undefined type 'struct iou_vec'
281 | ret = io_import_reg_vec(rw, iter, req, iou_vec, iou_vec->nr, 0,
| ^~
In file included from include/linux/linkage.h:7,
from include/linux/kernel.h:18,
from io_uring/uring_cmd.c:2:
io_uring/uring_cmd.c: At top level:
io_uring/uring_cmd.c:285:19: error: conflicting types for 'io_uring_cmd_import_fixed_vec'; have 'int(const struct iovec *, long unsigned int, int, struct iov_iter *, struct io_uring_cmd *, struct iou_vec *, bool, unsigned int)' {aka 'int(const struct iovec *, long unsigned int, int, struct iov_iter *, struct io_uring_cmd *, struct iou_vec *, _Bool, unsigned int)'}
285 | EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed_vec);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/export.h:70:28: note: in definition of macro '__EXPORT_SYMBOL'
70 | extern typeof(sym) sym; \
| ^~~
include/linux/export.h:84:41: note: in expansion of macro '_EXPORT_SYMBOL'
84 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "GPL")
| ^~~~~~~~~~~~~~
io_uring/uring_cmd.c:285:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL'
285 | EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed_vec);
| ^~~~~~~~~~~~~~~~~
include/linux/io_uring/cmd.h:47:5: note: previous declaration of 'io_uring_cmd_import_fixed_vec' with type 'int(const struct iovec *, long unsigned int, int, struct iov_iter *, struct io_uring_cmd *, struct iou_vec *, bool, unsigned int)' {aka 'int(const struct iovec *, long unsigned int, int, struct iov_iter *, struct io_uring_cmd *, struct iou_vec *, _Bool, unsigned int)'}
47 | int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +262 io_uring/uring_cmd.c
257
258 int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
259 unsigned long nr_segs, int rw,
260 struct iov_iter *iter,
261 struct io_uring_cmd *ioucmd,
> 262 struct iou_vec *iou_vec, bool compat,
263 unsigned int issue_flags)
264 {
265 struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
266 struct iovec *iov;
267 int ret;
268
269 iov = iovec_from_user(uiovec, nr_segs, 0, NULL, compat);
270 if (IS_ERR(iov))
271 return PTR_ERR(iov);
272
273 ret = io_vec_realloc(iou_vec, nr_segs);
274 if (ret) {
275 kfree(iov);
276 return ret;
277 }
278 memcpy(iou_vec->iovec, iov, sizeof(*iov) * nr_segs);
279 kfree(iov);
280
281 ret = io_import_reg_vec(rw, iter, req, iou_vec, iou_vec->nr, 0,
282 issue_flags);
283 return ret;
284 }
285 EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed_vec);
286
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 1/2] io_uring: cmd: introduce io_uring_cmd_import_fixed_vec
2025-03-11 11:40 ` [RFC PATCH 1/2] io_uring: cmd: " Sidong Yang
2025-03-11 13:08 ` Pavel Begunkov
2025-03-12 9:59 ` kernel test robot
@ 2025-03-12 10:10 ` kernel test robot
2 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2025-03-12 10:10 UTC (permalink / raw)
To: Sidong Yang; +Cc: llvm, oe-kbuild-all
Hi Sidong,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build warnings:
[auto build test WARNING on next-20250307]
[also build test WARNING on v6.14-rc6]
[cannot apply to kdave/for-next linus/master v6.14-rc6 v6.14-rc5 v6.14-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sidong-Yang/io_uring-cmd-introduce-io_uring_cmd_import_fixed_vec/20250311-194620
base: next-20250307
patch link: https://lore.kernel.org/r/20250311114053.216359-2-sidong.yang%40furiosa.ai
patch subject: [RFC PATCH 1/2] io_uring: cmd: introduce io_uring_cmd_import_fixed_vec
config: i386-buildonly-randconfig-002-20250312 (https://download.01.org/0day-ci/archive/20250312/202503121758.aWUV652p-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250312/202503121758.aWUV652p-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503121758.aWUV652p-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from block/ioctl.c:4:
In file included from include/linux/blkdev.h:9:
In file included from include/linux/blk_types.h:10:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:8:
In file included from include/linux/cacheflush.h:5:
In file included from arch/x86/include/asm/cacheflush.h:5:
In file included from include/linux/mm.h:2306:
include/linux/vmstat.h:507:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
507 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
| ~~~~~~~~~~~ ^ ~~~
In file included from block/ioctl.c:15:
>> include/linux/io_uring/cmd.h:51:14: warning: declaration of 'struct iou_vec' will not be visible outside of this function [-Wvisibility]
51 | struct iou_vec *iou_vec, bool compat,
| ^
2 warnings generated.
--
In file included from io_uring/uring_cmd.c:5:
In file included from include/linux/io_uring/cmd.h:6:
In file included from include/linux/io_uring_types.h:4:
In file included from include/linux/blkdev.h:9:
In file included from include/linux/blk_types.h:10:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:8:
In file included from include/linux/cacheflush.h:5:
In file included from arch/x86/include/asm/cacheflush.h:5:
In file included from include/linux/mm.h:2306:
include/linux/vmstat.h:507:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
507 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
| ~~~~~~~~~~~ ^ ~~~
In file included from io_uring/uring_cmd.c:5:
>> include/linux/io_uring/cmd.h:51:14: warning: declaration of 'struct iou_vec' will not be visible outside of this function [-Wvisibility]
51 | struct iou_vec *iou_vec, bool compat,
| ^
>> io_uring/uring_cmd.c:262:14: warning: declaration of 'struct iou_vec' will not be visible outside of this function [-Wvisibility]
262 | struct iou_vec *iou_vec, bool compat,
| ^
io_uring/uring_cmd.c:258:5: error: conflicting types for 'io_uring_cmd_import_fixed_vec'
258 | int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
| ^
include/linux/io_uring/cmd.h:47:5: note: previous declaration is here
47 | int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
| ^
io_uring/uring_cmd.c:273:8: error: call to undeclared function 'io_vec_realloc'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
273 | ret = io_vec_realloc(iou_vec, nr_segs);
| ^
io_uring/uring_cmd.c:278:16: error: incomplete definition of type 'struct iou_vec'
278 | memcpy(iou_vec->iovec, iov, sizeof(*iov) * nr_segs);
| ~~~~~~~^
arch/x86/include/asm/string_32.h:150:42: note: expanded from macro 'memcpy'
150 | #define memcpy(t, f, n) __builtin_memcpy(t, f, n)
| ^
io_uring/uring_cmd.c:262:14: note: forward declaration of 'struct iou_vec'
262 | struct iou_vec *iou_vec, bool compat,
| ^
io_uring/uring_cmd.c:281:8: error: call to undeclared function 'io_import_reg_vec'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
281 | ret = io_import_reg_vec(rw, iter, req, iou_vec, iou_vec->nr, 0,
| ^
io_uring/uring_cmd.c:281:8: note: did you mean 'io_import_reg_buf'?
io_uring/rsrc.h:61:5: note: 'io_import_reg_buf' declared here
61 | int io_import_reg_buf(struct io_kiocb *req, struct iov_iter *iter,
| ^
io_uring/uring_cmd.c:281:57: error: incomplete definition of type 'struct iou_vec'
281 | ret = io_import_reg_vec(rw, iter, req, iou_vec, iou_vec->nr, 0,
| ~~~~~~~^
io_uring/uring_cmd.c:262:14: note: forward declaration of 'struct iou_vec'
262 | struct iou_vec *iou_vec, bool compat,
| ^
3 warnings and 5 errors generated.
vim +51 include/linux/io_uring/cmd.h
40
41 #if defined(CONFIG_IO_URING)
42 int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
43 struct iov_iter *iter,
44 struct io_uring_cmd *ioucmd,
45 unsigned int issue_flags);
46
47 int io_uring_cmd_import_fixed_vec(const struct iovec __user *uiovec,
48 unsigned long nr_segs, int rw,
49 struct iov_iter *iter,
50 struct io_uring_cmd *ioucmd,
> 51 struct iou_vec *iou_vec, bool compat,
52 unsigned int issue_flags);
53
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 2/2] btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED
2025-03-11 11:40 ` [RFC PATCH 2/2] btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED Sidong Yang
2025-03-11 12:55 ` Pavel Begunkov
@ 2025-03-12 11:11 ` kernel test robot
1 sibling, 0 replies; 10+ messages in thread
From: kernel test robot @ 2025-03-12 11:11 UTC (permalink / raw)
To: Sidong Yang; +Cc: llvm, oe-kbuild-all
Hi Sidong,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:
[auto build test ERROR on next-20250307]
[also build test ERROR on v6.14-rc6]
[cannot apply to kdave/for-next linus/master v6.14-rc6 v6.14-rc5 v6.14-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sidong-Yang/io_uring-cmd-introduce-io_uring_cmd_import_fixed_vec/20250311-194620
base: next-20250307
patch link: https://lore.kernel.org/r/20250311114053.216359-3-sidong.yang%40furiosa.ai
patch subject: [RFC PATCH 2/2] btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED
config: i386-buildonly-randconfig-006-20250312 (https://download.01.org/0day-ci/archive/20250312/202503121808.6NloJdpM-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250312/202503121808.6NloJdpM-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503121808.6NloJdpM-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from fs/btrfs/ioctl.c:7:
In file included from include/linux/bio.h:10:
In file included from include/linux/blk_types.h:10:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:8:
In file included from include/linux/cacheflush.h:5:
In file included from arch/x86/include/asm/cacheflush.h:5:
In file included from include/linux/mm.h:2306:
include/linux/vmstat.h:507:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
507 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
| ~~~~~~~~~~~ ^ ~~~
In file included from fs/btrfs/ioctl.c:32:
include/linux/io_uring/cmd.h:51:14: warning: declaration of 'struct iou_vec' will not be visible outside of this function [-Wvisibility]
51 | struct iou_vec *iou_vec, bool compat,
| ^
>> fs/btrfs/ioctl.c:4647:17: error: field has incomplete type 'struct iou_vec'
4647 | struct iou_vec iou_vec;
| ^
fs/btrfs/ioctl.c:4647:9: note: forward declaration of 'struct iou_vec'
4647 | struct iou_vec iou_vec;
| ^
>> fs/btrfs/ioctl.c:4827:17: error: variable has incomplete type 'struct iou_vec'
4827 | struct iou_vec iou_vec = {};
| ^
fs/btrfs/ioctl.c:4647:9: note: forward declaration of 'struct iou_vec'
4647 | struct iou_vec iou_vec;
| ^
2 warnings and 2 errors generated.
vim +4647 fs/btrfs/ioctl.c
4636
4637 /*
4638 * Context that's attached to an encoded read io_uring command, in cmd->pdu. It
4639 * contains the fields in btrfs_uring_read_extent that are necessary to finish
4640 * off and cleanup the I/O in btrfs_uring_read_finished.
4641 */
4642 struct btrfs_uring_priv {
4643 struct io_uring_cmd *cmd;
4644 struct page **pages;
4645 unsigned long nr_pages;
4646 struct kiocb iocb;
> 4647 struct iou_vec iou_vec;
4648 struct iovec *iov;
4649 struct iov_iter iter;
4650 struct extent_state *cached_state;
4651 u64 count;
4652 u64 start;
4653 u64 lockend;
4654 int err;
4655 bool compressed;
4656 };
4657
4658 struct io_btrfs_cmd {
4659 struct btrfs_uring_priv *priv;
4660 };
4661
4662 static void btrfs_uring_read_finished(struct io_uring_cmd *cmd, unsigned int issue_flags)
4663 {
4664 struct io_btrfs_cmd *bc = io_uring_cmd_to_pdu(cmd, struct io_btrfs_cmd);
4665 struct btrfs_uring_priv *priv = bc->priv;
4666 struct btrfs_inode *inode = BTRFS_I(file_inode(priv->iocb.ki_filp));
4667 struct extent_io_tree *io_tree = &inode->io_tree;
4668 unsigned long index;
4669 u64 cur;
4670 size_t page_offset;
4671 ssize_t ret;
4672
4673 /* The inode lock has already been acquired in btrfs_uring_read_extent. */
4674 btrfs_lockdep_inode_acquire(inode, i_rwsem);
4675
4676 if (priv->err) {
4677 ret = priv->err;
4678 goto out;
4679 }
4680
4681 if (priv->compressed) {
4682 index = 0;
4683 page_offset = 0;
4684 } else {
4685 index = (priv->iocb.ki_pos - priv->start) >> PAGE_SHIFT;
4686 page_offset = offset_in_page(priv->iocb.ki_pos - priv->start);
4687 }
4688 cur = 0;
4689 while (cur < priv->count) {
4690 size_t bytes = min_t(size_t, priv->count - cur, PAGE_SIZE - page_offset);
4691
4692 if (copy_page_to_iter(priv->pages[index], page_offset, bytes,
4693 &priv->iter) != bytes) {
4694 ret = -EFAULT;
4695 goto out;
4696 }
4697
4698 index++;
4699 cur += bytes;
4700 page_offset = 0;
4701 }
4702 ret = priv->count;
4703
4704 out:
4705 unlock_extent(io_tree, priv->start, priv->lockend, &priv->cached_state);
4706 btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
4707
4708 io_uring_cmd_done(cmd, ret, 0, issue_flags);
4709 add_rchar(current, ret);
4710
4711 for (index = 0; index < priv->nr_pages; index++)
4712 __free_page(priv->pages[index]);
4713
4714 kfree(priv->pages);
4715 kfree(priv->iov);
4716 if (priv->iou_vec.iovec)
4717 kfree(priv->iou_vec.iovec);
4718 kfree(priv);
4719 }
4720
4721 void btrfs_uring_read_extent_endio(void *ctx, int err)
4722 {
4723 struct btrfs_uring_priv *priv = ctx;
4724 struct io_btrfs_cmd *bc = io_uring_cmd_to_pdu(priv->cmd, struct io_btrfs_cmd);
4725
4726 priv->err = err;
4727 bc->priv = priv;
4728
4729 io_uring_cmd_complete_in_task(priv->cmd, btrfs_uring_read_finished);
4730 }
4731
4732 static int btrfs_uring_read_extent(struct kiocb *iocb, struct iov_iter *iter,
4733 u64 start, u64 lockend,
4734 struct extent_state *cached_state,
4735 u64 disk_bytenr, u64 disk_io_size,
4736 size_t count, bool compressed,
4737 struct iovec *iov, struct io_uring_cmd *cmd,
4738 struct iou_vec *iou_vec)
4739 {
4740 struct btrfs_inode *inode = BTRFS_I(file_inode(iocb->ki_filp));
4741 struct extent_io_tree *io_tree = &inode->io_tree;
4742 struct page **pages;
4743 struct btrfs_uring_priv *priv = NULL;
4744 unsigned long nr_pages;
4745 int ret;
4746
4747 nr_pages = DIV_ROUND_UP(disk_io_size, PAGE_SIZE);
4748 pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
4749 if (!pages)
4750 return -ENOMEM;
4751 ret = btrfs_alloc_page_array(nr_pages, pages, 0);
4752 if (ret) {
4753 ret = -ENOMEM;
4754 goto out_fail;
4755 }
4756
4757 priv = kmalloc(sizeof(*priv), GFP_NOFS);
4758 if (!priv) {
4759 ret = -ENOMEM;
4760 goto out_fail;
4761 }
4762
4763 priv->iocb = *iocb;
4764 priv->iov = iov;
4765 priv->iter = *iter;
4766 priv->count = count;
4767 priv->cmd = cmd;
4768 priv->cached_state = cached_state;
4769 priv->compressed = compressed;
4770 priv->nr_pages = nr_pages;
4771 priv->pages = pages;
4772 priv->start = start;
4773 priv->lockend = lockend;
4774 priv->err = 0;
4775 priv->iou_vec = *iou_vec;
4776
4777 ret = btrfs_encoded_read_regular_fill_pages(inode, disk_bytenr,
4778 disk_io_size, pages, priv);
4779 if (ret && ret != -EIOCBQUEUED)
4780 goto out_fail;
4781
4782 /*
4783 * If we return -EIOCBQUEUED, we're deferring the cleanup to
4784 * btrfs_uring_read_finished(), which will handle unlocking the extent
4785 * and inode and freeing the allocations.
4786 */
4787
4788 /*
4789 * We're returning to userspace with the inode lock held, and that's
4790 * okay - it'll get unlocked in a worker thread. Call
4791 * btrfs_lockdep_inode_release() to avoid confusing lockdep.
4792 */
4793 btrfs_lockdep_inode_release(inode, i_rwsem);
4794
4795 return -EIOCBQUEUED;
4796
4797 out_fail:
4798 unlock_extent(io_tree, start, lockend, &cached_state);
4799 btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
4800 kfree(priv);
4801 return ret;
4802 }
4803
4804 struct btrfs_uring_encoded_data {
4805 struct btrfs_ioctl_encoded_io_args args;
4806 struct iovec iovstack[UIO_FASTIOV];
4807 struct iovec *iov;
4808 struct iov_iter iter;
4809 };
4810
4811 static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue_flags)
4812 {
4813 size_t copy_end_kernel = offsetofend(struct btrfs_ioctl_encoded_io_args, flags);
4814 size_t copy_end;
4815 int ret;
4816 u64 disk_bytenr, disk_io_size;
4817 struct file *file;
4818 struct btrfs_inode *inode;
4819 struct btrfs_fs_info *fs_info;
4820 struct extent_io_tree *io_tree;
4821 loff_t pos;
4822 struct kiocb kiocb;
4823 struct extent_state *cached_state = NULL;
4824 u64 start, lockend;
4825 void __user *sqe_addr;
4826 struct btrfs_uring_encoded_data *data = io_uring_cmd_get_async_data(cmd)->op_data;
> 4827 struct iou_vec iou_vec = {};
4828
4829 if (!capable(CAP_SYS_ADMIN)) {
4830 ret = -EPERM;
4831 goto out_acct;
4832 }
4833 file = cmd->file;
4834 inode = BTRFS_I(file->f_inode);
4835 fs_info = inode->root->fs_info;
4836 io_tree = &inode->io_tree;
4837 sqe_addr = u64_to_user_ptr(READ_ONCE(cmd->sqe->addr));
4838
4839 if (issue_flags & IO_URING_F_COMPAT) {
4840 #if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
4841 copy_end = offsetofend(struct btrfs_ioctl_encoded_io_args_32, flags);
4842 #else
4843 return -ENOTTY;
4844 #endif
4845 } else {
4846 copy_end = copy_end_kernel;
4847 }
4848
4849 if (!data) {
4850 data = kzalloc(sizeof(*data), GFP_NOFS);
4851 if (!data) {
4852 ret = -ENOMEM;
4853 goto out_acct;
4854 }
4855
4856 io_uring_cmd_get_async_data(cmd)->op_data = data;
4857
4858 if (issue_flags & IO_URING_F_COMPAT) {
4859 #if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
4860 struct btrfs_ioctl_encoded_io_args_32 args32;
4861
4862 if (copy_from_user(&args32, sqe_addr, copy_end)) {
4863 ret = -EFAULT;
4864 goto out_acct;
4865 }
4866
4867 data->args.iov = compat_ptr(args32.iov);
4868 data->args.iovcnt = args32.iovcnt;
4869 data->args.offset = args32.offset;
4870 data->args.flags = args32.flags;
4871 #endif
4872 } else {
4873 if (copy_from_user(&data->args, sqe_addr, copy_end)) {
4874 ret = -EFAULT;
4875 goto out_acct;
4876 }
4877 }
4878
4879 if (data->args.flags != 0) {
4880 ret = -EINVAL;
4881 goto out_acct;
4882 }
4883
4884 data->iov = data->iovstack;
4885
4886 if (cmd && (cmd->flags & IORING_URING_CMD_FIXED)) {
4887 ret = io_uring_cmd_import_fixed_vec(
4888 data->args.iov, data->args.iovcnt, ITER_DEST,
4889 &data->iter, cmd, &iou_vec, false, issue_flags);
4890 data->iov = NULL;
4891 } else {
4892 ret = import_iovec(ITER_DEST, data->args.iov,
4893 data->args.iovcnt,
4894 ARRAY_SIZE(data->iovstack),
4895 &data->iov, &data->iter);
4896 }
4897
4898 if (ret < 0)
4899 goto out_acct;
4900
4901 if (iov_iter_count(&data->iter) == 0) {
4902 ret = 0;
4903 goto out_free;
4904 }
4905 }
4906
4907 pos = data->args.offset;
4908 ret = rw_verify_area(READ, file, &pos, data->args.len);
4909 if (ret < 0)
4910 goto out_free;
4911
4912 init_sync_kiocb(&kiocb, file);
4913 kiocb.ki_pos = pos;
4914
4915 if (issue_flags & IO_URING_F_NONBLOCK)
4916 kiocb.ki_flags |= IOCB_NOWAIT;
4917
4918 start = ALIGN_DOWN(pos, fs_info->sectorsize);
4919 lockend = start + BTRFS_MAX_UNCOMPRESSED - 1;
4920
4921 ret = btrfs_encoded_read(&kiocb, &data->iter, &data->args, &cached_state,
4922 &disk_bytenr, &disk_io_size);
4923 if (ret < 0 && ret != -EIOCBQUEUED)
4924 goto out_free;
4925
4926 file_accessed(file);
4927
4928 if (copy_to_user(sqe_addr + copy_end,
4929 (const char *)&data->args + copy_end_kernel,
4930 sizeof(data->args) - copy_end_kernel)) {
4931 if (ret == -EIOCBQUEUED) {
4932 unlock_extent(io_tree, start, lockend, &cached_state);
4933 btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
4934 }
4935 ret = -EFAULT;
4936 goto out_free;
4937 }
4938
4939 if (ret == -EIOCBQUEUED) {
4940 u64 count = min_t(u64, iov_iter_count(&data->iter), disk_io_size);
4941
4942 /* Match ioctl by not returning past EOF if uncompressed. */
4943 if (!data->args.compression)
4944 count = min_t(u64, count, data->args.len);
4945
4946 ret = btrfs_uring_read_extent(&kiocb, &data->iter, start, lockend,
4947 cached_state, disk_bytenr, disk_io_size,
4948 count, data->args.compression,
4949 data->iov, cmd, &iou_vec);
4950
4951 goto out_acct;
4952 }
4953
4954 out_free:
4955 kfree(data->iov);
4956
4957 out_acct:
4958 if (ret > 0)
4959 add_rchar(current, ret);
4960 inc_syscr(current);
4961
4962 return ret;
4963 }
4964
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-03-12 11:12 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-11 11:40 [RFC PATCH 0/2] introduce io_uring_cmd_import_fixed_vec Sidong Yang
2025-03-11 11:40 ` [RFC PATCH 1/2] io_uring: cmd: " Sidong Yang
2025-03-11 13:08 ` Pavel Begunkov
2025-03-12 3:08 ` Sidong Yang
2025-03-12 9:59 ` kernel test robot
2025-03-12 10:10 ` kernel test robot
2025-03-11 11:40 ` [RFC PATCH 2/2] btrfs: ioctl: use registered buffer for IORING_URING_CMD_FIXED Sidong Yang
2025-03-11 12:55 ` Pavel Begunkov
2025-03-12 3:05 ` Sidong Yang
2025-03-12 11:11 ` kernel test robot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.