mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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


      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®