mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
fuse: fix io-uring background queue dispatch on request completion
When a background request completes via the io_uring path, the
background queue gets flushed to dispatch pending background requests,
but this is done before the connection-level background counters
(fc->num_background, fc->active_background) are properly accounted,
which may reduce effective queue depth to one.
The connection-level counters are decremented in fuse_request_end(), but
flush_bg_queue() flushes the /dev/fuse path queue (fc->bg_queue), not
the io_uring per-queue bg one, which means pending uring background
requests on the queue are never dispatched in this path.
Fix this by accounting the connection-level background counters first
before flushing the queue's background queue. Since
fuse_request_bg_finish() clears FR_BACKGROUND, fuse_request_end() will
skip the background cleanup branch entirely, which avoids any
double-decrements; it will call the wake_up(&req->waitq) branch but this
is effectively a no-op as background requests have no waiters on
req->waitq.
Reviewed-by: Bernd Schubert <bernd@bsbernd.com>
Fixes: 857b0263f3 ("fuse: Allow to queue bg requests through io-uring")
Cc: stable@vger.kernel.org
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
9fa4f7a534
commit
31da059891
|
|
@ -448,6 +448,29 @@ static void flush_bg_queue(struct fuse_conn *fc)
|
|||
}
|
||||
}
|
||||
|
||||
void fuse_request_bg_finish(struct fuse_conn *fc, struct fuse_req *req)
|
||||
{
|
||||
lockdep_assert_held(&fc->bg_lock);
|
||||
|
||||
clear_bit(FR_BACKGROUND, &req->flags);
|
||||
if (fc->num_background == fc->max_background) {
|
||||
fc->blocked = 0;
|
||||
wake_up(&fc->blocked_waitq);
|
||||
} else if (!fc->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
|
||||
* above.
|
||||
*/
|
||||
if (waitqueue_active(&fc->blocked_waitq))
|
||||
wake_up(&fc->blocked_waitq);
|
||||
}
|
||||
|
||||
fc->num_background--;
|
||||
fc->active_background--;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a request is finished. Either a reply
|
||||
* has arrived or it was aborted (and not yet sent) or some error
|
||||
|
|
@ -480,23 +503,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->bg_lock);
|
||||
clear_bit(FR_BACKGROUND, &req->flags);
|
||||
if (fc->num_background == fc->max_background) {
|
||||
fc->blocked = 0;
|
||||
wake_up(&fc->blocked_waitq);
|
||||
} else if (!fc->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
|
||||
* above.
|
||||
*/
|
||||
if (waitqueue_active(&fc->blocked_waitq))
|
||||
wake_up(&fc->blocked_waitq);
|
||||
}
|
||||
|
||||
fc->num_background--;
|
||||
fc->active_background--;
|
||||
fuse_request_bg_finish(fc, req);
|
||||
flush_bg_queue(fc);
|
||||
spin_unlock(&fc->bg_lock);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -90,6 +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->bg_lock);
|
||||
fuse_request_bg_finish(fc, req);
|
||||
fuse_uring_flush_bg(queue);
|
||||
spin_unlock(&fc->bg_lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,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_copy_init(struct fuse_copy_state *cs, bool write,
|
||||
struct iov_iter *iter);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user