[RHEL7,COMMIT] ms/fuse: Optimize request_end() by not taking fiq->waitq.lock

Submitted by Konstantin Khorenko on April 3, 2019, 9:49 a.m.

Details

Message ID 201904030949.x339nQZd006909@finist-ce7.sw.ru
State New
Series "fuse: Backport of ms locking patches part 1"
Headers show

Commit Message

Konstantin Khorenko April 3, 2019, 9:49 a.m.
The commit is pushed to "branch-rh7-3.10.0-957.10.1.vz7.94.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.10.1.vz7.85.10
------>
commit 0c05175bb913c58d59e78622bdd22d136d81e8ee
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Wed Apr 3 12:49:26 2019 +0300

    ms/fuse: Optimize request_end() by not taking fiq->waitq.lock
    
    ms commit 217316a60101
    
    We take global fiq->waitq.lock every time, when we are in this function,
    but interrupted requests are just small subset of all requests. This patch
    optimizes request_end() and makes it to take the lock when it's really
    needed.
    
    queue_interrupt() needs small change for that. After req is linked to
    interrupt list, we do smp_mb() and check for FR_FINISHED again. In case of
    FR_FINISHED bit has appeared, we remove req and leave the function:
    
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
    Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 fs/fuse/dev.c | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index eb5c62e3170f..18379fa9ca12 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -425,11 +425,19 @@  void request_end(struct fuse_conn *fc, struct fuse_req *req)
 	if (test_and_set_bit(FR_FINISHED, &req->flags))
 		return;
 
+	/*
+	 * test_and_set_bit() implies smp_mb() between bit
+	 * changing and below intr_entry check. Pairs with
+	 * smp_mb() from queue_interrupt().
+	 */
+	if (!list_empty(&req->intr_entry)) {
+		spin_lock(&fiq->waitq.lock);
+		list_del_init(&req->intr_entry);
+		spin_unlock(&fiq->waitq.lock);
+	}
+
 	bg = test_bit(FR_BACKGROUND, &req->flags);
 
-	spin_lock(&fiq->waitq.lock);
-	list_del_init(&req->intr_entry);
-	spin_unlock(&fiq->waitq.lock);
 	WARN_ON(test_bit(FR_PENDING, &req->flags));
 	WARN_ON(test_bit(FR_SENT, &req->flags));
 	if (bg) {
@@ -472,12 +480,18 @@  EXPORT_SYMBOL_GPL(request_end);
 static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req)
 {
 	spin_lock(&fiq->waitq.lock);
-	if (test_bit(FR_FINISHED, &req->flags)) {
-		spin_unlock(&fiq->waitq.lock);
-		return;
-	}
 	if (list_empty(&req->intr_entry)) {
 		list_add_tail(&req->intr_entry, &fiq->interrupts);
+		/*
+		 * Pairs with smp_mb() implied by test_and_set_bit()
+		 * from request_end().
+		 */
+		smp_mb();
+		if (test_bit(FR_FINISHED, &req->flags)) {
+			list_del_init(&req->intr_entry);
+			spin_unlock(&fiq->waitq.lock);
+			return;
+		}
 		wake_up_locked(&fiq->waitq);
 		kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
 	}