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