From patchwork Wed Nov 22 21:07:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Wilcox X-Patchwork-Id: 10071195 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 7C44760353 for ; Wed, 22 Nov 2017 21:22:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6E38E29D96 for ; Wed, 22 Nov 2017 21:22:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 62CB729DA4; Wed, 22 Nov 2017 21:22:18 +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 E9D1729D96 for ; Wed, 22 Nov 2017 21:22:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751987AbdKVVVe (ORCPT ); Wed, 22 Nov 2017 16:21:34 -0500 Received: from bombadil.infradead.org ([65.50.211.133]:48825 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751753AbdKVVIR (ORCPT ); Wed, 22 Nov 2017 16:08:17 -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=2O16qYC/aU9VgbdRcLYGP4mA/6hPCkVRTW7qVa93Ypo=; b=lVDjqxbn4OFtlRg/UCIxfXRoK BKve9DTHQUhnCMkub1Et8n6a617UvoqbigY9QGzeKgxvHnt0pbGq1ZjgneW88GNjiIwVRTZ2/yWJQ mJ0l8w2H/uBATQsRflaQn1iA3hm/Vn1V5vwE4K3QAmuyaS3tP/ZRb2KsdIGMk08zEfHFBcTWRVF3r uV1wN1upBVg2pRwdpjAvtlUj6LD01d/nvuY1dzWmRtPU7eFUGA9ClJDK3hH27MrqAYJ896XSrkE/c vOhf3BQ4FmuMbBpWaXqNJBCRN3jOL+PLS32zBpppODl3P9l2AVZkyY3MSMBfxMCG0beDLB5W9t9p9 XRKWZR/KA==; Received: from willy by bombadil.infradead.org with local (Exim 4.87 #1 (Red Hat Linux)) id 1eHcFl-0007tw-Gg; Wed, 22 Nov 2017 21:08:17 +0000 From: Matthew Wilcox To: linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org Cc: Matthew Wilcox Subject: [PATCH 23/62] xarray: Add xa_cmpxchg Date: Wed, 22 Nov 2017 13:07:00 -0800 Message-Id: <20171122210739.29916-24-willy@infradead.org> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20171122210739.29916-1-willy@infradead.org> References: <20171122210739.29916-1-willy@infradead.org> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@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 | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/linux/xarray.h b/include/linux/xarray.h index 5e975c512018..274dd7530e40 100644 --- a/include/linux/xarray.h +++ b/include/linux/xarray.h @@ -83,6 +83,8 @@ struct xarray { 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_empty() - Determine if an array has any present entries diff --git a/lib/xarray.c b/lib/xarray.c index a3f4f4ab673f..82f39d86fc76 100644 --- a/lib/xarray.c +++ b/lib/xarray.c @@ -818,6 +818,44 @@ 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, 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(xa, &xas); + if (curr == old) + xas_store(xa, &xas, entry); + xa_unlock_irqrestore(xa, flags); + } while (xas_nomem(&xas, gfp)); + xas_destroy(&xas); + + 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. * @xa: XArray.