Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/kernel.h>
3#include <linux/errno.h>
4#include <linux/file.h>
5#include <linux/io_uring.h>
6
7#include <uapi/linux/io_uring.h>
8
9#include "../fs/internal.h"
10
11#include "io_uring.h"
12#include "statx.h"
13
14struct io_statx {
15 struct file *file;
16 int dfd;
17 unsigned int mask;
18 unsigned int flags;
19 struct delayed_filename filename;
20 struct statx __user *buffer;
21};
22
23int io_statx_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
24{
25 struct io_statx *sx = io_kiocb_to_cmd(req, struct io_statx);
26 const char __user *path;
27 int ret;
28
29 if (sqe->buf_index || sqe->splice_fd_in)
30 return -EINVAL;
31 if (req->flags & REQ_F_FIXED_FILE)
32 return -EBADF;
33
34 sx->dfd = READ_ONCE(sqe->fd);
35 sx->mask = READ_ONCE(sqe->len);
36 path = u64_to_user_ptr(READ_ONCE(sqe->addr));
37 sx->buffer = u64_to_user_ptr(READ_ONCE(sqe->addr2));
38 sx->flags = READ_ONCE(sqe->statx_flags);
39
40 ret = delayed_getname_uflags(&sx->filename, path, sx->flags);
41
42 if (unlikely(ret))
43 return ret;
44
45 req->flags |= REQ_F_NEED_CLEANUP;
46 req->flags |= REQ_F_FORCE_ASYNC;
47 return 0;
48}
49
50int io_statx(struct io_kiocb *req, unsigned int issue_flags)
51{
52 struct io_statx *sx = io_kiocb_to_cmd(req, struct io_statx);
53 CLASS(filename_complete_delayed, name)(&sx->filename);
54 int ret;
55
56 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
57
58 ret = do_statx(sx->dfd, name, sx->flags, sx->mask, sx->buffer);
59 io_req_set_res(req, ret, 0);
60 return IOU_COMPLETE;
61}
62
63void io_statx_cleanup(struct io_kiocb *req)
64{
65 struct io_statx *sx = io_kiocb_to_cmd(req, struct io_statx);
66
67 dismiss_delayed_filename(&sx->filename);
68}