Files
cubelinux-kernel/fs/fuse/dev_uring_i.h
Greg Kroah-Hartman 598cf27219 Linux 6.19.3
Link: https://lore.kernel.org/r/20260217200002.683975158@linuxfoundation.org
Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
Tested-by: Takeshi Ogasawara <takeshi.ogasawara@futuring-girl.com>
Tested-by: Peter Schneider <pschneider1968@googlemail.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Tested-by: Salvatore Bonaccorso <carnil@debian.org>
Tested-by: Brett A C Sheffield <bacs@librecast.net>
Tested-by: Mark Brown <broonie@kernel.org>
Tested-by: Luna Jernberg <droidbittin@gmail.com>
Tested-by: Ronald Warsow <rwarsow@gmx.de>
Tested-by: Justin M. Forbes <jforbes@fedoraproject.org>
Tested-by: Ron Economos <re@w6rz.net>
Tested-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2026-02-19 16:33:27 +01:00

212 lines
4.4 KiB
C

/* SPDX-License-Identifier: GPL-2.0
*
* FUSE: Filesystem in Userspace
* Copyright (c) 2023-2024 DataDirect Networks.
*/
#ifndef _FS_FUSE_DEV_URING_I_H
#define _FS_FUSE_DEV_URING_I_H
#include "fuse_i.h"
#ifdef CONFIG_FUSE_IO_URING
#define FUSE_URING_TEARDOWN_TIMEOUT (5 * HZ)
#define FUSE_URING_TEARDOWN_INTERVAL (HZ/20)
enum fuse_ring_req_state {
FRRS_INVALID = 0,
/* The ring entry received from userspace and it is being processed */
FRRS_COMMIT,
/* The ring entry is waiting for new fuse requests */
FRRS_AVAILABLE,
/* The ring entry got assigned a fuse req */
FRRS_FUSE_REQ,
/* The ring entry is in or on the way to user space */
FRRS_USERSPACE,
/* The ring entry is in teardown */
FRRS_TEARDOWN,
/* The ring entry is released, but not freed yet */
FRRS_RELEASED,
};
/** A fuse ring entry, part of the ring queue */
struct fuse_ring_ent {
/* userspace buffer */
struct fuse_uring_req_header __user *headers;
void __user *payload;
/* the ring queue that owns the request */
struct fuse_ring_queue *queue;
/* fields below are protected by queue->lock */
struct io_uring_cmd *cmd;
struct list_head list;
enum fuse_ring_req_state state;
struct fuse_req *fuse_req;
};
struct fuse_ring_queue {
/*
* back pointer to the main fuse uring structure that holds this
* queue
*/
struct fuse_ring *ring;
/* queue id, corresponds to the cpu core */
unsigned int qid;
/*
* queue lock, taken when any value in the queue changes _and_ also
* a ring entry state changes.
*/
spinlock_t lock;
/* available ring entries (struct fuse_ring_ent) */
struct list_head ent_avail_queue;
/*
* entries in the process of being committed or in the process
* to be sent to userspace
*/
struct list_head ent_w_req_queue;
struct list_head ent_commit_queue;
/* entries in userspace */
struct list_head ent_in_userspace;
/* entries that are released */
struct list_head ent_released;
/* fuse requests waiting for an entry slot */
struct list_head fuse_req_queue;
/* background fuse requests */
struct list_head fuse_req_bg_queue;
struct fuse_pqueue fpq;
unsigned int active_background;
bool stopped;
};
/**
* Describes if uring is for communication and holds alls the data needed
* for uring communication
*/
struct fuse_ring {
/* back pointer */
struct fuse_conn *fc;
/* number of ring queues */
size_t nr_queues;
/* maximum payload/arg size */
size_t max_payload_sz;
struct fuse_ring_queue **queues;
/*
* Log ring entry states on stop when entries cannot be released
*/
unsigned int stop_debug_log : 1;
wait_queue_head_t stop_waitq;
/* async tear down */
struct delayed_work async_teardown_work;
/* log */
unsigned long teardown_time;
atomic_t queue_refs;
bool ready;
};
bool fuse_uring_enabled(void);
void fuse_uring_destruct(struct fuse_conn *fc);
void fuse_uring_stop_queues(struct fuse_ring *ring);
void fuse_uring_abort_end_requests(struct fuse_ring *ring);
int fuse_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags);
void fuse_uring_queue_fuse_req(struct fuse_iqueue *fiq, struct fuse_req *req);
bool fuse_uring_queue_bq_req(struct fuse_req *req);
bool fuse_uring_remove_pending_req(struct fuse_req *req);
bool fuse_uring_request_expired(struct fuse_conn *fc);
static inline void fuse_uring_abort(struct fuse_conn *fc)
{
struct fuse_ring *ring = fc->ring;
if (ring == NULL)
return;
if (atomic_read(&ring->queue_refs) > 0) {
fuse_uring_abort_end_requests(ring);
fuse_uring_stop_queues(ring);
}
}
static inline void fuse_uring_wait_stopped_queues(struct fuse_conn *fc)
{
struct fuse_ring *ring = fc->ring;
if (ring)
wait_event(ring->stop_waitq,
atomic_read(&ring->queue_refs) == 0);
}
static inline bool fuse_uring_ready(struct fuse_conn *fc)
{
return fc->ring && fc->ring->ready;
}
#else /* CONFIG_FUSE_IO_URING */
static inline void fuse_uring_destruct(struct fuse_conn *fc)
{
}
static inline bool fuse_uring_enabled(void)
{
return false;
}
static inline void fuse_uring_abort(struct fuse_conn *fc)
{
}
static inline void fuse_uring_wait_stopped_queues(struct fuse_conn *fc)
{
}
static inline bool fuse_uring_ready(struct fuse_conn *fc)
{
return false;
}
static inline bool fuse_uring_remove_pending_req(struct fuse_req *req)
{
return false;
}
static inline bool fuse_uring_request_expired(struct fuse_conn *fc)
{
return false;
}
#endif /* CONFIG_FUSE_IO_URING */
#endif /* _FS_FUSE_DEV_URING_I_H */