scx_link_sched() carries each failure out of the locked section through err_msg and ret because scx_error() used to take scx_sched_lock and couldn't be called under it. That restriction is gone, so report each failure at the site it's detected and return directly. The scx_error() here claims the exit on the sched being linked, which has no descendants yet, and the locked propagation walk is deferred, so nothing reacquires scx_sched_lock inline.
Showing the changes to kernel (1 of 1 file). Show all
Unified · Split
| @@ -5975,31 +5975,30 @@ static void refresh_watchdog(void) · 5974 unmodified lines | ||
| 5975 | 5975 | |
| 5976 | 5976 | s32 scx_link_sched(struct scx_sched *sch) |
| 5977 | 5977 | { |
| 5978 | − const char *err_msg = ""; | |
| 5979 | − s32 ret = 0; | |
| 5980 | − | |
| 5981 | 5978 | scoped_guard(raw_spinlock_irqsave, &scx_bypass_lock) /* for the parent bypass check */ |
| 5982 | 5979 | scoped_guard(raw_spinlock, &scx_sched_lock) { |
| 5983 | 5980 | #ifdef CONFIG_EXT_SUB_SCHED |
| 5984 | 5981 | struct scx_sched *parent = scx_parent(sch); |
| 5985 | 5982 | |
| 5986 | 5983 | if (parent) { |
| 5984 | + s32 ret; | |
| 5985 | + | |
| 5987 | 5986 | /* |
| 5988 | 5987 | * Bypass state is spread across per-cpu flags and a |
| 5989 | 5988 | * depth count, so inheriting it is tricky and has no |
| 5990 | 5989 | * valid use case. Refuse it. |
| 5991 | 5990 | */ |
| 5992 | 5991 | if (READ_ONCE(parent->bypass_depth)) { |
| 5993 | − err_msg = "parent bypassing"; | |
| 5994 | − ret = -EBUSY; | |
| 5995 | − break; | |
| 5992 | + scx_error(sch, "parent bypassing (%d)", -EBUSY); | |
| 5993 | + return -EBUSY; | |
| 5996 | 5994 | } |
| 5997 | 5995 | |
| 5998 | 5996 | ret = rhashtable_lookup_insert_fast(&scx_sched_hash, |
| 5999 | 5997 | &sch->hash_node, scx_sched_hash_params); |
| 6000 | 5998 | if (ret) { |
| 6001 | − err_msg = "failed to insert into scx_sched_hash"; | |
| 6002 | − break; | |
| 5999 | + scx_error(sch, "failed to insert into scx_sched_hash (%d)", | |
| 6000 | + ret); | |
| 6001 | + return ret; | |
| 6003 | 6002 | } |
| 6004 | 6003 | |
| 6005 | 6004 | list_add_tail_rcu(&sch->sibling, &parent->children); |
| @@ -6014,9 +6013,8 @@ s32 scx_link_sched(struct scx_sched *sch) · 8 unmodified lines | ||
| 6014 | 6013 | rhashtable_remove_fast(&scx_sched_hash, &sch->hash_node, |
| 6015 | 6014 | scx_sched_hash_params); |
| 6016 | 6015 | list_del_rcu(&sch->sibling); |
| 6017 | − err_msg = "parent disabled"; | |
| 6018 | − ret = -ENOENT; | |
| 6019 | − break; | |
| 6016 | + scx_error(sch, "parent disabled (%d)", -ENOENT); | |
| 6017 | + return -ENOENT; | |
| 6020 | 6018 | } |
| 6021 | 6019 | |
| 6022 | 6020 | sch->linked = true; |
| @@ -6026,15 +6024,6 @@ s32 scx_link_sched(struct scx_sched *sch) · 3 unmodified lines | ||
| 6026 | 6024 | list_add_tail_rcu(&sch->all, &scx_sched_all); |
| 6027 | 6025 | } |
| 6028 | 6026 | |
| 6029 | − /* | |
| 6030 | − * scx_error() takes scx_sched_lock via scx_claim_exit(), so it must run after | |
| 6031 | − * the guard above is released. | |
| 6032 | − */ | |
| 6033 | − if (ret) { | |
| 6034 | − scx_error(sch, "%s (%d)", err_msg, ret); | |
| 6035 | − return ret; | |
| 6036 | − } | |
| 6037 | − | |
| 6038 | 6027 | refresh_watchdog(); |
| 6039 | 6028 | return 0; |
| 6040 | 6029 | } |