io_uring: add support for madvise/fadvise
Subsystems (5)
Jens Axboe
maintainercover io_uring: add support for madvise/fadvise
Nothing earth shattering here, just wiring up madvise and fadvise for io_uring. The madvise part requires a small prep patch.
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerPATCH 1/3 io_uring: add IORING_OP_FADVISE
This adds support for doing fadvise through io_uring. We assume that WILLNEED doesn't block, but that DONTNEED may block.
--- fs/io_uring.c | 53 +++++++++++++++++++++++++++++++++++ include/uapi/linux/io_uring.h | 2 ++ 2 files changed, 55 insertions(+)
fs/io_uring.c +53 -0
@@ -72,6 +72,7 @@#include <linux/highmem.h> #include <linux/namei.h> #include <linux/fsnotify.h> +#include <linux/fadvise.h> #define CREATE_TRACE_POINTS #include <trace/events/io_uring.h>
@@ -400,6 +401,13 @@ struct io_files_update {u32 offset; }; +struct io_fadvise { +struct file *file; +u64 offset; +u32 len; +u32 advice; +}; +struct io_async_connect {struct sockaddr_storage address; };
@@ -452,6 +460,7 @@ struct io_kiocb {struct io_open open;struct io_close close;struct io_files_update files_update; +struct io_fadvise fadvise; };struct io_async_ctx *io;
@@ -669,6 +678,10 @@ static const struct io_op_def io_op_defs[] = { .needs_file = 1, .unbound_nonreg_file = 1, }, + { +/* IORING_OP_FADVISE */ + .needs_file = 1, + }, };static void io_wq_submit_work (struct io_wq_work **workptr);
@@ -2435,6 +2448,35 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt,return 0 ; } +static int io_fadvise_prep (struct io_kiocb *req,const struct io_uring_sqe *sqe) +{ +if (sqe->ioprio || sqe->buf_index || sqe->addr) +return -EINVAL ; + + req->fadvise.offset =READ_ONCE (sqe->off); + req->fadvise.len =READ_ONCE (sqe->len); + req->fadvise.advice =READ_ONCE (sqe->fadvise_advice); +return 0 ; +} + +static int io_fadvise (struct io_kiocb *req,struct io_kiocb **nxt, +bool force_nonblock) +{ +struct io_fadvise *fa = &req->fadvise; +int ret; + +/* DONTNEED may block, others _should_ not */ +if (fa->advice ==POSIX_FADV_DONTNEED && force_nonblock) +return -EAGAIN ; + + ret =vfs_fadvise (req->file, fa->offset, fa->len, fa->advice); +if (ret <0 ) +req_set_fail_links (req); +io_cqring_add_event (req, ret); +io_put_req_find_next (req, nxt); +return 0 ; +} +static int io_statx_prep (struct io_kiocb *req,const struct io_uring_sqe *sqe) {unsigned lookup_flags;
@@ -3724,6 +3766,9 @@ static int io_req_defer_prep(struct io_kiocb *req,case IORING_OP_STATX : ret =io_statx_prep (req, sqe);break ; +case IORING_OP_FADVISE : + ret =io_fadvise_prep (req, sqe); +break ;default :printk_once (KERN_WARNING "io_uring: unhandled opcode %d\n" , req->opcode);
@@ -3920,6 +3965,14 @@ static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe, } ret =io_statx (req, nxt, force_nonblock);break ; +case IORING_OP_FADVISE : +if (sqe) { + ret =io_fadvise_prep (req, sqe); +if (ret) +break ; + } + ret =io_fadvise (req, nxt, force_nonblock); +break ;default : ret = -EINVAL ;break ;
include/uapi/linux/io_uring.h +2 -0
@@ -36,6 +36,7 @@ struct io_uring_sqe {__u32 cancel_flags;__u32 open_flags;__u32 statx_flags; +__u32 fadvise_advice; };__u64 user_data;/* data to be passed back at completion time */ union {
@@ -86,6 +87,7 @@ enum {IORING_OP_STATX ,IORING_OP_READ ,IORING_OP_WRITE , +IORING_OP_FADVISE ,/* this goes last, obviously */ IORING_OP_LAST,
Signature · 1 line
2.24.1
Jens Axboe
maintainerPATCH 2/3 mm: make do_madvise() available internally
In reply to Jens AxboeThis is in preparation for enabling this functionality through io_uring. Add a helper that is just exporting what sys_madvise() does, and have the system call use it.
No functional changes in this patch.
--- include/linux/mm.h | 1 + mm/madvise.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-)
include/linux/mm.h +1 -0
@@ -2328,6 +2328,7 @@ extern int __do_munmap(struct mm_struct *, unsigned long, size_t, struct list_head *uf, bool downgrade);extern int do_munmap (struct mm_struct *,unsigned long ,size_t ,struct list_head *uf); +extern int do_madvise (unsigned long start,size_t len_in,int behavior); static inline unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
mm/madvise.c +6 -1
@@ -1044,7 +1044,7 @@ madvise_behavior_valid(int behavior)* -EBADF - map exists, but area maps something that isn't a file. * -EAGAIN - a kernel resource was temporarily unavailable. */ -SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) +int do_madvise (unsigned long start,size_t len_in,int behavior) {unsigned long end, tmp;struct vm_area_struct *vma, *prev;
@@ -1141,3 +1141,8 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior)return error; } + +SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) +{ +return do_madvise (start, len_in, behavior); +}
Signature · 1 line
2.24.1
Jens Axboe
maintainerPATCH 3/3 io_uring: add IORING_OP_MADVISE
In reply to Jens AxboeThis adds support for doing madvise(2) through io_uring. We assume that any operation can block, and hence punt everything async. This could be improved, but hard to make bullet proof. The async punt ensures it's safe.
--- fs/io_uring.c | 56 ++++++++++++++++++++++++++++++++++- include/uapi/linux/io_uring.h | 1 + 2 files changed, 56 insertions(+), 1 deletion(-)
fs/io_uring.c +55 -1
@@ -403,7 +403,10 @@ struct io_files_update {struct io_fadvise {struct file *file; -u64 offset; +union { +u64 offset; +u64 addr; + };u32 len;u32 advice; };
@@ -682,6 +685,10 @@ static const struct io_op_def io_op_defs[] = {/* IORING_OP_FADVISE */ .needs_file = 1, }, + { +/* IORING_OP_MADVISE */ + .needs_mm = 1, + }, };static void io_wq_submit_work (struct io_wq_work **workptr);
@@ -2448,6 +2455,42 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt,return 0 ; } +static int io_madvise_prep (struct io_kiocb *req,const struct io_uring_sqe *sqe) +{ +#if defined(CONFIG_ADVISE_SYSCALLS ) && defined(CONFIG_MMU ) +if (sqe->ioprio || sqe->buf_index || sqe->off) +return -EINVAL ; + + req->fadvise.addr =READ_ONCE (sqe->addr); + req->fadvise.len =READ_ONCE (sqe->len); + req->fadvise.advice =READ_ONCE (sqe->fadvise_advice); +return 0 ; +#else +return -EOPNOTSUPP ; +#endif +} + +static int io_madvise (struct io_kiocb *req,struct io_kiocb **nxt, +bool force_nonblock) +{ +#if defined(CONFIG_ADVISE_SYSCALLS ) && defined(CONFIG_MMU ) +struct io_fadvise *fa = &req->fadvise; +int ret; + +if (force_nonblock) +return -EAGAIN ; + + ret =do_madvise (fa->addr, fa->len, fa->advice); +if (ret <0 ) +req_set_fail_links (req); +io_cqring_add_event (req, ret); +io_put_req_find_next (req, nxt); +return 0 ; +#else +return -EOPNOTSUPP ; +#endif +} +static int io_fadvise_prep (struct io_kiocb *req,const struct io_uring_sqe *sqe) {if (sqe->ioprio || sqe->buf_index || sqe->addr)
@@ -3769,6 +3812,9 @@ static int io_req_defer_prep(struct io_kiocb *req,case IORING_OP_FADVISE : ret =io_fadvise_prep (req, sqe);break ; +case IORING_OP_MADVISE : + ret =io_madvise_prep (req, sqe); +break ;default :printk_once (KERN_WARNING "io_uring: unhandled opcode %d\n" , req->opcode);
@@ -3973,6 +4019,14 @@ static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe, } ret =io_fadvise (req, nxt, force_nonblock);break ; +case IORING_OP_MADVISE : +if (sqe) { + ret =io_madvise_prep (req, sqe); +if (ret) +break ; + } + ret =io_madvise (req, nxt, force_nonblock); +break ;default : ret = -EINVAL ;break ;
include/uapi/linux/io_uring.h +1 -0
@@ -88,6 +88,7 @@ enum {IORING_OP_READ ,IORING_OP_WRITE ,IORING_OP_FADVISE , +IORING_OP_MADVISE ,/* this goes last, obviously */ IORING_OP_LAST,
Signature · 1 line
2.24.1
Re: [PATCH 3/3] io_uring: add IORING_OP_MADVISE
Quoted 6 lines · Jens Axboe
This adds support for doing madvise(2) through
io_uring. We assume that any operation can block, and hence punt everything async. This could be improved, but hard to make bullet proof. The async punt ensures it's safe.Signed-off-by Jens Axboe <[email protected]>
How capability checks work with io_uring?
MADV_HWPOISON requires CAP_SYS_ADMIN and I just want to make sure it will not open a way around.
Signature · 1 line
Kirill A. Shutemov
Jens Axboe
maintainerRe: [PATCH 3/3] io_uring: add IORING_OP_MADVISE
Quoted 6 lines · Kirill A. Shutemov
Quoted 5 lines · Jens Axboe
This adds support for doing madvise(2) through
io_uring. We assume that any operation can block, and hence punt everything async. This could be improved, but hard to make bullet proof. The async punt ensures it's safe.
Quoted 6 lines
Quoted 1 line
Signed-off-by Jens Axboe <[email protected]>How capability checks work with
io_uring?
MADV_HWPOISONrequiresCAP_SYS_ADMINand I just want to make sure it will not open a way around.
There are two ways the request can get invoked from io_uring:
1) Inline from the system call, personality is the application (of course) in that case.
2) Async helper, personality (creds, mm, etc) are inherited from the ring.
So it should be totally safe, and madvise is no different than the other system calls supported in that regard.
Signature · 1 line
Jens Axboe
Re: [PATCH 3/3] io_uring: add IORING_OP_MADVISE
In reply to Jens AxboeQuoted 5 lines · Jens Axboe
This adds support for doing madvise(2) through
io_uring. We assume that any operation can block, and hence punt everything async. This could be improved, but hard to make bullet proof. The async punt ensures it's safe.
I don't like that it share structs/fields names with fadvise. E.g. madvise's context is called struct io_fadvise. Could it at least have fadvise_advice filed in struct io_uring_sqe? io_uring parts of the patchset look good.
Quoted 114 lines
Signed-off-by Jens Axboe <[email protected]>--- fs/io_uring.c | 56 ++++++++++++++++++++++++++++++++++- include/uapi/linux/io_uring.h | 1 + 2 files changed, 56 insertions(+), 1 deletion(-)fs/io_uring.c +55
-1@@ -403,7 +403,10 @@ struct io_files_update {struct io_fadvise {struct file *file; -u64 offset; +union { +u64 offset; +u64 addr; + };u32 len;u32 advice; };@@ -682,6 +685,10 @@ static const struct io_op_def io_op_defs[] = {/* IORING_OP_FADVISE */ .needs_file = 1, }, + { +/* IORING_OP_MADVISE */ + .needs_mm = 1, + }, };static void io_wq_submit_work (struct io_wq_work **workptr);@@ -2448,6 +2455,42 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt,return 0 ; } +static int io_madvise_prep (struct io_kiocb *req,const struct io_uring_sqe *sqe) +{ +#if defined(CONFIG_ADVISE_SYSCALLS ) && defined(CONFIG_MMU ) +if (sqe->ioprio || sqe->buf_index || sqe->off) +return -EINVAL ; + + req->fadvise.addr =READ_ONCE (sqe->addr); + req->fadvise.len =READ_ONCE (sqe->len); + req->fadvise.advice =READ_ONCE (sqe->fadvise_advice); +return 0 ; +#else +return -EOPNOTSUPP ; +#endif +} + +static int io_madvise (struct io_kiocb *req,struct io_kiocb **nxt, +bool force_nonblock) +{ +#if defined(CONFIG_ADVISE_SYSCALLS ) && defined(CONFIG_MMU ) +struct io_fadvise *fa = &req->fadvise; +int ret; + +if (force_nonblock) +return -EAGAIN ; + + ret =do_madvise (fa->addr, fa->len, fa->advice); +if (ret <0 ) +req_set_fail_links (req); +io_cqring_add_event (req, ret); +io_put_req_find_next (req, nxt); +return 0 ; +#else +return -EOPNOTSUPP ; +#endif +} +static int io_fadvise_prep (struct io_kiocb *req,const struct io_uring_sqe *sqe) {if (sqe->ioprio || sqe->buf_index || sqe->addr)@@ -3769,6 +3812,9 @@ static int io_req_defer_prep(struct io_kiocb *req,case IORING_OP_FADVISE : ret =io_fadvise_prep (req, sqe);break ; +case IORING_OP_MADVISE : + ret =io_madvise_prep (req, sqe); +break ;default :printk_once (KERN_WARNING "io_uring: unhandled opcode %d\n" , req->opcode);@@ -3973,6 +4019,14 @@ static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe, } ret =io_fadvise (req, nxt, force_nonblock);break ; +case IORING_OP_MADVISE : +if (sqe) { + ret =io_madvise_prep (req, sqe); +if (ret) +break ; + } + ret =io_madvise (req, nxt, force_nonblock); +break ;default : ret = -EINVAL ;break ;include/uapi/linux/io_uring.h +1
-0@@ -88,6 +88,7 @@ enum {IORING_OP_READ ,IORING_OP_WRITE ,IORING_OP_FADVISE , +IORING_OP_MADVISE ,/* this goes last, obviously */ IORING_OP_LAST,
Signature · 1 line
Pavel Begunkov
Jens Axboe
maintainerRe: [PATCH 3/3] io_uring: add IORING_OP_MADVISE
Quoted 11 lines · Pavel Begunkov
Quoted 5 lines · Jens Axboe
This adds support for doing madvise(2) through
io_uring. We assume that any operation can block, and hence punt everything async. This could be improved, but hard to make bullet proof. The async punt ensures it's safe.I don't like that it share structs/fields names with fadvise. E.g. madvise's context is called struct
io_fadvise. Could it at least havefadvise_advicefiled in structio_uring_sqe?io_uringparts of the patchset look good.Reviewed-by Pavel Begunkov <[email protected]>
Thanks, I can add the separate union, not a big deal.
Signature · 1 line
Jens Axboe