This adds support for doing fadvise through io_uring. We assume that WILLNEED doesn't block, but that DONTNEED may block.
Unified · Split
| @@ -72,6 +72,7 @@ · 71 unmodified lines | ||
| 72 | 72 | #include <linux/highmem.h> |
| 73 | 73 | #include <linux/namei.h> |
| 74 | 74 | #include <linux/fsnotify.h> |
| 75 | +#include <linux/fadvise.h> | |
| 75 | 76 | |
| 76 | 77 | #define CREATE_TRACE_POINTS |
| 77 | 78 | #include <trace/events/io_uring.h> |
| @@ -400,6 +401,13 @@ struct io_files_update { · 322 unmodified lines | ||
| 400 | 401 | u32 offset; |
| 401 | 402 | }; |
| 402 | 403 | |
| 404 | +struct io_fadvise { | |
| 405 | + struct file *file; | |
| 406 | + u64 offset; | |
| 407 | + u32 len; | |
| 408 | + u32 advice; | |
| 409 | +}; | |
| 410 | + | |
| 403 | 411 | struct io_async_connect { |
| 404 | 412 | struct sockaddr_storage address; |
| 405 | 413 | }; |
| @@ -452,6 +460,7 @@ struct io_kiocb { · 46 unmodified lines | ||
| 452 | 460 | struct io_open open; |
| 453 | 461 | struct io_close close; |
| 454 | 462 | struct io_files_update files_update; |
| 463 | + struct io_fadvise fadvise; | |
| 455 | 464 | }; |
| 456 | 465 | |
| 457 | 466 | struct io_async_ctx *io; |
| @@ -667,6 +676,10 @@ static const struct io_op_def io_op_defs[] = { · 209 unmodified lines | ||
| 667 | 676 | .needs_file = 1, |
| 668 | 677 | .unbound_nonreg_file = 1, |
| 669 | 678 | }, |
| 679 | + { | |
| 680 | + /* IORING_OP_FADVISE */ | |
| 681 | + .needs_file = 1, | |
| 682 | + }, | |
| 670 | 683 | }; |
| 671 | 684 | |
| 672 | 685 | static void io_wq_submit_work(struct io_wq_work **workptr); |
| @@ -2436,6 +2449,35 @@ err: · 1763 unmodified lines | ||
| 2436 | 2449 | return 0; |
| 2437 | 2450 | } |
| 2438 | 2451 | |
| 2452 | +static int io_fadvise_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) | |
| 2453 | +{ | |
| 2454 | + if (sqe->ioprio || sqe->buf_index || sqe->addr) | |
| 2455 | + return -EINVAL; | |
| 2456 | + | |
| 2457 | + req->fadvise.offset = READ_ONCE(sqe->off); | |
| 2458 | + req->fadvise.len = READ_ONCE(sqe->len); | |
| 2459 | + req->fadvise.advice = READ_ONCE(sqe->fadvise_advice); | |
| 2460 | + return 0; | |
| 2461 | +} | |
| 2462 | + | |
| 2463 | +static int io_fadvise(struct io_kiocb *req, struct io_kiocb **nxt, | |
| 2464 | + bool force_nonblock) | |
| 2465 | +{ | |
| 2466 | + struct io_fadvise *fa = &req->fadvise; | |
| 2467 | + int ret; | |
| 2468 | + | |
| 2469 | + /* DONTNEED may block, others _should_ not */ | |
| 2470 | + if (fa->advice == POSIX_FADV_DONTNEED && force_nonblock) | |
| 2471 | + return -EAGAIN; | |
| 2472 | + | |
| 2473 | + ret = vfs_fadvise(req->file, fa->offset, fa->len, fa->advice); | |
| 2474 | + if (ret < 0) | |
| 2475 | + req_set_fail_links(req); | |
| 2476 | + io_cqring_add_event(req, ret); | |
| 2477 | + io_put_req_find_next(req, nxt); | |
| 2478 | + return 0; | |
| 2479 | +} | |
| 2480 | + | |
| 2439 | 2481 | static int io_statx_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) |
| 2440 | 2482 | { |
| 2441 | 2483 | unsigned lookup_flags; |
| @@ -3721,6 +3763,9 @@ static int io_req_defer_prep(struct io_kiocb *req, · 1279 unmodified lines | ||
| 3721 | 3763 | case IORING_OP_STATX: |
| 3722 | 3764 | ret = io_statx_prep(req, sqe); |
| 3723 | 3765 | break; |
| 3766 | + case IORING_OP_FADVISE: | |
| 3767 | + ret = io_fadvise_prep(req, sqe); | |
| 3768 | + break; | |
| 3724 | 3769 | default: |
| 3725 | 3770 | printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", |
| 3726 | 3771 | req->opcode); |
| @@ -3917,6 +3962,14 @@ static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe, · 190 unmodified lines | ||
| 3917 | 3962 | } |
| 3918 | 3963 | ret = io_statx(req, nxt, force_nonblock); |
| 3919 | 3964 | break; |
| 3965 | + case IORING_OP_FADVISE: | |
| 3966 | + if (sqe) { | |
| 3967 | + ret = io_fadvise_prep(req, sqe); | |
| 3968 | + if (ret) | |
| 3969 | + break; | |
| 3970 | + } | |
| 3971 | + ret = io_fadvise(req, nxt, force_nonblock); | |
| 3972 | + break; | |
| 3920 | 3973 | default: |
| 3921 | 3974 | ret = -EINVAL; |
| 3922 | 3975 | break; |
| @@ -36,6 +36,7 @@ struct io_uring_sqe { · 35 unmodified lines | ||
| 36 | 36 | __u32 cancel_flags; |
| 37 | 37 | __u32 open_flags; |
| 38 | 38 | __u32 statx_flags; |
| 39 | + __u32 fadvise_advice; | |
| 39 | 40 | }; |
| 40 | 41 | __u64 user_data; /* data to be passed back at completion time */ |
| 41 | 42 | union { |
| @@ -86,6 +87,7 @@ enum { · 44 unmodified lines | ||
| 86 | 87 | IORING_OP_STATX, |
| 87 | 88 | IORING_OP_READ, |
| 88 | 89 | IORING_OP_WRITE, |
| 90 | + IORING_OP_FADVISE, | |
| 89 | 91 | |
| 90 | 92 | /* this goes last, obviously */ |
| 91 | 93 | IORING_OP_LAST, |