xref: /linux/fs/fuse/dev_uring.c (revision c2c9af9a0b13261c36909036057a116f2edb5e1a)
124fe962cSBernd Schubert // SPDX-License-Identifier: GPL-2.0
224fe962cSBernd Schubert /*
324fe962cSBernd Schubert  * FUSE: Filesystem in Userspace
424fe962cSBernd Schubert  * Copyright (c) 2023-2024 DataDirect Networks.
524fe962cSBernd Schubert  */
624fe962cSBernd Schubert 
724fe962cSBernd Schubert #include "fuse_i.h"
824fe962cSBernd Schubert #include "dev_uring_i.h"
924fe962cSBernd Schubert #include "fuse_dev_i.h"
1024fe962cSBernd Schubert 
1124fe962cSBernd Schubert #include <linux/fs.h>
1224fe962cSBernd Schubert #include <linux/io_uring/cmd.h>
1324fe962cSBernd Schubert 
1424fe962cSBernd Schubert static bool __read_mostly enable_uring;
1524fe962cSBernd Schubert module_param(enable_uring, bool, 0644);
1624fe962cSBernd Schubert MODULE_PARM_DESC(enable_uring,
1724fe962cSBernd Schubert 		 "Enable userspace communication through io-uring");
1824fe962cSBernd Schubert 
1924fe962cSBernd Schubert #define FUSE_URING_IOV_SEGS 2 /* header and payload */
2024fe962cSBernd Schubert 
2124fe962cSBernd Schubert 
2224fe962cSBernd Schubert bool fuse_uring_enabled(void)
2324fe962cSBernd Schubert {
2424fe962cSBernd Schubert 	return enable_uring;
2524fe962cSBernd Schubert }
2624fe962cSBernd Schubert 
27*c2c9af9aSBernd Schubert struct fuse_uring_pdu {
28*c2c9af9aSBernd Schubert 	struct fuse_ring_ent *ent;
29*c2c9af9aSBernd Schubert };
30*c2c9af9aSBernd Schubert 
31*c2c9af9aSBernd Schubert static const struct fuse_iqueue_ops fuse_io_uring_ops;
32*c2c9af9aSBernd Schubert 
33*c2c9af9aSBernd Schubert static void uring_cmd_set_ring_ent(struct io_uring_cmd *cmd,
34*c2c9af9aSBernd Schubert 				   struct fuse_ring_ent *ring_ent)
35*c2c9af9aSBernd Schubert {
36*c2c9af9aSBernd Schubert 	struct fuse_uring_pdu *pdu =
37*c2c9af9aSBernd Schubert 		io_uring_cmd_to_pdu(cmd, struct fuse_uring_pdu);
38*c2c9af9aSBernd Schubert 
39*c2c9af9aSBernd Schubert 	pdu->ent = ring_ent;
40*c2c9af9aSBernd Schubert }
41*c2c9af9aSBernd Schubert 
42*c2c9af9aSBernd Schubert static struct fuse_ring_ent *uring_cmd_to_ring_ent(struct io_uring_cmd *cmd)
43*c2c9af9aSBernd Schubert {
44*c2c9af9aSBernd Schubert 	struct fuse_uring_pdu *pdu =
45*c2c9af9aSBernd Schubert 		io_uring_cmd_to_pdu(cmd, struct fuse_uring_pdu);
46*c2c9af9aSBernd Schubert 
47*c2c9af9aSBernd Schubert 	return pdu->ent;
48*c2c9af9aSBernd Schubert }
49*c2c9af9aSBernd Schubert 
50c090c8abSBernd Schubert static void fuse_uring_req_end(struct fuse_ring_ent *ent, struct fuse_req *req,
51c090c8abSBernd Schubert 			       int error)
52c090c8abSBernd Schubert {
53c090c8abSBernd Schubert 	ent->fuse_req = NULL;
54c090c8abSBernd Schubert 	if (error)
55c090c8abSBernd Schubert 		req->out.h.error = error;
56c090c8abSBernd Schubert 
57c090c8abSBernd Schubert 	clear_bit(FR_SENT, &req->flags);
58c090c8abSBernd Schubert 	fuse_request_end(req);
59c090c8abSBernd Schubert }
60c090c8abSBernd Schubert 
614a9bfb9bSBernd Schubert /* Abort all list queued request on the given ring queue */
624a9bfb9bSBernd Schubert static void fuse_uring_abort_end_queue_requests(struct fuse_ring_queue *queue)
634a9bfb9bSBernd Schubert {
644a9bfb9bSBernd Schubert 	struct fuse_req *req;
654a9bfb9bSBernd Schubert 	LIST_HEAD(req_list);
664a9bfb9bSBernd Schubert 
674a9bfb9bSBernd Schubert 	spin_lock(&queue->lock);
684a9bfb9bSBernd Schubert 	list_for_each_entry(req, &queue->fuse_req_queue, list)
694a9bfb9bSBernd Schubert 		clear_bit(FR_PENDING, &req->flags);
704a9bfb9bSBernd Schubert 	list_splice_init(&queue->fuse_req_queue, &req_list);
714a9bfb9bSBernd Schubert 	spin_unlock(&queue->lock);
724a9bfb9bSBernd Schubert 
734a9bfb9bSBernd Schubert 	/* must not hold queue lock to avoid order issues with fi->lock */
744a9bfb9bSBernd Schubert 	fuse_dev_end_requests(&req_list);
754a9bfb9bSBernd Schubert }
764a9bfb9bSBernd Schubert 
774a9bfb9bSBernd Schubert void fuse_uring_abort_end_requests(struct fuse_ring *ring)
784a9bfb9bSBernd Schubert {
794a9bfb9bSBernd Schubert 	int qid;
804a9bfb9bSBernd Schubert 	struct fuse_ring_queue *queue;
814a9bfb9bSBernd Schubert 
824a9bfb9bSBernd Schubert 	for (qid = 0; qid < ring->nr_queues; qid++) {
834a9bfb9bSBernd Schubert 		queue = READ_ONCE(ring->queues[qid]);
844a9bfb9bSBernd Schubert 		if (!queue)
854a9bfb9bSBernd Schubert 			continue;
864a9bfb9bSBernd Schubert 
874a9bfb9bSBernd Schubert 		queue->stopped = true;
884a9bfb9bSBernd Schubert 		fuse_uring_abort_end_queue_requests(queue);
894a9bfb9bSBernd Schubert 	}
904a9bfb9bSBernd Schubert }
914a9bfb9bSBernd Schubert 
9224fe962cSBernd Schubert void fuse_uring_destruct(struct fuse_conn *fc)
9324fe962cSBernd Schubert {
9424fe962cSBernd Schubert 	struct fuse_ring *ring = fc->ring;
9524fe962cSBernd Schubert 	int qid;
9624fe962cSBernd Schubert 
9724fe962cSBernd Schubert 	if (!ring)
9824fe962cSBernd Schubert 		return;
9924fe962cSBernd Schubert 
10024fe962cSBernd Schubert 	for (qid = 0; qid < ring->nr_queues; qid++) {
10124fe962cSBernd Schubert 		struct fuse_ring_queue *queue = ring->queues[qid];
10224fe962cSBernd Schubert 
10324fe962cSBernd Schubert 		if (!queue)
10424fe962cSBernd Schubert 			continue;
10524fe962cSBernd Schubert 
10624fe962cSBernd Schubert 		WARN_ON(!list_empty(&queue->ent_avail_queue));
107c090c8abSBernd Schubert 		WARN_ON(!list_empty(&queue->ent_w_req_queue));
10824fe962cSBernd Schubert 		WARN_ON(!list_empty(&queue->ent_commit_queue));
109c090c8abSBernd Schubert 		WARN_ON(!list_empty(&queue->ent_in_userspace));
11024fe962cSBernd Schubert 
111c090c8abSBernd Schubert 		kfree(queue->fpq.processing);
11224fe962cSBernd Schubert 		kfree(queue);
11324fe962cSBernd Schubert 		ring->queues[qid] = NULL;
11424fe962cSBernd Schubert 	}
11524fe962cSBernd Schubert 
11624fe962cSBernd Schubert 	kfree(ring->queues);
11724fe962cSBernd Schubert 	kfree(ring);
11824fe962cSBernd Schubert 	fc->ring = NULL;
11924fe962cSBernd Schubert }
12024fe962cSBernd Schubert 
12124fe962cSBernd Schubert /*
12224fe962cSBernd Schubert  * Basic ring setup for this connection based on the provided configuration
12324fe962cSBernd Schubert  */
12424fe962cSBernd Schubert static struct fuse_ring *fuse_uring_create(struct fuse_conn *fc)
12524fe962cSBernd Schubert {
12624fe962cSBernd Schubert 	struct fuse_ring *ring;
12724fe962cSBernd Schubert 	size_t nr_queues = num_possible_cpus();
12824fe962cSBernd Schubert 	struct fuse_ring *res = NULL;
12924fe962cSBernd Schubert 	size_t max_payload_size;
13024fe962cSBernd Schubert 
13124fe962cSBernd Schubert 	ring = kzalloc(sizeof(*fc->ring), GFP_KERNEL_ACCOUNT);
13224fe962cSBernd Schubert 	if (!ring)
13324fe962cSBernd Schubert 		return NULL;
13424fe962cSBernd Schubert 
13524fe962cSBernd Schubert 	ring->queues = kcalloc(nr_queues, sizeof(struct fuse_ring_queue *),
13624fe962cSBernd Schubert 			       GFP_KERNEL_ACCOUNT);
13724fe962cSBernd Schubert 	if (!ring->queues)
13824fe962cSBernd Schubert 		goto out_err;
13924fe962cSBernd Schubert 
14024fe962cSBernd Schubert 	max_payload_size = max(FUSE_MIN_READ_BUFFER, fc->max_write);
14124fe962cSBernd Schubert 	max_payload_size = max(max_payload_size, fc->max_pages * PAGE_SIZE);
14224fe962cSBernd Schubert 
14324fe962cSBernd Schubert 	spin_lock(&fc->lock);
14424fe962cSBernd Schubert 	if (fc->ring) {
14524fe962cSBernd Schubert 		/* race, another thread created the ring in the meantime */
14624fe962cSBernd Schubert 		spin_unlock(&fc->lock);
14724fe962cSBernd Schubert 		res = fc->ring;
14824fe962cSBernd Schubert 		goto out_err;
14924fe962cSBernd Schubert 	}
15024fe962cSBernd Schubert 
1514a9bfb9bSBernd Schubert 	init_waitqueue_head(&ring->stop_waitq);
1524a9bfb9bSBernd Schubert 
15324fe962cSBernd Schubert 	fc->ring = ring;
15424fe962cSBernd Schubert 	ring->nr_queues = nr_queues;
15524fe962cSBernd Schubert 	ring->fc = fc;
15624fe962cSBernd Schubert 	ring->max_payload_sz = max_payload_size;
1574a9bfb9bSBernd Schubert 	atomic_set(&ring->queue_refs, 0);
15824fe962cSBernd Schubert 
15924fe962cSBernd Schubert 	spin_unlock(&fc->lock);
16024fe962cSBernd Schubert 	return ring;
16124fe962cSBernd Schubert 
16224fe962cSBernd Schubert out_err:
16324fe962cSBernd Schubert 	kfree(ring->queues);
16424fe962cSBernd Schubert 	kfree(ring);
16524fe962cSBernd Schubert 	return res;
16624fe962cSBernd Schubert }
16724fe962cSBernd Schubert 
16824fe962cSBernd Schubert static struct fuse_ring_queue *fuse_uring_create_queue(struct fuse_ring *ring,
16924fe962cSBernd Schubert 						       int qid)
17024fe962cSBernd Schubert {
17124fe962cSBernd Schubert 	struct fuse_conn *fc = ring->fc;
17224fe962cSBernd Schubert 	struct fuse_ring_queue *queue;
173c090c8abSBernd Schubert 	struct list_head *pq;
17424fe962cSBernd Schubert 
17524fe962cSBernd Schubert 	queue = kzalloc(sizeof(*queue), GFP_KERNEL_ACCOUNT);
17624fe962cSBernd Schubert 	if (!queue)
17724fe962cSBernd Schubert 		return NULL;
178c090c8abSBernd Schubert 	pq = kcalloc(FUSE_PQ_HASH_SIZE, sizeof(struct list_head), GFP_KERNEL);
179c090c8abSBernd Schubert 	if (!pq) {
180c090c8abSBernd Schubert 		kfree(queue);
181c090c8abSBernd Schubert 		return NULL;
182c090c8abSBernd Schubert 	}
183c090c8abSBernd Schubert 
18424fe962cSBernd Schubert 	queue->qid = qid;
18524fe962cSBernd Schubert 	queue->ring = ring;
18624fe962cSBernd Schubert 	spin_lock_init(&queue->lock);
18724fe962cSBernd Schubert 
18824fe962cSBernd Schubert 	INIT_LIST_HEAD(&queue->ent_avail_queue);
18924fe962cSBernd Schubert 	INIT_LIST_HEAD(&queue->ent_commit_queue);
190c090c8abSBernd Schubert 	INIT_LIST_HEAD(&queue->ent_w_req_queue);
191c090c8abSBernd Schubert 	INIT_LIST_HEAD(&queue->ent_in_userspace);
192c090c8abSBernd Schubert 	INIT_LIST_HEAD(&queue->fuse_req_queue);
193c090c8abSBernd Schubert 
194c090c8abSBernd Schubert 	queue->fpq.processing = pq;
195c090c8abSBernd Schubert 	fuse_pqueue_init(&queue->fpq);
19624fe962cSBernd Schubert 
19724fe962cSBernd Schubert 	spin_lock(&fc->lock);
19824fe962cSBernd Schubert 	if (ring->queues[qid]) {
19924fe962cSBernd Schubert 		spin_unlock(&fc->lock);
200c090c8abSBernd Schubert 		kfree(queue->fpq.processing);
20124fe962cSBernd Schubert 		kfree(queue);
20224fe962cSBernd Schubert 		return ring->queues[qid];
20324fe962cSBernd Schubert 	}
20424fe962cSBernd Schubert 
20524fe962cSBernd Schubert 	/*
20624fe962cSBernd Schubert 	 * write_once and lock as the caller mostly doesn't take the lock at all
20724fe962cSBernd Schubert 	 */
20824fe962cSBernd Schubert 	WRITE_ONCE(ring->queues[qid], queue);
20924fe962cSBernd Schubert 	spin_unlock(&fc->lock);
21024fe962cSBernd Schubert 
21124fe962cSBernd Schubert 	return queue;
21224fe962cSBernd Schubert }
21324fe962cSBernd Schubert 
2144a9bfb9bSBernd Schubert static void fuse_uring_stop_fuse_req_end(struct fuse_req *req)
2154a9bfb9bSBernd Schubert {
2164a9bfb9bSBernd Schubert 	clear_bit(FR_SENT, &req->flags);
2174a9bfb9bSBernd Schubert 	req->out.h.error = -ECONNABORTED;
2184a9bfb9bSBernd Schubert 	fuse_request_end(req);
2194a9bfb9bSBernd Schubert }
2204a9bfb9bSBernd Schubert 
2214a9bfb9bSBernd Schubert /*
2224a9bfb9bSBernd Schubert  * Release a request/entry on connection tear down
2234a9bfb9bSBernd Schubert  */
2244a9bfb9bSBernd Schubert static void fuse_uring_entry_teardown(struct fuse_ring_ent *ent)
2254a9bfb9bSBernd Schubert {
2264a9bfb9bSBernd Schubert 	struct fuse_req *req;
2274a9bfb9bSBernd Schubert 	struct io_uring_cmd *cmd;
2284a9bfb9bSBernd Schubert 
2294a9bfb9bSBernd Schubert 	struct fuse_ring_queue *queue = ent->queue;
2304a9bfb9bSBernd Schubert 
2314a9bfb9bSBernd Schubert 	spin_lock(&queue->lock);
2324a9bfb9bSBernd Schubert 	cmd = ent->cmd;
2334a9bfb9bSBernd Schubert 	ent->cmd = NULL;
2344a9bfb9bSBernd Schubert 	req = ent->fuse_req;
2354a9bfb9bSBernd Schubert 	ent->fuse_req = NULL;
2364a9bfb9bSBernd Schubert 	if (req) {
2374a9bfb9bSBernd Schubert 		/* remove entry from queue->fpq->processing */
2384a9bfb9bSBernd Schubert 		list_del_init(&req->list);
2394a9bfb9bSBernd Schubert 	}
2404a9bfb9bSBernd Schubert 	spin_unlock(&queue->lock);
2414a9bfb9bSBernd Schubert 
2424a9bfb9bSBernd Schubert 	if (cmd)
2434a9bfb9bSBernd Schubert 		io_uring_cmd_done(cmd, -ENOTCONN, 0, IO_URING_F_UNLOCKED);
2444a9bfb9bSBernd Schubert 
2454a9bfb9bSBernd Schubert 	if (req)
2464a9bfb9bSBernd Schubert 		fuse_uring_stop_fuse_req_end(req);
2474a9bfb9bSBernd Schubert 
2484a9bfb9bSBernd Schubert 	list_del_init(&ent->list);
2494a9bfb9bSBernd Schubert 	kfree(ent);
2504a9bfb9bSBernd Schubert }
2514a9bfb9bSBernd Schubert 
2524a9bfb9bSBernd Schubert static void fuse_uring_stop_list_entries(struct list_head *head,
2534a9bfb9bSBernd Schubert 					 struct fuse_ring_queue *queue,
2544a9bfb9bSBernd Schubert 					 enum fuse_ring_req_state exp_state)
2554a9bfb9bSBernd Schubert {
2564a9bfb9bSBernd Schubert 	struct fuse_ring *ring = queue->ring;
2574a9bfb9bSBernd Schubert 	struct fuse_ring_ent *ent, *next;
2584a9bfb9bSBernd Schubert 	ssize_t queue_refs = SSIZE_MAX;
2594a9bfb9bSBernd Schubert 	LIST_HEAD(to_teardown);
2604a9bfb9bSBernd Schubert 
2614a9bfb9bSBernd Schubert 	spin_lock(&queue->lock);
2624a9bfb9bSBernd Schubert 	list_for_each_entry_safe(ent, next, head, list) {
2634a9bfb9bSBernd Schubert 		if (ent->state != exp_state) {
2644a9bfb9bSBernd Schubert 			pr_warn("entry teardown qid=%d state=%d expected=%d",
2654a9bfb9bSBernd Schubert 				queue->qid, ent->state, exp_state);
2664a9bfb9bSBernd Schubert 			continue;
2674a9bfb9bSBernd Schubert 		}
2684a9bfb9bSBernd Schubert 
2694a9bfb9bSBernd Schubert 		list_move(&ent->list, &to_teardown);
2704a9bfb9bSBernd Schubert 	}
2714a9bfb9bSBernd Schubert 	spin_unlock(&queue->lock);
2724a9bfb9bSBernd Schubert 
2734a9bfb9bSBernd Schubert 	/* no queue lock to avoid lock order issues */
2744a9bfb9bSBernd Schubert 	list_for_each_entry_safe(ent, next, &to_teardown, list) {
2754a9bfb9bSBernd Schubert 		fuse_uring_entry_teardown(ent);
2764a9bfb9bSBernd Schubert 		queue_refs = atomic_dec_return(&ring->queue_refs);
2774a9bfb9bSBernd Schubert 		WARN_ON_ONCE(queue_refs < 0);
2784a9bfb9bSBernd Schubert 	}
2794a9bfb9bSBernd Schubert }
2804a9bfb9bSBernd Schubert 
2814a9bfb9bSBernd Schubert static void fuse_uring_teardown_entries(struct fuse_ring_queue *queue)
2824a9bfb9bSBernd Schubert {
2834a9bfb9bSBernd Schubert 	fuse_uring_stop_list_entries(&queue->ent_in_userspace, queue,
2844a9bfb9bSBernd Schubert 				     FRRS_USERSPACE);
2854a9bfb9bSBernd Schubert 	fuse_uring_stop_list_entries(&queue->ent_avail_queue, queue,
2864a9bfb9bSBernd Schubert 				     FRRS_AVAILABLE);
2874a9bfb9bSBernd Schubert }
2884a9bfb9bSBernd Schubert 
2894a9bfb9bSBernd Schubert /*
2904a9bfb9bSBernd Schubert  * Log state debug info
2914a9bfb9bSBernd Schubert  */
2924a9bfb9bSBernd Schubert static void fuse_uring_log_ent_state(struct fuse_ring *ring)
2934a9bfb9bSBernd Schubert {
2944a9bfb9bSBernd Schubert 	int qid;
2954a9bfb9bSBernd Schubert 	struct fuse_ring_ent *ent;
2964a9bfb9bSBernd Schubert 
2974a9bfb9bSBernd Schubert 	for (qid = 0; qid < ring->nr_queues; qid++) {
2984a9bfb9bSBernd Schubert 		struct fuse_ring_queue *queue = ring->queues[qid];
2994a9bfb9bSBernd Schubert 
3004a9bfb9bSBernd Schubert 		if (!queue)
3014a9bfb9bSBernd Schubert 			continue;
3024a9bfb9bSBernd Schubert 
3034a9bfb9bSBernd Schubert 		spin_lock(&queue->lock);
3044a9bfb9bSBernd Schubert 		/*
3054a9bfb9bSBernd Schubert 		 * Log entries from the intermediate queue, the other queues
3064a9bfb9bSBernd Schubert 		 * should be empty
3074a9bfb9bSBernd Schubert 		 */
3084a9bfb9bSBernd Schubert 		list_for_each_entry(ent, &queue->ent_w_req_queue, list) {
3094a9bfb9bSBernd Schubert 			pr_info(" ent-req-queue ring=%p qid=%d ent=%p state=%d\n",
3104a9bfb9bSBernd Schubert 				ring, qid, ent, ent->state);
3114a9bfb9bSBernd Schubert 		}
3124a9bfb9bSBernd Schubert 		list_for_each_entry(ent, &queue->ent_commit_queue, list) {
3134a9bfb9bSBernd Schubert 			pr_info(" ent-commit-queue ring=%p qid=%d ent=%p state=%d\n",
3144a9bfb9bSBernd Schubert 				ring, qid, ent, ent->state);
3154a9bfb9bSBernd Schubert 		}
3164a9bfb9bSBernd Schubert 		spin_unlock(&queue->lock);
3174a9bfb9bSBernd Schubert 	}
3184a9bfb9bSBernd Schubert 	ring->stop_debug_log = 1;
3194a9bfb9bSBernd Schubert }
3204a9bfb9bSBernd Schubert 
3214a9bfb9bSBernd Schubert static void fuse_uring_async_stop_queues(struct work_struct *work)
3224a9bfb9bSBernd Schubert {
3234a9bfb9bSBernd Schubert 	int qid;
3244a9bfb9bSBernd Schubert 	struct fuse_ring *ring =
3254a9bfb9bSBernd Schubert 		container_of(work, struct fuse_ring, async_teardown_work.work);
3264a9bfb9bSBernd Schubert 
3274a9bfb9bSBernd Schubert 	/* XXX code dup */
3284a9bfb9bSBernd Schubert 	for (qid = 0; qid < ring->nr_queues; qid++) {
3294a9bfb9bSBernd Schubert 		struct fuse_ring_queue *queue = READ_ONCE(ring->queues[qid]);
3304a9bfb9bSBernd Schubert 
3314a9bfb9bSBernd Schubert 		if (!queue)
3324a9bfb9bSBernd Schubert 			continue;
3334a9bfb9bSBernd Schubert 
3344a9bfb9bSBernd Schubert 		fuse_uring_teardown_entries(queue);
3354a9bfb9bSBernd Schubert 	}
3364a9bfb9bSBernd Schubert 
3374a9bfb9bSBernd Schubert 	/*
3384a9bfb9bSBernd Schubert 	 * Some ring entries might be in the middle of IO operations,
3394a9bfb9bSBernd Schubert 	 * i.e. in process to get handled by file_operations::uring_cmd
3404a9bfb9bSBernd Schubert 	 * or on the way to userspace - we could handle that with conditions in
3414a9bfb9bSBernd Schubert 	 * run time code, but easier/cleaner to have an async tear down handler
3424a9bfb9bSBernd Schubert 	 * If there are still queue references left
3434a9bfb9bSBernd Schubert 	 */
3444a9bfb9bSBernd Schubert 	if (atomic_read(&ring->queue_refs) > 0) {
3454a9bfb9bSBernd Schubert 		if (time_after(jiffies,
3464a9bfb9bSBernd Schubert 			       ring->teardown_time + FUSE_URING_TEARDOWN_TIMEOUT))
3474a9bfb9bSBernd Schubert 			fuse_uring_log_ent_state(ring);
3484a9bfb9bSBernd Schubert 
3494a9bfb9bSBernd Schubert 		schedule_delayed_work(&ring->async_teardown_work,
3504a9bfb9bSBernd Schubert 				      FUSE_URING_TEARDOWN_INTERVAL);
3514a9bfb9bSBernd Schubert 	} else {
3524a9bfb9bSBernd Schubert 		wake_up_all(&ring->stop_waitq);
3534a9bfb9bSBernd Schubert 	}
3544a9bfb9bSBernd Schubert }
3554a9bfb9bSBernd Schubert 
3564a9bfb9bSBernd Schubert /*
3574a9bfb9bSBernd Schubert  * Stop the ring queues
3584a9bfb9bSBernd Schubert  */
3594a9bfb9bSBernd Schubert void fuse_uring_stop_queues(struct fuse_ring *ring)
3604a9bfb9bSBernd Schubert {
3614a9bfb9bSBernd Schubert 	int qid;
3624a9bfb9bSBernd Schubert 
3634a9bfb9bSBernd Schubert 	for (qid = 0; qid < ring->nr_queues; qid++) {
3644a9bfb9bSBernd Schubert 		struct fuse_ring_queue *queue = READ_ONCE(ring->queues[qid]);
3654a9bfb9bSBernd Schubert 
3664a9bfb9bSBernd Schubert 		if (!queue)
3674a9bfb9bSBernd Schubert 			continue;
3684a9bfb9bSBernd Schubert 
3694a9bfb9bSBernd Schubert 		fuse_uring_teardown_entries(queue);
3704a9bfb9bSBernd Schubert 	}
3714a9bfb9bSBernd Schubert 
3724a9bfb9bSBernd Schubert 	if (atomic_read(&ring->queue_refs) > 0) {
3734a9bfb9bSBernd Schubert 		ring->teardown_time = jiffies;
3744a9bfb9bSBernd Schubert 		INIT_DELAYED_WORK(&ring->async_teardown_work,
3754a9bfb9bSBernd Schubert 				  fuse_uring_async_stop_queues);
3764a9bfb9bSBernd Schubert 		schedule_delayed_work(&ring->async_teardown_work,
3774a9bfb9bSBernd Schubert 				      FUSE_URING_TEARDOWN_INTERVAL);
3784a9bfb9bSBernd Schubert 	} else {
3794a9bfb9bSBernd Schubert 		wake_up_all(&ring->stop_waitq);
3804a9bfb9bSBernd Schubert 	}
3814a9bfb9bSBernd Schubert }
3824a9bfb9bSBernd Schubert 
38324fe962cSBernd Schubert /*
384c090c8abSBernd Schubert  * Checks for errors and stores it into the request
385c090c8abSBernd Schubert  */
386c090c8abSBernd Schubert static int fuse_uring_out_header_has_err(struct fuse_out_header *oh,
387c090c8abSBernd Schubert 					 struct fuse_req *req,
388c090c8abSBernd Schubert 					 struct fuse_conn *fc)
389c090c8abSBernd Schubert {
390c090c8abSBernd Schubert 	int err;
391c090c8abSBernd Schubert 
392c090c8abSBernd Schubert 	err = -EINVAL;
393c090c8abSBernd Schubert 	if (oh->unique == 0) {
394c090c8abSBernd Schubert 		/* Not supported through io-uring yet */
395c090c8abSBernd Schubert 		pr_warn_once("notify through fuse-io-uring not supported\n");
396c090c8abSBernd Schubert 		goto err;
397c090c8abSBernd Schubert 	}
398c090c8abSBernd Schubert 
399c090c8abSBernd Schubert 	if (oh->error <= -ERESTARTSYS || oh->error > 0)
400c090c8abSBernd Schubert 		goto err;
401c090c8abSBernd Schubert 
402c090c8abSBernd Schubert 	if (oh->error) {
403c090c8abSBernd Schubert 		err = oh->error;
404c090c8abSBernd Schubert 		goto err;
405c090c8abSBernd Schubert 	}
406c090c8abSBernd Schubert 
407c090c8abSBernd Schubert 	err = -ENOENT;
408c090c8abSBernd Schubert 	if ((oh->unique & ~FUSE_INT_REQ_BIT) != req->in.h.unique) {
409c090c8abSBernd Schubert 		pr_warn_ratelimited("unique mismatch, expected: %llu got %llu\n",
410c090c8abSBernd Schubert 				    req->in.h.unique,
411c090c8abSBernd Schubert 				    oh->unique & ~FUSE_INT_REQ_BIT);
412c090c8abSBernd Schubert 		goto err;
413c090c8abSBernd Schubert 	}
414c090c8abSBernd Schubert 
415c090c8abSBernd Schubert 	/*
416c090c8abSBernd Schubert 	 * Is it an interrupt reply ID?
417c090c8abSBernd Schubert 	 * XXX: Not supported through fuse-io-uring yet, it should not even
418c090c8abSBernd Schubert 	 *      find the request - should not happen.
419c090c8abSBernd Schubert 	 */
420c090c8abSBernd Schubert 	WARN_ON_ONCE(oh->unique & FUSE_INT_REQ_BIT);
421c090c8abSBernd Schubert 
422c090c8abSBernd Schubert 	err = 0;
423c090c8abSBernd Schubert err:
424c090c8abSBernd Schubert 	return err;
425c090c8abSBernd Schubert }
426c090c8abSBernd Schubert 
427c090c8abSBernd Schubert static int fuse_uring_copy_from_ring(struct fuse_ring *ring,
428c090c8abSBernd Schubert 				     struct fuse_req *req,
429c090c8abSBernd Schubert 				     struct fuse_ring_ent *ent)
430c090c8abSBernd Schubert {
431c090c8abSBernd Schubert 	struct fuse_copy_state cs;
432c090c8abSBernd Schubert 	struct fuse_args *args = req->args;
433c090c8abSBernd Schubert 	struct iov_iter iter;
434c090c8abSBernd Schubert 	int err;
435c090c8abSBernd Schubert 	struct fuse_uring_ent_in_out ring_in_out;
436c090c8abSBernd Schubert 
437c090c8abSBernd Schubert 	err = copy_from_user(&ring_in_out, &ent->headers->ring_ent_in_out,
438c090c8abSBernd Schubert 			     sizeof(ring_in_out));
439c090c8abSBernd Schubert 	if (err)
440c090c8abSBernd Schubert 		return -EFAULT;
441c090c8abSBernd Schubert 
442c090c8abSBernd Schubert 	err = import_ubuf(ITER_SOURCE, ent->payload, ring->max_payload_sz,
443c090c8abSBernd Schubert 			  &iter);
444c090c8abSBernd Schubert 	if (err)
445c090c8abSBernd Schubert 		return err;
446c090c8abSBernd Schubert 
447c090c8abSBernd Schubert 	fuse_copy_init(&cs, 0, &iter);
448c090c8abSBernd Schubert 	cs.is_uring = 1;
449c090c8abSBernd Schubert 	cs.req = req;
450c090c8abSBernd Schubert 
451c090c8abSBernd Schubert 	return fuse_copy_out_args(&cs, args, ring_in_out.payload_sz);
452c090c8abSBernd Schubert }
453c090c8abSBernd Schubert 
454c090c8abSBernd Schubert  /*
455c090c8abSBernd Schubert   * Copy data from the req to the ring buffer
456c090c8abSBernd Schubert   */
457c090c8abSBernd Schubert static int fuse_uring_args_to_ring(struct fuse_ring *ring, struct fuse_req *req,
458c090c8abSBernd Schubert 				   struct fuse_ring_ent *ent)
459c090c8abSBernd Schubert {
460c090c8abSBernd Schubert 	struct fuse_copy_state cs;
461c090c8abSBernd Schubert 	struct fuse_args *args = req->args;
462c090c8abSBernd Schubert 	struct fuse_in_arg *in_args = args->in_args;
463c090c8abSBernd Schubert 	int num_args = args->in_numargs;
464c090c8abSBernd Schubert 	int err;
465c090c8abSBernd Schubert 	struct iov_iter iter;
466c090c8abSBernd Schubert 	struct fuse_uring_ent_in_out ent_in_out = {
467c090c8abSBernd Schubert 		.flags = 0,
468c090c8abSBernd Schubert 		.commit_id = req->in.h.unique,
469c090c8abSBernd Schubert 	};
470c090c8abSBernd Schubert 
471c090c8abSBernd Schubert 	err = import_ubuf(ITER_DEST, ent->payload, ring->max_payload_sz, &iter);
472c090c8abSBernd Schubert 	if (err) {
473c090c8abSBernd Schubert 		pr_info_ratelimited("fuse: Import of user buffer failed\n");
474c090c8abSBernd Schubert 		return err;
475c090c8abSBernd Schubert 	}
476c090c8abSBernd Schubert 
477c090c8abSBernd Schubert 	fuse_copy_init(&cs, 1, &iter);
478c090c8abSBernd Schubert 	cs.is_uring = 1;
479c090c8abSBernd Schubert 	cs.req = req;
480c090c8abSBernd Schubert 
481c090c8abSBernd Schubert 	if (num_args > 0) {
482c090c8abSBernd Schubert 		/*
483c090c8abSBernd Schubert 		 * Expectation is that the first argument is the per op header.
484c090c8abSBernd Schubert 		 * Some op code have that as zero size.
485c090c8abSBernd Schubert 		 */
486c090c8abSBernd Schubert 		if (args->in_args[0].size > 0) {
487c090c8abSBernd Schubert 			err = copy_to_user(&ent->headers->op_in, in_args->value,
488c090c8abSBernd Schubert 					   in_args->size);
489c090c8abSBernd Schubert 			if (err) {
490c090c8abSBernd Schubert 				pr_info_ratelimited(
491c090c8abSBernd Schubert 					"Copying the header failed.\n");
492c090c8abSBernd Schubert 				return -EFAULT;
493c090c8abSBernd Schubert 			}
494c090c8abSBernd Schubert 		}
495c090c8abSBernd Schubert 		in_args++;
496c090c8abSBernd Schubert 		num_args--;
497c090c8abSBernd Schubert 	}
498c090c8abSBernd Schubert 
499c090c8abSBernd Schubert 	/* copy the payload */
500c090c8abSBernd Schubert 	err = fuse_copy_args(&cs, num_args, args->in_pages,
501c090c8abSBernd Schubert 			     (struct fuse_arg *)in_args, 0);
502c090c8abSBernd Schubert 	if (err) {
503c090c8abSBernd Schubert 		pr_info_ratelimited("%s fuse_copy_args failed\n", __func__);
504c090c8abSBernd Schubert 		return err;
505c090c8abSBernd Schubert 	}
506c090c8abSBernd Schubert 
507c090c8abSBernd Schubert 	ent_in_out.payload_sz = cs.ring.copied_sz;
508c090c8abSBernd Schubert 	err = copy_to_user(&ent->headers->ring_ent_in_out, &ent_in_out,
509c090c8abSBernd Schubert 			   sizeof(ent_in_out));
510c090c8abSBernd Schubert 	return err ? -EFAULT : 0;
511c090c8abSBernd Schubert }
512c090c8abSBernd Schubert 
513c090c8abSBernd Schubert static int fuse_uring_copy_to_ring(struct fuse_ring_ent *ent,
514c090c8abSBernd Schubert 				   struct fuse_req *req)
515c090c8abSBernd Schubert {
516c090c8abSBernd Schubert 	struct fuse_ring_queue *queue = ent->queue;
517c090c8abSBernd Schubert 	struct fuse_ring *ring = queue->ring;
518c090c8abSBernd Schubert 	int err;
519c090c8abSBernd Schubert 
520c090c8abSBernd Schubert 	err = -EIO;
521c090c8abSBernd Schubert 	if (WARN_ON(ent->state != FRRS_FUSE_REQ)) {
522c090c8abSBernd Schubert 		pr_err("qid=%d ring-req=%p invalid state %d on send\n",
523c090c8abSBernd Schubert 		       queue->qid, ent, ent->state);
524c090c8abSBernd Schubert 		return err;
525c090c8abSBernd Schubert 	}
526c090c8abSBernd Schubert 
527c090c8abSBernd Schubert 	err = -EINVAL;
528c090c8abSBernd Schubert 	if (WARN_ON(req->in.h.unique == 0))
529c090c8abSBernd Schubert 		return err;
530c090c8abSBernd Schubert 
531c090c8abSBernd Schubert 	/* copy the request */
532c090c8abSBernd Schubert 	err = fuse_uring_args_to_ring(ring, req, ent);
533c090c8abSBernd Schubert 	if (unlikely(err)) {
534c090c8abSBernd Schubert 		pr_info_ratelimited("Copy to ring failed: %d\n", err);
535c090c8abSBernd Schubert 		return err;
536c090c8abSBernd Schubert 	}
537c090c8abSBernd Schubert 
538c090c8abSBernd Schubert 	/* copy fuse_in_header */
539c090c8abSBernd Schubert 	err = copy_to_user(&ent->headers->in_out, &req->in.h,
540c090c8abSBernd Schubert 			   sizeof(req->in.h));
541c090c8abSBernd Schubert 	if (err) {
542c090c8abSBernd Schubert 		err = -EFAULT;
543c090c8abSBernd Schubert 		return err;
544c090c8abSBernd Schubert 	}
545c090c8abSBernd Schubert 
546c090c8abSBernd Schubert 	return 0;
547c090c8abSBernd Schubert }
548c090c8abSBernd Schubert 
549c090c8abSBernd Schubert static int fuse_uring_prepare_send(struct fuse_ring_ent *ent,
550c090c8abSBernd Schubert 				   struct fuse_req *req)
551c090c8abSBernd Schubert {
552c090c8abSBernd Schubert 	int err;
553c090c8abSBernd Schubert 
554c090c8abSBernd Schubert 	err = fuse_uring_copy_to_ring(ent, req);
555c090c8abSBernd Schubert 	if (!err)
556c090c8abSBernd Schubert 		set_bit(FR_SENT, &req->flags);
557c090c8abSBernd Schubert 	else
558c090c8abSBernd Schubert 		fuse_uring_req_end(ent, req, err);
559c090c8abSBernd Schubert 
560c090c8abSBernd Schubert 	return err;
561c090c8abSBernd Schubert }
562c090c8abSBernd Schubert 
563c090c8abSBernd Schubert /*
564c090c8abSBernd Schubert  * Write data to the ring buffer and send the request to userspace,
565c090c8abSBernd Schubert  * userspace will read it
566c090c8abSBernd Schubert  * This is comparable with classical read(/dev/fuse)
567c090c8abSBernd Schubert  */
568c090c8abSBernd Schubert static int fuse_uring_send_next_to_ring(struct fuse_ring_ent *ent,
569c090c8abSBernd Schubert 					struct fuse_req *req,
570c090c8abSBernd Schubert 					unsigned int issue_flags)
571c090c8abSBernd Schubert {
572c090c8abSBernd Schubert 	struct fuse_ring_queue *queue = ent->queue;
573c090c8abSBernd Schubert 	int err;
574c090c8abSBernd Schubert 	struct io_uring_cmd *cmd;
575c090c8abSBernd Schubert 
576c090c8abSBernd Schubert 	err = fuse_uring_prepare_send(ent, req);
577c090c8abSBernd Schubert 	if (err)
578c090c8abSBernd Schubert 		return err;
579c090c8abSBernd Schubert 
580c090c8abSBernd Schubert 	spin_lock(&queue->lock);
581c090c8abSBernd Schubert 	cmd = ent->cmd;
582c090c8abSBernd Schubert 	ent->cmd = NULL;
583c090c8abSBernd Schubert 	ent->state = FRRS_USERSPACE;
584c090c8abSBernd Schubert 	list_move(&ent->list, &queue->ent_in_userspace);
585c090c8abSBernd Schubert 	spin_unlock(&queue->lock);
586c090c8abSBernd Schubert 
587c090c8abSBernd Schubert 	io_uring_cmd_done(cmd, 0, 0, issue_flags);
588c090c8abSBernd Schubert 	return 0;
589c090c8abSBernd Schubert }
590c090c8abSBernd Schubert 
591c090c8abSBernd Schubert /*
59224fe962cSBernd Schubert  * Make a ring entry available for fuse_req assignment
59324fe962cSBernd Schubert  */
59424fe962cSBernd Schubert static void fuse_uring_ent_avail(struct fuse_ring_ent *ent,
59524fe962cSBernd Schubert 				 struct fuse_ring_queue *queue)
59624fe962cSBernd Schubert {
59724fe962cSBernd Schubert 	WARN_ON_ONCE(!ent->cmd);
59824fe962cSBernd Schubert 	list_move(&ent->list, &queue->ent_avail_queue);
59924fe962cSBernd Schubert 	ent->state = FRRS_AVAILABLE;
60024fe962cSBernd Schubert }
60124fe962cSBernd Schubert 
602c090c8abSBernd Schubert /* Used to find the request on SQE commit */
603c090c8abSBernd Schubert static void fuse_uring_add_to_pq(struct fuse_ring_ent *ent,
604c090c8abSBernd Schubert 				 struct fuse_req *req)
605c090c8abSBernd Schubert {
606c090c8abSBernd Schubert 	struct fuse_ring_queue *queue = ent->queue;
607c090c8abSBernd Schubert 	struct fuse_pqueue *fpq = &queue->fpq;
608c090c8abSBernd Schubert 	unsigned int hash;
609c090c8abSBernd Schubert 
610c090c8abSBernd Schubert 	req->ring_entry = ent;
611c090c8abSBernd Schubert 	hash = fuse_req_hash(req->in.h.unique);
612c090c8abSBernd Schubert 	list_move_tail(&req->list, &fpq->processing[hash]);
613c090c8abSBernd Schubert }
614c090c8abSBernd Schubert 
615c090c8abSBernd Schubert /*
616c090c8abSBernd Schubert  * Assign a fuse queue entry to the given entry
617c090c8abSBernd Schubert  */
618c090c8abSBernd Schubert static void fuse_uring_add_req_to_ring_ent(struct fuse_ring_ent *ent,
619c090c8abSBernd Schubert 					   struct fuse_req *req)
620c090c8abSBernd Schubert {
621c090c8abSBernd Schubert 	struct fuse_ring_queue *queue = ent->queue;
622c090c8abSBernd Schubert 	struct fuse_conn *fc = req->fm->fc;
623c090c8abSBernd Schubert 	struct fuse_iqueue *fiq = &fc->iq;
624c090c8abSBernd Schubert 
625c090c8abSBernd Schubert 	lockdep_assert_held(&queue->lock);
626c090c8abSBernd Schubert 
627c090c8abSBernd Schubert 	if (WARN_ON_ONCE(ent->state != FRRS_AVAILABLE &&
628c090c8abSBernd Schubert 			 ent->state != FRRS_COMMIT)) {
629c090c8abSBernd Schubert 		pr_warn("%s qid=%d state=%d\n", __func__, ent->queue->qid,
630c090c8abSBernd Schubert 			ent->state);
631c090c8abSBernd Schubert 	}
632c090c8abSBernd Schubert 
633c090c8abSBernd Schubert 	spin_lock(&fiq->lock);
634c090c8abSBernd Schubert 	clear_bit(FR_PENDING, &req->flags);
635c090c8abSBernd Schubert 	spin_unlock(&fiq->lock);
636c090c8abSBernd Schubert 	ent->fuse_req = req;
637c090c8abSBernd Schubert 	ent->state = FRRS_FUSE_REQ;
638c090c8abSBernd Schubert 	list_move(&ent->list, &queue->ent_w_req_queue);
639c090c8abSBernd Schubert 	fuse_uring_add_to_pq(ent, req);
640c090c8abSBernd Schubert }
641c090c8abSBernd Schubert 
642c090c8abSBernd Schubert /* Fetch the next fuse request if available */
643c090c8abSBernd Schubert static struct fuse_req *fuse_uring_ent_assign_req(struct fuse_ring_ent *ent)
644c090c8abSBernd Schubert 	__must_hold(&queue->lock)
645c090c8abSBernd Schubert {
646c090c8abSBernd Schubert 	struct fuse_req *req;
647c090c8abSBernd Schubert 	struct fuse_ring_queue *queue = ent->queue;
648c090c8abSBernd Schubert 	struct list_head *req_queue = &queue->fuse_req_queue;
649c090c8abSBernd Schubert 
650c090c8abSBernd Schubert 	lockdep_assert_held(&queue->lock);
651c090c8abSBernd Schubert 
652c090c8abSBernd Schubert 	/* get and assign the next entry while it is still holding the lock */
653c090c8abSBernd Schubert 	req = list_first_entry_or_null(req_queue, struct fuse_req, list);
654c090c8abSBernd Schubert 	if (req)
655c090c8abSBernd Schubert 		fuse_uring_add_req_to_ring_ent(ent, req);
656c090c8abSBernd Schubert 
657c090c8abSBernd Schubert 	return req;
658c090c8abSBernd Schubert }
659c090c8abSBernd Schubert 
660c090c8abSBernd Schubert /*
661c090c8abSBernd Schubert  * Read data from the ring buffer, which user space has written to
662c090c8abSBernd Schubert  * This is comparible with handling of classical write(/dev/fuse).
663c090c8abSBernd Schubert  * Also make the ring request available again for new fuse requests.
664c090c8abSBernd Schubert  */
665c090c8abSBernd Schubert static void fuse_uring_commit(struct fuse_ring_ent *ent, struct fuse_req *req,
666c090c8abSBernd Schubert 			      unsigned int issue_flags)
667c090c8abSBernd Schubert {
668c090c8abSBernd Schubert 	struct fuse_ring *ring = ent->queue->ring;
669c090c8abSBernd Schubert 	struct fuse_conn *fc = ring->fc;
670c090c8abSBernd Schubert 	ssize_t err = 0;
671c090c8abSBernd Schubert 
672c090c8abSBernd Schubert 	err = copy_from_user(&req->out.h, &ent->headers->in_out,
673c090c8abSBernd Schubert 			     sizeof(req->out.h));
674c090c8abSBernd Schubert 	if (err) {
675c090c8abSBernd Schubert 		req->out.h.error = -EFAULT;
676c090c8abSBernd Schubert 		goto out;
677c090c8abSBernd Schubert 	}
678c090c8abSBernd Schubert 
679c090c8abSBernd Schubert 	err = fuse_uring_out_header_has_err(&req->out.h, req, fc);
680c090c8abSBernd Schubert 	if (err) {
681c090c8abSBernd Schubert 		/* req->out.h.error already set */
682c090c8abSBernd Schubert 		goto out;
683c090c8abSBernd Schubert 	}
684c090c8abSBernd Schubert 
685c090c8abSBernd Schubert 	err = fuse_uring_copy_from_ring(ring, req, ent);
686c090c8abSBernd Schubert out:
687c090c8abSBernd Schubert 	fuse_uring_req_end(ent, req, err);
688c090c8abSBernd Schubert }
689c090c8abSBernd Schubert 
690c090c8abSBernd Schubert /*
691c090c8abSBernd Schubert  * Get the next fuse req and send it
692c090c8abSBernd Schubert  */
693c090c8abSBernd Schubert static void fuse_uring_next_fuse_req(struct fuse_ring_ent *ent,
694c090c8abSBernd Schubert 				     struct fuse_ring_queue *queue,
695c090c8abSBernd Schubert 				     unsigned int issue_flags)
696c090c8abSBernd Schubert {
697c090c8abSBernd Schubert 	int err;
698c090c8abSBernd Schubert 	struct fuse_req *req;
699c090c8abSBernd Schubert 
700c090c8abSBernd Schubert retry:
701c090c8abSBernd Schubert 	spin_lock(&queue->lock);
702c090c8abSBernd Schubert 	fuse_uring_ent_avail(ent, queue);
703c090c8abSBernd Schubert 	req = fuse_uring_ent_assign_req(ent);
704c090c8abSBernd Schubert 	spin_unlock(&queue->lock);
705c090c8abSBernd Schubert 
706c090c8abSBernd Schubert 	if (req) {
707c090c8abSBernd Schubert 		err = fuse_uring_send_next_to_ring(ent, req, issue_flags);
708c090c8abSBernd Schubert 		if (err)
709c090c8abSBernd Schubert 			goto retry;
710c090c8abSBernd Schubert 	}
711c090c8abSBernd Schubert }
712c090c8abSBernd Schubert 
713c090c8abSBernd Schubert static int fuse_ring_ent_set_commit(struct fuse_ring_ent *ent)
714c090c8abSBernd Schubert {
715c090c8abSBernd Schubert 	struct fuse_ring_queue *queue = ent->queue;
716c090c8abSBernd Schubert 
717c090c8abSBernd Schubert 	lockdep_assert_held(&queue->lock);
718c090c8abSBernd Schubert 
719c090c8abSBernd Schubert 	if (WARN_ON_ONCE(ent->state != FRRS_USERSPACE))
720c090c8abSBernd Schubert 		return -EIO;
721c090c8abSBernd Schubert 
722c090c8abSBernd Schubert 	ent->state = FRRS_COMMIT;
723c090c8abSBernd Schubert 	list_move(&ent->list, &queue->ent_commit_queue);
724c090c8abSBernd Schubert 
725c090c8abSBernd Schubert 	return 0;
726c090c8abSBernd Schubert }
727c090c8abSBernd Schubert 
728c090c8abSBernd Schubert /* FUSE_URING_CMD_COMMIT_AND_FETCH handler */
729c090c8abSBernd Schubert static int fuse_uring_commit_fetch(struct io_uring_cmd *cmd, int issue_flags,
730c090c8abSBernd Schubert 				   struct fuse_conn *fc)
731c090c8abSBernd Schubert {
732c090c8abSBernd Schubert 	const struct fuse_uring_cmd_req *cmd_req = io_uring_sqe_cmd(cmd->sqe);
733c090c8abSBernd Schubert 	struct fuse_ring_ent *ent;
734c090c8abSBernd Schubert 	int err;
735c090c8abSBernd Schubert 	struct fuse_ring *ring = fc->ring;
736c090c8abSBernd Schubert 	struct fuse_ring_queue *queue;
737c090c8abSBernd Schubert 	uint64_t commit_id = READ_ONCE(cmd_req->commit_id);
738c090c8abSBernd Schubert 	unsigned int qid = READ_ONCE(cmd_req->qid);
739c090c8abSBernd Schubert 	struct fuse_pqueue *fpq;
740c090c8abSBernd Schubert 	struct fuse_req *req;
741c090c8abSBernd Schubert 
742c090c8abSBernd Schubert 	err = -ENOTCONN;
743c090c8abSBernd Schubert 	if (!ring)
744c090c8abSBernd Schubert 		return err;
745c090c8abSBernd Schubert 
746c090c8abSBernd Schubert 	if (qid >= ring->nr_queues)
747c090c8abSBernd Schubert 		return -EINVAL;
748c090c8abSBernd Schubert 
749c090c8abSBernd Schubert 	queue = ring->queues[qid];
750c090c8abSBernd Schubert 	if (!queue)
751c090c8abSBernd Schubert 		return err;
752c090c8abSBernd Schubert 	fpq = &queue->fpq;
753c090c8abSBernd Schubert 
7544a9bfb9bSBernd Schubert 	if (!READ_ONCE(fc->connected) || READ_ONCE(queue->stopped))
7554a9bfb9bSBernd Schubert 		return err;
7564a9bfb9bSBernd Schubert 
757c090c8abSBernd Schubert 	spin_lock(&queue->lock);
758c090c8abSBernd Schubert 	/* Find a request based on the unique ID of the fuse request
759c090c8abSBernd Schubert 	 * This should get revised, as it needs a hash calculation and list
760c090c8abSBernd Schubert 	 * search. And full struct fuse_pqueue is needed (memory overhead).
761c090c8abSBernd Schubert 	 * As well as the link from req to ring_ent.
762c090c8abSBernd Schubert 	 */
763c090c8abSBernd Schubert 	req = fuse_request_find(fpq, commit_id);
764c090c8abSBernd Schubert 	err = -ENOENT;
765c090c8abSBernd Schubert 	if (!req) {
766c090c8abSBernd Schubert 		pr_info("qid=%d commit_id %llu not found\n", queue->qid,
767c090c8abSBernd Schubert 			commit_id);
768c090c8abSBernd Schubert 		spin_unlock(&queue->lock);
769c090c8abSBernd Schubert 		return err;
770c090c8abSBernd Schubert 	}
771c090c8abSBernd Schubert 	list_del_init(&req->list);
772c090c8abSBernd Schubert 	ent = req->ring_entry;
773c090c8abSBernd Schubert 	req->ring_entry = NULL;
774c090c8abSBernd Schubert 
775c090c8abSBernd Schubert 	err = fuse_ring_ent_set_commit(ent);
776c090c8abSBernd Schubert 	if (err != 0) {
777c090c8abSBernd Schubert 		pr_info_ratelimited("qid=%d commit_id %llu state %d",
778c090c8abSBernd Schubert 				    queue->qid, commit_id, ent->state);
779c090c8abSBernd Schubert 		spin_unlock(&queue->lock);
780c090c8abSBernd Schubert 		req->out.h.error = err;
781c090c8abSBernd Schubert 		clear_bit(FR_SENT, &req->flags);
782c090c8abSBernd Schubert 		fuse_request_end(req);
783c090c8abSBernd Schubert 		return err;
784c090c8abSBernd Schubert 	}
785c090c8abSBernd Schubert 
786c090c8abSBernd Schubert 	ent->cmd = cmd;
787c090c8abSBernd Schubert 	spin_unlock(&queue->lock);
788c090c8abSBernd Schubert 
789c090c8abSBernd Schubert 	/* without the queue lock, as other locks are taken */
790c090c8abSBernd Schubert 	fuse_uring_commit(ent, req, issue_flags);
791c090c8abSBernd Schubert 
792c090c8abSBernd Schubert 	/*
793c090c8abSBernd Schubert 	 * Fetching the next request is absolutely required as queued
794c090c8abSBernd Schubert 	 * fuse requests would otherwise not get processed - committing
795c090c8abSBernd Schubert 	 * and fetching is done in one step vs legacy fuse, which has separated
796c090c8abSBernd Schubert 	 * read (fetch request) and write (commit result).
797c090c8abSBernd Schubert 	 */
798c090c8abSBernd Schubert 	fuse_uring_next_fuse_req(ent, queue, issue_flags);
799c090c8abSBernd Schubert 	return 0;
800c090c8abSBernd Schubert }
801c090c8abSBernd Schubert 
802*c2c9af9aSBernd Schubert static bool is_ring_ready(struct fuse_ring *ring, int current_qid)
803*c2c9af9aSBernd Schubert {
804*c2c9af9aSBernd Schubert 	int qid;
805*c2c9af9aSBernd Schubert 	struct fuse_ring_queue *queue;
806*c2c9af9aSBernd Schubert 	bool ready = true;
807*c2c9af9aSBernd Schubert 
808*c2c9af9aSBernd Schubert 	for (qid = 0; qid < ring->nr_queues && ready; qid++) {
809*c2c9af9aSBernd Schubert 		if (current_qid == qid)
810*c2c9af9aSBernd Schubert 			continue;
811*c2c9af9aSBernd Schubert 
812*c2c9af9aSBernd Schubert 		queue = ring->queues[qid];
813*c2c9af9aSBernd Schubert 		if (!queue) {
814*c2c9af9aSBernd Schubert 			ready = false;
815*c2c9af9aSBernd Schubert 			break;
816*c2c9af9aSBernd Schubert 		}
817*c2c9af9aSBernd Schubert 
818*c2c9af9aSBernd Schubert 		spin_lock(&queue->lock);
819*c2c9af9aSBernd Schubert 		if (list_empty(&queue->ent_avail_queue))
820*c2c9af9aSBernd Schubert 			ready = false;
821*c2c9af9aSBernd Schubert 		spin_unlock(&queue->lock);
822*c2c9af9aSBernd Schubert 	}
823*c2c9af9aSBernd Schubert 
824*c2c9af9aSBernd Schubert 	return ready;
825*c2c9af9aSBernd Schubert }
826*c2c9af9aSBernd Schubert 
82724fe962cSBernd Schubert /*
82824fe962cSBernd Schubert  * fuse_uring_req_fetch command handling
82924fe962cSBernd Schubert  */
83024fe962cSBernd Schubert static void fuse_uring_do_register(struct fuse_ring_ent *ent,
83124fe962cSBernd Schubert 				   struct io_uring_cmd *cmd,
83224fe962cSBernd Schubert 				   unsigned int issue_flags)
83324fe962cSBernd Schubert {
83424fe962cSBernd Schubert 	struct fuse_ring_queue *queue = ent->queue;
835*c2c9af9aSBernd Schubert 	struct fuse_ring *ring = queue->ring;
836*c2c9af9aSBernd Schubert 	struct fuse_conn *fc = ring->fc;
837*c2c9af9aSBernd Schubert 	struct fuse_iqueue *fiq = &fc->iq;
83824fe962cSBernd Schubert 
83924fe962cSBernd Schubert 	spin_lock(&queue->lock);
84024fe962cSBernd Schubert 	ent->cmd = cmd;
84124fe962cSBernd Schubert 	fuse_uring_ent_avail(ent, queue);
84224fe962cSBernd Schubert 	spin_unlock(&queue->lock);
843*c2c9af9aSBernd Schubert 
844*c2c9af9aSBernd Schubert 	if (!ring->ready) {
845*c2c9af9aSBernd Schubert 		bool ready = is_ring_ready(ring, queue->qid);
846*c2c9af9aSBernd Schubert 
847*c2c9af9aSBernd Schubert 		if (ready) {
848*c2c9af9aSBernd Schubert 			WRITE_ONCE(fiq->ops, &fuse_io_uring_ops);
849*c2c9af9aSBernd Schubert 			WRITE_ONCE(ring->ready, true);
850*c2c9af9aSBernd Schubert 		}
851*c2c9af9aSBernd Schubert 	}
85224fe962cSBernd Schubert }
85324fe962cSBernd Schubert 
85424fe962cSBernd Schubert /*
85524fe962cSBernd Schubert  * sqe->addr is a ptr to an iovec array, iov[0] has the headers, iov[1]
85624fe962cSBernd Schubert  * the payload
85724fe962cSBernd Schubert  */
85824fe962cSBernd Schubert static int fuse_uring_get_iovec_from_sqe(const struct io_uring_sqe *sqe,
85924fe962cSBernd Schubert 					 struct iovec iov[FUSE_URING_IOV_SEGS])
86024fe962cSBernd Schubert {
86124fe962cSBernd Schubert 	struct iovec __user *uiov = u64_to_user_ptr(READ_ONCE(sqe->addr));
86224fe962cSBernd Schubert 	struct iov_iter iter;
86324fe962cSBernd Schubert 	ssize_t ret;
86424fe962cSBernd Schubert 
86524fe962cSBernd Schubert 	if (sqe->len != FUSE_URING_IOV_SEGS)
86624fe962cSBernd Schubert 		return -EINVAL;
86724fe962cSBernd Schubert 
86824fe962cSBernd Schubert 	/*
86924fe962cSBernd Schubert 	 * Direction for buffer access will actually be READ and WRITE,
87024fe962cSBernd Schubert 	 * using write for the import should include READ access as well.
87124fe962cSBernd Schubert 	 */
87224fe962cSBernd Schubert 	ret = import_iovec(WRITE, uiov, FUSE_URING_IOV_SEGS,
87324fe962cSBernd Schubert 			   FUSE_URING_IOV_SEGS, &iov, &iter);
87424fe962cSBernd Schubert 	if (ret < 0)
87524fe962cSBernd Schubert 		return ret;
87624fe962cSBernd Schubert 
87724fe962cSBernd Schubert 	return 0;
87824fe962cSBernd Schubert }
87924fe962cSBernd Schubert 
88024fe962cSBernd Schubert static struct fuse_ring_ent *
88124fe962cSBernd Schubert fuse_uring_create_ring_ent(struct io_uring_cmd *cmd,
88224fe962cSBernd Schubert 			   struct fuse_ring_queue *queue)
88324fe962cSBernd Schubert {
88424fe962cSBernd Schubert 	struct fuse_ring *ring = queue->ring;
88524fe962cSBernd Schubert 	struct fuse_ring_ent *ent;
88624fe962cSBernd Schubert 	size_t payload_size;
88724fe962cSBernd Schubert 	struct iovec iov[FUSE_URING_IOV_SEGS];
88824fe962cSBernd Schubert 	int err;
88924fe962cSBernd Schubert 
89024fe962cSBernd Schubert 	err = fuse_uring_get_iovec_from_sqe(cmd->sqe, iov);
89124fe962cSBernd Schubert 	if (err) {
89224fe962cSBernd Schubert 		pr_info_ratelimited("Failed to get iovec from sqe, err=%d\n",
89324fe962cSBernd Schubert 				    err);
89424fe962cSBernd Schubert 		return ERR_PTR(err);
89524fe962cSBernd Schubert 	}
89624fe962cSBernd Schubert 
89724fe962cSBernd Schubert 	err = -EINVAL;
89824fe962cSBernd Schubert 	if (iov[0].iov_len < sizeof(struct fuse_uring_req_header)) {
89924fe962cSBernd Schubert 		pr_info_ratelimited("Invalid header len %zu\n", iov[0].iov_len);
90024fe962cSBernd Schubert 		return ERR_PTR(err);
90124fe962cSBernd Schubert 	}
90224fe962cSBernd Schubert 
90324fe962cSBernd Schubert 	payload_size = iov[1].iov_len;
90424fe962cSBernd Schubert 	if (payload_size < ring->max_payload_sz) {
90524fe962cSBernd Schubert 		pr_info_ratelimited("Invalid req payload len %zu\n",
90624fe962cSBernd Schubert 				    payload_size);
90724fe962cSBernd Schubert 		return ERR_PTR(err);
90824fe962cSBernd Schubert 	}
90924fe962cSBernd Schubert 
91024fe962cSBernd Schubert 	err = -ENOMEM;
91124fe962cSBernd Schubert 	ent = kzalloc(sizeof(*ent), GFP_KERNEL_ACCOUNT);
91224fe962cSBernd Schubert 	if (!ent)
91324fe962cSBernd Schubert 		return ERR_PTR(err);
91424fe962cSBernd Schubert 
91524fe962cSBernd Schubert 	INIT_LIST_HEAD(&ent->list);
91624fe962cSBernd Schubert 
91724fe962cSBernd Schubert 	ent->queue = queue;
91824fe962cSBernd Schubert 	ent->headers = iov[0].iov_base;
91924fe962cSBernd Schubert 	ent->payload = iov[1].iov_base;
92024fe962cSBernd Schubert 
9214a9bfb9bSBernd Schubert 	atomic_inc(&ring->queue_refs);
92224fe962cSBernd Schubert 	return ent;
92324fe962cSBernd Schubert }
92424fe962cSBernd Schubert 
92524fe962cSBernd Schubert /*
92624fe962cSBernd Schubert  * Register header and payload buffer with the kernel and puts the
92724fe962cSBernd Schubert  * entry as "ready to get fuse requests" on the queue
92824fe962cSBernd Schubert  */
92924fe962cSBernd Schubert static int fuse_uring_register(struct io_uring_cmd *cmd,
93024fe962cSBernd Schubert 			       unsigned int issue_flags, struct fuse_conn *fc)
93124fe962cSBernd Schubert {
93224fe962cSBernd Schubert 	const struct fuse_uring_cmd_req *cmd_req = io_uring_sqe_cmd(cmd->sqe);
93324fe962cSBernd Schubert 	struct fuse_ring *ring = fc->ring;
93424fe962cSBernd Schubert 	struct fuse_ring_queue *queue;
93524fe962cSBernd Schubert 	struct fuse_ring_ent *ent;
93624fe962cSBernd Schubert 	int err;
93724fe962cSBernd Schubert 	unsigned int qid = READ_ONCE(cmd_req->qid);
93824fe962cSBernd Schubert 
93924fe962cSBernd Schubert 	err = -ENOMEM;
94024fe962cSBernd Schubert 	if (!ring) {
94124fe962cSBernd Schubert 		ring = fuse_uring_create(fc);
94224fe962cSBernd Schubert 		if (!ring)
94324fe962cSBernd Schubert 			return err;
94424fe962cSBernd Schubert 	}
94524fe962cSBernd Schubert 
94624fe962cSBernd Schubert 	if (qid >= ring->nr_queues) {
94724fe962cSBernd Schubert 		pr_info_ratelimited("fuse: Invalid ring qid %u\n", qid);
94824fe962cSBernd Schubert 		return -EINVAL;
94924fe962cSBernd Schubert 	}
95024fe962cSBernd Schubert 
95124fe962cSBernd Schubert 	queue = ring->queues[qid];
95224fe962cSBernd Schubert 	if (!queue) {
95324fe962cSBernd Schubert 		queue = fuse_uring_create_queue(ring, qid);
95424fe962cSBernd Schubert 		if (!queue)
95524fe962cSBernd Schubert 			return err;
95624fe962cSBernd Schubert 	}
95724fe962cSBernd Schubert 
95824fe962cSBernd Schubert 	/*
95924fe962cSBernd Schubert 	 * The created queue above does not need to be destructed in
96024fe962cSBernd Schubert 	 * case of entry errors below, will be done at ring destruction time.
96124fe962cSBernd Schubert 	 */
96224fe962cSBernd Schubert 
96324fe962cSBernd Schubert 	ent = fuse_uring_create_ring_ent(cmd, queue);
96424fe962cSBernd Schubert 	if (IS_ERR(ent))
96524fe962cSBernd Schubert 		return PTR_ERR(ent);
96624fe962cSBernd Schubert 
96724fe962cSBernd Schubert 	fuse_uring_do_register(ent, cmd, issue_flags);
96824fe962cSBernd Schubert 
96924fe962cSBernd Schubert 	return 0;
97024fe962cSBernd Schubert }
97124fe962cSBernd Schubert 
97224fe962cSBernd Schubert /*
97324fe962cSBernd Schubert  * Entry function from io_uring to handle the given passthrough command
97424fe962cSBernd Schubert  * (op code IORING_OP_URING_CMD)
97524fe962cSBernd Schubert  */
97624fe962cSBernd Schubert int __maybe_unused fuse_uring_cmd(struct io_uring_cmd *cmd,
97724fe962cSBernd Schubert 				  unsigned int issue_flags)
97824fe962cSBernd Schubert {
97924fe962cSBernd Schubert 	struct fuse_dev *fud;
98024fe962cSBernd Schubert 	struct fuse_conn *fc;
98124fe962cSBernd Schubert 	u32 cmd_op = cmd->cmd_op;
98224fe962cSBernd Schubert 	int err;
98324fe962cSBernd Schubert 
98424fe962cSBernd Schubert 	if (!enable_uring) {
98524fe962cSBernd Schubert 		pr_info_ratelimited("fuse-io-uring is disabled\n");
98624fe962cSBernd Schubert 		return -EOPNOTSUPP;
98724fe962cSBernd Schubert 	}
98824fe962cSBernd Schubert 
98924fe962cSBernd Schubert 	/* This extra SQE size holds struct fuse_uring_cmd_req */
99024fe962cSBernd Schubert 	if (!(issue_flags & IO_URING_F_SQE128))
99124fe962cSBernd Schubert 		return -EINVAL;
99224fe962cSBernd Schubert 
99324fe962cSBernd Schubert 	fud = fuse_get_dev(cmd->file);
99424fe962cSBernd Schubert 	if (!fud) {
99524fe962cSBernd Schubert 		pr_info_ratelimited("No fuse device found\n");
99624fe962cSBernd Schubert 		return -ENOTCONN;
99724fe962cSBernd Schubert 	}
99824fe962cSBernd Schubert 	fc = fud->fc;
99924fe962cSBernd Schubert 
100024fe962cSBernd Schubert 	if (fc->aborted)
100124fe962cSBernd Schubert 		return -ECONNABORTED;
100224fe962cSBernd Schubert 	if (!fc->connected)
100324fe962cSBernd Schubert 		return -ENOTCONN;
100424fe962cSBernd Schubert 
100524fe962cSBernd Schubert 	/*
100624fe962cSBernd Schubert 	 * fuse_uring_register() needs the ring to be initialized,
100724fe962cSBernd Schubert 	 * we need to know the max payload size
100824fe962cSBernd Schubert 	 */
100924fe962cSBernd Schubert 	if (!fc->initialized)
101024fe962cSBernd Schubert 		return -EAGAIN;
101124fe962cSBernd Schubert 
101224fe962cSBernd Schubert 	switch (cmd_op) {
101324fe962cSBernd Schubert 	case FUSE_IO_URING_CMD_REGISTER:
101424fe962cSBernd Schubert 		err = fuse_uring_register(cmd, issue_flags, fc);
101524fe962cSBernd Schubert 		if (err) {
101624fe962cSBernd Schubert 			pr_info_once("FUSE_IO_URING_CMD_REGISTER failed err=%d\n",
101724fe962cSBernd Schubert 				     err);
101824fe962cSBernd Schubert 			return err;
101924fe962cSBernd Schubert 		}
102024fe962cSBernd Schubert 		break;
1021c090c8abSBernd Schubert 	case FUSE_IO_URING_CMD_COMMIT_AND_FETCH:
1022c090c8abSBernd Schubert 		err = fuse_uring_commit_fetch(cmd, issue_flags, fc);
1023c090c8abSBernd Schubert 		if (err) {
1024c090c8abSBernd Schubert 			pr_info_once("FUSE_IO_URING_COMMIT_AND_FETCH failed err=%d\n",
1025c090c8abSBernd Schubert 				     err);
1026c090c8abSBernd Schubert 			return err;
1027c090c8abSBernd Schubert 		}
1028c090c8abSBernd Schubert 		break;
102924fe962cSBernd Schubert 	default:
103024fe962cSBernd Schubert 		return -EINVAL;
103124fe962cSBernd Schubert 	}
103224fe962cSBernd Schubert 
103324fe962cSBernd Schubert 	return -EIOCBQUEUED;
103424fe962cSBernd Schubert }
1035*c2c9af9aSBernd Schubert 
1036*c2c9af9aSBernd Schubert static void fuse_uring_send(struct fuse_ring_ent *ent, struct io_uring_cmd *cmd,
1037*c2c9af9aSBernd Schubert 			    ssize_t ret, unsigned int issue_flags)
1038*c2c9af9aSBernd Schubert {
1039*c2c9af9aSBernd Schubert 	struct fuse_ring_queue *queue = ent->queue;
1040*c2c9af9aSBernd Schubert 
1041*c2c9af9aSBernd Schubert 	spin_lock(&queue->lock);
1042*c2c9af9aSBernd Schubert 	ent->state = FRRS_USERSPACE;
1043*c2c9af9aSBernd Schubert 	list_move(&ent->list, &queue->ent_in_userspace);
1044*c2c9af9aSBernd Schubert 	ent->cmd = NULL;
1045*c2c9af9aSBernd Schubert 	spin_unlock(&queue->lock);
1046*c2c9af9aSBernd Schubert 
1047*c2c9af9aSBernd Schubert 	io_uring_cmd_done(cmd, ret, 0, issue_flags);
1048*c2c9af9aSBernd Schubert }
1049*c2c9af9aSBernd Schubert 
1050*c2c9af9aSBernd Schubert /*
1051*c2c9af9aSBernd Schubert  * This prepares and sends the ring request in fuse-uring task context.
1052*c2c9af9aSBernd Schubert  * User buffers are not mapped yet - the application does not have permission
1053*c2c9af9aSBernd Schubert  * to write to it - this has to be executed in ring task context.
1054*c2c9af9aSBernd Schubert  */
1055*c2c9af9aSBernd Schubert static void fuse_uring_send_in_task(struct io_uring_cmd *cmd,
1056*c2c9af9aSBernd Schubert 				    unsigned int issue_flags)
1057*c2c9af9aSBernd Schubert {
1058*c2c9af9aSBernd Schubert 	struct fuse_ring_ent *ent = uring_cmd_to_ring_ent(cmd);
1059*c2c9af9aSBernd Schubert 	struct fuse_ring_queue *queue = ent->queue;
1060*c2c9af9aSBernd Schubert 	int err;
1061*c2c9af9aSBernd Schubert 
1062*c2c9af9aSBernd Schubert 	if (!(issue_flags & IO_URING_F_TASK_DEAD)) {
1063*c2c9af9aSBernd Schubert 		err = fuse_uring_prepare_send(ent, ent->fuse_req);
1064*c2c9af9aSBernd Schubert 		if (err) {
1065*c2c9af9aSBernd Schubert 			fuse_uring_next_fuse_req(ent, queue, issue_flags);
1066*c2c9af9aSBernd Schubert 			return;
1067*c2c9af9aSBernd Schubert 		}
1068*c2c9af9aSBernd Schubert 	} else {
1069*c2c9af9aSBernd Schubert 		err = -ECANCELED;
1070*c2c9af9aSBernd Schubert 	}
1071*c2c9af9aSBernd Schubert 
1072*c2c9af9aSBernd Schubert 	fuse_uring_send(ent, cmd, err, issue_flags);
1073*c2c9af9aSBernd Schubert }
1074*c2c9af9aSBernd Schubert 
1075*c2c9af9aSBernd Schubert static struct fuse_ring_queue *fuse_uring_task_to_queue(struct fuse_ring *ring)
1076*c2c9af9aSBernd Schubert {
1077*c2c9af9aSBernd Schubert 	unsigned int qid;
1078*c2c9af9aSBernd Schubert 	struct fuse_ring_queue *queue;
1079*c2c9af9aSBernd Schubert 
1080*c2c9af9aSBernd Schubert 	qid = task_cpu(current);
1081*c2c9af9aSBernd Schubert 
1082*c2c9af9aSBernd Schubert 	if (WARN_ONCE(qid >= ring->nr_queues,
1083*c2c9af9aSBernd Schubert 		      "Core number (%u) exceeds nr queues (%zu)\n", qid,
1084*c2c9af9aSBernd Schubert 		      ring->nr_queues))
1085*c2c9af9aSBernd Schubert 		qid = 0;
1086*c2c9af9aSBernd Schubert 
1087*c2c9af9aSBernd Schubert 	queue = ring->queues[qid];
1088*c2c9af9aSBernd Schubert 	WARN_ONCE(!queue, "Missing queue for qid %d\n", qid);
1089*c2c9af9aSBernd Schubert 
1090*c2c9af9aSBernd Schubert 	return queue;
1091*c2c9af9aSBernd Schubert }
1092*c2c9af9aSBernd Schubert 
1093*c2c9af9aSBernd Schubert static void fuse_uring_dispatch_ent(struct fuse_ring_ent *ent)
1094*c2c9af9aSBernd Schubert {
1095*c2c9af9aSBernd Schubert 	struct io_uring_cmd *cmd = ent->cmd;
1096*c2c9af9aSBernd Schubert 
1097*c2c9af9aSBernd Schubert 	uring_cmd_set_ring_ent(cmd, ent);
1098*c2c9af9aSBernd Schubert 	io_uring_cmd_complete_in_task(cmd, fuse_uring_send_in_task);
1099*c2c9af9aSBernd Schubert }
1100*c2c9af9aSBernd Schubert 
1101*c2c9af9aSBernd Schubert /* queue a fuse request and send it if a ring entry is available */
1102*c2c9af9aSBernd Schubert void fuse_uring_queue_fuse_req(struct fuse_iqueue *fiq, struct fuse_req *req)
1103*c2c9af9aSBernd Schubert {
1104*c2c9af9aSBernd Schubert 	struct fuse_conn *fc = req->fm->fc;
1105*c2c9af9aSBernd Schubert 	struct fuse_ring *ring = fc->ring;
1106*c2c9af9aSBernd Schubert 	struct fuse_ring_queue *queue;
1107*c2c9af9aSBernd Schubert 	struct fuse_ring_ent *ent = NULL;
1108*c2c9af9aSBernd Schubert 	int err;
1109*c2c9af9aSBernd Schubert 
1110*c2c9af9aSBernd Schubert 	err = -EINVAL;
1111*c2c9af9aSBernd Schubert 	queue = fuse_uring_task_to_queue(ring);
1112*c2c9af9aSBernd Schubert 	if (!queue)
1113*c2c9af9aSBernd Schubert 		goto err;
1114*c2c9af9aSBernd Schubert 
1115*c2c9af9aSBernd Schubert 	if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
1116*c2c9af9aSBernd Schubert 		req->in.h.unique = fuse_get_unique(fiq);
1117*c2c9af9aSBernd Schubert 
1118*c2c9af9aSBernd Schubert 	spin_lock(&queue->lock);
1119*c2c9af9aSBernd Schubert 	err = -ENOTCONN;
1120*c2c9af9aSBernd Schubert 	if (unlikely(queue->stopped))
1121*c2c9af9aSBernd Schubert 		goto err_unlock;
1122*c2c9af9aSBernd Schubert 
1123*c2c9af9aSBernd Schubert 	ent = list_first_entry_or_null(&queue->ent_avail_queue,
1124*c2c9af9aSBernd Schubert 				       struct fuse_ring_ent, list);
1125*c2c9af9aSBernd Schubert 	if (ent)
1126*c2c9af9aSBernd Schubert 		fuse_uring_add_req_to_ring_ent(ent, req);
1127*c2c9af9aSBernd Schubert 	else
1128*c2c9af9aSBernd Schubert 		list_add_tail(&req->list, &queue->fuse_req_queue);
1129*c2c9af9aSBernd Schubert 	spin_unlock(&queue->lock);
1130*c2c9af9aSBernd Schubert 
1131*c2c9af9aSBernd Schubert 	if (ent)
1132*c2c9af9aSBernd Schubert 		fuse_uring_dispatch_ent(ent);
1133*c2c9af9aSBernd Schubert 
1134*c2c9af9aSBernd Schubert 	return;
1135*c2c9af9aSBernd Schubert 
1136*c2c9af9aSBernd Schubert err_unlock:
1137*c2c9af9aSBernd Schubert 	spin_unlock(&queue->lock);
1138*c2c9af9aSBernd Schubert err:
1139*c2c9af9aSBernd Schubert 	req->out.h.error = err;
1140*c2c9af9aSBernd Schubert 	clear_bit(FR_PENDING, &req->flags);
1141*c2c9af9aSBernd Schubert 	fuse_request_end(req);
1142*c2c9af9aSBernd Schubert }
1143*c2c9af9aSBernd Schubert 
1144*c2c9af9aSBernd Schubert static const struct fuse_iqueue_ops fuse_io_uring_ops = {
1145*c2c9af9aSBernd Schubert 	/* should be send over io-uring as enhancement */
1146*c2c9af9aSBernd Schubert 	.send_forget = fuse_dev_queue_forget,
1147*c2c9af9aSBernd Schubert 
1148*c2c9af9aSBernd Schubert 	/*
1149*c2c9af9aSBernd Schubert 	 * could be send over io-uring, but interrupts should be rare,
1150*c2c9af9aSBernd Schubert 	 * no need to make the code complex
1151*c2c9af9aSBernd Schubert 	 */
1152*c2c9af9aSBernd Schubert 	.send_interrupt = fuse_dev_queue_interrupt,
1153*c2c9af9aSBernd Schubert 	.send_req = fuse_uring_queue_fuse_req,
1154*c2c9af9aSBernd Schubert };
1155