linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: akpm@linux-foundation.org, ddstreet@ieee.org, linux-mm@kvack.org,
	mm-commits@vger.kernel.org, torvalds@linux-foundation.org,
	vitaly.wool@konsulko.com
Subject: [patch 073/118] mm/zswap.c: add allocation hysteresis if pool limit is hit
Date: Thu, 30 Jan 2020 22:15:04 -0800	[thread overview]
Message-ID: <20200131061504._6iRRJ82s%akpm@linux-foundation.org> (raw)
In-Reply-To: <20200130221021.5f0211c56346d5485af07923@linux-foundation.org>

From: Vitaly Wool <vitaly.wool@konsulko.com>
Subject: mm/zswap.c: add allocation hysteresis if pool limit is hit

zswap will always try to shrink pool when zswap is full.  If there is a
high pressure on zswap it will result in flipping pages in and out zswap
pool without any real benefit, and the overall system performance will
drop.  The previous discussion on this subject [1] ended up with a
suggestion to implement a sort of hysteresis to refuse taking pages into
zswap pool until it has sufficient space if the limit has been hit.  This
is my take on this.

Hysteresis is controlled with a sysfs-configurable parameter (namely,
/sys/kernel/debug/zswap/accept_threhsold_percent).  It specifies the
threshold at which zswap would start accepting pages again after it became
full.  Setting this parameter to 100 disables the hysteresis and sets the
zswap behavior to pre-hysteresis state.

[1] https://lkml.org/lkml/2019/11/8/949

Link: http://lkml.kernel.org/r/20200108200118.15563-1-vitaly.wool@konsulko.com
Signed-off-by: Vitaly Wool <vitaly.wool@konsulko.com>
Cc: Dan Streetman <ddstreet@ieee.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 Documentation/vm/zswap.rst |   13 +++++
 mm/zswap.c                 |   85 ++++++++++++++++++++++-------------
 2 files changed, 67 insertions(+), 31 deletions(-)

--- a/Documentation/vm/zswap.rst~zswap-add-allocation-hysteresis-if-pool-limit-is-hit
+++ a/Documentation/vm/zswap.rst
@@ -130,6 +130,19 @@ checking for the same-value filled pages
 existing pages which are marked as same-value filled pages remain stored
 unchanged in zswap until they are either loaded or invalidated.
 
+To prevent zswap from shrinking pool when zswap is full and there's a high
+pressure on swap (this will result in flipping pages in and out zswap pool
+without any real benefit but with a performance drop for the system), a
+special parameter has been introduced to implement a sort of hysteresis to
+refuse taking pages into zswap pool until it has sufficient space if the limit
+has been hit. To set the threshold at which zswap would start accepting pages
+again after it became full, use the sysfs ``accept_threhsold_percent``
+attribute, e. g.::
+
+	echo 80 > /sys/module/zswap/parameters/accept_threhsold_percent
+
+Setting this parameter to 100 will disable the hysteresis.
+
 A debugfs interface is provided for various statistic about pool size, number
 of pages stored, same-value filled pages and various counters for the reasons
 pages are rejected.
--- a/mm/zswap.c~zswap-add-allocation-hysteresis-if-pool-limit-is-hit
+++ a/mm/zswap.c
@@ -32,6 +32,7 @@
 #include <linux/swapops.h>
 #include <linux/writeback.h>
 #include <linux/pagemap.h>
+#include <linux/workqueue.h>
 
 /*********************************
 * statistics
@@ -65,6 +66,11 @@ static u64 zswap_reject_kmemcache_fail;
 /* Duplicate store was encountered (rare) */
 static u64 zswap_duplicate_entry;
 
+/* Shrinker work queue */
+static struct workqueue_struct *shrink_wq;
+/* Pool limit was hit, we need to calm down */
+static bool zswap_pool_reached_full;
+
 /*********************************
 * tunables
 **********************************/
@@ -109,6 +115,11 @@ module_param_cb(zpool, &zswap_zpool_para
 static unsigned int zswap_max_pool_percent = 20;
 module_param_named(max_pool_percent, zswap_max_pool_percent, uint, 0644);
 
+/* The threshold for accepting new pages after the max_pool_percent was hit */
+static unsigned int zswap_accept_thr_percent = 90; /* of max pool size */
+module_param_named(accept_threshold_percent, zswap_accept_thr_percent,
+		   uint, 0644);
+
 /* Enable/disable handling same-value filled pages (enabled by default) */
 static bool zswap_same_filled_pages_enabled = true;
 module_param_named(same_filled_pages_enabled, zswap_same_filled_pages_enabled,
@@ -123,7 +134,8 @@ struct zswap_pool {
 	struct crypto_comp * __percpu *tfm;
 	struct kref kref;
 	struct list_head list;
-	struct work_struct work;
+	struct work_struct release_work;
+	struct work_struct shrink_work;
 	struct hlist_node node;
 	char tfm_name[CRYPTO_MAX_ALG_NAME];
 };
@@ -214,6 +226,13 @@ static bool zswap_is_full(void)
 			DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE);
 }
 
+static bool zswap_can_accept(void)
+{
+	return totalram_pages() * zswap_accept_thr_percent / 100 *
+				zswap_max_pool_percent / 100 >
+			DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE);
+}
+
 static void zswap_update_total_size(void)
 {
 	struct zswap_pool *pool;
@@ -501,6 +520,16 @@ static struct zswap_pool *zswap_pool_fin
 	return NULL;
 }
 
+static void shrink_worker(struct work_struct *w)
+{
+	struct zswap_pool *pool = container_of(w, typeof(*pool),
+						shrink_work);
+
+	if (zpool_shrink(pool->zpool, 1, NULL))
+		zswap_reject_reclaim_fail++;
+	zswap_pool_put(pool);
+}
+
 static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
 {
 	struct zswap_pool *pool;
@@ -551,6 +580,7 @@ static struct zswap_pool *zswap_pool_cre
 	 */
 	kref_init(&pool->kref);
 	INIT_LIST_HEAD(&pool->list);
+	INIT_WORK(&pool->shrink_work, shrink_worker);
 
 	zswap_pool_debug("created", pool);
 
@@ -624,7 +654,8 @@ static int __must_check zswap_pool_get(s
 
 static void __zswap_pool_release(struct work_struct *work)
 {
-	struct zswap_pool *pool = container_of(work, typeof(*pool), work);
+	struct zswap_pool *pool = container_of(work, typeof(*pool),
+						release_work);
 
 	synchronize_rcu();
 
@@ -647,8 +678,8 @@ static void __zswap_pool_empty(struct kr
 
 	list_del_rcu(&pool->list);
 
-	INIT_WORK(&pool->work, __zswap_pool_release);
-	schedule_work(&pool->work);
+	INIT_WORK(&pool->release_work, __zswap_pool_release);
+	schedule_work(&pool->release_work);
 
 	spin_unlock(&zswap_pools_lock);
 }
@@ -942,22 +973,6 @@ end:
 	return ret;
 }
 
-static int zswap_shrink(void)
-{
-	struct zswap_pool *pool;
-	int ret;
-
-	pool = zswap_pool_last_get();
-	if (!pool)
-		return -ENOENT;
-
-	ret = zpool_shrink(pool->zpool, 1, NULL);
-
-	zswap_pool_put(pool);
-
-	return ret;
-}
-
 static int zswap_is_page_same_filled(void *ptr, unsigned long *value)
 {
 	unsigned int pos;
@@ -1011,21 +1026,23 @@ static int zswap_frontswap_store(unsigne
 
 	/* reclaim space if needed */
 	if (zswap_is_full()) {
+		struct zswap_pool *pool;
+
 		zswap_pool_limit_hit++;
-		if (zswap_shrink()) {
-			zswap_reject_reclaim_fail++;
-			ret = -ENOMEM;
-			goto reject;
-		}
+		zswap_pool_reached_full = true;
+		pool = zswap_pool_last_get();
+		if (pool)
+			queue_work(shrink_wq, &pool->shrink_work);
+		ret = -ENOMEM;
+		goto reject;
+	}
 
-		/* A second zswap_is_full() check after
-		 * zswap_shrink() to make sure it's now
-		 * under the max_pool_percent
-		 */
-		if (zswap_is_full()) {
+	if (zswap_pool_reached_full) {
+	       if (!zswap_can_accept()) {
 			ret = -ENOMEM;
 			goto reject;
-		}
+		} else
+			zswap_pool_reached_full = false;
 	}
 
 	/* allocate entry */
@@ -1332,11 +1349,17 @@ static int __init init_zswap(void)
 		zswap_enabled = false;
 	}
 
+	shrink_wq = create_workqueue("zswap-shrink");
+	if (!shrink_wq)
+		goto fallback_fail;
+
 	frontswap_register_ops(&zswap_frontswap_ops);
 	if (zswap_debugfs_init())
 		pr_warn("debugfs initialization failed\n");
 	return 0;
 
+fallback_fail:
+	zswap_pool_destroy(pool);
 hp_fail:
 	cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE);
 dstmem_fail:
_


  parent reply	other threads:[~2020-01-31  6:15 UTC|newest]

Thread overview: 122+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-31  6:10 incoming Andrew Morton
2020-01-31  6:11 ` [patch 001/118] lib/test_bitmap: correct test data offsets for 32-bit Andrew Morton
2020-01-31  6:11 ` [patch 002/118] memcg: fix a crash in wb_workfn when a device disappears Andrew Morton
2020-01-31  6:11 ` [patch 003/118] mm/mempolicy.c: fix out of bounds write in mpol_parse_str() Andrew Morton
2020-01-31  6:11 ` [patch 004/118] mm/sparse.c: reset section's mem_map when fully deactivated Andrew Morton
2020-01-31  6:11 ` [patch 005/118] mm/migrate.c: also overwrite error when it is bigger than zero Andrew Morton
2020-01-31  6:11 ` [patch 006/118] mm/memory_hotplug: fix remove_memory() lockdep splat Andrew Morton
2020-01-31  6:11 ` [patch 007/118] mm: thp: don't need care deferred split queue in memcg charge move path Andrew Morton
2020-01-31  6:11 ` [patch 008/118] mm: move_pages: report the number of non-attempted pages Andrew Morton
2020-01-31  6:11 ` [patch 009/118] scripts/spelling.txt: add more spellings to spelling.txt Andrew Morton
2020-01-31  6:11 ` [patch 010/118] scripts/spelling.txt: add "issus" typo Andrew Morton
2020-01-31  6:11 ` [patch 011/118] fs: ocfs: remove unnecessary assertion in dlm_migrate_lockres Andrew Morton
2020-01-31  6:11 ` [patch 012/118] ocfs2: remove unneeded semicolons Andrew Morton
2020-01-31  6:11 ` [patch 013/118] ocfs2: make local header paths relative to C files Andrew Morton
2020-01-31  6:11 ` [patch 014/118] ocfs2/dlm: remove redundant assignment to ret Andrew Morton
2020-01-31  6:11 ` [patch 015/118] ocfs2/dlm: move BITS_TO_BYTES() to bitops.h for wider use Andrew Morton
2020-01-31  6:11 ` [patch 016/118] ocfs2: fix a NULL pointer dereference when call ocfs2_update_inode_fsync_trans() Andrew Morton
2020-01-31  6:11 ` [patch 017/118] ocfs2: use ocfs2_update_inode_fsync_trans() to access t_tid in handle->h_transaction Andrew Morton
2020-01-31  6:11 ` [patch 018/118] mm/slub.c: avoid slub allocation while holding list_lock Andrew Morton
2020-02-03 17:25   ` Christopher Lameter
2020-01-31  6:12 ` [patch 019/118] mm/kmemleak: turn kmemleak_lock and object->lock to raw_spinlock_t Andrew Morton
2020-01-31  6:12 ` [patch 020/118] mm/debug.c: always print flags in dump_page() Andrew Morton
2020-01-31  6:12 ` [patch 021/118] mm/filemap.c: clean up filemap_write_and_wait() Andrew Morton
2020-01-31  6:12 ` [patch 022/118] mm: fix gup_pud_range Andrew Morton
2020-01-31  6:12 ` [patch 023/118] mm/gup.c: use is_vm_hugetlb_page() to check whether to follow huge Andrew Morton
2020-01-31  6:12 ` [patch 024/118] mm/gup: factor out duplicate code from four routines Andrew Morton
2020-01-31  6:12 ` [patch 025/118] mm/gup: move try_get_compound_head() to top, fix minor issues Andrew Morton
2020-01-31  6:12 ` [patch 026/118] mm: Cleanup __put_devmap_managed_page() vs ->page_free() Andrew Morton
2020-01-31  6:12 ` [patch 027/118] mm: devmap: refactor 1-based refcounting for ZONE_DEVICE pages Andrew Morton
2020-01-31  6:12 ` [patch 028/118] goldish_pipe: rename local pin_user_pages() routine Andrew Morton
2020-01-31  6:12 ` [patch 029/118] mm: fix get_user_pages_remote()'s handling of FOLL_LONGTERM Andrew Morton
2020-01-31  6:12 ` [patch 030/118] vfio: fix FOLL_LONGTERM use, simplify get_user_pages_remote() call Andrew Morton
2020-01-31  6:12 ` [patch 031/118] mm/gup: allow FOLL_FORCE for get_user_pages_fast() Andrew Morton
2020-01-31  6:12 ` [patch 032/118] IB/umem: use get_user_pages_fast() to pin DMA pages Andrew Morton
2020-01-31  6:12 ` [patch 033/118] media/v4l2-core: set pages dirty upon releasing DMA buffers Andrew Morton
2020-01-31  6:12 ` [patch 034/118] mm/gup: introduce pin_user_pages*() and FOLL_PIN Andrew Morton
2020-01-31  6:12 ` [patch 035/118] goldish_pipe: convert to pin_user_pages() and put_user_page() Andrew Morton
2020-01-31  6:13 ` [patch 036/118] IB/{core,hw,umem}: set FOLL_PIN via pin_user_pages*(), fix up ODP Andrew Morton
2020-01-31  6:13 ` [patch 037/118] mm/process_vm_access: set FOLL_PIN via pin_user_pages_remote() Andrew Morton
2020-01-31  6:13 ` [patch 038/118] drm/via: set FOLL_PIN via pin_user_pages_fast() Andrew Morton
2020-01-31  6:13 ` [patch 039/118] fs/io_uring: set FOLL_PIN via pin_user_pages() Andrew Morton
2020-01-31  6:13 ` [patch 040/118] net/xdp: " Andrew Morton
2020-01-31  6:13 ` [patch 041/118] media/v4l2-core: pin_user_pages (FOLL_PIN) and put_user_page() conversion Andrew Morton
2020-01-31  6:13 ` [patch 042/118] vfio, mm: " Andrew Morton
2020-01-31  6:13 ` [patch 043/118] powerpc: book3s64: convert to pin_user_pages() and put_user_page() Andrew Morton
2020-01-31  6:13 ` [patch 044/118] mm/gup_benchmark: use proper FOLL_WRITE flags instead of hard-coding "1" Andrew Morton
2020-01-31  6:13 ` [patch 045/118] mm, tree-wide: rename put_user_page*() to unpin_user_page*() Andrew Morton
2020-01-31  6:13 ` [patch 046/118] mm/swapfile.c: swap_next should increase position index Andrew Morton
2020-01-31  6:13 ` [patch 047/118] mm/memcontrol.c: cleanup some useless code Andrew Morton
2020-01-31  6:13 ` [patch 048/118] mm/page_vma_mapped.c: explicitly compare pfn for normal, hugetlbfs and THP page Andrew Morton
2020-01-31  6:13 ` [patch 049/118] mm, tracing: print symbol name for kmem_alloc_node call_site events Andrew Morton
2020-01-31  6:13 ` [patch 050/118] lib/test_kasan.c: fix memory leak in kmalloc_oob_krealloc_more() Andrew Morton
2020-01-31  6:13 ` [patch 051/118] mm/early_ioremap.c: use %pa to print resource_size_t variables Andrew Morton
2020-01-31  6:13 ` [patch 052/118] mm/page_alloc: skip non present sections on zone initialization Andrew Morton
2020-01-31  6:14 ` [patch 053/118] mm: remove the memory isolate notifier Andrew Morton
2020-01-31  6:14 ` [patch 054/118] mm: remove "count" parameter from has_unmovable_pages() Andrew Morton
2020-01-31  6:14 ` [patch 055/118] mm/vmscan.c: remove unused return value of shrink_node Andrew Morton
2020-01-31  6:14 ` [patch 056/118] mm/vmscan: remove prefetch_prev_lru_page Andrew Morton
2020-01-31  6:14 ` [patch 057/118] mm/vmscan: remove unused RECLAIM_OFF/RECLAIM_ZONE Andrew Morton
2020-01-31  6:14 ` [patch 058/118] tools/vm/slabinfo: fix sanity checks enabling Andrew Morton
2020-01-31  6:14 ` [patch 059/118] mm/memblock: define memblock_physmem_add() Andrew Morton
2020-01-31  6:14 ` [patch 060/118] memblock: Use __func__ in remaining memblock_dbg() call sites Andrew Morton
2020-01-31  6:14 ` [patch 061/118] mm, oom: dump stack of victim when reaping failed Andrew Morton
2020-01-31  6:14 ` [patch 062/118] mm/huge_memory.c: use head to check huge zero page Andrew Morton
2020-01-31  6:14 ` [patch 063/118] mm/huge_memory.c: use head to emphasize the purpose of page Andrew Morton
2020-01-31  6:14 ` [patch 064/118] mm/huge_memory.c: reduce critical section protected by split_queue_lock Andrew Morton
2020-01-31  6:14 ` [patch 065/118] mm/migrate: remove useless mask of start address Andrew Morton
2020-01-31  6:14 ` [patch 066/118] mm/migrate: clean up some minor coding style Andrew Morton
2020-01-31  6:14 ` [patch 067/118] mm/migrate: add stable check in migrate_vma_insert_page() Andrew Morton
2020-01-31  6:14 ` [patch 068/118] mm, thp: fix defrag setting if newline is not used Andrew Morton
2020-01-31  6:14 ` [patch 069/118] mm/mmap.c: get rid of odd jump labels in find_mergeable_anon_vma() Andrew Morton
2020-01-31  6:14 ` [patch 070/118] mm/memory_hotplug: pass in nid to online_pages() Andrew Morton
2020-01-31  6:14 ` [patch 071/118] mm/hotplug: silence a lockdep splat with printk() Andrew Morton
2020-01-31  6:15 ` [patch 072/118] mm/page_isolation: fix potential warning from user Andrew Morton
2020-01-31  6:15 ` Andrew Morton [this message]
2020-01-31  6:15 ` [patch 074/118] zswap: potential NULL dereference on error in init_zswap() Andrew Morton
2020-01-31  6:15 ` [patch 075/118] include/linux/mm.h: clean up obsolete check on space in page->flags Andrew Morton
2020-01-31  6:15 ` [patch 076/118] include/linux/mm.h: remove dead code totalram_pages_set() Andrew Morton
2020-01-31  6:15 ` [patch 077/118] include/linux/memory.h: drop fields 'hw' and 'phys_callback' from struct memory_block Andrew Morton
2020-01-31  6:15 ` [patch 078/118] mm: fix comments related to node reclaim Andrew Morton
2020-01-31  6:15 ` [patch 079/118] zram: try to avoid worst-case scenario on same element pages Andrew Morton
2020-01-31  6:15 ` [patch 080/118] drivers/block/zram/zram_drv.c: fix error return codes not being returned in writeback_store Andrew Morton
2020-01-31  6:15 ` [patch 081/118] include/linux/units.h: add helpers for kelvin to/from Celsius conversion Andrew Morton
2020-01-31  6:15 ` [patch 082/118] ACPI: thermal: switch to use <linux/units.h> helpers Andrew Morton
2020-01-31  6:15 ` [patch 083/118] platform/x86: asus-wmi: " Andrew Morton
2020-01-31  6:15 ` [patch 084/118] platform/x86: intel_menlow: " Andrew Morton
2020-01-31  6:15 ` [patch 085/118] thermal: int340x: " Andrew Morton
2020-01-31  6:15 ` [patch 086/118] thermal: intel_pch: " Andrew Morton
2020-01-31  6:15 ` [patch 087/118] nvme: hwmon: " Andrew Morton
2020-01-31  6:15 ` [patch 088/118] thermal: remove kelvin to/from Celsius conversion helpers from <linux/thermal.h> Andrew Morton
2020-01-31  6:16 ` [patch 089/118] iwlegacy: use <linux/units.h> helpers Andrew Morton
2020-01-31  6:16 ` [patch 090/118] iwlwifi: " Andrew Morton
2020-01-31  6:28   ` Luciano Coelho
2020-01-31  6:16 ` [patch 091/118] thermal: armada: remove unused TO_MCELSIUS macro Andrew Morton
2020-01-31  6:16 ` [patch 092/118] iio: adc: qcom-vadc-common: use <linux/units.h> helpers Andrew Morton
2020-01-31  6:16 ` [patch 093/118] lib/zlib: add s390 hardware support for kernel zlib_deflate Andrew Morton
2020-01-31  6:16 ` [patch 094/118] s390/boot: rename HEAP_SIZE due to name collision Andrew Morton
2020-01-31  6:16 ` [patch 095/118] lib/zlib: add s390 hardware support for kernel zlib_inflate Andrew Morton
2020-01-31  6:16 ` [patch 096/118] s390/boot: add dfltcc= kernel command line parameter Andrew Morton
2020-01-31  6:16 ` [patch 097/118] lib/zlib: add zlib_deflate_dfltcc_enabled() function Andrew Morton
2020-01-31  6:16 ` [patch 098/118] btrfs: use larger zlib buffer for s390 hardware compression Andrew Morton
2020-01-31  6:16 ` [patch 099/118] lib/scatterlist.c: adjust indentation in __sg_alloc_table Andrew Morton
2020-01-31  6:16 ` [patch 100/118] uapi: rename ext2_swab() to swab() and share globally in swab.h Andrew Morton
2020-01-31  6:16 ` [patch 101/118] lib/find_bit.c: join _find_next_bit{_le} Andrew Morton
2020-01-31  6:16 ` [patch 102/118] lib/find_bit.c: uninline helper _find_next_bit() Andrew Morton
2020-01-31  6:16 ` [patch 103/118] fs/binfmt_elf.c: smaller code generation around auxv vector fill Andrew Morton
2020-01-31  6:16 ` [patch 104/118] fs/binfmt_elf.c: fix ->start_code calculation Andrew Morton
2020-01-31  6:16 ` [patch 105/118] fs/binfmt_elf.c: don't copy ELF header around Andrew Morton
2023-11-22  7:15   ` Jinjie Ruan
2020-01-31  6:16 ` [patch 106/118] fs/binfmt_elf.c: better codegen around current->mm Andrew Morton
2020-01-31  6:17 ` [patch 107/118] fs/binfmt_elf.c: make BAD_ADDR() unlikely Andrew Morton
2020-01-31  6:17 ` [patch 108/118] fs/binfmt_elf.c: coredump: allocate core ELF header on stack Andrew Morton
2020-01-31  6:17 ` [patch 109/118] fs/binfmt_elf.c: coredump: delete duplicated overflow check Andrew Morton
2020-01-31  6:17 ` [patch 110/118] fs/binfmt_elf.c: coredump: allow process with empty address space to coredump Andrew Morton
2020-01-31  6:17 ` [patch 111/118] init/main.c: log arguments and environment passed to init Andrew Morton
2020-01-31  6:17 ` [patch 112/118] init/main.c: remove unnecessary repair_env_string in do_initcall_level Andrew Morton
2020-01-31  6:17 ` [patch 113/118] init/main.c: fix quoted value handling in unknown_bootoption Andrew Morton
2020-01-31  6:17 ` [patch 114/118] init/main.c: fix misleading "This architecture does not have kernel memory protection" message Andrew Morton
2020-01-31  6:17 ` [patch 115/118] reiserfs: prevent NULL pointer dereference in reiserfs_insert_item() Andrew Morton
2020-01-31  6:17 ` [patch 116/118] execve: warn if process starts with executable stack Andrew Morton
2020-01-31  6:17 ` [patch 117/118] include/linux/io-mapping.h-mapping: use PHYS_PFN() macro in io_mapping_map_atomic_wc() Andrew Morton
2020-01-31  6:17 ` [patch 118/118] kcov: ignore fault-inject and stacktrace Andrew Morton

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=20200131061504._6iRRJ82s%akpm@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=ddstreet@ieee.org \
    --cc=linux-mm@kvack.org \
    --cc=mm-commits@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=vitaly.wool@konsulko.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).