
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICFOA8 CVE: NA -------------------------------- Fix several issues in fuse_resend_pqueue(): 1. Set FR_PENDING flag atomically when resending request 2. Clear FR_SENT flag before resending 3. Check for aborted connection before adding requests to pending list 4. Wake up fiq->waitq after adding request back to pending queue Since kernel has merged 97f30876c943 ("fuse: Introduce a new notification type for resend pending requests") which already supports request resend functionality but not triggered via sysfs, simplify the code by replacing fuse_resend_pqueue() with fuse_resend(). This helps maintain code simplicity while ensuring correct request resend behavior. Signed-off-by: Long Li <leo.lilong@huawei.com> --- fs/fuse/control.c | 2 +- fs/fuse/dev.c | 63 +---------------------------------------------- fs/fuse/fuse_i.h | 2 +- 3 files changed, 3 insertions(+), 64 deletions(-) diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 8ae0f8625e59..9c7ce06276b3 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -62,7 +62,7 @@ static ssize_t fuse_conn_resend_write(struct file *file, const char __user *buf, struct fuse_conn *fc = fuse_ctl_file_conn_get(file); if (fc) { - fuse_resend_pqueue(fc); + fuse_resend(fc); fuse_conn_put(fc); } return count; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index d38db9ed4f35..98500f0f02ea 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1860,7 +1860,7 @@ static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size, * if the FUSE daemon takes careful measures to avoid processing duplicated * non-idempotent requests. */ -static void fuse_resend(struct fuse_conn *fc) +void fuse_resend(struct fuse_conn *fc) { struct fuse_dev *fud; struct fuse_req *req, *next; @@ -2398,67 +2398,6 @@ void fuse_flush_pq(struct fuse_conn *fc) end_requests(&to_end); } -/** - * Resend all processing queue requests. - * - * When a FUSE daemon panics and fails over, we want to reuse the existing FUSE - * connection and avoid affecting applications as little as possible. During - * FUSE daemon failover, the FUSE processing queue requests are waiting for - * replies from user space daemon that never come back and applications would - * stuck forever. - * - * Besides flushing the processing queue requests like being done in fuse_flush_pq(), - * we can also resend these requests to user space daemon so that they can be - * processed properly again. Such strategy can only be done for idempotent requests - * or if the user space daemon takes good care to record and avoid processing - * duplicated non-idempotent requests. - */ -void fuse_resend_pqueue(struct fuse_conn *fc) -{ - struct fuse_dev *fud; - struct fuse_req *req, *next; - struct fuse_iqueue *fiq = &fc->iq; - LIST_HEAD(to_queue); - unsigned int i; - - spin_lock(&fc->lock); - if (!fc->connected) { - spin_unlock(&fc->lock); - return; - } - - list_for_each_entry(fud, &fc->devices, entry) { - struct fuse_pqueue *fpq = &fud->pq; - - spin_lock(&fpq->lock); - /* - * Move requests for resend, including two parts: unlocked - * requests in io list, and all requests in pending queue. - */ - list_for_each_entry_safe(req, next, &fpq->io, list) { - spin_lock(&req->waitq.lock); - if (!test_bit(FR_LOCKED, &req->flags)) { - __fuse_get_request(req); - list_move(&req->list, &to_queue); - } - spin_unlock(&req->waitq.lock); - } - for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) - list_splice_tail_init(&fpq->processing[i], &to_queue); - spin_unlock(&fpq->lock); - } - spin_unlock(&fc->lock); - - list_for_each_entry_safe(req, next, &to_queue, list) { - __set_bit(FR_PENDING, &req->flags); - } - - spin_lock(&fiq->lock); - /* iq and pq requests are both oldest to newest */ - list_splice(&to_queue, &fiq->pending); - spin_unlock(&fiq->lock); -} - static int fuse_dev_fasync(int fd, struct file *file, int on) { struct fuse_dev *fud = fuse_get_dev(file); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index a5f88c0bdeb9..ac101018bdba 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1204,7 +1204,7 @@ void fuse_wait_aborted(struct fuse_conn *fc); void fuse_flush_pq(struct fuse_conn *fc); /* Resend all requests in processing queue so they can represent to userspace */ -void fuse_resend_pqueue(struct fuse_conn *fc); +void fuse_resend(struct fuse_conn *fc); /** * Invalidate inode attributes -- 2.39.2