All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/8] timers/migration: Fix three possible races and some improvements
@ 2024-07-16 14:19 Anna-Maria Behnsen
  2024-07-16 14:19 ` [PATCH v4 1/8] timers/migration: Do not rely always on group->parent Anna-Maria Behnsen
                   ` (7 more replies)
  0 siblings, 8 replies; 34+ messages in thread
From: Anna-Maria Behnsen @ 2024-07-16 14:19 UTC (permalink / raw)
  To: Frederic Weisbecker, Thomas Gleixner, linux-kernel
  Cc: Borislav Petkov, Anna-Maria Behnsen

Borislav reported a warning in timer migration deactive path

  https://lore.kernel.org/r/20240612090347.GBZmlkc5PwlVpOG6vT@fat_crate.local

Sadly it doesn't reproduce directly. But with the change of timing (by
adding a trace prinkt before the warning), it is possible to trigger the
warning reliable at least in my test setup. The problem here is a racy
check agains group->parent pointer. This is also used in other places in
the code and fixing this racy usage is adressed by the first patch.

There were two other races reported by Frederic in setup path:

  https://lore.kernel.org/r/ZnWOswTMML6ShzYO@localhost.localdomain

  https://lore.kernel.org/r/ZnoIlO22habOyQRe@lothringen

Those races are both is addressed by the change of patch 2.

Some updates/cleanups are provided by patch 3-8. ("timers/migration:
Improve tracing" and "timers/migration: Spare write when nothing changed"
are the same as provided by v2).

Patches are available here:

  https://git.kernel.org/pub/scm/linux/kernel/git/anna-maria/linux-devel.git timers/misc

---
Changes in v4:
- Update Patch 2: Fix broken cpuhp_setup_state() call for prepare
- Update Patch 2: Activate child during setup only when it is an already
  existing group
- Update Patch 2: Change init into early_initcall() to make usage of
  preparation by an already active CPU.
- Update Patch 2: Move initialization of tmc in tmigr_cpu_prepare() before
  using data of tmc (e.g. by a tracepoint)
- Update Patch 5: Use proper childmask for tmigr_walk in __walk_groups()
- Update Patch 6: Fix missing update of s/childmask/groupmask in
  connect_[cpu|child]_parent tracepoint and update to change of Patch 5
- Link to v3: https://lore.kernel.org/r/20240701-tmigr-fixes-v3-0-25cd5de318fb@linutronix.de

Changes in v3:
- Address the new reported possible race (childmask and parent pointer)
  together with the existing race (both reported by Frederic).
- New cleanup: Two patches to access childmask and parent pointer only in
  one place
- New cleanup: Rename childmask to parentmask as during discussions there
  was some kind of confusion because of the naming
- New cleanup: Fix typo
- Fix prefix in all patches (s$timer_migration$timers/migration$)
- Link to v2: https://lore.kernel.org/r/20240624-tmigr-fixes-v2-0-3eb4c0604790@linutronix.de

Changes in v2:
- Address another possible race in setup code (reported by Frederic) and
  recycle therefore one improvement patch
- Change order and move the already existing improvement patch to the end
  of the queue
- Existing patches didn't change
- Link to v1: https://lore.kernel.org/r/20240621-tmigr-fixes-v1-0-8c8a2d8e8d77@linutronix.de

Thanks,

        Anna-Maria

---
Anna-Maria Behnsen (8):
      timers/migration: Do not rely always on group->parent
      timers/migration: Move hierarchy setup into cpuhotplug prepare callback
      timers/migration: Improve tracing
      timers/migration: Use a single struct for hierarchy walk data
      timers/migration: Read childmask and parent pointer in a single place
      timers/migration: Rename childmask by groupmask to make naming more obvious
      timers/migration: Spare write when nothing changed
      timers/migration: Fix grammar in comment

 include/linux/cpuhotplug.h             |   1 +
 include/trace/events/timer_migration.h |  16 +-
 kernel/time/timer_migration.c          | 383 ++++++++++++++++-----------------
 kernel/time/timer_migration.h          |  27 ++-
 4 files changed, 214 insertions(+), 213 deletions(-)


^ permalink raw reply	[flat|nested] 34+ messages in thread
* [PATCH v3 6/8] timers/migration: Rename childmask by parentmask to make naming more obvious
@ 2024-07-01 10:18 Anna-Maria Behnsen
  2024-07-03 20:31 ` [PATCH v4 6/8] timers/migration: Rename childmask by groupmask " Anna-Maria Behnsen
  0 siblings, 1 reply; 34+ messages in thread
From: Anna-Maria Behnsen @ 2024-07-01 10:18 UTC (permalink / raw)
  To: Frederic Weisbecker, Thomas Gleixner, linux-kernel; +Cc: Anna-Maria Behnsen

childmask in the group reflects the mask that is required to 'reference'
this group in the parent. When reading childmask, this might be confusing,
as this suggests, that this is the mask of the child of the group.

Clarify this by renaming childmask in the tmigr_group and tmc_group by
parentmask.

Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
---
 include/trace/events/timer_migration.h |  4 ++--
 kernel/time/timer_migration.c          | 24 ++++++++++++------------
 kernel/time/timer_migration.h          | 15 +++++++--------
 3 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/include/trace/events/timer_migration.h b/include/trace/events/timer_migration.h
index 79f19e76a80b..e3c5afd1638d 100644
--- a/include/trace/events/timer_migration.h
+++ b/include/trace/events/timer_migration.h
@@ -52,7 +52,7 @@ TRACE_EVENT(tmigr_connect_child_parent,
 		__entry->lvl		= child->parent->level;
 		__entry->numa_node	= child->parent->numa_node;
 		__entry->num_children	= child->parent->num_children;
-		__entry->childmask	= child->childmask;
+		__entry->childmask	= child->parentmask;
 	),
 
 	TP_printk("group=%p childmask=%0x parent=%p lvl=%d numa=%d num_children=%d",
@@ -81,7 +81,7 @@ TRACE_EVENT(tmigr_connect_cpu_parent,
 		__entry->lvl		= tmc->tmgroup->level;
 		__entry->numa_node	= tmc->tmgroup->numa_node;
 		__entry->num_children	= tmc->tmgroup->num_children;
-		__entry->childmask	= tmc->childmask;
+		__entry->childmask	= tmc->parentmask;
 	),
 
 	TP_printk("cpu=%d childmask=%0x parent=%p lvl=%d numa=%d num_children=%d",
diff --git a/kernel/time/timer_migration.c b/kernel/time/timer_migration.c
index a681cf89910e..b73d89e78163 100644
--- a/kernel/time/timer_migration.c
+++ b/kernel/time/timer_migration.c
@@ -495,7 +495,7 @@ static bool tmigr_check_lonely(struct tmigr_group *group)
  *			outcome is a CPU which might wake up a little early.
  * @evt:		Pointer to tmigr_event which needs to be queued (of idle
  *			child group)
- * @childmask:		childmask of child group
+ * @childmask:		parentmask of child group
  * @remote:		Is set, when the new timer path is executed in
  *			tmigr_handle_remote_cpu()
  * @basej:		timer base in jiffies
@@ -535,7 +535,7 @@ static void __walk_groups(up_f up, struct tmigr_walk *data,
 
 		child = group;
 		group = group->parent;
-		data->childmask = group->childmask;
+		data->childmask = group->parentmask;
 	} while (group);
 }
 
@@ -669,7 +669,7 @@ static void __tmigr_cpu_activate(struct tmigr_cpu *tmc)
 {
 	struct tmigr_walk data;
 
-	data.childmask = tmc->childmask;
+	data.childmask = tmc->parentmask;
 
 	trace_tmigr_cpu_active(tmc);
 
@@ -1049,7 +1049,7 @@ void tmigr_handle_remote(void)
 	if (tmigr_is_not_available(tmc))
 		return;
 
-	data.childmask = tmc->childmask;
+	data.childmask = tmc->parentmask;
 	data.firstexp = KTIME_MAX;
 
 	/*
@@ -1057,7 +1057,7 @@ void tmigr_handle_remote(void)
 	 * in tmigr_handle_remote_up() anyway. Keep this check to speed up the
 	 * return when nothing has to be done.
 	 */
-	if (!tmigr_check_migrator(tmc->tmgroup, tmc->childmask)) {
+	if (!tmigr_check_migrator(tmc->tmgroup, tmc->parentmask)) {
 		/*
 		 * If this CPU was an idle migrator, make sure to clear its wakeup
 		 * value so it won't chase timers that have already expired elsewhere.
@@ -1150,7 +1150,7 @@ bool tmigr_requires_handle_remote(void)
 		return ret;
 
 	data.now = get_jiffies_update(&jif);
-	data.childmask = tmc->childmask;
+	data.childmask = tmc->parentmask;
 	data.firstexp = KTIME_MAX;
 	data.tmc_active = !tmc->idle;
 	data.check = false;
@@ -1310,7 +1310,7 @@ static u64 __tmigr_cpu_deactivate(struct tmigr_cpu *tmc, u64 nextexp)
 	struct tmigr_walk data = { .nextexp = nextexp,
 				   .firstexp = KTIME_MAX,
 				   .evt = &tmc->cpuevt,
-				   .childmask = tmc->childmask };
+				   .childmask = tmc->parentmask };
 
 	/*
 	 * If nextexp is KTIME_MAX, the CPU event will be ignored because the
@@ -1388,7 +1388,7 @@ u64 tmigr_quick_check(u64 nextevt)
 	if (WARN_ON_ONCE(tmc->idle))
 		return nextevt;
 
-	if (!tmigr_check_migrator_and_lonely(tmc->tmgroup, tmc->childmask))
+	if (!tmigr_check_migrator_and_lonely(tmc->tmgroup, tmc->parentmask))
 		return KTIME_MAX;
 
 	do {
@@ -1551,7 +1551,7 @@ static void tmigr_connect_child_parent(struct tmigr_group *child,
 	raw_spin_lock_nested(&parent->lock, SINGLE_DEPTH_NESTING);
 
 	child->parent = parent;
-	child->childmask = BIT(parent->num_children++);
+	child->parentmask = BIT(parent->num_children++);
 
 	raw_spin_unlock(&parent->lock);
 	raw_spin_unlock_irq(&child->lock);
@@ -1580,7 +1580,7 @@ static void tmigr_connect_child_parent(struct tmigr_group *child,
 	 *   the CPU executing the setup will be responsible up to current top
 	 *   level group. Therefore propagate active state unconditionally.
 	 */
-	data.childmask = child->childmask;
+	data.childmask = child->parentmask;
 
 	/*
 	 * There is only one new level per time (which is protected by
@@ -1646,7 +1646,7 @@ static int tmigr_setup_groups(unsigned int cpu, unsigned int node)
 			raw_spin_lock_irq(&group->lock);
 
 			tmc->tmgroup = group;
-			tmc->childmask = BIT(group->num_children++);
+			tmc->parentmask = BIT(group->num_children++);
 
 			raw_spin_unlock_irq(&group->lock);
 
@@ -1709,7 +1709,7 @@ static int tmigr_cpu_prepare(unsigned int cpu)
 	if (ret < 0)
 		return ret;
 
-	if (tmc->childmask == 0)
+	if (tmc->parentmask == 0)
 		return -EINVAL;
 
 	timerqueue_init(&tmc->cpuevt.nextevt);
diff --git a/kernel/time/timer_migration.h b/kernel/time/timer_migration.h
index 494f68cc13f4..3d08e611c3d6 100644
--- a/kernel/time/timer_migration.h
+++ b/kernel/time/timer_migration.h
@@ -51,9 +51,8 @@ struct tmigr_event {
  * @num_children:	Counter of group children to make sure the group is only
  *			filled with TMIGR_CHILDREN_PER_GROUP; Required for setup
  *			only
- * @childmask:		childmask of the group in the parent group; is set
- *			during setup and will never change; can be read
- *			lockless
+ * @parentmask:		mask of the group in the parent group; is set during
+ *			setup and will never change; can be read lockless
  * @list:		List head that is added to the per level
  *			tmigr_level_list; is required during setup when a
  *			new group needs to be connected to the existing
@@ -69,7 +68,7 @@ struct tmigr_group {
 	unsigned int		level;
 	int			numa_node;
 	unsigned int		num_children;
-	u8			childmask;
+	u8			parentmask;
 	struct list_head	list;
 };
 
@@ -89,7 +88,7 @@ struct tmigr_group {
  *			hierarchy
  * @remote:		Is set when timers of the CPU are expired remotely
  * @tmgroup:		Pointer to the parent group
- * @childmask:		childmask of tmigr_cpu in the parent group
+ * @parentmask:		mask of tmigr_cpu in the parent group
  * @wakeup:		Stores the first timer when the timer migration
  *			hierarchy is completely idle and remote expiry was done;
  *			is returned to timer code in the idle path and is only
@@ -102,7 +101,7 @@ struct tmigr_cpu {
 	bool			idle;
 	bool			remote;
 	struct tmigr_group	*tmgroup;
-	u8			childmask;
+	u8			parentmask;
 	u64			wakeup;
 	struct tmigr_event	cpuevt;
 };
@@ -118,8 +117,8 @@ union tmigr_state {
 	u32 state;
 	/**
 	 * struct - split state of tmigr_group
-	 * @active:	Contains each childmask bit of the active children
-	 * @migrator:	Contains childmask of the child which is migrator
+	 * @active:	Contains each mask bit of the active children
+	 * @migrator:	Contains mask of the child which is migrator
 	 * @seq:	Sequence counter needs to be increased when an update
 	 *		to the tmigr_state is done. It prevents a race when
 	 *		updates in the child groups are propagated in changed

-- 
2.39.2


^ permalink raw reply related	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2024-07-24 10:22 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-16 14:19 [PATCH v4 0/8] timers/migration: Fix three possible races and some improvements Anna-Maria Behnsen
2024-07-16 14:19 ` [PATCH v4 1/8] timers/migration: Do not rely always on group->parent Anna-Maria Behnsen
2024-07-19 18:06   ` [tip: timers/urgent] " tip-bot2 for Anna-Maria Behnsen
2024-07-22 19:35   ` tip-bot2 for Anna-Maria Behnsen
2024-07-16 14:19 ` [PATCH v4 2/8] timers/migration: Move hierarchy setup into cpuhotplug prepare callback Anna-Maria Behnsen
2024-07-16 23:01   ` Frederic Weisbecker
2024-07-17  9:49   ` [PATCH v5 " Anna-Maria Behnsen
2024-07-17 12:53     ` Frederic Weisbecker
2024-07-19 18:06     ` [tip: timers/urgent] " tip-bot2 for Anna-Maria Behnsen
2024-07-22 13:16       ` Frederic Weisbecker
2024-07-24 10:22         ` Borislav Petkov
2024-07-22 19:35     ` tip-bot2 for Anna-Maria Behnsen
2024-07-16 14:19 ` [PATCH v4 3/8] timers/migration: Improve tracing Anna-Maria Behnsen
2024-07-19 18:06   ` [tip: timers/urgent] " tip-bot2 for Anna-Maria Behnsen
2024-07-22 19:35   ` tip-bot2 for Anna-Maria Behnsen
2024-07-16 14:19 ` [PATCH v4 4/8] timers/migration: Use a single struct for hierarchy walk data Anna-Maria Behnsen
2024-07-19 18:06   ` [tip: timers/urgent] " tip-bot2 for Anna-Maria Behnsen
2024-07-22 19:35   ` tip-bot2 for Anna-Maria Behnsen
2024-07-16 14:19 ` [PATCH v4 5/8] timers/migration: Read childmask and parent pointer in a single place Anna-Maria Behnsen
2024-07-16 23:05   ` Frederic Weisbecker
2024-07-19 18:06   ` [tip: timers/urgent] " tip-bot2 for Anna-Maria Behnsen
2024-07-22 19:35   ` tip-bot2 for Anna-Maria Behnsen
2024-07-16 14:19 ` [PATCH v4 6/8] timers/migration: Rename childmask by groupmask to make naming more obvious Anna-Maria Behnsen
2024-07-16 23:10   ` Frederic Weisbecker
2024-07-19 18:06   ` [tip: timers/urgent] " tip-bot2 for Anna-Maria Behnsen
2024-07-22 19:35   ` tip-bot2 for Anna-Maria Behnsen
2024-07-16 14:19 ` [PATCH v4 7/8] timers/migration: Spare write when nothing changed Anna-Maria Behnsen
2024-07-19 18:06   ` [tip: timers/urgent] " tip-bot2 for Anna-Maria Behnsen
2024-07-22 19:35   ` tip-bot2 for Anna-Maria Behnsen
2024-07-16 14:19 ` [PATCH v4 8/8] timers/migration: Fix grammar in comment Anna-Maria Behnsen
2024-07-19 18:06   ` [tip: timers/urgent] " tip-bot2 for Anna-Maria Behnsen
2024-07-22 19:35   ` tip-bot2 for Anna-Maria Behnsen
  -- strict thread matches above, loose matches on Subject: below --
2024-07-01 10:18 [PATCH v3 6/8] timers/migration: Rename childmask by parentmask to make naming more obvious Anna-Maria Behnsen
2024-07-03 20:31 ` [PATCH v4 6/8] timers/migration: Rename childmask by groupmask " Anna-Maria Behnsen
2024-07-03 21:33   ` Frederic Weisbecker

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.