Received: by 2002:ac0:aa62:0:0:0:0:0 with SMTP id w31-v6csp4030491ima; Tue, 23 Oct 2018 15:46:58 -0700 (PDT) X-Google-Smtp-Source: AJdET5fDiO7Lv8NmJOFbh8c3y3222SDPgIsI2Z8/Aor1xeBXw2zFWDwejpE19DCLLo5HFdcu3zHz X-Received: by 2002:a62:f715:: with SMTP id h21-v6mr147777pfi.169.1540334818359; Tue, 23 Oct 2018 15:46:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1540334818; cv=none; d=google.com; s=arc-20160816; b=THx3Kqc5kvVps91IZ4w393wwlFhqvnnw1+VbaobOj6KAsrlOMh6xcFugX2QEWs9wrw 5DVUdN7icf1WKPQt5NujDLsExF/HSl47ufxlsmS1HjDWVmJU9/qWXQ9Mij4hffKIviOi 9K55JHi3F4rpARe3RpOrlV9K0gCiWcFj8w3xIbQrGB/QeHobERIFIg+JJuMJOw+BjsPM 8IutFkNPR7+631t/st9qCHECO+0Oa/YZGZfSG94Q7B40JZyL/qWyysdBV7hDMa2vcHyb A/cWKZmj1xkVmynqOm4vEpmY65jzBz7Ywtb95HBkdsH4A+vE1KgfMrINXg3DG4mTUt+S chIw== 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:cc:subject:date:to :from; bh=NIMOFVKCAiyMZfDQEGronQzWY4WFZc/tjQbJRCVixLs=; b=Of6VhrHKbRWjuot37+cFGuwbOKgsi5sYCm95tFnmOawXHT0boKX54sYFXEkdrWgAiR wFgXRMXTDP/71Y5DzQU9nOyez79+ennjI0l9CSo3t0fiT1YABo95LkpYsNLyKCZ5Hpb4 qA+1xDYAnUVD04kqlTexKjB/wwM9Yf4r1i3ThKf8q3/0vSv5shqXIu9l0R1wmX26kYqv yHTik+U8DqvrieSj8zOX1zej1nBtuji9pe6dXYP3l5OcTKMH8jCUVD8oYPPr8+79Wu3M PE4MqI1Y5LrrhddaBwa/ncoBUWvZ5Xi1KjEjhxpvHkzShD1pkIacl2OgD78vTceO+cIP iMgA== 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u12-v6si2783448pfd.66.2018.10.23.15.46.43; Tue, 23 Oct 2018 15:46:58 -0700 (PDT) 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729164AbeJXHL3 (ORCPT + 99 others); Wed, 24 Oct 2018 03:11:29 -0400 Received: from mx2.suse.de ([195.135.220.15]:36358 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725787AbeJXHL3 (ORCPT ); Wed, 24 Oct 2018 03:11:29 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 27DCEAF84; Tue, 23 Oct 2018 22:46:02 +0000 (UTC) From: NeilBrown To: Jeff Layton , Alexander Viro Date: Wed, 24 Oct 2018 09:43:54 +1100 Subject: [PATCH 4/9] fs/locks: allow a lock request to block other requests. Cc: "J. Bruce Fields" , Martin Wilck , linux-fsdevel@vger.kernel.org, Frank Filz , linux-kernel@vger.kernel.org Message-ID: <154033463449.29542.10275772676578015580.stgit@noble> In-Reply-To: <154033435272.29542.13985568983074440924.stgit@noble> References: <154033435272.29542.13985568983074440924.stgit@noble> User-Agent: StGit/0.17.1-dirty 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 Currently, a lock can block pending requests, but all pending requests are equal. If lots of pending requests are mutually exclusive, this means they will all be woken up and all but one will fail. This can hurt performance. So we will allow pending requests to block other requests. Only the first request will be woken, and it will wake the others. This patch doesn't implement this fully, but prepares the way. - It acknowledges that a request might be blocking other requests, and when the request is converted to a lock, those blocked requests are moved across. - When a request is requeued or discarded, all blocked requests are woken. - When deadlock-detection looks for the lock which blocks a given request, we follow the chain of ->fl_blocker all the way to the top. Signed-off-by: NeilBrown --- fs/locks.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index b8f33792a0a6..d362e84a7176 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -402,6 +402,17 @@ void locks_copy_lock(struct file_lock *new, struct file_lock *fl) EXPORT_SYMBOL(locks_copy_lock); +static void locks_move_blocks(struct file_lock *new, struct file_lock *fl) +{ + struct file_lock *f; + + spin_lock(&blocked_lock_lock); + list_splice_init(&fl->fl_blocked, &new->fl_blocked); + list_for_each_entry(f, &fl->fl_blocked, fl_block) + f->fl_blocker = new; + spin_unlock(&blocked_lock_lock); +} + static inline int flock_translate_cmd(int cmd) { if (cmd & LOCK_MAND) return cmd & (LOCK_MAND | LOCK_RW); @@ -690,6 +701,7 @@ static void __locks_wake_up_blocks(struct file_lock *blocker) static void locks_delete_block(struct file_lock *waiter) { spin_lock(&blocked_lock_lock); + __locks_wake_up_blocks(waiter); __locks_delete_block(waiter); spin_unlock(&blocked_lock_lock); } @@ -712,6 +724,12 @@ static void __locks_insert_block(struct file_lock *blocker, list_add_tail(&waiter->fl_block, &blocker->fl_blocked); if (IS_POSIX(blocker) && !IS_OFDLCK(blocker)) locks_insert_global_blocked(waiter); + + /* The requests in waiter->fl_blocked are known to conflict with + * waiter, but might not conflict with blocker, or the requests + * and lock which block it. So they all need to be woken. + */ + __locks_wake_up_blocks(waiter); } /* Must be called with flc_lock held. */ @@ -884,8 +902,11 @@ static struct file_lock *what_owner_is_waiting_for(struct file_lock *block_fl) struct file_lock *fl; hash_for_each_possible(blocked_hash, fl, fl_link, posix_owner_key(block_fl)) { - if (posix_same_owner(fl, block_fl)) - return fl->fl_blocker; + if (posix_same_owner(fl, block_fl)) { + while (fl->fl_blocker) + fl = fl->fl_blocker; + return fl; + } } return NULL; } @@ -978,6 +999,7 @@ static int flock_lock_inode(struct inode *inode, struct file_lock *request) if (request->fl_flags & FL_ACCESS) goto out; locks_copy_lock(new_fl, request); + locks_move_blocks(new_fl, request); locks_insert_lock_ctx(new_fl, &ctx->flc_flock); new_fl = NULL; error = 0; @@ -1171,6 +1193,7 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request, goto out; } locks_copy_lock(new_fl, request); + locks_move_blocks(new_fl, request); locks_insert_lock_ctx(new_fl, &fl->fl_list); fl = new_fl; new_fl = NULL; @@ -2585,13 +2608,14 @@ void locks_remove_file(struct file *filp) int posix_unblock_lock(struct file_lock *waiter) { - int status = 0; + int status = -ENOENT; spin_lock(&blocked_lock_lock); - if (waiter->fl_blocker) + if (waiter->fl_blocker) { + __locks_wake_up_blocks(waiter); __locks_delete_block(waiter); - else - status = -ENOENT; + status = 0; + } spin_unlock(&blocked_lock_lock); return status; }