Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp3646592imm; Mon, 18 Jun 2018 01:29:53 -0700 (PDT) X-Google-Smtp-Source: ADUXVKL9hF0SUf9K4Ec6lDN5Z0MCUbs/VVDzLlZdMf9QbEVbSwcDQX2VMiQnllakeulImh2Ad5cZ X-Received: by 2002:a63:8a4a:: with SMTP id y71-v6mr9844916pgd.291.1529310593839; Mon, 18 Jun 2018 01:29:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529310593; cv=none; d=google.com; s=arc-20160816; b=ud1+fENvlwd0os0aIJNBqhbpEija9heYDEXatxMPyx9IYtazjbfBkhEawpNLbQB5TS ImZnNicBblpmoUolsXxpu2TUrlMREq2fl9zA6C8SWB3+6J1/1JdHoEwm5Ykz1gd9YXek NcoZjbcGL8IBnQJtS8vodHlOh0bGoUtXxuUS7qYfPvEzn3SGvds0Mxv3cdtlhXxsPaaq 0mt/tGinRE6QXhtSdmw9ndfglf7x4Y5AkjLQQ3p9/5ywXxQKHP3D2c9GdDAkzxEZtR5A cqcQCZ4t1QRnA0HvPpsXmtrkgvUoit/a/w11RR/lVHaFJm4k1OX6KQ8RV3dkAWXqYIwi Z5Lg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=PCRRJ4YPeG4rDBTduRpse+y+56gGuHFrdtdR/IOMJjw=; b=HIGFqrEQtGCOwbgSN+rkwpthq+64xrASO20RcXXyBU8TZ3hgK2Un7ZXt5qtpXFX0vY +lE4EcZ2Wd8rx0Kfq4NmPiupbD5SctajC3tq854dXucxOvrSeNY6BSV7vVORcfz9IWoa gbr8/HAJnVvVRum1lqcn/bmonsuZXKG0NLx7XuVgRO/ioQQM6UZ5Gm2/tycTC4SfAEXa KranQG+ZTyJ3PBHc+V7McTcAZh9Anlk4+FyJ4zpjtiBwyDTGAMLMVV5K0sfutrgIm1Bm Yy1Q0Snxf3Wf8P7F6tu8mphAtkwxmhtPNz6g3w0Cmgh99RQk1ly1ooKEx0oeAtYvyvnj /Bhg== 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 34-v6si14115972plc.346.2018.06.18.01.29.40; Mon, 18 Jun 2018 01:29:53 -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 S966710AbeFRI27 (ORCPT + 99 others); Mon, 18 Jun 2018 04:28:59 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:33290 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965150AbeFRI2z (ORCPT ); Mon, 18 Jun 2018 04:28:55 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 6D88CC3C; Mon, 18 Jun 2018 08:28:54 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Amir Goldstein , Waiman Long , Peter Zijlstra , Andrew Morton , Davidlohr Bueso , Jan Kara , Linus Torvalds , Matthew Wilcox , Oleg Nesterov , "Paul E. McKenney" , "Theodore Y. Tso" , Thomas Gleixner , Will Deacon , linux-fsdevel@vger.kernel.org, Ingo Molnar , Sasha Levin Subject: [PATCH 4.16 267/279] locking/rwsem: Add a new RWSEM_ANONYMOUSLY_OWNED flag Date: Mon, 18 Jun 2018 10:14:12 +0200 Message-Id: <20180618080619.738367697@linuxfoundation.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180618080608.851973560@linuxfoundation.org> References: <20180618080608.851973560@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.16-stable review patch. If anyone has any objections, please let me know. ------------------ From: Waiman Long [ Upstream commit d7d760efad70c7a030725499bf9f342f04af24dd ] There are use cases where a rwsem can be acquired by one task, but released by another task. In thess cases, optimistic spinning may need to be disabled. One example will be the filesystem freeze/thaw code where the task that freezes the filesystem will acquire a write lock on a rwsem and then un-owns it before returning to userspace. Later on, another task will come along, acquire the ownership, thaw the filesystem and release the rwsem. Bit 0 of the owner field was used to designate that it is a reader owned rwsem. It is now repurposed to mean that the owner of the rwsem is not known. If only bit 0 is set, the rwsem is reader owned. If bit 0 and other bits are set, it is writer owned with an unknown owner. One such value for the latter case is (-1L). So we can set owner to 1 for reader-owned, -1 for writer-owned. The owner is unknown in both cases. To handle transfer of rwsem ownership, the higher level code should set the owner field to -1 to indicate a write-locked rwsem with unknown owner. Optimistic spinning will be disabled in this case. Once the higher level code figures who the new owner is, it can then set the owner field accordingly. Tested-by: Amir Goldstein Signed-off-by: Waiman Long Acked-by: Peter Zijlstra Cc: Andrew Morton Cc: Davidlohr Bueso Cc: Jan Kara Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Oleg Nesterov Cc: Paul E. McKenney Cc: Theodore Y. Ts'o Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-fsdevel@vger.kernel.org Link: http://lkml.kernel.org/r/1526420991-21213-2-git-send-email-longman@redhat.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- kernel/locking/rwsem-xadd.c | 17 +++++++---------- kernel/locking/rwsem.c | 2 -- kernel/locking/rwsem.h | 30 +++++++++++++++++++++--------- 3 files changed, 28 insertions(+), 21 deletions(-) --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -357,11 +357,8 @@ static inline bool rwsem_can_spin_on_own rcu_read_lock(); owner = READ_ONCE(sem->owner); - if (!rwsem_owner_is_writer(owner)) { - /* - * Don't spin if the rwsem is readers owned. - */ - ret = !rwsem_owner_is_reader(owner); + if (!owner || !is_rwsem_owner_spinnable(owner)) { + ret = !owner; /* !owner is spinnable */ goto done; } @@ -382,11 +379,11 @@ static noinline bool rwsem_spin_on_owner { struct task_struct *owner = READ_ONCE(sem->owner); - if (!rwsem_owner_is_writer(owner)) - goto out; + if (!is_rwsem_owner_spinnable(owner)) + return false; rcu_read_lock(); - while (sem->owner == owner) { + while (owner && (READ_ONCE(sem->owner) == owner)) { /* * Ensure we emit the owner->on_cpu, dereference _after_ * checking sem->owner still matches owner, if that fails, @@ -408,12 +405,12 @@ static noinline bool rwsem_spin_on_owner cpu_relax(); } rcu_read_unlock(); -out: + /* * If there is a new owner or the owner is not set, we continue * spinning. */ - return !rwsem_owner_is_reader(READ_ONCE(sem->owner)); + return is_rwsem_owner_spinnable(READ_ONCE(sem->owner)); } static bool rwsem_optimistic_spin(struct rw_semaphore *sem) --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c @@ -217,5 +217,3 @@ void up_read_non_owner(struct rw_semapho EXPORT_SYMBOL(up_read_non_owner); #endif - - --- a/kernel/locking/rwsem.h +++ b/kernel/locking/rwsem.h @@ -1,20 +1,24 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * The owner field of the rw_semaphore structure will be set to - * RWSEM_READ_OWNED when a reader grabs the lock. A writer will clear + * RWSEM_READER_OWNED when a reader grabs the lock. A writer will clear * the owner field when it unlocks. A reader, on the other hand, will * not touch the owner field when it unlocks. * - * In essence, the owner field now has the following 3 states: + * In essence, the owner field now has the following 4 states: * 1) 0 * - lock is free or the owner hasn't set the field yet * 2) RWSEM_READER_OWNED * - lock is currently or previously owned by readers (lock is free * or not set by owner yet) - * 3) Other non-zero value - * - a writer owns the lock + * 3) RWSEM_ANONYMOUSLY_OWNED bit set with some other bits set as well + * - lock is owned by an anonymous writer, so spinning on the lock + * owner should be disabled. + * 4) Other non-zero value + * - a writer owns the lock and other writers can spin on the lock owner. */ -#define RWSEM_READER_OWNED ((struct task_struct *)1UL) +#define RWSEM_ANONYMOUSLY_OWNED (1UL << 0) +#define RWSEM_READER_OWNED ((struct task_struct *)RWSEM_ANONYMOUSLY_OWNED) #ifdef CONFIG_RWSEM_SPIN_ON_OWNER /* @@ -45,14 +49,22 @@ static inline void rwsem_set_reader_owne WRITE_ONCE(sem->owner, RWSEM_READER_OWNED); } -static inline bool rwsem_owner_is_writer(struct task_struct *owner) +/* + * Return true if the a rwsem waiter can spin on the rwsem's owner + * and steal the lock, i.e. the lock is not anonymously owned. + * N.B. !owner is considered spinnable. + */ +static inline bool is_rwsem_owner_spinnable(struct task_struct *owner) { - return owner && owner != RWSEM_READER_OWNED; + return !((unsigned long)owner & RWSEM_ANONYMOUSLY_OWNED); } -static inline bool rwsem_owner_is_reader(struct task_struct *owner) +/* + * Return true if rwsem is owned by an anonymous writer or readers. + */ +static inline bool rwsem_has_anonymous_owner(struct task_struct *owner) { - return owner == RWSEM_READER_OWNED; + return (unsigned long)owner & RWSEM_ANONYMOUSLY_OWNED; } #else static inline void rwsem_set_owner(struct rw_semaphore *sem)