Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-6.17-rc7). No conflicts. Adjacent changes: drivers/net/ethernet/mellanox/mlx5/core/en/fs.h9536fbe10c("net/mlx5e: Add PSP steering in local NIC RX")7601a0a462("net/mlx5e: Add a miss level for ipsec crypto offload") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
+37
-7
@@ -126,8 +126,31 @@ DEFINE_PERCPU_RWSEM(cgroup_threadgroup_rwsem);
|
||||
* of concurrent destructions. Use a separate workqueue so that cgroup
|
||||
* destruction work items don't end up filling up max_active of system_wq
|
||||
* which may lead to deadlock.
|
||||
*
|
||||
* A cgroup destruction should enqueue work sequentially to:
|
||||
* cgroup_offline_wq: use for css offline work
|
||||
* cgroup_release_wq: use for css release work
|
||||
* cgroup_free_wq: use for free work
|
||||
*
|
||||
* Rationale for using separate workqueues:
|
||||
* The cgroup root free work may depend on completion of other css offline
|
||||
* operations. If all tasks were enqueued to a single workqueue, this could
|
||||
* create a deadlock scenario where:
|
||||
* - Free work waits for other css offline work to complete.
|
||||
* - But other css offline work is queued after free work in the same queue.
|
||||
*
|
||||
* Example deadlock scenario with single workqueue (cgroup_destroy_wq):
|
||||
* 1. umount net_prio
|
||||
* 2. net_prio root destruction enqueues work to cgroup_destroy_wq (CPUx)
|
||||
* 3. perf_event CSS A offline enqueues work to same cgroup_destroy_wq (CPUx)
|
||||
* 4. net_prio cgroup_destroy_root->cgroup_lock_and_drain_offline.
|
||||
* 5. net_prio root destruction blocks waiting for perf_event CSS A offline,
|
||||
* which can never complete as it's behind in the same queue and
|
||||
* workqueue's max_active is 1.
|
||||
*/
|
||||
static struct workqueue_struct *cgroup_destroy_wq;
|
||||
static struct workqueue_struct *cgroup_offline_wq;
|
||||
static struct workqueue_struct *cgroup_release_wq;
|
||||
static struct workqueue_struct *cgroup_free_wq;
|
||||
|
||||
/* generate an array of cgroup subsystem pointers */
|
||||
#define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys,
|
||||
@@ -4159,6 +4182,7 @@ static void cgroup_file_release(struct kernfs_open_file *of)
|
||||
cft->release(of);
|
||||
put_cgroup_ns(ctx->ns);
|
||||
kfree(ctx);
|
||||
of->priv = NULL;
|
||||
}
|
||||
|
||||
static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
|
||||
@@ -5558,7 +5582,7 @@ static void css_release_work_fn(struct work_struct *work)
|
||||
cgroup_unlock();
|
||||
|
||||
INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn);
|
||||
queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork);
|
||||
queue_rcu_work(cgroup_free_wq, &css->destroy_rwork);
|
||||
}
|
||||
|
||||
static void css_release(struct percpu_ref *ref)
|
||||
@@ -5567,7 +5591,7 @@ static void css_release(struct percpu_ref *ref)
|
||||
container_of(ref, struct cgroup_subsys_state, refcnt);
|
||||
|
||||
INIT_WORK(&css->destroy_work, css_release_work_fn);
|
||||
queue_work(cgroup_destroy_wq, &css->destroy_work);
|
||||
queue_work(cgroup_release_wq, &css->destroy_work);
|
||||
}
|
||||
|
||||
static void init_and_link_css(struct cgroup_subsys_state *css,
|
||||
@@ -5701,7 +5725,7 @@ err_list_del:
|
||||
list_del_rcu(&css->sibling);
|
||||
err_free_css:
|
||||
INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn);
|
||||
queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork);
|
||||
queue_rcu_work(cgroup_free_wq, &css->destroy_rwork);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@@ -5939,7 +5963,7 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
|
||||
|
||||
if (atomic_dec_and_test(&css->online_cnt)) {
|
||||
INIT_WORK(&css->destroy_work, css_killed_work_fn);
|
||||
queue_work(cgroup_destroy_wq, &css->destroy_work);
|
||||
queue_work(cgroup_offline_wq, &css->destroy_work);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6325,8 +6349,14 @@ static int __init cgroup_wq_init(void)
|
||||
* We would prefer to do this in cgroup_init() above, but that
|
||||
* is called before init_workqueues(): so leave this until after.
|
||||
*/
|
||||
cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1);
|
||||
BUG_ON(!cgroup_destroy_wq);
|
||||
cgroup_offline_wq = alloc_workqueue("cgroup_offline", 0, 1);
|
||||
BUG_ON(!cgroup_offline_wq);
|
||||
|
||||
cgroup_release_wq = alloc_workqueue("cgroup_release", 0, 1);
|
||||
BUG_ON(!cgroup_release_wq);
|
||||
|
||||
cgroup_free_wq = alloc_workqueue("cgroup_free", 0, 1);
|
||||
BUG_ON(!cgroup_free_wq);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(cgroup_wq_init);
|
||||
|
||||
+1
-1
@@ -9551,7 +9551,7 @@ static unsigned long tg_weight(struct task_group *tg)
|
||||
#ifdef CONFIG_FAIR_GROUP_SCHED
|
||||
return scale_load_down(tg->shares);
|
||||
#else
|
||||
return sched_weight_from_cgroup(tg->scx_weight);
|
||||
return sched_weight_from_cgroup(tg->scx.weight);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+1
-5
@@ -6788,12 +6788,8 @@ __bpf_kfunc u32 scx_bpf_reenqueue_local(void)
|
||||
* CPUs disagree, they use %ENQUEUE_RESTORE which is bypassed to
|
||||
* the current local DSQ for running tasks and thus are not
|
||||
* visible to the BPF scheduler.
|
||||
*
|
||||
* Also skip re-enqueueing tasks that can only run on this
|
||||
* CPU, as they would just be re-added to the same local
|
||||
* DSQ without any benefit.
|
||||
*/
|
||||
if (p->migration_pending || is_migration_disabled(p) || p->nr_cpus_allowed == 1)
|
||||
if (p->migration_pending)
|
||||
continue;
|
||||
|
||||
dispatch_dequeue(rq, p);
|
||||
|
||||
@@ -787,10 +787,10 @@ static void retrigger_next_event(void *arg)
|
||||
* of the next expiring timer is enough. The return from the SMP
|
||||
* function call will take care of the reprogramming in case the
|
||||
* CPU was in a NOHZ idle sleep.
|
||||
*
|
||||
* In periodic low resolution mode, the next softirq expiration
|
||||
* must also be updated.
|
||||
*/
|
||||
if (!hrtimer_hres_active(base) && !tick_nohz_active)
|
||||
return;
|
||||
|
||||
raw_spin_lock(&base->lock);
|
||||
hrtimer_update_base(base);
|
||||
if (hrtimer_hres_active(base))
|
||||
@@ -2295,11 +2295,6 @@ int hrtimers_cpu_dying(unsigned int dying_cpu)
|
||||
&new_base->clock_base[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* The migration might have changed the first expiring softirq
|
||||
* timer on this CPU. Update it.
|
||||
*/
|
||||
__hrtimer_get_next_event(new_base, HRTIMER_ACTIVE_SOFT);
|
||||
/* Tell the other CPU to retrigger the next event */
|
||||
smp_call_function_single(ncpu, retrigger_next_event, NULL, 0);
|
||||
|
||||
|
||||
@@ -908,6 +908,8 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
|
||||
return -EINVAL;
|
||||
}
|
||||
buf = kmemdup(&argv[0][1], len + 1, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
buf[len] = '\0';
|
||||
ret = kstrtouint(buf, 0, &maxactive);
|
||||
if (ret || !maxactive) {
|
||||
|
||||
Reference in New Issue
Block a user