~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/coccinelle/api/stream_open.cocci

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /scripts/coccinelle/api/stream_open.cocci (Architecture sparc64) and /scripts/coccinelle/api/stream_open.cocci (Architecture alpha)


  1 // SPDX-License-Identifier: GPL-2.0                 1 // SPDX-License-Identifier: GPL-2.0
  2 // Author: Kirill Smelkov (kirr@nexedi.com)         2 // Author: Kirill Smelkov (kirr@nexedi.com)
  3 //                                                  3 //
  4 // Search for stream-like files that are using      4 // Search for stream-like files that are using nonseekable_open and convert
  5 // them to stream_open. A stream-like file is       5 // them to stream_open. A stream-like file is a file that does not use ppos in
  6 // its read and write. Rationale for the conve      6 // its read and write. Rationale for the conversion is to avoid deadlock in
  7 // between read and write.                          7 // between read and write.
  8                                                     8 
  9 virtual report                                      9 virtual report
 10 virtual patch                                      10 virtual patch
 11 virtual explain  // explain decisions in the p     11 virtual explain  // explain decisions in the patch (SPFLAGS="-D explain")
 12                                                    12 
 13 // stream-like reader & writer - ones that do      13 // stream-like reader & writer - ones that do not depend on f_pos.
 14 @ stream_reader @                                  14 @ stream_reader @
 15 identifier readstream, ppos;                       15 identifier readstream, ppos;
 16 identifier f, buf, len;                            16 identifier f, buf, len;
 17 type loff_t;                                       17 type loff_t;
 18 @@                                                 18 @@
 19   ssize_t readstream(struct file *f, char *buf     19   ssize_t readstream(struct file *f, char *buf, size_t len, loff_t *ppos)
 20   {                                                20   {
 21     ... when != ppos                               21     ... when != ppos
 22   }                                                22   }
 23                                                    23 
 24 @ stream_writer @                                  24 @ stream_writer @
 25 identifier writestream, ppos;                      25 identifier writestream, ppos;
 26 identifier f, buf, len;                            26 identifier f, buf, len;
 27 type loff_t;                                       27 type loff_t;
 28 @@                                                 28 @@
 29   ssize_t writestream(struct file *f, const ch     29   ssize_t writestream(struct file *f, const char *buf, size_t len, loff_t *ppos)
 30   {                                                30   {
 31     ... when != ppos                               31     ... when != ppos
 32   }                                                32   }
 33                                                    33 
 34                                                    34 
 35 // a function that blocks                          35 // a function that blocks
 36 @ blocks @                                         36 @ blocks @
 37 identifier block_f;                                37 identifier block_f;
 38 identifier wait =~ "^wait_.*";                     38 identifier wait =~ "^wait_.*";
 39 @@                                                 39 @@
 40   block_f(...) {                                   40   block_f(...) {
 41     ... when exists                                41     ... when exists
 42     wait(...)                                      42     wait(...)
 43     ... when exists                                43     ... when exists
 44   }                                                44   }
 45                                                    45 
 46 // stream_reader that can block inside.            46 // stream_reader that can block inside.
 47 //                                                 47 //
 48 // XXX wait_* can be called not directly from      48 // XXX wait_* can be called not directly from current function (e.g. func -> f -> g -> wait())
 49 // XXX currently reader_blocks supports only d     49 // XXX currently reader_blocks supports only direct and 1-level indirect cases.
 50 @ reader_blocks_direct @                           50 @ reader_blocks_direct @
 51 identifier stream_reader.readstream;               51 identifier stream_reader.readstream;
 52 identifier wait =~ "^wait_.*";                     52 identifier wait =~ "^wait_.*";
 53 @@                                                 53 @@
 54   readstream(...)                                  54   readstream(...)
 55   {                                                55   {
 56     ... when exists                                56     ... when exists
 57     wait(...)                                      57     wait(...)
 58     ... when exists                                58     ... when exists
 59   }                                                59   }
 60                                                    60 
 61 @ reader_blocks_1 @                                61 @ reader_blocks_1 @
 62 identifier stream_reader.readstream;               62 identifier stream_reader.readstream;
 63 identifier blocks.block_f;                         63 identifier blocks.block_f;
 64 @@                                                 64 @@
 65   readstream(...)                                  65   readstream(...)
 66   {                                                66   {
 67     ... when exists                                67     ... when exists
 68     block_f(...)                                   68     block_f(...)
 69     ... when exists                                69     ... when exists
 70   }                                                70   }
 71                                                    71 
 72 @ reader_blocks depends on reader_blocks_direc     72 @ reader_blocks depends on reader_blocks_direct || reader_blocks_1 @
 73 identifier stream_reader.readstream;               73 identifier stream_reader.readstream;
 74 @@                                                 74 @@
 75   readstream(...) {                                75   readstream(...) {
 76     ...                                            76     ...
 77   }                                                77   }
 78                                                    78 
 79                                                    79 
 80 // file_operations + whether they have _any_ .     80 // file_operations + whether they have _any_ .read, .write, .llseek ... at all.
 81 //                                                 81 //
 82 // XXX add support for file_operations xxx[N]      82 // XXX add support for file_operations xxx[N] = ...     (sound/core/pcm_native.c)
 83 @ fops0 @                                          83 @ fops0 @
 84 identifier fops;                                   84 identifier fops;
 85 @@                                                 85 @@
 86   struct file_operations fops = {                  86   struct file_operations fops = {
 87     ...                                            87     ...
 88   };                                               88   };
 89                                                    89 
 90 @ has_read @                                       90 @ has_read @
 91 identifier fops0.fops;                             91 identifier fops0.fops;
 92 identifier read_f;                                 92 identifier read_f;
 93 @@                                                 93 @@
 94   struct file_operations fops = {                  94   struct file_operations fops = {
 95     .read = read_f,                                95     .read = read_f,
 96   };                                               96   };
 97                                                    97 
 98 @ has_read_iter @                                  98 @ has_read_iter @
 99 identifier fops0.fops;                             99 identifier fops0.fops;
100 identifier read_iter_f;                           100 identifier read_iter_f;
101 @@                                                101 @@
102   struct file_operations fops = {                 102   struct file_operations fops = {
103     .read_iter = read_iter_f,                     103     .read_iter = read_iter_f,
104   };                                              104   };
105                                                   105 
106 @ has_write @                                     106 @ has_write @
107 identifier fops0.fops;                            107 identifier fops0.fops;
108 identifier write_f;                               108 identifier write_f;
109 @@                                                109 @@
110   struct file_operations fops = {                 110   struct file_operations fops = {
111     .write = write_f,                             111     .write = write_f,
112   };                                              112   };
113                                                   113 
114 @ has_write_iter @                                114 @ has_write_iter @
115 identifier fops0.fops;                            115 identifier fops0.fops;
116 identifier write_iter_f;                          116 identifier write_iter_f;
117 @@                                                117 @@
118   struct file_operations fops = {                 118   struct file_operations fops = {
119     .write_iter = write_iter_f,                   119     .write_iter = write_iter_f,
120   };                                              120   };
121                                                   121 
122 @ has_llseek @                                    122 @ has_llseek @
123 identifier fops0.fops;                            123 identifier fops0.fops;
124 identifier llseek_f;                              124 identifier llseek_f;
125 @@                                                125 @@
126   struct file_operations fops = {                 126   struct file_operations fops = {
127     .llseek = llseek_f,                           127     .llseek = llseek_f,
128   };                                              128   };
129                                                   129 
130 @ has_no_llseek @                                 130 @ has_no_llseek @
131 identifier fops0.fops;                            131 identifier fops0.fops;
132 @@                                                132 @@
133   struct file_operations fops = {                 133   struct file_operations fops = {
134   };                                              134   };
135                                                   135 
136 @ has_noop_llseek @                               136 @ has_noop_llseek @
137 identifier fops0.fops;                            137 identifier fops0.fops;
138 @@                                                138 @@
139   struct file_operations fops = {                 139   struct file_operations fops = {
140     .llseek = noop_llseek,                        140     .llseek = noop_llseek,
141   };                                              141   };
142                                                   142 
143 @ has_mmap @                                      143 @ has_mmap @
144 identifier fops0.fops;                            144 identifier fops0.fops;
145 identifier mmap_f;                                145 identifier mmap_f;
146 @@                                                146 @@
147   struct file_operations fops = {                 147   struct file_operations fops = {
148     .mmap = mmap_f,                               148     .mmap = mmap_f,
149   };                                              149   };
150                                                   150 
151 @ has_copy_file_range @                           151 @ has_copy_file_range @
152 identifier fops0.fops;                            152 identifier fops0.fops;
153 identifier copy_file_range_f;                     153 identifier copy_file_range_f;
154 @@                                                154 @@
155   struct file_operations fops = {                 155   struct file_operations fops = {
156     .copy_file_range = copy_file_range_f,         156     .copy_file_range = copy_file_range_f,
157   };                                              157   };
158                                                   158 
159 @ has_remap_file_range @                          159 @ has_remap_file_range @
160 identifier fops0.fops;                            160 identifier fops0.fops;
161 identifier remap_file_range_f;                    161 identifier remap_file_range_f;
162 @@                                                162 @@
163   struct file_operations fops = {                 163   struct file_operations fops = {
164     .remap_file_range = remap_file_range_f,       164     .remap_file_range = remap_file_range_f,
165   };                                              165   };
166                                                   166 
167 @ has_splice_read @                               167 @ has_splice_read @
168 identifier fops0.fops;                            168 identifier fops0.fops;
169 identifier splice_read_f;                         169 identifier splice_read_f;
170 @@                                                170 @@
171   struct file_operations fops = {                 171   struct file_operations fops = {
172     .splice_read = splice_read_f,                 172     .splice_read = splice_read_f,
173   };                                              173   };
174                                                   174 
175 @ has_splice_write @                              175 @ has_splice_write @
176 identifier fops0.fops;                            176 identifier fops0.fops;
177 identifier splice_write_f;                        177 identifier splice_write_f;
178 @@                                                178 @@
179   struct file_operations fops = {                 179   struct file_operations fops = {
180     .splice_write = splice_write_f,               180     .splice_write = splice_write_f,
181   };                                              181   };
182                                                   182 
183                                                   183 
184 // file_operations that is candidate for strea    184 // file_operations that is candidate for stream_open conversion - it does not
185 // use mmap and other methods that assume @off    185 // use mmap and other methods that assume @offset access to file.
186 //                                                186 //
187 // XXX for simplicity require no .{read/write}    187 // XXX for simplicity require no .{read/write}_iter and no .splice_{read/write} for now.
188 // XXX maybe_steam.fops cannot be used in othe    188 // XXX maybe_steam.fops cannot be used in other rules - it gives "bad rule maybe_stream or bad variable fops".
189 @ maybe_stream depends on (!has_llseek || has_    189 @ maybe_stream depends on (!has_llseek || has_no_llseek || has_noop_llseek) && !has_mmap && !has_copy_file_range && !has_remap_file_range && !has_read_iter && !has_write_iter && !has_splice_read && !has_splice_write @
190 identifier fops0.fops;                            190 identifier fops0.fops;
191 @@                                                191 @@
192   struct file_operations fops = {                 192   struct file_operations fops = {
193   };                                              193   };
194                                                   194 
195                                                   195 
196 // ---- conversions ----                          196 // ---- conversions ----
197                                                   197 
198 // XXX .open = nonseekable_open -> .open = str    198 // XXX .open = nonseekable_open -> .open = stream_open
199 // XXX .open = func -> openfunc -> nonseekable    199 // XXX .open = func -> openfunc -> nonseekable_open
200                                                   200 
201 // read & write                                   201 // read & write
202 //                                                202 //
203 // if both are used in the same file_operation    203 // if both are used in the same file_operations together with an opener -
204 // under that conditions we can use stream_ope    204 // under that conditions we can use stream_open instead of nonseekable_open.
205 @ fops_rw depends on maybe_stream @               205 @ fops_rw depends on maybe_stream @
206 identifier fops0.fops, openfunc;                  206 identifier fops0.fops, openfunc;
207 identifier stream_reader.readstream;              207 identifier stream_reader.readstream;
208 identifier stream_writer.writestream;             208 identifier stream_writer.writestream;
209 @@                                                209 @@
210   struct file_operations fops = {                 210   struct file_operations fops = {
211       .open  = openfunc,                          211       .open  = openfunc,
212       .read  = readstream,                        212       .read  = readstream,
213       .write = writestream,                       213       .write = writestream,
214   };                                              214   };
215                                                   215 
216 @ report_rw depends on report @                   216 @ report_rw depends on report @
217 identifier fops_rw.openfunc;                      217 identifier fops_rw.openfunc;
218 position p1;                                      218 position p1;
219 @@                                                219 @@
220   openfunc(...) {                                 220   openfunc(...) {
221     <...                                          221     <...
222      nonseekable_open@p1                          222      nonseekable_open@p1
223     ...>                                          223     ...>
224   }                                               224   }
225                                                   225 
226 @ script:python depends on report && reader_bl    226 @ script:python depends on report && reader_blocks @
227 fops << fops0.fops;                               227 fops << fops0.fops;
228 p << report_rw.p1;                                228 p << report_rw.p1;
229 @@                                                229 @@
230 coccilib.report.print_report(p[0],                230 coccilib.report.print_report(p[0],
231   "ERROR: %s: .read() can deadlock .write(); c    231   "ERROR: %s: .read() can deadlock .write(); change nonseekable_open -> stream_open to fix." % (fops,))
232                                                   232 
233 @ script:python depends on report && !reader_b    233 @ script:python depends on report && !reader_blocks @
234 fops << fops0.fops;                               234 fops << fops0.fops;
235 p << report_rw.p1;                                235 p << report_rw.p1;
236 @@                                                236 @@
237 coccilib.report.print_report(p[0],                237 coccilib.report.print_report(p[0],
238   "WARNING: %s: .read() and .write() have stre    238   "WARNING: %s: .read() and .write() have stream semantic; safe to change nonseekable_open -> stream_open." % (fops,))
239                                                   239 
240                                                   240 
241 @ explain_rw_deadlocked depends on explain &&     241 @ explain_rw_deadlocked depends on explain && reader_blocks @
242 identifier fops_rw.openfunc;                      242 identifier fops_rw.openfunc;
243 @@                                                243 @@
244   openfunc(...) {                                 244   openfunc(...) {
245     <...                                          245     <...
246 -    nonseekable_open                             246 -    nonseekable_open
247 +    nonseekable_open /* read & write (was dea    247 +    nonseekable_open /* read & write (was deadlock) */
248     ...>                                          248     ...>
249   }                                               249   }
250                                                   250 
251                                                   251 
252 @ explain_rw_nodeadlock depends on explain &&     252 @ explain_rw_nodeadlock depends on explain && !reader_blocks @
253 identifier fops_rw.openfunc;                      253 identifier fops_rw.openfunc;
254 @@                                                254 @@
255   openfunc(...) {                                 255   openfunc(...) {
256     <...                                          256     <...
257 -    nonseekable_open                             257 -    nonseekable_open
258 +    nonseekable_open /* read & write (no dire    258 +    nonseekable_open /* read & write (no direct deadlock) */
259     ...>                                          259     ...>
260   }                                               260   }
261                                                   261 
262 @ patch_rw depends on patch @                     262 @ patch_rw depends on patch @
263 identifier fops_rw.openfunc;                      263 identifier fops_rw.openfunc;
264 @@                                                264 @@
265   openfunc(...) {                                 265   openfunc(...) {
266     <...                                          266     <...
267 -   nonseekable_open                              267 -   nonseekable_open
268 +   stream_open                                   268 +   stream_open
269     ...>                                          269     ...>
270   }                                               270   }
271                                                   271 
272                                                   272 
273 // read, but not write                            273 // read, but not write
274 @ fops_r depends on maybe_stream && !has_write    274 @ fops_r depends on maybe_stream && !has_write @
275 identifier fops0.fops, openfunc;                  275 identifier fops0.fops, openfunc;
276 identifier stream_reader.readstream;              276 identifier stream_reader.readstream;
277 @@                                                277 @@
278   struct file_operations fops = {                 278   struct file_operations fops = {
279       .open  = openfunc,                          279       .open  = openfunc,
280       .read  = readstream,                        280       .read  = readstream,
281   };                                              281   };
282                                                   282 
283 @ report_r depends on report @                    283 @ report_r depends on report @
284 identifier fops_r.openfunc;                       284 identifier fops_r.openfunc;
285 position p1;                                      285 position p1;
286 @@                                                286 @@
287   openfunc(...) {                                 287   openfunc(...) {
288     <...                                          288     <...
289     nonseekable_open@p1                           289     nonseekable_open@p1
290     ...>                                          290     ...>
291   }                                               291   }
292                                                   292 
293 @ script:python depends on report @               293 @ script:python depends on report @
294 fops << fops0.fops;                               294 fops << fops0.fops;
295 p << report_r.p1;                                 295 p << report_r.p1;
296 @@                                                296 @@
297 coccilib.report.print_report(p[0],                297 coccilib.report.print_report(p[0],
298   "WARNING: %s: .read() has stream semantic; s    298   "WARNING: %s: .read() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,))
299                                                   299 
300 @ explain_r depends on explain @                  300 @ explain_r depends on explain @
301 identifier fops_r.openfunc;                       301 identifier fops_r.openfunc;
302 @@                                                302 @@
303   openfunc(...) {                                 303   openfunc(...) {
304     <...                                          304     <...
305 -   nonseekable_open                              305 -   nonseekable_open
306 +   nonseekable_open /* read only */              306 +   nonseekable_open /* read only */
307     ...>                                          307     ...>
308   }                                               308   }
309                                                   309 
310 @ patch_r depends on patch @                      310 @ patch_r depends on patch @
311 identifier fops_r.openfunc;                       311 identifier fops_r.openfunc;
312 @@                                                312 @@
313   openfunc(...) {                                 313   openfunc(...) {
314     <...                                          314     <...
315 -   nonseekable_open                              315 -   nonseekable_open
316 +   stream_open                                   316 +   stream_open
317     ...>                                          317     ...>
318   }                                               318   }
319                                                   319 
320                                                   320 
321 // write, but not read                            321 // write, but not read
322 @ fops_w depends on maybe_stream && !has_read     322 @ fops_w depends on maybe_stream && !has_read @
323 identifier fops0.fops, openfunc;                  323 identifier fops0.fops, openfunc;
324 identifier stream_writer.writestream;             324 identifier stream_writer.writestream;
325 @@                                                325 @@
326   struct file_operations fops = {                 326   struct file_operations fops = {
327       .open  = openfunc,                          327       .open  = openfunc,
328       .write = writestream,                       328       .write = writestream,
329   };                                              329   };
330                                                   330 
331 @ report_w depends on report @                    331 @ report_w depends on report @
332 identifier fops_w.openfunc;                       332 identifier fops_w.openfunc;
333 position p1;                                      333 position p1;
334 @@                                                334 @@
335   openfunc(...) {                                 335   openfunc(...) {
336     <...                                          336     <...
337     nonseekable_open@p1                           337     nonseekable_open@p1
338     ...>                                          338     ...>
339   }                                               339   }
340                                                   340 
341 @ script:python depends on report @               341 @ script:python depends on report @
342 fops << fops0.fops;                               342 fops << fops0.fops;
343 p << report_w.p1;                                 343 p << report_w.p1;
344 @@                                                344 @@
345 coccilib.report.print_report(p[0],                345 coccilib.report.print_report(p[0],
346   "WARNING: %s: .write() has stream semantic;     346   "WARNING: %s: .write() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,))
347                                                   347 
348 @ explain_w depends on explain @                  348 @ explain_w depends on explain @
349 identifier fops_w.openfunc;                       349 identifier fops_w.openfunc;
350 @@                                                350 @@
351   openfunc(...) {                                 351   openfunc(...) {
352     <...                                          352     <...
353 -   nonseekable_open                              353 -   nonseekable_open
354 +   nonseekable_open /* write only */             354 +   nonseekable_open /* write only */
355     ...>                                          355     ...>
356   }                                               356   }
357                                                   357 
358 @ patch_w depends on patch @                      358 @ patch_w depends on patch @
359 identifier fops_w.openfunc;                       359 identifier fops_w.openfunc;
360 @@                                                360 @@
361   openfunc(...) {                                 361   openfunc(...) {
362     <...                                          362     <...
363 -   nonseekable_open                              363 -   nonseekable_open
364 +   stream_open                                   364 +   stream_open
365     ...>                                          365     ...>
366   }                                               366   }
367                                                   367 
368                                                   368 
369 // no read, no write - don't change anything      369 // no read, no write - don't change anything
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php