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

Konstantin Khorenko khorenko at virtuozzo.com
Wed Nov 1 22:23:14 MSK 2023


The commit is pushed to "branch-rh9-5.14.0-284.25.1.vz9.30.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh9-5.14.0-284.25.1.vz9.30.8
------>
commit f92fadba8974c47d124cc0b9b13c48627cb3808f
Author: Alexey Kuznetsov <kuznet at virtuozzo.com>
Date:   Fri Oct 6 18:42:20 2023 +0800

    fs/fuse: fix flush_bg_queue()
    
    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.
    
    https://pmc.acronis.work/browse/VSTOR-54040
    
    Signed-off-by: Liu Kui <Kui.Liu at acronis.com>
    Acked-by: Alexey Kuznetsov <kuznet at acronis.com>
    
    Feature: vStorage
---
 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);


More information about the Devel mailing list