[Devel] [PATCH RHEL9] fs/fuse: fix flush_bg_queue()

Kui Liu Kui.Liu at acronis.com
Fri Sep 29 12:17:35 MSK 2023


Currently flush_bg_queue() takes an input paramenter fiq, to which requests
in the bg_queue will be dispatched without respect to what's been set to
req->args->fiq. This behaviour totally breaks purpose of the request dispatching
algorithm when there are multiple input queues. So instead we need to enqueue
a request to its own req->args->fiq

Removes the unnecessary 'spin_lock(&fc->bg_lock)' operation before return
just to be unlocked later immediately. This can increase lock contention under
heavy workload, thus negatively affects performance.

Signed-off-by: Liu Kui <Kui.Liu at acronis.com>
---
fs/fuse/dev.c | 32 +++++++++++++++-----------------
1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index fe26e8f01609..424180ff7ab2 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -267,10 +267,12 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
               }
}

-static void flush_bg_queue(struct fuse_conn *fc, struct fuse_iqueue *fiq)
+static void flush_bg_queue_and_unlock(struct fuse_conn *fc)
+__releases(fc->bg_lock)
{
               struct fuse_req *req, *next;
               LIST_HEAD(kio_reqs);
+              struct fuse_iqueue *fiq;

               while (fc->active_background < fc->max_background &&
                      !list_empty(&fc->bg_queue)) {
@@ -287,17 +289,18 @@ static void flush_bg_queue(struct fuse_conn *fc, struct fuse_iqueue *fiq)
                                               } else if (ret < 0)
                                                               continue;
                               }
+                              fiq = req->args->fiq;
                               spin_lock(&fiq->lock);
                               req->in.h.unique = fuse_get_unique(fiq);
                               queue_request_and_unlock(fiq, req);
               }

               spin_unlock(&fc->bg_lock);
+
               list_for_each_entry_safe(req, next, &kio_reqs, list) {
                               list_del_init(&req->list);
                               fc->kio.op->req_send(req, true);
               }
-               spin_lock(&fc->bg_lock);
}

/*
@@ -356,8 +359,9 @@ void __fuse_request_end( struct fuse_req *req, bool flush_bg)
                               fc->num_background--;
                               fc->active_background--;
                               if (flush_bg)
-                                               flush_bg_queue(fc, fiq);
-                               spin_unlock(&fc->bg_lock);
+                                              flush_bg_queue_and_unlock(fc);
+                              else
+                                              spin_unlock(&fc->bg_lock);
               }

               if (test_bit(FR_ASYNC, &req->flags)) {
@@ -609,6 +613,7 @@ static int fuse_request_queue_background(struct fuse_req *req)
               if (ff && test_bit(FUSE_S_FAIL_IMMEDIATELY, &ff->ff_state)) {
                               ret = -EIO;
               } else if (likely(fc->connected)) {
+                              ret = 0;
                               fc->num_background++;
                               if (fc->num_background == fc->max_background)
                                               fc->blocked = 1;
@@ -622,17 +627,14 @@ static int fuse_request_queue_background(struct fuse_req *req)
                                               spin_lock(&fiq->lock);
                                               req->in.h.unique = fuse_get_unique(fiq);
                                               queue_request_and_unlock(fiq, req);
-                                               ret = 0;
-                                               goto unlock;
+                              } else {
+                                              list_add_tail(&req->list, &fc->bg_queue);
+                                              flush_bg_queue_and_unlock(fc);
+                                              goto out;
                               }
-
-                               list_add_tail(&req->list, &fc->bg_queue);
-                               flush_bg_queue(fc, fiq);
-                               ret = 0;
               }
-unlock:
               spin_unlock(&fc->bg_lock);
-
+out:
               return ret;
}

@@ -2297,11 +2299,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
                               spin_lock(&fc->bg_lock);
                               fc->blocked = 0;
                               fc->max_background = UINT_MAX;
-                               for_each_online_cpu(cpu)
-                                               flush_bg_queue(fc, per_cpu_ptr(fc->iqs, cpu));
-                               flush_bg_queue(fc, &fc->main_iq);
-                               spin_unlock(&fc->bg_lock);
-
+                              flush_bg_queue_and_unlock(fc);

                               for_each_online_cpu(cpu)
                                               fuse_abort_iqueue(per_cpu_ptr(fc->iqs, cpu), &to_end);
--
2.32.0 (Apple Git-132)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvz.org/pipermail/devel/attachments/20230929/c5f56d97/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-fs-fuse-fix-flush_bg_queue.patch
Type: application/octet-stream
Size: 3533 bytes
Desc: 0001-fs-fuse-fix-flush_bg_queue.patch
URL: <http://lists.openvz.org/pipermail/devel/attachments/20230929/c5f56d97/attachment-0001.obj>


More information about the Devel mailing list