2022-05-25 06:28:33 +03:00
// SPDX-License-Identifier: GPL-2.0
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/fs.h>
# include <linux/file.h>
# include <linux/mm.h>
# include <linux/slab.h>
# include <linux/namei.h>
# include <linux/io_uring.h>
# include <uapi/linux/fadvise.h>
# include <uapi/linux/io_uring.h>
# include "io_uring.h"
# include "advise.h"
struct io_fadvise {
struct file * file ;
u64 offset ;
u32 len ;
u32 advice ;
} ;
struct io_madvise {
struct file * file ;
u64 addr ;
u32 len ;
u32 advice ;
} ;
int io_madvise_prep ( struct io_kiocb * req , const struct io_uring_sqe * sqe )
{
# if defined(CONFIG_ADVISE_SYSCALLS) && defined(CONFIG_MMU)
2022-08-11 10:11:15 +03:00
struct io_madvise * ma = io_kiocb_to_cmd ( req , struct io_madvise ) ;
2022-05-25 06:28:33 +03:00
if ( sqe - > buf_index | | sqe - > off | | sqe - > splice_fd_in )
return - EINVAL ;
ma - > addr = READ_ONCE ( sqe - > addr ) ;
ma - > len = READ_ONCE ( sqe - > len ) ;
ma - > advice = READ_ONCE ( sqe - > fadvise_advice ) ;
2023-01-27 16:52:25 +03:00
req - > flags | = REQ_F_FORCE_ASYNC ;
2022-05-25 06:28:33 +03:00
return 0 ;
# else
return - EOPNOTSUPP ;
# endif
}
int io_madvise ( struct io_kiocb * req , unsigned int issue_flags )
{
# if defined(CONFIG_ADVISE_SYSCALLS) && defined(CONFIG_MMU)
2022-08-11 10:11:15 +03:00
struct io_madvise * ma = io_kiocb_to_cmd ( req , struct io_madvise ) ;
2022-05-25 06:28:33 +03:00
int ret ;
2023-01-27 16:52:25 +03:00
WARN_ON_ONCE ( issue_flags & IO_URING_F_NONBLOCK ) ;
2022-05-25 06:28:33 +03:00
ret = do_madvise ( current - > mm , ma - > addr , ma - > len , ma - > advice ) ;
io_req_set_res ( req , ret , 0 ) ;
return IOU_OK ;
# else
return - EOPNOTSUPP ;
# endif
}
int io_fadvise_prep ( struct io_kiocb * req , const struct io_uring_sqe * sqe )
{
2022-08-11 10:11:15 +03:00
struct io_fadvise * fa = io_kiocb_to_cmd ( req , struct io_fadvise ) ;
2022-05-25 06:28:33 +03:00
if ( sqe - > buf_index | | sqe - > addr | | sqe - > splice_fd_in )
return - EINVAL ;
fa - > offset = READ_ONCE ( sqe - > off ) ;
fa - > len = READ_ONCE ( sqe - > len ) ;
fa - > advice = READ_ONCE ( sqe - > fadvise_advice ) ;
return 0 ;
}
int io_fadvise ( struct io_kiocb * req , unsigned int issue_flags )
{
2022-08-11 10:11:15 +03:00
struct io_fadvise * fa = io_kiocb_to_cmd ( req , struct io_fadvise ) ;
2022-05-25 06:28:33 +03:00
int ret ;
if ( issue_flags & IO_URING_F_NONBLOCK ) {
switch ( fa - > advice ) {
case POSIX_FADV_NORMAL :
case POSIX_FADV_RANDOM :
case POSIX_FADV_SEQUENTIAL :
break ;
default :
return - EAGAIN ;
}
}
ret = vfs_fadvise ( req - > file , fa - > offset , fa - > len , fa - > advice ) ;
if ( ret < 0 )
req_set_fail ( req ) ;
io_req_set_res ( req , ret , 0 ) ;
return IOU_OK ;
}