]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.4
authorSasha Levin <sashal@kernel.org>
Sat, 9 Jan 2021 15:00:45 +0000 (10:00 -0500)
committerSasha Levin <sashal@kernel.org>
Sat, 9 Jan 2021 15:00:45 +0000 (10:00 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.4/depmod-handle-the-case-of-sbin-depmod-without-sbin-i.patch [new file with mode: 0644]
queue-4.4/lib-genalloc-fix-the-overflow-when-size-is-too-big.patch [new file with mode: 0644]
queue-4.4/series [new file with mode: 0644]
queue-4.4/workqueue-kick-a-worker-based-on-the-actual-activati.patch [new file with mode: 0644]

diff --git a/queue-4.4/depmod-handle-the-case-of-sbin-depmod-without-sbin-i.patch b/queue-4.4/depmod-handle-the-case-of-sbin-depmod-without-sbin-i.patch
new file mode 100644 (file)
index 0000000..c46e533
--- /dev/null
@@ -0,0 +1,40 @@
+From 5ea23f9c91ffb773e582f3817089051d70fc9177 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Dec 2020 11:40:22 -0800
+Subject: depmod: handle the case of /sbin/depmod without /sbin in PATH
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+[ Upstream commit cedd1862be7e666be87ec824dabc6a2b05618f36 ]
+
+Commit 436e980e2ed5 ("kbuild: don't hardcode depmod path") stopped
+hard-coding the path of depmod, but in the process caused trouble for
+distributions that had that /sbin location, but didn't have it in the
+PATH (generally because /sbin is limited to the super-user path).
+
+Work around it for now by just adding /sbin to the end of PATH in the
+depmod.sh script.
+
+Reported-and-tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/depmod.sh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/scripts/depmod.sh b/scripts/depmod.sh
+index baedaef53ca05..b0cb89e73bc56 100755
+--- a/scripts/depmod.sh
++++ b/scripts/depmod.sh
+@@ -14,6 +14,8 @@ if ! test -r System.map ; then
+       exit 0
+ fi
++# legacy behavior: "depmod" in /sbin, no /sbin in PATH
++PATH="$PATH:/sbin"
+ if [ -z $(command -v $DEPMOD) ]; then
+       echo "Warning: 'make modules_install' requires $DEPMOD. Please install it." >&2
+       echo "This is probably in the kmod package." >&2
+-- 
+2.27.0
+
diff --git a/queue-4.4/lib-genalloc-fix-the-overflow-when-size-is-too-big.patch b/queue-4.4/lib-genalloc-fix-the-overflow-when-size-is-too-big.patch
new file mode 100644 (file)
index 0000000..c78ce84
--- /dev/null
@@ -0,0 +1,131 @@
+From ac7370c88cff0bf0cad8d89727c650a13953a2f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Dec 2020 15:14:58 -0800
+Subject: lib/genalloc: fix the overflow when size is too big
+
+From: Huang Shijie <sjhuang@iluvatar.ai>
+
+[ Upstream commit 36845663843fc59c5d794e3dc0641472e3e572da ]
+
+Some graphic card has very big memory on chip, such as 32G bytes.
+
+In the following case, it will cause overflow:
+
+    pool = gen_pool_create(PAGE_SHIFT, NUMA_NO_NODE);
+    ret = gen_pool_add(pool, 0x1000000, SZ_32G, NUMA_NO_NODE);
+
+    va = gen_pool_alloc(pool, SZ_4G);
+
+The overflow occurs in gen_pool_alloc_algo_owner():
+
+               ....
+               size = nbits << order;
+               ....
+
+The @nbits is "int" type, so it will overflow.
+Then the gen_pool_avail() will return the wrong value.
+
+This patch converts some "int" to "unsigned long", and
+changes the compare code in while.
+
+Link: https://lkml.kernel.org/r/20201229060657.3389-1-sjhuang@iluvatar.ai
+Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
+Reported-by: Shi Jiasheng <jiasheng.shi@iluvatar.ai>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/genalloc.c | 25 +++++++++++++------------
+ 1 file changed, 13 insertions(+), 12 deletions(-)
+
+diff --git a/lib/genalloc.c b/lib/genalloc.c
+index e3a475b14e260..b8ac0450a2a68 100644
+--- a/lib/genalloc.c
++++ b/lib/genalloc.c
+@@ -83,14 +83,14 @@ static int clear_bits_ll(unsigned long *addr, unsigned long mask_to_clear)
+  * users set the same bit, one user will return remain bits, otherwise
+  * return 0.
+  */
+-static int bitmap_set_ll(unsigned long *map, int start, int nr)
++static int bitmap_set_ll(unsigned long *map, unsigned long start, unsigned long nr)
+ {
+       unsigned long *p = map + BIT_WORD(start);
+-      const int size = start + nr;
++      const unsigned long size = start + nr;
+       int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
+       unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
+-      while (nr - bits_to_set >= 0) {
++      while (nr >= bits_to_set) {
+               if (set_bits_ll(p, mask_to_set))
+                       return nr;
+               nr -= bits_to_set;
+@@ -118,14 +118,15 @@ static int bitmap_set_ll(unsigned long *map, int start, int nr)
+  * users clear the same bit, one user will return remain bits,
+  * otherwise return 0.
+  */
+-static int bitmap_clear_ll(unsigned long *map, int start, int nr)
++static unsigned long
++bitmap_clear_ll(unsigned long *map, unsigned long start, unsigned long nr)
+ {
+       unsigned long *p = map + BIT_WORD(start);
+-      const int size = start + nr;
++      const unsigned long size = start + nr;
+       int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
+       unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
+-      while (nr - bits_to_clear >= 0) {
++      while (nr >= bits_to_clear) {
+               if (clear_bits_ll(p, mask_to_clear))
+                       return nr;
+               nr -= bits_to_clear;
+@@ -184,8 +185,8 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
+                size_t size, int nid)
+ {
+       struct gen_pool_chunk *chunk;
+-      int nbits = size >> pool->min_alloc_order;
+-      int nbytes = sizeof(struct gen_pool_chunk) +
++      unsigned long nbits = size >> pool->min_alloc_order;
++      unsigned long nbytes = sizeof(struct gen_pool_chunk) +
+                               BITS_TO_LONGS(nbits) * sizeof(long);
+       chunk = vzalloc_node(nbytes, nid);
+@@ -242,7 +243,7 @@ void gen_pool_destroy(struct gen_pool *pool)
+       struct list_head *_chunk, *_next_chunk;
+       struct gen_pool_chunk *chunk;
+       int order = pool->min_alloc_order;
+-      int bit, end_bit;
++      unsigned long bit, end_bit;
+       list_for_each_safe(_chunk, _next_chunk, &pool->chunks) {
+               chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
+@@ -274,7 +275,7 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
+       struct gen_pool_chunk *chunk;
+       unsigned long addr = 0;
+       int order = pool->min_alloc_order;
+-      int nbits, start_bit, end_bit, remain;
++      unsigned long nbits, start_bit, end_bit, remain;
+ #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+       BUG_ON(in_nmi());
+@@ -357,7 +358,7 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size)
+ {
+       struct gen_pool_chunk *chunk;
+       int order = pool->min_alloc_order;
+-      int start_bit, nbits, remain;
++      unsigned long start_bit, nbits, remain;
+ #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
+       BUG_ON(in_nmi());
+@@ -553,7 +554,7 @@ unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size,
+       index = bitmap_find_next_zero_area(map, size, start, nr, 0);
+       while (index < size) {
+-              int next_bit = find_next_bit(map, size, index + nr);
++              unsigned long next_bit = find_next_bit(map, size, index + nr);
+               if ((next_bit - index) < len) {
+                       len = next_bit - index;
+                       start_bit = index;
+-- 
+2.27.0
+
diff --git a/queue-4.4/series b/queue-4.4/series
new file mode 100644 (file)
index 0000000..8211710
--- /dev/null
@@ -0,0 +1,3 @@
+workqueue-kick-a-worker-based-on-the-actual-activati.patch
+lib-genalloc-fix-the-overflow-when-size-is-too-big.patch
+depmod-handle-the-case-of-sbin-depmod-without-sbin-i.patch
diff --git a/queue-4.4/workqueue-kick-a-worker-based-on-the-actual-activati.patch b/queue-4.4/workqueue-kick-a-worker-based-on-the-actual-activati.patch
new file mode 100644 (file)
index 0000000..5e0e1ba
--- /dev/null
@@ -0,0 +1,69 @@
+From d80cc548911e1e112d9c3992890a419da74719be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Nov 2020 14:21:25 +0800
+Subject: workqueue: Kick a worker based on the actual activation of delayed
+ works
+
+From: Yunfeng Ye <yeyunfeng@huawei.com>
+
+[ Upstream commit 01341fbd0d8d4e717fc1231cdffe00343088ce0b ]
+
+In realtime scenario, We do not want to have interference on the
+isolated cpu cores. but when invoking alloc_workqueue() for percpu wq
+on the housekeeping cpu, it kick a kworker on the isolated cpu.
+
+  alloc_workqueue
+    pwq_adjust_max_active
+      wake_up_worker
+
+The comment in pwq_adjust_max_active() said:
+  "Need to kick a worker after thawed or an unbound wq's
+   max_active is bumped"
+
+So it is unnecessary to kick a kworker for percpu's wq when invoking
+alloc_workqueue(). this patch only kick a worker based on the actual
+activation of delayed works.
+
+Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
+Reviewed-by: Lai Jiangshan <jiangshanlai@gmail.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/workqueue.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index 3fb2d45c0b42f..6b293804cd734 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -3361,17 +3361,24 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq)
+        * is updated and visible.
+        */
+       if (!freezable || !workqueue_freezing) {
++              bool kick = false;
++
+               pwq->max_active = wq->saved_max_active;
+               while (!list_empty(&pwq->delayed_works) &&
+-                     pwq->nr_active < pwq->max_active)
++                     pwq->nr_active < pwq->max_active) {
+                       pwq_activate_first_delayed(pwq);
++                      kick = true;
++              }
+               /*
+                * Need to kick a worker after thawed or an unbound wq's
+-               * max_active is bumped.  It's a slow path.  Do it always.
++               * max_active is bumped. In realtime scenarios, always kicking a
++               * worker will cause interference on the isolated cpu cores, so
++               * let's kick iff work items were activated.
+                */
+-              wake_up_worker(pwq->pool);
++              if (kick)
++                      wake_up_worker(pwq->pool);
+       } else {
+               pwq->max_active = 0;
+       }
+-- 
+2.27.0
+