Re: [PATCH] fuse: serialize resend state transitions with fiq->lock
Mingyu He <[email protected]>
| Newsgroups | dev.linux.lists.fuse-devel |
|---|---|
| Message-ID | <CAAoBcuSRsSnPo3jK11N0dxq6zXZtivfXeE-4SPL7NUKhmQsc=w@mail.gmail.com> |
oops, I found that Jun Yang <[email protected]> also sent an email that have fixed same problem. Recently I am working for fuse recovery mechanism for my company, and found that problem. I was working for this problem on 4th Aug and sent this email the next day, so I didn't noticed that someone else had already sent an email before me. As Jun Yang has resolved this issue more completely and sent email before mine, I suppose to ignore my email and consider his solution. Thanks! Link: https://lore.kernel.org/all/[email protected]/ https://lore.kernel.org/all/[email protected]/ On Wed, Aug 5, 2026 at 3:10 PM Runli <[email protected]> wrote: > > fuse_chan_resend() moves processing requests to a private to_queue, then > sets FR_PENDING before taking fiq->lock. A fatal signal can consequently > remove and free a request while it is still being prepared for resend: > > CPU 0 (request holder) CPU 1 (resend) > ---------------------- ---------------- > request_wait_answer() > req moved to private to_queue > set_bit(FR_PENDING) > fatal signal > fuse_remove_pending_req() > list_del(&req->list) > __fuse_put_request(req) > fuse_put_request(req) > free req > clear_bit(FR_SENT) > update req->in.h.unique > > Hold fiq->lock while updating the requests and moving them to > fiq->pending, serializing the transition with fuse_remove_pending_req(). > > Connected requests retain the same flags, unique IDs, and queue order. On > disconnection, fuse_dev_end_requests() still ends every request, while > requests that were never requeued are no longer marked pending or resent. > > This also combines the two linear list walks into one, reducing the total > iteration count from 2n to n. The fiq->lock critical section remains O(n). > > Fixes: 760eac73f9f6 ("fuse: Introduce a new notification type for resend pending requests") > Signed-off-by: Runli <[email protected]> > --- > fs/fuse/dev.c | 24 ++++++++++-------------- > 1 file changed, 10 insertions(+), 14 deletions(-) > > diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c > index 5763a7cd3b37..fc1f5b9f100c 100644 > --- a/fs/fuse/dev.c > +++ b/fs/fuse/dev.c > @@ -1781,26 +1781,22 @@ void fuse_chan_resend(struct fuse_chan *fch) > } > spin_unlock(&fch->lock); > > - list_for_each_entry_safe(req, next, &to_queue, list) { > - set_bit(FR_PENDING, &req->flags); > - clear_bit(FR_SENT, &req->flags); > - /* mark the request as resend request */ > - req->in.h.unique |= FUSE_UNIQUE_RESEND; > - } > - > spin_lock(&fiq->lock); > if (!fiq->connected) { > spin_unlock(&fiq->lock); > - list_for_each_entry(req, &to_queue, list) > - clear_bit(FR_PENDING, &req->flags); > fuse_dev_end_requests(&to_queue); > return; > } > - /* > - * Remove interrupt entries for resent requests to prevent stale > - * intr_entry on fiq->interrupts after the request is re-queued. > - */ > - list_for_each_entry(req, &to_queue, list) { > + > + list_for_each_entry_safe(req, next, &to_queue, list) { > + set_bit(FR_PENDING, &req->flags); > + clear_bit(FR_SENT, &req->flags); > + /* mark the request as resend request */ > + req->in.h.unique |= FUSE_UNIQUE_RESEND; > + /* > + * Remove interrupt entries for resent requests to prevent stale > + * intr_entry on fiq->interrupts after the request is re-queued. > + */ > if (test_bit(FR_INTERRUPTED, &req->flags)) > list_del_init(&req->intr_entry); > } > -- > 2.47.0 >