io_uring/kbuf: Allow the full buffer id space for provided buffers
[ Upstream commit f74c746e476b9dad51448b9a9421aae72b60e25f ]
nbufs tracks the number of buffers and not the last bgid. In 16-bit, we
have 2^16 valid buffers, but the check mistakenly rejects the last
bid. Let's fix it to make the interface consistent with the
documentation.
Fixes: ddf0322db7
("io_uring: add IORING_OP_PROVIDE_BUFFERS")
Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
Link: https://lore.kernel.org/r/20231005000531.30800-3-krisman@suse.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
60db638be5
commit
32b15fef33
@ -19,12 +19,15 @@
|
|||||||
|
|
||||||
#define BGID_ARRAY 64
|
#define BGID_ARRAY 64
|
||||||
|
|
||||||
|
/* BIDs are addressed by a 16-bit field in a CQE */
|
||||||
|
#define MAX_BIDS_PER_BGID (1 << 16)
|
||||||
|
|
||||||
struct io_provide_buf {
|
struct io_provide_buf {
|
||||||
struct file *file;
|
struct file *file;
|
||||||
__u64 addr;
|
__u64 addr;
|
||||||
__u32 len;
|
__u32 len;
|
||||||
__u32 bgid;
|
__u32 bgid;
|
||||||
__u16 nbufs;
|
__u32 nbufs;
|
||||||
__u16 bid;
|
__u16 bid;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -281,7 +284,7 @@ int io_remove_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
tmp = READ_ONCE(sqe->fd);
|
tmp = READ_ONCE(sqe->fd);
|
||||||
if (!tmp || tmp > USHRT_MAX)
|
if (!tmp || tmp > MAX_BIDS_PER_BGID)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
memset(p, 0, sizeof(*p));
|
memset(p, 0, sizeof(*p));
|
||||||
@ -327,7 +330,7 @@ int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
tmp = READ_ONCE(sqe->fd);
|
tmp = READ_ONCE(sqe->fd);
|
||||||
if (!tmp || tmp > USHRT_MAX)
|
if (!tmp || tmp > MAX_BIDS_PER_BGID)
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
p->nbufs = tmp;
|
p->nbufs = tmp;
|
||||||
p->addr = READ_ONCE(sqe->addr);
|
p->addr = READ_ONCE(sqe->addr);
|
||||||
@ -347,7 +350,7 @@ int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
|
|||||||
tmp = READ_ONCE(sqe->off);
|
tmp = READ_ONCE(sqe->off);
|
||||||
if (tmp > USHRT_MAX)
|
if (tmp > USHRT_MAX)
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
if (tmp + p->nbufs > USHRT_MAX)
|
if (tmp + p->nbufs > MAX_BIDS_PER_BGID)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
p->bid = tmp;
|
p->bid = tmp;
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user