maillist inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9KUFO
Reference: https://lore.kernel.org/all/20240412135256.1546051-1-zhengyejian1@huawei.co…
--------------------------------
Infinite log printing occurs during fuzz test:
rc rc1: DViCO FusionHDTV DVB-T USB (LGZ201) as ...
...
dvb-usb: schedule remote query interval to 100 msecs.
dvb-usb: DViCO FusionHDTV DVB-T USB (LGZ201) successfully initialized ...
dvb-usb: bulk message failed: -22 (1/0)
dvb-usb: bulk message failed: -22 (1/0)
dvb-usb: bulk message failed: -22 (1/0)
...
dvb-usb: bulk message failed: -22 (1/0)
Looking into the codes, there is a loop in dvb_usb_read_remote_control(),
that is in rc_core_dvb_usb_remote_init() create a work that will call
dvb_usb_read_remote_control(), and this work will reschedule itself at
'rc_interval' intervals to recursively call dvb_usb_read_remote_control(),
see following code snippet:
rc_core_dvb_usb_remote_init() {
...
INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
schedule_delayed_work(&d->rc_query_work,
msecs_to_jiffies(rc_interval));
...
}
dvb_usb_read_remote_control() {
...
err = d->props.rc.core.rc_query(d);
if (err)
err(...) // Did not return even if query failed
schedule_delayed_work(&d->rc_query_work,
msecs_to_jiffies(rc_interval));
}
When the infinite log printing occurs, the query callback
'd->props.rc.core.rc_query' is cxusb_rc_query(). And the log is due to
the failure of finding a valid 'generic_bulk_ctrl_endpoint'
in usb_bulk_msg(), see following code snippet:
cxusb_rc_query() {
cxusb_ctrl_msg() {
dvb_usb_generic_rw() {
ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev,
d->props.generic_bulk_ctrl_endpoint),...);
if (ret)
err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
...
}
...
}
By analyzing the corresponding USB descriptor, it shows that the
bNumEndpoints is 0 in its interface descriptor, but
the 'generic_bulk_ctrl_endpoint' is 1, that means user don't configure
a valid endpoint for 'generic_bulk_ctrl_endpoint', therefore this
'invalid' USB device should be rejected before it calls into
dvb_usb_read_remote_control().
To fix it, iiuc, we can add endpoint check in dvb_usb_adapter_init().
Signed-off-by: Zheng Yejian <zhengyejian1(a)huawei.com>
---
drivers/media/usb/dvb-usb/dvb-usb-init.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c
index 58eea8ab5477..d8098c110450 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c
@@ -104,6 +104,14 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
* sometimes a timeout occurs, this helps
*/
if (d->props.generic_bulk_ctrl_endpoint != 0) {
+ ret = usb_pipe_type_check(d->udev, usb_sndbulkpipe(d->udev,
+ d->props.generic_bulk_ctrl_endpoint));
+ if (ret)
+ goto frontend_init_err;
+ ret = usb_pipe_type_check(d->udev, usb_rcvbulkpipe(d->udev,
+ d->props.generic_bulk_ctrl_endpoint));
+ if (ret)
+ goto frontend_init_err;
usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
}
--
2.25.1
tree: https://gitee.com/openeuler/kernel.git openEuler-1.0-LTS
head: 3c3550371ac3e9d3326c8263a6eb52d3bb0b43a8
commit: bccfa644c1b98b9d6fa102a39a10a1c52811fd0c [15647/22256] sched/fair: Steal work from an overloaded CPU when CPU goes idle
config: x86_64-randconfig-003-20240430 (https://download.01.org/0day-ci/archive/20240430/202404300955.dFOHBkZ8-lkp@…)
compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240430/202404300955.dFOHBkZ8-lkp@…)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp(a)intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202404300955.dFOHBkZ8-lkp@intel.com/
All warnings (new ones prefixed by >>):
kernel/sched/fair.c:2548:6: warning: no previous prototype for 'task_numa_work' [-Wmissing-prototypes]
2548 | void task_numa_work(struct callback_head *work)
| ^~~~~~~~~~~~~~
kernel/sched/fair.c:2694:6: warning: no previous prototype for 'task_tick_numa' [-Wmissing-prototypes]
2694 | void task_tick_numa(struct rq *rq, struct task_struct *curr)
| ^~~~~~~~~~~~~~
kernel/sched/fair.c:3658:6: warning: no previous prototype for 'sync_entity_load_avg' [-Wmissing-prototypes]
3658 | void sync_entity_load_avg(struct sched_entity *se)
| ^~~~~~~~~~~~~~~~~~~~
kernel/sched/fair.c:3671:6: warning: no previous prototype for 'remove_entity_load_avg' [-Wmissing-prototypes]
3671 | void remove_entity_load_avg(struct sched_entity *se)
| ^~~~~~~~~~~~~~~~~~~~~~
kernel/sched/fair.c: In function 'update_blocked_averages':
kernel/sched/fair.c:7626:14: warning: variable 'done' set but not used [-Wunused-but-set-variable]
7626 | bool done = true;
| ^~~~
In function 'group_faults_priv',
inlined from 'task_scan_max' at kernel/sched/fair.c:1175:27:
kernel/sched/fair.c:1307:37: warning: array subscript <unknown> is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
1307 | faults += ng->faults[task_faults_idx(NUMA_MEM, node, 1)];
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/fair.c: In function 'task_scan_max':
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
In function 'group_faults_shared',
inlined from 'task_scan_max' at kernel/sched/fair.c:1174:26:
kernel/sched/fair.c:1319:37: warning: array subscript <unknown> is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
1319 | faults += ng->faults[task_faults_idx(NUMA_MEM, node, 0)];
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/fair.c: In function 'task_scan_max':
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
In function 'group_faults_priv',
inlined from 'task_scan_start' at kernel/sched/fair.c:1151:27:
kernel/sched/fair.c:1307:37: warning: array subscript <unknown> is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
1307 | faults += ng->faults[task_faults_idx(NUMA_MEM, node, 1)];
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/fair.c: In function 'task_scan_start':
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
In function 'group_faults_shared',
inlined from 'task_scan_start' at kernel/sched/fair.c:1150:26:
kernel/sched/fair.c:1319:37: warning: array subscript <unknown> is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
1319 | faults += ng->faults[task_faults_idx(NUMA_MEM, node, 0)];
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/fair.c: In function 'task_scan_start':
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
In file included from include/linux/bitops.h:19,
from include/linux/kernel.h:11,
from arch/x86/include/asm/percpu.h:45,
from arch/x86/include/asm/current.h:6,
from include/linux/sched.h:12,
from kernel/sched/sched.h:5,
from kernel/sched/fair.c:23:
In function 'sparsemask_test_elem',
inlined from 'try_steal' at kernel/sched/fair.c:10007:8:
kernel/sched/sparsemask.h:53:10: warning: array subscript <unknown> is outside array bounds of 'const struct sparsemask_chunk[0]' [-Warray-bounds=]
53 | (&(mask)->chunks[SMASK_INDEX((mask), (elem))].word)
arch/x86/include/asm/bitops.h:341:37: note: in definition of macro 'test_bit'
341 | : variable_test_bit((nr), (addr)))
| ^~~~
kernel/sched/sparsemask.h:191:48: note: in expansion of macro 'SMASK_WORD'
191 | return test_bit(SMASK_BIT(mask, elem), SMASK_WORD(mask, elem));
| ^~~~~~~~~~
In file included from kernel/sched/fair.c:24:
kernel/sched/sparsemask.h: In function 'try_steal':
kernel/sched/sparsemask.h:45:33: note: while referencing 'chunks'
45 | struct sparsemask_chunk chunks[0]; /* embedded array of chunks */
| ^~~~~~
In function 'sparsemask_next',
inlined from 'try_steal' at kernel/sched/fair.c:10018:2:
kernel/sched/sparsemask.h:98:17: warning: array subscript <unknown> is outside array bounds of 'const struct sparsemask_chunk[0]' [-Warray-bounds=]
98 | chunk = &mask->chunks[_SMASK_INDEX(density, next)];
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/sparsemask.h: In function 'try_steal':
kernel/sched/sparsemask.h:45:33: note: while referencing 'chunks'
45 | struct sparsemask_chunk chunks[0]; /* embedded array of chunks */
| ^~~~~~
In function 'sparsemask_next',
inlined from 'try_steal' at kernel/sched/fair.c:10018:2:
>> kernel/sched/sparsemask.h:98:17: warning: array subscript 0 is outside array bounds of 'const struct sparsemask_chunk[0]' [-Warray-bounds=]
98 | chunk = &mask->chunks[_SMASK_INDEX(density, next)];
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/sparsemask.h: In function 'try_steal':
kernel/sched/sparsemask.h:45:33: note: while referencing 'chunks'
45 | struct sparsemask_chunk chunks[0]; /* embedded array of chunks */
| ^~~~~~
In function 'sparsemask_next',
inlined from 'try_steal' at kernel/sched/fair.c:10018:2:
kernel/sched/sparsemask.h:98:30: warning: array subscript <unknown> is outside array bounds of 'const struct sparsemask_chunk[0]' [-Warray-bounds=]
98 | chunk = &mask->chunks[_SMASK_INDEX(density, next)];
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/sparsemask.h: In function 'try_steal':
kernel/sched/sparsemask.h:45:33: note: while referencing 'chunks'
45 | struct sparsemask_chunk chunks[0]; /* embedded array of chunks */
| ^~~~~~
kernel/sched/fair.c: In function 'task_numa_group':
kernel/sched/fair.c:2335:36: warning: array subscript i is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
2335 | grp->faults[i] = p->numa_faults[i];
| ~~~~~~~~~~~^~~
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
kernel/sched/fair.c:2393:31: warning: array subscript i is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
2393 | my_grp->faults[i] -= p->numa_faults[i];
| ~~~~~~~~~~~~~~^~~
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
kernel/sched/fair.c:2393:31: warning: array subscript i is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
2393 | my_grp->faults[i] -= p->numa_faults[i];
| ~~~~~~~~~~~~~~^~~
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
kernel/sched/fair.c:2394:28: warning: array subscript i is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
2394 | grp->faults[i] += p->numa_faults[i];
| ~~~~~~~~~~~^~~
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
kernel/sched/fair.c:2394:28: warning: array subscript i is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
2394 | grp->faults[i] += p->numa_faults[i];
| ~~~~~~~~~~~^~~
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
In function 'sparsemask_clear_elem',
inlined from 'overload_clear.part.0' at kernel/sched/fair.c:3834:3:
kernel/sched/sparsemask.h:53:10: warning: array subscript <unknown> is outside array bounds of 'struct sparsemask_chunk[0]' [-Warray-bounds=]
53 | (&(mask)->chunks[SMASK_INDEX((mask), (elem))].word)
| ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/sparsemask.h:186:41: note: in expansion of macro 'SMASK_WORD'
186 | clear_bit(SMASK_BIT(dst, elem), SMASK_WORD(dst, elem));
| ^~~~~~~~~~
kernel/sched/sparsemask.h: In function 'overload_clear.part.0':
kernel/sched/sparsemask.h:45:33: note: while referencing 'chunks'
45 | struct sparsemask_chunk chunks[0]; /* embedded array of chunks */
| ^~~~~~
In function 'group_faults',
inlined from 'score_nearby_nodes.part.0' at kernel/sched/fair.c:1381:13:
kernel/sched/fair.c:1291:26: warning: array subscript <unknown> is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
1291 | return ng->faults[task_faults_idx(NUMA_MEM, nid, 0)] +
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/fair.c: In function 'score_nearby_nodes.part.0':
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
In function 'group_faults',
inlined from 'score_nearby_nodes.part.0' at kernel/sched/fair.c:1381:13:
kernel/sched/fair.c:1292:27: warning: array subscript <unknown> is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
1292 | ng->faults[task_faults_idx(NUMA_MEM, nid, 1)];
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/fair.c: In function 'score_nearby_nodes.part.0':
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
In function 'group_faults',
inlined from 'preferred_group_nid' at kernel/sched/fair.c:2161:16:
kernel/sched/fair.c:1291:26: warning: array subscript <unknown> is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
1291 | return ng->faults[task_faults_idx(NUMA_MEM, nid, 0)] +
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/fair.c: In function 'preferred_group_nid':
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
In function 'group_faults',
inlined from 'preferred_group_nid' at kernel/sched/fair.c:2161:16:
kernel/sched/fair.c:1292:27: warning: array subscript <unknown> is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
1292 | ng->faults[task_faults_idx(NUMA_MEM, nid, 1)];
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kernel/sched/fair.c: In function 'preferred_group_nid':
kernel/sched/fair.c:1083:23: note: while referencing 'faults'
1083 | unsigned long faults[0];
| ^~~~~~
In function 'group_faults',
inlined from 'group_weight' at kernel/sched/fair.c:1441:11,
inlined from 'preferred_group_nid' at kernel/sched/fair.c:2125:12:
kernel/sched/fair.c:1291:26: warning: array subscript <unknown> is outside array bounds of 'long unsigned int[0]' [-Warray-bounds=]
1291 | return ng->faults[task_faults_idx(NUMA_MEM, nid, 0)] +
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
vim +98 kernel/sched/sparsemask.h
6866be5a3aff4b Steve Sistare 2021-04-14 47
6866be5a3aff4b Steve Sistare 2021-04-14 48 #define _SMASK_INDEX(density, elem) ((elem) >> (density))
6866be5a3aff4b Steve Sistare 2021-04-14 49 #define _SMASK_BIT(density, elem) ((elem) & ((1U << (density)) - 1U))
6866be5a3aff4b Steve Sistare 2021-04-14 50 #define SMASK_INDEX(mask, elem) _SMASK_INDEX((mask)->density, elem)
6866be5a3aff4b Steve Sistare 2021-04-14 51 #define SMASK_BIT(mask, elem) _SMASK_BIT((mask)->density, elem)
6866be5a3aff4b Steve Sistare 2021-04-14 52 #define SMASK_WORD(mask, elem) \
6866be5a3aff4b Steve Sistare 2021-04-14 53 (&(mask)->chunks[SMASK_INDEX((mask), (elem))].word)
6866be5a3aff4b Steve Sistare 2021-04-14 54
6866be5a3aff4b Steve Sistare 2021-04-14 55 /*
6866be5a3aff4b Steve Sistare 2021-04-14 56 * sparsemask_next() - Return the next one bit in a bitmap, starting at a
6866be5a3aff4b Steve Sistare 2021-04-14 57 * specified position and wrapping from the last bit to the first, up to but
6866be5a3aff4b Steve Sistare 2021-04-14 58 * not including a specified origin. This is a helper, so do not call it
6866be5a3aff4b Steve Sistare 2021-04-14 59 * directly.
6866be5a3aff4b Steve Sistare 2021-04-14 60 *
6866be5a3aff4b Steve Sistare 2021-04-14 61 * @mask: Bitmap to search.
6866be5a3aff4b Steve Sistare 2021-04-14 62 * @origin: Origin.
6866be5a3aff4b Steve Sistare 2021-04-14 63 * @prev: Previous bit. Start search after this bit number.
6866be5a3aff4b Steve Sistare 2021-04-14 64 * If -1, start search at @origin.
6866be5a3aff4b Steve Sistare 2021-04-14 65 *
6866be5a3aff4b Steve Sistare 2021-04-14 66 * Return: the bit number, else mask->nelems if no bits are set in the range.
6866be5a3aff4b Steve Sistare 2021-04-14 67 */
6866be5a3aff4b Steve Sistare 2021-04-14 68 static inline int
6866be5a3aff4b Steve Sistare 2021-04-14 69 sparsemask_next(const struct sparsemask *mask, int origin, int prev)
6866be5a3aff4b Steve Sistare 2021-04-14 70 {
6866be5a3aff4b Steve Sistare 2021-04-14 71 int density = mask->density;
6866be5a3aff4b Steve Sistare 2021-04-14 72 int bits_per_word = 1U << density;
6866be5a3aff4b Steve Sistare 2021-04-14 73 const struct sparsemask_chunk *chunk;
6866be5a3aff4b Steve Sistare 2021-04-14 74 int nelems = mask->nelems;
6866be5a3aff4b Steve Sistare 2021-04-14 75 int next, bit, nbits;
6866be5a3aff4b Steve Sistare 2021-04-14 76 unsigned long word;
6866be5a3aff4b Steve Sistare 2021-04-14 77
6866be5a3aff4b Steve Sistare 2021-04-14 78 /* Calculate number of bits to be searched. */
6866be5a3aff4b Steve Sistare 2021-04-14 79 if (prev == -1) {
6866be5a3aff4b Steve Sistare 2021-04-14 80 nbits = nelems;
6866be5a3aff4b Steve Sistare 2021-04-14 81 next = origin;
6866be5a3aff4b Steve Sistare 2021-04-14 82 } else if (prev < origin) {
6866be5a3aff4b Steve Sistare 2021-04-14 83 nbits = origin - prev;
6866be5a3aff4b Steve Sistare 2021-04-14 84 next = prev + 1;
6866be5a3aff4b Steve Sistare 2021-04-14 85 } else {
6866be5a3aff4b Steve Sistare 2021-04-14 86 nbits = nelems - prev + origin - 1;
6866be5a3aff4b Steve Sistare 2021-04-14 87 next = prev + 1;
6866be5a3aff4b Steve Sistare 2021-04-14 88 }
6866be5a3aff4b Steve Sistare 2021-04-14 89
6866be5a3aff4b Steve Sistare 2021-04-14 90 if (unlikely(next >= nelems))
6866be5a3aff4b Steve Sistare 2021-04-14 91 return nelems;
6866be5a3aff4b Steve Sistare 2021-04-14 92
6866be5a3aff4b Steve Sistare 2021-04-14 93 /*
6866be5a3aff4b Steve Sistare 2021-04-14 94 * Fetch and adjust first word. Clear word bits below @next, and round
6866be5a3aff4b Steve Sistare 2021-04-14 95 * @next down to @bits_per_word boundary because later ffs will add
6866be5a3aff4b Steve Sistare 2021-04-14 96 * those bits back.
6866be5a3aff4b Steve Sistare 2021-04-14 97 */
6866be5a3aff4b Steve Sistare 2021-04-14 @98 chunk = &mask->chunks[_SMASK_INDEX(density, next)];
6866be5a3aff4b Steve Sistare 2021-04-14 99 bit = _SMASK_BIT(density, next);
6866be5a3aff4b Steve Sistare 2021-04-14 100 word = chunk->word & (~0UL << bit);
6866be5a3aff4b Steve Sistare 2021-04-14 101 next -= bit;
6866be5a3aff4b Steve Sistare 2021-04-14 102 nbits += bit;
6866be5a3aff4b Steve Sistare 2021-04-14 103
6866be5a3aff4b Steve Sistare 2021-04-14 104 while (!word) {
6866be5a3aff4b Steve Sistare 2021-04-14 105 next += bits_per_word;
6866be5a3aff4b Steve Sistare 2021-04-14 106 nbits -= bits_per_word;
6866be5a3aff4b Steve Sistare 2021-04-14 107 if (nbits <= 0)
6866be5a3aff4b Steve Sistare 2021-04-14 108 return nelems;
6866be5a3aff4b Steve Sistare 2021-04-14 109
6866be5a3aff4b Steve Sistare 2021-04-14 110 if (next >= nelems) {
6866be5a3aff4b Steve Sistare 2021-04-14 111 chunk = mask->chunks;
6866be5a3aff4b Steve Sistare 2021-04-14 112 nbits -= (next - nelems);
6866be5a3aff4b Steve Sistare 2021-04-14 113 next = 0;
6866be5a3aff4b Steve Sistare 2021-04-14 114 } else {
6866be5a3aff4b Steve Sistare 2021-04-14 115 chunk++;
6866be5a3aff4b Steve Sistare 2021-04-14 116 }
6866be5a3aff4b Steve Sistare 2021-04-14 117 word = chunk->word;
6866be5a3aff4b Steve Sistare 2021-04-14 118 }
6866be5a3aff4b Steve Sistare 2021-04-14 119
6866be5a3aff4b Steve Sistare 2021-04-14 120 next += __ffs(word);
6866be5a3aff4b Steve Sistare 2021-04-14 121 if (next >= origin && prev != -1)
6866be5a3aff4b Steve Sistare 2021-04-14 122 return nelems;
6866be5a3aff4b Steve Sistare 2021-04-14 123 return next;
6866be5a3aff4b Steve Sistare 2021-04-14 124 }
6866be5a3aff4b Steve Sistare 2021-04-14 125
:::::: The code at line 98 was first introduced by commit
:::::: 6866be5a3aff4bbd949059927d8f8790be53e3dd sched: Provide sparsemask, a reduced contention bitmap
:::::: TO: Steve Sistare <steven.sistare(a)oracle.com>
:::::: CC: Cheng Jian <cj.chengjian(a)huawei.com>
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
From: Petr Mladek <pmladek(a)suse.com>
stable inclusion
from stable-v6.6.23
commit a3b17859c818a4a9a861e8ec0b9c01d28c0770d2
category: bugfix
bugzilla:
CVE: NA
Reference:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
[ Upstream commit d04d5882cd678b898a9d7c5aee6afbe9e6e77fcd ]
The commit d51507098ff91 ("printk: disable optimistic spin
during panic") added checks to avoid becoming a console waiter
if a panic is in progress.
However, the transition to panic can occur while there is
already a waiter. The current owner should not pass the lock to
the waiter because it might get stopped or blocked anytime.
Also the panic context might pass the console lock owner to an
already stopped waiter by mistake. It might happen when
console_flush_on_panic() ignores the current lock owner, for
example:
CPU0 CPU1
---- ----
console_lock_spinning_enable()
console_trylock_spinning()
[CPU1 now console waiter]
NMI: panic()
panic_other_cpus_shutdown()
[stopped as console waiter]
console_flush_on_panic()
console_lock_spinning_enable()
[print 1 record]
console_lock_spinning_disable_and_check()
[handover to stopped CPU1]
This results in panic() not flushing the panic messages.
Fix these problems by disabling all spinning operations
completely during panic().
Another advantage is that it prevents possible deadlocks caused
by "console_owner_lock". The panic() context does not need to
take it any longer. The lockless checks are safe because the
functions become NOPs when they see the panic in progress. All
operations manipulating the state are still synchronized by the
lock even when non-panic CPUs would notice the panic
synchronously.
The current owner might stay spinning. But non-panic() CPUs
would get stopped anyway and the panic context will never start
spinning.
Fixes: dbdda842fe96 ("printk: Add console owner and waiter logic to load balance console writes")
Signed-off-by: John Ogness <john.ogness(a)linutronix.de>
Link: https://lore.kernel.org/r/20240207134103.1357162-12-john.ogness@linutronix.…
Signed-off-by: Petr Mladek <pmladek(a)suse.com>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Ye Weihua <yeweihua4(a)huawei.com>
---
kernel/printk/printk.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 8bccea05df1b..6ebcf40241fd 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1850,10 +1850,23 @@ static bool console_waiter;
*/
static void console_lock_spinning_enable(void)
{
+ /*
+ * Do not use spinning in panic(). The panic CPU wants to keep the lock.
+ * Non-panic CPUs abandon the flush anyway.
+ *
+ * Just keep the lockdep annotation. The panic-CPU should avoid
+ * taking console_owner_lock because it might cause a deadlock.
+ * This looks like the easiest way how to prevent false lockdep
+ * reports without handling races a lockless way.
+ */
+ if (panic_in_progress())
+ goto lockdep;
+
raw_spin_lock(&console_owner_lock);
console_owner = current;
raw_spin_unlock(&console_owner_lock);
+lockdep:
/* The waiter may spin on us after setting console_owner */
spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);
}
@@ -1878,6 +1891,22 @@ static int console_lock_spinning_disable_and_check(int cookie)
{
int waiter;
+ /*
+ * Ignore spinning waiters during panic() because they might get stopped
+ * or blocked at any time,
+ *
+ * It is safe because nobody is allowed to start spinning during panic
+ * in the first place. If there has been a waiter then non panic CPUs
+ * might stay spinning. They would get stopped anyway. The panic context
+ * will never start spinning and an interrupted spin on panic CPU will
+ * never continue.
+ */
+ if (panic_in_progress()) {
+ /* Keep lockdep happy. */
+ spin_release(&console_owner_dep_map, _THIS_IP_);
+ return 0;
+ }
+
raw_spin_lock(&console_owner_lock);
waiter = READ_ONCE(console_waiter);
console_owner = NULL;
--
2.34.1