io_uring: add support for IORING_OP_OPENAT2
Add support for the new openat2(2) system call. It's trivial to do, as we can have openat(2) just be wrapped around it. Suggested-by: Stefan Metzmacher <metze@samba.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
		
							parent
							
								
									f8748881b1
								
							
						
					
					
						commit
						cebdb98617
					
				| @ -707,6 +707,11 @@ static const struct io_op_def io_op_defs[] = { | ||||
| 		.needs_file		= 1, | ||||
| 		.unbound_nonreg_file	= 1, | ||||
| 	}, | ||||
| 	{ | ||||
| 		/* IORING_OP_OPENAT2 */ | ||||
| 		.needs_file		= 1, | ||||
| 		.fd_non_neg		= 1, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| static void io_wq_submit_work(struct io_wq_work **workptr); | ||||
| @ -2487,11 +2492,46 @@ static int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, | ||||
| 		     bool force_nonblock) | ||||
| static int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) | ||||
| { | ||||
| 	struct open_how __user *how; | ||||
| 	const char __user *fname; | ||||
| 	size_t len; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (sqe->ioprio || sqe->buf_index) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	req->open.dfd = READ_ONCE(sqe->fd); | ||||
| 	fname = u64_to_user_ptr(READ_ONCE(sqe->addr)); | ||||
| 	how = u64_to_user_ptr(READ_ONCE(sqe->addr2)); | ||||
| 	len = READ_ONCE(sqe->len); | ||||
| 
 | ||||
| 	if (len < OPEN_HOW_SIZE_VER0) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	ret = copy_struct_from_user(&req->open.how, sizeof(req->open.how), how, | ||||
| 					len); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	if (!(req->open.how.flags & O_PATH) && force_o_largefile()) | ||||
| 		req->open.how.flags |= O_LARGEFILE; | ||||
| 
 | ||||
| 	req->open.filename = getname(fname); | ||||
| 	if (IS_ERR(req->open.filename)) { | ||||
| 		ret = PTR_ERR(req->open.filename); | ||||
| 		req->open.filename = NULL; | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int io_openat2(struct io_kiocb *req, struct io_kiocb **nxt, | ||||
| 		      bool force_nonblock) | ||||
| { | ||||
| 	struct open_flags op; | ||||
| 	struct open_how how; | ||||
| 	struct file *file; | ||||
| 	int ret; | ||||
| 
 | ||||
| @ -2500,12 +2540,11 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, | ||||
| 		return -EAGAIN; | ||||
| 	} | ||||
| 
 | ||||
| 	how = build_open_how(req->open.how.flags, req->open.how.mode); | ||||
| 	ret = build_open_flags(&how, &op); | ||||
| 	ret = build_open_flags(&req->open.how, &op); | ||||
| 	if (ret) | ||||
| 		goto err; | ||||
| 
 | ||||
| 	ret = get_unused_fd_flags(how.flags); | ||||
| 	ret = get_unused_fd_flags(req->open.how.flags); | ||||
| 	if (ret < 0) | ||||
| 		goto err; | ||||
| 
 | ||||
| @ -2526,6 +2565,13 @@ err: | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, | ||||
| 		     bool force_nonblock) | ||||
| { | ||||
| 	req->open.how = build_open_how(req->open.how.flags, req->open.how.mode); | ||||
| 	return io_openat2(req, nxt, force_nonblock); | ||||
| } | ||||
| 
 | ||||
| static int io_madvise_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) | ||||
| { | ||||
| #if defined(CONFIG_ADVISE_SYSCALLS) && defined(CONFIG_MMU) | ||||
| @ -3984,6 +4030,9 @@ static int io_req_defer_prep(struct io_kiocb *req, | ||||
| 	case IORING_OP_MADVISE: | ||||
| 		ret = io_madvise_prep(req, sqe); | ||||
| 		break; | ||||
| 	case IORING_OP_OPENAT2: | ||||
| 		ret = io_openat2_prep(req, sqe); | ||||
| 		break; | ||||
| 	default: | ||||
| 		printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", | ||||
| 				req->opcode); | ||||
| @ -4204,6 +4253,14 @@ static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe, | ||||
| 		} | ||||
| 		ret = io_madvise(req, nxt, force_nonblock); | ||||
| 		break; | ||||
| 	case IORING_OP_OPENAT2: | ||||
| 		if (sqe) { | ||||
| 			ret = io_openat2_prep(req, sqe); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 		} | ||||
| 		ret = io_openat2(req, nxt, force_nonblock); | ||||
| 		break; | ||||
| 	default: | ||||
| 		ret = -EINVAL; | ||||
| 		break; | ||||
|  | ||||
| @ -92,6 +92,7 @@ enum { | ||||
| 	IORING_OP_MADVISE, | ||||
| 	IORING_OP_SEND, | ||||
| 	IORING_OP_RECV, | ||||
| 	IORING_OP_OPENAT2, | ||||
| 
 | ||||
| 	/* this goes last, obviously */ | ||||
| 	IORING_OP_LAST, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user