From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 60D08194C96; Tue, 7 Jul 2026 00:12:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783383167; cv=none; b=gL5+KA41XK0ob8nR7i2oMVnHGg/oTYIktdOPM4Htj/CfqLPDAazAlH7j4/DUgVgHNZc7HxZH+3WkWMSzG5fZEJ1wbtPRyQoz2k9GJEArZTOIba9NDM8OhwBzJPQ5MvXoGfZu+ZnrBlO2S054shUm3zVNIQxC24EkzdJRCDZIE9k= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783383167; c=relaxed/simple; bh=w0ImiDOxTlb/npeCdpy/+VblruQr6nHqE43qkyeEbO8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EKkSFrxS+V56Zn85dwkbXHIn/gt4mxHqtH0dpf7QbO6N6RLX7cVeVfJW3LCZ3fdbHjd2CQOkrE7bzI6BjKRBfU7rkAUVp6EJ+TmbpOf/0yC4Ni9fS9NQgcgdLTS8Qzj+8PFrOmjkfWaTj0Pi7EvmyuQPounfTNNqiuZePGvV3TM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Td8QF/1H; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Td8QF/1H" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D39C81F00A3A; Tue, 7 Jul 2026 00:12:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1783383164; bh=aA0ubIyNT6z82WAk4ZBwfzNsqJAhdZFnTqNXRrkVxoQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Td8QF/1Hq4w61bNVx8HWu6ITbNhRgoptitGx3XYNoVPifavKTFmsC4l8YOAxEq21/ z9tkJHvBEOj6qiW5z2g0XR7ZYaRjvgkIdtg3g6G1AV6PZ9+MwvH0vhSN7YuALKpfly PH3EMjV9NW/TmwIr3FvPZkUzdW7key0ttfBH+iU7eS0RoiNW6IiPZU/3AErxNi984q KFwb6wCOA3HHSL7l8W6eLmTq1VdGJX6hA+6etuO0ozpNgWjJ0ypLZnzDUzQVCJqgeU 7D5viZQ/vnoxU/KMXOzrDlT0LVyVBXs3SxUaxd4pXq1WODAZw4Jo7oapLJ4xX+uJuU R261mimJ4SLjA== From: Tejun Heo To: David Vernet , Andrea Righi , Changwoo Min Cc: sched-ext@lists.linux.dev, Emil Tsalapatis , linux-kernel@vger.kernel.org, Tejun Heo Subject: [PATCH v3 sched_ext/for-7.3 14/36] sched_ext: Add per-shard scx_sched storage scaffolding Date: Mon, 6 Jul 2026 14:12:07 -1000 Message-ID: <20260707001229.1410929-15-tj@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260707001229.1410929-1-tj@kernel.org> References: <20260707001229.1410929-1-tj@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Add struct scx_pshard and sch->pshard[] indexed by shard_idx, each entry allocated on its shard's NUMA node from scx_shard_node[si]. The struct starts empty (one dummy field). Follow-up patches will grow it as shard-local state lands. Only cid-type schedulers with an arena pool get pshards. Allocation happens after ops.init_cids() returns so any scx_bpf_cid_override() it issues has finalized scx_nr_cid_shards and scx_shard_node[]. sch->nr_pshards records the array size for the async RCU free path, which may run after a later scheduler's scx_cid_init() has rewritten the global. v2: Free the partially-allocated pshard array on alloc failure. (sashiko AI) Signed-off-by: Tejun Heo --- kernel/sched/ext/ext.c | 8 +++++++ kernel/sched/ext/internal.h | 18 +++++++++++++++ kernel/sched/ext/sub.c | 46 +++++++++++++++++++++++++++++++++++++ kernel/sched/ext/sub.h | 4 ++++ 4 files changed, 76 insertions(+) diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c index 340d1cf3630c..a5e782147bf4 100644 --- a/kernel/sched/ext/ext.c +++ b/kernel/sched/ext/ext.c @@ -4644,6 +4644,8 @@ static void scx_sched_free_rcu_work(struct work_struct *work) free_pnode(sch->pnode[node]); kfree(sch->pnode); + scx_free_pshards(sch); + rhashtable_walk_enter(&sch->dsq_hash, &rht_iter); do { rhashtable_walk_start(&rht_iter); @@ -6722,6 +6724,12 @@ static void scx_root_enable_workfn(struct kthread_work *work) goto err_disable; } + ret = scx_alloc_pshards(sch); + if (ret) { + cpus_read_unlock(); + goto err_disable; + } + if (sch->ops.init) { ret = SCX_CALL_OP_RET(sch, init, NULL); if (ret) { diff --git a/kernel/sched/ext/internal.h b/kernel/sched/ext/internal.h index 61a9230265cd..dce07b83c166 100644 --- a/kernel/sched/ext/internal.h +++ b/kernel/sched/ext/internal.h @@ -1183,6 +1183,12 @@ struct scx_sched_pnode { struct scx_dispatch_q global_dsq; }; +#ifdef CONFIG_EXT_SUB_SCHED +struct scx_pshard { + int _dummy; /* until the first real field lands */ +}; +#endif + struct scx_sched { /* * cpu-form and cid-form ops share field offsets up to .priv (verified @@ -1230,6 +1236,9 @@ struct scx_sched { */ struct rhashtable dsq_hash; struct scx_sched_pnode **pnode; +#ifdef CONFIG_EXT_SUB_SCHED + struct scx_pshard **pshard; /* indexed by shard_idx */ +#endif struct scx_sched_pcpu __percpu *pcpu; u64 slice_dfl; @@ -1245,6 +1254,15 @@ struct scx_sched { u32 dsp_max_batch; s32 level; +#ifdef CONFIG_EXT_SUB_SCHED + /* + * pshard[] size captured at enable for the async RCU free path - + * scx_nr_cid_shards may be rewritten by a later scx_cid_init() before + * free runs. While sch is active, use the global. + */ + u32 nr_pshards; +#endif + /* * Updates to the following warned bitfields can race causing RMW issues * but it doesn't really matter. diff --git a/kernel/sched/ext/sub.c b/kernel/sched/ext/sub.c index e94a415ee10a..6d8b9bcf2f49 100644 --- a/kernel/sched/ext/sub.c +++ b/kernel/sched/ext/sub.c @@ -82,6 +82,52 @@ void set_cgroup_sched(struct cgroup *cgrp, struct scx_sched *sch) rcu_assign_pointer(pos->scx_sched, sch); } +static void free_pshard(struct scx_pshard *pshard) +{ + kfree(pshard); +} + +void scx_free_pshards(struct scx_sched *sch) +{ + s32 si; + + if (!sch->pshard) + return; + for (si = 0; si < sch->nr_pshards; si++) + free_pshard(sch->pshard[si]); + kfree(sch->pshard); +} + +static struct scx_pshard *alloc_pshard(struct scx_sched *sch, s32 shard_idx, s32 node) +{ + return kzalloc_node(sizeof(struct scx_pshard), GFP_KERNEL, node); +} + +s32 scx_alloc_pshards(struct scx_sched *sch) +{ + s32 si; + + if (!sch->is_cid_type || !sch->arena_pool) + return 0; + + sch->pshard = kzalloc_objs(sch->pshard[0], scx_nr_cid_shards, GFP_KERNEL); + if (!sch->pshard) + return -ENOMEM; + + sch->nr_pshards = scx_nr_cid_shards; + + for (si = 0; si < scx_nr_cid_shards; si++) { + sch->pshard[si] = alloc_pshard(sch, si, scx_shard_node[si]); + if (!sch->pshard[si]) { + /* drop the partial array so the !pshard cap guards hold */ + scx_free_pshards(sch); + sch->pshard = NULL; + return -ENOMEM; + } + } + return 0; +} + static DECLARE_WAIT_QUEUE_HEAD(scx_unlink_waitq); void drain_descendants(struct scx_sched *sch) diff --git a/kernel/sched/ext/sub.h b/kernel/sched/ext/sub.h index 460a9fd196dc..9fa6b5c8be23 100644 --- a/kernel/sched/ext/sub.h +++ b/kernel/sched/ext/sub.h @@ -24,6 +24,8 @@ void drain_descendants(struct scx_sched *sch); void scx_sub_disable(struct scx_sched *sch); void scx_sub_enable_workfn(struct kthread_work *work); bool scx_bpf_sub_dispatch(u64 cgroup_id, const struct bpf_prog_aux *aux); +void scx_free_pshards(struct scx_sched *sch); +s32 scx_alloc_pshards(struct scx_sched *sch); #else /* CONFIG_EXT_SUB_SCHED */ @@ -33,6 +35,8 @@ static inline struct cgroup *sch_cgroup(struct scx_sched *sch) { return NULL; } static inline void set_cgroup_sched(struct cgroup *cgrp, struct scx_sched *sch) {} static inline void drain_descendants(struct scx_sched *sch) { } static inline void scx_sub_disable(struct scx_sched *sch) { } +static inline void scx_free_pshards(struct scx_sched *sch) {} +static inline s32 scx_alloc_pshards(struct scx_sched *sch) { return 0; } #endif /* CONFIG_EXT_SUB_SCHED */ -- 2.54.0