From: Dave Chinner <david@fromorbit.com>
To: Qi Zheng <zhengqi.arch@bytedance.com>
Cc: akpm@linux-foundation.org, tkhai@ya.ru, vbabka@suse.cz,
roman.gushchin@linux.dev, djwong@kernel.org, brauner@kernel.org,
paulmck@kernel.org, tytso@mit.edu, steven.price@arm.com,
cel@kernel.org, senozhatsky@chromium.org, yujie.liu@intel.com,
gregkh@linuxfoundation.org, muchun.song@linux.dev,
linux-kernel@vger.kernel.org, linux-mm@kvack.org, x86@kernel.org,
kvm@vger.kernel.org, xen-devel@lists.xenproject.org,
linux-erofs@lists.ozlabs.org,
linux-f2fs-devel@lists.sourceforge.net, cluster-devel@redhat.com,
linux-nfs@vger.kernel.org, linux-mtd@lists.infradead.org,
rcu@vger.kernel.org, netdev@vger.kernel.org,
dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org,
dm-devel@redhat.com, linux-raid@vger.kernel.org,
linux-bcache@vger.kernel.org,
virtualization@lists.linux-foundation.org,
linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org,
linux-xfs@vger.kernel.org, linux-btrfs@vger.kernel.org
Subject: Re: [PATCH v2 44/47] mm: shrinker: make global slab shrink lockless
Date: Wed, 26 Jul 2023 18:08:50 +1000 [thread overview]
Message-ID: <ZMDUkoIXUlTkCSYL@dread.disaster.area> (raw)
In-Reply-To: <20230724094354.90817-45-zhengqi.arch@bytedance.com>
On Mon, Jul 24, 2023 at 05:43:51PM +0800, Qi Zheng wrote:
> The shrinker_rwsem is a global read-write lock in shrinkers subsystem,
> which protects most operations such as slab shrink, registration and
> unregistration of shrinkers, etc. This can easily cause problems in the
> following cases.
>
> 1) When the memory pressure is high and there are many filesystems
> mounted or unmounted at the same time, slab shrink will be affected
> (down_read_trylock() failed).
>
> Such as the real workload mentioned by Kirill Tkhai:
>
> ```
> One of the real workloads from my experience is start
> of an overcommitted node containing many starting
> containers after node crash (or many resuming containers
> after reboot for kernel update). In these cases memory
> pressure is huge, and the node goes round in long reclaim.
> ```
>
> 2) If a shrinker is blocked (such as the case mentioned
> in [1]) and a writer comes in (such as mount a fs),
> then this writer will be blocked and cause all
> subsequent shrinker-related operations to be blocked.
>
> Even if there is no competitor when shrinking slab, there may still be a
> problem. The down_read_trylock() may become a perf hotspot with frequent
> calls to shrink_slab(). Because of the poor multicore scalability of
> atomic operations, this can lead to a significant drop in IPC
> (instructions per cycle).
>
> We used to implement the lockless slab shrink with SRCU [2], but then
> kernel test robot reported -88.8% regression in
> stress-ng.ramfs.ops_per_sec test case [3], so we reverted it [4].
>
> This commit uses the refcount+RCU method [5] proposed by Dave Chinner
> to re-implement the lockless global slab shrink. The memcg slab shrink is
> handled in the subsequent patch.
>
> For now, all shrinker instances are converted to dynamically allocated and
> will be freed by kfree_rcu(). So we can use rcu_read_{lock,unlock}() to
> ensure that the shrinker instance is valid.
>
> And the shrinker instance will not be run again after unregistration. So
> the structure that records the pointer of shrinker instance can be safely
> freed without waiting for the RCU read-side critical section.
>
> In this way, while we implement the lockless slab shrink, we don't need to
> be blocked in unregister_shrinker().
>
> The following are the test results:
>
> stress-ng --timeout 60 --times --verify --metrics-brief --ramfs 9 &
>
> 1) Before applying this patchset:
>
> setting to a 60 second run per stressor
> dispatching hogs: 9 ramfs
> stressor bogo ops real time usr time sys time bogo ops/s bogo ops/s
> (secs) (secs) (secs) (real time) (usr+sys time)
> ramfs 735238 60.00 12.37 363.70 12253.05 1955.08
> for a 60.01s run time:
> 1440.27s available CPU time
> 12.36s user time ( 0.86%)
> 363.70s system time ( 25.25%)
> 376.06s total time ( 26.11%)
> load average: 10.79 4.47 1.69
> passed: 9: ramfs (9)
> failed: 0
> skipped: 0
> successful run completed in 60.01s (1 min, 0.01 secs)
>
> 2) After applying this patchset:
>
> setting to a 60 second run per stressor
> dispatching hogs: 9 ramfs
> stressor bogo ops real time usr time sys time bogo ops/s bogo ops/s
> (secs) (secs) (secs) (real time) (usr+sys time)
> ramfs 746677 60.00 12.22 367.75 12443.70 1965.13
> for a 60.01s run time:
> 1440.26s available CPU time
> 12.21s user time ( 0.85%)
> 367.75s system time ( 25.53%)
> 379.96s total time ( 26.38%)
> load average: 8.37 2.48 0.86
> passed: 9: ramfs (9)
> failed: 0
> skipped: 0
> successful run completed in 60.01s (1 min, 0.01 secs)
>
> We can see that the ops/s has hardly changed.
>
> [1]. https://lore.kernel.org/lkml/20191129214541.3110-1-ptikhomirov@virtuozzo.com/
> [2]. https://lore.kernel.org/lkml/20230313112819.38938-1-zhengqi.arch@bytedance.com/
> [3]. https://lore.kernel.org/lkml/202305230837.db2c233f-yujie.liu@intel.com/
> [4]. https://lore.kernel.org/all/20230609081518.3039120-1-qi.zheng@linux.dev/
> [5]. https://lore.kernel.org/lkml/ZIJhou1d55d4H1s0@dread.disaster.area/
>
> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
> ---
> include/linux/shrinker.h | 19 +++++++---
> mm/shrinker.c | 75 ++++++++++++++++++++++++++--------------
> mm/shrinker_debug.c | 52 +++++++++++++++++++++-------
> 3 files changed, 104 insertions(+), 42 deletions(-)
>
> diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h
> index 36977a70bebb..335da93cccee 100644
> --- a/include/linux/shrinker.h
> +++ b/include/linux/shrinker.h
> @@ -4,6 +4,7 @@
>
> #include <linux/atomic.h>
> #include <linux/types.h>
> +#include <linux/refcount.h>
>
> #define SHRINKER_UNIT_BITS BITS_PER_LONG
>
> @@ -86,6 +87,10 @@ struct shrinker {
> long batch; /* reclaim batch size, 0 = default */
> int seeks; /* seeks to recreate an obj */
> unsigned flags;
> + bool registered;
> +
> + refcount_t refcount;
> + struct rcu_head rcu;
>
> void *private_data;
>
> @@ -106,14 +111,13 @@ struct shrinker {
> #define DEFAULT_SEEKS 2 /* A good number if you don't know better. */
>
> /* Flags */
> -#define SHRINKER_REGISTERED (1 << 0)
> -#define SHRINKER_NUMA_AWARE (1 << 1)
> -#define SHRINKER_MEMCG_AWARE (1 << 2)
> +#define SHRINKER_NUMA_AWARE (1 << 0)
> +#define SHRINKER_MEMCG_AWARE (1 << 1)
> /*
> * It just makes sense when the shrinker is also MEMCG_AWARE for now,
> * non-MEMCG_AWARE shrinker should not have this flag set.
> */
> -#define SHRINKER_NONSLAB (1 << 3)
> +#define SHRINKER_NONSLAB (1 << 2)
>
> unsigned long shrink_slab(gfp_t gfp_mask, int nid, struct mem_cgroup *memcg,
> int priority);
> @@ -122,6 +126,13 @@ void shrinker_free_non_registered(struct shrinker *shrinker);
> void shrinker_register(struct shrinker *shrinker);
> void shrinker_unregister(struct shrinker *shrinker);
>
> +static inline bool shrinker_try_get(struct shrinker *shrinker)
> +{
> + return READ_ONCE(shrinker->registered) &&
> + refcount_inc_not_zero(&shrinker->refcount);
> +}
Why do we care about shrinker->registered here? If we don't set
the refcount to 1 until we have fully initialised everything, then
the shrinker code can key entirely off the reference count and
none of the lookup code needs to care about whether the shrinker is
registered or not.
> +void shrinker_put(struct shrinker *shrinker);
> +
> #ifdef CONFIG_SHRINKER_DEBUG
> extern int shrinker_debugfs_add(struct shrinker *shrinker);
> extern struct dentry *shrinker_debugfs_detach(struct shrinker *shrinker,
> diff --git a/mm/shrinker.c b/mm/shrinker.c
> index 8a1fe844f1a4..8e3334749552 100644
> --- a/mm/shrinker.c
> +++ b/mm/shrinker.c
> @@ -2,10 +2,13 @@
> #include <linux/memcontrol.h>
> #include <linux/rwsem.h>
> #include <linux/shrinker.h>
> +#include <linux/rculist.h>
> +#include <linux/spinlock.h>
> #include <trace/events/vmscan.h>
>
> LIST_HEAD(shrinker_list);
> DECLARE_RWSEM(shrinker_rwsem);
> +DEFINE_SPINLOCK(shrinker_lock);
>
> #ifdef CONFIG_MEMCG
> static int shrinker_nr_max;
> @@ -450,6 +453,18 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
> return freed;
> }
>
> +void shrinker_put(struct shrinker *shrinker)
> +{
> + if (refcount_dec_and_test(&shrinker->refcount)) {
> + spin_lock(&shrinker_lock);
> + list_del_rcu(&shrinker->list);
> + spin_unlock(&shrinker_lock);
> +
> + kfree(shrinker->nr_deferred);
> + kfree_rcu(shrinker, rcu);
> + }
> +}
Urk, no.
We want the shrinker_free() code to block waiting for the shrinker
reference count to go to zero, because the shrinkers can reference
structures that are associated with the path that is freeing the
shrinker.
i.e. we do not want to free the superblock of a filesystem whilst
the shrinker is still running, but the way you've done this is that
the shrinker can run whilst the structure that contains it has been
torn down.
This should use a completion, then it is always safe under
rcu_read_lock(). This also gets rid of the shrinker_lock spin lock,
which only exists because we can't take a blocking lock under
rcu_read_lock(). i.e:
void shrinker_put(struct shrinker *shrinker)
{
if (refcount_dec_and_test(&shrinker->refcount))
complete(&shrinker->done);
}
void shrinker_free()
{
.....
refcount_dec(&shrinker->refcount);
wait_for_completion(&shrinker->done);
/*
* lookups on the shrinker will now all fail as refcount has
* fallen to zero. We can now remove it from the lists and
* free it.
*/
down_write(shrinker_rwsem);
list_del_rcu(&shrinker->list);
up_write(&shrinker_rwsem);
call_rcu(shrinker->rcu_head, shrinker_free_rcu_cb);
}
....
> @@ -686,11 +711,14 @@ EXPORT_SYMBOL(shrinker_free_non_registered);
>
> void shrinker_register(struct shrinker *shrinker)
> {
> - down_write(&shrinker_rwsem);
> - list_add_tail(&shrinker->list, &shrinker_list);
> - shrinker->flags |= SHRINKER_REGISTERED;
> + refcount_set(&shrinker->refcount, 1);
> +
> + spin_lock(&shrinker_lock);
> + list_add_tail_rcu(&shrinker->list, &shrinker_list);
> + spin_unlock(&shrinker_lock);
> +
> shrinker_debugfs_add(shrinker);
> - up_write(&shrinker_rwsem);
> + WRITE_ONCE(shrinker->registered, true);
> }
> EXPORT_SYMBOL(shrinker_register);
This just looks wrong - you are trying to use WRITE_ONCE() as a
release barrier to indicate that the shrinker is now set up fully.
That's not necessary - the refcount is an atomic and along with the
rcu locks they should provides all the barriers we need. i.e.
void shrinker_register(struct shrinker *shrinker)
{
down_write(&shrinker_rwsem);
list_add_tail_rcu(&shrinker->list, &shrinker_list);
shrinker->flags |= SHRINKER_REGISTERED;
shrinker_debugfs_add(shrinker);
up_write(&shrinker_rwsem);
/*
* now the shrinker is fully set up, take the first
* reference to it to indicate that lookup operations are
* now allowed to use it via shrinker_try_get().
*/
refcount_set(&shrinker->refcount, 1);
}
> diff --git a/mm/shrinker_debug.c b/mm/shrinker_debug.c
> index f1becfd45853..c5573066adbf 100644
> --- a/mm/shrinker_debug.c
> +++ b/mm/shrinker_debug.c
> @@ -5,6 +5,7 @@
> #include <linux/seq_file.h>
> #include <linux/shrinker.h>
> #include <linux/memcontrol.h>
> +#include <linux/rculist.h>
>
> /* defined in vmscan.c */
> extern struct rw_semaphore shrinker_rwsem;
> @@ -161,17 +162,21 @@ int shrinker_debugfs_add(struct shrinker *shrinker)
> {
> struct dentry *entry;
> char buf[128];
> - int id;
> -
> - lockdep_assert_held(&shrinker_rwsem);
> + int id, ret = 0;
>
> /* debugfs isn't initialized yet, add debugfs entries later. */
> if (!shrinker_debugfs_root)
> return 0;
>
> + down_write(&shrinker_rwsem);
> + if (shrinker->debugfs_entry)
> + goto fail;
> +
> id = ida_alloc(&shrinker_debugfs_ida, GFP_KERNEL);
> - if (id < 0)
> - return id;
> + if (id < 0) {
> + ret = id;
> + goto fail;
> + }
> shrinker->debugfs_id = id;
>
> snprintf(buf, sizeof(buf), "%s-%d", shrinker->name, id);
> @@ -180,7 +185,8 @@ int shrinker_debugfs_add(struct shrinker *shrinker)
> entry = debugfs_create_dir(buf, shrinker_debugfs_root);
> if (IS_ERR(entry)) {
> ida_free(&shrinker_debugfs_ida, id);
> - return PTR_ERR(entry);
> + ret = PTR_ERR(entry);
> + goto fail;
> }
> shrinker->debugfs_entry = entry;
>
> @@ -188,7 +194,10 @@ int shrinker_debugfs_add(struct shrinker *shrinker)
> &shrinker_debugfs_count_fops);
> debugfs_create_file("scan", 0220, entry, shrinker,
> &shrinker_debugfs_scan_fops);
> - return 0;
> +
> +fail:
> + up_write(&shrinker_rwsem);
> + return ret;
> }
>
> int shrinker_debugfs_rename(struct shrinker *shrinker, const char *fmt, ...)
> @@ -243,6 +252,11 @@ struct dentry *shrinker_debugfs_detach(struct shrinker *shrinker,
> shrinker->name = NULL;
>
> *debugfs_id = entry ? shrinker->debugfs_id : -1;
> + /*
> + * Ensure that shrinker->registered has been set to false before
> + * shrinker->debugfs_entry is set to NULL.
> + */
> + smp_wmb();
> shrinker->debugfs_entry = NULL;
>
> return entry;
> @@ -266,14 +280,26 @@ static int __init shrinker_debugfs_init(void)
> shrinker_debugfs_root = dentry;
>
> /* Create debugfs entries for shrinkers registered at boot */
> - down_write(&shrinker_rwsem);
> - list_for_each_entry(shrinker, &shrinker_list, list)
> + rcu_read_lock();
> + list_for_each_entry_rcu(shrinker, &shrinker_list, list) {
> + if (!shrinker_try_get(shrinker))
> + continue;
> + rcu_read_unlock();
> +
> if (!shrinker->debugfs_entry) {
> - ret = shrinker_debugfs_add(shrinker);
> - if (ret)
> - break;
> + /* Paired with smp_wmb() in shrinker_debugfs_detach() */
> + smp_rmb();
> + if (READ_ONCE(shrinker->registered))
> + ret = shrinker_debugfs_add(shrinker);
> }
> - up_write(&shrinker_rwsem);
> +
> + rcu_read_lock();
> + shrinker_put(shrinker);
> +
> + if (ret)
> + break;
> + }
> + rcu_read_unlock();
>
> return ret;
> }
And all this churn and complexity can go away because the
shrinker_rwsem is still used to protect shrinker_register()
entirely....
-Dave.
--
Dave Chinner
david@fromorbit.com
next prev parent reply other threads:[~2023-07-26 8:20 UTC|newest]
Thread overview: 110+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-24 9:43 [PATCH v2 00/47] use refcount+RCU method to implement lockless slab shrink Qi Zheng
2023-07-24 9:43 ` [PATCH v2 01/47] mm: vmscan: move shrinker-related code into a separate file Qi Zheng
2023-07-25 2:35 ` Muchun Song
2023-07-25 3:09 ` Qi Zheng
2023-07-25 3:23 ` Muchun Song
2023-07-25 3:27 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 02/47] mm: shrinker: remove redundant shrinker_rwsem in debugfs operations Qi Zheng
2023-07-25 3:17 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 03/47] mm: shrinker: add infrastructure for dynamically allocating shrinker Qi Zheng
2023-07-24 12:25 ` Peter Zijlstra
2023-07-25 3:01 ` Qi Zheng
2023-07-25 9:02 ` Muchun Song
2023-07-25 9:56 ` Qi Zheng
2023-07-26 7:26 ` Dave Chinner
2023-07-26 9:20 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 04/47] kvm: mmu: dynamically allocate the x86-mmu shrinker Qi Zheng
2023-07-25 9:16 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 05/47] binder: dynamically allocate the android-binder shrinker Qi Zheng
2023-07-24 9:56 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 06/47] drm/ttm: dynamically allocate the drm-ttm_pool shrinker Qi Zheng
2023-07-25 9:19 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 07/47] xenbus/backend: dynamically allocate the xen-backend shrinker Qi Zheng
2023-07-25 9:22 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 08/47] erofs: dynamically allocate the erofs-shrinker Qi Zheng
2023-07-25 9:24 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 09/47] f2fs: dynamically allocate the f2fs-shrinker Qi Zheng
2023-07-25 9:25 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 10/47] gfs2: dynamically allocate the gfs2-glock shrinker Qi Zheng
2023-07-26 6:43 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 11/47] gfs2: dynamically allocate the gfs2-qd shrinker Qi Zheng
2023-07-26 6:49 ` Muchun Song
2023-07-26 9:22 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 12/47] NFSv4.2: dynamically allocate the nfs-xattr shrinkers Qi Zheng
2023-07-26 6:55 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 13/47] nfs: dynamically allocate the nfs-acl shrinker Qi Zheng
2023-07-26 6:57 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 14/47] nfsd: dynamically allocate the nfsd-filecache shrinker Qi Zheng
2023-07-26 6:59 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 15/47] quota: dynamically allocate the dquota-cache shrinker Qi Zheng
2023-07-26 6:59 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 16/47] ubifs: dynamically allocate the ubifs-slab shrinker Qi Zheng
2023-07-26 7:00 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 17/47] rcu: dynamically allocate the rcu-lazy shrinker Qi Zheng
2023-07-26 7:04 ` Muchun Song
2023-07-26 9:24 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 18/47] rcu: dynamically allocate the rcu-kfree shrinker Qi Zheng
2023-07-26 7:05 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 19/47] mm: thp: dynamically allocate the thp-related shrinkers Qi Zheng
2023-07-26 7:10 ` Muchun Song
2023-07-26 9:27 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 20/47] sunrpc: dynamically allocate the sunrpc_cred shrinker Qi Zheng
2023-07-26 7:11 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 21/47] mm: workingset: dynamically allocate the mm-shadow shrinker Qi Zheng
2023-07-26 7:13 ` Muchun Song
2023-07-26 9:28 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 22/47] drm/i915: dynamically allocate the i915_gem_mm shrinker Qi Zheng
2023-07-26 7:15 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 23/47] drm/msm: dynamically allocate the drm-msm_gem shrinker Qi Zheng
2023-07-26 7:24 ` Muchun Song
2023-07-26 9:31 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 24/47] drm/panfrost: dynamically allocate the drm-panfrost shrinker Qi Zheng
2023-07-24 11:17 ` Steven Price
2023-07-25 3:05 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 25/47] dm: dynamically allocate the dm-bufio shrinker Qi Zheng
2023-07-26 7:24 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 26/47] dm zoned: dynamically allocate the dm-zoned-meta shrinker Qi Zheng
2023-07-26 7:25 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 27/47] md/raid5: dynamically allocate the md-raid5 shrinker Qi Zheng
2023-07-26 7:27 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 28/47] bcache: dynamically allocate the md-bcache shrinker Qi Zheng
2023-07-26 7:32 ` Muchun Song
2023-07-26 9:33 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 29/47] vmw_balloon: dynamically allocate the vmw-balloon shrinker Qi Zheng
2023-07-26 7:35 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 30/47] virtio_balloon: dynamically allocate the virtio-balloon shrinker Qi Zheng
2023-07-26 7:36 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 31/47] mbcache: dynamically allocate the mbcache shrinker Qi Zheng
2023-07-26 7:39 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 32/47] ext4: dynamically allocate the ext4-es shrinker Qi Zheng
2023-07-26 7:40 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 33/47] jbd2,ext4: dynamically allocate the jbd2-journal shrinker Qi Zheng
2023-07-26 7:41 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 34/47] nfsd: dynamically allocate the nfsd-client shrinker Qi Zheng
2023-07-24 12:17 ` Jeff Layton
2023-07-24 9:43 ` [PATCH v2 35/47] nfsd: dynamically allocate the nfsd-reply shrinker Qi Zheng
2023-07-24 12:17 ` Jeff Layton
2023-07-24 9:43 ` [PATCH v2 36/47] xfs: dynamically allocate the xfs-buf shrinker Qi Zheng
2023-07-26 7:42 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 37/47] xfs: dynamically allocate the xfs-inodegc shrinker Qi Zheng
2023-07-26 7:42 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 38/47] xfs: dynamically allocate the xfs-qm shrinker Qi Zheng
2023-07-26 7:43 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 39/47] zsmalloc: dynamically allocate the mm-zspool shrinker Qi Zheng
2023-07-26 7:43 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 40/47] fs: super: dynamically allocate the s_shrink Qi Zheng
2023-07-26 7:45 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 41/47] mm: shrinker: remove old APIs Qi Zheng
2023-07-26 7:46 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 42/47] drm/ttm: introduce pool_shrink_rwsem Qi Zheng
2023-07-26 7:56 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 43/47] mm: shrinker: add a secondary array for shrinker_info::{map, nr_deferred} Qi Zheng
2023-07-26 9:30 ` Muchun Song
2023-07-24 9:43 ` [PATCH v2 44/47] mm: shrinker: make global slab shrink lockless Qi Zheng
2023-07-26 8:08 ` Dave Chinner [this message]
2023-07-26 9:14 ` Qi Zheng
2023-07-26 23:09 ` Dave Chinner
2023-07-27 3:34 ` Qi Zheng
2023-07-24 9:43 ` [PATCH v2 45/47] mm: shrinker: make memcg " Qi Zheng
2023-07-24 9:43 ` [PATCH v2 46/47] mm: shrinker: hold write lock to reparent shrinker nr_deferred Qi Zheng
2023-07-24 9:43 ` [PATCH v2 47/47] mm: shrinker: convert shrinker_rwsem to mutex Qi Zheng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZMDUkoIXUlTkCSYL@dread.disaster.area \
--to=david@fromorbit.com \
--cc=akpm@linux-foundation.org \
--cc=brauner@kernel.org \
--cc=cel@kernel.org \
--cc=cluster-devel@redhat.com \
--cc=djwong@kernel.org \
--cc=dm-devel@redhat.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=gregkh@linuxfoundation.org \
--cc=kvm@vger.kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-bcache@vger.kernel.org \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-erofs@lists.ozlabs.org \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-f2fs-devel@lists.sourceforge.net \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-mtd@lists.infradead.org \
--cc=linux-nfs@vger.kernel.org \
--cc=linux-raid@vger.kernel.org \
--cc=linux-xfs@vger.kernel.org \
--cc=muchun.song@linux.dev \
--cc=netdev@vger.kernel.org \
--cc=paulmck@kernel.org \
--cc=rcu@vger.kernel.org \
--cc=roman.gushchin@linux.dev \
--cc=senozhatsky@chromium.org \
--cc=steven.price@arm.com \
--cc=tkhai@ya.ru \
--cc=tytso@mit.edu \
--cc=vbabka@suse.cz \
--cc=virtualization@lists.linux-foundation.org \
--cc=x86@kernel.org \
--cc=xen-devel@lists.xenproject.org \
--cc=yujie.liu@intel.com \
--cc=zhengqi.arch@bytedance.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).