Skip to content
Snippets Groups Projects
Forked from drm / kernel
29777 commits behind the upstream repository.
  • Jens Axboe's avatar
    3b87184f
    io_uring/advise: support 64-bit lengths · 3b87184f
    Jens Axboe authored
    
    The existing fadvise/madvise support only supports 32-bit lengths. Add
    support for 64-bit lengths, enabled by the application setting sqe->off
    rather than sqe->len for the length. If sqe->len is set, then that is
    used as the 32-bit length. If sqe->len is zero, then sqe->off is read
    for full 64-bit support.
    
    Older kernels will return -EINVAL if 64-bit support isn't available.
    
    Fixes: 4840e418 ("io_uring: add IORING_OP_FADVISE")
    Fixes: c1ca757b ("io_uring: add IORING_OP_MADVISE")
    Reported-by: default avatarStefan <source@s.muenzel.net>
    Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
    3b87184f
    History
    io_uring/advise: support 64-bit lengths
    Jens Axboe authored
    
    The existing fadvise/madvise support only supports 32-bit lengths. Add
    support for 64-bit lengths, enabled by the application setting sqe->off
    rather than sqe->len for the length. If sqe->len is set, then that is
    used as the 32-bit length. If sqe->len is zero, then sqe->off is read
    for full 64-bit support.
    
    Older kernels will return -EINVAL if 64-bit support isn't available.
    
    Fixes: 4840e418 ("io_uring: add IORING_OP_FADVISE")
    Fixes: c1ca757b ("io_uring: add IORING_OP_MADVISE")
    Reported-by: default avatarStefan <source@s.muenzel.net>
    Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
advise.c 2.39 KiB
// 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;
	u64				len;
	u32				advice;
};

struct io_madvise {
	struct file			*file;
	u64				addr;
	u64				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)
	struct io_madvise *ma = io_kiocb_to_cmd(req, struct io_madvise);

	if (sqe->buf_index || sqe->splice_fd_in)
		return -EINVAL;

	ma->addr = READ_ONCE(sqe->addr);
	ma->len = READ_ONCE(sqe->off);
	if (!ma->len)
		ma->len = READ_ONCE(sqe->len);
	ma->advice = READ_ONCE(sqe->fadvise_advice);
	req->flags |= REQ_F_FORCE_ASYNC;
	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)
	struct io_madvise *ma = io_kiocb_to_cmd(req, struct io_madvise);
	int ret;

	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);

	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
}

static bool io_fadvise_force_async(struct io_fadvise *fa)
{
	switch (fa->advice) {
	case POSIX_FADV_NORMAL: