can: statistics: use atomic access in hot path
Subsystems (5)
Sasha Levin
maintainerPATCH 1/5 can: statistics: use atomic access in hot path
From: Oliver Hartkopp <[email protected]>
[ Upstream commit 80b5f90158d1364cbd80ad82852a757fc0692bf2 ]
In can_send() and can_receive() CAN messages and CAN filter matches are counted to be visible in the CAN procfs files.
KCSAN detected a data race within can_send() when two CAN frames have been generated by a timer event writing to the same CAN netdevice at the same time. Use atomic operations to access the statistics in the hot path to fix the KCSAN complaint.
--- net/can/af_can.c | 12 ++++++------ net/can/af_can.h | 12 ++++++------ net/can/proc.c | 46 +++++++++++++++++++++++++++------------------- 3 files changed, 39 insertions(+), 31 deletions(-)
net/can/af_can.c +6 -6
@@ -287,8 +287,8 @@ int can_send(struct sk_buff *skb, int loop)netif_rx (newskb);/* update statistics */ - pkg_stats->tx_frames++; - pkg_stats->tx_frames_delta++; +atomic_long_inc (&pkg_stats->tx_frames); +atomic_long_inc (&pkg_stats->tx_frames_delta);return 0 ;
@@ -647,8 +647,8 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev)int matches;/* update statistics */ - pkg_stats->rx_frames++; - pkg_stats->rx_frames_delta++; +atomic_long_inc (&pkg_stats->rx_frames); +atomic_long_inc (&pkg_stats->rx_frames_delta);/* create non-zero unique skb identifier together with *skb */ while (!(can_skb_prv (skb)->skbcnt))
@@ -669,8 +669,8 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev)consume_skb (skb);if (matches >0 ) { - pkg_stats->matches++; - pkg_stats->matches_delta++; +atomic_long_inc (&pkg_stats->matches); +atomic_long_inc (&pkg_stats->matches_delta); } }
net/can/af_can.h +6 -6
@@ -66,9 +66,9 @@ struct receiver {struct can_pkg_stats {unsigned long jiffies_init; -unsigned long rx_frames; -unsigned long tx_frames; -unsigned long matches; +atomic_long_t rx_frames; +atomic_long_t tx_frames; +atomic_long_t matches;unsigned long total_rx_rate;unsigned long total_tx_rate;
@@ -82,9 +82,9 @@ struct can_pkg_stats {unsigned long max_tx_rate;unsigned long max_rx_match_ratio; -unsigned long rx_frames_delta; -unsigned long tx_frames_delta; -unsigned long matches_delta; +atomic_long_t rx_frames_delta; +atomic_long_t tx_frames_delta; +atomic_long_t matches_delta; };/* persistent statistics */
net/can/proc.c +27 -19
86 lines not on this page · raw message
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH 2/5 memory: omap-gpmc: drop no compatible check
From: Roger Quadros <[email protected]>
[ Upstream commit edcccc6892f65eff5fd3027a13976131dc7fd733 ]
We are no longer depending on legacy device trees so drop the no compatible check for NAND and OneNAND nodes.
--- drivers/memory/omap-gpmc.c | 20 -------------------- 1 file changed, 20 deletions(-)
drivers/memory/omap-gpmc.c +0 -20
@@ -2245,26 +2245,6 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, goto err; } -if (of_node_name_eq (child,"nand" )) { -/* Warn about older DT blobs with no compatible property */ -if (!of_property_read_bool (child,"compatible" )) { -dev_warn (&pdev->dev, -"Incompatible NAND node: missing compatible" ); - ret = -EINVAL ; - goto err; - } - } - -if (of_node_name_eq (child,"onenand" )) { -/* Warn about older DT blobs with no compatible property */ -if (!of_property_read_bool (child,"compatible" )) { -dev_warn (&pdev->dev, -"Incompatible OneNAND node: missing compatible" ); - ret = -EINVAL ; - goto err; - } - } -if (of_match_node (omap_nand_ids, child)) {/* NAND specific setup */ val =8 ;
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH 3/5 Revert "sched/core: Reduce cost of sched_move_task when config autogroup"
In reply to Sasha LevinFrom: Dietmar Eggemann <[email protected]>
[ Upstream commit 76f970ce51c80f625eb6ddbb24e9cb51b977b598 ]
This reverts commit eff6c8ce8d4d7faef75f66614dd20bb50595d261.
Hazem reported a 30% drop in UnixBench spawn test with commit eff6c8ce8d4d ("sched/core: Reduce cost of sched_move_task when config autogroup") on a m6g.xlarge AWS EC2 instance with 4 vCPUs and 16 GiB RAM (aarch64) (single level MC sched domain):
https://lkml.kernel.org/r/[email protected]
There is an early bail from sched_move_task() if p->sched_task_group is equal to p's 'cpu cgroup' (sched_get_task_group()). E.g. both are pointing to taskgroup '/user.slice/user-1000.slice/session-1.scope' (Ubuntu '22.04.5 LTS').
So in:
do_exit()
sched_autogroup_exit_task()
sched_move_task()
if sched_get_task_group(p) == p->sched_task_group
return
/* p is enqueued */
dequeue_task() \
sched_change_group() |
task_change_group_fair() |
detach_task_cfs_rq() | (1)
set_task_rq() |
attach_task_cfs_rq() |
enqueue_task() /(1) isn't called for p anymore.
Turns out that the regression is related to sgs->group_util in group_is_overloaded() and group_has_capacity(). If (1) isn't called for all the 'spawn' tasks then sgs->group_util is ~900 and sgs->group_capacity = 1024 (single CPU sched domain) and this leads to group_is_overloaded() returning true (2) and group_has_capacity() false
(3) much more often compared to the case when (1) is called.
I.e. there are much more cases of 'group_is_overloaded' and 'group_fully_busy' in WF_FORK wakeup sched_balance_find_dst_cpu() which then returns much more often a CPU != smp_processor_id() (5).
This isn't good for these extremely short running tasks (FORK + EXIT) and also involves calling sched_balance_find_dst_group_cpu() unnecessary (single CPU sched domain).
Instead if (1) is called for 'p->flags & PF_EXITING' then the path (4),(6) is taken much more often.
select_task_rq_fair(..., wake_flags = WF_FORK)
cpu = smp_processor_id()
new_cpu = sched_balance_find_dst_cpu(..., cpu, ...)
group = sched_balance_find_dst_group(..., cpu)
do {
update_sg_wakeup_stats()
sgs->group_type = group_classify()
if group_is_overloaded() (2)
return group_overloaded
if !group_has_capacity() (3)
return group_fully_busy
return group_has_spare (4)
} while group
if local_sgs.group_type > idlest_sgs.group_type
return idlest (5)
case group_has_spare:
if local_sgs.idle_cpus >= idlest_sgs.idle_cpus
return NULL (6)
Unixbench Tests './Run -c 4 spawn' on:
(a) VM AWS instance (m7gd.16xlarge) with v6.13 ('maxcpus=4 nr_cpus=4')
and Ubuntu 22.04.5 LTS (aarch64).
Shell & test run in '/user.slice/user-1000.slice/session-1.scope'.
w/o patch w/ patch
21005 27120(b) i7-13700K with tip/sched/core ('nosmt maxcpus=8 nr_cpus=8') and Ubuntu 22.04.5 LTS (x86_64).
Shell & test run in '/A'.
w/o patch w/ patch
67675 88806
CONFIG_SCHED_AUTOGROUP=y & /sys/proc/kernel/sched_autogroup_enabled equal 0 or 1.
--- kernel/sched/core.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-)
kernel/sched/core.c +3 -18
@@ -8919,7 +8919,7 @@ void sched_release_group(struct task_group *tg)spin_unlock_irqrestore (&task_group_lock, flags); } -static struct task_group *sched_get_task_group (struct task_struct *tsk) +static void sched_change_group (struct task_struct *tsk) {struct task_group *tg;
@@ -8931,13 +8931,7 @@ static struct task_group *sched_get_task_group(struct task_struct *tsk) tg =container_of (task_css_check (tsk, cpu_cgrp_id, true), struct task_group, css); tg =autogroup_task_group (tsk, tg); - -return tg; -} - -static void sched_change_group (struct task_struct *tsk,struct task_group *group) -{ - tsk->sched_task_group = group; + tsk->sched_task_group = tg;#ifdef CONFIG_FAIR_GROUP_SCHED if (tsk->sched_class->task_change_group)
@@ -8958,20 +8952,11 @@ void sched_move_task(struct task_struct *tsk, bool for_autogroup) {int queued, running, queue_flags =DEQUEUE_SAVE |DEQUEUE_MOVE |DEQUEUE_NOCLOCK ; -struct task_group *group;struct rq *rq;CLASS (task_rq_lock, rq_guard)(tsk); rq = rq_guard.rq; -/* -* Esp. with SCHED_AUTOGROUP enabled it is possible to get superfluous -* group changes. -*/ - group =sched_get_task_group (tsk); -if (group == tsk->sched_task_group) -return ; -update_rq_clock (rq); running =task_current (rq, tsk);
@@ -8982,7 +8967,7 @@ void sched_move_task(struct task_struct *tsk, bool for_autogroup)if (running)put_prev_task (rq, tsk); -sched_change_group (tsk, group); +sched_change_group (tsk);if (!for_autogroup)scx_cgroup_move_task (tsk);
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH 4/5 hwmon: (nct6775-core) Fix out of bounds access for NCT679{8,9}
In reply to Sasha LevinFrom: Tasos Sahanidis <[email protected]>
[ Upstream commit 815f80ad20b63830949a77c816e35395d5d55144 ]
pwm_num is set to 7 for these chips, but NCT6776_REG_PWM_MODE and NCT6776_PWM_MODE_MASK only contain 6 values.
Fix this by adding another 0 to the end of each array.
--- drivers/hwmon/nct6775-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/hwmon/nct6775-core.c +2 -2
@@ -273,8 +273,8 @@ static const s8 NCT6776_BEEP_BITS[NUM_BEEP_BITS] = {static const u16 NCT6776_REG_TOLERANCE_H [] = {0x10c ,0x20c ,0x30c ,0x80c ,0x90c ,0xa0c ,0xb0c }; -static const u8 NCT6776_REG_PWM_MODE [] = {0x04 ,0 ,0 ,0 ,0 ,0 }; -static const u8 NCT6776_PWM_MODE_MASK [] = {0x01 ,0 ,0 ,0 ,0 ,0 }; +static const u8 NCT6776_REG_PWM_MODE [] = {0x04 ,0 ,0 ,0 ,0 ,0 ,0 }; +static const u8 NCT6776_PWM_MODE_MASK [] = {0x01 ,0 ,0 ,0 ,0 ,0 ,0 };static const u16 NCT6776_REG_FAN_MIN [] = {0x63a ,0x63c ,0x63e ,0x640 ,0x642 ,0x64a ,0x64c };
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH 5/5 netfs: Fix netfs_unbuffered_read() to return ssize_t rather than int
In reply to Sasha LevinFrom: David Howells <[email protected]>
[ Upstream commit 07c574eb53d4cc9aa7b985bc8bfcb302e5dc4694 ]
Fix netfs_unbuffered_read() to return an ssize_t rather than an int as netfs_wait_for_read() returns ssize_t and this gets implicitly truncated.
--- fs/netfs/direct_read.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/netfs/direct_read.c +3 -3
@@ -108,9 +108,9 @@ static int netfs_dispatch_unbuffered_reads(struct netfs_io_request *rreq)* Perform a read to an application buffer, bypassing the pagecache and the * local disk cache. */ -static int netfs_unbuffered_read (struct netfs_io_request *rreq,bool sync) +static ssize_t netfs_unbuffered_read (struct netfs_io_request *rreq,bool sync) { -int ret; +ssize_t ret;_enter ("R=%x %llx-%llx" , rreq->debug_id, rreq->start, rreq->start + rreq->len -1 );
@@ -149,7 +149,7 @@ static int netfs_unbuffered_read(struct netfs_io_request *rreq, bool sync) } out: -_leave (" = %d" , ret); +_leave (" = %zd" , ret);return ret; }
Signature · 1 line
2.39.5