Commit | Line | Data |
---|---|---|
f4c163dd JA |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <linux/kernel.h> | |
3 | #include <linux/errno.h> | |
4 | #include <linux/fs.h> | |
5 | #include <linux/file.h> | |
6 | #include <linux/mm.h> | |
7 | #include <linux/slab.h> | |
8 | #include <linux/namei.h> | |
9 | #include <linux/io_uring.h> | |
10 | ||
11 | #include <uapi/linux/fadvise.h> | |
12 | #include <uapi/linux/io_uring.h> | |
13 | ||
f4c163dd JA |
14 | #include "io_uring.h" |
15 | #include "advise.h" | |
16 | ||
17 | struct io_fadvise { | |
18 | struct file *file; | |
19 | u64 offset; | |
20 | u32 len; | |
21 | u32 advice; | |
22 | }; | |
23 | ||
24 | struct io_madvise { | |
25 | struct file *file; | |
26 | u64 addr; | |
27 | u32 len; | |
28 | u32 advice; | |
29 | }; | |
30 | ||
31 | int io_madvise_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) | |
32 | { | |
33 | #if defined(CONFIG_ADVISE_SYSCALLS) && defined(CONFIG_MMU) | |
f2ccb5ae | 34 | struct io_madvise *ma = io_kiocb_to_cmd(req, struct io_madvise); |
f4c163dd JA |
35 | |
36 | if (sqe->buf_index || sqe->off || sqe->splice_fd_in) | |
37 | return -EINVAL; | |
38 | ||
39 | ma->addr = READ_ONCE(sqe->addr); | |
40 | ma->len = READ_ONCE(sqe->len); | |
41 | ma->advice = READ_ONCE(sqe->fadvise_advice); | |
aebb224f | 42 | req->flags |= REQ_F_FORCE_ASYNC; |
f4c163dd JA |
43 | return 0; |
44 | #else | |
45 | return -EOPNOTSUPP; | |
46 | #endif | |
47 | } | |
48 | ||
49 | int io_madvise(struct io_kiocb *req, unsigned int issue_flags) | |
50 | { | |
51 | #if defined(CONFIG_ADVISE_SYSCALLS) && defined(CONFIG_MMU) | |
f2ccb5ae | 52 | struct io_madvise *ma = io_kiocb_to_cmd(req, struct io_madvise); |
f4c163dd JA |
53 | int ret; |
54 | ||
aebb224f | 55 | WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); |
f4c163dd JA |
56 | |
57 | ret = do_madvise(current->mm, ma->addr, ma->len, ma->advice); | |
58 | io_req_set_res(req, ret, 0); | |
59 | return IOU_OK; | |
60 | #else | |
61 | return -EOPNOTSUPP; | |
62 | #endif | |
63 | } | |
64 | ||
c31cc60f DY |
65 | static bool io_fadvise_force_async(struct io_fadvise *fa) |
66 | { | |
67 | switch (fa->advice) { | |
68 | case POSIX_FADV_NORMAL: | |
69 | case POSIX_FADV_RANDOM: | |
70 | case POSIX_FADV_SEQUENTIAL: | |
71 | return false; | |
72 | default: | |
73 | return true; | |
74 | } | |
75 | } | |
76 | ||
f4c163dd JA |
77 | int io_fadvise_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) |
78 | { | |
f2ccb5ae | 79 | struct io_fadvise *fa = io_kiocb_to_cmd(req, struct io_fadvise); |
f4c163dd JA |
80 | |
81 | if (sqe->buf_index || sqe->addr || sqe->splice_fd_in) | |
82 | return -EINVAL; | |
83 | ||
84 | fa->offset = READ_ONCE(sqe->off); | |
85 | fa->len = READ_ONCE(sqe->len); | |
86 | fa->advice = READ_ONCE(sqe->fadvise_advice); | |
c31cc60f DY |
87 | if (io_fadvise_force_async(fa)) |
88 | req->flags |= REQ_F_FORCE_ASYNC; | |
f4c163dd JA |
89 | return 0; |
90 | } | |
91 | ||
92 | int io_fadvise(struct io_kiocb *req, unsigned int issue_flags) | |
93 | { | |
f2ccb5ae | 94 | struct io_fadvise *fa = io_kiocb_to_cmd(req, struct io_fadvise); |
f4c163dd JA |
95 | int ret; |
96 | ||
c31cc60f | 97 | WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK && io_fadvise_force_async(fa)); |
f4c163dd JA |
98 | |
99 | ret = vfs_fadvise(req->file, fa->offset, fa->len, fa->advice); | |
100 | if (ret < 0) | |
101 | req_set_fail(req); | |
102 | io_req_set_res(req, ret, 0); | |
103 | return IOU_OK; | |
104 | } |