From: Junjie Cao <junjie.cao@linux.dev>
To: syzbot+2642f347f7309b4880dc@syzkaller.appspotmail.com
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, hdanton@sina.com
Subject: Re: [syzbot] [mm?] INFO: rcu detected stall in exit_to_user_mode_loop
Date: Mon, 17 Aug 2026 02:21:46 -0500 [thread overview]
Message-ID: <20260817072146.313493-1-junjie.cao@linux.dev> (raw)
In-Reply-To: <6887ebf4.a00a0220.b12ec.00ae.GAE@google.com>
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git 24ef02f934eeb48830cff6b739abc3c62b1d107b
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 299234a5f0fe..7519bc5c1aff 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -259,6 +259,26 @@ static int length_to_duration(struct taprio_sched *q, int len)
return div_u64(len * atomic64_read(&q->picos_per_byte), PSEC_PER_NSEC);
}
+/* Software schedules service one hrtimer expiry per entry; intervals
+ * shorter than the expiry service cost rearm the timer with an expiry
+ * already in the past and storm the CPU. 100us leaves margin above the
+ * measured cost on debug configurations.
+ */
+#define TAPRIO_MIN_SW_INTERVAL_NS (100 * NSEC_PER_USEC)
+
+static s64 taprio_min_interval(struct taprio_sched *q)
+{
+ s64 min_interval = length_to_duration(q, ETH_ZLEN);
+
+ /* Only pure software schedules arm the per-entry hrtimer. */
+ if (!FULL_OFFLOAD_IS_ENABLED(q->flags) &&
+ !TXTIME_ASSIST_IS_ENABLED(q->flags))
+ min_interval = max_t(s64, min_interval,
+ TAPRIO_MIN_SW_INTERVAL_NS);
+
+ return min_interval;
+}
+
static int duration_to_length(struct taprio_sched *q, u64 duration)
{
return div_u64(duration * PSEC_PER_NSEC, atomic64_read(&q->picos_per_byte));
@@ -915,6 +935,51 @@ static bool should_change_schedules(const struct sched_gate_list *admin,
return false;
}
+/* The operational schedule fell behind, e.g. because the timer was delayed
+ * or the reference clock stepped forward. Advancing one entry per timer
+ * expiry would replay the whole backlog from hrtimer context, so skip
+ * complete cycles arithmetically and walk the remaining entries to land on
+ * the entry covering the current time.
+ */
+static void taprio_catch_up(struct sched_gate_list *oper,
+ struct sched_entry **next, ktime_t *next_start,
+ ktime_t *end_time, ktime_t now)
+{
+ int budget = 2 * oper->num_entries + 1;
+ struct sched_entry *entry = *next;
+ ktime_t start = *next_start;
+ ktime_t end = *end_time;
+ s64 behind = ktime_sub(now, end);
+
+ if (oper->cycle_time > 0 && behind >= oper->cycle_time) {
+ s64 jump = div64_s64(behind, oper->cycle_time) * oper->cycle_time;
+
+ start = ktime_add_ns(start, jump);
+ end = ktime_add_ns(end, jump);
+ oper->cycle_end_time = ktime_add_ns(oper->cycle_end_time, jump);
+ }
+
+ while (ktime_before(end, now) && --budget) {
+ if (list_is_last(&entry->list, &oper->entries) ||
+ ktime_compare(end, oper->cycle_end_time) == 0) {
+ entry = list_first_entry(&oper->entries,
+ struct sched_entry, list);
+ oper->cycle_end_time = ktime_add_ns(oper->cycle_end_time,
+ oper->cycle_time);
+ } else {
+ entry = list_next_entry(entry, list);
+ }
+
+ start = end;
+ end = ktime_add_ns(end, entry->interval);
+ end = min_t(ktime_t, end, oper->cycle_end_time);
+ }
+
+ *next = entry;
+ *next_start = start;
+ *end_time = end;
+}
+
static enum hrtimer_restart advance_sched(struct hrtimer *timer)
{
struct taprio_sched *q = container_of(timer, struct taprio_sched,
@@ -924,7 +989,7 @@ static enum hrtimer_restart advance_sched(struct hrtimer *timer)
int num_tc = netdev_get_num_tc(dev);
struct sched_entry *entry, *next;
struct Qdisc *sch = q->root;
- ktime_t end_time;
+ ktime_t end_time, next_start, now;
int tc;
spin_lock(&q->current_entry_lock);
@@ -960,14 +1025,19 @@ static enum hrtimer_restart advance_sched(struct hrtimer *timer)
next = list_next_entry(entry, list);
}
- end_time = ktime_add_ns(entry->end_time, next->interval);
+ next_start = entry->end_time;
+ end_time = ktime_add_ns(next_start, next->interval);
end_time = min_t(ktime_t, end_time, oper->cycle_end_time);
+ now = taprio_get_time(q);
+ if (unlikely(ktime_before(end_time, now)))
+ taprio_catch_up(oper, &next, &next_start, &end_time, now);
+
for (tc = 0; tc < num_tc; tc++) {
if (next->gate_duration[tc] == oper->cycle_time)
next->gate_close_time[tc] = KTIME_MAX;
else
- next->gate_close_time[tc] = ktime_add_ns(entry->end_time,
+ next->gate_close_time[tc] = ktime_add_ns(next_start,
next->gate_duration[tc]);
}
@@ -1038,7 +1108,7 @@ static int fill_sched_entry(struct taprio_sched *q, struct nlattr **tb,
struct sched_entry *entry,
struct netlink_ext_ack *extack)
{
- int min_duration = length_to_duration(q, ETH_ZLEN);
+ s64 min_duration = taprio_min_interval(q);
u32 interval = 0;
if (tb[TCA_TAPRIO_SCHED_ENTRY_CMD])
@@ -1166,7 +1236,7 @@ static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb,
new->cycle_time = cycle;
}
- if (new->cycle_time < new->num_entries * length_to_duration(q, ETH_ZLEN)) {
+ if (new->cycle_time < (s64)new->num_entries * taprio_min_interval(q)) {
NL_SET_ERR_MSG(extack, "'cycle_time' is too small");
return -EINVAL;
}
next prev parent reply other threads:[~2026-08-17 5:22 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-21 15:44 [syzbot] [mm?] INFO: rcu detected stall in exit_to_user_mode_loop syzbot
2025-07-12 0:18 ` syzbot
2025-07-28 21:30 ` syzbot
2025-07-29 1:06 ` Hillf Danton
2025-07-29 4:47 ` syzbot
2026-08-17 7:21 ` Junjie Cao [this message]
2026-08-17 6:02 ` syzbot
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=20260817072146.313493-1-junjie.cao@linux.dev \
--to=junjie.cao@linux.dev \
--cc=hdanton@sina.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=syzbot+2642f347f7309b4880dc@syzkaller.appspotmail.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 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.