History

include/linux/list.h: mark list_add and __list_add as __always_inline

This commit resolves an issue where modpost section verification fails due to section mismatches between list_add and its callers. At present, list_add (and its internal __list_add) are called from both .text and .init code sections. Since inlining can vary per call site, list_add can be 4 different states: list_add in text with arguments to non-.init.data values list_add in init with arguments to static .init.data values list_add in init with arguments to non-.init.data values list_add in text with arguments to static .init.data values It is last instance that ends up causing the section mismatch caused by constant propagation of the address of static libs inside the `dir_add` as seen below (with the dir_list being defined statically in initramfs.c, resting in .init.data). WARNING: modpost: vmlinux.o: section mismatch in reference: __list_add (section: .text.unlikely.) -> dir_list (section: .init.data) Because of these section matching requirements, semantically, __list_add and list_add MUST be inlined. This will then ensure callers inside .init will receive a list_add that exists and refers to only .init data, and list_add code in .text sections will only refer to non-init data. This issue manifests predominently in AutoFDO with clang, which is very hesitant to inline cold functions such as list_add even when marked `inline`. Marking them as `__always_inline` therefore matches the existing semantic constraints imposed by modpost's section mismatch checks.

Jordan R Abrahams-Whitehead committed 3 months ago

Commit 27808601 parent 825cef91 file · +11 −4Browse files

Unified · Split

include/linux/list.h+11−4
@@ -150,10 +150,13 @@ static inline bool __list_del_entry_valid(struct list_head *entry) · 149 unmodified lines
150 *150 *
151 * This is only for internal list manipulation where we know151 * This is only for internal list manipulation where we know
152 * the prev/next entries already!152 * the prev/next entries already!
153 *
154 * Must be inlined to ensure it can be safely called
155 * with initdata arguments.
153 */156 */
154static inline void __list_add(struct list_head *new,157static __always_inline void __list_add(struct list_head *new,
155 struct list_head *prev,158 struct list_head *prev,
156 struct list_head *next)159 struct list_head *next)
157{160{
158 if (!__list_add_valid(new, prev, next))161 if (!__list_add_valid(new, prev, next))
159 return;162 return;
@@ -171,8 +174,12 @@ static inline void __list_add(struct list_head *new, · 11 unmodified lines
171 *174 *
172 * Insert a new entry after the specified head.175 * Insert a new entry after the specified head.
173 * This is good for implementing stacks.176 * This is good for implementing stacks.
177 *
178 * Must be inlined to ensure it can be safely called
179 * with initdata arguments.
174 */180 */
175static inline void list_add(struct list_head *new, struct list_head *head)181static __always_inline void list_add(struct list_head *new,
182 struct list_head *head)
176{183{
177 __list_add(new, head, head->next);184 __list_add(new, head, head->next);
178}185}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t