]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 10 Jan 2018 09:37:34 +0000 (10:37 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 10 Jan 2018 09:37:34 +0000 (10:37 +0100)
added patches:
dm-bufio-fix-shrinker-scans-when-nr_to_scan-retain_target.patch

queue-4.14/dm-bufio-fix-shrinker-scans-when-nr_to_scan-retain_target.patch [new file with mode: 0644]
queue-4.14/series [new file with mode: 0644]
queue-4.4/series [new file with mode: 0644]
queue-4.9/series [new file with mode: 0644]

diff --git a/queue-4.14/dm-bufio-fix-shrinker-scans-when-nr_to_scan-retain_target.patch b/queue-4.14/dm-bufio-fix-shrinker-scans-when-nr_to_scan-retain_target.patch
new file mode 100644 (file)
index 0000000..9a5978e
--- /dev/null
@@ -0,0 +1,75 @@
+From fbc7c07ec23c040179384a1f16b62b6030eb6bdd Mon Sep 17 00:00:00 2001
+From: Suren Baghdasaryan <surenb@google.com>
+Date: Wed, 6 Dec 2017 09:27:30 -0800
+Subject: dm bufio: fix shrinker scans when (nr_to_scan < retain_target)
+
+From: Suren Baghdasaryan <surenb@google.com>
+
+commit fbc7c07ec23c040179384a1f16b62b6030eb6bdd upstream.
+
+When system is under memory pressure it is observed that dm bufio
+shrinker often reclaims only one buffer per scan. This change fixes
+the following two issues in dm bufio shrinker that cause this behavior:
+
+1. ((nr_to_scan - freed) <= retain_target) condition is used to
+terminate slab scan process. This assumes that nr_to_scan is equal
+to the LRU size, which might not be correct because do_shrink_slab()
+in vmscan.c calculates nr_to_scan using multiple inputs.
+As a result when nr_to_scan is less than retain_target (64) the scan
+will terminate after the first iteration, effectively reclaiming one
+buffer per scan and making scans very inefficient. This hurts vmscan
+performance especially because mutex is acquired/released every time
+dm_bufio_shrink_scan() is called.
+New implementation uses ((LRU size - freed) <= retain_target)
+condition for scan termination. LRU size can be safely determined
+inside __scan() because this function is called after dm_bufio_lock().
+
+2. do_shrink_slab() uses value returned by dm_bufio_shrink_count() to
+determine number of freeable objects in the slab. However dm_bufio
+always retains retain_target buffers in its LRU and will terminate
+a scan when this mark is reached. Therefore returning the entire LRU size
+from dm_bufio_shrink_count() is misleading because that does not
+represent the number of freeable objects that slab will reclaim during
+a scan. Returning (LRU size - retain_target) better represents the
+number of freeable objects in the slab. This way do_shrink_slab()
+returns 0 when (LRU size < retain_target) and vmscan will not try to
+scan this shrinker avoiding scans that will not reclaim any memory.
+
+Test: tested using Android device running
+<AOSP>/system/extras/alloc-stress that generates memory pressure
+and causes intensive shrinker scans
+
+Signed-off-by: Suren Baghdasaryan <surenb@google.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/md/dm-bufio.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/dm-bufio.c
++++ b/drivers/md/dm-bufio.c
+@@ -1611,7 +1611,8 @@ static unsigned long __scan(struct dm_bu
+       int l;
+       struct dm_buffer *b, *tmp;
+       unsigned long freed = 0;
+-      unsigned long count = nr_to_scan;
++      unsigned long count = c->n_buffers[LIST_CLEAN] +
++                            c->n_buffers[LIST_DIRTY];
+       unsigned long retain_target = get_retain_buffers(c);
+       for (l = 0; l < LIST_SIZE; l++) {
+@@ -1647,8 +1648,11 @@ static unsigned long
+ dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
+ {
+       struct dm_bufio_client *c = container_of(shrink, struct dm_bufio_client, shrinker);
++      unsigned long count = ACCESS_ONCE(c->n_buffers[LIST_CLEAN]) +
++                            ACCESS_ONCE(c->n_buffers[LIST_DIRTY]);
++      unsigned long retain_target = get_retain_buffers(c);
+-      return ACCESS_ONCE(c->n_buffers[LIST_CLEAN]) + ACCESS_ONCE(c->n_buffers[LIST_DIRTY]);
++      return (count < retain_target) ? 0 : (count - retain_target);
+ }
+ /*
diff --git a/queue-4.14/series b/queue-4.14/series
new file mode 100644 (file)
index 0000000..f77b2e5
--- /dev/null
@@ -0,0 +1 @@
+dm-bufio-fix-shrinker-scans-when-nr_to_scan-retain_target.patch
diff --git a/queue-4.4/series b/queue-4.4/series
new file mode 100644 (file)
index 0000000..f77b2e5
--- /dev/null
@@ -0,0 +1 @@
+dm-bufio-fix-shrinker-scans-when-nr_to_scan-retain_target.patch
diff --git a/queue-4.9/series b/queue-4.9/series
new file mode 100644 (file)
index 0000000..f77b2e5
--- /dev/null
@@ -0,0 +1 @@
+dm-bufio-fix-shrinker-scans-when-nr_to_scan-retain_target.patch