This is the start of the stable review cycle for the 4.14.324 release.
There are 57 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 30 Aug 2023 10:11:30 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.324-r…
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.14.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Linux 4.14.324-rc1
Rob Clark <robdclark(a)chromium.org>
dma-buf/sw_sync: Avoid recursive lock during fence signal
Zhu Wang <wangzhu9(a)huawei.com>
scsi: core: raid_class: Remove raid_component_add()
Zhu Wang <wangzhu9(a)huawei.com>
scsi: snic: Fix double free in snic_tgt_create()
Ido Schimmel <idosch(a)nvidia.com>
rtnetlink: Reject negative ifindexes in RTM_NEWLINK
Feng Tang <feng.tang(a)intel.com>
x86/fpu: Set X86_FEATURE_OSXSAVE feature after enabling OSXSAVE in CR4
Wei Chen <harperchen1110(a)gmail.com>
media: vcodec: Fix potential array out-of-bounds in encoder queue_setup
Helge Deller <deller(a)gmx.de>
lib/clz_ctz.c: Fix __clzdi2() and __ctzdi2() for 32-bit kernels
Remi Pommarel <repk(a)triplefau.lt>
batman-adv: Fix batadv_v_ogm_aggr_send memory leak
Remi Pommarel <repk(a)triplefau.lt>
batman-adv: Fix TT global entry leak when client roamed back
Remi Pommarel <repk(a)triplefau.lt>
batman-adv: Do not get eth header before batadv_check_management_packet
Sven Eckelmann <sven(a)narfation.org>
batman-adv: Trigger events for auto adjusted MTU
Michael Ellerman <mpe(a)ellerman.id.au>
ibmveth: Use dcbf rather than dcbfl
Sishuai Gong <sishuai.system(a)gmail.com>
ipvs: fix racy memcpy in proc_do_sync_threshold
Junwei Hu <hujunwei4(a)huawei.com>
ipvs: Improve robustness to the ipvs sysctl
Alessio Igor Bogani <alessio.bogani(a)elettra.eu>
igb: Avoid starting unnecessary workqueues
Eric Dumazet <edumazet(a)google.com>
sock: annotate data-races around prot->memory_pressure
Zheng Yejian <zhengyejian1(a)huawei.com>
tracing: Fix memleak due to race between current_tracer and trace
Justin Chen <justin.chen(a)broadcom.com>
net: phy: broadcom: stub c45 read/write for 54810
Lin Ma <linma(a)zju.edu.cn>
net: xfrm: Amend XFRMA_SEC_CTX nla_policy structure
Jason Xing <kernelxing(a)tencent.com>
net: fix the RTO timer retransmitting skb every 1ms if linear option is enabled
Kuniyuki Iwashima <kuniyu(a)amazon.com>
af_unix: Fix null-ptr-deref in unix_stream_sendpage().
Zhang Shurong <zhang_shurong(a)foxmail.com>
ASoC: rt5665: add missed regulator_bulk_disable
Xin Long <lucien.xin(a)gmail.com>
netfilter: set default timeout to 3 secs for sctp shutdown send and recv state
Mirsad Goran Todorovac <mirsad.todorovac(a)alu.unizg.hr>
test_firmware: prevent race conditions by a correct implementation of locking
Qi Zheng <zhengqi.arch(a)bytedance.com>
binder: fix memory leak in binder_init()
Tony Lindgren <tony(a)atomide.com>
serial: 8250: Fix oops for port->pm on uart_change_pm()
Yang Yingliang <yangyingliang(a)huawei.com>
mmc: wbsd: fix double mmc_free_host() in wbsd_init()
Russell Harmon via samba-technical <samba-technical(a)lists.samba.org>
cifs: Release folio lock on fscache read hit.
dengxiang <dengxiang(a)nfschina.com>
ALSA: usb-audio: Add support for Mythware XA001AU capture and playback interfaces.
Eric Dumazet <edumazet(a)google.com>
net: do not allow gso_size to be set to GSO_BY_FRAGS
Abel Wu <wuyun.abel(a)bytedance.com>
sock: Fix misuse of sk_under_memory_pressure()
Andrii Staikov <andrii.staikov(a)intel.com>
i40e: fix misleading debug logs
Ziyang Xuan <william.xuanziyang(a)huawei.com>
team: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves
Pablo Neira Ayuso <pablo(a)netfilter.org>
netfilter: nft_dynset: disallow object maps
Lin Ma <linma(a)zju.edu.cn>
xfrm: add NULL check in xfrm_update_ae_params
Zhengchao Shao <shaozhengchao(a)huawei.com>
ip_vti: fix potential slab-use-after-free in decode_session6
Zhengchao Shao <shaozhengchao(a)huawei.com>
ip6_vti: fix slab-use-after-free in decode_session6
Lin Ma <linma(a)zju.edu.cn>
net: af_key: fix sadb_x_filter validation
Lin Ma <linma(a)zju.edu.cn>
net: xfrm: Fix xfrm_address_filter OOB read
Nathan Lynch <nathanl(a)linux.ibm.com>
powerpc/rtas_flash: allow user copy to flash block cache objects
Yuanjun Gong <ruc_gongyuanjun(a)163.com>
fbdev: mmp: fix value check in mmphw_probe()
shanzhulig <shanzhulig(a)gmail.com>
drm/amdgpu: Fix potential fence use-after-free v2
Zhengping Jiang <jiangzp(a)google.com>
Bluetooth: L2CAP: Fix use-after-free
Armin Wolf <W_Armin(a)gmx.de>
pcmcia: rsrc_nonstatic: Fix memory leak in nonstatic_release_resource_db()
Tuo Li <islituo(a)gmail.com>
gfs2: Fix possible data races in gfs2_show_options()
Hans Verkuil <hverkuil-cisco(a)xs4all.nl>
media: platform: mediatek: vpu: fix NULL ptr dereference
Yunfei Dong <yunfei.dong(a)mediatek.com>
media: v4l2-mem2mem: add lock to protect parameter num_rdy
Immad Mir <mirimmad17(a)gmail.com>
FS: JFS: Check for read-only mounted filesystem in txBegin
Immad Mir <mirimmad17(a)gmail.com>
FS: JFS: Fix null-ptr-deref Read in txBegin
Gustavo A. R. Silva <gustavoars(a)kernel.org>
MIPS: dec: prom: Address -Warray-bounds warning
Yogesh <yogi.kernel(a)gmail.com>
fs: jfs: Fix UBSAN: array-index-out-of-bounds in dbAllocDmapLev
Jan Kara <jack(a)suse.cz>
udf: Fix uninitialized array access for some pathnames
Ye Bin <yebin10(a)huawei.com>
quota: fix warning in dqgrab()
Jan Kara <jack(a)suse.cz>
quota: Properly disable quotas when add_dquot_ref() fails
Oswald Buddenhagen <oswald.buddenhagen(a)gmx.de>
ALSA: emu10k1: roll up loops in DSP setup code for Audigy
hackyzh002 <hackyzh002(a)gmail.com>
drm/radeon: Fix integer overflow in radeon_cs_parser_init
Nathan Chancellor <natechancellor(a)gmail.com>
lib/mpi: Eliminate unused umul_ppmm definitions for MIPS
-------------
Diffstat:
Makefile | 4 +-
arch/mips/include/asm/dec/prom.h | 2 +-
arch/powerpc/kernel/rtas_flash.c | 6 +-
arch/x86/kernel/fpu/xstate.c | 8 ++
drivers/android/binder.c | 1 +
drivers/android/binder_alloc.c | 6 ++
drivers/android/binder_alloc.h | 1 +
drivers/dma-buf/sw_sync.c | 18 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 3 +
drivers/gpu/drm/radeon/radeon_cs.c | 3 +-
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 2 +
drivers/media/platform/mtk-vpu/mtk_vpu.c | 6 +-
drivers/mmc/host/wbsd.c | 2 -
drivers/net/ethernet/ibm/ibmveth.c | 2 +-
drivers/net/ethernet/intel/i40e/i40e_nvm.c | 16 +--
drivers/net/ethernet/intel/igb/igb_ptp.c | 24 ++---
drivers/net/phy/broadcom.c | 13 +++
drivers/net/team/team.c | 4 +-
drivers/pcmcia/rsrc_nonstatic.c | 2 +
drivers/scsi/raid_class.c | 48 ---------
drivers/scsi/snic/snic_disc.c | 3 +-
drivers/tty/serial/8250/8250_port.c | 1 +
drivers/video/fbdev/mmp/hw/mmp_ctrl.c | 4 +-
fs/cifs/file.c | 2 +-
fs/gfs2/super.c | 26 +++--
fs/jfs/jfs_dmap.c | 3 +
fs/jfs/jfs_txnmgr.c | 5 +
fs/jfs/namei.c | 5 +
fs/quota/dquot.c | 5 +-
fs/udf/unicode.c | 2 +-
include/linux/raid_class.h | 4 -
include/linux/virtio_net.h | 4 +
include/media/v4l2-mem2mem.h | 18 +++-
include/net/sock.h | 11 +-
kernel/trace/trace.c | 9 +-
kernel/trace/trace_irqsoff.c | 3 +-
kernel/trace/trace_sched_wakeup.c | 2 +
lib/clz_ctz.c | 32 ++----
lib/mpi/longlong.h | 36 +------
lib/test_firmware.c | 39 +++++--
net/batman-adv/bat_v_elp.c | 3 +-
net/batman-adv/bat_v_ogm.c | 7 +-
net/batman-adv/hard-interface.c | 2 +-
net/batman-adv/translation-table.c | 1 -
net/bluetooth/l2cap_core.c | 5 +
net/core/rtnetlink.c | 5 +-
net/core/sock.c | 2 +-
net/ipv4/ip_vti.c | 4 +-
net/ipv4/tcp_timer.c | 4 +-
net/ipv6/ip6_vti.c | 4 +-
net/key/af_key.c | 4 +-
net/netfilter/ipvs/ip_vs_ctl.c | 74 +++++++-------
net/netfilter/nf_conntrack_proto_sctp.c | 6 +-
net/netfilter/nft_dynset.c | 3 +
net/sctp/socket.c | 2 +-
net/unix/af_unix.c | 9 +-
net/xfrm/xfrm_user.c | 13 ++-
sound/pci/emu10k1/emufx.c | 112 ++-------------------
sound/soc/codecs/rt5665.c | 2 +
sound/usb/quirks-table.h | 29 ++++++
60 files changed, 325 insertions(+), 351 deletions(-)
From: Linus Torvalds <torvalds(a)linux-foundation.org>
[ upstream commit 5ef64cc8987a9211d3f3667331ba3411a94ddc79 ]
Commit 2a9127fcf229 ("mm: rewrite wait_on_page_bit_common() logic") made
the page locking entirely fair, in that if a waiter came in while the
lock was held, the lock would be transferred to the lockers strictly in
order.
That was intended to finally get rid of the long-reported watchdog
failures that involved the page lock under extreme load, where a process
could end up waiting essentially forever, as other page lockers stole
the lock from under it.
It also improved some benchmarks, but it ended up causing huge
performance regressions on others, simply because fair lock behavior
doesn't end up giving out the lock as aggressively, causing better
worst-case latency, but potentially much worse average latencies and
throughput.
Instead of reverting that change entirely, this introduces a controlled
amount of unfairness, with a sysctl knob to tune it if somebody needs
to. But the default value should hopefully be good for any normal load,
allowing a few rounds of lock stealing, but enforcing the strict
ordering before the lock has been stolen too many times.
There is also a hint from Matthieu Baerts that the fair page coloring
may end up exposing an ABBA deadlock that is hidden by the usual
optimistic lock stealing, and while the unfairness doesn't fix the
fundamental issue (and I'm still looking at that), it avoids it in
practice.
The amount of unfairness can be modified by writing a new value to the
'sysctl_page_lock_unfairness' variable (default value of 5, exposed
through /proc/sys/vm/page_lock_unfairness), but that is hopefully
something we'd use mainly for debugging rather than being necessary for
any deep system tuning.
This whole issue has exposed just how critical the page lock can be, and
how contended it gets under certain locks. And the main contention
doesn't really seem to be anything related to IO (which was the origin
of this lock), but for things like just verifying that the page file
mapping is stable while faulting in the page into a page table.
Link: https://lore.kernel.org/linux-fsdevel/ed8442fd-6f54-dd84-cd4a-941e8b7ee603@…
Link: https://www.phoronix.com/scan.php?page=article&item=linux-50-59&num=1
Link: https://lore.kernel.org/linux-fsdevel/c560a38d-8313-51fb-b1ec-e904bd8836bc@…
Reported-and-tested-by: Michael Larabel <Michael(a)michaellarabel.com>
Tested-by: Matthieu Baerts <matthieu.baerts(a)tessares.net>
Cc: Dave Chinner <david(a)fromorbit.com>
Cc: Matthew Wilcox <willy(a)infradead.org>
Cc: Chris Mason <clm(a)fb.com>
Cc: Jan Kara <jack(a)suse.cz>
Cc: Amir Goldstein <amir73il(a)gmail.com>
Signed-off-by: Linus Torvalds <torvalds(a)linux-foundation.org>
CC: <stable(a)vger.kernel.org> # 5.4
[ mheyne: fixed contextual conflict in mm/filemap.c due to missing
commit c7510ab2cf5c ("mm: abstract out wake_page_match() from
wake_page_function()"). Added WQ_FLAG_CUSTOM due to missing commit
7f26482a872c ("locking/percpu-rwsem: Remove the embedded rwsem") ]
Signed-off-by: Maximilian Heyne <mheyne(a)amazon.de>
---
include/linux/mm.h | 2 +
include/linux/wait.h | 2 +
kernel/sysctl.c | 8 +++
mm/filemap.c | 160 ++++++++++++++++++++++++++++++++++---------
4 files changed, 141 insertions(+), 31 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d35c29d322d8..d14aba548ff4 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -37,6 +37,8 @@ struct user_struct;
struct writeback_control;
struct bdi_writeback;
+extern int sysctl_page_lock_unfairness;
+
void init_mm_internals(void);
#ifndef CONFIG_NEED_MULTIPLE_NODES /* Don't use mapnrs, do it properly */
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 7d04c1b588c7..03bff85e365f 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -20,6 +20,8 @@ int default_wake_function(struct wait_queue_entry *wq_entry, unsigned mode, int
#define WQ_FLAG_EXCLUSIVE 0x01
#define WQ_FLAG_WOKEN 0x02
#define WQ_FLAG_BOOKMARK 0x04
+#define WQ_FLAG_CUSTOM 0x08
+#define WQ_FLAG_DONE 0x10
/*
* A single wait-queue entry structure:
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index decabf5714c0..4f85f7ed42fc 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1563,6 +1563,14 @@ static struct ctl_table vm_table[] = {
.proc_handler = percpu_pagelist_fraction_sysctl_handler,
.extra1 = SYSCTL_ZERO,
},
+ {
+ .procname = "page_lock_unfairness",
+ .data = &sysctl_page_lock_unfairness,
+ .maxlen = sizeof(sysctl_page_lock_unfairness),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ },
#ifdef CONFIG_MMU
{
.procname = "max_map_count",
diff --git a/mm/filemap.c b/mm/filemap.c
index adc27af737c6..f1ed0400c37c 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1044,9 +1044,43 @@ struct wait_page_queue {
wait_queue_entry_t wait;
};
+/*
+ * The page wait code treats the "wait->flags" somewhat unusually, because
+ * we have multiple different kinds of waits, not just he usual "exclusive"
+ * one.
+ *
+ * We have:
+ *
+ * (a) no special bits set:
+ *
+ * We're just waiting for the bit to be released, and when a waker
+ * calls the wakeup function, we set WQ_FLAG_WOKEN and wake it up,
+ * and remove it from the wait queue.
+ *
+ * Simple and straightforward.
+ *
+ * (b) WQ_FLAG_EXCLUSIVE:
+ *
+ * The waiter is waiting to get the lock, and only one waiter should
+ * be woken up to avoid any thundering herd behavior. We'll set the
+ * WQ_FLAG_WOKEN bit, wake it up, and remove it from the wait queue.
+ *
+ * This is the traditional exclusive wait.
+ *
+ * (b) WQ_FLAG_EXCLUSIVE | WQ_FLAG_CUSTOM:
+ *
+ * The waiter is waiting to get the bit, and additionally wants the
+ * lock to be transferred to it for fair lock behavior. If the lock
+ * cannot be taken, we stop walking the wait queue without waking
+ * the waiter.
+ *
+ * This is the "fair lock handoff" case, and in addition to setting
+ * WQ_FLAG_WOKEN, we set WQ_FLAG_DONE to let the waiter easily see
+ * that it now has the lock.
+ */
static int wake_page_function(wait_queue_entry_t *wait, unsigned mode, int sync, void *arg)
{
- int ret;
+ unsigned int flags;
struct wait_page_key *key = arg;
struct wait_page_queue *wait_page
= container_of(wait, struct wait_page_queue, wait);
@@ -1059,35 +1093,44 @@ static int wake_page_function(wait_queue_entry_t *wait, unsigned mode, int sync,
return 0;
/*
- * If it's an exclusive wait, we get the bit for it, and
- * stop walking if we can't.
- *
- * If it's a non-exclusive wait, then the fact that this
- * wake function was called means that the bit already
- * was cleared, and we don't care if somebody then
- * re-took it.
+ * If it's a lock handoff wait, we get the bit for it, and
+ * stop walking (and do not wake it up) if we can't.
*/
- ret = 0;
- if (wait->flags & WQ_FLAG_EXCLUSIVE) {
- if (test_and_set_bit(key->bit_nr, &key->page->flags))
+ flags = wait->flags;
+ if (flags & WQ_FLAG_EXCLUSIVE) {
+ if (test_bit(key->bit_nr, &key->page->flags))
return -1;
- ret = 1;
+ if (flags & WQ_FLAG_CUSTOM) {
+ if (test_and_set_bit(key->bit_nr, &key->page->flags))
+ return -1;
+ flags |= WQ_FLAG_DONE;
+ }
}
- wait->flags |= WQ_FLAG_WOKEN;
+ /*
+ * We are holding the wait-queue lock, but the waiter that
+ * is waiting for this will be checking the flags without
+ * any locking.
+ *
+ * So update the flags atomically, and wake up the waiter
+ * afterwards to avoid any races. This store-release pairs
+ * with the load-acquire in wait_on_page_bit_common().
+ */
+ smp_store_release(&wait->flags, flags | WQ_FLAG_WOKEN);
wake_up_state(wait->private, mode);
/*
* Ok, we have successfully done what we're waiting for,
* and we can unconditionally remove the wait entry.
*
- * Note that this has to be the absolute last thing we do,
- * since after list_del_init(&wait->entry) the wait entry
+ * Note that this pairs with the "finish_wait()" in the
+ * waiter, and has to be the absolute last thing we do.
+ * After this list_del_init(&wait->entry) the wait entry
* might be de-allocated and the process might even have
* exited.
*/
list_del_init_careful(&wait->entry);
- return ret;
+ return (flags & WQ_FLAG_EXCLUSIVE) != 0;
}
static void wake_up_page_bit(struct page *page, int bit_nr)
@@ -1167,8 +1210,8 @@ enum behavior {
};
/*
- * Attempt to check (or get) the page bit, and mark the
- * waiter woken if successful.
+ * Attempt to check (or get) the page bit, and mark us done
+ * if successful.
*/
static inline bool trylock_page_bit_common(struct page *page, int bit_nr,
struct wait_queue_entry *wait)
@@ -1179,13 +1222,17 @@ static inline bool trylock_page_bit_common(struct page *page, int bit_nr,
} else if (test_bit(bit_nr, &page->flags))
return false;
- wait->flags |= WQ_FLAG_WOKEN;
+ wait->flags |= WQ_FLAG_WOKEN | WQ_FLAG_DONE;
return true;
}
+/* How many times do we accept lock stealing from under a waiter? */
+int sysctl_page_lock_unfairness = 5;
+
static inline int wait_on_page_bit_common(wait_queue_head_t *q,
struct page *page, int bit_nr, int state, enum behavior behavior)
{
+ int unfairness = sysctl_page_lock_unfairness;
struct wait_page_queue wait_page;
wait_queue_entry_t *wait = &wait_page.wait;
bool thrashing = false;
@@ -1203,11 +1250,18 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
}
init_wait(wait);
- wait->flags = behavior == EXCLUSIVE ? WQ_FLAG_EXCLUSIVE : 0;
wait->func = wake_page_function;
wait_page.page = page;
wait_page.bit_nr = bit_nr;
+repeat:
+ wait->flags = 0;
+ if (behavior == EXCLUSIVE) {
+ wait->flags = WQ_FLAG_EXCLUSIVE;
+ if (--unfairness < 0)
+ wait->flags |= WQ_FLAG_CUSTOM;
+ }
+
/*
* Do one last check whether we can get the
* page bit synchronously.
@@ -1230,27 +1284,63 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
/*
* From now on, all the logic will be based on
- * the WQ_FLAG_WOKEN flag, and the and the page
- * bit testing (and setting) will be - or has
- * already been - done by the wake function.
+ * the WQ_FLAG_WOKEN and WQ_FLAG_DONE flag, to
+ * see whether the page bit testing has already
+ * been done by the wake function.
*
* We can drop our reference to the page.
*/
if (behavior == DROP)
put_page(page);
+ /*
+ * Note that until the "finish_wait()", or until
+ * we see the WQ_FLAG_WOKEN flag, we need to
+ * be very careful with the 'wait->flags', because
+ * we may race with a waker that sets them.
+ */
for (;;) {
+ unsigned int flags;
+
set_current_state(state);
- if (signal_pending_state(state, current))
+ /* Loop until we've been woken or interrupted */
+ flags = smp_load_acquire(&wait->flags);
+ if (!(flags & WQ_FLAG_WOKEN)) {
+ if (signal_pending_state(state, current))
+ break;
+
+ io_schedule();
+ continue;
+ }
+
+ /* If we were non-exclusive, we're done */
+ if (behavior != EXCLUSIVE)
break;
- if (wait->flags & WQ_FLAG_WOKEN)
+ /* If the waker got the lock for us, we're done */
+ if (flags & WQ_FLAG_DONE)
break;
- io_schedule();
+ /*
+ * Otherwise, if we're getting the lock, we need to
+ * try to get it ourselves.
+ *
+ * And if that fails, we'll have to retry this all.
+ */
+ if (unlikely(test_and_set_bit(bit_nr, &page->flags)))
+ goto repeat;
+
+ wait->flags |= WQ_FLAG_DONE;
+ break;
}
+ /*
+ * If a signal happened, this 'finish_wait()' may remove the last
+ * waiter from the wait-queues, but the PageWaiters bit will remain
+ * set. That's ok. The next wakeup will take care of it, and trying
+ * to do it here would be difficult and prone to races.
+ */
finish_wait(q, wait);
if (thrashing) {
@@ -1260,12 +1350,20 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
}
/*
- * A signal could leave PageWaiters set. Clearing it here if
- * !waitqueue_active would be possible (by open-coding finish_wait),
- * but still fail to catch it in the case of wait hash collision. We
- * already can fail to clear wait hash collision cases, so don't
- * bother with signals either.
+ * NOTE! The wait->flags weren't stable until we've done the
+ * 'finish_wait()', and we could have exited the loop above due
+ * to a signal, and had a wakeup event happen after the signal
+ * test but before the 'finish_wait()'.
+ *
+ * So only after the finish_wait() can we reliably determine
+ * if we got woken up or not, so we can now figure out the final
+ * return value based on that state without races.
+ *
+ * Also note that WQ_FLAG_WOKEN is sufficient for a non-exclusive
+ * waiter, but an exclusive one requires WQ_FLAG_DONE.
*/
+ if (behavior == EXCLUSIVE)
+ return wait->flags & WQ_FLAG_DONE ? 0 : -EINTR;
return wait->flags & WQ_FLAG_WOKEN ? 0 : -EINTR;
}
--
2.40.1
Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879
From: Song Shuai <suagrfillet(a)gmail.com>
The pt_level uses CONFIG_PGTABLE_LEVELS to display page table names.
But if page mode is downgraded from kernel cmdline or restricted by
the hardware in 64BIT, it will give a wrong name.
Like, using no4lvl for sv39, ptdump named the 1G-mapping as "PUD"
that should be "PGD":
0xffffffd840000000-0xffffffd900000000 0x00000000c0000000 3G PUD D A G . . W R V
So select "P4D/PUD" or "PGD" via pgtable_l5/4_enabled to correct it.
Fixes: e8a62cc26ddf ("riscv: Implement sv48 support")
Reviewed-by: Alexandre Ghiti <alexghiti(a)rivosinc.com>
Signed-off-by: Song Shuai <suagrfillet(a)gmail.com>
Link: https://lore.kernel.org/r/20230712115740.943324-1-suagrfillet@gmail.com
Cc: stable(a)vger.kernel.org
Signed-off-by: Palmer Dabbelt <palmer(a)rivosinc.com>
---
arch/riscv/mm/ptdump.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c
index 20a9f991a6d7..e9090b38f811 100644
--- a/arch/riscv/mm/ptdump.c
+++ b/arch/riscv/mm/ptdump.c
@@ -384,6 +384,9 @@ static int __init ptdump_init(void)
kernel_ptd_info.base_addr = KERN_VIRT_START;
+ pg_level[1].name = pgtable_l5_enabled ? "P4D" : "PGD";
+ pg_level[2].name = pgtable_l4_enabled ? "PUD" : "PGD";
+
for (i = 0; i < ARRAY_SIZE(pg_level); i++)
for (j = 0; j < ARRAY_SIZE(pte_bits); j++)
pg_level[i].mask |= pte_bits[j].mask;
--
2.41.0
There are instances where rcu_cpu_stall_reset() is called when jiffies
did not get a chance to update for a long time. Before jiffies is
updated, the CPU stall detector can go off triggering false-positives
where a just-started grace period appears to be ages old. In the past,
we disabled stall detection in rcu_cpu_stall_reset() however this got
changed [1]. This is resulting in false-positives in KGDB usecase [2].
Fix this by deferring the update of jiffies to the third run of the FQS
loop. This is more robust, as, even if rcu_cpu_stall_reset() is called
just before jiffies is read, we would end up pushing out the jiffies
read by 3 more FQS loops. Meanwhile the CPU stall detection will be
delayed and we will not get any false positives.
[1] https://lore.kernel.org/all/20210521155624.174524-2-senozhatsky@chromium.or…
[2] https://lore.kernel.org/all/20230814020045.51950-2-chenhuacai@loongson.cn/
Tested with rcutorture.cpu_stall option as well to verify stall behavior
with/without patch.
Tested-by: Huacai Chen <chenhuacai(a)loongson.cn>
Reported-by: Huacai Chen <chenhuacai(a)loongson.cn>
Closes: https://lore.kernel.org/all/20230814020045.51950-2-chenhuacai@loongson.cn/
Suggested-by: Paul McKenney <paulmck(a)kernel.org>
Cc: Sergey Senozhatsky <senozhatsky(a)chromium.org>
Cc: Thomas Gleixner <tglx(a)linutronix.de>
Cc: stable(a)vger.kernel.org
Fixes: a80be428fbc1 ("rcu: Do not disable GP stall detection in rcu_cpu_stall_reset()")
Signed-off-by: Joel Fernandes (Google) <joel(a)joelfernandes.org>
---
kernel/rcu/tree.c | 12 ++++++++++++
kernel/rcu/tree.h | 4 ++++
kernel/rcu/tree_stall.h | 20 ++++++++++++++++++--
3 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 1449cb69a0e0..b695c0eb515a 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -1552,10 +1552,22 @@ static bool rcu_gp_fqs_check_wake(int *gfp)
*/
static void rcu_gp_fqs(bool first_time)
{
+ int nr_fqs = READ_ONCE(rcu_state.nr_fqs_jiffies_stall);
struct rcu_node *rnp = rcu_get_root();
WRITE_ONCE(rcu_state.gp_activity, jiffies);
WRITE_ONCE(rcu_state.n_force_qs, rcu_state.n_force_qs + 1);
+
+ WARN_ON_ONCE(nr_fqs > 3);
+ /* Only countdown nr_fqs for stall purposes if jiffies moves. */
+ if (nr_fqs) {
+ if (nr_fqs == 1) {
+ WRITE_ONCE(rcu_state.jiffies_stall,
+ jiffies + rcu_jiffies_till_stall_check());
+ }
+ WRITE_ONCE(rcu_state.nr_fqs_jiffies_stall, --nr_fqs);
+ }
+
if (first_time) {
/* Collect dyntick-idle snapshots. */
force_qs_rnp(dyntick_save_progress_counter);
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index 192536916f9a..e9821a8422db 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -386,6 +386,10 @@ struct rcu_state {
/* in jiffies. */
unsigned long jiffies_stall; /* Time at which to check */
/* for CPU stalls. */
+ int nr_fqs_jiffies_stall; /* Number of fqs loops after
+ * which read jiffies and set
+ * jiffies_stall. Stall
+ * warnings disabled if !0. */
unsigned long jiffies_resched; /* Time at which to resched */
/* a reluctant CPU. */
unsigned long n_force_qs_gpstart; /* Snapshot of n_force_qs at */
diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
index b10b8349bb2a..a2fa6b22e248 100644
--- a/kernel/rcu/tree_stall.h
+++ b/kernel/rcu/tree_stall.h
@@ -149,12 +149,17 @@ static void panic_on_rcu_stall(void)
/**
* rcu_cpu_stall_reset - restart stall-warning timeout for current grace period
*
+ * To perform the reset request from the caller, disable stall detection until
+ * 3 fqs loops have passed. This is required to ensure a fresh jiffies is
+ * loaded. It should be safe to do from the fqs loop as enough timer
+ * interrupts and context switches should have passed.
+ *
* The caller must disable hard irqs.
*/
void rcu_cpu_stall_reset(void)
{
- WRITE_ONCE(rcu_state.jiffies_stall,
- jiffies + rcu_jiffies_till_stall_check());
+ WRITE_ONCE(rcu_state.nr_fqs_jiffies_stall, 3);
+ WRITE_ONCE(rcu_state.jiffies_stall, ULONG_MAX);
}
//////////////////////////////////////////////////////////////////////////////
@@ -170,6 +175,7 @@ static void record_gp_stall_check_time(void)
WRITE_ONCE(rcu_state.gp_start, j);
j1 = rcu_jiffies_till_stall_check();
smp_mb(); // ->gp_start before ->jiffies_stall and caller's ->gp_seq.
+ WRITE_ONCE(rcu_state.nr_fqs_jiffies_stall, 0);
WRITE_ONCE(rcu_state.jiffies_stall, j + j1);
rcu_state.jiffies_resched = j + j1 / 2;
rcu_state.n_force_qs_gpstart = READ_ONCE(rcu_state.n_force_qs);
@@ -725,6 +731,16 @@ static void check_cpu_stall(struct rcu_data *rdp)
!rcu_gp_in_progress())
return;
rcu_stall_kick_kthreads();
+
+ /*
+ * Check if it was requested (via rcu_cpu_stall_reset()) that the FQS
+ * loop has to set jiffies to ensure a non-stale jiffies value. This
+ * is required to have good jiffies value after coming out of long
+ * breaks of jiffies updates. Not doing so can cause false positives.
+ */
+ if (READ_ONCE(rcu_state.nr_fqs_jiffies_stall) > 0)
+ return;
+
j = jiffies;
/*
--
2.42.0.rc2.253.gd59a3bf2b4-goog
Dear friend
my name is Mohamed Abdul please send me your what-sap number for easy
communication i have millions of dollars to invest
thanks
Mohamed Abdul
In the line 910, the value of m1 may be zero, so there is a possibility
of dividing by zero, we fixed it by checking the values before dividing
(found with SVACE). In the same way, after checking and reading the
function, we found that lines 906, 908, 912 have the same situation, so
we fixed them as well.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Signed-off-by: Rand Deeb <deeb.rand(a)confident.ru>
---
drivers/ssb/main.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 0a26984acb2c..e0776a16d04d 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -903,13 +903,21 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)
case SSB_CHIPCO_CLK_MC_BYPASS:
return clock;
case SSB_CHIPCO_CLK_MC_M1:
- return (clock / m1);
+ if (m1 != 0)
+ return (clock / m1);
+ break;
case SSB_CHIPCO_CLK_MC_M1M2:
- return (clock / (m1 * m2));
+ if ((m1 * m2) != 0)
+ return (clock / (m1 * m2));
+ break;
case SSB_CHIPCO_CLK_MC_M1M2M3:
- return (clock / (m1 * m2 * m3));
+ if ((m1 * m2 * m3) != 0)
+ return (clock / (m1 * m2 * m3));
+ break;
case SSB_CHIPCO_CLK_MC_M1M3:
- return (clock / (m1 * m3));
+ if ((m1 * m3) != 0)
+ return (clock / (m1 * m3));
+ break;
}
return 0;
case SSB_PLLTYPE_2:
--
2.34.1