summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/sched/ext/ext.c90
-rw-r--r--kernel/sched/ext/internal.h7
-rw-r--r--kernel/sched/ext/sub.c7
3 files changed, 64 insertions, 40 deletions
diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
index dfa624b8607e..cc526776b3cc 100644
--- a/kernel/sched/ext/ext.c
+++ b/kernel/sched/ext/ext.c
@@ -196,9 +196,6 @@ static const struct rhashtable_params dsq_hash_params = {
static LLIST_HEAD(dsqs_to_free);
-DEFINE_RAW_SPINLOCK(scx_exit_bstr_buf_lock);
-struct scx_bstr_buf scx_exit_bstr_buf;
-
/* ops debug dump */
static DEFINE_RAW_SPINLOCK(scx_dump_lock);
@@ -6760,17 +6757,12 @@ static void scx_disable_irq_workfn(struct irq_work *irq_work)
kthread_queue_work(sch->helper, &sch->disable_work);
}
-bool scx_vexit(struct scx_sched *sch,
- enum scx_exit_kind kind, s64 exit_code, s32 exit_cpu,
- const char *fmt, va_list args)
+/* finish exit_info and kick the disable work, ei->msg must already be set */
+static void scx_finish_exit(struct scx_sched *sch, enum scx_exit_kind kind,
+ s64 exit_code, s32 exit_cpu)
{
struct scx_exit_info *ei = sch->exit_info;
- guard(preempt)();
-
- if (!scx_claim_exit(sch, kind))
- return false;
-
ei->exit_code = exit_code;
#ifdef CONFIG_STACKTRACE
/*
@@ -6780,8 +6772,6 @@ bool scx_vexit(struct scx_sched *sch,
if (kind >= SCX_EXIT_ERROR && !in_nmi())
ei->bt_len = stack_trace_save(ei->bt, SCX_EXIT_BT_LEN, 1);
#endif
- vscnprintf(ei->msg, SCX_EXIT_MSG_LEN, fmt, args);
-
/*
* Set ei->kind and ->reason for scx_dump_state(). They'll be set again
* in scx_disable_workfn().
@@ -6791,6 +6781,22 @@ bool scx_vexit(struct scx_sched *sch,
ei->exit_cpu = exit_cpu;
irq_work_queue(&sch->disable_irq_work);
+}
+
+bool scx_vexit(struct scx_sched *sch,
+ enum scx_exit_kind kind, s64 exit_code, s32 exit_cpu,
+ const char *fmt, va_list args)
+{
+ struct scx_exit_info *ei = sch->exit_info;
+
+ guard(preempt)();
+
+ if (!scx_claim_exit(sch, kind))
+ return false;
+
+ vscnprintf(ei->msg, SCX_EXIT_MSG_LEN, fmt, args);
+
+ scx_finish_exit(sch, kind, exit_code, exit_cpu);
return true;
}
@@ -9604,12 +9610,38 @@ static s32 __bstr_format(struct scx_sched *sch, u64 *data_buf, char *line_buf,
return ret;
}
-__printf(3, 0)
-s32 scx_bstr_format(struct scx_sched *sch, struct scx_bstr_buf *buf,
- char *fmt, unsigned long long *data, u32 data__sz)
+/*
+ * Exit @sch with the reason formatted from a BPF-supplied bstr format. The exit
+ * is claimed first and the reason is formatted directly into the winner-owned
+ * exit_info buffer, which allows use from any context including NMI.
+ *
+ * @fmt_blame is the sched blamed for formatting failures through the
+ * scx_error() calls in __bstr_format() and differs from @sch when a parent
+ * supplies the kill reason for a child. A formatting failure doesn't revert the
+ * claim - @sch still exits with the claimed kind and a fallback message.
+ */
+__printf(5, 0)
+bool scx_exit_bstr(struct scx_sched *sch, enum scx_exit_kind kind,
+ s64 exit_code, struct scx_sched *fmt_blame, char *fmt,
+ unsigned long long *data, u32 data__sz)
{
- return __bstr_format(sch, buf->data, buf->line, sizeof(buf->line),
- fmt, data, data__sz);
+ struct scx_exit_info *ei = sch->exit_info;
+ u64 data_buf[MAX_BPRINTF_VARARGS];
+ s32 ret;
+
+ guard(preempt)();
+
+ if (!scx_claim_exit(sch, kind))
+ return false;
+
+ ret = __bstr_format(fmt_blame, data_buf, ei->msg, SCX_EXIT_MSG_LEN,
+ fmt, data, data__sz);
+ if (ret < 0)
+ scnprintf(ei->msg, SCX_EXIT_MSG_LEN,
+ "exit message formatting failed (%d)", ret);
+
+ scx_finish_exit(sch, kind, exit_code, raw_smp_processor_id());
+ return true;
}
__bpf_kfunc_start_defs();
@@ -9631,14 +9663,13 @@ __bpf_kfunc void scx_bpf_exit_bstr(s64 exit_code, char *fmt,
const struct bpf_prog_aux *aux)
{
struct scx_sched *sch;
- unsigned long flags;
- raw_spin_lock_irqsave(&scx_exit_bstr_buf_lock, flags);
+ guard(rcu)();
+
sch = scx_prog_sched(aux);
- if (likely(sch) &&
- scx_bstr_format(sch, &scx_exit_bstr_buf, fmt, data, data__sz) >= 0)
- scx_exit(sch, SCX_EXIT_UNREG_BPF, exit_code, "%s", scx_exit_bstr_buf.line);
- raw_spin_unlock_irqrestore(&scx_exit_bstr_buf_lock, flags);
+ if (likely(sch))
+ scx_exit_bstr(sch, SCX_EXIT_UNREG_BPF, exit_code, sch, fmt,
+ data, data__sz);
}
/**
@@ -9656,14 +9687,13 @@ __bpf_kfunc void scx_bpf_error_bstr(char *fmt, unsigned long long *data,
u32 data__sz, const struct bpf_prog_aux *aux)
{
struct scx_sched *sch;
- unsigned long flags;
- raw_spin_lock_irqsave(&scx_exit_bstr_buf_lock, flags);
+ guard(rcu)();
+
sch = scx_prog_sched(aux);
- if (likely(sch) &&
- scx_bstr_format(sch, &scx_exit_bstr_buf, fmt, data, data__sz) >= 0)
- scx_exit(sch, SCX_EXIT_ERROR_BPF, 0, "%s", scx_exit_bstr_buf.line);
- raw_spin_unlock_irqrestore(&scx_exit_bstr_buf_lock, flags);
+ if (likely(sch))
+ scx_exit_bstr(sch, SCX_EXIT_ERROR_BPF, 0, sch, fmt, data,
+ data__sz);
}
/**
diff --git a/kernel/sched/ext/internal.h b/kernel/sched/ext/internal.h
index d9ab6571d7ad..5b73ffb0251a 100644
--- a/kernel/sched/ext/internal.h
+++ b/kernel/sched/ext/internal.h
@@ -2004,15 +2004,14 @@ struct scx_sched *scx_alloc_and_add_sched(struct scx_enable_cmd *cmd,
int scx_validate_ops(struct scx_sched *sch, const struct sched_ext_ops *ops);
int scx_sched_sysfs_add(struct scx_sched *sch);
bool scx_is_descendant(struct scx_sched *sch, struct scx_sched *ancestor);
-__printf(3, 0) s32 scx_bstr_format(struct scx_sched *sch, struct scx_bstr_buf *buf,
- char *fmt, unsigned long long *data, u32 data__sz);
+__printf(5, 0) bool scx_exit_bstr(struct scx_sched *sch, enum scx_exit_kind kind,
+ s64 exit_code, struct scx_sched *fmt_blame,
+ char *fmt, unsigned long long *data, u32 data__sz);
extern raw_spinlock_t scx_sched_lock;
extern struct mutex scx_enable_mutex;
extern struct percpu_rw_semaphore scx_fork_rwsem;
extern bool scx_cgroup_enabled;
-extern raw_spinlock_t scx_exit_bstr_buf_lock;
-extern struct scx_bstr_buf scx_exit_bstr_buf;
#ifdef CONFIG_EXT_SUB_SCHED
extern const struct rhashtable_params scx_sched_hash_params;
extern struct rhashtable scx_sched_hash;
diff --git a/kernel/sched/ext/sub.c b/kernel/sched/ext/sub.c
index 7a5eb3a6f488..daf7fbd3d0c3 100644
--- a/kernel/sched/ext/sub.c
+++ b/kernel/sched/ext/sub.c
@@ -2155,7 +2155,6 @@ __bpf_kfunc s32 scx_bpf_sub_kill_bstr(u64 cgroup_id, char *fmt,
const struct bpf_prog_aux *aux)
{
struct scx_sched *parent, *child;
- s32 ret;
guard(rcu)();
@@ -2178,11 +2177,7 @@ __bpf_kfunc s32 scx_bpf_sub_kill_bstr(u64 cgroup_id, char *fmt,
return -EINVAL;
}
- guard(raw_spinlock_irqsave)(&scx_exit_bstr_buf_lock);
- ret = scx_bstr_format(parent, &scx_exit_bstr_buf, fmt, data, data__sz);
- if (ret < 0)
- return ret;
- scx_exit(child, SCX_EXIT_PARENT_KILL, 0, "%s", scx_exit_bstr_buf.line);
+ scx_exit_bstr(child, SCX_EXIT_PARENT_KILL, 0, parent, fmt, data, data__sz);
return 0;
}