Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1627029imu; Tue, 6 Nov 2018 01:31:28 -0800 (PST) X-Google-Smtp-Source: AJdET5equaV16uzIP8PuU6s/as3etGAvDRRnbrgIHWfuj7l1GvdhPDtri8maDUd2FpUPGt5nfYqK X-Received: by 2002:a65:638a:: with SMTP id h10-v6mr23212853pgv.136.1541496688403; Tue, 06 Nov 2018 01:31:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1541496688; cv=none; d=google.com; s=arc-20160816; b=nTawhjSDnziK7ykH+mQSjvRocQwC3fJnDH9sK44WSQz8ehsMoha4bZF1QmBFWf10I0 fHhbdFNa6sa0DV1Tf+NIpQRQMtYKz3/rf4lTdhTCj4vgn+PqQ2tYCd1UVTOYzhcfMHpA xtyEhloUSrSJkPHK2kooIXigCZej2UQ3nwXRzu260fhEIBwyNlKQ1zps8WWpN+KUGfY1 1IQyAIAEZ5ZlhNT/FkaxzPlKreASXEsgBS6A2ZGgW7blAdEPvSVm21SbFM1bkr2b103Z VcRrzTaQgUSHK2re6l8bzcWCoUUs/pQlO8SGAN/kO1FPgasAtz/0zbm5zVylS6k5qi8P xUwQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:to:from:subject; bh=As7q/zWrCc0AoeKTBVeRu22ZAbw4TNCTs1w80VWFW/g=; b=MexwqU7PD0XA4EnpMJLl2GmlXa3tmkGgjzr4h1/VEDX/tLiz6bt4psyjMvVIAoBCI2 b2c0xfYZBoqDAfEr85UrneDVZwdVx2r/a1vLFwVIITK5YkleQxaG/ESmuKFK/6Y+KrR/ TYMX8A80awOG76pCNnWIj1OXr2AMfKkwfuVKICl+d2il83gyZlqln4H9jQkq3E+DRQXm QYEZaIxWv6Zftb1rwFStnmj7uPajsa9IQXyUIf/QZKC89xFhWNl29fyDCeNLN6Xvgkih UZbdTATiST2XQMgRDYeMGfld3eZGvVpD+udURrd+dkqPQwX/rvl/KOuJI2lY9EYM8mf3 fvKg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=virtuozzo.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y13si19338492pgj.157.2018.11.06.01.31.13; Tue, 06 Nov 2018 01:31:28 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=virtuozzo.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730268AbeKFSzB (ORCPT + 99 others); Tue, 6 Nov 2018 13:55:01 -0500 Received: from relay.sw.ru ([185.231.240.75]:59152 "EHLO relay.sw.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729430AbeKFSzA (ORCPT ); Tue, 6 Nov 2018 13:55:00 -0500 Received: from [172.16.25.169] (helo=localhost.localdomain) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1gJxh0-0002vn-Ub; Tue, 06 Nov 2018 12:30:39 +0300 Subject: [PATCH 2/6] fuse: Optimize request_end() by not taking fiq->waitq.lock From: Kirill Tkhai To: miklos@szeredi.hu, ktkhai@virtuozzo.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Tue, 06 Nov 2018 12:30:38 +0300 Message-ID: <154149663862.17764.9649077325029198892.stgit@localhost.localdomain> In-Reply-To: <154149586524.17764.5252013294539109287.stgit@localhost.localdomain> References: <154149586524.17764.5252013294539109287.stgit@localhost.localdomain> User-Agent: StGit/0.18 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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: CPU 0 CPU 1 queue_interrupt() request_end() spin_lock(&fiq->waitq.lock) list_add_tail(&req->intr_entry, &fiq->interrupts) test_and_set_bit(FR_FINISHED, &req->flags) smp_mb() if (test_bit(FR_FINISHED, &req->flags)) if (!list_empty(&req->intr_entry)) list_del_init(&req->intr_entry) spin_lock(&fiq->waitq.lock) list_del_init(&req->intr_entry) Check the change is visible in perf report: 1)Firstly mount fusexmp_fh: $fuse/example/.libs/fusexmp_fh mnt 2)Run test doing futimes(fd, tv1); futimes(fd, tv2); in many threads endlessly. 3)perf record -g (all the system load) Without the patch in request_end() we spend 62.58% of do_write() time: (= 12.58 / 20.10 * 100%) 55,22% entry_SYSCALL_64 20,10% do_writev ... 18,08% fuse_dev_do_write 12,58% request_end 10,08% __wake_up_common_lock 1,97% queued_spin_lock_slowpath 1,31% fuse_copy_args 1,04% fuse_copy_one 0,85% queued_spin_lock_slowpath With the patch, the perf report becomes better, and only 58.16% of do_write() time we spend in request_end(): 54,15% entry_SYSCALL_64 18,24% do_writev ... 16,25% fuse_dev_do_write 10,61% request_end 10,25% __wake_up_common_lock 1,34% fuse_copy_args 1,06% fuse_copy_one 0,88% queued_spin_lock_slowpath Signed-off-by: Kirill Tkhai --- fs/fuse/dev.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 7705f75c77a3..391498e680ec 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -427,10 +427,16 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) if (test_and_set_bit(FR_FINISHED, &req->flags)) goto put_request; - - spin_lock(&fiq->waitq.lock); - list_del_init(&req->intr_entry); - spin_unlock(&fiq->waitq.lock); + /* + * 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); + } WARN_ON(test_bit(FR_PENDING, &req->flags)); WARN_ON(test_bit(FR_SENT, &req->flags)); if (test_bit(FR_BACKGROUND, &req->flags)) { @@ -470,13 +476,21 @@ static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) { bool kill = false; - spin_lock(&fiq->waitq.lock); - if (test_bit(FR_FINISHED, &req->flags)) { - spin_unlock(&fiq->waitq.lock); + if (test_bit(FR_FINISHED, &req->flags)) return; - } + spin_lock(&fiq->waitq.lock); 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 = true; }