From patchwork Wed Dec 6 00:40:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Matthew Wilcox (Oracle)" X-Patchwork-Id: 10094451 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4094160329 for ; Wed, 6 Dec 2017 00:53:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 324A828573 for ; Wed, 6 Dec 2017 00:53:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2712428A27; Wed, 6 Dec 2017 00:53:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D1A0A28573 for ; Wed, 6 Dec 2017 00:53:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753369AbdLFAmO (ORCPT ); Tue, 5 Dec 2017 19:42:14 -0500 Received: from bombadil.infradead.org ([65.50.211.133]:43520 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753125AbdLFAmJ (ORCPT ); Tue, 5 Dec 2017 19:42:09 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=References:In-Reply-To:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=7gmPfR6sEN3OZqX34LT7hoRjNs5dFLccOVO1jiX2ybk=; b=Q7b/BXhwjOPDVvNvoSsSdl3kH cgP2iOXmrKuFru5azsPN/+memUMyG9o67IiEudy0QCEE299tu7aPwJuKOrczDupFJHoLLD6bY21Vq 7KpsEZFr6/ZG8EWWqVD0dIORnILkKqLIs/TACVa1ky1+6JQVYGHuT1zEzR67wxVdO2/FsNNhrOgab Gu28u5hkRTTxhaBcTa5fv61Vo4MN8I4SZ+dQ2bUaEdSKbM82tLY06mMhhihioKzmHWHwUw6DOTNvg Vo03QEWNmN20bNGbgsahBZTr7Pne1E1P3Aa2nRcDdD/NP27hkk4TlLqZTVLEDSlRMgKGOx1hbUe6O sTICpTxgA==; Received: from willy by bombadil.infradead.org with local (Exim 4.87 #1 (Red Hat Linux)) id 1eMNmo-00011o-ST; Wed, 06 Dec 2017 00:42:06 +0000 From: Matthew Wilcox Cc: Matthew Wilcox , Ross Zwisler , Jens Axboe , Rehas Sachdeva , linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-nilfs@vger.kernel.org, linux-btrfs@vger.kernel.org, linux-xfs@vger.kernel.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 12/73] xarray: Add xa_cmpxchg Date: Tue, 5 Dec 2017 16:40:58 -0800 Message-Id: <20171206004159.3755-13-willy@infradead.org> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20171206004159.3755-1-willy@infradead.org> References: <20171206004159.3755-1-willy@infradead.org> To: unlisted-recipients:; (no To-header on input) Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Matthew Wilcox This works like doing cmpxchg() on an array entry. Code which wants the radix_tree_insert() semantic of not overwriting an existing entry can cmpxchg() with NULL and get the action it wants. Plus, instead of having an error returned, they get the value currently stored in the array, which often saves them a subsequent lookup. Signed-off-by: Matthew Wilcox --- include/linux/xarray.h | 2 ++ lib/xarray.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/include/linux/xarray.h b/include/linux/xarray.h index 6f1f55d9fc94..a570d7d9a252 100644 --- a/include/linux/xarray.h +++ b/include/linux/xarray.h @@ -72,6 +72,8 @@ static inline void xa_init(struct xarray *xa) void *xa_load(struct xarray *, unsigned long index); void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t); +void *xa_cmpxchg(struct xarray *, unsigned long index, + void *old, void *entry, gfp_t); /** * xa_erase() - Erase this entry from the XArray. diff --git a/lib/xarray.c b/lib/xarray.c index fbbb02c25b6d..6625b1763123 100644 --- a/lib/xarray.c +++ b/lib/xarray.c @@ -852,6 +852,43 @@ void *xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) } EXPORT_SYMBOL(xa_store); +/** + * xa_cmpxchg() - Conditionally replace an entry in the XArray. + * @xa: XArray. + * @index: Index into array. + * @old: Old value to test against. + * @entry: New value to place in array. + * @gfp: Allocation flags. + * + * If the entry at @index is the same as @old, replace it with @entry. + * If the return value is equal to @old, then the exchange was successful. + * + * Return: The old value at this index or ERR_PTR() if an error happened. + */ +void *xa_cmpxchg(struct xarray *xa, unsigned long index, + void *old, void *entry, gfp_t gfp) +{ + XA_STATE(xas, xa, index); + unsigned long flags; + void *curr; + + if (WARN_ON_ONCE(xa_is_internal(entry))) + return ERR_PTR(-EINVAL); + + do { + xa_lock_irqsave(xa, flags); + curr = xas_create(&xas); + if (curr == old) + xas_store(&xas, entry); + xa_unlock_irqrestore(xa, flags); + } while (xas_nomem(&xas, gfp)); + + if (xas_error(&xas)) + curr = ERR_PTR(xas_error(&xas)); + return curr; +} +EXPORT_SYMBOL(xa_cmpxchg); + /** * __xa_set_tag() - Set this tag on this entry while locked. * @xa: XArray.