Received: by 10.213.65.68 with SMTP id h4csp689imn; Wed, 21 Mar 2018 10:56:49 -0700 (PDT) X-Google-Smtp-Source: AG47ELsKipVb33HmpxAze5D84Ywy4yJat0pnrOzcZo/yUIFvCsBwZBfS9lskBBbj1AMJb+aEGv/u X-Received: by 2002:a17:902:5910:: with SMTP id o16-v6mr4867150pli.258.1521655009609; Wed, 21 Mar 2018 10:56:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521655009; cv=none; d=google.com; s=arc-20160816; b=T/sNK5oUax2HDzzbDsienGgT75brPnN4swkb0vG/UQHktoNjrKDeAdlJ0UergJPiXM o4H9bS+UY/pNzIo1UwnguS9tiCbZBs/BIUDLHdAwvUzj00IoaX4YBg7OAm9nCyPY5coQ mmwwge2UkTOYfJiTuXNXAO3FcGAWSvtIVYIBElMTOolqhwNQb11HBwDlyquCdAXUG1Ot Ustp5YoDI3AofIAK+AmRU6a7vRjChZn8MVJaJgeJ9b4vJhIk6KH0amFWOXtDrTsJMbwd jPE1In9sgO829iCk2KuWGC+G1WO//uA7tsQMwgoCihi1VmdnyEMT3jmh9N1g0zR/ApSO vU7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature:arc-authentication-results; bh=pc/5JQD75Srbm5b9w0NUfLDZBc/5J20egPrTFpg/SOM=; b=ehHXiTJbaNyQmdLJUf6LklJeOWAgtHHzripd6dqSilzW5/weVxLLpZfmdQ/29XNIOA 2i42uMwZhMwT5CdpzmO0s6AJDrGKCtJmyneSyJtpHQfxHREaBKTroDGayjylqMkOntfj eROsZN3ayz/RwH0kC3hdcn3JVsPIF5TYQnwlE8cm7+YD2OKgk/E1ksId5Wf4P2Awgy0l L2A/ZQbM8vkoWaDcZ7BN6vXs+F6dND8jtKieK7wsbv69yPlLfrlcN94KasjAgtZdmQS4 x7dn0ZDQOh1m4PmtzkK0rZHoL+VuO9uvljYf/RT0/xWDEEOZvLp38467SEtRoBV96m4Y ApXA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@infradead.org header.s=bombadil.20170209 header.b=O7QuZlAQ; 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 f15-v6si4275962plr.454.2018.03.21.10.56.34; Wed, 21 Mar 2018 10:56:49 -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; dkim=fail header.i=@infradead.org header.s=bombadil.20170209 header.b=O7QuZlAQ; 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 S1752561AbeCURz1 (ORCPT + 99 others); Wed, 21 Mar 2018 13:55:27 -0400 Received: from bombadil.infradead.org ([198.137.202.133]:39502 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751917AbeCURz0 (ORCPT ); Wed, 21 Mar 2018 13:55:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=In-Reply-To:Content-Type:MIME-Version :References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: 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=pc/5JQD75Srbm5b9w0NUfLDZBc/5J20egPrTFpg/SOM=; b=O7QuZlAQQt0oh6xUCPErDPj4v k5v+p7qqYvhrA+rMuFvzc0upRaXM9M6INp7fsd6Xfa6heRNAiTgchMGiSF8ChUp1SrEMtM96HcNDp F1nwPlltvxJpyGAN1bCAMhQqfTS01WwW7Dtjelmg6SZLoBWj7nJr0ErVRiPGvdqAUpgUS1qh+OA64 0hEtAhStBr3mjv8BxVM/SPrm5hY7xJucSfILZ04lkWDVscUNFrBKyxD44FVEO9mf8LJ1TnTw3rMMX IslW5maIK/Sz2x42ZzvtF3NbJmDSzTM19Qfv/iuSU9Bc2hHuY4puURCOjJxnXH1MLEzSOT2ALyxfa bTIsRMlNQ==; Received: from willy by bombadil.infradead.org with local (Exim 4.90_1 #2 (Red Hat Linux)) id 1eyhws-0002N6-6g; Wed, 21 Mar 2018 17:54:54 +0000 Date: Wed, 21 Mar 2018 10:54:53 -0700 From: Matthew Wilcox To: Kirill Tkhai Cc: viro@zeniv.linux.org.uk, hannes@cmpxchg.org, mhocko@kernel.org, vdavydov.dev@gmail.com, akpm@linux-foundation.org, tglx@linutronix.de, pombredanne@nexb.com, stummala@codeaurora.org, gregkh@linuxfoundation.org, sfr@canb.auug.org.au, guro@fb.com, mka@chromium.org, penguin-kernel@I-love.SAKURA.ne.jp, chris@chris-wilson.co.uk, longman@redhat.com, minchan@kernel.org, hillf.zj@alibaba-inc.com, ying.huang@intel.com, mgorman@techsingularity.net, shakeelb@google.com, jbacik@fb.com, linux@roeck-us.net, linux-kernel@vger.kernel.org, linux-mm@kvack.org Subject: Re: [PATCH 03/10] mm: Assign memcg-aware shrinkers bitmap to memcg Message-ID: <20180321175453.GG4780@bombadil.infradead.org> References: <152163840790.21546.980703278415599202.stgit@localhost.localdomain> <152163850081.21546.6969747084834474733.stgit@localhost.localdomain> <20180321145625.GA4780@bombadil.infradead.org> <20180321152647.GB4780@bombadil.infradead.org> <638887a1-35f8-a71d-6e45-4e779eb62dc4@virtuozzo.com> <20180321162039.GC4780@bombadil.infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.9.2 (2017-12-15) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Mar 21, 2018 at 07:42:38PM +0300, Kirill Tkhai wrote: > On 21.03.2018 19:20, Matthew Wilcox wrote: > >> Sound great, thanks for explaining this. The big problem I see is > >> that IDA/IDR add primitives allocate memory, while they will be used > >> in the places, where they mustn't fail. There is list_lru_add(), and > >> it's called unconditionally in current kernel code. The patchset makes > >> the bitmap be populated in this function. So, we can't use IDR there. > > > > Maybe we can use GFP_NOFAIL here. They're small allocations, so we're > > only asking for single-page allocations to not fail, which shouldn't > > put too much strain on the VM. > > Oh. I'm not sure about this. Even if each allocation is small, there is > theoretically possible a situation, when many lists will want to add first > element. list_lru_add() is called from iput() for example. I see. Maybe we could solve this with an IDA_NO_SHRINK flag and an ida_resize(ida, max); call. You'll also want something like this: diff --git a/include/linux/idr.h b/include/linux/idr.h index 0f650b90ced0..ee7185354fb2 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -273,6 +273,22 @@ static inline void ida_init(struct ida *ida) ida_alloc_range(ida, start, (end) - 1, gfp) #define ida_simple_remove(ida, id) ida_free(ida, id) +int ida_find(struct ida *, unsigned int id); + +/** + * ida_for_each() - Iterate over all allocated IDs. + * @ida: IDA handle. + * @id: Loop cursor. + * + * For each iteration of this loop, @id will be set to an allocated ID. + * No locks are held across the body of the loop, so you can call ida_free() + * if you want or adjust @id to skip IDs or re-process earlier IDs. + * + * On successful loop exit, @id will be less than 0. + */ +#define ida_for_each(ida, i) \ + for (i = ida_find(ida, 0); i >= 0; i = ida_find(ida, i + 1)) + /** * ida_get_new - allocate new ID * @ida: idr handle diff --git a/lib/idr.c b/lib/idr.c index fab3763e8c2a..ba9fae7eb2f5 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -612,3 +612,54 @@ void ida_free(struct ida *ida, unsigned int id) spin_unlock_irqrestore(&simple_ida_lock, flags); } EXPORT_SYMBOL(ida_free); + +/** + * ida_find() - Find an allocated ID. + * @ida: IDA handle. + * @id: Minimum ID to return. + * + * Context: Any context. + * Return: An ID which is at least as large as @id or %-ENOSPC if @id is + * higher than any allocated ID. + */ +int ida_find(struct ida *ida, unsigned int id) +{ + unsigned long flags; + unsigned long index = id / IDA_BITMAP_BITS; + unsigned bit = id % IDA_BITMAP_BITS; + struct ida_bitmap *bitmap; + struct radix_tree_iter iter; + void __rcu **slot; + int ret = -ENOSPC; + + spin_lock_irqsave(&simple_ida_lock, flags); +advance: + slot = radix_tree_iter_find(&ida->ida_rt, &iter, index); + if (!slot) + goto unlock; + bitmap = rcu_dereference_raw(*slot); + if (radix_tree_exception(bitmap)) { + if (bit < (BITS_PER_LONG - RADIX_TREE_EXCEPTIONAL_SHIFT)) { + unsigned long bits = (unsigned long)bitmap; + + bits >>= bit + RADIX_TREE_EXCEPTIONAL_SHIFT; + if (bits) { + bit += __ffs(bits); + goto found; + } + } + } else { + bit = find_next_bit(bitmap->bitmap, IDA_BITMAP_BITS, bit); + if (bit < IDA_BITMAP_BITS) + goto found; + } + bit = 0; + index++; + goto advance; +found: + ret = iter.index * IDA_BITMAP_BITS + bit; +unlock: + spin_unlock_irqrestore(&simple_ida_lock, flags); + return ret; +} +EXPORT_SYMBOL(ida_find); diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 6c645eb77d42..a9b5a33a4ef3 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -358,8 +358,12 @@ void ida_check_conv(void) assert(ida_pre_get(&ida, GFP_KERNEL)); assert(!ida_get_new_above(&ida, i + 1, &id)); assert(id == i + 1); + ida_for_each(&ida, id) + BUG_ON(id != (i + 1)); assert(!ida_get_new_above(&ida, i + BITS_PER_LONG, &id)); assert(id == i + BITS_PER_LONG); + ida_for_each(&ida, id) + BUG_ON((id != (i + 1)) && (id != (i + BITS_PER_LONG))); ida_remove(&ida, i + 1); ida_remove(&ida, i + BITS_PER_LONG); assert(ida_is_empty(&ida)); @@ -484,7 +488,7 @@ void ida_simple_get_remove_test(void) void ida_checks(void) { DEFINE_IDA(ida); - int id; + int id, id2; unsigned long i; radix_tree_cpu_dead(1); @@ -496,8 +500,22 @@ void ida_checks(void) assert(id == i); } + id2 = 0; + ida_for_each(&ida, id) { + BUG_ON(id != id2++); + } + BUG_ON(id >= 0); + BUG_ON(id2 != 10000); + ida_remove(&ida, 20); ida_remove(&ida, 21); + id2 = 0; + ida_for_each(&ida, id) { + if (id != id2++) { + BUG_ON(id != 22 || id2 != 21); + id2 = 23; + } + } for (i = 0; i < 3; i++) { assert(ida_pre_get(&ida, GFP_KERNEL)); assert(!ida_get_new(&ida, &id));