public inbox for [email protected]
 help / color / mirror / Atom feed
From: Jens Axboe <[email protected]>
To: [email protected]
Cc: [email protected], Jens Axboe <[email protected]>
Subject: [PATCH 08/10] io_uring: add support for IORING_OP_CLOSE
Date: Fri, 13 Dec 2019 11:36:30 -0700	[thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>

This works just like close(2), unsurprisingly. We remove the file
descriptor and post the completion inline, then offload the actual
(potential) last file put to async context.

Mark the async part of this work as uncancellable, as we really must
guarantee that the latter part of the close is run.

Signed-off-by: Jens Axboe <[email protected]>
---
 fs/io_uring.c                 | 70 +++++++++++++++++++++++++++++++++++
 include/uapi/linux/io_uring.h |  1 +
 2 files changed, 71 insertions(+)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 132f887ef18d..927f28112f0e 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -298,6 +298,11 @@ struct io_poll_iocb {
 	struct wait_queue_entry		wait;
 };
 
+struct io_close {
+	struct file			*file;
+	struct file			*put_file;
+};
+
 struct io_timeout_data {
 	struct io_kiocb			*req;
 	struct hrtimer			timer;
@@ -350,6 +355,7 @@ struct io_kiocb {
 		struct file		*file;
 		struct kiocb		rw;
 		struct io_poll_iocb	poll;
+		struct io_close		close;
 	};
 
 	const struct io_uring_sqe	*sqe;
@@ -2093,6 +2099,64 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt,
 	return 0;
 }
 
+static int io_close(struct io_kiocb *req, struct io_kiocb **nxt,
+		    bool force_nonblock)
+{
+	const struct io_uring_sqe *sqe = req->sqe;
+	int ret, fd;
+
+	if (sqe->ioprio || sqe->off || sqe->addr || sqe->len ||
+	    sqe->rw_flags || sqe->buf_index)
+		return -EINVAL;
+
+	fd = READ_ONCE(sqe->fd);
+	if (req->file->f_op == &io_uring_fops || fd == req->ring_fd)
+		return -EBADF;
+
+	/*
+	 * If we queue this for async, it must not be cancellable. That would
+	 * leave the 'file' in an undeterminate state.
+	 */
+	req->work.flags |= IO_WQ_WORK_NO_CANCEL;
+
+	ret = 0;
+	if (force_nonblock) {
+		req->close.put_file = NULL;
+		ret = __close_fd_get_file(fd, &req->close.put_file);
+		if (ret < 0)
+			return ret;
+
+		/* if the file has a flush method, be safe and punt to async */
+		if (req->close.put_file->f_op->flush) {
+			req->work.flags |= IO_WQ_WORK_NEEDS_FILES;
+			return -EAGAIN;
+		}
+
+		/*
+		 * No ->flush(), safely close from here and just punt the
+		 * fput() to async context.
+		 */
+		ret = filp_close(req->close.put_file, current->files);
+		if (ret < 0)
+			req_set_fail_links(req);
+
+		io_cqring_add_event(req, ret);
+		return -EAGAIN;
+	} else {
+		/* Invoked with files, we need to do the close */
+		if (req->work.files) {
+			ret = filp_close(req->close.put_file, req->work.files);
+			if (ret < 0)
+				req_set_fail_links(req);
+			io_cqring_add_event(req, ret);
+		}
+		fput(req->close.put_file);
+	}
+
+	io_put_req_find_next(req, nxt);
+	return ret;
+}
+
 static int io_prep_sfr(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
 	struct io_ring_ctx *ctx = req->ctx;
@@ -3116,6 +3180,9 @@ static int io_issue_sqe(struct io_kiocb *req, struct io_kiocb **nxt,
 	case IORING_OP_OPENAT:
 		ret = io_openat(req, nxt, force_nonblock);
 		break;
+	case IORING_OP_CLOSE:
+		ret = io_close(req, nxt, force_nonblock);
+		break;
 	default:
 		ret = -EINVAL;
 		break;
@@ -3275,6 +3342,9 @@ static int io_grab_files(struct io_kiocb *req)
 	int ret = -EBADF;
 	struct io_ring_ctx *ctx = req->ctx;
 
+	if (!req->ring_file)
+		return -EBADF;
+
 	rcu_read_lock();
 	spin_lock_irq(&ctx->inflight_lock);
 	/*
diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 02af580754ce..42a7f0e8dee3 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -79,6 +79,7 @@ enum {
 	IORING_OP_CONNECT,
 	IORING_OP_FALLOCATE,
 	IORING_OP_OPENAT,
+	IORING_OP_CLOSE,
 
 	/* this goes last, obviously */
 	IORING_OP_LAST,
-- 
2.24.1


  parent reply	other threads:[~2019-12-13 20:40 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-13 18:36 [PATCHSET 0/10] io_uring items for 5.6 Jens Axboe
2019-12-13 18:36 ` [PATCH 01/10] io_uring: add support for fallocate() Jens Axboe
2019-12-13 18:36 ` [PATCH 02/10] io_uring: remove 'sqe' parameter to the OP helpers that take it Jens Axboe
2019-12-13 18:36 ` [PATCH 03/10] fs: add namei support for doing a non-blocking path lookup Jens Axboe
2019-12-27  0:42   ` Al Viro
2019-12-27  5:05     ` Jens Axboe
2019-12-27  5:25       ` Jens Axboe
2019-12-27 15:45         ` Jens Axboe
2019-12-28 19:03           ` Jens Axboe
2019-12-13 18:36 ` [PATCH 04/10] fs: make build_open_flags() available internally Jens Axboe
2019-12-13 18:36 ` [PATCH 05/10] io_uring: add support for IORING_OP_OPENAT Jens Axboe
2019-12-13 18:36 ` [PATCH 06/10] fs: move filp_close() outside of __close_fd_get_file() Jens Axboe
2019-12-16 19:27   ` Jann Horn
2019-12-16 19:39     ` Jens Axboe
2019-12-13 18:36 ` [PATCH 07/10] io-wq: add support for uncancellable work Jens Axboe
2019-12-13 18:36 ` Jens Axboe [this message]
2019-12-13 18:36 ` [PATCH 09/10] io_uring: use u64_to_user_ptr() consistently Jens Axboe
2019-12-13 18:36 ` [PATCH 10/10] io_uring: avoid ring quiesce for fixed file set unregister and update Jens Axboe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox