From: Joel Fernandes <joelagnelf@nvidia.com>
To: Mark Brown <broonie@kernel.org>,
"Paul E. McKenney" <paulmck@kernel.org>,
Frederic Weisbecker <frederic@kernel.org>,
Neeraj Upadhyay <neeraj.upadhyay@kernel.org>,
Boqun Feng <boqun.feng@gmail.com>,
Uladzislau Rezki <urezki@gmail.com>
Cc: Kees Cook <kees@kernel.org>, Kees Cook <kees+treewide@kernel.org>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Linux Next Mailing List <linux-next@vger.kernel.org>
Subject: Re: linux-next: manual merge of the rcu tree with the origin tree
Date: Tue, 10 Nov 2026 15:17:07 -0500 [thread overview]
Message-ID: <09ebf7bb-f802-4bbb-ae78-dc4b45c1f693@nvidia.com> (raw)
In-Reply-To: <avNzIwARUFPlPyrF@sirena.org.uk>
Thanks for the report! This will save us some pain down the line. I have rebased
rcu/next on Linux -rc2 and resolved the conflict.
Thanks!
Joel Fernandes
On 11/10/2026 2:40 PM, Mark Brown wrote:
> Hi all,
>
> Today's linux-next merge of the rcu tree got a conflict in:
>
> kernel/rcu/rcuscale.c
>
> between commit:
>
> 0af298e62e5cf ("treewide: refresh kmalloc_obj() conversions")
>
> from the origin tree and commit:
>
> 08fa1784740f6 ("rcuscale: Consolidate per-writer arrays into struct writer_state")
>
> from the rcu tree. Kees, let me once more renew my complaints about
> this being done at -rc2...
>
> I fixed it up (see below) and can carry the fix as necessary. This
> is now fixed as far as linux-next is concerned, but any non trivial
> conflicts should be mentioned to your upstream maintainer when your tree
> is submitted for merging. You may also want to consider cooperating
> with the maintainer of the conflicting tree to minimise any particularly
> complex conflicts.
>
> diff --combined kernel/rcu/rcuscale.c
> index 38c75c37a07c3,5659eaebc5c0d..0000000000000
> --- a/kernel/rcu/rcuscale.c
> +++ b/kernel/rcu/rcuscale.c
> @@@ -115,17 -115,21 +115,21 @@@ struct writer_freelist
> struct writer_mblock *ws_mblocks;
> };
>
> + struct writer_state {
> + struct writer_freelist wst_fl;
> + struct task_struct *wst_task;
> + u64 *wst_durations;
> + int wst_n_durations;
> + bool wst_done;
> + };
> +
> static int nrealreaders;
> static int nrealwriters;
> static int nrealexp;
> - static struct task_struct **writer_tasks;
> static struct task_struct **reader_tasks;
> static struct task_struct **exp_tasks;
>
> - static u64 **writer_durations;
> - static bool *writer_done;
> - static struct writer_freelist *writer_freelists;
> - static int *writer_n_durations;
> + static struct writer_state *writer_states;
> static atomic_t n_rcu_scale_reader_started;
> static atomic_t n_rcu_scale_writer_started;
> static atomic_t n_rcu_scale_writer_finished;
> @@@ -293,6 -297,44 +297,44 @@@ static struct rcu_scale_ops srcud_ops
> .name = "srcud"
> };
>
> + static struct srcu_struct srcua;
> +
> + static int srcu_scale_atomic_read_lock(void)
> + {
> + return srcu_read_lock_atomic(srcu_ctlp);
> + }
> +
> + static void srcu_scale_atomic_read_unlock(int idx)
> + {
> + srcu_read_unlock_atomic(srcu_ctlp, idx);
> + }
> +
> + static void srcu_scale_atomic_synchronize(void)
> + {
> + synchronize_srcu_atomic(srcu_ctlp);
> + }
> +
> + static void srcu_atomic_scale_init(void)
> + {
> + srcu_ctlp = &srcua;
> + init_srcu_struct_atomic(srcu_ctlp);
> + }
> +
> + static struct rcu_scale_ops srcua_ops = {
> + .ptype = SRCU_FLAVOR,
> + .init = srcu_atomic_scale_init,
> + .cleanup = srcu_sync_scale_cleanup,
> + .readlock = srcu_scale_atomic_read_lock,
> + .readunlock = srcu_scale_atomic_read_unlock,
> + .get_gp_seq = srcu_scale_completed,
> + .gp_diff = rcu_seq_diff,
> + .exp_completed = srcu_scale_completed,
> + .sync = srcu_scale_atomic_synchronize,
> + .exp_sync = srcu_scale_atomic_synchronize,
> + .stats = srcu_scale_stats,
> + .name = "srcua"
> + };
> +
> #ifdef CONFIG_TASKS_RCU
>
> /*
> @@@ -504,9 -546,9 +546,9 @@@ static struct writer_mblock *rcu_scale_
> struct writer_freelist *wflp;
> struct writer_mblock *wmbp;
>
> - if (WARN_ON_ONCE(!writer_freelists))
> + if (WARN_ON_ONCE(!writer_states))
> return NULL;
> - wflp = &writer_freelists[me];
> + wflp = &writer_states[me].wst_fl;
> if (llist_empty(&wflp->ws_lhp)) {
> // ->ws_lhp is private to its rcu_scale_writer task.
> wmbp = container_of(llist_del_all(&wflp->ws_lhg), struct writer_mblock, wmb_node);
> @@@ -560,8 -602,9 +602,9 @@@ rcu_scale_writer(void *arg
> u64 t;
> DEFINE_TORTURE_RANDOM(tr);
> u64 *wdp;
> - u64 *wdpp = writer_durations[me];
> - struct writer_freelist *wflp = &writer_freelists[me];
> + struct writer_state *wsp = &writer_states[me];
> + u64 *wdpp = wsp->wst_durations;
> + struct writer_freelist *wflp = &wsp->wst_fl;
> struct writer_mblock *wmbp = NULL;
>
> VERBOSE_SCALEOUT_STRING("rcu_scale_writer task started");
> @@@ -631,7 -674,7 +674,7 @@@
> started = true;
> if (!done && i >= MIN_MEAS && time_after(jiffies, jdone)) {
> done = true;
> - WRITE_ONCE(writer_done[me], true);
> + WRITE_ONCE(wsp->wst_done, true);
> sched_set_normal(current, 0);
> pr_alert("%s%s rcu_scale_writer %ld has %d measurements\n",
> scale_type, SCALE_FLAG, me, MIN_MEAS);
> @@@ -649,7 -692,7 +692,7 @@@
> cur_ops->get_gp_seq();
> }
> if (shutdown_secs) {
> - writer_tasks[me] = NULL;
> + wsp->wst_task = NULL;
> smp_mb(); /* Assign before wake. */
> rcu_scale_cleanup();
> kernel_power_off();
> @@@ -665,10 -708,10 +708,10 @@@
>
> if (!atomic_xchg(&dumped, 1)) {
> for (i = 0; i < nrealwriters; i++) {
> - if (writer_done[i])
> + if (writer_states[i].wst_done)
> continue;
> pr_info("%s: Task %ld flags writer %d:\n", __func__, me, i);
> - sched_show_task(writer_tasks[i]);
> + sched_show_task(writer_states[i].wst_task);
> }
> if (cur_ops->stats)
> cur_ops->stats();
> @@@ -676,7 -719,7 +719,7 @@@
> }
> if (!selfreport && time_after(jiffies, jdone + HZ * (70 + me))) {
> pr_info("%s: Writer %ld self-report: started %d done %d/%d->%d i %d jdone %lu.\n",
> - __func__, me, started, done, writer_done[me], atomic_read(&n_rcu_scale_writer_finished), i, jiffies - jdone);
> + __func__, me, started, done, wsp->wst_done, atomic_read(&n_rcu_scale_writer_finished), i, jiffies - jdone);
> selfreport = true;
> }
> if (gp_succeeded && started && !alldone && i < MAX_MEAS - 1)
> @@@ -687,7 -730,7 +730,7 @@@
> rcu_scale_free(wmbp);
> cur_ops->gp_barrier();
> }
> - writer_n_durations[me] = i_max + 1;
> + wsp->wst_n_durations = i_max + 1;
> torture_kthread_stopping("rcu_scale_writer");
> return 0;
> }
> @@@ -1031,13 -1074,11 +1074,11 @@@ rcu_scale_cleanup(void
> reader_tasks = NULL;
> }
>
> - if (writer_tasks) {
> + if (writer_states) {
> for (i = 0; i < nrealwriters; i++) {
> torture_stop_kthread(rcu_scale_writer,
> - writer_tasks[i]);
> - if (!writer_n_durations)
> - continue;
> - j = writer_n_durations[i];
> + writer_states[i].wst_task);
> + j = writer_states[i].wst_n_durations;
> pr_alert("%s%s writer %d gps: %d\n",
> scale_type, SCALE_FLAG, i, j);
> ngps += j;
> @@@ -1051,14 -1092,12 +1092,12 @@@
> rcuscale_seq_diff(b_rcu_gp_test_finished,
> b_rcu_gp_test_started));
> for (i = 0; i < nrealwriters; i++) {
> - if (!writer_durations)
> - break;
> - if (!writer_n_durations)
> - continue;
> - wdpp = writer_durations[i];
> + struct writer_state *wsp = &writer_states[i];
> +
> + wdpp = wsp->wst_durations;
> if (!wdpp)
> continue;
> - for (j = 0; j < writer_n_durations[i]; j++) {
> + for (j = 0; j < wsp->wst_n_durations; j++) {
> wdp = &wdpp[j];
> pr_alert("%s%s %4d writer-duration: %5d %llu\n",
> scale_type, SCALE_FLAG,
> @@@ -1066,34 -1105,23 +1105,23 @@@
> if (j % 100 == 0)
> schedule_timeout_uninterruptible(1);
> }
> - kfree(writer_durations[i]);
> - if (writer_freelists) {
> + kfree(wdpp);
> + if (wsp->wst_fl.ws_mblocks) {
> int ctr = 0;
> struct llist_node *llnp;
> - struct writer_freelist *wflp = &writer_freelists[i];
>
> - if (wflp->ws_mblocks) {
> - llist_for_each(llnp, wflp->ws_lhg.first)
> - ctr++;
> - llist_for_each(llnp, wflp->ws_lhp.first)
> - ctr++;
> - WARN_ONCE(ctr != gp_async_max,
> - "%s: ctr = %d gp_async_max = %d\n",
> - __func__, ctr, gp_async_max);
> - kfree(wflp->ws_mblocks);
> - }
> + llist_for_each(llnp, wsp->wst_fl.ws_lhg.first)
> + ctr++;
> + llist_for_each(llnp, wsp->wst_fl.ws_lhp.first)
> + ctr++;
> + WARN_ONCE(ctr != gp_async_max,
> + "%s: ctr = %d gp_async_max = %d\n",
> + __func__, ctr, gp_async_max);
> + kfree(wsp->wst_fl.ws_mblocks);
> }
> }
> - kfree(writer_tasks);
> - writer_tasks = NULL;
> - kfree(writer_durations);
> - writer_durations = NULL;
> - kfree(writer_n_durations);
> - writer_n_durations = NULL;
> - kfree(writer_done);
> - writer_done = NULL;
> - kfree(writer_freelists);
> - writer_freelists = NULL;
> + kfree(writer_states);
> + writer_states = NULL;
> }
>
> /* Do torture-type-specific cleanup operations. */
> @@@ -1110,7 -1138,8 +1138,8 @@@ rcu_scale_init(void
> long i;
> long j;
> static struct rcu_scale_ops *scale_ops[] = {
> - &rcu_ops, &srcu_ops, &srcud_ops, TASKS_OPS TASKS_RUDE_OPS TASKS_TRACING_OPS
> + &rcu_ops, &srcu_ops, &srcua_ops, &srcud_ops,
> + TASKS_OPS TASKS_RUDE_OPS TASKS_TRACING_OPS
> };
>
> if (!torture_init_begin(scale_type, verbose))
> @@@ -1187,36 -1216,30 +1216,30 @@@
> goto unwind;
> }
> }
> - writer_tasks = kzalloc_objs(writer_tasks[0], nrealwriters);
> - writer_durations = kzalloc_objs(*writer_durations, nrealwriters);
> - writer_n_durations = kzalloc_objs(*writer_n_durations, nrealwriters);
> - writer_done = kzalloc_objs(writer_done[0], nrealwriters);
> - if (gp_async) {
> - if (gp_async_max <= 0) {
> - pr_warn("%s: gp_async_max = %d must be greater than zero.\n",
> - __func__, gp_async_max);
> - WARN_ON_ONCE(IS_BUILTIN(CONFIG_RCU_TORTURE_TEST));
> - firsterr = -EINVAL;
> - goto unwind;
> - }
> - writer_freelists = kzalloc_objs(writer_freelists[0],
> - nrealwriters);
> + writer_states = kzalloc_objs(writer_states[0], nrealwriters);
> + if (gp_async && gp_async_max <= 0) {
> + pr_warn("%s: gp_async_max = %d must be greater than zero.\n",
> + __func__, gp_async_max);
> + WARN_ON_ONCE(IS_BUILTIN(CONFIG_RCU_TORTURE_TEST));
> + firsterr = -EINVAL;
> + goto unwind;
> }
> - if (!writer_tasks || !writer_durations || !writer_n_durations || !writer_done ||
> - (gp_async && !writer_freelists)) {
> + if (!writer_states) {
> SCALEOUT_ERRSTRING("out of memory");
> firsterr = -ENOMEM;
> goto unwind;
> }
> for (i = 0; i < nrealwriters; i++) {
> - writer_durations[i] =
> - kzalloc_objs(*writer_durations[i], MAX_MEAS);
> - if (!writer_durations[i]) {
> + struct writer_state *wsp = &writer_states[i];
> +
> + wsp->wst_durations = kcalloc(MAX_MEAS, sizeof(*wsp->wst_durations),
> + GFP_KERNEL);
> + if (!wsp->wst_durations) {
> firsterr = -ENOMEM;
> goto unwind;
> }
> - if (writer_freelists) {
> - struct writer_freelist *wflp = &writer_freelists[i];
> + if (gp_async) {
> + struct writer_freelist *wflp = &wsp->wst_fl;
>
> init_llist_head(&wflp->ws_lhg);
> init_llist_head(&wflp->ws_lhp);
> @@@ -1234,7 -1257,7 +1257,7 @@@
> }
> }
> firsterr = torture_create_kthread(rcu_scale_writer, (void *)i,
> - writer_tasks[i]);
> + wsp->wst_task);
> if (torture_init_error(firsterr))
> goto unwind;
> }
--
Joel Fernandes
prev parent reply other threads:[~2026-11-10 20:17 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 19:40 Mark Brown
2026-11-10 20:17 ` Joel Fernandes [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=09ebf7bb-f802-4bbb-ae78-dc4b45c1f693@nvidia.com \
--to=joelagnelf@nvidia.com \
--cc=boqun.feng@gmail.com \
--cc=broonie@kernel.org \
--cc=frederic@kernel.org \
--cc=kees+treewide@kernel.org \
--cc=kees@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-next@vger.kernel.org \
--cc=neeraj.upadhyay@kernel.org \
--cc=paulmck@kernel.org \
--cc=urezki@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®