xref: /openbmc/linux/io_uring/statx.c (revision 9b68f30b)
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 
14 struct io_statx {
15 	struct file			*file;
16 	int				dfd;
17 	unsigned int			mask;
18 	unsigned int			flags;
19 	struct filename			*filename;
20 	struct statx __user		*buffer;
21 };
22 
23 int 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 
28 	if (sqe->buf_index || sqe->splice_fd_in)
29 		return -EINVAL;
30 	if (req->flags & REQ_F_FIXED_FILE)
31 		return -EBADF;
32 
33 	sx->dfd = READ_ONCE(sqe->fd);
34 	sx->mask = READ_ONCE(sqe->len);
35 	path = u64_to_user_ptr(READ_ONCE(sqe->addr));
36 	sx->buffer = u64_to_user_ptr(READ_ONCE(sqe->addr2));
37 	sx->flags = READ_ONCE(sqe->statx_flags);
38 
39 	sx->filename = getname_flags(path,
40 				     getname_statx_lookup_flags(sx->flags),
41 				     NULL);
42 
43 	if (IS_ERR(sx->filename)) {
44 		int ret = PTR_ERR(sx->filename);
45 
46 		sx->filename = NULL;
47 		return ret;
48 	}
49 
50 	req->flags |= REQ_F_NEED_CLEANUP;
51 	req->flags |= REQ_F_FORCE_ASYNC;
52 	return 0;
53 }
54 
55 int io_statx(struct io_kiocb *req, unsigned int issue_flags)
56 {
57 	struct io_statx *sx = io_kiocb_to_cmd(req, struct io_statx);
58 	int ret;
59 
60 	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
61 
62 	ret = do_statx(sx->dfd, sx->filename, sx->flags, sx->mask, sx->buffer);
63 	io_req_set_res(req, ret, 0);
64 	return IOU_OK;
65 }
66 
67 void io_statx_cleanup(struct io_kiocb *req)
68 {
69 	struct io_statx *sx = io_kiocb_to_cmd(req, struct io_statx);
70 
71 	if (sx->filename)
72 		putname(sx->filename);
73 }
74