Skip to content

Commit ab4df19

Browse files
committed
Documentation: Use coccinelle to identify and count LLR candidates
From Linux Kernel Requirements Template: The design elements to be documented are the Linux Kernel drivers/subsystems mainly through the documentation of the respective interfaces. [...] Summary: - Syscalls - Procfs - sysfs - debugfs - "other user space interfaces" - Signals - Kernel Space Interfaces To assess feasiblity and get a definition of done, we should know exactly how many / which elements to document. This demonstrates an approach how to search for relevant elements using Coccinell. [1] https://docs.google.com/document/d/1c7S7YAledHP2EEQ2nh26Ibegij-XPNuUFkrFLtJPlzs/edit?tab=t.0#heading=h.9rwxa6ye9gez Signed-off-by: Tobias Deiminger <tobias.deiminger@linutronix.de>
1 parent f8fbab9 commit ab4df19

7 files changed

Lines changed: 1368 additions & 0 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Kernel Requirements CI
2+
on:
3+
push:
4+
jobs:
5+
build:
6+
permissions:
7+
contents: write
8+
name: Search for functions that need documentation
9+
runs-on: ubuntu-24.04
10+
steps:
11+
- uses: actions/checkout@v3
12+
13+
- name: install StrictDoc
14+
run: sudo apt install coccinelle
15+
16+
- name: Run coccinelle
17+
run: cocci/find_doc_elements.sh | tee >(wc -l | xargs printf "We need to document %s elements.\n")
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Exported Symbols
3+
*
4+
* Exported symbols are accessible to loadable module and out-of-tree drivers
5+
* and thus are public API.
6+
*
7+
* This implements a search for macros EXPORT_SYMBOL and EXPORT_SYMBOL_GPL,
8+
* and then finds the name and position of the referenced function definition.
9+
*/
10+
11+
12+
@export_symbol@
13+
declarer name EXPORT_SYMBOL;
14+
declarer name EXPORT_SYMBOL_GPL;
15+
identifier fn;
16+
@@
17+
(
18+
EXPORT_SYMBOL(fn);
19+
|
20+
EXPORT_SYMBOL_GPL(fn);
21+
)
22+
23+
@export_symbol_fn@
24+
identifier export_symbol.fn;
25+
position p_fn;
26+
@@
27+
fn@p_fn(...) {...}
28+
29+
30+
// Report
31+
32+
@script:python@
33+
fn << export_symbol.fn;
34+
p << export_symbol_fn.p_fn;
35+
@@
36+
print(f"exppoted function: {fn} at {p[0].file}:{p[0].line}")
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/bin/bash
2+
3+
coccidir=$(dirname "$0")
4+
5+
/usr/bin/spatch \
6+
--very-quiet \
7+
--cocci-file "${coccidir}/syscall.cocci" \
8+
--macro-file-builtins "${coccidir}/standard.h" \
9+
--no-includes \
10+
--include-headers \
11+
-I ./arch/x86/include \
12+
-I ./arch/x86/include/generated \
13+
-I ./include \
14+
-I ./include \
15+
-I ./arch/x86/include/uapi \
16+
-I ./arch/x86/include/generated/uapi \
17+
-I ./include/uapi \
18+
-I ./include/generated/uapi \
19+
--include ./include/linux/compiler-version.h \
20+
--include ./include/linux/kconfig.h \
21+
--jobs 4 --chunksize 1 \
22+
--dir .
23+
24+
/usr/bin/spatch \
25+
--very-quiet \
26+
--cocci-file "${coccidir}/exportedsyms.cocci" \
27+
--no-includes \
28+
--include-headers \
29+
-I ./arch/x86/include \
30+
-I ./arch/x86/include/generated \
31+
-I ./include \
32+
-I ./include \
33+
-I ./arch/x86/include/uapi \
34+
-I ./arch/x86/include/generated/uapi \
35+
-I ./include/uapi \
36+
-I ./include/generated/uapi \
37+
--include ./include/linux/compiler-version.h \
38+
--include ./include/linux/kconfig.h \
39+
--jobs 4 --chunksize 1 \
40+
--no-show-diff \
41+
--dir .
42+
43+
/usr/bin/spatch \
44+
--very-quiet \
45+
--cocci-file "${coccidir}/sysfs.cocci" \
46+
--no-includes \
47+
--include-headers \
48+
-I ./arch/x86/include \
49+
-I ./arch/x86/include/generated \
50+
-I ./include \
51+
-I ./include \
52+
-I ./arch/x86/include/uapi \
53+
-I ./arch/x86/include/generated/uapi \
54+
-I ./include/uapi \
55+
-I ./include/generated/uapi \
56+
--include ./include/linux/compiler-version.h \
57+
--include ./include/linux/kconfig.h \
58+
--jobs 4 --chunksize 1 \
59+
--no-show-diff \
60+
--dir .
61+
62+
/usr/bin/spatch \
63+
--very-quiet \
64+
--cocci-file "${coccidir}/fops.cocci" \
65+
--no-includes \
66+
--include-headers \
67+
-I ./arch/x86/include \
68+
-I ./arch/x86/include/generated \
69+
-I ./include \
70+
-I ./include \
71+
-I ./arch/x86/include/uapi \
72+
-I ./arch/x86/include/generated/uapi \
73+
-I ./include/uapi \
74+
-I ./include/generated/uapi \
75+
--include ./include/linux/compiler-version.h \
76+
--include ./include/linux/kconfig.h \
77+
--jobs 4 --chunksize 1 \
78+
--dir .

scripts/coccinelle/docs/fops.cocci

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
/*
2+
* All functions of file-like drivers.
3+
*/
4+
5+
@ fops0 @
6+
identifier fops;
7+
@@
8+
struct file_operations fops = {
9+
...
10+
};
11+
12+
@ has_read @
13+
identifier fops0.fops;
14+
identifier read_f;
15+
@@
16+
struct file_operations fops = {
17+
.read = read_f,
18+
};
19+
20+
@ read_fn @
21+
identifier has_read.read_f;
22+
position p_read_f;
23+
@@
24+
read_f@p_read_f(...) {...}
25+
26+
27+
@ has_read_iter @
28+
identifier fops0.fops;
29+
identifier read_iter_f;
30+
@@
31+
struct file_operations fops = {
32+
.read_iter = read_iter_f,
33+
};
34+
35+
@ read_iter_fn @
36+
identifier has_read_iter.read_iter_f;
37+
position p_read_iter_f;
38+
@@
39+
read_iter_f@p_read_iter_f(...) {...}
40+
41+
42+
@ has_write @
43+
identifier fops0.fops;
44+
identifier write_f;
45+
@@
46+
struct file_operations fops = {
47+
.write = write_f,
48+
};
49+
50+
@ write_fn @
51+
identifier has_write.write_f;
52+
position p_write_f;
53+
@@
54+
write_f@p_write_f(...) {...}
55+
56+
57+
@ has_write_iter @
58+
identifier fops0.fops;
59+
identifier write_iter_f;
60+
@@
61+
struct file_operations fops = {
62+
.write_iter = write_iter_f,
63+
};
64+
65+
@ write_iter_fn @
66+
identifier has_write_iter.write_iter_f;
67+
position p_write_iter_f;
68+
@@
69+
write_iter_f@p_write_iter_f(...) {...}
70+
71+
72+
@ has_llseek @
73+
identifier fops0.fops;
74+
identifier llseek_f;
75+
@@
76+
struct file_operations fops = {
77+
.llseek = llseek_f,
78+
};
79+
80+
@ llseek_fn @
81+
identifier has_llseek.llseek_f;
82+
position p_llseek_f;
83+
@@
84+
llseek_f@p_llseek_f(...) {...}
85+
86+
87+
@ has_mmap @
88+
identifier fops0.fops;
89+
identifier mmap_f;
90+
@@
91+
struct file_operations fops = {
92+
.mmap = mmap_f,
93+
};
94+
95+
@ mmap_fn @
96+
identifier has_mmap.mmap_f;
97+
position p_mmap_f;
98+
@@
99+
mmap_f@p_mmap_f(...) {...}
100+
101+
102+
@ has_copy_file_range @
103+
identifier fops0.fops;
104+
identifier copy_file_range_f;
105+
@@
106+
struct file_operations fops = {
107+
.copy_file_range = copy_file_range_f,
108+
};
109+
110+
@ copy_file_range_fn @
111+
identifier has_copy_file_range.copy_file_range_f;
112+
position p_copy_file_range_f;
113+
@@
114+
copy_file_range_f@p_copy_file_range_f(...) {...}
115+
116+
117+
@ has_remap_file_range @
118+
identifier fops0.fops;
119+
identifier remap_file_range_f;
120+
@@
121+
struct file_operations fops = {
122+
.remap_file_range = remap_file_range_f,
123+
};
124+
125+
@ remap_file_range_fn @
126+
identifier has_remap_file_range.remap_file_range_f;
127+
position p_remap_file_range_f;
128+
@@
129+
remap_file_range_f@p_remap_file_range_f(...) {...}
130+
131+
132+
@ has_splice_read @
133+
identifier fops0.fops;
134+
identifier splice_read_f;
135+
@@
136+
struct file_operations fops = {
137+
.splice_read = splice_read_f,
138+
};
139+
140+
@ splice_read_fn @
141+
identifier has_splice_read.splice_read_f;
142+
position p_splice_read_f;
143+
@@
144+
splice_read_f@p_splice_read_f(...) {...}
145+
146+
147+
@ has_splice_write @
148+
identifier fops0.fops;
149+
identifier splice_write_f;
150+
@@
151+
struct file_operations fops = {
152+
.splice_write = splice_write_f,
153+
};
154+
155+
@ splice_write_fn @
156+
identifier has_splice_write.splice_write_f;
157+
position p_splice_write_f;
158+
@@
159+
splice_write_f@p_splice_write_f(...) {...}
160+
161+
162+
@ script:python@
163+
fops << fops0.fops;
164+
read_f << has_read.read_f;
165+
p << read_fn.p_read_f;
166+
@@
167+
print(f"read ({fops}): {read_f} at {p[0].file}:{p[0].line}")
168+
169+
@script:python@
170+
fops << fops0.fops;
171+
read_iter_f << has_read_iter.read_iter_f;
172+
p << read_iter_fn.p_read_iter_f;
173+
@@
174+
print(f"read_iter ({fops}): {read_iter_f} at {p[0].file}:{p[0].line}")
175+
176+
@script:python@
177+
fops << fops0.fops;
178+
write_f << has_write.write_f;
179+
p << write_fn.p_write_f;
180+
@@
181+
print(f"write ({fops}): {write_f} at {p[0].file}:{p[0].line}")
182+
183+
@script:python@
184+
fops << fops0.fops;
185+
write_iter_f << has_write_iter.write_iter_f;
186+
p << write_iter_fn.p_write_iter_f;
187+
@@
188+
print(f"write_iter ({fops}): {write_iter_f} at {p[0].file}:{p[0].line}")
189+
190+
@script:python@
191+
fops << fops0.fops;
192+
llseek_f << has_llseek.llseek_f;
193+
p << llseek_fn.p_llseek_f;
194+
@@
195+
print(f"llseek ({fops}): {llseek_f} at {p[0].file}:{p[0].line}")
196+
197+
@script:python@
198+
fops << fops0.fops;
199+
mmap_f << has_mmap.mmap_f;
200+
p << mmap_fn.p_mmap_f;
201+
@@
202+
print(f"mmap_f ({fops}): {mmap_f} at {p[0].file}:{p[0].line}")
203+
204+
@script:python@
205+
fops << fops0.fops;
206+
copy_file_range_f << has_copy_file_range.copy_file_range_f;
207+
p << copy_file_range_fn.p_copy_file_range_f;
208+
@@
209+
print(f"copy_file_range ({fops}): {copy_file_range_f} at {p[0].file}:{p[0].line}")
210+
211+
@script:python@
212+
fops << fops0.fops;
213+
remap_file_range_f << has_remap_file_range.remap_file_range_f;
214+
p << remap_file_range_fn.p_remap_file_range_f;
215+
@@
216+
print(f"remap_file_range ({fops}): {remap_file_range_f} at {p[0].file}:{p[0].line}")
217+
218+
@script:python@
219+
fops << fops0.fops;
220+
splice_read_f << has_splice_read.splice_read_f;
221+
p << splice_read_fn.p_splice_read_f;
222+
@@
223+
print(f"splice_read ({fops}): {splice_read_f} at {p[0].file}:{p[0].line}")
224+
225+
@script:python@
226+
fops << fops0.fops;
227+
splice_write_f << has_splice_write.splice_write_f;
228+
p << splice_write_fn.p_splice_write_f;
229+
@@
230+
print(f"splice_write ({fops}): {splice_write_f} at {p[0].file}:{p[0].line}")

0 commit comments

Comments
 (0)