From: Miklos Szeredi Date: Tue, 17 Mar 2026 13:48:33 +0000 (+0100) Subject: fuse: move request blocking related members to fuse_chan X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=599ad4427bbc901eadd4f2872071eef87830959d;p=thirdparty%2Fkernel%2Flinux.git fuse: move request blocking related members to fuse_chan Move: - initialized - blocked - blocked_waitq - connected - num_waiting Signed-off-by: Miklos Szeredi --- diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 6279a37716c54..228e1e7114b7a 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -58,7 +58,7 @@ static ssize_t fuse_conn_waiting_read(struct file *file, char __user *buf, if (!fc) return 0; - value = atomic_read(&fc->num_waiting); + value = atomic_read(&fc->chan->num_waiting); file->private_data = (void *)value; fuse_conn_put(fc); } @@ -132,9 +132,9 @@ static ssize_t fuse_conn_max_background_write(struct file *file, if (fc) { spin_lock(&fc->chan->bg_lock); fc->chan->max_background = val; - fc->blocked = fc->chan->num_background >= fc->chan->max_background; - if (!fc->blocked) - wake_up(&fc->blocked_waitq); + fc->chan->blocked = fc->chan->num_background >= fc->chan->max_background; + if (!fc->chan->blocked) + wake_up(&fc->chan->blocked_waitq); spin_unlock(&fc->chan->bg_lock); fuse_conn_put(fc); } diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 36215a6b3e3ae..950c070ab3e96 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -529,7 +529,7 @@ static int cuse_channel_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&cc->list); - cc->fc.initialized = 1; + cc->fc.chan->initialized = 1; rc = cuse_send_init(cc); if (rc) { fuse_dev_put(fud); @@ -586,7 +586,7 @@ static ssize_t cuse_class_waiting_show(struct device *dev, { struct cuse_conn *cc = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", atomic_read(&cc->fc.num_waiting)); + return sprintf(buf, "%d\n", atomic_read(&cc->fc.chan->num_waiting)); } static DEVICE_ATTR(waiting, 0400, cuse_class_waiting_show, NULL); diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 1a22d9004c85c..3c05a84b5d706 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -74,26 +74,26 @@ void fuse_set_initialized(struct fuse_conn *fc) { /* Make sure stores before this are seen on another CPU */ smp_wmb(); - fc->initialized = 1; + fc->chan->initialized = 1; } static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background) { - return !fc->initialized || (for_background && fc->blocked) || - (fc->io_uring && fc->connected && !fuse_uring_ready(fc)); + return !fc->chan->initialized || (for_background && fc->chan->blocked) || + (fc->io_uring && fc->chan->connected && !fuse_uring_ready(fc)); } static void fuse_drop_waiting(struct fuse_conn *fc) { /* - * lockess check of fc->connected is okay, because atomic_dec_and_test() + * lockess check of fc->chan->connected is okay, because atomic_dec_and_test() * provides a memory barrier matched with the one in fuse_wait_aborted() * to ensure no wake-up is missed. */ - if (atomic_dec_and_test(&fc->num_waiting) && - !READ_ONCE(fc->connected)) { + if (atomic_dec_and_test(&fc->chan->num_waiting) && + !READ_ONCE(fc->chan->connected)) { /* wake up aborters */ - wake_up_all(&fc->blocked_waitq); + wake_up_all(&fc->chan->blocked_waitq); } } @@ -110,11 +110,11 @@ static struct fuse_req *fuse_get_req(struct mnt_idmap *idmap, kgid_t fsgid; int err; - atomic_inc(&fc->num_waiting); + atomic_inc(&fc->chan->num_waiting); if (fuse_block_alloc(fc, for_background)) { err = -EINTR; - if (wait_event_state_exclusive(fc->blocked_waitq, + if (wait_event_state_exclusive(fc->chan->blocked_waitq, !fuse_block_alloc(fc, for_background), (TASK_KILLABLE | TASK_FREEZABLE))) goto out; @@ -123,7 +123,7 @@ static struct fuse_req *fuse_get_req(struct mnt_idmap *idmap, smp_rmb(); err = -ENOTCONN; - if (!fc->connected) + if (!fc->chan->connected) goto out; err = -ECONNREFUSED; @@ -134,7 +134,7 @@ static struct fuse_req *fuse_get_req(struct mnt_idmap *idmap, err = -ENOMEM; if (!req) { if (for_background) - wake_up(&fc->blocked_waitq); + wake_up(&fc->chan->blocked_waitq); goto out; } @@ -182,8 +182,8 @@ static void fuse_put_request(struct fuse_req *req) * request was allocated but not sent */ spin_lock(&fc->chan->bg_lock); - if (!fc->blocked) - wake_up(&fc->blocked_waitq); + if (!fc->chan->blocked) + wake_up(&fc->chan->blocked_waitq); spin_unlock(&fc->chan->bg_lock); } @@ -357,7 +357,12 @@ struct fuse_chan *fuse_chan_new(void) INIT_LIST_HEAD(&fch->devices); spin_lock_init(&fch->bg_lock); INIT_LIST_HEAD(&fch->bg_queue); + init_waitqueue_head(&fch->blocked_waitq); + atomic_set(&fch->num_waiting, 0); fch->max_background = FUSE_DEFAULT_MAX_BACKGROUND; + fch->initialized = 0; + fch->blocked = 0; + fch->connected = 1; return fch; } @@ -426,7 +431,7 @@ void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc) * - it was already set to a different fc * - it was set to disconneted */ - fc->connected = 0; + fc->chan->connected = 0; } else { list_add_tail(&fud->entry, &fc->chan->devices); fuse_conn_get(fc); @@ -503,27 +508,27 @@ static void flush_bg_queue(struct fuse_conn *fc) } } -void fuse_request_bg_finish(struct fuse_conn *fc, struct fuse_req *req) +void fuse_request_bg_finish(struct fuse_chan *fch, struct fuse_req *req) { - lockdep_assert_held(&fc->chan->bg_lock); + lockdep_assert_held(&fch->bg_lock); clear_bit(FR_BACKGROUND, &req->flags); - if (fc->chan->num_background == fc->chan->max_background) { - fc->blocked = 0; - wake_up(&fc->blocked_waitq); - } else if (!fc->blocked) { + if (fch->num_background == fch->max_background) { + fch->blocked = 0; + wake_up(&fch->blocked_waitq); + } else if (!fch->blocked) { /* * Wake up next waiter, if any. It's okay to use * waitqueue_active(), as we've already synced up - * fc->blocked with waiters with the wake_up() call + * fch->blocked with waiters with the wake_up() call * above. */ - if (waitqueue_active(&fc->blocked_waitq)) - wake_up(&fc->blocked_waitq); + if (waitqueue_active(&fch->blocked_waitq)) + wake_up(&fch->blocked_waitq); } - fc->chan->num_background--; - fc->chan->active_background--; + fch->num_background--; + fch->active_background--; } /* @@ -558,7 +563,7 @@ void fuse_request_end(struct fuse_req *req) WARN_ON(test_bit(FR_SENT, &req->flags)); if (test_bit(FR_BACKGROUND, &req->flags)) { spin_lock(&fc->chan->bg_lock); - fuse_request_bg_finish(fc, req); + fuse_request_bg_finish(fc->chan, req); flush_bg_queue(fc); spin_unlock(&fc->chan->bg_lock); } else { @@ -737,7 +742,7 @@ ssize_t __fuse_simple_request(struct mnt_idmap *idmap, ssize_t ret; if (args->force) { - atomic_inc(&fc->num_waiting); + atomic_inc(&fc->chan->num_waiting); req = fuse_request_alloc(fm, GFP_KERNEL | __GFP_NOFAIL); if (!args->nocreds) @@ -797,7 +802,7 @@ static int fuse_request_queue_background(struct fuse_req *req) WARN_ON(!test_bit(FR_BACKGROUND, &req->flags)); if (!test_bit(FR_WAITING, &req->flags)) { __set_bit(FR_WAITING, &req->flags); - atomic_inc(&fc->num_waiting); + atomic_inc(&fc->chan->num_waiting); } __set_bit(FR_ISREPLY, &req->flags); @@ -807,10 +812,10 @@ static int fuse_request_queue_background(struct fuse_req *req) #endif spin_lock(&fc->chan->bg_lock); - if (likely(fc->connected)) { + if (likely(fc->chan->connected)) { fc->chan->num_background++; if (fc->chan->num_background == fc->chan->max_background) - fc->blocked = 1; + fc->chan->blocked = 1; list_add_tail(&req->list, &fc->chan->bg_queue); flush_bg_queue(fc); queued = true; @@ -2056,7 +2061,7 @@ static void fuse_resend(struct fuse_conn *fc) unsigned int i; spin_lock(&fc->lock); - if (!fc->connected) { + if (!fc->chan->connected) { spin_unlock(&fc->lock); return; } @@ -2162,7 +2167,7 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, * Only allow notifications during while the connection is in an * initialized and connected state */ - if (!fc->initialized || !fc->connected) + if (!fc->chan->initialized || !fc->chan->connected) return -EINVAL; /* Don't try to move folios (yet) */ @@ -2527,7 +2532,7 @@ void fuse_abort_conn(struct fuse_conn *fc) struct fuse_iqueue *fiq = &fc->chan->iq; spin_lock(&fc->lock); - if (fc->connected) { + if (fc->chan->connected) { struct fuse_dev *fud; struct fuse_req *req, *next; LIST_HEAD(to_end); @@ -2536,9 +2541,9 @@ void fuse_abort_conn(struct fuse_conn *fc) if (fc->timeout.req_timeout) cancel_delayed_work(&fc->timeout.work); - /* Background queuing checks fc->connected under bg_lock */ + /* Background queuing checks fc->chan->connected under bg_lock */ spin_lock(&fc->chan->bg_lock); - fc->connected = 0; + fc->chan->connected = 0; spin_unlock(&fc->chan->bg_lock); fuse_set_initialized(fc); @@ -2564,7 +2569,7 @@ void fuse_abort_conn(struct fuse_conn *fc) spin_unlock(&fpq->lock); } spin_lock(&fc->chan->bg_lock); - fc->blocked = 0; + fc->chan->blocked = 0; fc->chan->max_background = UINT_MAX; flush_bg_queue(fc); spin_unlock(&fc->chan->bg_lock); @@ -2580,7 +2585,7 @@ void fuse_abort_conn(struct fuse_conn *fc) spin_unlock(&fiq->lock); kill_fasync(&fiq->fasync, SIGIO, POLL_IN); end_polls(fc); - wake_up_all(&fc->blocked_waitq); + wake_up_all(&fc->chan->blocked_waitq); spin_unlock(&fc->lock); fuse_dev_end_requests(&to_end); @@ -2600,7 +2605,7 @@ void fuse_wait_aborted(struct fuse_conn *fc) { /* matches implicit memory barrier in fuse_drop_waiting() */ smp_mb(); - wait_event(fc->blocked_waitq, atomic_read(&fc->num_waiting) == 0); + wait_event(fc->chan->blocked_waitq, atomic_read(&fc->chan->num_waiting) == 0); fuse_uring_wait_stopped_queues(fc); } diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c index 9c553726701e9..723f7f2e2b1e7 100644 --- a/fs/fuse/dev_uring.c +++ b/fs/fuse/dev_uring.c @@ -90,7 +90,7 @@ static void fuse_uring_req_end(struct fuse_ring_ent *ent, struct fuse_req *req, if (test_bit(FR_BACKGROUND, &req->flags)) { queue->active_background--; spin_lock(&fc->chan->bg_lock); - fuse_request_bg_finish(fc, req); + fuse_request_bg_finish(fc->chan, req); fuse_uring_flush_bg(queue); spin_unlock(&fc->chan->bg_lock); } @@ -244,7 +244,7 @@ static struct fuse_ring *fuse_uring_create(struct fuse_conn *fc) max_payload_size = max(max_payload_size, fc->max_pages * PAGE_SIZE); spin_lock(&fc->lock); - if (!fc->connected) { + if (!fc->chan->connected) { spin_unlock(&fc->lock); goto out_err; } @@ -917,7 +917,7 @@ static int fuse_uring_commit_fetch(struct io_uring_cmd *cmd, int issue_flags, return err; fpq = &queue->fpq; - if (!READ_ONCE(fc->connected)) + if (!READ_ONCE(fc->chan->connected)) return err; spin_lock(&queue->lock); @@ -1010,7 +1010,7 @@ static int fuse_uring_do_register(struct fuse_ring_ent *ent, spin_lock(&fc->lock); /* abort teardown path is running or has run */ - if (!fc->connected) { + if (!fc->chan->connected) { spin_unlock(&fc->lock); if (atomic_dec_and_test(&ring->queue_refs)) wake_up_all(&ring->stop_waitq); @@ -1032,7 +1032,7 @@ static int fuse_uring_do_register(struct fuse_ring_ent *ent, if (ready) { WRITE_ONCE(fiq->ops, &fuse_io_uring_ops); smp_store_release(&ring->ready, true); - wake_up_all(&fc->blocked_waitq); + wake_up_all(&fc->chan->blocked_waitq); } } return 0; @@ -1190,14 +1190,14 @@ int fuse_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags) if (fc->aborted) return -ECONNABORTED; - if (!fc->connected) + if (!fc->chan->connected) return -ENOTCONN; /* * fuse_uring_register() needs the ring to be initialized, * we need to know the max payload size */ - if (!fc->initialized) + if (!fc->chan->initialized) return -EAGAIN; switch (cmd_op) { @@ -1207,7 +1207,7 @@ int fuse_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags) pr_info_once("FUSE_IO_URING_CMD_REGISTER failed err=%d\n", err); fc->io_uring = 0; - wake_up_all(&fc->blocked_waitq); + wake_up_all(&fc->chan->blocked_waitq); return err; } break; @@ -1373,7 +1373,7 @@ bool fuse_uring_queue_bq_req(struct fuse_req *req) spin_lock(&fc->chan->bg_lock); fc->chan->num_background++; if (fc->chan->num_background == fc->chan->max_background) - fc->blocked = 1; + fc->chan->blocked = 1; fuse_uring_flush_bg(queue); spin_unlock(&fc->chan->bg_lock); diff --git a/fs/fuse/fuse_dev_i.h b/fs/fuse/fuse_dev_i.h index db539dbb11f2f..3c350dfd31b48 100644 --- a/fs/fuse/fuse_dev_i.h +++ b/fs/fuse/fuse_dev_i.h @@ -108,6 +108,25 @@ struct fuse_chan { /** Protects: max_background, num_background, active_background, bg_queue, blocked */ spinlock_t bg_lock; + + /** Flag indicating that INIT reply has been received. Allocating + * any fuse request will be suspended until the flag is set */ + int initialized; + + /** Flag indicating if connection is blocked. This will be + the case before the INIT reply is received, and if there + are too many outstading backgrounds requests */ + int blocked; + + /** waitq for blocked connection */ + wait_queue_head_t blocked_waitq; + + /** Connection established, cleared on umount, connection + abort and device release */ + unsigned connected; + + /** The number of requests waiting for completion */ + atomic_t num_waiting; }; #define FUSE_PQ_HASH_BITS 8 @@ -205,7 +224,7 @@ unsigned int fuse_req_hash(u64 unique); struct fuse_req *fuse_request_find(struct fuse_pqueue *fpq, u64 unique); void fuse_dev_end_requests(struct list_head *head); -void fuse_request_bg_finish(struct fuse_conn *fc, struct fuse_req *req); +void fuse_request_bg_finish(struct fuse_chan *fch, struct fuse_req *req); void fuse_copy_init(struct fuse_copy_state *cs, bool write, struct iov_iter *iter); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index ccf0db3a4eeb0..a56e49c7a3249 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -569,22 +569,6 @@ struct fuse_conn { /** Number of background requests at which congestion starts */ unsigned congestion_threshold; - /** Flag indicating that INIT reply has been received. Allocating - * any fuse request will be suspended until the flag is set */ - int initialized; - - /** Flag indicating if connection is blocked. This will be - the case before the INIT reply is received, and if there - are too many outstading backgrounds requests */ - int blocked; - - /** waitq for blocked connection */ - wait_queue_head_t blocked_waitq; - - /** Connection established, cleared on umount, connection - abort and device release */ - unsigned connected; - /** Connection aborted via sysfs */ bool aborted; @@ -786,9 +770,6 @@ struct fuse_conn { /** Maximum stack depth for passthrough backing files */ int max_stack_depth; - /** The number of requests waiting for completion */ - atomic_t num_waiting; - /** Negotiated minor version */ unsigned minor; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 6e0ab13b093c9..13d788abe6de1 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -975,15 +975,10 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, refcount_set(&fc->count, 1); atomic_set(&fc->epoch, 1); INIT_WORK(&fc->epoch_work, fuse_epoch_work); - init_waitqueue_head(&fc->blocked_waitq); INIT_LIST_HEAD(&fc->entry); - atomic_set(&fc->num_waiting, 0); fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; atomic64_set(&fc->khctr, 0); fc->polled_files = RB_ROOT; - fc->blocked = 0; - fc->initialized = 0; - fc->connected = 1; atomic64_set(&fc->attr_version, 1); atomic64_set(&fc->evict_ctr, 1); get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); @@ -1444,7 +1439,7 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args, } fuse_set_initialized(fc); - wake_up_all(&fc->blocked_waitq); + wake_up_all(&fc->chan->blocked_waitq); } static struct fuse_init_args *fuse_new_init(struct fuse_mount *fm) diff --git a/fs/fuse/req_timeout.c b/fs/fuse/req_timeout.c index ee2b4dc394e0c..ef2e39e4dcf46 100644 --- a/fs/fuse/req_timeout.c +++ b/fs/fuse/req_timeout.c @@ -74,7 +74,7 @@ static void fuse_check_timeout(struct work_struct *work) struct fuse_pqueue *fpq; bool expired = false; - if (!atomic_read(&fc->num_waiting)) + if (!atomic_read(&fc->chan->num_waiting)) goto out; spin_lock(&fiq->lock); @@ -90,7 +90,7 @@ static void fuse_check_timeout(struct work_struct *work) goto abort_conn; spin_lock(&fc->lock); - if (!fc->connected) { + if (!fc->chan->connected) { spin_unlock(&fc->lock); return; }