Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'docs-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/docs/linux

Pull documentation updates from Jonathan Corbet:
"A busier cycle than I had expected for docs, including:

- Translations: some overdue updates to the Japanese translations,
Chinese translations for some of the Rust documentation, and the
beginnings of a Portuguese translation.

- New documents covering CPU isolation, managed interrupts, debugging
Python gbb scripts, and more.

- More tooling work from Mauro, reducing docs-build warnings, adding
self tests, improving man-page output, bringing in a proper C
tokenizer to replace (some of) the mess of kernel-doc regexes, and
more.

- Update and synchronize changes.rst and scripts/ver_linux, and put
both into alphabetical order.

... and a long list of documentation updates, typo fixes, and general
improvements"

* tag 'docs-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/docs/linux: (162 commits)
Documentation: core-api: real-time: correct spelling
doc: Add CPU Isolation documentation
Documentation: Add managed interrupts
Documentation: seq_file: drop 2.6 reference
docs/zh_CN: update rust/index.rst translation
docs/zh_CN: update rust/quick-start.rst translation
docs/zh_CN: update rust/coding-guidelines.rst translation
docs/zh_CN: update rust/arch-support.rst translation
docs/zh_CN: sync process/2.Process.rst with English version
docs/zh_CN: fix an inconsistent statement in dev-tools/testing-overview
tracing: Documentation: Update histogram-design.rst for fn() handling
docs: sysctl: Add documentation for /proc/sys/xen/
Docs: hid: intel-ish-hid: make long URL usable
Documentation/kernel-parameters: fix architecture alignment for pt, nopt, and nobypass
sched/doc: Update yield_task description in sched-design-CFS
Documentation/rtla: Convert links to RST format
docs: fix typos and duplicated words across documentation
docs: fix typo in zoran driver documentation
docs: add an Assisted-by mention to submitting-patches.rst
Revert "scripts/checkpatch: add Assisted-by: tag validation"
...

+11346 -1047
+1 -1
Documentation/admin-guide/bcache.rst
··· 618 618 One of either lru, fifo or random. 619 619 620 620 freelist_percent 621 - Size of the freelist as a percentage of nbuckets. Can be written to to 621 + Size of the freelist as a percentage of nbuckets. Can be written to 622 622 increase the number of buckets kept on the freelist, which lets you 623 623 artificially reduce the size of the cache at runtime. Mostly for testing 624 624 purposes (i.e. testing how different size caches affect your hit rate).
+357
Documentation/admin-guide/cpu-isolation.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ============= 4 + CPU Isolation 5 + ============= 6 + 7 + Introduction 8 + ============ 9 + 10 + "CPU Isolation" means leaving a CPU exclusive to a given workload 11 + without any undesired code interference from the kernel. 12 + 13 + Those interferences, commonly pointed out as "noise", can be triggered 14 + by asynchronous events (interrupts, timers, scheduler preemption by 15 + workqueues and kthreads, ...) or synchronous events (syscalls and page 16 + faults). 17 + 18 + Such noise usually goes unnoticed. After all, synchronous events are a 19 + component of the requested kernel service. And asynchronous events are 20 + either sufficiently well-distributed by the scheduler when executed 21 + as tasks or reasonably fast when executed as interrupt. The timer 22 + interrupt can even execute 1024 times per seconds without a significant 23 + and measurable impact most of the time. 24 + 25 + However some rare and extreme workloads can be quite sensitive to 26 + those kinds of noise. This is the case, for example, with high 27 + bandwidth network processing that can't afford losing a single packet 28 + or very low latency network processing. Typically those use cases 29 + involve DPDK, bypassing the kernel networking stack and performing 30 + direct access to the networking device from userspace. 31 + 32 + In order to run a CPU without or with limited kernel noise, the 33 + related housekeeping work needs to be either shut down, migrated or 34 + offloaded. 35 + 36 + Housekeeping 37 + ============ 38 + 39 + In the CPU isolation terminology, housekeeping is the work, often 40 + asynchronous, that the kernel needs to process in order to maintain 41 + all its services. It matches the noises and disturbances enumerated 42 + above except when at least one CPU is isolated. Then housekeeping may 43 + make use of further coping mechanisms if CPU-tied work must be 44 + offloaded. 45 + 46 + Housekeeping CPUs are the non-isolated CPUs where the kernel noise 47 + is moved away from isolated CPUs. 48 + 49 + The isolation can be implemented in several ways depending on the 50 + nature of the noise: 51 + 52 + - Unbound work, where "unbound" means not tied to any CPU, can be 53 + simply migrated away from isolated CPUs to housekeeping CPUs. 54 + This is the case of unbound workqueues, kthreads and timers. 55 + 56 + - Bound work, where "bound" means tied to a specific CPU, usually 57 + can't be moved away as-is by nature. Either: 58 + 59 + - The work must switch to a locked implementation. E.g.: 60 + This is the case of RCU with CONFIG_RCU_NOCB_CPU. 61 + 62 + - The related feature must be shut down and considered 63 + incompatible with isolated CPUs. E.g.: Lockup watchdog, 64 + unreliable clocksources, etc... 65 + 66 + - An elaborate and heavyweight coping mechanism stands as a 67 + replacement. E.g.: the timer tick is shut down on nohz_full 68 + CPUs but with the constraint of running a single task on 69 + them. A significant cost penalty is added on kernel entry/exit 70 + and a residual 1Hz scheduler tick is offloaded to housekeeping 71 + CPUs. 72 + 73 + In any case, housekeeping work has to be handled, which is why there 74 + must be at least one housekeeping CPU in the system, preferably more 75 + if the machine runs a lot of CPUs. For example one per node on NUMA 76 + systems. 77 + 78 + Also CPU isolation often means a tradeoff between noise-free isolated 79 + CPUs and added overhead on housekeeping CPUs, sometimes even on 80 + isolated CPUs entering the kernel. 81 + 82 + Isolation features 83 + ================== 84 + 85 + Different levels of isolation can be configured in the kernel, each of 86 + which has its own drawbacks and tradeoffs. 87 + 88 + Scheduler domain isolation 89 + -------------------------- 90 + 91 + This feature isolates a CPU from the scheduler topology. As a result, 92 + the target isn't part of the load balancing. Tasks won't migrate 93 + either from or to it unless affined explicitly. 94 + 95 + As a side effect the CPU is also isolated from unbound workqueues and 96 + unbound kthreads. 97 + 98 + Requirements 99 + ~~~~~~~~~~~~ 100 + 101 + - CONFIG_CPUSETS=y for the cpusets-based interface 102 + 103 + Tradeoffs 104 + ~~~~~~~~~ 105 + 106 + By nature, the system load is overall less distributed since some CPUs 107 + are extracted from the global load balancing. 108 + 109 + Interfaces 110 + ~~~~~~~~~~ 111 + 112 + - Documentation/admin-guide/cgroup-v2.rst cpuset isolated partitions are recommended 113 + because they are tunable at runtime. 114 + 115 + - The 'isolcpus=' kernel boot parameter with the 'domain' flag is a 116 + less flexible alternative that doesn't allow for runtime 117 + reconfiguration. 118 + 119 + IRQs isolation 120 + -------------- 121 + 122 + Isolate the IRQs whenever possible, so that they don't fire on the 123 + target CPUs. 124 + 125 + Interfaces 126 + ~~~~~~~~~~ 127 + 128 + - The file /proc/irq/\*/smp_affinity as explained in detail in 129 + Documentation/core-api/irq/irq-affinity.rst page. 130 + 131 + - The "irqaffinity=" kernel boot parameter for a default setting. 132 + 133 + - The "managed_irq" flag in the "isolcpus=" kernel boot parameter 134 + tries a best effort affinity override for managed IRQs. 135 + 136 + Full Dynticks (aka nohz_full) 137 + ----------------------------- 138 + 139 + Full dynticks extends the dynticks idle mode, which stops the tick when 140 + the CPU is idle, to CPUs running a single task in userspace. That is, 141 + the timer tick is stopped if the environment allows it. 142 + 143 + Global timer callbacks are also isolated from the nohz_full CPUs. 144 + 145 + Requirements 146 + ~~~~~~~~~~~~ 147 + 148 + - CONFIG_NO_HZ_FULL=y 149 + 150 + Constraints 151 + ~~~~~~~~~~~ 152 + 153 + - The isolated CPUs must run a single task only. Multitask requires 154 + the tick to maintain preemption. This is usually fine since the 155 + workload usually can't stand the latency of random context switches. 156 + 157 + - No call to the kernel from isolated CPUs, at the risk of triggering 158 + random noise. 159 + 160 + - No use of POSIX CPU timers on isolated CPUs. 161 + 162 + - Architecture must have a stable and reliable clocksource (no 163 + unreliable TSC that requires the watchdog). 164 + 165 + 166 + Tradeoffs 167 + ~~~~~~~~~ 168 + 169 + In terms of cost, this is the most invasive isolation feature. It is 170 + assumed to be used when the workload spends most of its time in 171 + userspace and doesn't rely on the kernel except for preparatory 172 + work because: 173 + 174 + - RCU adds more overhead due to the locked, offloaded and threaded 175 + callbacks processing (the same that would be obtained with "rcu_nocbs" 176 + boot parameter). 177 + 178 + - Kernel entry/exit through syscalls, exceptions and IRQs are more 179 + costly due to fully ordered RmW operations that maintain userspace 180 + as RCU extended quiescent state. Also the CPU time is accounted on 181 + kernel boundaries instead of periodically from the tick. 182 + 183 + - Housekeeping CPUs must run a 1Hz residual remote scheduler tick 184 + on behalf of the isolated CPUs. 185 + 186 + Checklist 187 + ========= 188 + 189 + You have set up each of the above isolation features but you still 190 + observe jitters that trash your workload? Make sure to check a few 191 + elements before proceeding. 192 + 193 + Some of these checklist items are similar to those of real-time 194 + workloads: 195 + 196 + - Use mlock() to prevent your pages from being swapped away. Page 197 + faults are usually not compatible with jitter sensitive workloads. 198 + 199 + - Avoid SMT to prevent your hardware thread from being "preempted" 200 + by another one. 201 + 202 + - CPU frequency changes may induce subtle sorts of jitter in a 203 + workload. Cpufreq should be used and tuned with caution. 204 + 205 + - Deep C-states may result in latency issues upon wake-up. If this 206 + happens to be a problem, C-states can be limited via kernel boot 207 + parameters such as processor.max_cstate or intel_idle.max_cstate. 208 + More finegrained tunings are described in 209 + Documentation/admin-guide/pm/cpuidle.rst page 210 + 211 + - Your system may be subject to firmware-originating interrupts - x86 has 212 + System Management Interrupts (SMIs) for example. Check your system BIOS 213 + to disable such interference, and with some luck your vendor will have 214 + a BIOS tuning guidance for low-latency operations. 215 + 216 + 217 + Full isolation example 218 + ====================== 219 + 220 + In this example, the system has 8 CPUs and the 8th is to be fully 221 + isolated. Since CPUs start from 0, the 8th CPU is CPU 7. 222 + 223 + Kernel parameters 224 + ----------------- 225 + 226 + Set the following kernel boot parameters to disable SMT and setup tick 227 + and IRQ isolation: 228 + 229 + - Full dynticks: nohz_full=7 230 + 231 + - IRQs isolation: irqaffinity=0-6 232 + 233 + - Managed IRQs isolation: isolcpus=managed_irq,7 234 + 235 + - Prevent SMT: nosmt 236 + 237 + The full command line is then: 238 + 239 + nohz_full=7 irqaffinity=0-6 isolcpus=managed_irq,7 nosmt 240 + 241 + CPUSET configuration (cgroup v2) 242 + -------------------------------- 243 + 244 + Assuming cgroup v2 is mounted to /sys/fs/cgroup, the following script 245 + isolates CPU 7 from scheduler domains. 246 + 247 + :: 248 + 249 + cd /sys/fs/cgroup 250 + # Activate the cpuset subsystem 251 + echo +cpuset > cgroup.subtree_control 252 + # Create partition to be isolated 253 + mkdir test 254 + cd test 255 + echo +cpuset > cgroup.subtree_control 256 + # Isolate CPU 7 257 + echo 7 > cpuset.cpus 258 + echo "isolated" > cpuset.cpus.partition 259 + 260 + The userspace workload 261 + ---------------------- 262 + 263 + Fake a pure userspace workload, the program below runs a dummy 264 + userspace loop on the isolated CPU 7. 265 + 266 + :: 267 + 268 + #include <stdio.h> 269 + #include <fcntl.h> 270 + #include <unistd.h> 271 + #include <errno.h> 272 + int main(void) 273 + { 274 + // Move the current task to the isolated cpuset (bind to CPU 7) 275 + int fd = open("/sys/fs/cgroup/test/cgroup.procs", O_WRONLY); 276 + if (fd < 0) { 277 + perror("Can't open cpuset file...\n"); 278 + return 0; 279 + } 280 + 281 + write(fd, "0\n", 2); 282 + close(fd); 283 + 284 + // Run an endless dummy loop until the launcher kills us 285 + while (1) 286 + ; 287 + 288 + return 0; 289 + } 290 + 291 + Build it and save for later step: 292 + 293 + :: 294 + 295 + # gcc user_loop.c -o user_loop 296 + 297 + The launcher 298 + ------------ 299 + 300 + The below launcher runs the above program for 10 seconds and traces 301 + the noise resulting from preempting tasks and IRQs. 302 + 303 + :: 304 + 305 + TRACING=/sys/kernel/tracing/ 306 + # Make sure tracing is off for now 307 + echo 0 > $TRACING/tracing_on 308 + # Flush previous traces 309 + echo > $TRACING/trace 310 + # Record disturbance from other tasks 311 + echo 1 > $TRACING/events/sched/sched_switch/enable 312 + # Record disturbance from interrupts 313 + echo 1 > $TRACING/events/irq_vectors/enable 314 + # Now we can start tracing 315 + echo 1 > $TRACING/tracing_on 316 + # Run the dummy user_loop for 10 seconds on CPU 7 317 + ./user_loop & 318 + USER_LOOP_PID=$! 319 + sleep 10 320 + kill $USER_LOOP_PID 321 + # Disable tracing and save traces from CPU 7 in a file 322 + echo 0 > $TRACING/tracing_on 323 + cat $TRACING/per_cpu/cpu7/trace > trace.7 324 + 325 + If no specific problem arose, the output of trace.7 should look like 326 + the following: 327 + 328 + :: 329 + 330 + <idle>-0 [007] d..2. 1980.976624: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=user_loop next_pid=1553 next_prio=120 331 + user_loop-1553 [007] d.h.. 1990.946593: reschedule_entry: vector=253 332 + user_loop-1553 [007] d.h.. 1990.946593: reschedule_exit: vector=253 333 + 334 + That is, no specific noise triggered between the first trace and the 335 + second during 10 seconds when user_loop was running. 336 + 337 + Debugging 338 + ========= 339 + 340 + Of course things are never so easy, especially on this matter. 341 + Chances are that actual noise will be observed in the aforementioned 342 + trace.7 file. 343 + 344 + The best way to investigate further is to enable finer grained 345 + tracepoints such as those of subsystems producing asynchronous 346 + events: workqueue, timer, irq_vector, etc... It also can be 347 + interesting to enable the tick_stop event to diagnose why the tick is 348 + retained when that happens. 349 + 350 + Some tools may also be useful for higher level analysis: 351 + 352 + - Documentation/tools/rtla/rtla.rst provides a suite of tools to analyze 353 + latency and noise in the system. For example Documentation/tools/rtla/rtla-osnoise.rst 354 + runs a kernel tracer that analyzes and output a summary of the noises. 355 + 356 + - dynticks-testing does something similar to rtla-osnoise but in userspace. It is available 357 + at git://git.kernel.org/pub/scm/linux/kernel/git/frederic/dynticks-testing.git
+1
Documentation/admin-guide/index.rst
··· 94 94 95 95 cgroup-v2 96 96 cgroup-v1/index 97 + cpu-isolation 97 98 cpu-load 98 99 mm/index 99 100 module-signing
+2 -6
Documentation/admin-guide/kernel-parameters.txt
··· 2630 2630 Intel machines). This can be used to prevent the usage 2631 2631 of an available hardware IOMMU. 2632 2632 2633 - [X86] 2634 2633 pt 2635 - [X86] 2636 2634 nopt 2637 - [PPC/POWERNV] 2638 - nobypass 2635 + nobypass [PPC/POWERNV] 2639 2636 Disable IOMMU bypass, using IOMMU for PCI devices. 2640 2637 2641 - [X86] 2642 2638 AMD Gart HW IOMMU-specific options: 2643 2639 2644 2640 <size> ··· 6757 6761 Default is 'on'. 6758 6762 6759 6763 initramfs_options= [KNL] 6760 - Specify mount options for for the initramfs mount. 6764 + Specify mount options for the initramfs mount. 6761 6765 6762 6766 rootfstype= [KNL] Set root filesystem type 6763 6767
+1 -1
Documentation/admin-guide/pm/intel-speed-select.rst
··· 287 287 Check presence of other Intel(R) SST features 288 288 --------------------------------------------- 289 289 290 - Each of the performance profiles also specifies weather there is support of 290 + Each of the performance profiles also specifies whether there is support of 291 291 other two Intel(R) SST features (Intel(R) Speed Select Technology - Base Frequency 292 292 (Intel(R) SST-BF) and Intel(R) Speed Select Technology - Turbo Frequency (Intel 293 293 SST-TF)).
+8 -6
Documentation/admin-guide/quickly-build-trimmed-linux.rst
··· 349 349 350 350 .. _submit_improvements_qbtl: 351 351 352 - Did you run into trouble following any of the above steps that is not cleared up 353 - by the reference section below? Or do you have ideas how to improve the text? 354 - Then please take a moment of your time and let the maintainer of this document 355 - know by email (Thorsten Leemhuis <linux@leemhuis.info>), ideally while CCing the 356 - Linux docs mailing list (linux-doc@vger.kernel.org). Such feedback is vital to 357 - improve this document further, which is in everybody's interest, as it will 352 + Did you run into trouble following the step-by-step guide not cleared up by the 353 + reference section below? Did you spot errors? Or do you have ideas on how to 354 + improve the guide? 355 + 356 + If any of that applies, please let the developers know by sending a short note 357 + or a patch to Thorsten Leemhuis <linux@leemhuis.info> while ideally CCing the 358 + public Linux docs mailing list <linux-doc@vger.kernel.org>. Such feedback is 359 + vital to improve this text further, which is in everybody's interest, as it will 358 360 enable more people to master the task described here. 359 361 360 362 Reference section for the step-by-step guide
+94 -88
Documentation/admin-guide/reporting-issues.rst
··· 48 48 can. That includes keeping the ball rolling by occasionally retesting with newer 49 49 releases and sending a status update afterwards. 50 50 51 + .. 52 + Note: If you see this note, you are reading the text's source file. You 53 + might want to switch to a rendered version: It makes it a lot easier to 54 + read and navigate this document -- especially when you want to look something 55 + up in the reference section, then jump back to where you left off. 56 + .. 57 + Find the latest rendered version of this text here: 58 + https://docs.kernel.org/admin-guide/reporting-issues.html 59 + 60 + 51 61 Step-by-step guide how to report issues to the kernel maintainers 52 62 ================================================================= 53 63 ··· 241 231 The reference section below explains each of these steps in more detail. 242 232 243 233 234 + Conclusion of the step-by-step guide 235 + ------------------------------------ 236 + 237 + Did you run into trouble following the step-by-step guide not cleared up by the 238 + reference section below? Did you spot errors? Or do you have ideas on how to 239 + improve the guide? 240 + 241 + If any of that applies, please let the developers know by sending a short note 242 + or a patch to Thorsten Leemhuis <linux@leemhuis.info> while ideally CCing the 243 + public Linux docs mailing list <linux-doc@vger.kernel.org>. Such feedback is 244 + vital to improve this text further, which is in everybody's interest, as it will 245 + enable more people to master the task described here. 246 + 247 + 244 248 Reference section: Reporting issues to the kernel maintainers 245 249 ============================================================= 246 250 247 - The detailed guides above outline all the major steps in brief fashion, which 248 - should be enough for most people. But sometimes there are situations where even 249 - experienced users might wonder how to actually do one of those steps. That's 250 - what this section is for, as it will provide a lot more details on each of the 251 - above steps. Consider this as reference documentation: it's possible to read it 252 - from top to bottom. But it's mainly meant to skim over and a place to look up 253 - details how to actually perform those steps. 251 + The step-by-step guide above outlines all the major steps in brief fashion, 252 + which usually covers everything required. But even experienced users will 253 + sometimes wonder how to actually realize some of those steps or why they are 254 + needed; there are also corner cases the guide ignores for readability. That is 255 + what the entries in this reference section are for, which provide additional 256 + information for each of the steps in the guide. 254 257 255 - A few words of general advice before digging into the details: 258 + A few words of general advice: 256 259 257 - * The Linux kernel developers are well aware this process is complicated and 258 - demands more than other FLOSS projects. We'd love to make it simpler. But 259 - that would require work in various places as well as some infrastructure, 260 - which would need constant maintenance; nobody has stepped up to do that 261 - work, so that's just how things are for now. 260 + * The Linux developers are well aware that reporting bugs to them is more 261 + complicated and demanding than in other FLOSS projects. Some of it is because 262 + the kernel is different, among others due to its mail-driven development 263 + process and because it consists mostly of drivers. Some of it is because 264 + improving things would require work in several technical areas and people 265 + triaging bugs –– and nobody has stepped up to do or fund that work. 262 266 263 - * A warranty or support contract with some vendor doesn't entitle you to 264 - request fixes from developers in the upstream Linux kernel community: such 265 - contracts are completely outside the scope of the Linux kernel, its 266 - development community, and this document. That's why you can't demand 267 - anything such a contract guarantees in this context, not even if the 268 - developer handling the issue works for the vendor in question. If you want 269 - to claim your rights, use the vendor's support channel instead. When doing 270 - so, you might want to mention you'd like to see the issue fixed in the 271 - upstream Linux kernel; motivate them by saying it's the only way to ensure 272 - the fix in the end will get incorporated in all Linux distributions. 267 + * A warranty or support contract with some vendor doesn't entitle you to 268 + request fixes from the upstream Linux developers: Such contracts are 269 + completely outside the scope of the upstream Linux kernel, its development 270 + community, and this document -- even if those handling the issue work for the 271 + vendor who issued the contract. If you want to claim your rights, use the 272 + vendor's support channel. 273 273 274 - * If you never reported an issue to a FLOSS project before you should consider 275 - reading `How to Report Bugs Effectively 276 - <https://www.chiark.greenend.org.uk/~sgtatham/bugs.html>`_, `How To Ask 277 - Questions The Smart Way 278 - <http://www.catb.org/esr/faqs/smart-questions.html>`_, and `How to ask good 279 - questions <https://jvns.ca/blog/good-questions/>`_. 274 + * If you never reported an issue to a FLOSS project before, consider skimming 275 + guides like `How to ask good questions 276 + <https://jvns.ca/blog/good-questions/>`_, `How To Ask Questions The Smart Way 277 + <http://www.catb.org/esr/faqs/smart-questions.html>`_, and `How to Report 278 + Bugs Effectively <https://www.chiark.greenend.org.uk/~sgtatham/bugs.html>`_,. 280 279 281 - With that off the table, find below the details on how to properly report 282 - issues to the Linux kernel developers. 280 + With that off the table, find below details for the steps from the detailed 281 + guide on reporting issues to the Linux kernel developers. 283 282 284 283 285 284 Make sure you're using the upstream Linux kernel ··· 1693 1674 for the subsystem as well as the stable mailing list (stable@vger.kernel.org). 1694 1675 1695 1676 1696 - Why some issues won't get any reaction or remain unfixed after being reported 1697 - ============================================================================= 1677 + Appendix: Why it is somewhat hard to report kernel bugs 1678 + ======================================================= 1698 1679 1699 - When reporting a problem to the Linux developers, be aware only 'issues of high 1700 - priority' (regressions, security issues, severe problems) are definitely going 1701 - to get resolved. The maintainers or if all else fails Linus Torvalds himself 1702 - will make sure of that. They and the other kernel developers will fix a lot of 1703 - other issues as well. But be aware that sometimes they can't or won't help; and 1704 - sometimes there isn't even anyone to send a report to. 1680 + The Linux kernel developers are well aware that reporting bugs to them is harder 1681 + than in other Free/Libre Open Source Projects. Many reasons for that lie in the 1682 + nature of kernels, Linux' development model, and how the world uses the kernel: 1705 1683 1706 - This is best explained with kernel developers that contribute to the Linux 1707 - kernel in their spare time. Quite a few of the drivers in the kernel were 1708 - written by such programmers, often because they simply wanted to make their 1709 - hardware usable on their favorite operating system. 1684 + * *Most kernels of Linux distributions are totally unsuitable for reporting bugs 1685 + upstream.* The reference section above already explained this in detail: 1686 + outdated codebases as well as modifications and add-ons lead to kernel bugs 1687 + that were fixed upstream a long time ago or never happened there in the first 1688 + place. Developers of other Open Source software face these problems as well, 1689 + but the situation is a lot worse when it comes to the kernel, as the changes 1690 + and their impact are much more severe -- which is why many kernel developers 1691 + expect reports with kernels built from fresh and nearly unmodified sources. 1710 1692 1711 - These programmers most of the time will happily fix problems other people 1712 - report. But nobody can force them to do, as they are contributing voluntarily. 1693 + * *Bugs often only occur in a special environment.* That is because Linux is 1694 + mostly drivers and can be used in a multitude of ways. Developers often do not 1695 + have a matching setup at hand -- and therefore frequently must rely on bug 1696 + reporters for isolating a problems's cause and testing proposed fixes. 1713 1697 1714 - Then there are situations where such developers really want to fix an issue, 1715 - but can't: sometimes they lack hardware programming documentation to do so. 1716 - This often happens when the publicly available docs are superficial or the 1717 - driver was written with the help of reverse engineering. 1698 + * *The kernel has hundreds of maintainers, but all-rounders are very rare.* That 1699 + again is and effect caused by the multitude of features and drivers, due to 1700 + which many kernel developers know little about lower or higher layers related 1701 + to their code and even less about other areas. 1718 1702 1719 - Sooner or later spare time developers will also stop caring for the driver. 1720 - Maybe their test hardware broke, got replaced by something more fancy, or is so 1721 - old that it's something you don't find much outside of computer museums 1722 - anymore. Sometimes developer stops caring for their code and Linux at all, as 1723 - something different in their life became way more important. In some cases 1724 - nobody is willing to take over the job as maintainer – and nobody can be forced 1725 - to, as contributing to the Linux kernel is done on a voluntary basis. Abandoned 1726 - drivers nevertheless remain in the kernel: they are still useful for people and 1727 - removing would be a regression. 1703 + * *It is hard finding where to report issues to, among others, due to the lack 1704 + of a central bug tracker.* This is something even some kernel developers 1705 + dislike, but that's the situation everyone has to deal with currently. 1728 1706 1729 - The situation is not that different with developers that are paid for their 1730 - work on the Linux kernel. Those contribute most changes these days. But their 1731 - employers sooner or later also stop caring for their code or make its 1732 - programmer focus on other things. Hardware vendors for example earn their money 1733 - mainly by selling new hardware; quite a few of them hence are not investing 1734 - much time and energy in maintaining a Linux kernel driver for something they 1735 - stopped selling years ago. Enterprise Linux distributors often care for a 1736 - longer time period, but in new versions often leave support for old and rare 1737 - hardware aside to limit the scope. Often spare time contributors take over once 1738 - a company orphans some code, but as mentioned above: sooner or later they will 1739 - leave the code behind, too. 1707 + * *Stable and longterm kernels are primarily maintained by a dedicated 'stable 1708 + team', which only handles regressions introduced within stable and longterm 1709 + series.* When someone reports a bug, say, using Linux 6.1.2, the team will, 1710 + therefore, always ask if mainline is affected: if the bug already happened 1711 + in 6.1 or occurs with latest mainline (say, 6.2-rc3), they in everybody's 1712 + interest shove it to the regular developers, as those know the code best. 1740 1713 1741 - Priorities are another reason why some issues are not fixed, as maintainers 1742 - quite often are forced to set those, as time to work on Linux is limited. 1743 - That's true for spare time or the time employers grant their developers to 1744 - spend on maintenance work on the upstream kernel. Sometimes maintainers also 1745 - get overwhelmed with reports, even if a driver is working nearly perfectly. To 1746 - not get completely stuck, the programmer thus might have no other choice than 1747 - to prioritize issue reports and reject some of them. 1714 + * *Linux developers are free to focus on latest mainline.* Some, thus, react 1715 + coldly to reports about bugs in, say, Linux 6.0 when 6.1 is already out; 1716 + even the latter might not be enough once 6.2-rc1 is out. Some will also not 1717 + be very welcoming to reports with 6.1.5 or 6.1.6, as the problem might be a 1718 + series-specific regression the stable team (see above) caused and must fix. 1748 1719 1749 - But don't worry too much about all of this, a lot of drivers have active 1750 - maintainers who are quite interested in fixing as many issues as possible. 1720 + * *Sometimes there is nobody to help.* Sometimes this is due to the lack of 1721 + hardware documentation -- for example, when a driver was built using reverse 1722 + engineering or was taken over by spare-time developers when the hardware 1723 + manufacturer left it behind. Other times there is nobody to even report bugs 1724 + to: when maintainers move on without a replacement, their code often remains 1725 + in the kernel as long as it's useful. 1751 1726 1752 - 1753 - Closing words 1754 - ============= 1755 - 1756 - Compared with other Free/Libre & Open Source Software it's hard to report 1757 - issues to the Linux kernel developers: the length and complexity of this 1758 - document and the implications between the lines illustrate that. But that's how 1759 - it is for now. The main author of this text hopes documenting the state of the 1760 - art will lay some groundwork to improve the situation over time. 1761 - 1727 + Some of these aspects could be improved to facilitate bug reporting -- many 1728 + Linux kernel developers are well aware of this and would be glad if a few 1729 + individuals or an entity would make this their mission. 1762 1730 1763 1731 .. 1764 1732 end-of-content
+47
Documentation/admin-guide/sysctl/crypto.rst
··· 1 + ================= 2 + /proc/sys/crypto/ 3 + ================= 4 + 5 + These files show up in ``/proc/sys/crypto/``, depending on the 6 + kernel configuration: 7 + 8 + .. contents:: :local: 9 + 10 + fips_enabled 11 + ============ 12 + 13 + Read-only flag that indicates whether FIPS mode is enabled. 14 + 15 + - ``0``: FIPS mode is disabled (default). 16 + - ``1``: FIPS mode is enabled. 17 + 18 + This value is set at boot time via the ``fips=1`` kernel command line 19 + parameter. When enabled, the cryptographic API will restrict the use 20 + of certain algorithms and perform self-tests to ensure compliance with 21 + FIPS (Federal Information Processing Standards) requirements, such as 22 + FIPS 140-2 and the newer FIPS 140-3, depending on the kernel 23 + configuration and the module in use. 24 + 25 + fips_name 26 + ========= 27 + 28 + Read-only file that contains the name of the FIPS module currently in use. 29 + The value is typically configured via the ``CONFIG_CRYPTO_FIPS_NAME`` 30 + kernel configuration option. 31 + 32 + fips_version 33 + ============ 34 + 35 + Read-only file that contains the version string of the FIPS module. 36 + If ``CONFIG_CRYPTO_FIPS_CUSTOM_VERSION`` is set, it uses the value from 37 + ``CONFIG_CRYPTO_FIPS_VERSION``. Otherwise, it defaults to the kernel 38 + release version (``UTS_RELEASE``). 39 + 40 + Copyright (c) 2026, Shubham Chakraborty <chakrabortyshubham66@gmail.com> 41 + 42 + For general info and legal blurb, please look in 43 + Documentation/admin-guide/sysctl/index.rst. 44 + 45 + .. See scripts/check-sysctl-docs to keep this up to date: 46 + .. scripts/check-sysctl-docs -vtable="crypto" \ 47 + .. $(git grep -l register_sysctl_)
+52
Documentation/admin-guide/sysctl/debug.rst
··· 1 + ================ 2 + /proc/sys/debug/ 3 + ================ 4 + 5 + These files show up in ``/proc/sys/debug/``, depending on the 6 + kernel configuration: 7 + 8 + .. contents:: :local: 9 + 10 + exception-trace 11 + =============== 12 + 13 + This flag controls whether the kernel prints information about unhandled 14 + signals (like segmentation faults) to the kernel log (``dmesg``). 15 + 16 + - ``0``: Unhandled signals are not traced. 17 + - ``1``: Information about unhandled signals is printed. 18 + 19 + The default value is ``1`` on most architectures (like x86, MIPS, RISC-V), 20 + but it is ``0`` on **arm64**. 21 + 22 + The actual information printed and the context provided varies 23 + significantly depending on the CPU architecture. For example: 24 + 25 + - On **x86**, it typically prints the instruction pointer (IP), error 26 + code, and address that caused a page fault. 27 + - On **PowerPC**, it may print the next instruction pointer (NIP), 28 + link register (LR), and other relevant registers. 29 + 30 + When enabled, this feature is often rate-limited to prevent the kernel 31 + log from being flooded during a crash loop. 32 + 33 + kprobes-optimization 34 + ==================== 35 + 36 + This flag enables or disables the optimization of Kprobes on certain 37 + architectures (like x86). 38 + 39 + - ``0``: Kprobes optimization is turned off. 40 + - ``1``: Kprobes optimization is turned on (default). 41 + 42 + For more details on Kprobes and its optimization, please refer to 43 + Documentation/trace/kprobes.rst. 44 + 45 + Copyright (c) 2026, Shubham Chakraborty <chakrabortyshubham66@gmail.com> 46 + 47 + For general info and legal blurb, please look in 48 + Documentation/admin-guide/sysctl/index.rst. 49 + 50 + .. See scripts/check-sysctl-docs to keep this up to date: 51 + .. scripts/check-sysctl-docs -vtable="debug" \ 52 + .. $(git grep -l register_sysctl_)
+6 -3
Documentation/admin-guide/sysctl/index.rst
··· 67 67 =============== =============================================================== 68 68 abi/ execution domains & personalities 69 69 <$ARCH> tuning controls for various CPU architecture (e.g. csky, s390) 70 - crypto/ <undocumented> 71 - debug/ <undocumented> 70 + crypto/ cryptographic subsystem 71 + debug/ debugging features 72 72 dev/ device specific information (e.g. dev/cdrom/info) 73 73 fs/ specific filesystems 74 74 filehandle, inode, dentry and quota tuning ··· 84 84 user/ Per user namespace limits 85 85 vm/ memory management tuning 86 86 buffer and cache management 87 - xen/ <undocumented> 87 + xen/ Xen hypervisor controls 88 88 =============== =============================================================== 89 89 90 90 These are the subdirs I have on my system or have been discovered by ··· 96 96 :maxdepth: 1 97 97 98 98 abi 99 + crypto 100 + debug 99 101 fs 100 102 kernel 101 103 net 102 104 sunrpc 103 105 user 104 106 vm 107 + xen
+31
Documentation/admin-guide/sysctl/xen.rst
··· 1 + =============== 2 + /proc/sys/xen/ 3 + =============== 4 + 5 + Copyright (c) 2026, Shubham Chakraborty <chakrabortyshubham66@gmail.com> 6 + 7 + For general info and legal blurb, please look in 8 + Documentation/admin-guide/sysctl/index.rst. 9 + 10 + ------------------------------------------------------------------------------ 11 + 12 + These files show up in ``/proc/sys/xen/``, depending on the 13 + kernel configuration: 14 + 15 + .. contents:: :local: 16 + 17 + balloon/hotplug_unpopulated 18 + =========================== 19 + 20 + This flag controls whether unpopulated memory ranges are automatically 21 + hotplugged as system RAM. 22 + 23 + - ``0``: Unpopulated ranges are not hotplugged (default). 24 + - ``1``: Unpopulated ranges are automatically hotplugged. 25 + 26 + When enabled, the Xen balloon driver will add memory regions that are 27 + marked as unpopulated in the Xen memory map to the system as usable RAM. 28 + This allows for dynamic memory expansion in Xen guest domains. 29 + 30 + This option is only available when the kernel is built with 31 + ``CONFIG_XEN_BALLOON_MEMORY_HOTPLUG`` enabled.
+1 -1
Documentation/admin-guide/tainted-kernels.rst
··· 74 74 script, but if you need something quick you can use this shell command to check 75 75 which bits are set:: 76 76 77 - $ for i in $(seq 18); do echo $(($i-1)) $(($(cat /proc/sys/kernel/tainted)>>($i-1)&1));done 77 + $ for i in $(seq 20); do echo $(($i-1)) $(($(cat /proc/sys/kernel/tainted)>>($i-1)&1));done 78 78 79 79 Table for decoding tainted state 80 80 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+7 -8
Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst
··· 1062 1062 1063 1063 You have reached the end of the step-by-step guide. 1064 1064 1065 - Did you run into trouble following any of the above steps not cleared up by the 1066 - reference section below? Did you spot errors? Or do you have ideas how to 1065 + Did you run into trouble following the step-by-step guide not cleared up by the 1066 + reference section below? Did you spot errors? Or do you have ideas on how to 1067 1067 improve the guide? 1068 1068 1069 - If any of that applies, please take a moment and let the maintainer of this 1070 - document know by email (Thorsten Leemhuis <linux@leemhuis.info>), ideally while 1071 - CCing the Linux docs mailing list (linux-doc@vger.kernel.org). Such feedback is 1072 - vital to improve this text further, which is in everybody's interest, as it 1073 - will enable more people to master the task described here -- and hopefully also 1074 - improve similar guides inspired by this one. 1069 + If any of that applies, please let the developers know by sending a short note 1070 + or a patch to Thorsten Leemhuis <linux@leemhuis.info> while ideally CCing the 1071 + public Linux docs mailing list <linux-doc@vger.kernel.org>. Such feedback is 1072 + vital to improve this text further, which is in everybody's interest, as it will 1073 + enable more people to master the task described here. 1075 1074 1076 1075 1077 1076 Reference section for the step-by-step guide
+1
Documentation/conf.py
··· 455 455 # The name of an image file (relative to this directory) to place at the top 456 456 # of the sidebar. 457 457 html_logo = "images/logo.svg" 458 + html_favicon = "images/logo.svg" 458 459 459 460 # Output file base name for HTML help builder. 460 461 htmlhelp_basename = "TheLinuxKerneldoc"
+1 -1
Documentation/core-api/housekeeping.rst
··· 15 15 Sometimes housekeeping is just some unbound work (unbound workqueues, 16 16 unbound timers, ...) that gets easily assigned to non-isolated CPUs. 17 17 But sometimes housekeeping is tied to a specific CPU and requires 18 - elaborated tricks to be offloaded to non-isolated CPUs (RCU_NOCB, remote 18 + elaborate tricks to be offloaded to non-isolated CPUs (RCU_NOCB, remote 19 19 scheduler tick, etc...). 20 20 21 21 Thus, a housekeeping CPU can be considered as the reverse of an isolated
+1
Documentation/core-api/irq/index.rst
··· 9 9 irq-affinity 10 10 irq-domain 11 11 irqflags-tracing 12 + managed_irq
+116
Documentation/core-api/irq/managed_irq.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + =========================== 4 + Affinity managed interrupts 5 + =========================== 6 + 7 + The IRQ core provides support for managing interrupts according to a specified 8 + CPU affinity. Under normal operation, an interrupt is associated with a 9 + particular CPU. If that CPU is taken offline, the interrupt is migrated to 10 + another online CPU. 11 + 12 + Devices with large numbers of interrupt vectors can stress the available vector 13 + space. For example, an NVMe device with 128 I/O queues typically requests one 14 + interrupt per queue on systems with at least 128 CPUs. Two such devices 15 + therefore request 256 interrupts. On x86, the interrupt vector space is 16 + notoriously low, providing only 256 vectors per CPU, and the kernel reserves a 17 + subset of these, further reducing the number available for device interrupts. 18 + In practice this is not an issue because the interrupts are distributed across 19 + many CPUs, so each CPU only receives a small number of vectors. 20 + 21 + During system suspend, however, all secondary CPUs are taken offline and all 22 + interrupts are migrated to the single CPU that remains online. This can exhaust 23 + the available interrupt vectors on that CPU and cause the suspend operation to 24 + fail. 25 + 26 + Affinity‑managed interrupts address this limitation. Each interrupt is assigned 27 + a CPU affinity mask that specifies the set of CPUs on which the interrupt may 28 + be targeted. When a CPU in the mask goes offline, the interrupt is moved to the 29 + next CPU in the mask. If the last CPU in the mask goes offline, the interrupt 30 + is shut down. Drivers using affinity‑managed interrupts must ensure that the 31 + associated queue is quiesced before the interrupt is disabled so that no 32 + further interrupts are generated. When a CPU in the affinity mask comes back 33 + online, the interrupt is re‑enabled. 34 + 35 + Implementation 36 + -------------- 37 + 38 + Devices must provide per‑instance interrupts, such as per‑I/O‑queue interrupts 39 + for storage devices like NVMe. The driver allocates interrupt vectors with the 40 + required affinity settings using struct irq_affinity. For MSI‑X devices, this 41 + is done via pci_alloc_irq_vectors_affinity() with the PCI_IRQ_AFFINITY flag 42 + set. 43 + 44 + Based on the provided affinity information, the IRQ core attempts to spread the 45 + interrupts evenly across the system. The affinity masks are computed during 46 + this allocation step, but the final IRQ assignment is performed when 47 + request_irq() is invoked. 48 + 49 + Isolated CPUs 50 + ------------- 51 + 52 + The affinity of managed interrupts is handled entirely in the kernel and cannot 53 + be modified from user space through the /proc interfaces. The managed_irq 54 + sub‑parameter of the isolcpus boot option specifies a CPU mask that managed 55 + interrupts should attempt to avoid. This isolation is best‑effort and only 56 + applies if the automatically assigned interrupt mask also contains online CPUs 57 + outside the avoided mask. If the requested mask contains only isolated CPUs, 58 + the setting has no effect. 59 + 60 + CPUs listed in the avoided mask remain part of the interrupt’s affinity mask. 61 + This means that if all non‑isolated CPUs go offline while isolated CPUs remain 62 + online, the interrupt will be assigned to one of the isolated CPUs. 63 + 64 + The following examples assume a system with 8 CPUs. 65 + 66 + - A QEMU instance is booted with "-device virtio-scsi-pci". 67 + The MSI‑X device exposes 11 interrupts: 3 "management" interrupts and 8 68 + "queue" interrupts. The driver requests the 8 queue interrupts, each of which 69 + is affine to exactly one CPU. If that CPU goes offline, the interrupt is shut 70 + down. 71 + 72 + Assuming interrupt 48 is one of the queue interrupts, the following appears:: 73 + 74 + /proc/irq/48/effective_affinity_list:7 75 + /proc/irq/48/smp_affinity_list:7 76 + 77 + This indicates that the interrupt is served only by CPU7. Shutting down CPU7 78 + does not migrate the interrupt to another CPU:: 79 + 80 + /proc/irq/48/effective_affinity_list:0 81 + /proc/irq/48/smp_affinity_list:7 82 + 83 + This can be verified via the debugfs interface 84 + (/sys/kernel/debug/irq/irqs/48). The dstate field will include 85 + IRQD_IRQ_DISABLED, IRQD_IRQ_MASKED and IRQD_MANAGED_SHUTDOWN. 86 + 87 + - A QEMU instance is booted with "-device virtio-scsi-pci,num_queues=2" 88 + and the kernel command line includes: 89 + "irqaffinity=0,1 isolcpus=domain,2-7 isolcpus=managed_irq,1-3,5-7". 90 + The MSI‑X device exposes 5 interrupts: 3 management interrupts and 2 queue 91 + interrupts. The management interrupts follow the irqaffinity= setting. The 92 + queue interrupts are spread across available CPUs:: 93 + 94 + /proc/irq/47/effective_affinity_list:0 95 + /proc/irq/47/smp_affinity_list:0-3 96 + /proc/irq/48/effective_affinity_list:4 97 + /proc/irq/48/smp_affinity_list:4-7 98 + 99 + The two queue interrupts are evenly distributed. Interrupt 48 is placed on CPU4 100 + because the managed_irq mask avoids CPUs 5–7 when possible. 101 + 102 + Replacing the managed_irq argument with "isolcpus=managed_irq,1-3,4-5,7" 103 + results in:: 104 + 105 + /proc/irq/48/effective_affinity_list:6 106 + /proc/irq/48/smp_affinity_list:4-7 107 + 108 + Interrupt 48 is now served on CPU6 because the system avoids CPUs 4, 5 and 109 + 7. If CPU6 is taken offline, the interrupt migrates to one of the "isolated" 110 + CPUs:: 111 + 112 + /proc/irq/48/effective_affinity_list:7 113 + /proc/irq/48/smp_affinity_list:4-7 114 + 115 + The interrupt is shut down once all CPUs listed in its smp_affinity mask are 116 + offline.
+1 -1
Documentation/core-api/memory-hotplug.rst
··· 96 96 Generated if NODE_ADDING_FIRST_MEMORY fails. 97 97 98 98 NODE_ADDED_FIRST_MEMORY 99 - Generated when memory has become available fo this node for the first time. 99 + Generated when memory has become available for this node for the first time. 100 100 101 101 NODE_REMOVING_LAST_MEMORY 102 102 Generated when the last memory available to this node is about to be offlined.
+36
Documentation/core-api/printk-basics.rst
··· 103 103 pr_debug() and pr_devel(), which are compiled-out unless ``DEBUG`` (or 104 104 also ``CONFIG_DYNAMIC_DEBUG`` in the case of pr_debug()) is defined. 105 105 106 + Avoiding lockups from excessive printk() use 107 + ============================================ 108 + 109 + .. note:: 110 + 111 + This section is relevant only for legacy console drivers (those not 112 + using the nbcon API) and !PREEMPT_RT kernels. Once all console drivers 113 + are updated to nbcon, this documentation can be removed. 114 + 115 + Using ``printk()`` in hot paths (such as interrupt handlers, timer 116 + callbacks, or high-frequency network receive routines) with legacy 117 + consoles (e.g., ``console=ttyS0``) may cause lockups. Legacy consoles 118 + synchronously acquire ``console_sem`` and block while flushing messages, 119 + potentially disabling interrupts long enough to trigger hard or soft 120 + lockup detectors. 121 + 122 + To avoid this: 123 + 124 + - Use rate-limited variants (e.g., ``pr_*_ratelimited()``) or one-time 125 + macros (e.g., ``pr_*_once()``) to reduce message frequency. 126 + - Assign lower log levels (e.g., ``KERN_DEBUG``) to non-essential messages 127 + and filter console output via ``console_loglevel``. 128 + - Use ``printk_deferred()`` to log messages immediately to the ringbuffer 129 + and defer console printing. This is a workaround for legacy consoles. 130 + - Port legacy console drivers to the non-blocking ``nbcon`` API (indicated 131 + by ``CON_NBCON``). This is the preferred solution, as nbcon consoles 132 + offload message printing to a dedicated kernel thread. 133 + 134 + For temporary debugging, ``trace_printk()`` can be used, but it must not 135 + appear in mainline code. See ``Documentation/trace/debugging.rst`` for 136 + more information. 137 + 138 + If more permanent output is needed in a hot path, trace events can be used. 139 + See ``Documentation/trace/events.rst`` and 140 + ``samples/trace_events/trace-events-sample.[ch]``. 141 + 106 142 107 143 Function reference 108 144 ==================
+1 -1
Documentation/core-api/real-time/architecture-porting.rst
··· 74 74 Enabling interrupts is especially important on PREEMPT_RT, where certain 75 75 locks, such as spinlock_t, become sleepable. For example, handling an 76 76 invalid opcode may result in sending a SIGILL signal to the user task. A 77 - debug excpetion will send a SIGTRAP signal. 77 + debug exception will send a SIGTRAP signal. 78 78 In both cases, if the exception occurred in user space, it is safe to enable 79 79 interrupts early. Sending a signal requires both interrupts and kernel 80 80 preemption to be enabled.
+1 -1
Documentation/core-api/real-time/differences.rst
··· 213 213 risking livelock. 214 214 215 215 In order to solve the problem at the API level, the sequence locks were extended 216 - to allow a proper handover between the the spinning reader and the maybe 216 + to allow a proper handover between the spinning reader and the maybe 217 217 blocked writer. 218 218 219 219 Sequence locks
+3 -2
Documentation/dev-tools/coccinelle.rst
··· 29 29 - Ubuntu 30 30 - OpenSUSE 31 31 - Arch Linux 32 + - Gentoo 32 33 - NetBSD 33 34 - FreeBSD 34 35 35 36 Some distribution packages are obsolete and it is recommended 36 37 to use the latest version released from the Coccinelle homepage at 37 - http://coccinelle.lip6.fr/ 38 + https://coccinelle.gitlabpages.inria.fr/website 38 39 39 40 Or from Github at: 40 41 ··· 61 60 62 61 For supplemental documentation refer to the wiki: 63 62 64 - https://bottest.wiki.kernel.org/coccicheck 63 + https://bottest.wiki.kernel.org/coccicheck.html 65 64 66 65 The wiki documentation always refers to the linux-next version of the script. 67 66
+6
Documentation/doc-guide/kernel-doc.rst
··· 213 213 ``/*`` comment marker. They may optionally include comments between the 214 214 ``:`` and the ending ``*/`` marker. 215 215 216 + When ``private:`` is used on nested structs, it propagates only to inner 217 + structs/unions. 218 + 219 + 216 220 Example:: 217 221 218 222 /** ··· 260 256 union { 261 257 struct { 262 258 int memb1; 259 + /* private: hides memb2 from documentation */ 263 260 int memb2; 264 261 }; 262 + /* Everything here is public again, as private scope finished */ 265 263 struct { 266 264 void *memb3; 267 265 int memb4;
+1 -1
Documentation/driver-api/acpi/acpi-drivers.rst
··· 47 47 Moreover, a device ID is necessary to bind a driver directly to an ACPI device 48 48 node, but device IDs are not generally associated with all of them. Some of 49 49 them contain alternative information allowing the corresponding pieces of 50 - hardware to be identified, for example represeted by an _ADR object return 50 + hardware to be identified, for example represented by an _ADR object return 51 51 value, and device IDs are not used in those cases. In consequence, confusingly 52 52 enough, binding an ACPI driver to an ACPI device node may even be impossible. 53 53
+1 -1
Documentation/driver-api/cxl/platform/acpi/cedt.rst
··· 55 55 Bit[1]: CXL Type 3 Memory 56 56 Bit[2]: Volatile Memory 57 57 Bit[3]: Persistent Memory 58 - Bit[4]: Fixed Config (HPA cannot be re-used) 58 + Bit[4]: Fixed Config (HPA cannot be reused) 59 59 60 60 INTRA-host-bridge interleave (multiple devices on one host bridge) is NOT 61 61 reported in this structure, and is solely defined via CXL device decoder
+1 -1
Documentation/driver-api/cxl/platform/bios-and-efi.rst
··· 277 277 the described memory region allows volatile or persistent memory (or both). If 278 278 the platform intends to support either: 279 279 280 - 1) A device with multiple medias, or 280 + 1) A device with multiple media, or 281 281 2) Using a persistent memory device as normal memory 282 282 283 283 A platform may wish to create multiple CEDT CFMWS entries to describe the same
+1 -1
Documentation/driver-api/dmaengine/pxa_dma.rst
··· 40 40 ====== 41 41 a) Virtual channels 42 42 Same concept as in sa11x0 driver, ie. a driver was assigned a "virtual 43 - channel" linked to the requestor line, and the physical DMA channel is 43 + channel" linked to the requester line, and the physical DMA channel is 44 44 assigned on the fly when the transfer is issued. 45 45 46 46 b) Transfer anatomy for a scatter-gather transfer
+1 -1
Documentation/driver-api/early-userspace/early_userspace_support.rst
··· 73 73 can really be interpreted as any legal argument to 74 74 gen_initramfs.sh. If a directory is specified as an argument then 75 75 the contents are scanned, uid/gid translation is performed, and 76 - usr/gen_init_cpio file directives are output. If a directory is 76 + usr/gen_init_cpio file directives are output. If a file is 77 77 specified as an argument to usr/gen_initramfs.sh then the 78 78 contents of the file are simply copied to the output. All of the output 79 79 directives from directory scanning and file contents copying are
+14 -2
Documentation/driver-api/interconnect.rst
··· 84 84 85 85 .. kernel-doc:: include/linux/interconnect-provider.h 86 86 87 + .. kernel-doc:: drivers/interconnect/core.c 88 + :functions: icc_provider_init icc_provider_register icc_provider_deregister 89 + icc_node_create icc_node_create_dyn icc_node_destroy 90 + icc_node_add icc_node_del icc_nodes_remove icc_node_set_name 91 + icc_link_create icc_link_nodes 92 + 87 93 Interconnect consumers 88 94 ---------------------- 89 95 90 96 Interconnect consumers are the clients which use the interconnect APIs to 91 97 get paths between endpoints and set their bandwidth/latency/QoS requirements 92 - for these interconnect paths. These interfaces are not currently 93 - documented. 98 + for these interconnect paths. 99 + 100 + .. kernel-doc:: drivers/interconnect/core.c 101 + :functions: devm_of_icc_get of_icc_get_by_index of_icc_get icc_get 102 + icc_put icc_enable icc_disable icc_set_bw icc_set_tag 103 + icc_get_name 104 + 105 + .. kernel-doc:: drivers/interconnect/bulk.c 94 106 95 107 Interconnect debugfs interfaces 96 108 -------------------------------
+1 -1
Documentation/driver-api/libata.rst
··· 286 286 implementation is to call :c:func:`ata_std_error_handler`. 287 287 288 288 :c:func:`ata_std_error_handler` will perform a standard error handling sequence 289 - to resurect failed devices, detach lost devices and add new devices (if any). 289 + to resurrect failed devices, detach lost devices and add new devices (if any). 290 290 This function will call the various reset operations for a port, as needed. 291 291 These operations are as follows. 292 292
+1 -1
Documentation/driver-api/media/drivers/zoran.rst
··· 222 222 Ireland, Nigeria, South Africa. 223 223 224 224 The CCIR - N uses the PAL colorsystem and PAL frame size but the NTSC framerate, 225 - and is used in Argentina, Uruguay, an a few others 225 + and is used in Argentina, Uruguay, and a few others 226 226 227 227 We do not talk about how the audio is broadcast ! 228 228
+1 -1
Documentation/driver-api/pci/p2pdma.rst
··· 38 38 At the lowest level the P2P subsystem offers a naked struct p2p_provider that 39 39 delegates lifecycle management to the providing driver. It is expected that 40 40 drivers using this option will wrap their MMIO memory in DMABUF and use DMABUF 41 - to provide an invalidation shutdown. These MMIO addresess have no struct page, and 41 + to provide an invalidation shutdown. These MMIO addresses have no struct page, and 42 42 if used with mmap() must create special PTEs. As such there are very few 43 43 kernel uAPIs that can accept pointers to them; in particular they cannot be used 44 44 with read()/write(), including O_DIRECT.
+1 -1
Documentation/features/perf/perf-regs/arch-support.txt
··· 18 18 | mips: | ok | 19 19 | nios2: | TODO | 20 20 | openrisc: | TODO | 21 - | parisc: | TODO | 21 + | parisc: | ok | 22 22 | powerpc: | ok | 23 23 | riscv: | ok | 24 24 | s390: | ok |
+1 -1
Documentation/features/perf/perf-stackdump/arch-support.txt
··· 18 18 | mips: | ok | 19 19 | nios2: | TODO | 20 20 | openrisc: | TODO | 21 - | parisc: | TODO | 21 + | parisc: | ok | 22 22 | powerpc: | ok | 23 23 | riscv: | ok | 24 24 | s390: | ok |
+1 -1
Documentation/filesystems/path-lookup.rst
··· 1364 1364 symlinks. Some system calls set or clear it implicitly, while 1365 1365 others have API flags such as ``AT_SYMLINK_FOLLOW`` and 1366 1366 ``UMOUNT_NOFOLLOW`` to control it. Its effect is similar to 1367 - ``WALK_GET`` that we already met, but it is used in a different way. 1367 + ``WALK_TRAILING`` that we already met, but it is used in a different way. 1368 1368 1369 1369 ``LOOKUP_DIRECTORY`` insists that the final component is a directory. 1370 1370 Various callers set this and it is also set when the final component
+32 -20
Documentation/filesystems/proc.rst
··· 464 464 KSM: 0 kB 465 465 LazyFree: 0 kB 466 466 AnonHugePages: 0 kB 467 + FilePmdMapped: 0 kB 467 468 ShmemPmdMapped: 0 kB 468 469 Shared_Hugetlb: 0 kB 469 470 Private_Hugetlb: 0 kB 470 471 Swap: 0 kB 471 472 SwapPss: 0 kB 472 - KernelPageSize: 4 kB 473 - MMUPageSize: 4 kB 474 473 Locked: 0 kB 475 474 THPeligible: 0 476 475 VmFlags: rd ex mr mw me dw 477 476 478 477 The first of these lines shows the same information as is displayed for 479 478 the mapping in /proc/PID/maps. Following lines show the size of the 480 - mapping (size); the size of each page allocated when backing a VMA 481 - (KernelPageSize), which is usually the same as the size in the page table 482 - entries; the page size used by the MMU when backing a VMA (in most cases, 483 - the same as KernelPageSize); the amount of the mapping that is currently 484 - resident in RAM (RSS); the process's proportional share of this mapping 485 - (PSS); and the number of clean and dirty shared and private pages in the 486 - mapping. 479 + mapping (size); the smallest possible page size allocated when backing a 480 + VMA (KernelPageSize), which is the granularity in which VMA modifications 481 + can be performed; the smallest possible page size that could be used by the 482 + MMU (MMUPageSize) when backing a VMA; the amount of the mapping that is 483 + currently resident in RAM (RSS); the process's proportional share of this 484 + mapping (PSS); and the number of clean and dirty shared and private pages 485 + in the mapping. 486 + 487 + "KernelPageSize" always corresponds to "MMUPageSize", except when a larger 488 + kernel page size is emulated on a system with a smaller page size used by the 489 + MMU, which is the case for some PPC64 setups with hugetlb. Furthermore, 490 + "KernelPageSize" and "MMUPageSize" always correspond to the smallest 491 + possible granularity (fallback) that can be encountered in a VMA throughout 492 + its lifetime. These values are not affected by Transparent Huge Pages 493 + being in effect, or any usage of larger MMU page sizes (either through 494 + architectural huge-page mappings or other explicit/implicit coalescing of 495 + virtual ranges performed by the MMU). "AnonHugePages", "ShmemPmdMapped" and 496 + "FilePmdMapped" provide insight into the usage of PMD-level architectural 497 + huge-page mappings. 487 498 488 499 The "proportional set size" (PSS) of a process is the count of pages it has 489 500 in memory, where each page is divided by the number of processes sharing it. ··· 539 528 be lower than the real value due to optimizations used in the current 540 529 implementation. If this is not desirable please file a bug report. 541 530 542 - "AnonHugePages" shows the amount of memory backed by transparent hugepage. 531 + "AnonHugePages", "ShmemPmdMapped" and "FilePmdMapped" show the amount of 532 + memory backed by Transparent Huge Pages that are currently mapped by 533 + architectural huge-page mappings at the PMD level. "AnonHugePages" 534 + corresponds to memory that does not belong to a file, "ShmemPmdMapped" to 535 + shared memory (shmem/tmpfs) and "FilePmdMapped" to file-backed memory 536 + (excluding shmem/tmpfs). 543 537 544 - "ShmemPmdMapped" shows the amount of shared (shmem/tmpfs) memory backed by 545 - huge pages. 538 + There are no dedicated entries for Transparent Huge Pages (or similar concepts) 539 + that are not mapped by architectural huge-page mappings at the PMD level. 546 540 547 541 "Shared_Hugetlb" and "Private_Hugetlb" show the amounts of memory backed by 548 542 hugetlbfs page which is *not* counted in "RSS" or "PSS" field for historical ··· 743 727 in the kernel image 744 728 cpuinfo Info about the CPU 745 729 devices Available devices (block and character) 746 - dma Used DMS channels 730 + dma Used DMA channels 747 731 filesystems Supported filesystems 748 732 driver Various drivers grouped here, currently rtc (2.4) 749 733 execdomains Execdomains, related to security (2.4) ··· 877 861 Of some interest is the introduction of the /proc/irq directory to 2.4. 878 862 It could be used to set IRQ to CPU affinity. This means that you can "hook" an 879 863 IRQ to only one CPU, or to exclude a CPU of handling IRQs. The contents of the 880 - irq subdir is one subdir for each IRQ, and two files; default_smp_affinity and 881 - prof_cpu_mask. 864 + irq subdir is one subdir for each IRQ, and default_smp_affinity. 882 865 883 866 For example:: 884 867 885 868 > ls /proc/irq/ 886 - 0 10 12 14 16 18 2 4 6 8 prof_cpu_mask 887 - 1 11 13 15 17 19 3 5 7 9 default_smp_affinity 869 + 0 10 12 14 16 18 2 4 6 8 default_smp_affinity 870 + 1 11 13 15 17 19 3 5 7 9 888 871 > ls /proc/irq/0/ 889 872 smp_affinity 890 873 ··· 913 898 The node file on an SMP system shows the node to which the device using the IRQ 914 899 reports itself as being attached. This hardware locality information does not 915 900 include information about any possible driver locality preference. 916 - 917 - prof_cpu_mask specifies which CPUs are to be profiled by the system wide 918 - profiler. Default value is ffffffff (all CPUs if there are only 32 of them). 919 901 920 902 The way IRQs are routed is handled by the IO-APIC, and it's Round Robin 921 903 between all the CPUs which are allowed to handle it. As usual the kernel has
+1 -1
Documentation/filesystems/seq_file.rst
··· 27 27 middle of a line of output. The kernel has traditionally had a number of 28 28 implementations that got this wrong. 29 29 30 - The 2.6 kernel contains a set of functions (implemented by Alexander Viro) 30 + The kernel now contains a set of functions (implemented by Alexander Viro) 31 31 which are designed to make it easy for virtual file creators to get it 32 32 right. 33 33
+2 -2
Documentation/hid/intel-ish-hid.rst
··· 163 163 - A flow control mechanism to avoid buffer overflows 164 164 165 165 This protocol resembles bus messages described in the following document: 166 - http://www.intel.com/content/dam/www/public/us/en/documents/technical-\ 167 - specifications/dcmi-hi-1-0-spec.pdf "Chapter 7: Bus Message Layer" 166 + http://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/dcmi-hi-1-0-spec.pdf 167 + "Chapter 7: Bus Message Layer". 168 168 169 169 Connection and Flow Control Mechanism 170 170 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1 -1
Documentation/mm/hwpoison.rst
··· 38 38 for the mapping from a vma to a process. Since this case is expected 39 39 to be rare we hope we can get away with this. 40 40 41 - The code consists of a the high level handler in mm/memory-failure.c, 41 + The code consists of the high level handler in mm/memory-failure.c, 42 42 a new page poison bit and various checks in the VM to handle poisoned 43 43 pages. 44 44
+1 -1
Documentation/mm/numa.rst
··· 140 140 141 141 If the architecture supports--does not hide--memoryless nodes, then CPUs 142 142 attached to memoryless nodes would always incur the fallback path overhead 143 - or some subsystems would fail to initialize if they attempted to allocated 143 + or some subsystems would fail to initialize if they attempted to allocate 144 144 memory exclusively from a node without memory. To support such 145 145 architectures transparently, kernel subsystems can use the numa_mem_id() 146 146 or cpu_to_mem() function to locate the "local memory node" for the calling or
+1 -1
Documentation/process/2.Process.rst
··· 291 291 there is a definite chance that it will not even compile. 292 292 293 293 The primary tree for next-cycle patch merging is linux-next, maintained by 294 - Stephen Rothwell. The linux-next tree is, by design, a snapshot of what 294 + Mark Brown. The linux-next tree is, by design, a snapshot of what 295 295 the mainline is expected to look like after the next merge window closes. 296 296 Linux-next trees are announced on the linux-kernel and linux-next mailing 297 297 lists when they are assembled; they can be downloaded from:
+1 -1
Documentation/process/backporting.rst
··· 432 432 statements. 433 433 434 434 Error handling is typically located at the bottom of the function, so it 435 - may not be part of the conflict even though could have been changed by 435 + may not be part of the conflict even though it could have been changed by 436 436 other patches. 437 437 438 438 A good way to ensure that you review the error paths is to always use
+33 -31
Documentation/process/changes.rst
··· 19 19 20 20 Upgrade to at **least** these software revisions before thinking you've 21 21 encountered a bug! If you're unsure what version you're currently 22 - running, the suggested command should tell you. 22 + running, the suggested command should tell you. For a list of the programs 23 + on your system including their version execute ./scripts/ver_linux 23 24 24 25 Again, keep in mind that this list assumes you are already functionally 25 26 running a Linux kernel. Also, not all tools are necessary on all 26 27 systems; obviously, if you don't have any PC Card hardware, for example, 27 - you probably needn't concern yourself with pcmciautils. 28 + you probably do not need to concern yourself with pcmciautils. 28 29 29 30 ====================== =============== ======================================== 30 31 Program Minimal version Command to check the version 31 32 ====================== =============== ======================================== 32 - GNU C 8.1 gcc --version 33 - Clang/LLVM (optional) 15.0.0 clang --version 34 - Rust (optional) 1.85.0 rustc --version 35 - bindgen (optional) 0.71.1 bindgen --version 36 - GNU make 4.0 make --version 37 33 bash 4.2 bash --version 38 - binutils 2.30 ld -v 39 - flex 2.5.35 flex --version 40 - bison 2.0 bison --version 41 - pahole 1.22 pahole --version 42 - util-linux 2.10o mount --version 43 - kmod 13 depmod -V 44 - e2fsprogs 1.41.4 e2fsck -V 45 - jfsutils 1.1.3 fsck.jfs -V 46 - xfsprogs 2.6.0 xfs_db -V 47 - squashfs-tools 4.0 mksquashfs -version 48 - btrfs-progs 0.18 btrfs --version 49 - pcmciautils 004 pccardctl -V 50 - quota-tools 3.09 quota -V 51 - PPP 2.4.0 pppd --version 52 - nfs-utils 1.0.5 showmount --version 53 - procps 3.2.0 ps --version 54 - udev 081 udevd --version 55 - grub 0.93 grub --version || grub-install --version 56 - mcelog 0.6 mcelog --version 57 - iptables 1.4.2 iptables -V 58 - openssl & libcrypto 1.0.0 openssl version 59 34 bc 1.06.95 bc --version 60 - Sphinx\ [#f1]_ 3.4.3 sphinx-build --version 35 + bindgen (optional) 0.71.1 bindgen --version 36 + binutils 2.30 ld -v 37 + bison 2.0 bison --version 38 + btrfs-progs 0.18 btrfs --version 39 + Clang/LLVM (optional) 15.0.0 clang --version 40 + e2fsprogs 1.41.4 e2fsck -V 41 + flex 2.5.35 flex --version 42 + gdb 7.2 gdb --version 43 + GNU awk (optional) 5.1.0 gawk --version 44 + GNU C 8.1 gcc --version 45 + GNU make 4.0 make --version 61 46 GNU tar 1.28 tar --version 47 + GRUB 0.93 grub --version || grub-install --version 62 48 gtags (optional) 6.6.5 gtags --version 49 + iptables 1.4.2 iptables -V 50 + jfsutils 1.1.3 fsck.jfs -V 51 + kmod 13 kmod -V 52 + mcelog 0.6 mcelog --version 63 53 mkimage (optional) 2017.01 mkimage --version 54 + nfs-utils 1.0.5 showmount --version 55 + openssl & libcrypto 1.0.0 openssl version 56 + pahole 1.22 pahole --version 57 + pcmciautils 004 pccardctl -V 58 + PPP 2.4.0 pppd --version 59 + procps 3.2.0 ps --version 64 60 Python 3.9.x python3 --version 65 - GNU AWK (optional) 5.1.0 gawk --version 61 + quota-tools 3.09 quota -V 62 + Rust (optional) 1.85.0 rustc --version 63 + Sphinx\ [#f1]_ 3.4.3 sphinx-build --version 64 + squashfs-tools 4.0 mksquashfs -version 65 + udev 081 udevadm --version 66 + util-linux 2.10o mount --version 67 + xfsprogs 2.6.0 xfs_db -V 66 68 ====================== =============== ======================================== 67 69 68 70 .. [#f1] Sphinx is needed only to build the Kernel documentation ··· 393 391 Sphinx 394 392 ------ 395 393 396 - Please see :ref:`sphinx_install` in :ref:`Documentation/doc-guide/sphinx.rst <sphinxdoc>` 394 + Please see :ref:`sphinx_install` in Documentation/doc-guide/sphinx.rst 397 395 for details about Sphinx requirements. 398 396 399 397 rustdoc
+9
Documentation/process/debugging/gdb-kernel-debugging.rst
··· 173 173 174 174 Detailed help can be obtained via "help <command-name>" for commands and "help 175 175 function <function-name>" for convenience functions. 176 + 177 + Debugging GDB scripts 178 + --------------------- 179 + 180 + GDB does not enable a full Python backtrace which can make debugging GDB 181 + scripts more difficult than necessary. The following will allow for printing a 182 + full backtrace of the python environment:: 183 + 184 + (gdb) set python print-stack full
+464 -233
Documentation/process/handling-regressions.rst
··· 461 461 Quotes from Linus about regression 462 462 ---------------------------------- 463 463 464 - Find below a few real life examples of how Linus Torvalds expects regressions to 465 - be handled: 464 + The following statements from Linus Torvalds provide some insight into Linux 465 + "no regressions" rule and how he expects regressions to be handled: 466 466 467 - * From `2017-10-26 (1/2) 468 - <https://lore.kernel.org/lkml/CA+55aFwiiQYJ+YoLKCXjN_beDVfu38mg=Ggg5LFOcqHE8Qi7Zw@mail.gmail.com/>`_:: 467 + On how quickly regressions should be fixed 468 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 469 469 470 - If you break existing user space setups THAT IS A REGRESSION. 470 + * From `2026-01-22 <https://lore.kernel.org/all/CAHk-=wheQNiW_WtHGO7bKkT7Uib-p+ai2JP9M+z+FYcZ6CAxYA@mail.gmail.com/>`_:: 471 471 472 - It's not ok to say "but we'll fix the user space setup". 472 + But a user complaining should basically result in an immediate fix - 473 + possibly a "revert and rethink". 473 474 474 - Really. NOT OK. 475 + With a later clarification on `2026-01-28 <https://lore.kernel.org/all/CAHk-%3Dwi86AosXs66-yi54%2BmpQjPu0upxB8ZAfG%2BLsMyJmcuMSA@mail.gmail.com/>`_:: 475 476 476 - [...] 477 + It's also worth noting that "immediate" obviously doesn't mean "right 478 + this *second* when the problem has been reported". 477 479 478 - The first rule is: 480 + But if it's a regression with a known commit that caused it, I think 481 + the rule of thumb should generally be "within a week", preferably 482 + before the next rc. 479 483 480 - - we don't cause regressions 484 + * From `2023-04-21 <https://lore.kernel.org/all/CAHk-=wgD98pmSK3ZyHk_d9kZ2bhgN6DuNZMAJaV0WTtbkf=RDw@mail.gmail.com/>`_:: 481 485 482 - and the corollary is that when regressions *do* occur, we admit to 483 - them and fix them, instead of blaming user space. 486 + Known-broken commits either 487 + (a) get a timely fix that doesn't have other questions 488 + or 489 + (b) get reverted 484 490 485 - The fact that you have apparently been denying the regression now for 486 - three weeks means that I will revert, and I will stop pulling apparmor 487 - requests until the people involved understand how kernel development 488 - is done. 489 - 490 - * From `2017-10-26 (2/2) 491 - <https://lore.kernel.org/lkml/CA+55aFxW7NMAMvYhkvz1UPbUTUJewRt6Yb51QAx5RtrWOwjebg@mail.gmail.com/>`_:: 491 + * From `2021-09-20(2) <https://lore.kernel.org/all/CAHk-=wgOvmtRw1TNbMC1rn5YqyTKyn0hz+sc4k0DGNn++u9aYw@mail.gmail.com/>`_:: 492 492 493 - People should basically always feel like they can update their kernel 494 - and simply not have to worry about it. 493 + [...] review shouldn't hold up reported regressions of existing code. That's 494 + just basic _testing_ - either the fix should be applied, or - if the fix is 495 + too invasive or too ugly - the problematic source of the regression should 496 + be reverted. 495 497 496 - I refuse to introduce "you can only update the kernel if you also 497 - update that other program" kind of limitations. If the kernel used to 498 - work for you, the rule is that it continues to work for you. 498 + Review should be about new code, it shouldn't be holding up "there's a 499 + bug report, here's the obvious fix". 499 500 500 - There have been exceptions, but they are few and far between, and they 501 - generally have some major and fundamental reasons for having happened, 502 - that were basically entirely unavoidable, and people _tried_hard_ to 503 - avoid them. Maybe we can't practically support the hardware any more 504 - after it is decades old and nobody uses it with modern kernels any 505 - more. Maybe there's a serious security issue with how we did things, 506 - and people actually depended on that fundamentally broken model. Maybe 507 - there was some fundamental other breakage that just _had_ to have a 508 - flag day for very core and fundamental reasons. 501 + * From `2023-05-08 <https://lore.kernel.org/all/CAHk-=wgzU8_dGn0Yg+DyX7ammTkDUCyEJ4C=NvnHRhxKWC7Wpw@mail.gmail.com/>`_:: 509 502 510 - And notice that this is very much about *breaking* peoples environments. 503 + If something doesn't even build, it should damn well be fixed ASAP. 511 504 512 - Behavioral changes happen, and maybe we don't even support some 513 - feature any more. There's a number of fields in /proc/<pid>/stat that 514 - are printed out as zeroes, simply because they don't even *exist* in 515 - the kernel any more, or because showing them was a mistake (typically 516 - an information leak). But the numbers got replaced by zeroes, so that 517 - the code that used to parse the fields still works. The user might not 518 - see everything they used to see, and so behavior is clearly different, 519 - but things still _work_, even if they might no longer show sensitive 520 - (or no longer relevant) information. 505 + On how fixing regressions with reverts can help prevent maintainer burnout 506 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 521 507 522 - But if something actually breaks, then the change must get fixed or 523 - reverted. And it gets fixed in the *kernel*. Not by saying "well, fix 524 - your user space then". It was a kernel change that exposed the 525 - problem, it needs to be the kernel that corrects for it, because we 526 - have a "upgrade in place" model. We don't have a "upgrade with new 527 - user space". 508 + * From `2026-01-28 <https://lore.kernel.org/all/CAHk-%3Dwi86AosXs66-yi54%2BmpQjPu0upxB8ZAfG%2BLsMyJmcuMSA@mail.gmail.com/>`_:: 528 509 529 - And I seriously will refuse to take code from people who do not 530 - understand and honor this very simple rule. 510 + > So how can I/we make "immediate fixes" happen more often without 511 + > contributing to maintainer burnout? 531 512 532 - This rule is also not going to change. 513 + [...] the "revert and rethink" model [...] often a good idea in general [...] 533 514 534 - And yes, I realize that the kernel is "special" in this respect. I'm 535 - proud of it. 515 + Exactly so that maintainers don't get stressed out over having a pending 516 + problem report that people keep pestering them about. 536 517 537 - I have seen, and can point to, lots of projects that go "We need to 538 - break that use case in order to make progress" or "you relied on 539 - undocumented behavior, it sucks to be you" or "there's a better way to 540 - do what you want to do, and you have to change to that new better 541 - way", and I simply don't think that's acceptable outside of very early 542 - alpha releases that have experimental users that know what they signed 543 - up for. The kernel hasn't been in that situation for the last two 544 - decades. 518 + I think people are sometimes a bit too bought into whatever changes 519 + they made, and reverting is seen as "too drastic", but I think it's 520 + often the quick and easy solution for when there isn't some obvious 521 + response to a regression report. 545 522 546 - We do API breakage _inside_ the kernel all the time. We will fix 547 - internal problems by saying "you now need to do XYZ", but then it's 548 - about internal kernel API's, and the people who do that then also 549 - obviously have to fix up all the in-kernel users of that API. Nobody 550 - can say "I now broke the API you used, and now _you_ need to fix it 551 - up". Whoever broke something gets to fix it too. 523 + On mainlining fixes when the last -rc or a new release is close 524 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 552 525 553 - And we simply do not break user space. 526 + * From `2026-02-01 <https://lore.kernel.org/all/CAHk-%3DwhXTw1oPsa%2BTLuY1Rc9D1OAiPVOdR_-R2xG45kwDObKdA@mail.gmail.com/>`_:: 554 527 555 - * From `2020-05-21 556 - <https://lore.kernel.org/all/CAHk-=wiVi7mSrsMP=fLXQrXK_UimybW=ziLOwSzFTtoXUacWVQ@mail.gmail.com/>`_:: 528 + So I think I'd rather see them hit rc8 (later today) and have a week 529 + of testing in my tree and be reverted if they cause problems, than 530 + have them go in after rc8 and then cause problems in the 6.19 release 531 + instead. 557 532 558 - The rules about regressions have never been about any kind of 559 - documented behavior, or where the code lives. 533 + * From `2023-04-20 <https://lore.kernel.org/all/CAHk-=wis_qQy4oDNynNKi5b7Qhosmxtoj1jxo5wmB6SRUwQUBQ@mail.gmail.com/>`_:: 560 534 561 - The rules about regressions are always about "breaks user workflow". 535 + But something like this, where the regression was in the previous release 536 + and it's just a clear fix with no semantic subtlety, I consider to be just a 537 + regular regression that should be expedited - partly to make it into stable, 538 + and partly to avoid having to put the fix into _another_ stable kernel. 562 539 563 - Users are literally the _only_ thing that matters. 540 + On sending merge requests with just one fix 541 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 564 542 565 - No amount of "you shouldn't have used this" or "that behavior was 566 - undefined, it's your own fault your app broke" or "that used to work 567 - simply because of a kernel bug" is at all relevant. 543 + * From `2024-04-24 <https://lore.kernel.org/all/CAHk-=wjy_ph9URuFt-pq+2AJ__p7gFDx=yzVSCsx16xAYvNw9g@mail.gmail.com/>`_:: 568 544 569 - Now, reality is never entirely black-and-white. So we've had things 570 - like "serious security issue" etc that just forces us to make changes 571 - that may break user space. But even then the rule is that we don't 572 - really have other options that would allow things to continue. 545 + If the issue is just that there's nothing else happening, I think people 546 + should just point me to the patch and say "can you apply this single fix?" 573 547 574 - And obviously, if users take years to even notice that something 575 - broke, or if we have sane ways to work around the breakage that 576 - doesn't make for too much trouble for users (ie "ok, there are a 577 - handful of users, and they can use a kernel command line to work 578 - around it" kind of things) we've also been a bit less strict. 548 + * From `2023-04-20 <https://lore.kernel.org/all/CAHk-=wis_qQy4oDNynNKi5b7Qhosmxtoj1jxo5wmB6SRUwQUBQ@mail.gmail.com/>`_:: 579 549 580 - But no, "that was documented to be broken" (whether it's because the 581 - code was in staging or because the man-page said something else) is 582 - irrelevant. If staging code is so useful that people end up using it, 583 - that means that it's basically regular kernel code with a flag saying 584 - "please clean this up". 550 + I'm always open to direct fixes when there is no controversy about the fix. 551 + No problem. I still happily deal with individual patches. 585 552 586 - The other side of the coin is that people who talk about "API 587 - stability" are entirely wrong. API's don't matter either. You can make 588 - any changes to an API you like - as long as nobody notices. 553 + On the importance of pointing to bug reports using Link:/Closes: tags 554 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 589 555 590 - Again, the regression rule is not about documentation, not about 591 - API's, and not about the phase of the moon. 556 + * From `2025-07-29(1) <https://lore.kernel.org/all/CAHk-=wj2kJRPWx8B09AAtzj+_g+T6UBX11TP0ebs1WJdTtv=WQ@mail.gmail.com/>`_:: 592 557 593 - It's entirely about "we caused problems for user space that used to work". 558 + [...] revert like this, it really would be good to link to the problems, so 559 + that when people try to re-enable it, they have the history for why it 560 + didn't work the first time. 594 561 595 - * From `2017-11-05 596 - <https://lore.kernel.org/all/CA+55aFzUvbGjD8nQ-+3oiMBx14c_6zOj2n7KLN3UsJ-qsd4Dcw@mail.gmail.com/>`_:: 562 + * From `2022-05-08 <https://lore.kernel.org/all/CAHk-=wjMmSZzMJ3Xnskdg4+GGz=5p5p+GSYyFBTh0f-DgvdBWg@mail.gmail.com/>`_:: 597 563 598 - And our regression rule has never been "behavior doesn't change". 599 - That would mean that we could never make any changes at all. 564 + So I have to once more complain [...] 600 565 601 - For example, we do things like add new error handling etc all the 602 - time, which we then sometimes even add tests for in our kselftest 603 - directory. 566 + [...] There's no link to the actual problem the patch fixes. 604 567 605 - So clearly behavior changes all the time and we don't consider that a 606 - regression per se. 568 + * From `2022-06-22 <https://lore.kernel.org/all/CAHk-=wjxzafG-=J8oT30s7upn4RhBs6TX-uVFZ5rME+L5_DoJA@mail.gmail.com/>`_:: 607 569 608 - The rule for a regression for the kernel is that some real user 609 - workflow breaks. Not some test. Not a "look, I used to be able to do 610 - X, now I can't". 570 + See, *that* link [to the report] would have been useful in the commit. 611 571 612 - * From `2018-08-03 613 - <https://lore.kernel.org/all/CA+55aFwWZX=CXmWDTkDGb36kf12XmTehmQjbiMPCqCRG2hi9kw@mail.gmail.com/>`_:: 572 + On why the "no regressions" rule exists 573 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 614 574 615 - YOU ARE MISSING THE #1 KERNEL RULE. 575 + * From `2026-01-22 <https://lore.kernel.org/all/CAHk-=wheQNiW_WtHGO7bKkT7Uib-p+ai2JP9M+z+FYcZ6CAxYA@mail.gmail.com/>`_:: 616 576 617 - We do not regress, and we do not regress exactly because your are 100% wrong. 577 + But the basic rule is: be so good about backwards compatibility that 578 + users never have to worry about upgrading. They should absolutely feel 579 + confident that any kernel-reported problem will either be solved, or 580 + have an easy solution that is appropriate for *them* (ie a 581 + non-technical user shouldn't be expected to be able to do a lot). 618 582 619 - And the reason you state for your opinion is in fact exactly *WHY* you 620 - are wrong. 583 + Because the last thing we want is people holding back from trying new 584 + kernels. 621 585 622 - Your "good reasons" are pure and utter garbage. 586 + * From `2024-05-28 <https://lore.kernel.org/all/CAHk-=wgtb7y-bEh7tPDvDWru7ZKQ8-KMjZ53Tsk37zsPPdwXbA@mail.gmail.com/>`_:: 623 587 624 - The whole point of "we do not regress" is so that people can upgrade 625 - the kernel and never have to worry about it. 588 + I introduced that "no regressions" rule something like two decades 589 + ago, because people need to be able to update their kernel without 590 + fear of something they relied on suddenly stopping to work. 626 591 627 - > Kernel had a bug which has been fixed 592 + * From `2018-08-03 <https://lore.kernel.org/all/CA+55aFwWZX=CXmWDTkDGb36kf12XmTehmQjbiMPCqCRG2hi9kw@mail.gmail.com/>`_:: 628 593 629 - That is *ENTIRELY* immaterial. 594 + The whole point of "we do not regress" is so that people can upgrade 595 + the kernel and never have to worry about it. 630 596 631 - Guys, whether something was buggy or not DOES NOT MATTER. 597 + [...] 632 598 633 - Why? 599 + Because the only thing that matters IS THE USER. 634 600 635 - Bugs happen. That's a fact of life. Arguing that "we had to break 636 - something because we were fixing a bug" is completely insane. We fix 637 - tens of bugs every single day, thinking that "fixing a bug" means that 638 - we can break something is simply NOT TRUE. 601 + * From `2017-10-26(1) <https://lore.kernel.org/lkml/CA+55aFxW7NMAMvYhkvz1UPbUTUJewRt6Yb51QAx5RtrWOwjebg@mail.gmail.com/>`_:: 639 602 640 - So bugs simply aren't even relevant to the discussion. They happen, 641 - they get found, they get fixed, and it has nothing to do with "we 642 - break users". 603 + If the kernel used to work for you, the rule is that it continues to work 604 + for you. 643 605 644 - Because the only thing that matters IS THE USER. 606 + [...] 645 607 646 - How hard is that to understand? 608 + People should basically always feel like they can update their kernel 609 + and simply not have to worry about it. 647 610 648 - Anybody who uses "but it was buggy" as an argument is entirely missing 649 - the point. As far as the USER was concerned, it wasn't buggy - it 650 - worked for him/her. 611 + I refuse to introduce "you can only update the kernel if you also 612 + update that other program" kind of limitations. If the kernel used to 613 + work for you, the rule is that it continues to work for you. 651 614 652 - Maybe it worked *because* the user had taken the bug into account, 653 - maybe it worked because the user didn't notice - again, it doesn't 654 - matter. It worked for the user. 615 + On exceptions to the "no regressions" rule 616 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 655 617 656 - Breaking a user workflow for a "bug" is absolutely the WORST reason 657 - for breakage you can imagine. 618 + * From `2026-01-22 <https://lore.kernel.org/all/CAHk-=wheQNiW_WtHGO7bKkT7Uib-p+ai2JP9M+z+FYcZ6CAxYA@mail.gmail.com/>`_:: 658 619 659 - It's basically saying "I took something that worked, and I broke it, 660 - but now it's better". Do you not see how f*cking insane that statement 661 - is? 620 + There are _very_ few exceptions to that rule, the main one being "the 621 + problem was a fundamental huge and gaping security issue and we *had* to 622 + make that change, and we couldn't even make your limited use-case just 623 + continue to work". 662 624 663 - And without users, your program is not a program, it's a pointless 664 - piece of code that you might as well throw away. 625 + The other exception is "the problem was reported years after it was 626 + introduced, and now most people rely on the new behavior". 665 627 666 - Seriously. This is *why* the #1 rule for kernel development is "we 667 - don't break users". Because "I fixed a bug" is absolutely NOT AN 668 - ARGUMENT if that bug fix broke a user setup. You actually introduced a 669 - MUCH BIGGER bug by "fixing" something that the user clearly didn't 670 - even care about. 628 + [...] 671 629 672 - And dammit, we upgrade the kernel ALL THE TIME without upgrading any 673 - other programs at all. It is absolutely required, because flag-days 674 - and dependencies are horribly bad. 630 + Now, if it's one or two users and you can just get them to recompile, 631 + that's one thing. Niche hardware and odd use-cases can sometimes be 632 + solved that way, and regressions can sometimes be fixed by handholding 633 + every single reporter if the reporter is willing and able to change 634 + his or her workflow. 675 635 676 - And it is also required simply because I as a kernel developer do not 677 - upgrade random other tools that I don't even care about as I develop 678 - the kernel, and I want any of my users to feel safe doing the same 679 - time. 636 + * From `2023-04-20 <https://lore.kernel.org/all/CAHk-=wis_qQy4oDNynNKi5b7Qhosmxtoj1jxo5wmB6SRUwQUBQ@mail.gmail.com/>`_:: 680 637 681 - So no. Your rule is COMPLETELY wrong. If you cannot upgrade a kernel 682 - without upgrading some other random binary, then we have a problem. 638 + And yes, I do consider "regression in an earlier release" to be a 639 + regression that needs fixing. 683 640 684 - * From `2021-06-05 685 - <https://lore.kernel.org/all/CAHk-=wiUVqHN76YUwhkjZzwTdjMMJf_zN4+u7vEJjmEGh3recw@mail.gmail.com/>`_:: 641 + There's obviously a time limit: if that "regression in an earlier 642 + release" was a year or more ago, and just took forever for people to 643 + notice, and it had semantic changes that now mean that fixing the 644 + regression could cause a _new_ regression, then that can cause me to 645 + go "Oh, now the new semantics are what we have to live with". 686 646 687 - THERE ARE NO VALID ARGUMENTS FOR REGRESSIONS. 647 + * From `2017-10-26(2) <https://lore.kernel.org/lkml/CA+55aFxW7NMAMvYhkvz1UPbUTUJewRt6Yb51QAx5RtrWOwjebg@mail.gmail.com/>`_:: 688 648 689 - Honestly, security people need to understand that "not working" is not 690 - a success case of security. It's a failure case. 649 + There have been exceptions, but they are few and far between, and they 650 + generally have some major and fundamental reasons for having happened, 651 + that were basically entirely unavoidable, and people _tried_hard_ to 652 + avoid them. Maybe we can't practically support the hardware any more 653 + after it is decades old and nobody uses it with modern kernels any 654 + more. Maybe there's a serious security issue with how we did things, 655 + and people actually depended on that fundamentally broken model. Maybe 656 + there was some fundamental other breakage that just _had_ to have a 657 + flag day for very core and fundamental reasons. 691 658 692 - Yes, "not working" may be secure. But security in that case is *pointless*. 659 + On situations where updating something in userspace can resolve regressions 660 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 693 661 694 - * From `2011-05-06 (1/3) 695 - <https://lore.kernel.org/all/BANLkTim9YvResB+PwRp7QTK-a5VNg2PvmQ@mail.gmail.com/>`_:: 662 + * From `2018-08-03 <https://lore.kernel.org/all/CA+55aFwWZX=CXmWDTkDGb36kf12XmTehmQjbiMPCqCRG2hi9kw@mail.gmail.com/>`_:: 696 663 697 - Binary compatibility is more important. 664 + And dammit, we upgrade the kernel ALL THE TIME without upgrading any 665 + other programs at all. It is absolutely required, because flag-days 666 + and dependencies are horribly bad. 698 667 699 - And if binaries don't use the interface to parse the format (or just 700 - parse it wrongly - see the fairly recent example of adding uuid's to 701 - /proc/self/mountinfo), then it's a regression. 668 + And it is also required simply because I as a kernel developer do not 669 + upgrade random other tools that I don't even care about as I develop the 670 + kernel, and I want any of my users to feel safe doing the same time. 702 671 703 - And regressions get reverted, unless there are security issues or 704 - similar that makes us go "Oh Gods, we really have to break things". 672 + * From `2017-10-26(3) <https://lore.kernel.org/lkml/CA+55aFxW7NMAMvYhkvz1UPbUTUJewRt6Yb51QAx5RtrWOwjebg@mail.gmail.com/>`_:: 705 673 706 - I don't understand why this simple logic is so hard for some kernel 707 - developers to understand. Reality matters. Your personal wishes matter 708 - NOT AT ALL. 674 + But if something actually breaks, then the change must get fixed or 675 + reverted. And it gets fixed in the *kernel*. Not by saying "well, fix your 676 + user space then". It was a kernel change that exposed the problem, it needs 677 + to be the kernel that corrects for it, because we have a "upgrade in place" 678 + model. We don't have a "upgrade with new user space". 709 679 710 - If you made an interface that can be used without parsing the 711 - interface description, then we're stuck with the interface. Theory 712 - simply doesn't matter. 680 + And I seriously will refuse to take code from people who do not understand 681 + and honor this very simple rule. 713 682 714 - You could help fix the tools, and try to avoid the compatibility 715 - issues that way. There aren't that many of them. 683 + This rule is also not going to change. 716 684 717 - From `2011-05-06 (2/3) 718 - <https://lore.kernel.org/all/BANLkTi=KVXjKR82sqsz4gwjr+E0vtqCmvA@mail.gmail.com/>`_:: 685 + And yes, I realize that the kernel is "special" in this respect. I'm proud 686 + of it. 719 687 720 - it's clearly NOT an internal tracepoint. By definition. It's being 721 - used by powertop. 688 + * From `2017-10-26(4) <https://lore.kernel.org/all/CA+55aFwiiQYJ+YoLKCXjN_beDVfu38mg=Ggg5LFOcqHE8Qi7Zw@mail.gmail.com/>`_:: 722 689 723 - From `2011-05-06 (3/3) 724 - <https://lore.kernel.org/all/BANLkTinazaXRdGovYL7rRVp+j6HbJ7pzhg@mail.gmail.com/>`_:: 690 + If you break existing user space setups THAT IS A REGRESSION. 725 691 726 - We have programs that use that ABI and thus it's a regression if they break. 692 + It's not ok to say "but we'll fix the user space setup". 727 693 728 - * From `2012-07-06 <https://lore.kernel.org/all/CA+55aFwnLJ+0sjx92EGREGTWOx84wwKaraSzpTNJwPVV8edw8g@mail.gmail.com/>`_:: 694 + Really. NOT OK. 729 695 730 - > Now this got me wondering if Debian _unstable_ actually qualifies as a 731 - > standard distro userspace. 696 + On what qualifies as userspace interface, ABI, API, documented interfaces, etc. 697 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 732 698 733 - Oh, if the kernel breaks some standard user space, that counts. Tons 734 - of people run Debian unstable 699 + * From `2026-01-20 <https://lore.kernel.org/all/CAHk-=wga8Qu0-OSE9VZbviq9GuqwhPhLUXeAt-S7_9+fMCLkKg@mail.gmail.com/>`_:: 735 700 736 - * From `2019-09-15 737 - <https://lore.kernel.org/lkml/CAHk-=wiP4K8DRJWsCo=20hn_6054xBamGKF2kPgUzpB5aMaofA@mail.gmail.com/>`_:: 701 + So I absolutely detest the whole notion of "ABI changes". It's a 702 + meaningless concept, and I hate it with a passion, [...] 738 703 739 - One _particularly_ last-minute revert is the top-most commit (ignoring 740 - the version change itself) done just before the release, and while 741 - it's very annoying, it's perhaps also instructive. 704 + The Linux rule for regressions is basically based on the philosophical 705 + question of "If a tree falls in the forest, and nobody is around to 706 + hear it, does it make a sound?". 742 707 743 - What's instructive about it is that I reverted a commit that wasn't 744 - actually buggy. In fact, it was doing exactly what it set out to do, 745 - and did it very well. In fact it did it _so_ well that the much 746 - improved IO patterns it caused then ended up revealing a user-visible 747 - regression due to a real bug in a completely unrelated area. 708 + So the only thing that matters is if something breaks user-*conscious* 709 + behavior. 748 710 749 - The actual details of that regression are not the reason I point that 750 - revert out as instructive, though. It's more that it's an instructive 751 - example of what counts as a regression, and what the whole "no 752 - regressions" kernel rule means. The reverted commit didn't change any 753 - API's, and it didn't introduce any new bugs. But it ended up exposing 754 - another problem, and as such caused a kernel upgrade to fail for a 755 - user. So it got reverted. 711 + And when that happens, the distinction between "bug fix" and "new 712 + feature" and "ABI change" matters not one whit, and the change needs 713 + to be done differently. 756 714 757 - The point here being that we revert based on user-reported _behavior_, 758 - not based on some "it changes the ABI" or "it caused a bug" concept. 759 - The problem was really pre-existing, and it just didn't happen to 760 - trigger before. The better IO patterns introduced by the change just 761 - happened to expose an old bug, and people had grown to depend on the 762 - previously benign behavior of that old issue. 715 + [...] 763 716 764 - And never fear, we'll re-introduce the fix that improved on the IO 765 - patterns once we've decided just how to handle the fact that we had a 766 - bad interaction with an interface that people had then just happened 767 - to rely on incidental behavior for before. It's just that we'll have 768 - to hash through how to do that (there are no less than three different 769 - patches by three different developers being discussed, and there might 770 - be more coming...). In the meantime, I reverted the thing that exposed 771 - the problem to users for this release, even if I hope it will be 772 - re-introduced (perhaps even backported as a stable patch) once we have 773 - consensus about the issue it exposed. 717 + I just wanted to point out that the argument about whether it's an ABI 718 + change or not is irrelevant. If it turns out that some program - not a test 719 + script, but something with relevance to conscious user expectations ~ 720 + depended on the old broken behavior, then it needs to be done some other 721 + way. 774 722 775 - Take-away from the whole thing: it's not about whether you change the 776 - kernel-userspace ABI, or fix a bug, or about whether the old code 777 - "should never have worked in the first place". It's about whether 778 - something breaks existing users' workflow. 723 + * From `2026-02-13 <https://lore.kernel.org/all/CAHk-=whY-N8kjm8kiFUV5Ei-8AuYw--EPGD-AR3Pd+5GTx2sAQ@mail.gmail.com/>`_:: 779 724 780 - Anyway, that was my little aside on the whole regression thing. Since 781 - it's that "first rule of kernel programming", I felt it is perhaps 782 - worth just bringing it up every once in a while 725 + > [...] this should not fall under the don't break user space rule [...] 726 + 727 + Note that the rule is about breaking *users*, not breaking user space per 728 + se. [...] 729 + 730 + If some user setup breaks, things need fixing. 731 + 732 + [...] but I want to make it very clear that there are no excuses about "user 733 + space applications". 734 + 735 + * From `2021-09-20(4) <https://lore.kernel.org/all/CAHk-=wi7DB2SJ-wngVvsJ7Ak2cM556Q8437sOXo4EJt2BWPdEg@mail.gmail.com/>`_:: 736 + 737 + [...] a regression is a bit like Schrödinger's cat - if nobody is around 738 + to notice it and it doesn't actually affect any real workload, then you 739 + can treat the regression as if it doesn't exist. 740 + 741 + * From `2020-05-21 <https://lore.kernel.org/all/CAHk-=wiVi7mSrsMP=fLXQrXK_UimybW=ziLOwSzFTtoXUacWVQ@mail.gmail.com/>`_:: 742 + 743 + The rules about regressions have never been about any kind of documented 744 + behavior, or where the code lives. 745 + 746 + The rules about regressions are always about "breaks user workflow". 747 + 748 + Users are literally the _only_ thing that matters. 749 + 750 + * From `2019-09-15 <https://lore.kernel.org/lkml/CAHk-=wiP4K8DRJWsCo=20hn_6054xBamGKF2kPgUzpB5aMaofA@mail.gmail.com/>`_:: 751 + 752 + One _particularly_ last-minute revert is the top-most commit (ignoring 753 + the version change itself) done just before the release, and while 754 + it's very annoying, it's perhaps also instructive. 755 + 756 + What's instructive about it is that I reverted a commit that wasn't 757 + actually buggy. In fact, it was doing exactly what it set out to do, 758 + and did it very well. In fact it did it _so_ well that the much 759 + improved IO patterns it caused then ended up revealing a user-visible 760 + regression due to a real bug in a completely unrelated area. 761 + 762 + The actual details of that regression are not the reason I point that 763 + revert out as instructive, though. It's more that it's an instructive 764 + example of what counts as a regression, and what the whole "no 765 + regressions" kernel rule means. 766 + 767 + [...] The reverted commit didn't change any API's, and it didn't introduce 768 + any new bugs. But it ended up exposing another problem, and as such caused 769 + a kernel upgrade to fail for a user. So it got reverted. 770 + 771 + The point here being that we revert based on user-reported _behavior_, not 772 + based on some "it changes the ABI" or "it caused a bug" concept. The problem 773 + was really pre-existing, and it just didn't happen to trigger before. [...] 774 + 775 + Take-away from the whole thing: it's not about whether you change the 776 + kernel-userspace ABI, or fix a bug, or about whether the old code 777 + "should never have worked in the first place". It's about whether 778 + something breaks existing users' workflow. 779 + 780 + * From `2017-11-05 <https://lore.kernel.org/all/CA+55aFzUvbGjD8nQ-+3oiMBx14c_6zOj2n7KLN3UsJ-qsd4Dcw@mail.gmail.com/>`_:: 781 + 782 + And our regression rule has never been "behavior doesn't change". 783 + That would mean that we could never make any changes at all. 784 + 785 + * From `2020-05-21 <https://lore.kernel.org/all/CAHk-=wiVi7mSrsMP=fLXQrXK_UimybW=ziLOwSzFTtoXUacWVQ@mail.gmail.com/>`_:: 786 + 787 + No amount of "you shouldn't have used this" or "that behavior was 788 + undefined, it's your own fault your app broke" or "that used to work 789 + simply because of a kernel bug" is at all relevant. 790 + 791 + * From `2021-05-21 <https://lore.kernel.org/all/CAHk-=wiVi7mSrsMP=fLXQrXK_UimybW=ziLOwSzFTtoXUacWVQ@mail.gmail.com/>`_:: 792 + 793 + But no, "that was documented to be broken" (whether it's because the code 794 + was in staging or because the man-page said something else) is irrelevant. 795 + If staging code is so useful that people end up using it, that means that 796 + it's basically regular kernel code with a flag saying "please clean this 797 + up". 798 + 799 + [...] 800 + 801 + The other side of the coin is that people who talk about "API stability" are 802 + entirely wrong. API's don't matter either. You can make any changes to an 803 + API you like - as long as nobody notices. 804 + 805 + Again, the regression rule is not about documentation, not about API's, and 806 + not about the phase of the moon. 807 + 808 + * From `2012-07-06 <https://lore.kernel.org/all/CA+55aFwnLJ+0sjx92EGREGTWOx84wwKaraSzpTNJwPVV8edw8g@mail.gmail.com/>`_:: 809 + 810 + > Now this got me wondering if Debian _unstable_ actually qualifies as a 811 + > standard distro userspace. 812 + 813 + Oh, if the kernel breaks some standard user space, that counts. Tons 814 + of people run Debian unstable 815 + 816 + * From `2011-05-06 <https://lore.kernel.org/all/BANLkTi=KVXjKR82sqsz4gwjr+E0vtqCmvA@mail.gmail.com/>`_:: 817 + 818 + It's clearly NOT an internal tracepoint. By definition. It's being 819 + used by powertop. 820 + 821 + On regressions noticed by users or test-suites/CIs 822 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 823 + 824 + * From `2026-01-22 <https://lore.kernel.org/all/CAHk-=wheQNiW_WtHGO7bKkT7Uib-p+ai2JP9M+z+FYcZ6CAxYA@mail.gmail.com/>`_:: 825 + 826 + Users complaining is the only real line in the end. 827 + 828 + [...] a test-suite complaining is then often a *very* good indication that 829 + maybe users will hit some problem, and test suite issues should be taken 830 + very seriously [...] 831 + 832 + But a test-suite error isn't necessarily where you have to draw the 833 + line - it's a big red flag [...] 834 + 835 + * From `2024-29-01 <https://lore.kernel.org/all/CAHk-=wg8BrZEzjJ5kUyZzHPZmFqH6ooMN1gRBCofxxCfucgjaw@mail.gmail.com/>`_:: 836 + 837 + The "no regressions" rule is not about made-up "if I do this, behavior 838 + changes". 839 + 840 + The "no regressions" rule is about *users*. 841 + 842 + If you have an actual user that has been doing insane things, and we 843 + change something, and now the insane thing no longer works, at that 844 + point it's a regression, and we'll sigh, and go "Users are insane" and 845 + have to fix it. 846 + 847 + But if you have some random test that now behaves differently, it's 848 + not a regression. It's a *warning* sign, sure: tests are useful. 849 + 850 + On accepting when a regression occurred 851 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 852 + 853 + * From `2026-01-22 <https://lore.kernel.org/all/CAHk-=wheQNiW_WtHGO7bKkT7Uib-p+ai2JP9M+z+FYcZ6CAxYA@mail.gmail.com/>`_:: 854 + 855 + But starting to argue about users reporting breaking changes is 856 + basically the final line for me. I have a couple of people that I have 857 + in my spam block-list and refuse to have anything to do with, and they 858 + have generally been about exactly that. 859 + 860 + Note how it's not about making mistakes and _causing_ the regression. 861 + That's normal. That's development. But then arguing about it is a 862 + no-no. 863 + 864 + * From `2024-06-23 <https://lore.kernel.org/all/CAHk-=wi_KMO_rJ6OCr8mAWBRg-irziM=T9wxGC+J1VVoQb39gw@mail.gmail.com/>`_:: 865 + 866 + We don't introduce regressions and then blame others. 867 + 868 + There's a very clear rule in kernel development: things that break 869 + other things ARE NOT FIXES. 870 + 871 + EVER. 872 + 873 + They get reverted, or the thing they broke gets fixed. 874 + 875 + * From `2021-06-05 <https://lore.kernel.org/all/CAHk-=wiUVqHN76YUwhkjZzwTdjMMJf_zN4+u7vEJjmEGh3recw@mail.gmail.com/>`_:: 876 + 877 + THERE ARE NO VALID ARGUMENTS FOR REGRESSIONS. 878 + 879 + Honestly, security people need to understand that "not working" is not 880 + a success case of security. It's a failure case. 881 + 882 + Yes, "not working" may be secure. But security in that case is *pointless*. 883 + 884 + * From `2017-10-26(5) <https://lore.kernel.org/lkml/CA+55aFwiiQYJ+YoLKCXjN_beDVfu38mg=Ggg5LFOcqHE8Qi7Zw@mail.gmail.com/>`_:: 885 + 886 + [...] when regressions *do* occur, we admit to them and fix them, instead of 887 + blaming user space. 888 + 889 + The fact that you have apparently been denying the regression now for 890 + three weeks means that I will revert, and I will stop pulling apparmor 891 + requests until the people involved understand how kernel development 892 + is done. 893 + 894 + On back-and-forth 895 + ~~~~~~~~~~~~~~~~~ 896 + 897 + * From `2024-05-28 <https://lore.kernel.org/all/CAHk-=wgtb7y-bEh7tPDvDWru7ZKQ8-KMjZ53Tsk37zsPPdwXbA@mail.gmail.com/>`_:: 898 + 899 + The "no regressions" rule is that we do not introduce NEW bugs. 900 + 901 + It *literally* came about because we had an endless dance of "fix two 902 + bugs, introduce one new one", and that then resulted in a system that 903 + you cannot TRUST. 904 + 905 + * From `2021-09-20(1) <https://lore.kernel.org/all/CAHk-=wi7DB2SJ-wngVvsJ7Ak2cM556Q8437sOXo4EJt2BWPdEg@mail.gmail.com/>`_:: 906 + 907 + And the thing that makes regressions special is that back when I 908 + wasn't so strict about these things, we'd end up in endless "seesaw 909 + situations" where somebody would fix something, it would break 910 + something else, then that something else would break, and it would 911 + never actually converge on anything reliable at all. 912 + 913 + * From `2015-08-13 <https://lore.kernel.org/all/CA+55aFxk8-BsiKwr_S-c+4G6wihKPQVMLE34H9wOZpeua6W9+Q@mail.gmail.com/>`_:: 914 + 915 + The strict policy of no regressions actually originally started mainly wrt 916 + suspend/resume issues, where the "fix one machine, break another" kind of 917 + back-and-forth caused endless problems, and meant that we didn't actually 918 + necessarily make any forward progress, just moving a problem around. 919 + 920 + On changes with a risk of causing regressions 921 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 922 + 923 + * From `2023-06-02 <https://lore.kernel.org/all/CAHk-=wgyAGUMHmQM-5Eb556z5xiHZB7cF05qjrtUH4F7P-1rSA@mail.gmail.com/>`_:: 924 + 925 + So what I think you should do is to fix the bug right, with a clean 926 + patch, and no crazy hacks. That is something we can then apply and 927 + test. All the while knowing full well that "uhhuh, this is a visible 928 + change, we may have to revert it". 929 + 930 + If then some *real* load ends up showing a regression, we may just be 931 + screwed. Our current behavior may be buggy, but we have the rule that 932 + once user space depends on kernel bugs, they become features pretty 933 + much by definition, however much we might dislike it. 934 + 935 + On in-kernel workarounds to avoid regressions 936 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 937 + 938 + * From `2017-10-26(6) <https://lore.kernel.org/lkml/CA+55aFxW7NMAMvYhkvz1UPbUTUJewRt6Yb51QAx5RtrWOwjebg@mail.gmail.com/>`_:: 939 + 940 + Behavioral changes happen, and maybe we don't even support some 941 + feature any more. There's a number of fields in /proc/<pid>/stat that 942 + are printed out as zeroes, simply because they don't even *exist* in 943 + the kernel any more, or because showing them was a mistake (typically 944 + an information leak). But the numbers got replaced by zeroes, so that 945 + the code that used to parse the fields still works. The user might not 946 + see everything they used to see, and so behavior is clearly different, 947 + but things still _work_, even if they might no longer show sensitive 948 + (or no longer relevant) information. 949 + 950 + On regressions caused by bugfixes 951 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 952 + 953 + * From `2018-08-03 <https://lore.kernel.org/all/CA+55aFwWZX=CXmWDTkDGb36kf12XmTehmQjbiMPCqCRG2hi9kw@mail.gmail.com/>`_:: 954 + 955 + > Kernel had a bug which has been fixed 956 + 957 + That is *ENTIRELY* immaterial. 958 + 959 + Guys, whether something was buggy or not DOES NOT MATTER. 960 + 961 + [...] 962 + 963 + It's basically saying "I took something that worked, and I broke it, 964 + but now it's better". Do you not see how f*cking insane that statement 965 + is? 966 + 967 + On internal API changes 968 + ~~~~~~~~~~~~~~~~~~~~~~~ 969 + 970 + * From `2017-10-26(7) <https://lore.kernel.org/lkml/CA+55aFxW7NMAMvYhkvz1UPbUTUJewRt6Yb51QAx5RtrWOwjebg@mail.gmail.com/>`_:: 971 + 972 + We do API breakage _inside_ the kernel all the time. We will fix 973 + internal problems by saying "you now need to do XYZ", but then it's 974 + about internal kernel API's, and the people who do that then also 975 + obviously have to fix up all the in-kernel users of that API. Nobody 976 + can say "I now broke the API you used, and now _you_ need to fix it 977 + up". Whoever broke something gets to fix it too. 978 + 979 + On regressions only found after a long time 980 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 981 + 982 + * From `2024-03-28 <https://lore.kernel.org/all/CAHk-=wgFuoHpMk_Z_R3qMXVDgq0N1592+bABkyGjwwSL4zBtHA@mail.gmail.com/>`_:: 983 + 984 + I'm definitely not reverting a patch from almost a decade ago as a 985 + regression. 986 + 987 + If it took that long to find, it can't be that critical of a regression. 988 + 989 + So yes, let's treat it as a regular bug. 990 + 991 + On testing regressions fixes in linux-next 992 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 993 + 994 + * On `maintainers summit 2024 <https://lwn.net/Articles/990599/>`_:: 995 + 996 + So running fixes though linux-next is just a waste of time. 997 + 998 + On a few other aspects related to regressions 999 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1000 + 1001 + * From `2025-07-29(2) <https://lore.kernel.org/all/CAHk-=wjj9DvOZtmTkoLtyfHmy5mNKy6q_96d9=4FUEDXre=cww@mail.gmail.com/>`_ 1002 + [which `is not quite a regression, but a huge inconvenience <https://lore.kernel.org/all/CAHk-=wgO0Rx2LcYT4f75Xs46orbJ4JxO2jbAFQnVKDYAjV5HeQ@mail.gmail.com/>`_]:: 1003 + 1004 + I no longer have sound. 1005 + 1006 + I also suspect that it's purely because "make oldconfig" doesn't work, 1007 + and probably turned off my old Intel HDA settings. Or something. 1008 + 1009 + Renaming config parameters is *bad*. I've harped on the Kconfig phase 1010 + of the kernel build probably being our nastiest point, and a real pain 1011 + point to people getting involved with development simply because 1012 + building your own kernel can be so daunting with hundreds of fairly 1013 + esoteric questions. 783 1014 784 1015 .. 785 1016 end-of-content
-2
Documentation/process/maintainer-handbooks.rst
··· 1 1 .. SPDX-License-Identifier: GPL-2.0 2 2 3 - .. _maintainer_handbooks_main: 4 - 5 3 Subsystem and maintainer tree specific development process notes 6 4 ================================================================ 7 5
+1 -1
Documentation/process/maintainer-tip.rst
··· 352 352 Changelog text starts here.... 353 353 354 354 so the authorship is preserved. The 'From:' line has to be followed 355 - by a empty newline. If that 'From:' line is missing, then the patch 355 + by an empty newline. If that 'From:' line is missing, then the patch 356 356 would be attributed to the person who sent (transported, handled) it. 357 357 The 'From:' line is automatically removed when the patch is applied 358 358 and does not show up in the final git changelog. It merely affects
+11 -1
Documentation/process/submitting-patches.rst
··· 23 23 24 24 Some subsystems and maintainer trees have additional information about 25 25 their workflow and expectations, see 26 - :ref:`Documentation/process/maintainer-handbooks.rst <maintainer_handbooks_main>`. 26 + Documentation/process/maintainer-handbooks.rst. 27 27 28 28 Obtain a current source tree 29 29 ---------------------------- ··· 633 633 bugzilla.kernel.org is a public place in this sense, but email addresses 634 634 used there are private; so do not expose them in tags, unless the person 635 635 used them in earlier contributions. 636 + 637 + Using Assisted-by: 638 + ------------------ 639 + 640 + If you used any sort of advanced coding tool in the creation of your patch, 641 + you need to acknowledge that use by adding an Assisted-by tag. Failure to 642 + do so may impede the acceptance of your work. Please see 643 + Documentation/process/coding-assistants.rst for details regarding the 644 + acknowledgment of coding assistants. 645 + 636 646 637 647 .. _the_canonical_patch_format: 638 648
+17 -5
Documentation/scheduler/sched-deadline.rst
··· 628 628 * the new scheduling related syscalls that manipulate it, i.e., 629 629 sched_setattr() and sched_getattr() are implemented. 630 630 631 - For debugging purposes, the leftover runtime and absolute deadline of a 632 - SCHED_DEADLINE task can be retrieved through /proc/<pid>/sched (entries 633 - dl.runtime and dl.deadline, both values in ns). A programmatic way to 634 - retrieve these values from production code is under discussion. 631 + The leftover runtime and absolute deadline of a SCHED_DEADLINE task can be 632 + read using the sched_getattr() syscall, setting the last syscall parameter 633 + flags to the SCHED_GETATTR_FLAG_DL_DYNAMIC=1 value. This updates the 634 + runtime left, converts the absolute deadline in CLOCK_MONOTONIC reference, 635 + then returns these parameters to user-space. The absolute deadline is 636 + returned as the number of nanoseconds since the CLOCK_MONOTONIC time 637 + reference (boot instant), as a u64 in the sched_deadline field of sched_attr, 638 + which can represent nearly 585 years since boot time (calling sched_getattr() 639 + with flags=0 causes retrieval of the static parameters instead). 640 + 641 + For debugging purposes, these parameters can also be retrieved through 642 + /proc/<pid>/sched (entries dl.runtime and dl.deadline, both values in ns), 643 + but: this is highly inefficient; the returned runtime left is not updated as 644 + done by sched_getattr(); the deadline is provided in kernel rq_clock time 645 + reference, that is not directly usable from user-space. 635 646 636 647 637 648 4.3 Default behavior ··· 711 700 5.2 Using cgroup v2 cpuset controller 712 701 ------------------------------------- 713 702 714 - Assuming the cgroup v2 root is mounted at ``/sys/fs/cgroup``. 703 + Assuming the cgroup v2 root is mounted at ``/sys/fs/cgroup``, an example of a 704 + simple configuration (pin a -deadline task to CPU0) follows:: 715 705 716 706 cd /sys/fs/cgroup 717 707 echo '+cpuset' > cgroup.subtree_control
+2 -3
Documentation/scheduler/sched-design-CFS.rst
··· 183 183 184 184 - yield_task(...) 185 185 186 - This function is basically just a dequeue followed by an enqueue, unless the 187 - compat_yield sysctl is turned on; in that case, it places the scheduling 188 - entity at the right-most end of the red-black tree. 186 + This function yields the CPU by moving the currently running task's position back 187 + in the runqueue, so that other runnable tasks get scheduled first. 189 188 190 189 - wakeup_preempt(...) 191 190
+26
Documentation/sphinx-static/custom.css
··· 40 40 dl.function, dl.struct, dl.enum { margin-top: 2em; background-color: #ecf0f3; } 41 41 /* indent lines 2+ of multi-line function prototypes */ 42 42 dl.function dt { margin-left: 10em; text-indent: -10em; } 43 + /* 44 + * Preserve C API signatures on one line and apply contained horizontal 45 + * scrolling to prevent them from exceeding their container width and 46 + * breaking page layout. 47 + */ 48 + dl.c { overflow-x: auto; overflow-y: hidden; } 49 + dl.c > dt.sig.sig-object { white-space: nowrap; } 43 50 dt.sig-object { font-size: larger; } 44 51 div.kernelindent { margin-left: 2em; margin-right: 4em; } 45 52 ··· 154 147 155 148 div.language-selection ul li:hover { 156 149 background: #dddddd; 150 + } 151 + 152 + /* 153 + * Let long inline literals in paragraph text wrap as needed to prevent 154 + * overflow. 155 + */ 156 + code.docutils.literal span.pre { 157 + white-space: normal; 158 + overflow-wrap: anywhere; 159 + } 160 + 161 + /* Let rendered reference links in tables wrap when needed. */ 162 + div.body table.docutils a.reference { 163 + overflow-wrap: anywhere; 164 + } 165 + 166 + /* Let long link text wrap instead of forcing overflow. */ 167 + a { 168 + overflow-wrap: anywhere; 157 169 } 158 170 159 171 /* Make xrefs more universally visible */
+1
Documentation/sphinx/translations.py
··· 25 25 'it_IT': 'Italian', 26 26 'ja_JP': 'Japanese', 27 27 'ko_KR': 'Korean', 28 + 'pt_BR': 'Portuguese (Brazilian)', 28 29 'sp_SP': 'Spanish', 29 30 } 30 31
+17
Documentation/tools/kdoc_ancillary.rst
··· 21 21 :undoc-members: 22 22 23 23 24 + C tokenizer 25 + =========== 26 + 27 + .. automodule:: lib.python.kdoc.c_lex 28 + :members: 29 + :show-inheritance: 30 + :undoc-members: 31 + 32 + 24 33 Chinese, Japanese and Korean variable fonts handler 25 34 =================================================== 26 35 ··· 50 41 ================================ 51 42 52 43 .. automodule:: lib.python.kdoc.python_version 44 + :members: 45 + :show-inheritance: 46 + :undoc-members: 47 + 48 + Write output on YAML file 49 + ========================= 50 + 51 + .. automodule:: lib.python.kdoc.kdoc_yaml_file 53 52 :members: 54 53 :show-inheritance: 55 54 :undoc-members:
+8
Documentation/tools/kdoc_parser.rst
··· 4 4 Kernel-doc parser stage 5 5 ======================= 6 6 7 + C replacement rules used by the parser 8 + ====================================== 9 + 10 + .. automodule:: lib.python.kdoc.xforms_lists 11 + :members: 12 + :show-inheritance: 13 + :undoc-members: 14 + 7 15 File handler classes 8 16 ==================== 9 17
+2
Documentation/tools/python.rst
··· 11 11 feat 12 12 kdoc 13 13 kabi 14 + 15 + unittest
+1 -1
Documentation/tools/rtla/rtla-hwnoise.rst
··· 100 100 101 101 **rtla-osnoise**\(1) 102 102 103 - Osnoise tracer documentation: <https://www.kernel.org/doc/html/latest/trace/osnoise-tracer.html> 103 + `Osnoise tracer <https://docs.kernel.org/trace/osnoise-tracer.html>`__ 104 104 105 105 AUTHOR 106 106 ======
+1 -1
Documentation/tools/rtla/rtla-osnoise-hist.rst
··· 59 59 ======== 60 60 **rtla-osnoise**\(1), **rtla-osnoise-top**\(1) 61 61 62 - *osnoise* tracer documentation: <https://www.kernel.org/doc/html/latest/trace/osnoise-tracer.html> 62 + `Osnoise tracer <https://docs.kernel.org/trace/osnoise-tracer.html>`__ 63 63 64 64 AUTHOR 65 65 ======
+1 -1
Documentation/tools/rtla/rtla-osnoise-top.rst
··· 54 54 55 55 **rtla-osnoise**\(1), **rtla-osnoise-hist**\(1) 56 56 57 - Osnoise tracer documentation: <https://www.kernel.org/doc/html/latest/trace/osnoise-tracer.html> 57 + `Osnoise tracer <https://docs.kernel.org/trace/osnoise-tracer.html>`__ 58 58 59 59 AUTHOR 60 60 ======
+1 -1
Documentation/tools/rtla/rtla-osnoise.rst
··· 50 50 ======== 51 51 **rtla-osnoise-top**\(1), **rtla-osnoise-hist**\(1) 52 52 53 - Osnoise tracer documentation: <https://www.kernel.org/doc/html/latest/trace/osnoise-tracer.html> 53 + `Osnoise tracer <https://docs.kernel.org/trace/osnoise-tracer.html>`__ 54 54 55 55 AUTHOR 56 56 ======
+1 -1
Documentation/tools/rtla/rtla-timerlat-hist.rst
··· 104 104 ======== 105 105 **rtla-timerlat**\(1), **rtla-timerlat-top**\(1) 106 106 107 - *timerlat* tracer documentation: <https://www.kernel.org/doc/html/latest/trace/timerlat-tracer.html> 107 + `Timerlat tracer <https://docs.kernel.org/trace/timerlat-tracer.html>`__ 108 108 109 109 AUTHOR 110 110 ======
+1 -1
Documentation/tools/rtla/rtla-timerlat-top.rst
··· 127 127 -------- 128 128 **rtla-timerlat**\(1), **rtla-timerlat-hist**\(1) 129 129 130 - *timerlat* tracer documentation: <https://www.kernel.org/doc/html/latest/trace/timerlat-tracer.html> 130 + `Timerlat tracer <https://docs.kernel.org/trace/timerlat-tracer.html>`__ 131 131 132 132 AUTHOR 133 133 ------
+1 -1
Documentation/tools/rtla/rtla-timerlat.rst
··· 45 45 ======== 46 46 **rtla-timerlat-top**\(1), **rtla-timerlat-hist**\(1) 47 47 48 - *timerlat* tracer documentation: <https://www.kernel.org/doc/html/latest/trace/timerlat-tracer.html> 48 + `Timerlat tracer <https://docs.kernel.org/trace/timerlat-tracer.html>`__ 49 49 50 50 AUTHOR 51 51 ======
+5 -1
Documentation/tools/rtla/rtla.rst
··· 21 21 22 22 COMMANDS 23 23 ======== 24 + **hwnoise** 25 + 26 + Detect and quantify hardware-related noise. 27 + 24 28 **osnoise** 25 29 26 30 Gives information about the operating system noise (osnoise). ··· 43 39 44 40 SEE ALSO 45 41 ======== 46 - **rtla-osnoise**\(1), **rtla-timerlat**\(1) 42 + **rtla-hwnoise**\(1), **rtla-osnoise**\(1), **rtla-timerlat**\(1) 47 43 48 44 AUTHOR 49 45 ======
+24
Documentation/tools/unittest.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + =============== 4 + Python unittest 5 + =============== 6 + 7 + Checking consistency of python modules can be complex. Sometimes, it is 8 + useful to define a set of unit tests to help checking them. 9 + 10 + While the actual test implementation is usecase dependent, Python already 11 + provides a standard way to add unit tests by using ``import unittest``. 12 + 13 + Using such class, requires setting up a test suite. Also, the default format 14 + is a little bit ackward. To improve it and provide a more uniform way to 15 + report errors, some unittest classes and functions are defined. 16 + 17 + 18 + Unittest helper module 19 + ====================== 20 + 21 + .. automodule:: lib.python.unittest_helper 22 + :members: 23 + :show-inheritance: 24 + :undoc-members:
+13 -7
Documentation/trace/histogram-design.rst
··· 69 69 bucket contains a value for that bucket, counting the number of times 70 70 sched_waking was called for that pid. 71 71 72 - Each histogram is represented by a hist_data struct. 72 + Each histogram is represented by a hist_data struct 73 + (struct hist_trigger_data). 73 74 74 75 To keep track of each key and value field in the histogram, hist_data 75 76 keeps an array of these fields named fields[]. The fields[] array is ··· 83 82 84 83 Each struct hist_field contains a pointer to the ftrace_event_field 85 84 from the event's trace_event_file along with various bits related to 86 - that such as the size, offset, type, and a hist_field_fn_t function, 85 + that such as the size, offset, type, and a hist field function, 87 86 which is used to grab the field's data from the ftrace event buffer 88 87 (in most cases - some hist_fields such as hitcount don't directly map 89 88 to an event field in the trace buffer - in these cases the function ··· 242 241 with the key: for each subkey in the key (in the above example, there 243 242 is just one subkey corresponding to pid), the hist_field that 244 243 represents that subkey is retrieved from hist_data.fields[] and the 245 - hist_field_fn_t fn() associated with that field, along with the 244 + hist field function associated with that field, along with the 246 245 field's size and offset, is used to grab that subkey's data from the 247 246 current trace record. 247 + 248 + Note, the hist field function use to be a function pointer in the 249 + hist_field stucture. Due to spectre mitigation, it was converted into 250 + a fn_num and hist_fn_call() is used to call the associated hist field 251 + function that corresponds to the fn_num of the hist_field structure. 248 252 249 253 Once the complete key has been retrieved, it's used to look that key 250 254 up in the tracing_map. If there's no tracing_map_elt associated with ··· 257 251 key. In either case, the tracing_map_elt associated with that key is 258 252 returned. 259 253 260 - Once a tracing_map_elt available, hist_trigger_elt_update() is called. 254 + Once a tracing_map_elt is available, hist_trigger_elt_update() is called. 261 255 As the name implies, this updates the element, which basically means 262 256 updating the element's fields. There's a tracing_map_field associated 263 257 with each key and value in the histogram, and each of these correspond 264 258 to the key and value hist_fields created when the histogram was 265 259 created. hist_trigger_elt_update() goes through each value hist_field 266 - and, as for the keys, uses the hist_field's fn() and size and offset 260 + and, as for the keys, uses the hist_field's function and size and offset 267 261 to grab the field's value from the current trace record. Once it has 268 262 that value, it simply adds that value to that field's 269 263 continually-updated tracing_map_field.sum member. Some hist_field 270 - fn()s, such as for the hitcount, don't actually grab anything from the 271 - trace record (the hitcount fn() just increments the counter sum by 1), 264 + functions, such as for the hitcount, don't actually grab anything from the 265 + trace record (the hitcount function just increments the counter sum by 1), 272 266 but the idea is the same. 273 267 274 268 Once all the values have been updated, hist_trigger_elt_update() is
+2 -2
Documentation/translations/index.rst
··· 10 10 zh_CN/index 11 11 zh_TW/index 12 12 it_IT/index 13 - ko_KR/index 14 13 ja_JP/index 14 + ko_KR/index 15 + pt_BR/index 15 16 sp_SP/index 16 - 17 17 18 18 .. _translations_disclaimer: 19 19
+2 -1
Documentation/translations/it_IT/process/4.Coding.rst
··· 329 329 lo prevede, potete trovarlo su https://sparse.wiki.kernel.org/index.php/Main_Page); 330 330 può essere attivato sul codice aggiungendo "C=1" al comando make. 331 331 332 - Lo strumento "Coccinelle" (http://coccinelle.lip6.fr/) è in grado di trovare 332 + Lo strumento "Coccinelle" (https://coccinelle.gitlabpages.inria.fr/website/) 333 + è in grado di trovare 333 334 una vasta varietà di potenziali problemi di codifica; e può inoltre proporre 334 335 soluzioni per risolverli. Un buon numero di "patch semantiche" per il kernel 335 336 sono state preparate nella cartella scripts/coccinelle; utilizzando
+127 -2
Documentation/translations/ja_JP/process/submitting-patches.rst
··· 35 35 36 36 いくつかのサブシステムやメンテナツリーには、各々のワークフローや 37 37 期待事項に関する追加情報があります。次を参照してください: 38 - :ref:`Documentation/process/maintainer-handbooks.rst <maintainer_handbooks_main>`. 38 + Documentation/process/maintainer-handbooks.rst. 39 39 40 40 現在のソースツリーを入手する 41 41 ---------------------------- ··· 52 52 ツリーは MAINTAINERS ファイル内の **T:** エントリを参照して見つけてください。 53 53 そこに掲載されていない場合は、メンテナに問い合わせてください。 54 54 55 - 変更内容を説明する 55 + 変更内容を記述する 56 56 ------------------ 57 + 58 + まず問題点を記べてください。あなたのパッチが 1 行のバグ修正であっても、 59 + 5000 行の新機能であっても、それを行う動機となった根本的な問題が 60 + 必ずあるはずです。レビューアが、修正すべき問題がたしかに存在し、冒頭の 61 + 段落の続きを読むべきだと納得できるように書いてください。 62 + 63 + 次にユーザーから見える影響を記述してください。クラッシュやロックアップは 64 + 分かりやすいですが、すべてのバグがそこまで露骨とは限りません。 65 + たとえコードレビュー中に見つかった問題であっても、ユーザーに 66 + どのような影響があり得るかを記述してください。 67 + Linux の多くの環境は、上流から特定のパッチだけを取り込む二次的な 68 + 安定版ツリーや、ベンダー/製品固有のツリーのカーネルで動いています。 69 + したがって、変更を適切に下流へ流す助けになる情報(発生条件、dmesg 70 + の抜粋、クラッシュ内容、性能劣化、レイテンシのスパイク、 71 + ロックアップ等)があれば記載してください。 72 + 73 + 次に最適化とトレードオフを定量的に示してください。パフォーマンス、 74 + メモリ消費量、スタックフットプリント、バイナリサイズの改善を主張する 75 + 場合は、それを裏付ける数値を記載してください。 76 + また、目に見えないコストについても記述してください。多くの場合、 77 + 最適化は CPU・メモリ・可読性の間でのトレードオフとなります。 78 + ヒューリスティクスの場合は、異なるワークロード間でのトレードオフと 79 + なります。レビューアがコストとメリットを比較検討できるよう、 80 + 最適化に伴って想定されるデメリットも記述してください。 81 + 82 + 問題点の明確化が済んだら、実際にどのような対策を講じているかを技術的に 83 + 詳しく説明してください。コードが意図したとおりに動作していることを 84 + レビューアが確認できるよう、変更内容を平易な言葉で書き下すことが重要です。 85 + 86 + パッチの説明が Linux のソースコード管理システム ``git`` の「コミットログ」 87 + としてそのまま取り込める形で書かれていれば、メンテナは助かります。 88 + 詳細は原文の該当節 ("The canonical patch format") を参照してください。 89 + 90 + .. TODO: Convert to file-local cross-reference when the destination is 91 + translated. 92 + 93 + 1 つのパッチでは 1 つの問題だけを解決してください。記述が長くなり 94 + 始めたら、それはパッチを分割すべきサインです。 95 + 詳細は原文の該当節 ("Separate your changes") を参照してください。 96 + 97 + .. TODO: Convert to file-local cross-reference when the destination is 98 + translated. 99 + 100 + パッチまたはパッチシリーズを投稿/再投稿する際は、その完全な 101 + 説明と、それを正当化する理由を含めてください。単に「これはパッチ 102 + (シリーズ)のバージョン N です」とだけ書くのは避けてください。 103 + サブシステムメンテナが以前のパッチバージョンや参照先 URL をさかのぼって 104 + パッチ記述を探し、それをパッチに補うことを期待してはいけません。 105 + つまり、パッチ(シリーズ)とその説明は、それだけで完結しているべき 106 + です。これはメンテナとレビューアの双方に有益です。レビューアの 107 + 中には、以前のパッチバージョンを受け取っていない人もいるでしょう。 108 + 109 + 変更内容は、あたかもコードベースに対してその振る舞いを変えるように 110 + 命令するかの如く、(訳補: 英語の)命令形で記述してください。たとえば、 111 + "[This patch] makes xyzzy do frotz" や 112 + "[I] changed xyzzy to do frotz" のような言い回しを避け、 113 + "make xyzzy do frotz" のように書いてください。 114 + 115 + 特定のコミットに言及したい場合に、コミットの SHA-1 ID だけを 116 + 書くのは避けてください。レビューアがそれが何についてのものかを 117 + 把握しやすいよう、コミットの 1 行要約も含めてください。例:: 118 + 119 + Commit e21d2170f36602ae2708 ("video: remove unnecessary 120 + platform_set_drvdata()") removed the unnecessary 121 + platform_set_drvdata(), but left the variable "dev" unused, 122 + delete it. 123 + 124 + また、SHA-1 ID は少なくとも先頭 12 文字を使うようにしてください。 125 + カーネルのリポジトリには\ **非常に多くの**\ オブジェクトがあるため、 126 + それより短い ID では衝突が現実問題となります。6 文字の ID が今現在 127 + 衝突しないからといって、5 年後もそうであるとは限らないことを念頭に 128 + 置いてください。 129 + 130 + 変更に関連する議論や、その背景情報が Web 上で参照できる場合は、 131 + それを指す 'Link:' タグを追加してください。過去のメーリングリスト 132 + での議論や、Web に記録された何かに由来するパッチならば、 133 + それを示してください。 134 + 135 + メーリングリストのアーカイブへリンクする場合は、できれば lore.kernel.org 136 + のメッセージアーカイブサービスを使ってください。リンク URL を作るには、 137 + そのメッセージの ``Message-ID`` ヘッダの内容から、前後の山括弧を取り除いた 138 + ものを使います。例:: 139 + 140 + Link: https://lore.kernel.org/30th.anniversary.repost@klaava.Helsinki.FI 141 + 142 + 実際にリンクが機能し、該当するメッセージを指していることを 143 + 確認してください。 144 + 145 + ただし、外部リソースを見なくても説明が理解できるようにするよう努めてください。 146 + メーリングリストのアーカイブやバグへの URL を示すだけでなく、 147 + 投稿されたパッチに至った議論のポイントも要約してください。 148 + 149 + パッチがバグを修正するものであれば、メーリングリストのアーカイブや 150 + 公開バグトラッカー上の報告を指す URL を付けて、``Closes:`` タグを 151 + 使ってください。例:: 152 + 153 + Closes: https://example.com/issues/1234 154 + 155 + このようなタグ付きのコミットが適用されたとき、自動的に issue を 156 + 閉じるバグトラッカーもあります。メーリングリストを監視している 157 + ボットの中には、そのようなタグを追跡して一定の動作を行うものも 158 + あります。ただし、非公開バグトラッカーの(訳補: 部外者が)閲覧できない 159 + URL は禁止です。 160 + 161 + パッチが特定のコミットに含まれるバグを修正するもの、たとえば 162 + ``git bisect`` で問題を見つけたものの場合には、SHA-1 ID の 163 + 先頭少なくとも 12 文字と 1 行要約を含めて 'Fixes:' タグを 164 + 使ってください。タグを複数行に分割してはいけません。タグは 165 + 解析スクリプトを単純にするため、「75 桁で折り返す」規則の 166 + 例外です。例:: 167 + 168 + Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed") 169 + 170 + ``git log`` や ``git show`` の出力を上の形式で整形させるには、 171 + 次の ``git config`` 設定が使えます:: 172 + 173 + [core] 174 + abbrev = 12 175 + [pretty] 176 + fixes = Fixes: %h ("%s") 177 + 178 + 呼び出し例:: 179 + 180 + $ git log -1 --pretty=fixes 54a4f0239f2e 181 + Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+11
Documentation/translations/pt_BR/disclaimer-pt_BR.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + 4 + 5 + Aviso sobre traduções para português 6 + ==================================== 7 + 8 + Esta documentação foi traduzida para português brasileiro por voluntários. 9 + Em caso de qualquer divergência entre esta tradução e o documento original 10 + em inglês, a versão em inglês (encontrada no diretório Documentation/) 11 + deve ser considerada a única fonte de verdade.
+77
Documentation/translations/pt_BR/index.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + 4 + 5 + ========================================= 6 + Documentação do Kernel Linux em Português 7 + ========================================= 8 + 9 + .. raw:: latex 10 + 11 + \kerneldocCJKoff 12 + 13 + :mantenedor: Daniel Pereira <danielmaraboo@gmail.com> 14 + 15 + Este é o nível principal da documentação do kernel em língua portuguesa (Brasil). 16 + A tradução ainda está em seu estágio inicial e incompleta; você notará avisos 17 + sinalizando a falta de traduções para grupos específicos de documentos. 18 + 19 + De maneira geral, a documentação, assim como o próprio kernel, está em constante 20 + desenvolvimento; isso é especialmente verdade agora, pois estamos trabalhando 21 + na reorganização da documentação de forma mais coerente. Melhorias na 22 + documentação são sempre bem-vindas; se você deseja ajudar, inscreva-se na lista 23 + de discussão linux-doc em vger.kernel.org. 24 + 25 + 26 + 27 + Avisos 28 + ====== 29 + 30 + .. include:: disclaimer-pt_BR.rst 31 + 32 + O objetivo desta tradução é facilitar a leitura e compreensão para aqueles que 33 + não dominam o inglês ou têm dúvidas sobre sua interpretação, ou simplesmente 34 + para quem prefere ler em sua língua nativa. No entanto, tenha em mente que a 35 + *única* documentação oficial é a em língua inglesa: :ref:`linux_doc` 36 + 37 + A propagação simultânea de uma alteração em :ref:`linux_doc` para todas as 38 + traduções é altamente improvável. Os mantenedores das traduções — e seus 39 + contribuidores — acompanham a evolução da documentação oficial e tentam manter 40 + as respectivas traduções alinhadas na medida do possível. Por este motivo, não 41 + há garantia de que uma tradução esteja atualizada com a última modificação. 42 + Se o que você ler em uma tradução não corresponder ao que ler no código, 43 + informe o mantenedor da tradução e — se puder — verifique também a 44 + documentação em inglês. 45 + 46 + Uma tradução não é um *fork* da documentação oficial; portanto, os usuários não 47 + encontrarão nela informações diferentes daquelas contidas na versão oficial. 48 + Qualquer adição, remoção ou modificação de conteúdo deve ser feita primeiro nos 49 + documentos em inglês. Posteriormente, quando possível, a mesma alteração deve 50 + ser aplicada às traduções. Os mantenedores das traduções aceitam contribuições 51 + que afetem puramente a atividade de tradução (por exemplo, novas traduções, 52 + atualizações, correções). 53 + 54 + As traduções buscam ser o mais precisas possível, mas não é possível mapear 55 + diretamente uma língua em outra. Cada língua possui sua própria gramática e 56 + cultura, portanto, a tradução de uma frase em inglês pode ser modificada para 57 + se adaptar ao português. Por esse motivo, ao ler esta tradução, você poderá 58 + encontrar algumas diferenças de forma, mas que transmitem a mensagem original. 59 + 60 + Trabalhando com a comunidade de desenvolvimento 61 + =============================================== 62 + 63 + As guias fundamentais para a interação com a comunidade de desenvolvimento do 64 + kernel e sobre como ver seu trabalho integrado. 65 + 66 + .. toctree:: 67 + :maxdepth: 1 68 + 69 + Introdução <process/1.Intro> 70 + Como começar <process/howto> 71 + Requisitos mínimos <process/changes> 72 + Conclave (Continuidade do projeto) <process/conclave> 73 + Manuais dos mantenedores <process/maintainer-handbooks> 74 + Processo do subsistema de rede (netdev) <process/maintainer-netdev> 75 + Processo do subsistema SoC <process/maintainer-soc> 76 + Conformidade de DTS para SoC <process/maintainer-soc-clean-dts> 77 + Processo do subsistema KVM x86 <process/maintainer-kvm-x86>
+269
Documentation/translations/pt_BR/process/1.Intro.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + Introdução 4 + ========== 5 + 6 + Sumário 7 + ------- 8 + 9 + O restante desta seção cobre o processo de desenvolvimento do kernel e os 10 + tipos de frustração que os desenvolvedores e empresas podem encontrar pelo 11 + caminho. Existem diversas razões que justificam a recomendação para que seja 12 + feito o merge do código do kernel ao kernel principal ("mainline"), como 13 + disponibilidade automática aos usuários, suporte da comunidade em diversas 14 + formas, e a oportunidade de influenciar a direção do desenvolvimento do 15 + kernel. Contribuições ao kernel Linux obrigatoriamente devem estar disponíveis 16 + sob uma licença compatível com a GPL. 17 + 18 + :ref:`development_process` apresenta o processo de desenvolvimento, o ciclo de 19 + lançamento, e a mecânica da janela de merge. As várias fases no desenvolvimento 20 + de patch, revisão, e ciclo de merge são explicadas. Algumas ferramentas e 21 + listas de e-mail são discutidas. Desenvolvedores que queiram começar a 22 + desenvolver o kernel são encorajados a buscar e corrigir bugs como exercício 23 + inicial. 24 + 25 + :ref:`development_early_stage` cobre os primeiros passos do processo de 26 + desenvolvimento, com ênfase no envolvimento da comunidade de desenvolvedores o 27 + mais cedo possível. 28 + 29 + :ref:`development_coding` é sobre o processo de codificação; muitas armadilhas 30 + já encontradas por outros desenvolvedores são discutidas. Alguns requisitos 31 + para patches são explicados, e é feita uma introdução para algumas ferramentas 32 + que podem ajudar a garantir que os patches de kernel estão corretos. 33 + 34 + :ref:`development_posting` fala sobre o processo de envio de patches para 35 + revisão. Para serem levados em consideração pela comunidade desenvolvedora, os 36 + patches devem estar devidamente formatados e descritos, assim como devem estar 37 + no lugar correto. Seguir os conselhos dessa seção pode ajudar na recepção 38 + positiva do seu trabalho. 39 + 40 + :ref:`development_followthrough` cobre o que acontece após o envio dos patches; 41 + o trabalho ainda está longe de estar concluído. Trabalhar com os revisores é 42 + parte crucial do processo de desenvolvimento; essa seção oferece dicas de como 43 + evitar problemas nesse estágio importante. Desenvolvedores são alertados a não 44 + presumir que o trabalho acabou após o merge do patch no "mainline". 45 + 46 + :ref:`development_advancedtopics` introduz dois tópicos mais "avançados": 47 + gerenciamento de patches com git e revisão de patches por outros. 48 + 49 + :ref:`development_conclusion` conclui o documento com indicações de fontes com 50 + mais informações sobre o desenvolvimento do kernel. 51 + 52 + Sobre este documento 53 + -------------------- 54 + 55 + O kernel Linux, com mais de 8 milhões de linhas de código e bem mais de 1000 56 + contribuintes a cada lançamento ("release"), é um dos maiores e mais ativos 57 + projetos de software livre em existência. Desde seu modesto início em 1991, 58 + este kernel evoluiu para se tornar um dos melhores componentes de sistemas 59 + operacionais, rodando em pequenos players de música digital, PCs de mesa, os 60 + maiores supercomputadores em existência, e todos os outros tipos de sistema 61 + entre eles. É robusto, eficiente, e uma solução escalável para quase toda 62 + situação. 63 + 64 + O crescimento do Linux trouxe o aumento no número de desenvolvedores (e 65 + empresas) desejando participar no seu desenvolvimento. Fabricantes de hardware 66 + querem garantir que o Linux suporte bem os seus produtos, tornando-os atrativos 67 + para usuários Linux. Fabricantes de sistemas embarcados, que usam o Linux como 68 + componente em um produto integrado, querem que o Linux seja tão capaz e 69 + adequado quanto possível para a tarefa em questão. Distribuidores de software 70 + que baseiam seus produtos em Linux têm claro interesse nas capacidades, 71 + performance, e confiabilidade do kernel Linux. É também comum que usuários 72 + finais queiram alterar o Linux para atender melhor suas necessidades. 73 + 74 + Uma das características mais atrativas do Linux é sua facilidade de acesso a 75 + esses desenvolvedores; qualquer um com as habilidades necessárias pode melhorar 76 + o Linux e influenciar a direção do seu desenvolvimento. Produtos proprietários 77 + não conseguem oferecer esse tipo de abertura, que é característico do processo 78 + de software livre. O kernel é ainda mais acessível que a maioria dos outros 79 + projetos de software livre. Um ciclo típico de três meses de desenvolvimento 80 + do kernel pode envolver mais de 1000 desenvolvedores trabalhando para mais de 81 + 100 empresas (ou absolutamente nenhuma empresa). 82 + 83 + Trabalhar com a comunidade de desenvolvimento do kernel não é uma tarefa árdua. 84 + Contudo, muitos colaboradores potenciais passaram por dificuldades ao tentar 85 + trabalhar no kernel. A comunidade evoluiu suas próprias formas de funcionamento 86 + que permitem operar de forma fluida (e produzir um produto de alta qualidade) 87 + em um ambiente em que milhares de linhas de código são alteradas todos os dias. 88 + Não é surpresa que o processo de desenvolvimento do kernel Linux seja muito 89 + diferente dos modelos de desenvolvimento proprietários. 90 + 91 + O processo de desenvolvimento do kernel pode parecer estranho e intimidador 92 + para novos desenvolvedores, mas existem bons motivos e uma sólida experiência 93 + por trás disso. Um desenvolvedor que não entenda os caminhos próprios da 94 + comunidade kernel (ou pior, que tente menosprezá-los ou contorná-los) terá uma 95 + experiência frustrante pela frente. A comunidade de desenvolvimento ajuda 96 + aqueles que tentam aprender, mas gasta pouco tempo com aqueles que não escutam 97 + ou não ligam para o processo de desenvolvimento. 98 + 99 + Espera-se que aqueles que leiam este documento sejam capazes de evitar essa 100 + experiência frustrante. Há muito material aqui, mas o esforço envolvido na sua 101 + leitura valerá a pena. A comunidade de desenvolvimento sempre necessita de 102 + desenvolvedores que ajudem a melhorar o kernel; o texto a seguir deve ajudar 103 + você - ou aqueles trabalhando para você - a se juntar à nossa comunidade. 104 + 105 + Créditos 106 + -------- 107 + 108 + Esse documento foi escrito por Jonathan Corbet, corbet@lwn.net. Aprimorado 109 + pelos comentários de Johannes Berg, James Berry, Alex Chiang, Roland Dreier, 110 + Randy Dunlap, Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh, Amanda 111 + McPherson, Andrew Morton, Andrew Price, Tsugikazu Shibata, e Jochen Voß. 112 + 113 + Esse trabalho contou com o apoio da Linux Foundation; agradecimentos especiais 114 + para Amanda McPherson, que viu o valor desse esforço e fez tudo acontecer. 115 + 116 + A importância de levar o código até o "mainline" 117 + ------------------------------------------------- 118 + 119 + Algumas empresas e desenvolvedores ocasionalmente se perguntam por que devem 120 + se importar em aprender como trabalhar com a comunidade do kernel e ter seu 121 + código no "mainline" (o kernel mantido por Linus Torvalds e usado como base 122 + para os distribuidores Linux). No curto prazo, contribuir com o código pode 123 + parecer um gasto evitável; parece mais fácil apenas manter o seu código à 124 + parte e oferecer suporte direto aos usuários. A verdade é que manter código 125 + fora da árvore principal ("out-of-tree") é uma falsa economia. 126 + 127 + Para ilustrar os custos do código "out-of-tree", aqui estão alguns aspectos 128 + relevantes do processo de desenvolvimento do kernel; a maioria será discutida 129 + com mais detalhes adiante neste documento. Considere: 130 + 131 + - Código integrado via merge ao "mainline" fica disponível para todos os 132 + usuários Linux. Estará automaticamente presente em todas as distribuições 133 + que o habilitarem. Não há necessidade de discos de armazenamento, downloads, 134 + ou as complicações de dar suporte a múltiplas versões de variadas 135 + distribuições; tudo simplesmente funciona, para o desenvolvedor e para o 136 + usuário. Incorporação ao "mainline" resolve um grande número de problemas 137 + de distribuição e suporte. 138 + 139 + - Enquanto desenvolvedores do kernel se esforçam para manter uma interface 140 + estável para o espaço do usuário, a API interna está em constante mudança. 141 + A ausência de uma interface interna estável é uma escolha deliberada de 142 + design; permite que sejam feitas melhorias fundamentais a qualquer tempo e 143 + resulta em código de qualidade superior. Uma consequência dessa política é 144 + que código "out-of-tree" precisa ser constantemente atualizado para que 145 + continue funcionando com novos kernels. Manter código "out-of-tree" requer 146 + significativo trabalho apenas para mantê-lo funcionando. 147 + 148 + Por sua vez, código que está no "mainline" não precisa dessa manutenção, 149 + resultado de uma regra simples que exige que qualquer desenvolvedor que 150 + altere uma API, também conserte qualquer código que deixe de funcionar como 151 + resultado da alteração. Código que teve o merge realizado no "mainline" tem 152 + custo significativamente menor de manutenção. 153 + 154 + - Além disso, código que está no kernel será muitas vezes melhorado por outros 155 + desenvolvedores. Resultados surpreendentes podem surgir ao permitir que sua 156 + comunidade de usuários e clientes melhore seu produto. 157 + 158 + - Código do kernel está sujeito a revisão, tanto antes como depois do merge ao 159 + "mainline". Independentemente das habilidades do desenvolvedor original, o 160 + processo de revisão invariavelmente encontra maneiras de evoluí-lo. Bugs 161 + severos e problemas de segurança são constantemente encontrados durante o 162 + processo de revisão. Isso é especialmente válido para código desenvolvido em 163 + ambiente isolado; tais códigos se beneficiam fortemente ao serem revistos por 164 + outros desenvolvedores. Código "out-of-tree" é código de baixa qualidade. 165 + 166 + - Participação no processo de desenvolvimento é a forma pela qual você pode 167 + influenciar a direção do desenvolvimento do kernel. Usuários que se queixam 168 + externamente são ouvidos, porém desenvolvedores ativos têm maior poder de 169 + articulação - e a habilidade de implementar mudanças que façam o kernel 170 + funcionar melhor para suas necessidades. 171 + 172 + - Quando o código é mantido à parte, sempre existe a possibilidade de que 173 + terceiros contribuam para uma implementação diferente de uma funcionalidade 174 + parecida. Se isso acontecer, ter seu código integrado via merge se tornará 175 + muito mais difícil - ao ponto de ser impossível. Você enfrentará duas 176 + alternativas desagradáveis, (1) manter uma funcionalidade "out-of-tree" 177 + indefinidamente ou (2) abandonar seu código e migrar seus usuários para a 178 + versão na árvore principal ("in-tree"). 179 + 180 + - Contribuição de código é a ação fundamental que faz todo o processo 181 + funcionar. Ao contribuir com seu código você pode adicionar nova 182 + funcionalidade ao kernel e proporcionar capacidades e exemplos que podem ser 183 + usados por outros desenvolvedores de kernel. Se você desenvolveu código para 184 + o Linux (ou está pensando em desenvolver), você claramente tem interesse na 185 + continuidade do sucesso dessa plataforma; contribuição de código é uma das 186 + melhores maneiras de garantir esse sucesso. 187 + 188 + Todos os argumentos acima se aplicam a qualquer código "out-of-tree", incluindo 189 + código distribuído de maneira proprietária, em formato exclusivamente binário. 190 + Existem fatores adicionais que devem ser levados em consideração antes de 191 + qualquer distribuição de código de kernel apenas em binário, incluindo: 192 + 193 + - As questões legais da distribuição de kernel proprietário são, no melhor dos 194 + casos, confusas; muitos detentores de direitos autorais do kernel acreditam 195 + que a maioria dos módulos binários são produtos derivados do kernel e que, 196 + como resultado, sua distribuição é uma violação da Licença Pública Geral GNU 197 + ("GNU General Public License"), que será tratada com mais profundidade abaixo. 198 + Este autor não é um advogado, e nada neste documento pode ser considerado 199 + aconselhamento jurídico. O verdadeiro status de módulos privados ("closed 200 + source") só pode ser determinado judicialmente. Independentemente disso, a 201 + incerteza que cerca esses módulos existe. 202 + 203 + - Os módulos binários aumentam consideravelmente a dificuldade de depuração de 204 + problemas do kernel ("debugging"), a ponto de a maioria dos desenvolvedores 205 + de kernel sequer tentar. Portanto, a distribuição de módulos exclusivamente 206 + binários tornará mais difícil que os seus usuários recebam suporte. 207 + 208 + - O suporte também é mais difícil para distribuidores de módulos exclusivamente 209 + binários, que precisam fornecer uma versão do módulo para cada distribuição e 210 + cada versão do kernel que desejam suportar. Dezenas de versões de um único 211 + módulo podem ser necessárias para fornecer uma cobertura razoavelmente 212 + abrangente, e seus usuários terão que atualizar seu módulo separadamente 213 + sempre que atualizarem seu kernel. 214 + 215 + - Tudo o que foi dito acima sobre revisão de código se aplica em dobro ao 216 + código fechado. Como esse código não está disponível, ele não pode ter sido 217 + revisado pela comunidade e, sem dúvida, terá sérios problemas. 218 + 219 + Os fabricantes de sistemas embarcados, em particular, podem ser tentados a 220 + ignorar grande parte do que foi dito nesta seção, acreditando que estão 221 + lançando um produto autossuficiente que usa uma versão congelada do kernel e 222 + não requer mais desenvolvimento após o lançamento. Esse argumento ignora o 223 + valor de uma revisão de código abrangente e o valor de permitir que seus 224 + usuários adicionem recursos ao seu produto. Mas esses produtos também têm uma 225 + vida comercial limitada, após a qual uma nova versão deve ser lançada. Nesse 226 + ponto, os fornecedores cujo código está no "mainline" e bem mantido estarão em 227 + uma posição muito melhor para preparar o novo produto para o mercado 228 + rapidamente. 229 + 230 + Licenciamento 231 + ------------- 232 + 233 + Código é submetido ao kernel do Linux sob diversas licenças, mas todo ele deve 234 + ser compatível com a versão 2 da Licença Pública Geral GNU (GPLv2), que é a 235 + licença que cobre a distribuição do kernel como um todo. Na prática, isso 236 + significa que todas as contribuições de código são cobertas pela GPLv2 (com, 237 + opcionalmente, uma linguagem que permita a distribuição sob versões posteriores 238 + da GPL) ou pela licença BSD de três cláusulas. Quaisquer contribuições que não 239 + sejam cobertas por uma licença compatível não serão aceitas no kernel. 240 + 241 + A cessão de direitos autorais não é exigida (nem solicitada) para o código 242 + contribuído para o kernel. Todo o código incorporado ao kernel principal mantém 243 + sua titularidade original; como resultado, o kernel agora tem milhares de 244 + proprietários. 245 + 246 + Uma implicação dessa estrutura de propriedade é que qualquer tentativa de 247 + alterar o licenciamento do kernel está fadada ao fracasso quase certo. Existem 248 + poucos cenários práticos em que o acordo de todos os detentores de direitos 249 + autorais poderia ser obtido (ou seu código removido do kernel). Portanto, em 250 + particular, não há perspectiva de migração para a versão 3 da GPL em um futuro 251 + próximo. 252 + 253 + É imprescindível que todo o código contribuído para o kernel seja legitimamente 254 + software livre. Por esse motivo, código de contribuidores sem identidade 255 + conhecida ou contribuidores anônimos não será aceito. Todos os contribuidores 256 + são obrigados a "assinar" seu código, declarando que ele pode ser distribuído 257 + com o kernel sob a GPL. Código que não tenha sido licenciado como software 258 + livre por seu proprietário, ou que apresente risco de criar problemas 259 + relacionados a direitos autorais para o kernel (como código derivado de 260 + esforços de engenharia reversa sem as devidas salvaguardas) não pode ser 261 + contribuído. 262 + 263 + Questões sobre direitos autorais são comuns em listas de discussão de 264 + desenvolvimento Linux. Normalmente, essas perguntas recebem muitas respostas, 265 + mas é importante lembrar que as pessoas que respondem a essas perguntas não são 266 + advogados e não podem fornecer aconselhamento jurídico. Se você tiver dúvidas 267 + jurídicas relacionadas ao código-fonte do Linux, não há substituto para 268 + conversar com um advogado especializado nessa área. Confiar em respostas 269 + obtidas em listas de discussão técnicas é arriscado.
+576
Documentation/translations/pt_BR/process/changes.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + 4 + 5 + Requisitos mínimos para compilar o Kernel 6 + ++++++++++++++++++++++++++++++++++++++++++ 7 + 8 + Introdução 9 + =========== 10 + 11 + Este documento foi projetado para fornecer uma lista das versões mínimas 12 + de software necessárias para executar a versão atual do kernel. 13 + 14 + Este documento é originalmente baseado no meu arquivo 'Changes' para os kernels 15 + 2.0.x e portanto, deve créditos às mesmas pessoas que aquele arquivo (Jared 16 + Mauch, Axel Boldt, Alessandro Sigala e inúmeros outros usuários em toda a rede). 17 + 18 + Requisitos Mínimos Atuais 19 + **************************** 20 + 21 + Atualize para pelo menos estas revisões de software antes de pensar que 22 + encontrou um bug! Se não tiver certeza de qual versão está executando atualmente 23 + , o comando sugerido deve lhe informar. 24 + 25 + Novamente, tenha em mente que esta lista pressupõe que você já possui um kernel 26 + Linux em execução funcional. Além disso, nem todas as ferramentas são 27 + necessárias em todos os sistemas; obviamente, se você não possui nenhum hardware 28 + PC Card por exemplo, provavelmente não precisará se preocupar com o pcmciautils. 29 + 30 + ====================== =============== ======================================== 31 + Programa Versão mínima Comando para verificar a versão 32 + ====================== =============== ======================================== 33 + GNU C 8.1 gcc --version 34 + Clang/LLVM (optional) 15.0.0 clang --version 35 + Rust (optional) 1.78.0 rustc --version 36 + bindgen (optional) 0.65.1 bindgen --version 37 + GNU make 4.0 make --version 38 + bash 4.2 bash --version 39 + binutils 2.30 ld -v 40 + flex 2.5.35 flex --version 41 + bison 2.0 bison --version 42 + pahole 1.16 pahole --version 43 + util-linux 2.10o mount --version 44 + kmod 13 depmod -V 45 + e2fsprogs 1.41.4 e2fsck -V 46 + jfsutils 1.1.3 fsck.jfs -V 47 + xfsprogs 2.6.0 xfs_db -V 48 + squashfs-tools 4.0 mksquashfs -version 49 + btrfs-progs 0.18 btrfs --version 50 + pcmciautils 004 pccardctl -V 51 + quota-tools 3.09 quota -V 52 + PPP 2.4.0 pppd --version 53 + nfs-utils 1.0.5 showmount --version 54 + procps 3.2.0 ps --version 55 + udev 081 udevd --version 56 + grub 0.93 grub --version || grub-install --version 57 + mcelog 0.6 mcelog --version 58 + iptables 1.4.2 iptables -V 59 + openssl & libcrypto 1.0.0 openssl version 60 + bc 1.06.95 bc --version 61 + Sphinx\ [#f1]_ 3.4.3 sphinx-build --version 62 + GNU tar 1.28 tar --version 63 + gtags (opcional) 6.6.5 gtags --version 64 + mkimage (opcional) 2017.01 mkimage --version 65 + Python 3.9.x python3 --version 66 + GNU AWK (opcional) 5.1.0 gawk --version 67 + ====================== =============== ======================================== 68 + 69 + .. [#f1] O Sphinx é necessário apenas para gerar a documentação do Kernel. 70 + 71 + Compilação do Kernel 72 + ********************* 73 + 74 + GCC 75 + --- 76 + 77 + Os requisitos da versão do gcc podem variar dependendo do tipo de CPU 78 + do seu computador. 79 + 80 + Clang/LLVM (opcional) 81 + --------------------- 82 + 83 + A versão formal mais recente do clang e dos utilitários LLVM (de acordo com 84 + releases.llvm.org <https://releases.llvm.org>_) é suportada para a compilação 85 + de kernels. Versões anteriores não têm funcionamento garantido, e poderemos 86 + remover do kernel soluções de contorno (workarounds) que eram utilizadas para 87 + suportar versões mais antigas. Por favor, veja a documentação adicional em: 88 + ref:Building Linux with Clang/LLVM <kbuild_llvm>. 89 + 90 + Rust (opcional) 91 + --------------- 92 + 93 + É necessária uma versão recente do compilador Rust. 94 + 95 + Por favor, consulte Documentation/rust/quick-start.rst para obter instruções 96 + sobre como atender aos requisitos de compilação do suporte a Rust. Em 97 + particular, o alvo (target) rustavailable do Makefile é útil para verificar por 98 + que a cadeia de ferramentas (toolchain) Rust pode não estar sendo detectada. 99 + 100 + bindgen (opcional) 101 + ------------------ 102 + 103 + O ``bindgen`` é utilizado para gerar os vínculos (bindings) Rust para o lado C 104 + do kernel. Ele depende da ``libclang``. 105 + 106 + Make 107 + ---- 108 + 109 + Você precisará do GNU make 4.0 ou superior para compilar o kernel. 110 + 111 + Bash 112 + ---- 113 + 114 + Alguns scripts bash são usados para a compilação do kernel. 115 + É necessário o Bash 4.2 ou mais recente. 116 + 117 + Binutils 118 + -------- 119 + 120 + O binutils 2.30 ou mais recente é necessário para compilar o kernel. 121 + 122 + pkg-config 123 + ---------- 124 + 125 + O sistema de compilação, a partir da versão 4.18, requer o pkg-config para 126 + verificar as ferramentas kconfig instaladas e para determinar as configurações 127 + de flags para uso em make {g,x}config. Anteriormente, o pkg-config já era 128 + utilizado, mas não era verificado nem documentado. 129 + 130 + Flex 131 + ---- 132 + 133 + Desde o Linux 4.16, o sistema de compilação gera analisadores léxicos durante a 134 + compilação. Isso requer o flex 2.5.35 ou superior. 135 + 136 + 137 + Bison 138 + ----- 139 + 140 + Desde o Linux 4.16, o sistema de compilação gera analisadores sintáticos durante 141 + a compilação. Isso requer o bison 2.0 ou superior 142 + 143 + pahole 144 + ------ 145 + 146 + Desde o Linux 5.2, se CONFIG_DEBUG_INFO_BTF estiver selecionado, o sistema de 147 + compilação gera BTF (BPF Type Format) a partir do DWARF no vmlinux, e um pouco 148 + depois para os módulos do kernel também. Isso requer o pahole v1.16 ou superior. 149 + 150 + Ele pode ser encontrado nos pacotes ``dwarves`` ou ``pahole`` das 151 + distribuições, ou em https://fedorapeople.org/~acme/dwarves/. 152 + 153 + Perl 154 + ---- 155 + 156 + Você precisará do perl 5 e dos seguintes módulos: Getopt::Long, 157 + Getopt::Std, File::Basename e File::Find para compilar o kernel. 158 + 159 + Python 160 + ------ 161 + 162 + Várias opções de configuração o exigem: ele é necessário para as configurações 163 + padrão (defconfigs) de arm/arm64, CONFIG_LTO_CLANG, algumas configurações 164 + opcionais de DRM, a ferramenta kernel-doc e a geração da documentação (Sphinx), 165 + entre outros. 166 + 167 + BC 168 + -- 169 + 170 + Você precisará do bc para compilar kernels 3.10 ou superior. 171 + 172 + 173 + OpenSSL 174 + ------- 175 + 176 + A assinatura de módulos e a manipulação de certificados externos utilizam o 177 + programa OpenSSL e a biblioteca de criptografia para realizar a criação de 178 + chaves e a geração de assinaturas. 179 + 180 + Você precisará do openssl para compilar kernels 3.7 e superiores se a assinatura 181 + de módulos estiver habilitada. Você também precisará dos pacotes de 182 + desenvolvimento do openssl para compilar kernels 4.3 e superiores. 183 + 184 + Tar 185 + --- 186 + 187 + O GNU tar é necessário caso você deseje habilitar o acesso aos cabeçalhos do 188 + kernel via sysfs (CONFIG_IKHEADERS). 189 + 190 + gtags / GNU GLOBAL (optional) 191 + ----------------------------- 192 + 193 + A compilação do kernel requer o GNU GLOBAL versão 6.6.5 ou superior para gerar 194 + arquivos de tags através de make gtags. Isso se deve ao uso da flag -C 195 + (--directory) pelo gtags. 196 + 197 + mkimage 198 + ------- 199 + 200 + Esta ferramenta é utilizada ao gerar uma Flat Image Tree (FIT), comumente usada 201 + em plataformas ARM. A ferramenta está disponível através do pacote u-boot-tools 202 + ou pode ser compilada a partir do código-fonte do U-Boot. Veja as instruções em 203 + https://docs.u-boot.org/en/latest/build/tools.html#building-tools-for-linux 204 + 205 + GNU AWK 206 + ------- 207 + 208 + O GNU AWK é necessário caso você deseje que a compilação do kernel gere dados de 209 + intervalo de endereços para 210 + módulos integrados (CONFIG_BUILTIN_MODULE_RANGES). 211 + 212 + Utilitários de sistema 213 + *********************** 214 + 215 + Mudanças de arquitetura 216 + ------------------------ 217 + 218 + O DevFS tornou-se obsoleto em favor do udev 219 + (https://www.kernel.org/pub/linux/utils/kernel/hotplug/) 220 + 221 + O suporte a UIDs de 32 bits já está implementado. Divirta-se! 222 + 223 + A documentação das funções do Linux está migrando para a documentação embutida 224 + (inline), por meio de comentários com formatação especial próximos às suas 225 + definições no código-fonte. Esses comentários podem ser combinados com arquivos 226 + ReST no diretório Documentation/ para criar uma documentação enriquecida, que 227 + pode então ser convertida para arquivos PostScript, HTML, LaTeX, ePUB e PDF. 228 + Para converter do formato ReST para o formato de sua escolha,você precisará do 229 + Sphinx. 230 + 231 + Util-linux 232 + ---------- 233 + 234 + Novas versões do util-linux oferecem suporte no fdisk para discos maiores, 235 + suporte a novas opções para o mount, reconhecimento de mais tipos de partição e 236 + outras funcionalidades interessantes. Você provavelmente vai querer atualizar. 237 + 238 + Ksymoops 239 + -------- 240 + 241 + Se o impensável acontecer e o seu kernel sofrer um oops, você pode precisar da 242 + ferramenta ksymoops para decodificá-lo, mas na maioria dos casos, não será 243 + necessário. É geralmente preferível compilar o kernel com CONFIG_KALLSYMS para 244 + que ele produza dumps legíveis que possam ser usados no estado em que se 245 + encontram (isso também gera uma saída melhor do que a do ksymoops). 246 + Se por algum motivo o seu kernel não for compilado com CONFIG_KALLSYMS e você 247 + não tiver como recompilar e reproduzir o oops com essa opção, você ainda poderá 248 + decodificá-lo com o ksymoops. 249 + 250 + Mkinitrd 251 + -------- 252 + 253 + Estas mudanças no layout da árvore de arquivos /lib/modules também exigem que o 254 + mkinitrd seja atualizado. 255 + 256 + E2fsprogs 257 + --------- 258 + 259 + A versão mais recente do e2fsprogs corrige diversos bugs no fsck e no debugfs. 260 + Obviamente, é uma boa ideia atualizar. 261 + 262 + JFSutils 263 + -------- 264 + 265 + O pacote jfsutils contém os utilitários para o sistema de arquivos. Os seguintes 266 + utilitários estão disponíveis: 267 + 268 + - ``fsck.jfs`` - inicia a reprodução (replay) do log de transações, além de 269 + verificar e reparar uma partição formatada em JFS. 270 + 271 + - ``mkfs.jfs`` - cria uma partição formatada em JFS. 272 + 273 + - Para o seu arquivo changes.rst, a tradução técnica adequada é: 274 + 275 + Outros utilitários de sistema de arquivos também estão disponíveis neste pacote. 276 + 277 + Xfsprogs 278 + -------- 279 + 280 + A versão mais recente do ``xfsprogs`` contém os utilitários ``mkfs.xfs``, 281 + ``xfs_db`` e ``xfs_repair``, entre outros, para o sistema de arquivos XFS. Ele é 282 + independente de arquitetura e qualquer versão a partir da 2.0.0 deve funcionar 283 + corretamente com esta versão do código do kernel XFS (recomenda-se a 284 + versão 2.6.0 ou posterior, devido a algumas melhorias significativas). 285 + 286 + PCMCIAutils 287 + ----------- 288 + 289 + O PCMCIAutils substitui o pcmcia-cs. Ele configura corretamente os sockets 290 + PCMCIA na inicialização do sistema e carrega os módulos apropriados para 291 + dispositivos PCMCIA de 16 bits, caso o kernel esteja modularizado e o subsistema 292 + de hotplug seja utilizado. 293 + 294 + Quota-tools 295 + ----------- 296 + 297 + O suporte a UIDs e GIDs de 32 bits é necessário caso você deseje utilizar o 298 + formato de cota versão 2 mais recente. O quota-tools versão 3.07 e superiores 299 + possuem esse suporte. Utilize a versão recomendada ou superior da tabela acima. 300 + 301 + Intel IA32 microcode 302 + -------------------- 303 + 304 + Um driver foi adicionado para permitir a atualização do microcódigo Intel IA32, 305 + acessível como um dispositivo de caracteres comum (misc). Se você não estiver 306 + usando o udev, você poderá precisar de:: 307 + 308 + mkdir /dev/cpu 309 + mknod /dev/cpu/microcode c 10 184 310 + chmod 0644 /dev/cpu/microcode 311 + 312 + Se você não estiver usando o udev, você poderá precisar executar os comandos 313 + acima como root antes de poder usar isso. Você provavelmente também desejará 314 + obter o utilitário de espaço de usuário ``microcode_ctl`` para utilizar em 315 + conjunto com este driver. 316 + 317 + udev 318 + ---- 319 + 320 + O udev é uma aplicação de espaço de usuário para popular o diretório /dev 321 + dinamicamente, apenas com entradas para dispositivos de fat presentes no 322 + sistema. O udev substitui a funcionalidade básica do devfs, permitindo ao mesmo 323 + tempo a nomeação persistente de dispositivos. 324 + 325 + FUSE 326 + ---- 327 + 328 + Necessita do libfuse 2.4.0 ou posterior. O mínimo absoluto é a versão 2.3.0, 329 + mas as opções de montagem direct_io e kernel_cache não funcionarão. 330 + 331 + Redes 332 + ****** 333 + 334 + Mudanças gerais 335 + ---------------- 336 + 337 + Caso você tenha necessidades avançadas de configuração de rede, você deve 338 + provavelmente considerar o uso das ferramentas de rede do iproute2. 339 + 340 + Filtro de Pacotes / NAT 341 + ------------------------ 342 + 343 + O código de filtragem de pacotes e NAT utiliza as mesmas ferramentas da série 344 + anterior de kernels 2.4.x (iptables). Ele ainda inclui módulos de 345 + retrocompatibilidade para o ipchains (estilo 2.2.x) e o ipfwadm (estilo 2.0.x). 346 + 347 + PPP 348 + --- 349 + 350 + O driver PPP foi reestruturado para suportar multilink e permitir que opere 351 + sobre diversas camadas de mídia. Se você utiliza PPP, atualize o pppd para, no 352 + mínimo, a versão 2.4.0. 353 + 354 + Se você não estiver usando o udev, você deve possuir o arquivo de dispositivo 355 + ``/dev/ppp``, o qual pode ser criado por:: 356 + 357 + mknod /dev/ppp c 108 0 358 + 359 + como root. 360 + 361 + NFS-utils 362 + --------- 363 + 364 + Em kernels antigos (2.4 e anteriores), o servidor NFS precisava conhecer 365 + qualquer cliente que pretendesse acessar arquivos via NFS. Essa informação era 366 + fornecida ao kernel pelo mountd quando o cliente montava o sistema de arquivos, 367 + ou pelo exportfs na inicialização do sistema. O exportfs obtinha informações 368 + sobre clientes ativos a partir de /var/lib/nfs/rmtab. 369 + 370 + Esta abordagem é bastante frágil, pois depende da integridade do rmtab, o que 371 + nem sempre é fácil, particularmente ao tentar implementar fail-over. Mesmo 372 + quando o sistema está funcionando bem, o rmtab sofre com o acúmulo de muitas 373 + entradas antigas que nunca são removidas. 374 + 375 + Com kernels modernos, temos a opção de fazer o kernel informar ao mountd quando 376 + recebe uma requisição de um host desconhecido, permitindo que o mountd forneça 377 + as informações de exportação apropriadas ao kernel. Isso remove a dependência do 378 + rmtab e significa que o kernel só precisa conhecer os clientes ativos no 379 + momento. 380 + 381 + Para habilitar esta nova funcionalidade, você precisa:: 382 + 383 + mount -t nfsd nfsd /proc/fs/nfsd 384 + 385 + antes de executar o exportfs ou o mountd. Recomenda-se que todos os serviços NFS 386 + sejam protegidos da internet em geral por um firewall, sempre que possível. 387 + 388 + mcelog 389 + ------ 390 + 391 + Em kernels x86, o utilitário mcelog é necessário para processar e registrar 392 + eventos de machine check quando opção CONFIG_X86_MCE está ativada. Eventos de 393 + machine check são erros relatados pela CPU. O processamento desses eventos é 394 + fortemente recomendado. 395 + 396 + Documentação do Kernel 397 + *********************** 398 + 399 + Sphinx 400 + ------ 401 + 402 + Por favor, consulte Documentation/doc-guide/sphinx.rst para detalhes sobre os 403 + requisitos do Sphinx. 404 + 405 + rustdoc 406 + ------- 407 + 408 + O rustdoc é utilizado para gerar a documentação para código Rust. Por favor, 409 + consulte Documentation/rust/general-information.rst para mais informações. 410 + 411 + Obtendo software atualizado 412 + ============================ 413 + 414 + Compilação do kernel 415 + ********************** 416 + 417 + gcc 418 + --- 419 + 420 + - <ftp://ftp.gnu.org/gnu/gcc/> 421 + 422 + Clang/LLVM 423 + ---------- 424 + 425 + - :ref:`Getting LLVM <getting_llvm>`. 426 + 427 + Rust 428 + ---- 429 + 430 + - Documentation/rust/quick-start.rst. 431 + 432 + bindgen 433 + ------- 434 + 435 + - Documentation/rust/quick-start.rst. 436 + 437 + Make 438 + ---- 439 + 440 + - <ftp://ftp.gnu.org/gnu/make/> 441 + 442 + Bash 443 + ---- 444 + 445 + - <ftp://ftp.gnu.org/gnu/bash/> 446 + 447 + Binutils 448 + -------- 449 + 450 + - <https://www.kernel.org/pub/linux/devel/binutils/> 451 + 452 + Flex 453 + ---- 454 + 455 + - <https://github.com/westes/flex/releases> 456 + 457 + Bison 458 + ----- 459 + 460 + - <ftp://ftp.gnu.org/gnu/bison/> 461 + 462 + OpenSSL 463 + ------- 464 + 465 + - <https://www.openssl.org/> 466 + 467 + System utilities 468 + **************** 469 + 470 + Util-linux 471 + ---------- 472 + 473 + - <https://www.kernel.org/pub/linux/utils/util-linux/> 474 + 475 + Kmod 476 + ---- 477 + 478 + - <https://www.kernel.org/pub/linux/utils/kernel/kmod/> 479 + - <https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git> 480 + 481 + Ksymoops 482 + -------- 483 + 484 + - <https://www.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/> 485 + 486 + Mkinitrd 487 + -------- 488 + 489 + - <https://code.launchpad.net/initrd-tools/main> 490 + 491 + E2fsprogs 492 + --------- 493 + 494 + - <https://www.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/> 495 + - <https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/> 496 + 497 + JFSutils 498 + -------- 499 + 500 + - <https://jfs.sourceforge.net/> 501 + 502 + Xfsprogs 503 + -------- 504 + 505 + - <https://git.kernel.org/pub/scm/fs/xfs/xfsprogs-dev.git> 506 + - <https://www.kernel.org/pub/linux/utils/fs/xfs/xfsprogs/> 507 + 508 + Pcmciautils 509 + ----------- 510 + 511 + - <https://www.kernel.org/pub/linux/utils/kernel/pcmcia/> 512 + 513 + Quota-tools 514 + ----------- 515 + 516 + - <https://sourceforge.net/projects/linuxquota/> 517 + 518 + 519 + Intel P6 microcode 520 + ------------------ 521 + 522 + - <https://downloadcenter.intel.com/> 523 + 524 + udev 525 + ---- 526 + 527 + - <https://www.freedesktop.org/software/systemd/man/udev.html> 528 + 529 + FUSE 530 + ---- 531 + 532 + - <https://github.com/libfuse/libfuse/releases> 533 + 534 + mcelog 535 + ------ 536 + 537 + - <https://www.mcelog.org/> 538 + 539 + Redes 540 + ****** 541 + 542 + PPP 543 + --- 544 + 545 + - <https://download.samba.org/pub/ppp/> 546 + - <https://git.ozlabs.org/?p=ppp.git> 547 + - <https://github.com/paulusmack/ppp/> 548 + 549 + NFS-utils 550 + --------- 551 + 552 + - <https://sourceforge.net/project/showfiles.php?group_id=14> 553 + - <https://nfs.sourceforge.net/> 554 + 555 + Iptables 556 + -------- 557 + 558 + - <https://netfilter.org/projects/iptables/index.html> 559 + 560 + Ip-route2 561 + --------- 562 + 563 + - <https://www.kernel.org/pub/linux/utils/net/iproute2/> 564 + 565 + OProfile 566 + -------- 567 + 568 + - <https://oprofile.sf.net/download/> 569 + 570 + Kernel documentation 571 + ******************** 572 + 573 + Sphinx 574 + ------ 575 + 576 + - <https://www.sphinx-doc.org/>
+40
Documentation/translations/pt_BR/process/conclave.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + Continuidade do projeto do kernel Linux 4 + ======================================= 5 + 6 + O projeto de desenvolvimento do kernel Linux é amplamente distribuído, com mais de 7 + 100 mantenedores, cada um trabalhando para manter as mudanças fluindo através de 8 + seus próprios repositórios. A etapa final, no entanto, é centralizada, onde as 9 + mudanças são puxadas para o repositório mainline. Isso é normalmente feito por 10 + Linus Torvalds mas, como foi demonstrado pelo lançamento da versão 4.19 em 2018, 11 + existem outros que podem realizar esse trabalho quando surge a necessidade. 12 + 13 + Caso os mantenedores desse repositório se tornem indispostos ou incapazes de 14 + realizar esse trabalho daqui em diante (incluindo a facilitação de uma transição), 15 + o projeto precisará encontrar um ou mais substitutos sem demora. O processo pelo 16 + qual isso será feito está listado abaixo. O $ORGANIZER é o último organizador do 17 + Maintainer Summit ou o atual presidente do Conselho Consultivo Técnico (TAB) da 18 + Linux Foundation (LF) como reserva. 19 + 20 + - Em até 72 horas, o $ORGANIZER abrirá uma discussão com os convidados do 21 + Maintainer Summit concluído mais recentemente. Uma reunião desses convidados e 22 + do TAB, seja online ou presencial, será agendada o mais rápido possível de uma 23 + forma que maximize o número de pessoas que possam participar. 24 + 25 + - Se não houver ocorrido um Maintainer Summit nos últimos 15 meses, o conjunto de 26 + convidados para esta reunião será determinado pelo TAB. 27 + 28 + - Os convidados para esta reunião podem trazer outros mantenedores conforme 29 + necessário. 30 + 31 + - Esta reunião, presidida pelo $ORGANIZER, considerará opções para a gestão 32 + contínua do repositório de nível superior do kernel, de forma consistente com 33 + a expectativa de maximizar a saúde a longo prazo do projeto e de sua comunidade. 34 + 35 + - Em até duas semanas, um representante deste grupo comunicará à comunidade em 36 + geral, utilizando a lista de discussão ksummit@lists.linux.dev, quais serão os 37 + próximos passos. 38 + 39 + A Linux Foundation, conforme orientada pelo TAB, tomará as medidas necessárias 40 + para apoiar e implementar este plano.
+637
Documentation/translations/pt_BR/process/howto.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + .. _pt_process_howto: 4 + 5 + COMO FAZER o desenvolvimento do kernel Linux 6 + ============================================ 7 + 8 + Este é o documento definitivo sobre este tópico. Ele contém instruções 9 + sobre como se tornar um desenvolvedor do kernel Linux e como aprender a 10 + trabalhar com a comunidade de desenvolvimento do kernel Linux. Ele tenta 11 + não conter nada relacionado aos aspectos técnicos da programação do kernel, 12 + mas ajudará a apontar a direção certa para isso. 13 + 14 + Se algo neste documento ficar desatualizado, por favor, envie patches para 15 + o mantenedor deste arquivo, que está listado no final do documento. 16 + 17 + 18 + Introdução 19 + ------------ 20 + 21 + Então, você quer aprender como se tornar um desenvolvedor do kernel Linux? 22 + Ou o seu gerente lhe disse: "Vá escrever um driver Linux para este 23 + dispositivo". O objetivo deste documento é ensinar tudo o que você precisa 24 + saber para conseguir isso, descrevendo o processo pelo qual você deve passar 25 + e oferecendo dicas sobre como trabalhar com a comunidade. Ele também tentará 26 + explicar algumas das razões pelas quais a comunidade trabalha da forma que 27 + trabalha. 28 + 29 + O kernel é escrito principalmente em C, com algumas partes dependentes de 30 + arquitetura escritas em assembly. Um bom entendimento de C é necessário para 31 + o desenvolvimento do kernel. O conhecimento de Assembly (de qualquer 32 + arquitetura) não é obrigatório, a menos que você planeje fazer 33 + desenvolvimento de baixo nível para essa arquitetura específica. Embora não 34 + sejam um substituto para uma formação sólida em C e/ou anos de experiência, 35 + os seguintes livros são bons para, no mínimo, referência: 36 + 37 + - "The C Programming Language" por Kernighan e Ritchie [Prentice Hall] 38 + 39 + - "Practical C Programming" por Steve Oualline [O'Reilly] 40 + 41 + - "C: A Reference Manual" por Harbison e Steele [Prentice Hall] 42 + 43 + O kernel é escrito usando o GNU C e a GNU toolchain. Embora ele siga o 44 + padrão ISO C11, ele utiliza uma série de extensões que não estão presentes 45 + no padrão. O kernel é um ambiente C independente (freestanding), sem 46 + dependência da biblioteca C padrão (libc), portanto, algumas partes do 47 + padrão C não são suportadas. Divisões arbitrárias de "long long" e ponto 48 + flutuante não são permitidas. Às vezes, pode ser difícil entender as 49 + suposições que o kernel faz sobre a toolchain e as extensões que ele utiliza 50 + e, infelizmente, não existe uma referência definitiva para elas. Por favor, 51 + verifique as páginas de informações do gcc (`info gcc`) para obter algumas 52 + informações sobre elas. 53 + 54 + Por favor, lembre-se de que você está tentando aprender como trabalhar com a 55 + comunidade de desenvolvimento existente. É um grupo diversificado de pessoas, 56 + com altos padrões de codificação, estilo e procedimento. Esses padrões foram 57 + criados ao longo do tempo com base no que se descobriu funcionar melhor para 58 + uma equipe tão grande e geograficamente dispersa. Tente aprender o máximo 59 + possível sobre esses padrões com antecedência, pois eles estão bem 60 + documentados; não espere que as pessoas se adaptem a você ou à forma de fazer 61 + as coisas da sua empresa. 62 + 63 + 64 + Questões Legais 65 + --------------- 66 + 67 + O código-fonte do kernel Linux é lançado sob a GPL. Por favor, veja o arquivo 68 + COPYING no diretório principal da árvore de fontes. As regras de licenciamento 69 + do kernel Linux e como usar os identificadores `SPDX <https://spdx.org/>`_ no 70 + código-fonte estão descritas em :ref:`Documentation/process/license-rules.rst <kernel_licensing>`. 71 + Se você tiver mais perguntas sobre a licença, por favor, entre em contato com 72 + um advogado e não pergunte na lista de discussão do kernel Linux. As pessoas 73 + nas listas de discussão não são advogados e você não deve confiar em suas 74 + declarações sobre assuntos jurídicos. 75 + 76 + Para perguntas e respostas comuns sobre a GPL, por favor, veja: 77 + 78 + https://www.gnu.org/licenses/gpl-faq.html 79 + 80 + 81 + Documentação 82 + ------------ 83 + 84 + A árvore de fontes do kernel Linux possui uma vasta gama de documentos que 85 + são inestimáveis para aprender como interagir com a comunidade do kernel. 86 + Quando novos recursos são adicionados ao kernel, recomenda-se que novos 87 + arquivos de documentação também sejam adicionados explicando como usar o 88 + recurso. Quando uma mudança no kernel faz com que a interface que o kernel 89 + expõe para o espaço do usuário (userspace) mude, recomenda-se que você envie 90 + a informação ou um patch para as páginas de manual explicando a mudança para 91 + o mantenedor das páginas de manual em alx@kernel.org, e coloque em cópia (CC) 92 + a lista linux-api@vger.kernel.org. 93 + 94 + Aqui está uma lista de arquivos que estão na árvore de fontes do kernel e 95 + que são de leitura obrigatória: 96 + 97 + :ref:`Documentation/admin-guide/README.rst <readme>` 98 + Este arquivo fornece um breve histórico sobre o kernel Linux e descreve 99 + o que é necessário fazer para configurar e compilar o kernel. Pessoas 100 + que são novas no kernel devem começar por aqui. 101 + 102 + :doc:`changes` 103 + Este arquivo fornece uma lista das versões mínimas de vários pacotes de 104 + software que são necessários para compilar e executar o kernel com 105 + sucesso. 106 + 107 + :ref:`Documentation/process/coding-style.rst <codingstyle>` 108 + Este documento descreve o estilo de codificação do kernel Linux e parte 109 + da fundamentação por trás dele. Espera-se que todo código novo siga as 110 + diretrizes deste documento. A maioria dos mantenedores apenas aceitará 111 + patches se essas regras forem seguidas, e muitas pessoas apenas 112 + revisarão o código se ele estiver no estilo adequado. 113 + 114 + :ref:`Documentation/process/submitting-patches.rst <submittingpatches>` 115 + Este arquivo descreve em detalhes explícitos como criar e enviar 116 + um patch com sucesso, incluindo (mas não limitado a): 117 + 118 + - Conteúdo do e-mail 119 + - Formato do e-mail 120 + - Para quem enviá-lo 121 + 122 + Seguir estas regras não garantirá o sucesso (já que todos os patches 123 + estão sujeitos a um escrutínio de conteúdo e estilo), mas não segui-las 124 + quase sempre o impedirá. 125 + 126 + Outras excelentes descrições de como criar patches adequadamente são: 127 + 128 + "O Patch Perfeito" 129 + https://www.ozlabs.org/~akpm/stuff/tpp.txt 130 + 131 + "Formato de Submissão de Patch do Kernel Linux" 132 + https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html 133 + 134 + :ref:`Documentation/process/stable-api-nonsense.rst <stable_api_nonsense>` 135 + Este arquivo descreve a justificativa por trás da decisão consciente de 136 + não ter uma API estável dentro do kernel, incluindo pontos como: 137 + 138 + - Camadas de adaptação (shim-layers) de subsistemas (para compatibilidade?) 139 + - Portabilidade de drivers entre sistemas operacionais. 140 + - Mitigação de mudanças rápidas dentro da árvore de fontes do kernel 141 + (ou impedimento de mudanças rápidas). 142 + 143 + Este documento é crucial para compreender a filosofia de desenvolvimento 144 + do Linux e é muito importante para pessoas que estão migrando para o 145 + Linux vindas do desenvolvimento em outros Sistemas Operacionais. 146 + 147 + :ref:`Documentation/process/security-bugs.rst <securitybugs>` 148 + Se você acredita ter encontrado um problema de segurança no kernel Linux, 149 + por favor, siga os passos descritos neste documento para ajudar a 150 + notificar os desenvolvedores do kernel e auxiliar na resolução do problema. 151 + 152 + :ref:`Documentation/process/management-style.rst <managementstyle>` 153 + Este documento descreve como os mantenedores do kernel Linux operam e o 154 + ethos compartilhado por trás de suas metodologias. Esta é uma leitura 155 + importante para qualquer pessoa nova no desenvolvimento do kernel (ou 156 + para qualquer pessoa simplesmente curiosa sobre isso), pois resolve muitos 157 + equívocos comuns e confusões sobre o comportamento único dos mantenedores 158 + do kernel. 159 + 160 + :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>` 161 + Este arquivo descreve as regras sobre como ocorrem os lançamentos das 162 + versões estáveis (stable) do kernel e o que fazer se você desejar que 163 + uma alteração seja incluída em um desses lançamentos. 164 + 165 + :ref:`Documentation/process/kernel-docs.rst <kernel_docs>` 166 + Uma lista de documentação externa que pertence ao desenvolvimento do 167 + kernel. Por favor, consulte esta lista caso não encontre o que está 168 + procurando dentro da documentação interna do kernel. 169 + 170 + :ref:`Documentation/process/applying-patches.rst <applying_patches>` 171 + Uma boa introdução descrevendo exatamente o que é um patch e como 172 + aplicá-lo aos diferentes ramos (branches) de desenvolvimento do kernel. 173 + 174 + O kernel também possui um grande número de documentos que podem ser 175 + gerados automaticamente a partir do próprio código-fonte ou de 176 + marcações ReStructuredText (ReST), como esta. Isso inclui uma 177 + descrição completa da API interna do kernel e regras sobre como 178 + manipular o bloqueio (locking) corretamente. 179 + 180 + Todos esses documentos podem ser gerados em formato PDF ou HTML ao 181 + executar:: 182 + 183 + make pdfdocs 184 + make htmldocs 185 + 186 + respectivamente, a partir do diretório principal do código-fonte do kernel. 187 + 188 + Os documentos que utilizam a marcação ReST serão gerados em 189 + Documentation/output. Eles também podem ser gerados nos formatos 190 + LaTeX e ePub com:: 191 + 192 + make latexdocs 193 + make epubdocs 194 + 195 + Como se tornar um desenvolvedor do kernel 196 + ------------------------------------------ 197 + 198 + Se você não sabe nada sobre o desenvolvimento do kernel Linux, você deve 199 + consultar o projeto Linux KernelNewbies: 200 + 201 + https://kernelnewbies.org 202 + 203 + Ele consiste em uma lista de discussão útil onde você pode fazer quase 204 + qualquer tipo de pergunta básica sobre o desenvolvimento do kernel 205 + (certifique-se de pesquisar nos arquivos primeiro, antes de perguntar 206 + algo que já foi respondido no passado). Ele também possui um canal de 207 + IRC que você pode usar para fazer perguntas em tempo real, e muita 208 + documentação útil para aprender sobre o desenvolvimento do kernel Linux. 209 + 210 + O site possui informações básicas sobre a organização do código, 211 + subsistemas e projetos atuais (tanto in-tree quanto out-of-tree). 212 + Também descreve algumas informações logísticas básicas, como por exemplo, 213 + como compilar um kernel e aplicar um patch. 214 + 215 + Se você não sabe por onde começar, mas deseja procurar alguma tarefa 216 + para iniciar sua integração na comunidade de desenvolvimento do kernel, 217 + acesse o projeto Linux Kernel Janitor: 218 + 219 + https://kernelnewbies.org/KernelJanitors 220 + 221 + É um ótimo lugar para começar. Ele descreve uma lista de problemas 222 + relativamente simples que precisam ser limpos e corrigidos dentro da 223 + árvore de códigos-fonte do kernel Linux. Ao trabalhar com os 224 + desenvolvedores responsáveis por este projeto, você aprenderá o básico 225 + sobre como incluir seu patch na árvore do kernel Linux e, 226 + possivelmente, será orientado sobre o que trabalhar em seguida, caso 227 + ainda não tenha uma ideia. 228 + 229 + Antes de fazer qualquer modificação real no código do kernel Linux, é 230 + imperativo entender como o código em questão funciona. Para esse 231 + propósito, nada é melhor do que lê-lo diretamente (a maioria das partes 232 + complexas está bem comentada), talvez até com a ajuda de ferramentas 233 + especializadas. Uma ferramenta particularmente recomendada é o projeto 234 + Linux Cross-Reference, que é capaz de apresentar o código-fonte em um 235 + formato de página web indexada e auto-referenciada. Um excelente 236 + repositório atualizado do código do kernel pode ser encontrado em: 237 + 238 + https://elixir.bootlin.com/ 239 + 240 + 241 + O processo de desenvolvimento 242 + ----------------------------- 243 + 244 + O processo de desenvolvimento do kernel Linux consiste atualmente em algumas 245 + "branches" (ramos) principais diferentes e muitos ramos de subsistemas 246 + específicos. Esses diferentes ramos são: 247 + 248 + - Árvore principal (mainline) do Linus 249 + - Várias árvores estáveis com múltiplos números de versão principal 250 + - Árvores específicas de subsistemas 251 + - Árvore de testes de integração linux-next 252 + 253 + Árvore principal (Mainline tree) 254 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 255 + 256 + A árvore principal é mantida por Linus Torvalds e pode ser encontrada em 257 + https://kernel.org ou no repositório. Seu processo de desenvolvimento é 258 + o seguinte: 259 + 260 + - Assim que um novo kernel é lançado, uma janela de duas semanas é aberta; 261 + durante esse período, os mantenedores podem enviar grandes diffs para 262 + Linus, geralmente patches que já foram incluídos na linux-next por algumas 263 + semanas. A forma preferida de enviar grandes mudanças é usando o git 264 + (a ferramenta de gerenciamento de código-fonte do kernel, mais informações 265 + podem ser encontradas em https://git-scm.com/), mas patches simples 266 + também são aceitos. 267 + - Após duas semanas, um kernel -rc1 é lançado e o foco passa a ser tornar 268 + o novo kernel o mais sólido possível. A maioria dos patches neste estágio 269 + deve corrigir uma regressão. Bugs que sempre existiram não são regressões, 270 + portanto, envie esses tipos de correções apenas se forem importantes. 271 + Observe que um driver (ou sistema de arquivos) totalmente novo pode ser 272 + aceito após o -rc1 porque não há risco de causar regressões com tal 273 + mudança, desde que a alteração seja autocontida e não afete áreas fora do 274 + código que está sendo adicionado. O git pode ser usado para enviar 275 + patches para Linus após o lançamento do -rc1, mas os patches também 276 + precisam ser enviados para uma lista de discussão pública para revisão. 277 + - Um novo -rc é lançado sempre que Linus considerar que a árvore git atual 278 + está em um estado razoavelmente estável e adequado para testes. O objetivo 279 + é lançar um novo kernel -rc a cada semana. 280 + - O processo continua até que o kernel seja considerado "pronto"; o 281 + processo deve durar cerca de 6 semanas. 282 + 283 + Vale a pena mencionar o que Andrew Morton escreveu na lista de discussão 284 + do kernel Linux sobre os lançamentos do kernel: 285 + 286 + *"Ninguém sabe quando um kernel será lançado, porque ele é 287 + lançado de acordo com o status percebido dos bugs, não de acordo 288 + com um cronograma pré-concebido."* 289 + 290 + Várias árvores estáveis com múltiplos números de versão principal 291 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 292 + 293 + Kernels com versões de 3 partes são kernels -stable (estáveis). Eles 294 + contêm correções relativamente pequenas e críticas para problemas de 295 + segurança ou regressões significativas descobertas em um determinado 296 + lançamento principal da árvore mainline. Cada lançamento em uma série 297 + estável principal incrementa a terceira parte do número da versão, 298 + mantendo as duas primeiras partes iguais. 299 + 300 + Este é o ramo recomendado para usuários que desejam o kernel estável 301 + mais recente e não estão interessados em ajudar a testar versões de 302 + desenvolvimento ou experimentais. 303 + 304 + As árvores estáveis são mantidas pela equipe "stable" 305 + <stable@vger.kernel.org> e são lançadas conforme a necessidade exigir. 306 + O período normal de lançamento é de aproximadamente duas semanas, mas 307 + pode ser mais longo se não houver problemas urgentes. Por outro lado, 308 + um problema relacionado à segurança pode fazer com que um lançamento 309 + ocorra quase instantaneamente. 310 + 311 + O arquivo :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>` 312 + na árvore do kernel documenta quais tipos de mudanças são aceitáveis para 313 + a árvore -stable e como o processo de lançamento funciona. 314 + 315 + Árvores específicas de subsistemas 316 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 317 + 318 + Os mantenedores dos vários subsistemas do kernel — e também muitos 319 + desenvolvedores de subsistemas do kernel — expõem seu estado atual de 320 + desenvolvimento em repositórios de código-fonte. Dessa forma, outros 321 + podem ver o que está acontecendo nas diferentes áreas do kernel. Em 322 + áreas onde o desenvolvimento é rápido, um desenvolvedor pode ser 323 + solicitado a basear suas submissões em tal árvore de subsistema do 324 + kernel para que conflitos entre a submissão e outros trabalhos já em 325 + andamento sejam evitados. 326 + 327 + A maioria desses repositórios são árvores git, mas também existem outros 328 + SCMs em uso, ou filas de patches sendo publicadas como séries quilt. Os 329 + endereços desses repositórios de subsistemas estão listados no arquivo 330 + MAINTAINERS. Muitos deles podem ser navegados em https://git.kernel.org/. 331 + 332 + Antes que um patch proposto seja incluído em tal árvore de subsistema, 333 + ele está sujeito a uma revisão que ocorre principalmente em listas de 334 + discussão (veja a seção respectiva abaixo). Para vários subsistemas do 335 + kernel, este processo de revisão é rastreado com a ferramenta patchwork. 336 + O Patchwork oferece uma interface web que mostra as postagens de patches, 337 + quaisquer comentários sobre um patch ou revisões feitas a ele, e os 338 + mantenedores podem marcar os patches como "sob revisão", "aceitos" ou 339 + "rejeitados". A maioria desses sites patchwork está listada em 340 + https://patchwork.kernel.org/. 341 + 342 + Árvore de testes de integração linux-next 343 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 344 + 345 + Antes que as atualizações das árvores de subsistemas sejam mescladas na 346 + árvore mainline, elas precisam ser testadas quanto à integração. Para 347 + este propósito, existe um repositório de testes especial no qual 348 + praticamente todas as árvores de subsistemas são integradas (pulled) 349 + quase diariamente: 350 + 351 + https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git 352 + 353 + Dessa forma, a linux-next oferece uma visão resumida do que se espera 354 + que entre no kernel mainline no próximo período de mesclagem (merge 355 + window). Testadores aventureiros são muito bem-vindos para testar a 356 + linux-next em tempo de execução. 357 + 358 + 359 + Relato de Bugs 360 + -------------- 361 + 362 + O arquivo 'Documentation/admin-guide/reporting-issues.rst' no diretório 363 + principal de códigos-fonte do kernel descreve como relatar um possível 364 + bug no kernel e detalha que tipo de informação é necessária para os 365 + desenvolvedores do kernel ajudarem a rastrear o problema. 366 + 367 + Gerenciando relatos de bugs 368 + --------------------------- 369 + 370 + Uma das melhores maneiras de colocar em prática suas habilidades de hacking 371 + é corrigindo bugs relatados por outras pessoas. Você não apenas ajudará a 372 + tornar o kernel mais estável, mas também aprenderá a resolver problemas do 373 + mundo real, melhorará suas habilidades e outros desenvolvedores passarão a 374 + notar sua presença. Corrigir bugs é uma das melhores formas de obter mérito 375 + entre outros desenvolvedores, pois poucas pessoas gostam de gastar tempo 376 + corrigindo bugs de terceiros. 377 + 378 + Para trabalhar em relatos de bugs já existentes, encontre um subsistema no 379 + qual você esteja interessado. Verifique no arquivo MAINTAINERS para onde 380 + os bugs daquele subsistema são relatados; geralmente será uma lista de 381 + discussão, raramente um rastreador de bugs (bugtracker). Pesquise nos 382 + arquivos de mensagens do local indicado por relatos recentes e ajude onde 383 + achar apropriado. Você também pode verificar o site 384 + https://bugzilla.kernel.org para relatos de bugs; apenas alguns 385 + subsistemas do kernel o utilizam ativamente para relato ou rastreamento, 386 + entretanto, bugs de todo o kernel acabam sendo registrados lá. 387 + 388 + 389 + Listas de discussão 390 + ------------------- 391 + 392 + Como alguns dos documentos acima descrevem, a maioria dos desenvolvedores 393 + do núcleo (core) do kernel participa da Linux Kernel Mailing List (LKML). 394 + Detalhes sobre como se inscrever e cancelar a inscrição na lista podem 395 + ser encontrados em: 396 + 397 + https://subspace.kernel.org/subscribing.html 398 + 399 + Existem arquivos de mensagens da lista na web em muitos lugares diferentes. 400 + Use um mecanismo de busca para encontrar esses arquivos. Por exemplo: 401 + 402 + https://lore.kernel.org/linux-kernel/ 403 + 404 + É altamente recomendável que você pesquise nos arquivos sobre o tópico que 405 + deseja abordar antes de postar na lista. Muitas coisas já discutidas em 406 + detalhes estão registradas apenas nos arquivos das listas de discussão. 407 + 408 + A maioria dos subsistemas individuais do kernel também possui sua própria 409 + lista de discussão separada, onde realizam seus esforços de desenvolvimento. 410 + Consulte o arquivo MAINTAINERS para obter uma lista de quais são essas 411 + listas para os diferentes grupos. 412 + 413 + Muitas das listas estão hospedadas no kernel.org. Informações sobre elas 414 + podem ser encontradas em: 415 + 416 + https://subspace.kernel.org 417 + 418 + Por favor, lembre-se de seguir bons hábitos de comportamento ao usar as 419 + listas. Embora um pouco clichê, a URL a seguir possui algumas diretrizes 420 + simples para interagir com a lista (ou qualquer outra lista): 421 + 422 + https://subspace.kernel.org/etiquette.html 423 + 424 + Se várias pessoas responderem ao seu e-mail, a lista de destinatários em 425 + CC: pode se tornar bem grande. Não remova ninguém da lista CC: sem um 426 + bom motivo, e não responda apenas para o endereço da lista. Acostume-se 427 + a receber o e-mail duas vezes (um do remetente e outro da lista) e não 428 + tente ajustar isso adicionando cabeçalhos de e-mail complexos; as pessoas 429 + não gostarão disso. 430 + 431 + Lembre-se de manter o contexto e a atribuição de suas respostas intactos; 432 + mantenha as linhas do tipo "John Kernelhacker escreveu...:" no topo da 433 + sua resposta e adicione seus comentários entre as seções citadas 434 + individualmente, em vez de escrever tudo no topo do e-mail. 435 + 436 + Se você adicionar patches ao seu e-mail, certifique-se de que sejam texto 437 + puro legível, conforme declarado em 438 + :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`. 439 + Os desenvolvedores do kernel não querem lidar com anexos ou patches 440 + compactados; eles podem querer comentar linhas individuais do seu patch, 441 + o que só funciona dessa forma. Certifique-se de usar um programa de 442 + e-mail que não altere espaços e caracteres de tabulação (tabs). Um bom 443 + primeiro teste é enviar o e-mail para si mesmo e tentar aplicar o seu 444 + próprio patch. Se isso não funcionar, conserte seu programa de e-mail ou 445 + troque-o até que funcione. 446 + 447 + Acima de tudo, por favor, lembre-se de mostrar respeito aos outros 448 + inscritos. 449 + 450 + 451 + Trabalhando com a comunidade 452 + ---------------------------- 453 + 454 + O objetivo da comunidade do kernel é fornecer o melhor kernel possível. 455 + Quando você envia um patch para aceitação, ele será revisado por seus 456 + méritos técnicos e apenas por eles. Então, o que você deve esperar? 457 + 458 + - críticas 459 + - comentários 460 + - solicitações de mudança 461 + - solicitações de justificativa 462 + - silêncio 463 + 464 + Lembre-se, isso faz parte do processo de incluir seu patch no kernel. 465 + Você deve ser capaz de aceitar críticas e comentários sobre seus patches, 466 + avaliá-los em nível técnico e retrabalhar seus patches ou fornecer 467 + raciocínios claros e concisos sobre o porquê de certas mudanças não 468 + deverem ser feitas. Se não houver respostas à sua postagem, aguarde 469 + alguns dias e tente novamente; às vezes, as coisas se perdem no enorme 470 + volume de mensagens. 471 + 472 + O que você não deve fazer? 473 + 474 + - esperar que seu patch seja aceito sem questionamentos 475 + - tornar-se defensivo 476 + - ignorar comentários 477 + - reenviar o patch sem fazer nenhuma das alterações solicitadas 478 + 479 + Em uma comunidade que busca a melhor solução técnica possível, sempre 480 + haverá opiniões divergentes sobre o quão benéfico é um patch. Você deve 481 + ser cooperativo e estar disposto a adaptar sua ideia para que ela se 482 + encaixe no kernel. Ou, pelo menos, estar disposto a provar que sua ideia 483 + vale a pena. Lembre-se: estar errado é aceitável, desde que você esteja 484 + disposto a trabalhar em direção a uma solução correta. 485 + 486 + É normal que as respostas ao seu primeiro patch sejam apenas uma lista 487 + de uma dúzia de coisas que você deve corrigir. Isso **não** implica que 488 + seu patch não será aceito e **não** é algo pessoal contra você. Simplesmente 489 + corrija todos os problemas apontados em seu patch e envie-o novamente. 490 + 491 + 492 + Diferenças entre a comunidade do kernel e estruturas corporativas 493 + ----------------------------------------------------------------- 494 + 495 + A comunidade do kernel trabalha de forma diferente da maioria dos ambientes 496 + tradicionais de desenvolvimento corporativo. Aqui está uma lista de coisas 497 + que você pode tentar fazer para evitar problemas: 498 + 499 + Boas coisas a dizer em relação às suas mudanças propostas: 500 + 501 + - "Isto resolve múltiplos problemas." 502 + - "Isto remove 2000 linhas de código." 503 + - "Aqui está um patch que explica o que estou tentando descrever." 504 + - "Eu testei isso em 5 arquiteturas diferentes..." 505 + - "Aqui está uma série de pequenos patches que..." 506 + - "Isto aumenta a performance em máquinas comuns..." 507 + 508 + Coisas ruins que você deve evitar dizer: 509 + 510 + - "Nós fizemos desta forma no AIX/ptx/Solaris, portanto deve ser bom..." 511 + - "Eu faço isso há 20 anos, então..." 512 + - "Isto é necessário para minha empresa ganhar dinheiro." 513 + - "Isto é para nossa linha de produtos Enterprise." 514 + - "Aqui está meu documento de design de 1000 páginas que descreve minha ideia." 515 + - "Estou trabalhando nisso há 6 meses..." 516 + - "Aqui está um patch de 5000 linhas que..." 517 + - "Eu reescrevi toda a bagunça atual, e aqui está..." 518 + - "Eu tenho um prazo (deadline), e este patch precisa ser aplicado agora." 519 + 520 + Outra forma em que a comunidade do kernel difere da maioria dos ambientes 521 + tradicionais de engenharia de software é a natureza anônima da interação. 522 + Um benefício de usar e-mail e IRC como as principais formas de comunicação 523 + é a ausência de discriminação baseada em gênero ou raça. O ambiente de 524 + trabalho do kernel Linux aceita mulheres e minorias porque tudo o que você 525 + é, é um endereço de e-mail. O aspecto internacional também ajuda a nivelar 526 + o campo de jogo porque você não pode adivinhar o gênero com base no nome 527 + de uma pessoa. Um homem pode se chamar Andrea e uma mulher pode se chamar 528 + Pat. A maioria das mulheres que trabalharam no kernel Linux e expressaram 529 + uma opinião tiveram experiências positivas. 530 + 531 + A barreira do idioma pode causar problemas para algumas pessoas que não 532 + se sentem confortáveis com o inglês. Um bom domínio do idioma pode ser 533 + necessário para transmitir ideias adequadamente nas listas de discussão, 534 + por isso recomenda-se que você verifique seus e-mails para garantir que 535 + façam sentido em inglês antes de enviá-los. 536 + 537 + 538 + Divida suas alterações 539 + ---------------------- 540 + 541 + A comunidade do kernel Linux não aceita de bom grado grandes blocos de 542 + código jogados de uma só vez. As mudanças precisam ser devidamente 543 + introduzidas, discutidas e divididas em porções minúsculas e individuais. 544 + Isso é quase o exato oposto do que as empresas costumam fazer. Sua proposta 545 + também deve ser introduzida muito cedo no processo de desenvolvimento, para 546 + que você possa receber feedback sobre o que está fazendo. Isso também permite 547 + que a comunidade sinta que você está trabalhando com eles, e não simplesmente 548 + usando-os como um depósito para sua funcionalidade. No entanto, não envie 549 + 50 e-mails de uma só vez para uma lista de discussão; sua série de patches 550 + deve ser menor que isso quase sempre. 551 + 552 + As razões para dividir as coisas são as seguintes: 553 + 554 + 1) Patches pequenos aumentam a probabilidade de serem aplicados, pois não 555 + exigem muito tempo ou esforço para verificar sua correção. Um patch de 556 + 5 linhas pode ser aplicado por um mantenedor com apenas um olhar rápido. 557 + No entanto, um patch de 500 linhas pode levar horas para ser revisado 558 + (o tempo que leva é exponencialmente proporcional ao tamanho do patch, 559 + ou algo assim). 560 + 561 + Patches pequenos também tornam muito fácil a depuração (debug) quando 562 + algo dá errado. É muito mais fácil reverter patches um por um do que 563 + dissecar um patch muito grande após ele ter sido aplicado (e quebrado algo). 564 + 565 + 2) É importante não apenas enviar patches pequenos, mas também reescrever 566 + e simplificar (ou simplesmente reordenar) os patches antes de submetê-los. 567 + 568 + Aqui está uma analogia do desenvolvedor do kernel Al Viro: 569 + 570 + *"Pense em um professor corrigindo o dever de casa de um aluno de 571 + matemática. O professor não quer ver as tentativas e erros do aluno 572 + antes de chegar à solução. Ele quer ver a resposta mais limpa e 573 + elegante. Um bom aluno sabe disso e nunca enviaria seu trabalho 574 + intermediário antes da solução final.* 575 + 576 + *O mesmo vale para o desenvolvimento do kernel. Os mantenedores e 577 + revisores não querem ver o processo de pensamento por trás da solução 578 + do problema que se está resolvendo. Eles querem ver uma solução 579 + simples e elegante."* 580 + 581 + Pode ser desafiador manter o equilíbrio entre apresentar uma solução 582 + elegante e trabalhar em conjunto com a comunidade discutindo seu trabalho 583 + inacabado. Portanto, é bom entrar no processo cedo para obter feedback e 584 + melhorar seu trabalho, mas também manter suas alterações em pequenos blocos 585 + que possam ser aceitos, mesmo quando sua tarefa completa ainda não esteja 586 + pronta para inclusão. 587 + 588 + Também entenda que não é aceitável enviar patches para inclusão que estejam 589 + inacabados e que serão "consertados mais tarde". 590 + 591 + 592 + Justifique sua alteração 593 + ------------------------ 594 + 595 + Além de dividir seus patches, é muito importante que você deixe a comunidade 596 + Linux saber por que eles deveriam adicionar essa mudança. Novas 597 + funcionalidades devem ser justificadas como necessárias e úteis. 598 + 599 + 600 + Documente sua alteração 601 + ----------------------- 602 + 603 + Ao enviar seus patches, preste atenção especial ao que você diz no texto 604 + do seu e-mail. Essas informações se tornarão as informações do ChangeLog 605 + para o patch e serão preservadas para que todos vejam para sempre. Elas 606 + devem descrever o patch completamente, contendo: 607 + 608 + - por que a mudança é necessária 609 + - a abordagem geral de design no patch 610 + - detalhes de implementação 611 + - resultados de testes 612 + 613 + Para mais detalhes sobre como tudo isso deve ser, por favor, veja a seção 614 + ChangeLog do documento: 615 + 616 + "O Patch Perfeito" 617 + https://www.ozlabs.org/~akpm/stuff/tpp.txt 618 + 619 + Todas essas coisas às vezes são muito difíceis de fazer. Pode levar anos 620 + para aperfeiçoar essas práticas (se é que é possível). É um processo 621 + contínuo de melhoria que exige muita paciência e determinação. Mas não 622 + desista, é possível. Muitos fizeram isso antes, e cada um teve que começar 623 + exatamente onde você está agora. 624 + 625 + ---------- 626 + 627 + Agradecimentos a Paolo Ciarrocchi, que permitiu que a seção "Processo de 628 + Desenvolvimento" (https://lwn.net/Articles/94386/) fosse baseada em um 629 + texto que ele escreveu, e a Randy Dunlap e Gerrit Huizenga por parte da 630 + lista de coisas que você deve ou não dizer. Também agradecemos a Pat Mochel, 631 + Hanna Linder, Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, 632 + Josh Boyer, Kees Cook, Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, 633 + Adrian Bunk, Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, 634 + Michael Kerrisk e Alex Shepard por suas revisões, comentários e contribuições. 635 + Sem a ajuda deles, este documento não teria sido possível. 636 + 637 + Mantenedor: Greg Kroah-Hartman <greg@kroah.com>
+18
Documentation/translations/pt_BR/process/maintainer-handbooks.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + Notas sobre o processo de desenvolvimento de subsistemas e mantenedores 4 + ======================================================================= 5 + 6 + O propósito deste documento é fornecer informações específicas de 7 + subsistemas que são suplementares ao manual geral do processo de 8 + desenvolvimento. 9 + 10 + Conteúdos: 11 + 12 + .. toctree:: 13 + :numbered: 14 + :maxdepth: 2 15 + 16 + maintainer-netdev 17 + maintainer-soc 18 + maintainer-soc-clean-dts
+435
Documentation/translations/pt_BR/process/maintainer-kvm-x86.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + KVM x86 4 + ======= 5 + 6 + Prefácio 7 + -------- 8 + 9 + O KVM se esforça para ser uma comunidade acolhedora; as contribuições de 10 + recém-chegados são valorizadas e incentivadas. Por favor, não se sinta 11 + desanimado ou intimidado pela extensão deste documento e pelas muitas 12 + regras/diretrizes que ele contém. Todo mundo comete erros e todo mundo já foi um 13 + novato em algum momento. Desde que você faça um esforço honesto para seguir as 14 + diretrizes do KVM x86, seja receptivo ao feedback e aprenda com os erros que 15 + cometer, você será recebido de braços abertos, não com tochas e forquilhas. 16 + 17 + (TL;DR) 18 + -------- 19 + Testes são obrigatórios. Seja consistente com os estilos e padrões estabelecidos. 20 + 21 + Árvores 22 + ------- 23 + O KVM x86 está atualmente em um período de transição: deixando de fazer parte da 24 + árvore principal do KVM para se tornar "apenas mais uma arquitetura KVM". Como tal, 25 + o KVM x86 está dividido entre a árvore principal do KVM, 26 + ``git.kernel.org/pub/scm/virt/kvm/kvm.git``, e uma árvore específica para KVM x86, 27 + ``github.com/kvm-x86/linux.git``. 28 + 29 + De modo geral, as correções (fixes) para o ciclo atual são aplicadas diretamente 30 + na árvore principal do KVM, enquanto todo o desenvolvimento para o próximo ciclo 31 + é roteado através da árvore do KVM x86. No caso improvável de uma correção para o 32 + ciclo atual ser roteada através da árvore do KVM x86, ela será aplicada à branch 33 + ``fixes`` antes de seguir para a árvore principal do KVM. 34 + 35 + Note que espera-se que este período de transição dure bastante tempo, ou seja, 36 + será o status quo em um futuro próximo. 37 + 38 + Branches 39 + ~~~~~~~~ 40 + A árvore do KVM x86 é organizada em múltiplas branches de tópicos (topic 41 + branches). O objetivo de usar branches de tópicos mais granulares é facilitar o 42 + acompanhamento de uma área específica de desenvolvimento e limitar os danos 43 + colaterais de erros humanos e/ou commits com bugs; por exemplo, descartar o 44 + commit HEAD de uma branch de tópico não tem impacto nos hashes SHA1 de outros 45 + commits em andamento, e a necessidade de rejeitar um pull request devido a bugs 46 + atrasa apenas aquela branch de tópico específica. 47 + 48 + Todas as branches de tópicos, exceto a ``next`` e a ``fixes``, são incorporadas 49 + na ``next`` via um "Cthulhu merge" conforme a necessidade, ou seja, sempre que 50 + uma branch de tópico é atualizada. Como resultado, force pushes para a branch 51 + ``next`` são comuns. 52 + 53 + Ciclo de Vida 54 + ~~~~~~~~~~~~~ 55 + As correções (fixes) destinadas ao lançamento atual, também conhecido como 56 + mainline, são normalmente aplicadas diretamente na árvore principal do KVM, ou 57 + seja, não passam pela árvore do KVM x86. 58 + 59 + As mudanças destinadas ao próximo lançamento são roteadas através da árvore do 60 + KVM x86. Pull requests (do KVM x86 para o KVM principal) são enviados para cada 61 + branch de tópico do KVM x86, normalmente na semana anterior à abertura da janela 62 + de merge por Linus, por exemplo, na semana seguinte ao rc7 para lançamentos 63 + "normais". Se tudo correr bem, as branches de tópicos são incorporadas ao pull 64 + request principal do KVM enviado durante a janela de merge de Linus. 65 + 66 + A árvore do KVM x86 não possui sua própria janela de merge oficial, mas há um 67 + "soft close" (fechamento flexível) por volta do rc5 para novos recursos, e um 68 + "soft close" por volta do rc6 para correções (para o próximo lançamento; veja 69 + acima para correções destinadas ao lançamento atual). 70 + 71 + Cronograma 72 + ---------- 73 + As submissões são normalmente revisadas e aplicadas em ordem FIFO (primeiro a 74 + entrar, primeiro a sair), com alguma margem de manobra para o tamanho de uma 75 + série, patches que estão "cache hot", etc. Correções (fixes), especialmente para 76 + o lançamento atual e/ou árvores estáveis (stable trees), têm prioridade na fila. 77 + Patches que serão aceitos através de uma árvore não-KVM (mais frequentemente 78 + através da árvore "tip") e/ou que possuam outros "acks"/revisões também ganham 79 + certa prioridade. 80 + 81 + Note que a grande maioria das revisões é feita entre o rc1 e o rc6, 82 + aproximadamente. O período entre o rc6 e o próximo rc1 é usado para colocar 83 + outras tarefas em dia, ou seja, o "silêncio de rádio" durante este período não é 84 + incomum. 85 + 86 + Pings para obter uma atualização de status são bem-vindos, mas tenha em mente o 87 + tempo do ciclo de lançamento atual e tenha expectativas realistas. Se você está 88 + dando um ping para aceitação — ou seja, não apenas para feedback ou uma 89 + atualização — por favor, faça tudo o que puder, dentro do razoável, para garantir 90 + que seus patches estejam prontos para o merge! Pings em séries que quebram o 91 + build ou falham em testes resultam em mantenedores infelizes! 92 + 93 + Desenvolvimento 94 + --------------- 95 + 96 + Árvore/Branch Base 97 + ~~~~~~~~~~~~~~~~~~ 98 + Correções destinadas ao lançamento atual, também conhecido como mainline, devem 99 + ser baseadas em ``git://git.kernel.org/pub/scm/virt/kvm/kvm.git master``. Note 100 + que as correções não garantem inclusão automática no lançamento atual. Não 101 + existe uma regra única, mas tipicamente apenas correções para bugs que sejam 102 + urgentes, críticos e/ou que tenham sido introduzidos no lançamento atual devem 103 + ser destinadas ao lançamento atual. 104 + 105 + Todo o restante deve ser baseado em ``kvm-x86/next``, ou seja, não há 106 + necessidade de selecionar uma branch de tópico específica como base. Se houver 107 + conflitos e/ou dependências entre as branches de tópicos, é trabalho do 108 + mantenedor resolvê-los. 109 + 110 + A única exceção ao uso da ``kvm-x86/next`` como base é se um patch/série for uma 111 + série multi-arquitetura (multi-arch), ou seja, possuir modificações não triviais 112 + no código comum do KVM e/ou possuir mudanças mais do que superficiais no código 113 + de outras arquiteturas. Patches/séries multi-arquitetura devem, em vez disso, 114 + ser baseados em um ponto comum e estável no histórico do KVM, por exemplo, o 115 + release candidate no qual a ``kvm-x86 next`` se baseia. Se você não tiver 116 + certeza se um patch/série é verdadeiramente multi-arquitetura, erre pelo lado da 117 + cautela e trate-o como tal, ou seja, use uma base comum. 118 + 119 + Estilo de Codificação 120 + ~~~~~~~~~~~~~~~~~~~~~ 121 + Quando se trata de estilo, nomenclatura, padrões, etc., a consistência é a 122 + prioridade número um no KVM x86. Se tudo mais falhar, siga o que já existe. 123 + 124 + Com algumas ressalvas listadas abaixo, siga o estilo de codificação preferido 125 + dos mantenedores da árvore "tip" (:ref:`maintainer-tip-coding-style`), já que 126 + patches/séries frequentemente tocam tanto arquivos do KVM quanto arquivos x86 127 + não-KVM, ou seja, atraem a atenção de mantenedores do KVM *e* da árvore "tip". 128 + 129 + O uso de "reverse fir tree" (árvore de abeto invertida), também conhecido como 130 + "árvore de Natal invertida", para declarações de variáveis não é estritamente 131 + obrigatório, embora ainda seja preferido. 132 + 133 + Exceto por alguns casos excepcionais, não use comentários kernel-doc para 134 + funções. A grande maioria das funções "públicas" do KVM não são verdadeiramente 135 + públicas, pois se destinam apenas ao consumo interno do KVM (há planos para 136 + privatizar os headers e exports do KVM para reforçar isso). 137 + 138 + Comentários 139 + ~~~~~~~~~~~ 140 + Escreva comentários usando o modo imperativo e evite pronomes. Use comentários 141 + para fornecer uma visão geral de alto nível do código e/ou para explicar por 142 + que o código faz o que faz. Não reitere o que o código faz literalmente; deixe 143 + o código falar por si mesmo. Se o código em si for inescrutável, comentários 144 + não ajudarão. 145 + 146 + Referências ao SDM e ao APM 147 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 148 + Grande parte da base de código do KVM está diretamente ligada ao comportamento 149 + arquitetural definido no Manual de Desenvolvimento de Software (SDM) da Intel e 150 + no Manual do Programador de Arquitetura (APM) da AMD. O uso de "Intel SDM" e 151 + "AMD APM", ou até mesmo apenas "SDM" ou "APM", sem contexto adicional, é 152 + perfeitamente aceitável. 153 + 154 + Não faça referência a seções, tabelas, figuras, etc., por número, especialmente 155 + em comentários. Em vez disso, se necessário (veja abaixo), copie e cole o trecho 156 + relevante e referencie seções/tabelas/figuras pelo nome. Os layouts do SDM e do 157 + APM mudam constantemente e, portanto, os números/rótulos não são estáveis. 158 + 159 + De modo geral, não faça referência explícita nem copie e cole do SDM ou do APM 160 + em comentários. Com poucas exceções, o KVM *deve* respeitar o comportamento 161 + arquitetural; portanto, subentende-se que o comportamento do KVM está emulando o 162 + comportamento do SDM e/ou do APM. Note que fazer referência ao SDM/APM em 163 + changelogs para justificar a mudança e fornecer contexto é perfeitamente 164 + aceitável e incentivado. 165 + 166 + Shortlog 167 + ~~~~~~~~ 168 + O formato de prefixo preferencial é ``KVM: <topic>:``, onde ``<topic>`` é um dos 169 + seguintes:: 170 + 171 + - x86 172 + - x86/mmu 173 + - x86/pmu 174 + - x86/xen 175 + - selftests 176 + - SVM 177 + - nSVM 178 + - VMX 179 + - nVMX 180 + 181 + **NÃO use x86/kvm!** ``x86/kvm`` é usado exclusivamente para mudanças no Linux 182 + como convidado (guest) de um KVM, ou seja, para ``arch/x86/kernel/kvm.c``. Não 183 + use nomes de arquivos ou caminhos completos de arquivos como prefixo do 184 + assunto/shortlog. 185 + 186 + Note que estes não se alinham com as branches de tópicos (as branches de tópicos 187 + se preocupam muito mais com conflitos de código). 188 + 189 + Todos os nomes são sensíveis a maiúsculas e minúsculas! ``KVM: x86:`` é bom, 190 + ``kvm: vmx:`` não é. 191 + 192 + Comece com letra maiúscula a primeira palavra da descrição condensada do patch, 193 + mas omita a pontuação final. Ex.:: 194 + 195 + KVM: x86: Fix a null pointer dereference in function_xyz() 196 + 197 + e não:: 198 + 199 + kvm: x86: fix a null pointer dereference in function_xyz. 200 + 201 + Se um patch tocar em múltiplos tópicos, suba na árvore conceitual para encontrar 202 + o primeiro pai comum (que geralmente é apenas ``x86``). Em caso de dúvida, 203 + ``git log caminho/do/arquivo`` deve fornecer uma dica razoável. 204 + 205 + Novos tópicos surgem ocasionalmente, mas, por favor, inicie uma discussão na 206 + lista se desejar propor a introdução de um novo tópico; ou seja, não aja por 207 + conta própria. 208 + 209 + Veja :ref:`the_canonical_patch_format` para mais informações, com uma ressalva: 210 + não trate o limite de 70-75 caracteres como um limite absoluto e rígido. Em 211 + vez disso, use 75 caracteres como um limite firme, mas não rígido, e use 80 212 + caracteres como um limite intransponível. Ou seja, permita que o shortlog 213 + ultrapasse alguns caracteres do limite padrão se você tiver um bom motivo para 214 + fazê-lo. 215 + 216 + Changelog 217 + ~~~~~~~~~ 218 + O mais importante: escreva os changelogs usando o modo imperativo e evite o uso 219 + de pronomes. 220 + 221 + Veja :ref:`describe_changes` para mais informações, com uma ressalva: comece com 222 + uma breve descrição das mudanças reais e, em seguida, apresente o contexto e o 223 + histórico. Note! Esta ordem entra em conflito direto com a abordagem preferida 224 + da árvore "tip"! Por favor, siga o estilo preferido da árvore "tip" ao enviar 225 + patches que visam primariamente o código de arch/x86 que _NÃO_ seja código KVM. 226 + 227 + Declarar o que um patch faz antes de mergulhar nos detalhes é preferido pelo KVM 228 + x86 por vários motivos. Primeiro e mais importante, qual código está sendo 229 + realmente alterado é, reconhecidamente, a informação mais importante e, 230 + portanto, essa informação deve ser fácil de encontrar. Changelogs que escondem 231 + "o que está mudando de fato" em uma única linha após 3 ou mais parágrafos de 232 + histórico tornam muito difícil encontrar essa informação. 233 + 234 + Para uma revisão inicial, pode-se argumentar que "o que está quebrado" é mais 235 + importante, mas para uma leitura rápida de logs e arqueologia do git, os 236 + detalhes minuciosos importam cada vez menos. Por exemplo, ao fazer uma série de 237 + "git blame", os detalhes de cada mudança ao longo do caminho são inúteis; os 238 + detalhes só importam para o culpado. Fornecer "o que mudou" facilita determinar 239 + rapidamente se um commit pode ou não ser de interesse. 240 + 241 + Outro benefício de declarar "o que está mudando" primeiro é que quase sempre é 242 + possível declarar "o que está mudando" em uma única frase. Por outro lado, 243 + exceto pelos bugs mais simples, todos exigem várias frases ou parágrafos para 244 + descrever totalmente o problema. Se tanto "o que está mudando" quanto "qual é o 245 + bug" forem super curtos, a ordem não importa. Mas se um for mais curto (quase 246 + sempre o "o que está mudando"), então cobrir o mais curto primeiro é vantajoso 247 + porque é menos inconveniente para leitores/revisores que têm uma preferência de 248 + ordenação estrita. Ex: ter que pular uma frase para chegar ao contexto é menos 249 + doloroso do que ter que pular três parágrafos para chegar ao "o que está 250 + mudando". 251 + 252 + Correções (Fixes) 253 + ~~~~~~~~~~~~~~~~~ 254 + Se uma mudança corrige um bug do KVM/kernel, adicione uma tag Fixes:, mesmo que 255 + a mudança não precise ser portada (backported) para kernels estáveis, e mesmo 256 + que a mudança corrija um bug em uma versão mais antiga. 257 + 258 + Por outro lado, se uma correção realmente precisar de backport, marque 259 + explicitamente o patch com "Cc: stable@vger.kernel.org" (embora o e-mail em si 260 + não precise enviar cópia para a lista stable); o KVM x86 opta por não realizar 261 + o backport automático de tags Fixes: por padrão. Alguns patches selecionados 262 + automaticamente são portados, mas exigem aprovação explícita do mantenedor 263 + (pesquise por MANUALSEL). 264 + 265 + Referências a Funções 266 + ~~~~~~~~~~~~~~~~~~~~~ 267 + Quando uma função for mencionada em um comentário, changelog ou shortlog (ou em 268 + qualquer outro lugar, aliás), use o formato ``nome_da_funcao()``. Os parênteses 269 + fornecem contexto e removem a ambiguidade da referência. 270 + 271 + Testes 272 + ------ 273 + No mínimo, *todos* os patches de uma série devem compilar sem erros para 274 + KVM_INTEL=m, KVM_AMD=m e KVM_WERROR=y. Compilar cada combinação possível de 275 + Kconfigs não é viável, mas quanto mais, melhor. KVM_SMM, KVM_XEN, PROVE_LOCKING 276 + e X86_64 são opções (knobs) particularmente interessantes para se testar. 277 + 278 + A execução de KVM selftests e KVM-unit-tests também é obrigatória (e, para 279 + afirmar o óbvio, os testes precisam passar). A única exceção é para mudanças 280 + que tenham probabilidade insignificante de afetar o comportamento em tempo de 281 + execução, por exemplo, patches que apenas modificam comentários. Sempre que 282 + possível e relevante, o teste tanto em Intel quanto em AMD é fortemente 283 + preferido. A inicialização de uma VM real é incentivada, mas não obrigatória. 284 + 285 + Para mudanças que tocam o código de shadow paging do KVM, executar com o TDP 286 + (EPT/NPT) desabilitado é obrigatório. Para mudanças que afetam o código comum da 287 + MMU do KVM, a execução com o TDP desabilitado é fortemente incentivada. Para 288 + todas as outras mudanças, se o código sendo modificado depender de e/ou 289 + interagir com um parâmetro de módulo (module param), o teste com as 290 + configurações relevantes é obrigatório. 291 + 292 + Note que o KVM selftests e o KVM-unit-tests possuem falhas conhecidas. Se você 293 + suspeitar que uma falha não se deve às suas alterações, verifique se a *exata 294 + mesma* falha ocorre com e sem as suas mudanças. 295 + 296 + Mudanças que tocam a documentação em reStructuredText, ou seja, arquivos .rst, 297 + devem compilar o htmldocs de forma limpa, ou seja, sem novos avisos (warnings) 298 + ou erros. 299 + 300 + Se você não puder testar totalmente uma mudança, por exemplo, devido à falta de 301 + hardware, declare claramente qual nível de teste você foi capaz de realizar, 302 + por exemplo, na cover letter (carta de apresentação). 303 + 304 + Novos Recursos 305 + ~~~~~~~~~~~~~~ 306 + Com uma exceção, novos recursos *devem* vir acompanhados de cobertura de testes. 307 + Testes específicos do KVM não são estritamente obrigatórios, por exemplo, se a 308 + cobertura for fornecida ao executar uma VM convidada (guest) suficientemente 309 + habilitada, ou ao executar um selftest de kernel relacionado em uma VM, mas 310 + testes dedicados do KVM são preferidos em todos os casos. Casos de teste 311 + negativos, em particular, são obrigatórios para a habilitação de novos recursos 312 + de hardware, já que fluxos de erro e exceção raramente são exercitados 313 + simplesmente ao executar uma VM. 314 + 315 + A única exceção a esta regra é se o KVM estiver simplesmente anunciando suporte 316 + para um recurso via KVM_GET_SUPPORTED_CPUID, ou seja, para instruções/recursos 317 + que o KVM não pode impedir um convidado de usar e para os quais não há uma 318 + habilitação real. 319 + 320 + Note que "novos recursos" não significa apenas "novos recursos de hardware"! 321 + Novos recursos que não podem ser bem validados usando os KVM selftests e/ou 322 + KVM-unit-tests existentes devem vir acompanhados de testes. 323 + 324 + Enviar o desenvolvimento de novos recursos sem testes para obter feedback 325 + antecipado é mais do que bem-vindo, mas tais submissões devem ser marcadas como 326 + RFC, e a carta de apresentação (cover letter) deve declarar claramente que tipo 327 + de feedback é solicitado/esperado. Não abuse do processo de RFC; as RFCs 328 + normalmente não receberão uma revisão profunda. 329 + 330 + Correções de Bugs 331 + ~~~~~~~~~~~~~~~~~ 332 + Exceto por bugs "óbvios" encontrados por inspeção, as correções devem vir 333 + acompanhadas de um reprodutor (reproducer) para o bug que está sendo corrigido. 334 + Em muitos casos, o reprodutor é implícito, por exemplo, para erros de build e 335 + falhas de teste, mas ainda assim deve estar claro para os leitores o que está 336 + quebrado e como verificar a correção. Alguma margem de manobra é dada para 337 + bugs encontrados através de cargas de trabalho ou testes não públicos, mas a 338 + disponibilização de testes de regressão para tais bugs é fortemente preferida. 339 + 340 + Em geral, testes de regressão são preferidos para qualquer bug que não seja 341 + trivial de ser atingido. Por exemplo, mesmo que o bug tenha sido originalmente 342 + encontrado por um fuzzer como o syzkaller, um teste de regressão direcionado 343 + pode ser justificável se o bug exigir que se atinja uma condição de corrida do 344 + tipo "uma em um milhão". 345 + 346 + Note que os bugs do KVM raramente são urgentes *e* não triviais de reproduzir. 347 + Pergunte a si mesmo se um bug é realmente o fim do mundo antes de enviar uma 348 + correção sem um reprodutor. 349 + 350 + Postagem 351 + -------- 352 + 353 + Links 354 + ~~~~~ 355 + Não faça referência explícita a relatórios de bugs, versões anteriores de um 356 + patch/série, etc., através de cabeçalhos ``In-Reply-To:``. O uso de 357 + ``In-Reply-To:`` torna-se uma bagunça infernal para grandes séries e/ou quando 358 + o número de versões aumenta, e o ``In-Reply-To:`` é inútil para qualquer 359 + pessoa que não tenha a mensagem original, por exemplo, se alguém não estava 360 + em cópia (Cc) no relatório do bug ou se a lista de destinatários mudar entre 361 + as versões. 362 + 363 + Para vincular a um relatório de bug, versão anterior ou qualquer coisa de 364 + interesse, use links do lore. Para referenciar versão(ões) anterior(es), de modo 365 + geral, não inclua um Link: no changelog, pois não há necessidade de registrar o 366 + histórico no git; ou seja, coloque o link na carta de apresentação (cover 367 + letter) ou na seção que o git ignora. Forneça um Link: formal para relatórios 368 + de bugs e/ou discussões que levaram ao patch. O contexto de por que uma mudança 369 + foi feita é altamente valioso para futuros leitores. 370 + 371 + Base do Git (Git Base) 372 + ~~~~~~~~~~~~~~~~~~~~~~ 373 + Se você estiver usando o git versão 2.9.0 ou posterior (Googlers, isso inclui 374 + todos vocês!), use ``git format-patch`` com a flag ``--base`` para incluir 375 + automaticamente as informações da árvore base nos patches gerados. 376 + 377 + Note que ``--base=auto`` funciona conforme o esperado se, e somente se, o 378 + upstream de uma branch estiver definido para a branch de tópico base; por 379 + exemplo, ele fará a coisa errada se o seu upstream estiver definido para o seu 380 + repositório pessoal para fins de backup. Uma solução "auto" alternativa é 381 + derivar os nomes das suas branches de desenvolvimento com base no seu tópico 382 + KVM x86 e alimentar isso no ``--base``. Por exemplo, 383 + ``x86/pmu/minha_branch`` e, em seguida, escrever um pequeno wrapper para 384 + extrair ``pmu`` do nome da branch atual para resultar em ``--base=x/pmu``, onde 385 + ``x`` é o nome que seu repositório usa para rastrear o remoto do KVM x86. 386 + 387 + Postagem Conjunta de Testes 388 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 389 + KVM selftests que estão associados a mudanças no KVM, por exemplo, testes de 390 + regressão para correções de bugs, devem ser postados junto com as mudanças do 391 + KVM como uma única série. As regras padrão do kernel para bissecção (bisection) 392 + se aplicam, ou seja, mudanças no KVM que resultem em falhas de teste devem ser 393 + ordenadas após as atualizações dos selftests e, vice-versa, novos testes que 394 + falhem devido a bugs do KVM devem ser ordenados após as correções do KVM. 395 + 396 + KVM-unit-tests devem *sempre* ser postados separadamente. Ferramentas, como o 397 + b4 am, não sabem que o KVM-unit-tests é um repositório separado e ficam 398 + confusas quando os patches de uma série se aplicam a árvores diferentes. Para 399 + vincular os patches do KVM-unit-tests aos patches do KVM, poste primeiro as 400 + mudanças do KVM e, em seguida, forneça um link do lore para o patch/série do 401 + KVM no(s) patch(es) do KVM-unit-tests. 402 + 403 + Notificações 404 + ------------ 405 + Quando um patch/série é oficialmente aceito, um e-mail de notificação será 406 + enviado em resposta à postagem original (carta de apresentação para séries de 407 + múltiplos patches). A notificação incluirá a árvore e a branch de tópico, 408 + juntamente com os SHA1s dos commits dos patches aplicados. 409 + 410 + Se um subconjunto de patches for aplicado, isso será claramente declarado na 411 + notificação. A menos que seja dito o contrário, subentende-se que quaisquer 412 + patches na série que não foram aceitos precisam de mais trabalho e devem ser 413 + enviados em uma nova versão. 414 + 415 + Se, por algum motivo, um patch for descartado após ter sido oficialmente 416 + aceito, uma resposta será enviada ao e-mail de notificação explicando o porquê 417 + do descarte, bem como os próximos passos. 418 + 419 + Estabilidade de SHA1 420 + ~~~~~~~~~~~~~~~~~~~~ 421 + Os SHA1s não têm garantia de serem 100% estáveis até que cheguem na árvore do 422 + Linus! Um SHA1 é *geralmente* estável uma vez que a notificação tenha sido 423 + enviada, mas imprevistos acontecem. Na maioria dos casos, uma atualização no 424 + e-mail de notificação será fornecida se o SHA1 de um patch aplicado mudar. No 425 + entanto, em alguns cenários, por exemplo, se todas as branches do KVM x86 426 + precisarem de rebase, as notificações individuais não serão enviadas. 427 + 428 + Vulnerabilidades 429 + ---------------- 430 + Bugs que podem ser explorados pelo convidado (guest) para atacar o hospedeiro 431 + (host) (kernel ou espaço do usuário), ou que podem ser explorados por uma VM 432 + aninhada (nested) contra o *seu* próprio hospedeiro (L2 atacando L1), são de 433 + interesse particular para o KVM. Por favor, siga o protocolo em 434 + :ref:`securitybugs` se você suspeitar que um bug possa levar a um escape, 435 + vazamento de dados, etc.
+596
Documentation/translations/pt_BR/process/maintainer-netdev.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ===================================== 4 + Subsistema de Rede do Linux (netdev) 5 + ===================================== 6 + 7 + tl;dr 8 + ----- 9 + 10 + - **Direcione seu patch para uma árvore** – use ``[PATCH net]``para correções 11 + ou ``[PATCH net-next]`` para novas funcionalidades. 12 + - **Tag Fixes** – para correções, a tag ``Fixes:`` é obrigatória, 13 + independentemente da árvore de destino. 14 + - **Tamanho da série** – não envie séries grandes (> 15 patches);divida-as em 15 + partes menores. 16 + - **Intervalo de envio** – não reenvie seus patches dentro de um período de 24 17 + horas. 18 + - **Reverse xmas tree** – organize as declarações de variáveis locais da mais 19 + longa para a mais curta. 20 + 21 + netdev 22 + ------ 23 + A **netdev** é a lista de discussão para todos os assuntos do Linux relacionados 24 + a rede. Isso inclui qualquer item encontrado em ``net/`` (ex: código principal 25 + como IPv6) e em ``drivers/net`` (ex: drivers específicos de hardware) na árvore 26 + de diretórios do Linux. 27 + 28 + Note que alguns subsistemas (ex: drivers de rede sem fio/wireless), que possuem 29 + um alto volume de tráfego, possuem suas próprias listas de discussão e árvores 30 + específicas. 31 + 32 + Como muitas outras listas de discussão do Linux, a lista netdev é hospedada no 33 + `kernel.org <https://www.kernel.org/>`_, com arquivos disponíveis em 34 + https://lore.kernel.org/netdev/. 35 + 36 + À exceção dos subsistemas mencionados anteriormente, todo o desenvolvimento de 37 + rede do Linux (ex: RFCs, revisões, comentários, etc.) ocorre na **netdev**. 38 + 39 + Ciclo de Desenvolvimento 40 + ------------------------ 41 + 42 + Aqui está um pouco de informação contextual sobre a cadência de desenvolvimento 43 + do Linux. Cada nova versão (release) inicia-se com uma "janela de mesclagem" 44 + (*merge window*) de duas semanas, onde os mantenedores principais enviam suas 45 + novas implementações para o Linus para incorporação na árvore principal 46 + (*mainline tree*). 47 + 48 + Após as duas semanas, a janela de mesclagem é fechada e a versão é 49 + nomeada/etiquetada como ``-rc1``. Nenhuma funcionalidade nova é incorporada à 50 + árvore principal após isso -- espera-se apenas correções (*fixes*) para o 51 + conteúdo da rc1. 52 + 53 + Após cerca de uma semana coletando correções para a rc1, a rc2 é lançada. Isso 54 + se repete semanalmente até a rc7 (tipicamente; às vezes rc6 se o ritmo estiver 55 + calmo, ou rc8 se houver muita instabilidade); uma semana após a última vX.Y-rcN 56 + ser concluída, a versão oficial vX.Y é lançada. 57 + 58 + Para descobrir em que ponto do ciclo estamos agora - carregue a página da 59 + mainline (Linus) aqui: 60 + 61 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 62 + 63 + e observe o topo da seção de "tags". Se for rc1, estamos no início do ciclo 64 + de desenvolvimento. Se a rc7 foi marcada há uma semana, então um lançamento 65 + é provavelmente iminente. Se a tag mais recente for uma tag de lançamento 66 + final (sem o sufixo ``-rcN``) - muito provavelmente estamos em uma janela de 67 + mesclagem (*merge window*) e o ``net-next`` está fechado. 68 + 69 + Árvores git e fluxo de patches 70 + ------------------------------ 71 + 72 + Existem duas árvores de rede (repositórios git) em jogo. Ambas são coordenadas 73 + por David Miller, o mantenedor principal de rede. Há a árvore ``net``e a árvore 74 + ``net-next``. Como você provavelmente pode adivinhar pelos nomes, a árvore 75 + ``net`` é para correções de código existente já na árvore mainline de Linus, e a 76 + ``net-next`` é para onde o novo código vai para o lançamento futuro. 77 + Você pode encontrar as árvores aqui: 78 + 79 + - https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git 80 + - https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git 81 + 82 + Relacionando isso ao desenvolvimento do kernel: no início da janela de mesclagem 83 + (*merge window*) de 2 semanas, a árvore ``net-next`` será fechada, sem novas 84 + mudanças ou funcionalidades. O conteúdo novo acumulado nas últimas 10 semanas 85 + será passado para a mainline/Linus via um *pull request* para a vX.Y ao mesmo 86 + tempo, a árvore ``net`` começará a acumular correções para este conteúdo enviado 87 + relacionado à vX.Y. 88 + 89 + Um anúncio indicando quando a ``net-next`` foi fechada é geralmente enviado para 90 + a netdev, mas sabendo o que foi dito acima, você pode prever isso com 91 + antecedência. 92 + 93 + .. warning:: 94 + 95 + Não envie novo conteúdo para a ``net-next`` para a netdev durante o período 96 + em que a árvore ``net-next`` estiver fechada. 97 + 98 + Patches RFC enviados apenas para revisão são obviamente bem-vindos a qualquer 99 + momento (use ``--subject-prefix='RFC net-next'`` com ``git format-patch``). 100 + 101 + Pouco depois das duas semanas terem passado (e a vX.Y-rc1 ser lançada), a árvore 102 + para a ``net-next`` reabre para coletar conteúdo para o próximo lançamento 103 + (vX.Y+1). 104 + 105 + Se você não estiver inscrito na netdev e/ou simplesmente não tiver certeza se a 106 + ``net-next`` já reabriu, basta verificar o link do repositório git da 107 + ``net-next`` acima para quaisquer novos *commits* relacionados à rede. Você 108 + também pode verificar o seguinte site para o status atual: 109 + 110 + https://netdev.bots.linux.dev/net-next.html 111 + 112 + A árvore ``net`` continua a coletar correções para o conteúdo da vX.Y e é 113 + enviada de volta para Linus em intervalos regulares (~semanais). Isso significa 114 + que o foco da ``net`` é a estabilização e correções de bugs. 115 + 116 + Finalmente, a vX.Y é lançada e todo o ciclo recomeça. 117 + 118 + Revisão de patches da netdev 119 + ---------------------------- 120 + 121 + Status do patch 122 + ~~~~~~~~~~~~~~~ 123 + 124 + O status de um patch pode ser verificado olhando a fila principal do patchwork 125 + para a netdev: 126 + 127 + https://patchwork.kernel.org/project/netdevbpf/list/ 128 + 129 + O campo "State" informará exatamente onde as coisas estão com o seu patch: 130 + 131 + ================= ============================================================ 132 + Estado do patch Descrição 133 + ================= ============================================================ 134 + New, Under review revisão pendente, o patch está na fila do mantenedor 135 + para revisão; os dois estados são usados alternadamente 136 + (dependendo do co-mantenedor exato que estiver lidando 137 + com o patchwork no momento) 138 + Accepted o patch foi aplicado à árvore de rede apropriada, 139 + isso é geralmente definido de forma automática pelo pw-bot 140 + Needs ACK aguardando um "ack" de um especialista da área 141 + ou testes 142 + Changes requested o patch não passou na revisão, espera-se uma nova 143 + revisão com mudanças apropriadas no código e na mensagem 144 + de commit 145 + Rejected o patch foi rejeitado e não se espera uma nova 146 + revisão 147 + Not applicable espera-se que o patch seja aplicado fora do 148 + subsistema de rede 149 + Awaiting upstream o patch deve ser revisado e tratado pelo sub-mantenedor 150 + apropriado, que o enviará para as árvores de rede; 151 + patches definidos como ``Awaiting upstream`` no patchwork 152 + da netdev geralmente permanecerão neste estado, 153 + independentemente de o sub-mantenedor ter solicitado 154 + mudanças, aceito ou rejeitado o patch 155 + Deferred o patch precisa ser reenviado mais tarde, geralmente 156 + devido a alguma dependência ou porque foi enviado para 157 + uma árvore fechada 158 + Superseded uma nova versão do patch foi enviada, geralmente 159 + definido pelo pw-bot 160 + RFC não deve ser aplicado, geralmente não está na 161 + fila de revisão do mantenedor; o pw-bot pode definir 162 + patches para este estado automaticamente com base nas 163 + tags do assunto 164 + ================= ============================================================ 165 + 166 + Os patches são indexados pelo cabeçalho ``Message-ID`` dos e-mails que os 167 + transportaram; portanto, se você tiver problemas para encontrar seu patch, 168 + anexe o valor do ``Message-ID`` à URL acima. 169 + 170 + Atualizando o status do patch 171 + ----------------------------- 172 + 173 + Colaboradores e revisores não têm permissões para atualizar o estado do patch 174 + diretamente no patchwork. O Patchwork não expõe muitas informações sobre o 175 + histórico do estado dos patches; portanto, ter várias pessoas atualizando o 176 + estado leva a confusões. 177 + 178 + Em vez de delegar permissões do patchwork, a netdev usa um robô de e-mail 179 + simples (bot) que procura por comandos/linhas especiais dentro dos e-mails 180 + enviados para a lista de discussão. Por exemplo, para marcar uma série como 181 + Mudanças Solicitadas (*Changes Requested*), é necessário enviar a seguinte 182 + linha em qualquer lugar na thread do e-mail:: 183 + 184 + pw-bot: changes-requested 185 + 186 + Como resultado, o bot definirá toda a série como Mudanças Solicitadas. Isso 187 + pode ser útil quando o autor descobre um bug em sua própria série e deseja 188 + evitar que ela seja aplicada. 189 + 190 + O uso do bot é totalmente opcional; em caso de dúvida, ignore completamente a 191 + existência dele. Os mantenedores classificarão e atualizarão o estado dos 192 + patches por conta própria. Nenhum e-mail deve ser enviado à lista com o 193 + propósito principal de se comunicar com o bot; os comandos do bot devem ser 194 + vistos como metadados. 195 + 196 + O uso do bot é restrito aos autores dos patches (o cabeçalho ``From:`` no envio 197 + do patch e no comando deve coincidir!), mantenedores do código modificado de 198 + acordo com o arquivo MAINTAINERS (novamente, o ``From:`` deve coincidir 199 + com a entrada no MAINTAINERS) e alguns revisores seniores. 200 + 201 + O bot registra sua atividade aqui: 202 + 203 + https://netdev.bots.linux.dev/pw-bot.html 204 + 205 + Prazos de revisão 206 + ~~~~~~~~~~~~~~~~~ 207 + 208 + De modo geral, os patches são triados rapidamente (em menos de 48h). Mas 209 + seja paciente; se o seu patch estiver ativo no patchwork (ou seja, listado 210 + na lista de patches do projeto), as chances de ele ter sido esquecido são 211 + próximas de zero. 212 + 213 + O alto volume de desenvolvimento na netdev faz com que os revisores encerrem 214 + discussões de forma relativamente rápida. É muito improvável que novos 215 + comentários e respostas cheguem após uma semana de silêncio. Se um 216 + patch não estiver mais ativo no patchwork e a thread ficar inativa por mais de 217 + uma semana - esclareça os próximos passos e/ou envie a próxima versão. 218 + 219 + Especificamente para envios de RFC, se ninguém responder em uma semana ou os 220 + revisores perderam o envio ou não têm opiniões fortes a respeito. Se o código 221 + estiver pronto, reenvie como um PATCH. 222 + 223 + E-mails dizendo apenas "ping" ou "bump" são considerados rudes. Se você não 224 + conseguir identificar o status do patch pelo patchwork ou onde a discussão 225 + parou - descreva sua melhor suposição e pergunte se ela está correta. Por 226 + exemplo:: 227 + 228 + Não entendo quais são os próximos passos. A Pessoa X parece estar descontente 229 + com A; devo fazer B e enviar novamente os patches? 230 + 231 + .. _Solicitações de mudanças: 232 + 233 + Mudanças solicitadas 234 + ~~~~~~~~~~~~~~~~~~~~ 235 + 236 + Patches marcados como ``Changes Requested`` precisam ser revisados. A nova 237 + versão deve vir com um registro de alterações (changelog), 238 + preferencialmente incluindo links para as postagens anteriores, por exemplo:: 239 + 240 + [PATCH net-next v3] net: faz as vacas dizerem "muuu" 241 + 242 + Mesmo os usuários que não bebem leite apreciam ouvir as vacas dizendo 243 + "muuu". 244 + 245 + A quantidade de mugidos dependerá da taxa de pacotes, portanto, deve 246 + corresponder muito bem ao ciclo diurno. 247 + 248 + Signed-off-by: Joe Defarmer <joe@barn.org> 249 + --- 250 + v3: 251 + - adicionada uma nota sobre a flutuação do mugido conforme a hora 252 + do dia na 253 + mensagem de commit 254 + v2: https://lore.kernel.org/netdev/123themessageid@barn.org/ 255 + - corrigido argumento ausente na kernel doc para netif_is_bovine() 256 + - corrigido vazamento de memória (memory leak) em 257 + netdev_register_cow() 258 + v1: https://lore.kernel.org/netdev/456getstheclicks@barn.org/ 259 + 260 + A mensagem de commit deve ser revisada para responder a quaisquer perguntas que 261 + os revisores tenham feito em discussões anteriores. Ocasionalmente, a 262 + atualização da mensagem de commit será a única mudança na nova versão. 263 + 264 + Reenvios parciais 265 + ~~~~~~~~~~~~~~~~~ 266 + 267 + Por favor, sempre reenvie a série completa de patches e certifique-se de 268 + numerar seus patches de forma que fique claro que este é o conjunto mais 269 + recente e completo de patches que pode ser aplicado. Não tente reenviar apenas 270 + os patches que foram alterados. 271 + 272 + Lidando com patches aplicados incorretamente 273 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 274 + 275 + Ocasionalmente, uma série de patches é aplicada antes de receber feedback 276 + crítico, ou a versão errada de uma série é aplicada. 277 + 278 + Não é possível fazer o patch desaparecer uma vez que ele foi enviado (pushed); 279 + o histórico de commits nas árvores netdev é imutável. Por favor, envie versões 280 + incrementais sobre o que foi mesclado para corrigir os patches da maneira que 281 + eles ficariam se a sua série de patches mais recente fosse mesclada. 282 + 283 + Em casos onde uma reversão completa (revert) é necessária, a reversão deve ser 284 + enviada como um patch para a lista com uma mensagem de commit explicando os 285 + problemas técnicos com o commit revertido. Reversões devem ser usadas como 286 + último recurso, quando a mudança original está completamente errada; correções 287 + incrementais são preferidas. 288 + 289 + Árvore estável 290 + ~~~~~~~~~~~~~~ 291 + 292 + Embora antigamente as submissões para a netdev não devessem carregar tags 293 + explícitas ``CC: stable@vger.kernel.org``, esse não é mais o caso hoje em dia. 294 + Por favor, siga as regras padrão de estabilidade em 295 + ``Documentation/process/stable-kernel-rules.rst``, e certifique-se de incluir as 296 + tags Fixes apropriadas! 297 + 298 + Correções de segurança 299 + ~~~~~~~~~~~~~~~~~~~~~~ 300 + 301 + Não envie e-mails diretamente para os mantenedores da netdev se você acha que 302 + descobriu um bug que possa ter possíveis implicações de segurança. O atual 303 + mantenedor da netdev tem solicitado consistentemente que as pessoas usem as 304 + listas de discussão e não entrem em contato diretamente. Se você não estiver 305 + de acordo com isso, considere enviar um e-mail para security@kernel.org ou 306 + ler sobre http://oss-security.openwall.org/wiki/mailing-lists/distros como 307 + possíveis mecanismos alternativos. 308 + 309 + Envio conjunto de mudanças em componentes de espaço do usuário 310 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 311 + 312 + O código de espaço do usuário (*user space*) que exercita funcionalidades do 313 + kernel deve ser enviado juntamente com os patches do kernel. Isso dá aos 314 + revisores a chance de ver como qualquer nova interface é usada e quão 315 + bem ela funciona. 316 + 317 + Quando as ferramentas de espaço do usuário residem no próprio repositório do 318 + kernel, todas as alterações devem geralmente vir em uma única série. Se a série 319 + se tornar muito grande ou se o projeto de espaço do usuário não for revisado na 320 + netdev, inclua um link para um repositório público onde os patches de espaço do 321 + usuário possam ser vistos. 322 + 323 + No caso de ferramentas de espaço do usuário residirem em um repositório 324 + separado, mas serem revisadas na netdev (por exemplo, patches para ferramentas 325 + ``iproute2``), os patches do kernel e do espaço do usuário devem formar séries 326 + (threads) separadas quando postados na lista de discussão, por exemplo:: 327 + 328 + [PATCH net-next 0/3] net: carta de apresentação de alguma funcionalidade 329 + └─ [PATCH net-next 1/3] net: preparação para alguma funcionalidade 330 + └─ [PATCH net-next 2/3] net: implementação de alguma funcionalidade 331 + └─ [PATCH net-next 3/3] selftest: net: alguma funcionalidade 332 + 333 + [PATCH iproute2-next] ip: adiciona suporte para alguma funcionalidade 334 + 335 + A postagem em uma única thread é desencorajada porque confunde o patchwork 336 + (a partir da versão 2.2.2 do patchwork). 337 + 338 + Envio conjunto de selftests 339 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 340 + 341 + Os selftests devem fazer parte da mesma série que as mudanças de código. 342 + Especificamente para correções, tanto a mudança de código quanto o teste 343 + relacionado devem ir para a mesma árvore (os testes podem não ter uma tag 344 + Fixes, o que é esperado). Misturar mudanças de código e mudanças de teste em 345 + um único commit é desencorajado. 346 + 347 + Preparando as mudanças 348 + ---------------------- 349 + 350 + Atenção aos detalhes é importante. Releia seu próprio trabalho como se você 351 + fosse o revisor. Você pode começar usando o ``checkpatch.pl``, talvez até com 352 + a flag ``--strict``. Mas não seja robótico e irracional ao fazer isso. Se sua 353 + mudança for uma correção de bug, certifique-se de que seu log de commit indique 354 + o sintoma visível para o usuário final, a razão subjacente de por que isso 355 + acontece e, se necessário, explique por que a correção proposta é a melhor 356 + maneira de resolver as coisas. Não corrompa espaços em branco e, como é comum, 357 + não use recuos incorretos em argumentos de função que abrangem várias linhas. 358 + Se for o seu primeiro patch, envie-o para si mesmo por e-mail para que você 359 + possa testar a aplicação em uma árvore sem patches para confirmar que a 360 + infraestrutura não o danificou. 361 + 362 + Finalmente, volte e leia ``Documentation/process/submitting-patches.rst`` 363 + para ter certeza de que não está repetindo algum erro comum documentado lá. 364 + 365 + Indicando a árvore de destino 366 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 367 + 368 + Para ajudar os mantenedores e os bots de CI, você deve marcar explicitamente 369 + qual árvore seu patch tem como alvo. Supondo que você use git, utilize a flag 370 + de prefixo:: 371 + 372 + git format-patch --subject-prefix='PATCH net-next' inicio..fim 373 + 374 + Use ``net`` em vez de ``net-next`` (sempre em letras minúsculas) no comando 375 + acima para conteúdos de correção de bugs da árvore ``net``. 376 + 377 + Dividindo o trabalho em patches 378 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 379 + 380 + Coloque-se no lugar do revisor. Cada patch é lido separadamente e, portanto, 381 + deve constituir um passo compreensível em direção ao seu objetivo declarado. 382 + 383 + Evite enviar séries com mais de 15 patches. Séries maiores levam mais tempo 384 + para serem revisadas, pois os revisores adiarão a análise até encontrarem um 385 + grande bloco de tempo disponível. Uma série pequena pode ser revisada em pouco 386 + tempo, então os mantenedores simplesmente a revisam de imediato. Como resultado, 387 + uma sequência de séries menores é mesclada mais rapidamente e com melhor 388 + cobertura de revisão. Reenviar séries grandes também aumenta o tráfego na lista 389 + de discussão. 390 + 391 + Limitar patches pendentes na lista de discussão 392 + ----------------------------------------------- 393 + 394 + Evite ter mais de 15 patches, em todas as séries, pendentes de revisão na lista 395 + de discussão para uma única árvore. Em outras palavras, um máximo de 15 patches 396 + sob revisão na ``net`` e um máximo de 15 patches sob revisão na ``net-next``. 397 + 398 + Este limite tem o objetivo de focar o esforço do desenvolvedor nos testes dos 399 + patches antes da revisão upstream, auxiliando a qualidade das submissões 400 + upstream e aliviando a carga sobre os revisores. 401 + 402 + Ordenação de variáveis locais ("árvore invertida", "RCS") 403 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 404 + 405 + A netdev tem uma convenção para ordenar variáveis locais em funções. Ordene as 406 + linhas de declaração de variáveis da mais longa para a mais curta, por exemplo:: 407 + 408 + struct scatterlist *sg; 409 + struct sk_buff *skb; 410 + int err, i; 411 + 412 + Se houver dependências entre as variáveis que impeçam a ordenação, mova a 413 + inicialização para fora da linha de declaração. 414 + 415 + Precedência de formatação 416 + ~~~~~~~~~~~~~~~~~~~~~~~~~ 417 + 418 + Ao trabalhar em código existente que utiliza formatação não padrão, faça com 419 + que seu código siga as diretrizes mais recentes, para que, eventualmente, 420 + todo o código no domínio da netdev esteja no formato preferido. 421 + 422 + Uso de construções gerenciadas por dispositivo e cleanup.h 423 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 424 + 425 + Historicamente, a netdev permanece cética em relação às promessas de todas as 426 + APIs de "auto-limpeza" (auto-cleanup), incluindo até mesmo os auxiliares 427 + ``devm_``. Eles não são o estilo preferido de implementação, apenas um estilo 428 + aceitável. 429 + 430 + O uso de ``guard()`` é desencorajado em qualquer função com mais de 20 linhas; 431 + ``scoped_guard()`` é considerado mais legível. O uso de lock/unlock normal 432 + ainda é (levemente) preferido. 433 + 434 + Construções de limpeza de baixo nível (como ``__free()``) podem ser usadas ao 435 + construir APIs e auxiliares, especialmente iteradores com escopo. No entanto, o 436 + uso direto de ``__free()`` dentro do núcleo de rede (networking core) e drivers 437 + é desencorajado. Orientações semelhantes se aplicam à declaração de variáveis 438 + no meio da função. 439 + 440 + Patches de limpeza (Clean-up patches) 441 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 442 + 443 + A netdev desencoraja patches que realizam limpezas simples que não estejam no 444 + contexto de outro trabalho. Por exemplo: 445 + 446 + * Tratar avisos do ``checkpatch.pl`` e outros avisos triviais de estilo de 447 + codificação 448 + * Tratar problemas de Ordenação de variáveis locais 449 + * Conversões para APIs gerenciadas por dispositivo (auxiliares ``devm_``) 450 + 451 + Isso ocorre porque se considera que a agitação (*churn*) que tais mudanças 452 + produzem tem um custo maior do que o valor de tais limpezas. 453 + 454 + Por outro lado, correções de ortografia e gramática não são desencorajadas. 455 + 456 + Reenviando após a revisão 457 + ~~~~~~~~~~~~~~~~~~~~~~~~~ 458 + 459 + Aguarde pelo menos 24 horas entre as postagens. Isso garantirá que revisores de 460 + todas as localizações geográficas tenham a chance de se manifestar. Não espere 461 + muito tempo (semanas) entre as postagens, pois isso tornará mais difícil para 462 + os revisores lembrarem de todo o contexto. 463 + 464 + Certifique-se de tratar todo o feedback em sua nova postagem. Não envie uma 465 + nova versão do código se a discussão sobre a versão anterior ainda estiver em 466 + andamento, a menos que seja instruído diretamente por um revisor. 467 + 468 + A nova versão dos patches deve ser postada como uma thread separada, não como 469 + uma resposta à postagem anterior. O registro de alterações (changelog) deve 470 + incluir um link para a postagem anterior (veja :ref:`Solicitações 471 + de mudanças`). 472 + 473 + Testes 474 + ------ 475 + 476 + Nível de teste esperado 477 + ~~~~~~~~~~~~~~~~~~~~~~~ 478 + 479 + No mínimo, suas alterações devem passar por uma compilação ``allyesconfig`` e 480 + uma ``allmodconfig`` com ``W=1`` definido, sem novos avisos ou falhas. 481 + 482 + O ideal é que você tenha feito testes em tempo de execução específicos para sua 483 + alteração, e que a série de patches contenha um conjunto de selftests do kernel 484 + para ``tools/testing/selftests/net`` ou usando o framework KUnit. 485 + 486 + Espera-se que você teste suas alterações no topo da árvore de rede relevante 487 + (``net`` ou ``net-next``) e não, por exemplo, em uma árvore estável ou na 488 + ``linux-next``. 489 + 490 + Verificações do patchwork 491 + ~~~~~~~~~~~~~~~~~~~~~~~~~ 492 + 493 + As verificações (*checks*) no patchwork são, em sua maioria, wrappers simples 494 + em torno de scripts existentes do kernel; as fontes estão disponíveis em: 495 + 496 + https://github.com/linux-netdev/nipa/tree/master/tests 497 + 498 + **Não** envie seus patches apenas para executá-los nas verificações. Você deve 499 + garantir que seus patches estejam prontos, testando-os localmente antes de 500 + postar na lista de discussão. A instância do bot de build do patchwork fica 501 + sobrecarregada com muita facilidade e a netdev@vger realmente não precisa de 502 + mais tráfego se pudermos evitar. 503 + 504 + netdevsim 505 + ~~~~~~~~~ 506 + 507 + O ``netdevsim`` é um driver de teste que pode ser usado para exercitar APIs de 508 + configuração de driver sem a necessidade de hardware compatível. Mock-ups e 509 + testes baseados no ``netdevsim`` são fortemente encorajados ao adicionar novas 510 + APIs, mas o ``netdevsim`` em si **não** é considerado um caso de uso/usuário. 511 + Você também deve implementar as novas APIs em um driver real. 512 + 513 + Não damos garantias de que o ``netdevsim`` mudará no futuro de uma forma que 514 + quebraria o que normalmente seria considerado uAPI. O ``netdevsim`` é reservado 515 + apenas para uso por testes upstream, portanto, quaisquer novos recursos do 516 + ``netdevsim`` devem ser acompanhados de selftests em ``tools/testing/selftests/``. 517 + 518 + Status de suporte para drivers 519 + ------------------------------ 520 + 521 + .. note: 522 + 523 + Os requisitos a seguir aplicam-se apenas a drivers de NIC Ethernet. 524 + 525 + A netdev define requisitos adicionais para drivers que desejam adquirir o status 526 + ``Supported`` (Suportado) no arquivo MAINTAINERS. Drivers ``Supported`` devem 527 + executar todos os testes de driver upstream e relatar os resultados duas vezes 528 + por dia. Drivers que não cumprirem este requisito devem usar o status 529 + ``Maintained`` (Mantido). Atualmente, não há diferença na forma como os drivers 530 + ``Supported`` e ``Maintained`` são tratados no upstream. 531 + 532 + As regras exatas que um driver deve seguir para adquirir o status ``Supported``: 533 + 534 + 1. Deve executar todos os testes sob os alvos ``drivers/net`` e 535 + ``drivers/net/hw`` dos selftests do Linux. A execução e o relato 536 + de testes privados / internos também são bem-vindos, mas os testes 537 + upstream são obrigatórios. 538 + 539 + 2. A frequência mínima de execução é uma vez a cada 12 horas. Deve 540 + testar o branch designado a partir do feed de branches selecionado. 541 + Observe que os branches são construídos automaticamente e estão 542 + expostos à postagem intencional de patches maliciosos; portanto, 543 + os sistemas de teste devem ser isolados. 544 + 545 + 3. Drivers que suportam múltiplas gerações de dispositivos devem 546 + testar pelo menos um dispositivo de cada geração. Um manifesto do 547 + ambiente de teste (*testbed manifest* - formato exato a definir) 548 + deve descrever os modelos de dispositivos testados. 549 + 550 + 4. Os testes devem ser executados de forma confiável; se múltiplos 551 + branches forem ignorados ou se os testes falharem devido a problemas 552 + no ambiente de execução, o status ``Supported`` será retirado. 553 + 554 + 5. Falhas nos testes devido a bugs no driver ou no próprio teste, 555 + ou falta de suporte para a funcionalidade que o teste visa, *não* 556 + são motivo para a perda do status ``Supported``. 557 + 558 + O CI da netdev manterá uma página oficial de dispositivos suportados, listando 559 + seus resultados de testes recentes. 560 + 561 + O mantenedor do driver pode providenciar para que outra pessoa execute o teste; 562 + não há exigência de que a pessoa listada como mantenedora (ou seu empregador) 563 + seja responsável pela execução dos testes. Colaborações entre 564 + fornecedores, hospedagem de CI no GitHub (GH CI), outros repositórios sob o 565 + linux-netdev, etc., são muito bem-vindas. 566 + 567 + Veja https://github.com/linux-netdev/nipa/wiki para mais informações sobre o CI 568 + da netdev. Sinta-se à vontade para entrar em contato com os mantenedores ou com 569 + a lista para quaisquer dúvidas. 570 + 571 + Orientações para revisores 572 + -------------------------- 573 + 574 + Revisar patches de outras pessoas na lista é altamente incentivado, 575 + independentemente do nível de experiência. Para orientações gerais e dicas 576 + úteis, consulte `revisão de tópicos avançados de desenvolvimento`. 577 + 578 + É seguro assumir que os mantenedores da netdev conhecem a comunidade e o nível 579 + de experiência dos revisores. Os revisores não devem se preocupar com o fato de 580 + seus comentários impedirem ou desviarem o fluxo de patches. Revisores menos 581 + experientes são fortemente incentivados a fazer uma revisão mais aprofundada das 582 + submissões e não focar exclusivamente em questões triviais ou subjetivas, como 583 + formatação de código, tags, etc. 584 + 585 + Depoimentos / feedback 586 + ---------------------- 587 + 588 + Algumas empresas utilizam o feedback de colegas em revisões de desempenho de 589 + funcionários. Sinta-se à vontade para solicitar feedback dos mantenedores da 590 + netdev, especialmente se você dedica uma quantidade significativa de tempo 591 + revisando código e se esforça além do esperado para melhorar a infraestrutura 592 + compartilhada. 593 + 594 + O feedback deve ser solicitado por você, o colaborador, e será sempre 595 + compartilhado com você (mesmo que você solicite que ele seja enviado ao seu 596 + gerente).
+28
Documentation/translations/pt_BR/process/maintainer-soc-clean-dts.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ===================================================== 4 + Plataformas SoC com Requisitos de Conformidade de DTS 5 + ===================================================== 6 + 7 + Visão Geral 8 + ----------- 9 + 10 + As plataformas SoC ou subarquiteturas devem seguir todas as regras de 11 + Documentation/process/maintainer-soc.rst. Este documento, referenciado em 12 + MAINTAINERS, impõe requisitos adicionais listados abaixo. 13 + 14 + Conformidade Estrita com DT Schema de DTS e dtc 15 + ----------------------------------------------- 16 + 17 + Nenhuma alteração nos arquivos de origem do Devicetree da plataforma SoC 18 + (arquivos DTS) deve introduzir novos avisos de ``make dtbs_check W=1``. 19 + Avisos em um novo DTS de placa, que sejam resultado de problemas em um 20 + arquivo DTSI incluído, são considerados avisos existentes, não novos. 21 + Para séries divididas entre árvores diferentes (vínculos de DT seguem pela 22 + árvore do subsistema de drivers), os avisos no linux-next são decisivos. 23 + Os mantenedores da plataforma possuem automação implementada que deve 24 + apontar quaisquer novos avisos. 25 + 26 + Se um commit que introduz novos avisos for aceito de alguma forma, os 27 + problemas resultantes deverão ser corrigidos em um tempo razoável 28 + (por exemplo, dentro de um ciclo de lançamento) ou o commit será revertido.
+222
Documentation/translations/pt_BR/process/maintainer-soc.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ============== 4 + Subsistema SoC 5 + ============== 6 + 7 + Visão Geral 8 + ----------- 9 + 10 + O subsistema SoC é um local de agregação para códigos específicos de SoC 11 + System on Chip). Os principais componentes do subsistema são: 12 + 13 + * Devicetrees (DTS) para ARM de 32 e 64 bits e RISC-V. 14 + * Arquivos de placa (board files) ARM de 32 bits (arch/arm/mach*). 15 + * Defconfigs ARM de 32 e 64 bits. 16 + * Drivers específicos de SoC em diversas arquiteturas, em particular para ARM de 17 + * 32 e 64 bits, RISC-V e Loongarch. 18 + 19 + Estes "drivers específicos de SoC" não incluem drivers de clock, GPIO, etc., que 20 + possuem outros mantenedores de alto nível. O diretório ``drivers/soc/`` é 21 + geralmente destinado a drivers internos do kernel que são usados por outros 22 + drivers para fornecer funcionalidades específicas do SoC, como identificar uma 23 + revisão do chip ou fazer a interface com domínios de energia. 24 + 25 + O subsistema SoC também serve como um local intermediário para alterações em 26 + ``drivers/bus``, ``drivers/firmware``, ``drivers/reset`` e ``drivers/memory``. 27 + A adição de novas plataformas, ou a remoção de existentes, geralmente passa pela 28 + árvore SoC como um branch dedicado cobrindo múltiplos subsistemas. 29 + 30 + A árvore principal do SoC está hospedada no git.kernel.org: 31 + https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git/ 32 + 33 + Mantenedores 34 + ------------ 35 + 36 + Claramente, esta é uma gama bastante ampla de tópicos, que nenhuma pessoa, ou 37 + mesmo um pequeno grupo de pessoas, é capaz de manter. Em vez disso, o 38 + subsistema SoC é composto por muitos submantenedores (mantenedores de 39 + plataforma), cada um cuidando de plataformas individuais e subdiretórios de 40 + drivers. 41 + 42 + Nesse sentido, "plataforma" geralmente se refere a uma série de SoCs de um 43 + determinado fornecedor, por exemplo, a série de SoCs Tegra da Nvidia. Muitos 44 + submantenedores operam em nível de fornecedor, sendo responsáveis por várias 45 + linhas de produtos. Por diversos motivos, incluindo aquisições ou diferentes 46 + unidades de negócios em uma empresa, as coisas variam significativamente aqui. 47 + Os diversos submantenedores estão documentados no arquivo ``MAINTAINERS``. 48 + 49 + A maioria desses submantenedores possui suas próprias árvores onde preparam os 50 + patches, enviando pull requests para a árvore SoC principal. Essas árvores são 51 + geralmente, mas nem sempre, listadas em ``MAINTAINERS``. 52 + 53 + O que a árvore SoC não é, contudo, é um local para alterações de código 54 + específicas da arquitetura. Cada arquitetura possui seus próprios mantenedores 55 + que são responsáveis pelos detalhes arquiteturais, erratas de CPU e afins. 56 + 57 + Submetendo Patches para um Determinado SoC 58 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 59 + 60 + Todos os patches típicos relacionados à plataforma devem ser enviados por meio 61 + dos submantenedores de SoC (mantenedores específicos da plataforma). Isso inclui 62 + também alterações em defconfigs por plataforma ou compartilhadas. Note que 63 + ``scripts/get_maintainer.pl`` pode não fornecer os endereços corretos para a 64 + defconfig compartilhada; portanto, ignore sua saída e crie manualmente a lista 65 + de CC baseada no arquivo ``MAINTAINERS`` ou use algo como 66 + ``scripts/get_maintainer.pl -f drivers/soc/FOO/``. 67 + 68 + Submetendo Patches para os Mantenedores Principais de SoC 69 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 70 + 71 + Os mantenedores principais de SoC podem ser contatados via o alias 72 + soc@kernel.org apenas nos seguintes casos: 73 + 74 + 1. Não existem mantenedores específicos para a plataforma. 75 + 76 + 2. Os mantenedores específicos da plataforma não respondem. 77 + 78 + 3. Introdução de uma plataforma SoC completamente nova. Tal trabalho de novo SoC 79 + deve ser enviado primeiro para as listas de discussão comuns, indicadas por 80 + ``scripts/get_maintainer.pl``, para revisão da comunidade. Após uma revisão 81 + positiva da comunidade, o trabalho deve ser enviado para soc@kernel.org em 82 + um único conjunto de patches (*patchset*) contendo a nova entrada em 83 + ``arch/foo/Kconfig``, arquivos DTS, entrada no arquivo ``MAINTAINERS`` e, 84 + opcionalmente, drivers iniciais com seus respectivos bindings de Devicetree. 85 + A entrada no arquivo ``MAINTAINERS`` deve listar os novos mantenedores 86 + específicos da plataforma, que serão responsáveis por lidar com os patches 87 + da plataforma de agora em diante. 88 + 89 + Note que o endereço soc@kernel.org geralmente não é o local para discutir os 90 + patches; portanto, o trabalho enviado para este endereço já deve ser 91 + considerado aceitável pela comunidade. 92 + 93 + Informações para (novos) Submantenedores 94 + ---------------------------------------- 95 + 96 + À medida que novas plataformas surgem, elas frequentemente trazem consigo novos 97 + submantenedores, muitos dos quais trabalham para o fornecedor do silício e podem 98 + não estar familiarizados com o processo. 99 + 100 + Estabilidade da ABI do Devicetree 101 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 102 + 103 + Talvez um dos pontos mais importantes a destacar é que os *dt-bindings* 104 + documentam a ABI entre o devicetree e o kernel. Por favor, leia 105 + ``Documentation/devicetree/bindings/ABI.rst``. 106 + 107 + Se estiverem sendo feitas alterações em um DTS que sejam incompatíveis com 108 + kernels antigos, o patch do DTS não deve ser aplicado até que o driver seja, ou 109 + em um momento apropriado posterior. Mais importante ainda, quaisquer alterações 110 + incompatíveis devem ser claramente apontadas na descrição do patch e no pull 111 + request, juntamente com o impacto esperado nos usuários existentes, como 112 + bootloaders ou outros sistemas operacionais. 113 + 114 + Dependências de Branch de Driver 115 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 116 + 117 + Um problema comum é a sincronização de alterações entre drivers de dispositivos 118 + e arquivos de devicetree. Mesmo que uma alteração seja compatível em ambas as 119 + direções, isso pode exigir a coordenação de como as mudanças são mescladas 120 + através de diferentes árvores de mantenedores. 121 + 122 + Geralmente, o branch que inclui uma alteração de driver também incluirá a 123 + mudança correspondente na descrição do binding do devicetree, para garantir que 124 + sejam, de fato, compatíveis. Isso significa que o branch do devicetree pode 125 + acabar causando avisos na etapa ``make dtbs_check``. Se uma alteração de 126 + devicetree depender de adições ausentes em um arquivo de cabeçalho em 127 + ``include/dt-bindings/``, ela falhará na etapa ``make dtbs`` e não será mesclada. 128 + 129 + Existem várias maneiras de lidar com isso: 130 + 131 + * Evite definir macros personalizadas em ``include/dt-bindings/`` para constantes 132 + de hardware que podem ser derivadas de um datasheet -- macros de binding em 133 + arquivos de cabeçalho devem ser usadas apenas como último recurso, se não 134 + houver uma maneira natural de definir um binding. 135 + 136 + * Use valores literais no arquivo devicetree em vez de macros, mesmo quando um 137 + cabeçalho for necessário, e altere-os para a representação nomeada em um 138 + lançamento posterior. 139 + 140 + * Adie as alterações do devicetree para um lançamento após o binding e o driver 141 + já terem sido mesclados. 142 + 143 + * Altere os bindings em um branch imutável compartilhado que seja usado como 144 + base tanto para a alteração do driver quanto para as alterações do devicetree. 145 + 146 + * Adicione definições duplicadas no arquivo devicetree protegidas por uma seção 147 + ``#ifndef``, removendo-as em um lançamento posterior. 148 + 149 + Convenção de Nomenclatura de Devicetree 150 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 151 + 152 + O esquema geral de nomenclatura para arquivos de devicetree é o seguinte. Os 153 + aspectos de uma plataforma que são definidos no nível do SoC, como núcleos de 154 + CPU, são contidos em um arquivo nomeado ``$soc.dtsi``, por exemplo, 155 + ``jh7100.dtsi``. Detalhes de integração, que variam de placa para placa, são 156 + descritos em ``$soc-$board.dts``. Um exemplo disso é 157 + ``jh7100-beaglev-starlight.dts``. Frequentemente, muitas placas são variações 158 + de um mesmo tema, e é comum haver arquivos intermediários, como 159 + ``jh7100-common.dtsi``, que ficam entre os arquivos ``$soc.dtsi`` e 160 + ``$soc-$board.dts``, contendo as descrições de hardware comum. 161 + 162 + Algumas plataformas também possuem *System on Modules* (SoM), contendo um SoC, 163 + que são então integrados em diversas placas diferentes. Para essas plataformas, 164 + ``$soc-$som.dtsi`` e ``$soc-$som-$board.dts`` são típicos. 165 + 166 + Os diretórios geralmente são nomeados após o fornecedor do SoC no momento de sua 167 + inclusão, o que leva a alguns nomes de diretórios históricos na árvore. 168 + 169 + Validando Arquivos de Devicetree 170 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 171 + 172 + ``make dtbs_check`` pode ser usado para validar se os arquivos de devicetree 173 + estão em conformidade com os *dt-bindings* que descrevem a ABI. Por favor, leia 174 + a seção "Running checks" de ``Documentation/devicetree/bindings/writing-schema.rst`` 175 + para mais informações sobre a validação de devicetrees. 176 + 177 + Para novas plataformas, ou adições a plataformas existentes, ``make dtbs_check`` 178 + não deve adicionar nenhum aviso (*warning*) novo. Para SoCs RISC-V e Samsung, é 179 + exigido que ``make dtbs_check W=1`` não adicione nenhum novo aviso. 180 + Se houver qualquer dúvida sobre uma alteração de devicetree, entre em contato 181 + com os mantenedores de devicetree. 182 + 183 + Branches e Pull Requests 184 + ~~~~~~~~~~~~~~~~~~~~~~~~ 185 + 186 + Assim como a árvore SoC principal possui vários branches, espera-se que os 187 + submantenedores façam o mesmo. Alterações de drivers, defconfig e devicetree 188 + devem ser todas divididas em branches separados e aparecer em pull requests 189 + distintos para os mantenedores de SoC. Cada branch deve ser utilizável por si só 190 + e evitar regressões originadas de dependências em outros branches. 191 + 192 + Pequenos conjuntos de patches também podem ser enviados como e-mails separados 193 + para soc@kernel.org, agrupados nas mesmas categorias. 194 + 195 + Se as alterações não se encaixarem nos padrões normais, pode haver branches de 196 + nível superior adicionais, por exemplo, para uma reformulação em toda a árvore 197 + (*treewide rework*) ou a adição de novas plataformas SoC, incluindo arquivos dts 198 + e drivers. 199 + 200 + Branches com muitas alterações podem se beneficiar ao serem divididos em 201 + branches de tópicos separados, mesmo que acabem sendo mesclados no mesmo branch 202 + da árvore SoC. Um exemplo aqui seria um branch para correções de avisos de 203 + devicetree, um para uma reformulação e um para placas recém-adicionadas. 204 + 205 + Outra forma comum de dividir as alterações é enviar um pull request antecipado 206 + com a maioria das mudanças em algum momento entre rc1 e rc4, seguido por um ou 207 + mais pull requests menores no final do ciclo, que podem adicionar alterações 208 + tardias ou resolver problemas identificados durante os testes do primeiro 209 + conjunto. 210 + 211 + Embora não haja um prazo limite para pull requests tardios, ajuda enviar apenas 212 + branches pequenos à medida que o tempo se aproxima da janela de mesclagem 213 + (*merge window*). 214 + 215 + Pull requests para correções de bugs (*bugfixes*) da versão atual podem ser 216 + enviados a qualquer momento, mas, novamente, ter múltiplos branches menores é 217 + melhor do que tentar combinar muitos patches em um único pull request. 218 + 219 + A linha de assunto de um pull request deve começar com "[GIT PULL]" e ser feita 220 + usando uma tag assinada, em vez de um branch. Esta tag deve conter uma breve 221 + descrição resumindo as alterações no pull request. Para mais detalhes sobre o 222 + envio de pull requests, consulte ``Documentation/maintainer/pull-requests.rst``.
+2 -1
Documentation/translations/sp_SP/process/4.Coding.rst
··· 336 336 empaqueta); luego, puede ejecutarse en el código agregando "C=1" a su 337 337 comando make. 338 338 339 - La herramienta "Coccinelle" (http://coccinelle.lip6.fr/) puede encontrar 339 + La herramienta "Coccinelle" (https://coccinelle.gitlabpages.inria.fr/website/) 340 + puede encontrar 340 341 una amplia variedad de posibles problemas de codificación; también puede 341 342 proponer correcciones para esos problemas. Bastantes "parches semánticos" 342 343 para el kernel se han empaquetado en el directorio scripts/coccinelle;
+1 -1
Documentation/translations/sp_SP/process/submitting-patches.rst
··· 30 30 31 31 Algunos subsistemas y árboles de mantenimiento cuentan con información 32 32 adicional sobre su flujo de trabajo y expectativas, consulte 33 - :ref:`Documentation/process/maintainer-handbooks.rst <maintainer_handbooks_main>`. 33 + Documentation/process/maintainer-handbooks.rst. 34 34 35 35 Obtenga el código fuente actual 36 36 --------------------------------
+3 -3
Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst
··· 198 198 199 199 - yield_task(...) 200 200 201 - Esta función es básicamente desencolar, seguido por encolar, a menos que 202 - sysctl compat_yield esté activado; en ese caso, sitúa la entidad a gestionar 203 - en la parte más hacia la derecha del árbol rojo-negro. 201 + Esta función cede la CPU desplazando la posición de la tarea actualmente 202 + en ejecución hacia atrás en la cola de ejecución, para que otras tareas 203 + ejecutables sean planificadas primero. 204 204 205 205 - check_preempt_curr(...) 206 206
+1 -1
Documentation/translations/zh_CN/dev-tools/testing-overview.rst
··· 154 154 Coccinelle可能是最容易写检查的。它在预处理器之前工作,所以用Coccinelle 155 155 检查宏中的错误更容易。Coccinelle还能为你创建补丁,这是其他工具无法做到的。 156 156 157 - 例如,用Coccinelle你可以从 ``kmalloc_array(x, size, GFP_KERNEL)`` 157 + 例如,用Coccinelle你可以从 ``kmalloc(x * size, GFP_KERNEL)`` 158 158 到 ``kmalloc_array(x, size, GFP_KERNEL)`` 进行大规模转换,这真的很 159 159 有用。如果你只是创建一个Smatch警告,并试图把转换的工作推给维护者,他们会很 160 160 恼火。你将不得不为每个警告争论是否真的可以溢出。
+23 -29
Documentation/translations/zh_CN/process/2.Process.rst
··· 23 23 总览 24 24 ---- 25 25 26 - 内核开发人员使用一个松散的基于时间的发布过程,每两到三个月发布一次新的主要 27 - 内核版本。最近的发布历史记录如下: 26 + 内核开发使用一个松散的、基于时间的滚动发布(rolling release)开发模型。 27 + 一个新的主内核发行版本(作为示例,我们将其称为 9.x) [1]_ 大约每两到三个月 28 + 发布一次,它带来了新特性、内部 API 的更改等。一个典型的版本包含大约 13,000 29 + 个变更集(changesets),涉及几十万行代码的修改。最近的发行版本及其日期可以 30 + 在这里找到 31 + `维基百科 <https://en.wikipedia.org/wiki/Linux_kernel_version_history>`_ 28 32 29 - ====== ================= 30 - 5.0 2019年3月3日 31 - 5.1 2019年5月5日 32 - 5.2 2019年7月7日 33 - 5.3 2019年9月15日 34 - 5.4 2019年11月24日 35 - 5.5 2020年1月6日 36 - ====== ================= 37 33 38 - 每个5.x版本都是一个主要的内核版本,具有新特性、内部API更改等等。一个典型的5.x 39 - 版本包含大约13000个变更集,变更了几十万行代码。因此,5.x是Linux内核开发的前 40 - 沿;内核使用滚动开发模型,不断集成重大变化。 34 + .. [1] 严格来说,Linux 内核并不采用语义化版本号方案,而是将 9.x 这一组数字 35 + 作为一个整体来标识主发行版本号。对于每一个版本,x 都会递增,但只有 36 + 当 x 被认为足够大时,9 才会递增(例如:Linux 5.0 是紧随 Linux 4.20 37 + 之后发布的)。 41 38 42 39 对于每个版本的补丁合并,遵循一个相对简单的规则。在每个开发周期的开头,“合并 43 40 窗口”被打开。这时,被认为足够稳定(并且被开发社区接受)的代码被合并到主线内 ··· 45 48 提前收集、测试和分级的。稍后将详细描述该过程的工作方式。) 46 49 47 50 合并窗口持续大约两周。在这段时间结束时,Linus Torvalds将声明窗口已关闭,并 48 - 释放第一个“rc”内核。例如,对于目标为5.6的内核,在合并窗口结束时发生的释放 49 - 将被称为5.6-rc1。-rc1 版本是一个信号,表示合并新特性的时间已经过去,稳定下一 51 + 释放第一个“rc”内核。例如,对于目标为9.x的内核,在合并窗口结束时发生的释放 52 + 将被称为9.x-rc1。-rc1 版本是一个信号,表示合并新特性的时间已经过去,稳定下一 50 53 个内核的时间已经到来。 51 54 52 55 在接下来的6到10周内,只有修复问题的补丁才应该提交给主线。有时会允许更大的 ··· 81 84 开发人员的目标是在稳定发布之前修复所有已知的回归。在现实世界中,这种完美是 82 85 很难实现的;在这种规模的项目中,变数太多了。需要说明的是,延迟最终版本只会 83 86 使问题变得更糟;等待下一个合并窗口的更改将变多,导致下次出现更多的回归错误。 84 - 因此,大多数5.x内核都有一些已知的回归错误,不过,希望没有一个是严重的。 87 + 因此,大多数内核发布时都会带有一部分已知的回归问题,不过希望它们都不是严重 88 + 的问题。 85 89 86 90 一旦一个稳定的版本发布,它的持续维护工作就被移交给“稳定团队”,目前由 87 - Greg Kroah-Hartman领导。稳定团队将使用5.x.y编号方案不定期地发布稳定版本的 88 - 更新。要合入更新版本,补丁必须(1)修复一个重要的缺陷,且(2)已经合并到 91 + Greg Kroah-Hartman领导。稳定团队将使用9.x.y编号方案不定期地发布稳定版本的 92 + 更新。 93 + 94 + 要合入更新版本,补丁必须(1)修复一个重要的缺陷,且(2)已经合并到 89 95 下一个开发版本主线中。内核通常会在其初始版本后的一个以上的开发周期内收到 90 96 稳定版更新。例如,5.2内核的历史如下(2019年): 91 97 ··· 105 105 106 106 5.2.21是5.2版本的最终稳定更新。 107 107 108 - 有些内核被指定为“长期”内核;它们将得到更长时间的支持。在本文中,当前的长期 109 - 内核及其维护者是: 108 + 有些内核被指定为“长期”内核;它们将得到更长时间的支持。请参考以下链接 109 + 获取当前长期支持内核版本及其维护者的列表: 110 110 111 - ====== ================================ ================ 112 - 3.16 Ben Hutchings (长期稳定内核) 113 - 4.4 Greg Kroah-Hartman & Sasha Levin (长期稳定内核) 114 - 4.9 Greg Kroah-Hartman & Sasha Levin 115 - 4.14 Greg Kroah-Hartman & Sasha Levin 116 - 4.19 Greg Kroah-Hartman & Sasha Levin 117 - 5.4 Greg Kroah-Hartman & Sasha Levin 118 - ====== ================================ ================ 111 + https://www.kernel.org/category/releases.html 119 112 120 113 长期支持内核的选择纯粹是维护人员是否有需求和时间来维护该版本的问题。 121 114 目前还没有为即将发布的任何特定版本提供长期支持的已知计划。 ··· 313 320 没有完成家庭作业的人感到不耐烦。 314 321 315 322 - 避免顶部回复(把你的答案放在你要回复的引文上面的做法)。这会让你的回答更难 316 - 理解,印象也很差。 323 + 理解,印象也很差,详细请查看 324 + :ref:`Documentation/process/submitting-patches.rst <interleaved_replies>` 317 325 318 326 - 在正确的邮件列表发问。linux-kernel 可能是通用的讨论场所,但它不是寻找所有 319 327 子系统开发人员的最佳场所。
+1 -1
Documentation/translations/zh_CN/process/4.Coding.rst
··· 216 216 可以在 https://sparse.wiki.kernel.org/index.php/Main_page 找到), 217 217 然后可以通过在make命令中添加“C=1”在代码上运行它。 218 218 219 - “Coccinelle”工具 :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>` 219 + “Coccinelle”工具 :ref:`https://coccinelle.gitlabpages.inria.fr/website/ <devtools_coccinelle>` 220 220 能够发现各种潜在的编码问题;它还可以为这些问题提出修复方案。在 221 221 scripts/coccinelle目录下已经打包了相当多的内核“语义补丁”;运行 222 222 “make coccicheck”将运行这些语义补丁并报告发现的任何问题。有关详细信息,请参阅
+5 -4
Documentation/translations/zh_CN/rust/arch-support.rst
··· 19 19 ============= ================ ============================================== 20 20 架构 支持水平 限制因素 21 21 ============= ================ ============================================== 22 - ``arm64`` Maintained 只有小端序 22 + ``arm`` Maintained 仅 ARMv7 小端序。 23 + ``arm64`` Maintained 仅小端序。 23 24 ``loongarch`` Maintained \- 24 - ``riscv`` Maintained 只有 ``riscv64`` 25 - ``um`` Maintained 只有 ``x86_64`` 26 - ``x86`` Maintained 只有 ``x86_64`` 25 + ``riscv`` Maintained 仅 ``riscv64``,且仅限 LLVM/Clang。 26 + ``um`` Maintained \- 27 + ``x86`` Maintained 仅 ``x86_64``。 27 28 ============= ================ ==============================================
+248 -14
Documentation/translations/zh_CN/rust/coding-guidelines.rst
··· 37 37 像内核其他部分的 ``clang-format`` 一样, ``rustfmt`` 在单个文件上工作,并且不需要 38 38 内核配置。有时,它甚至可以与破碎的代码一起工作。 39 39 40 + 导入 41 + ~~~~ 42 + 43 + ``rustfmt`` 默认会以一种在合并和变基时容易产生冲突的方式格式化导入,因为在某些情况下 44 + 它会将多个条目合并到同一行。例如: 45 + 46 + .. code-block:: rust 47 + 48 + // Do not use this style. 49 + use crate::{ 50 + example1, 51 + example2::{example3, example4, example5}, 52 + example6, example7, 53 + example8::example9, 54 + }; 55 + 56 + 相反,内核使用如下所示的垂直布局: 57 + 58 + .. code-block:: rust 59 + 60 + use crate::{ 61 + example1, 62 + example2::{ 63 + example3, 64 + example4, 65 + example5, // 66 + }, 67 + example6, 68 + example7, 69 + example8::example9, // 70 + }; 71 + 72 + 也就是说,每个条目占一行,只要列表中有多个条目就使用花括号。 73 + 74 + 末尾的空注释可以保留这种格式。不仅如此, ``rustfmt`` 在添加空注释后实际上会将导入重 75 + 新格式化为垂直布局。也就是说,可以通过对如下输入运行 ``rustfmt`` 来轻松地将原始示例 76 + 重新格式化为预期的风格: 77 + 78 + .. code-block:: rust 79 + 80 + // Do not use this style. 81 + use crate::{ 82 + example1, 83 + example2::{example3, example4, example5, // 84 + }, 85 + example6, example7, 86 + example8::example9, // 87 + }; 88 + 89 + 末尾的空注释适用于嵌套导入(如上所示)以及单条目导入——这有助于最小化补丁系列中的差 90 + 异: 91 + 92 + .. code-block:: rust 93 + 94 + use crate::{ 95 + example1, // 96 + }; 97 + 98 + 末尾的空注释可以放在花括号内的任何一行中,但建议放在最后一个条目上,因为这让人联想到其 99 + 他格式化工具中的末尾逗号。有时在补丁系列中由于列表的变更,避免多次移动注释可能更简单。 100 + 101 + 在某些情况下可能需要例外处理,即以上都不是硬性规则。也有一些代码尚未迁移到这种风格,但 102 + 请不要引入其他风格的代码。 103 + 104 + 最终目标是让 ``rustfmt`` 在稳定版本中自动支持这种格式化风格(或类似的风格),而无需 105 + 末尾的空注释。因此,在某个时候,目标是移除这些注释。 106 + 40 107 41 108 注释 42 109 ---- ··· 143 76 pub fn f(x: i32) -> Foo { 144 77 // ... 145 78 } 79 + 80 + 这适用于公共和私有项目。这增加了与公共项目的一致性,允许在更改可见性时减少涉及的更改, 81 + 并允许我们将来也为私有项目生成文档。换句话说,如果为私有项目编写了文档,那么仍然应该使 82 + 用 ``///`` 。例如: 83 + 84 + .. code-block:: rust 85 + 86 + /// My private function. 87 + // TODO: ... 88 + fn f() {} 146 89 147 90 一种特殊的注释是 ``// SAFETY:`` 注释。这些注释必须出现在每个 ``unsafe`` 块之前,它们 148 91 解释了为什么该块内的代码是正确/健全的,即为什么它在任何情况下都不会触发未定义行为,例如: ··· 208 131 209 132 这个例子展示了一些 ``rustdoc`` 的特性和内核中遵循的一些惯例: 210 133 211 - - 第一段必须是一个简单的句子,简要地描述被记录的项目的作用。进一步的解释必须放在额 212 - 外的段落中。 134 + - 第一段必须是一个简单的句子,简要地描述被记录的项目的作用。进一步的解释必须放在额 135 + 外的段落中。 213 136 214 - - 不安全的函数必须在 ``# Safety`` 部分记录其安全前提条件。 137 + - 不安全的函数必须在 ``# Safety`` 部分记录其安全前提条件。 215 138 216 - - 虽然这里没有显示,但如果一个函数可能会恐慌,那么必须在 ``# Panics`` 部分描述发 217 - 生这种情况的条件。 139 + - 虽然这里没有显示,但如果一个函数可能会恐慌,那么必须在 ``# Panics`` 部分描述发 140 + 生这种情况的条件。 218 141 219 - 请注意,恐慌应该是非常少见的,只有在有充分理由的情况下才会使用。几乎在所有的情况下, 220 - 都应该使用一个可失败的方法,通常是返回一个 ``Result``。 142 + 请注意,恐慌应该是非常少见的,只有在有充分理由的情况下才会使用。几乎在所有的情况下, 143 + 都应该使用一个可失败的方法,通常是返回一个 ``Result``。 221 144 222 - - 如果提供使用实例对读者有帮助的话,必须写在一个叫做``# Examples``的部分。 145 + - 如果提供使用实例对读者有帮助的话,必须写在一个叫做``# Examples``的部分。 223 146 224 - - Rust项目(函数、类型、常量……)必须有适当的链接(``rustdoc`` 会自动创建一个 225 - 链接)。 147 + - Rust项目(函数、类型、常量……)必须有适当的链接(``rustdoc`` 会自动创建一个 148 + 链接)。 226 149 227 - - 任何 ``unsafe`` 的代码块都必须在前面加上一个 ``// SAFETY:`` 的注释,描述里面 228 - 的代码为什么是正确的。 150 + - 任何 ``unsafe`` 的代码块都必须在前面加上一个 ``// SAFETY:`` 的注释,描述里面 151 + 的代码为什么是正确的。 229 152 230 - 虽然有时原因可能看起来微不足道,但写这些注释不仅是记录已经考虑到的问题的好方法, 231 - 最重要的是,它提供了一种知道没有额外隐含约束的方法。 153 + 虽然有时原因可能看起来微不足道,但写这些注释不仅是记录已经考虑到的问题的好方法, 154 + 最重要的是,它提供了一种知道没有额外隐含约束的方法。 232 155 233 156 要了解更多关于如何编写Rust和拓展功能的文档,请看看 ``rustdoc`` 这本书,网址是: 234 157 ··· 245 168 .. code-block:: rust 246 169 247 170 /// [`struct mutex`]: srctree/include/linux/mutex.h 171 + 172 + 173 + C FFI 类型 174 + ---------- 175 + 176 + Rust 内核代码使用类型别名(如 ``c_int``)来引用 C 类型(如 ``int``),这些别名可 177 + 以直接从 ``kernel`` 预导入(prelude)中获取。请不要使用 ``core::ffi`` 中的别 178 + 名——它们可能无法映射到正确的类型。 179 + 180 + 这些别名通常应该直接通过其标识符引用,即作为单段路径。例如: 181 + 182 + .. code-block:: rust 183 + 184 + fn f(p: *const c_char) -> c_int { 185 + // ... 186 + } 248 187 249 188 250 189 命名 ··· 295 202 296 203 也就是说, ``GPIO_LINE_DIRECTION_IN`` 的等价物将被称为 ``gpio::LineDirection::In`` 。 297 204 特别是,它不应该被命名为 ``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN`` 。 205 + 206 + 207 + 代码检查提示(Lints) 208 + --------------------- 209 + 210 + 在 Rust 中,可以在局部 ``allow`` 特定的警告(诊断信息、代码检查提示(lint)), 211 + 使编译器忽略给定函数、模块、代码块等中给定警告的实例。 212 + 213 + 这类似于 C 中的 ``#pragma GCC diagnostic push`` + ``ignored`` + ``pop`` 214 + [#]_: 215 + 216 + .. code-block:: c 217 + 218 + #pragma GCC diagnostic push 219 + #pragma GCC diagnostic ignored "-Wunused-function" 220 + static void f(void) {} 221 + #pragma GCC diagnostic pop 222 + 223 + .. [#] 在这个特定情况下,可以使用内核的 ``__{always,maybe}_unused`` 属性 224 + (C23 的 ``[[maybe_unused]]``);然而,此示例旨在反映下文讨论的 Rust 中 225 + 的等效代码检查提示。 226 + 227 + 但要简洁得多: 228 + 229 + .. code-block:: rust 230 + 231 + #[allow(dead_code)] 232 + fn f() {} 233 + 234 + 凭借这一点,可以更方便地默认启用更多诊断(即在 ``W=`` 级别之外)。特别是那些可能有 235 + 一些误报但在其他方面非常有用的诊断,保持启用可以捕获潜在的错误。 236 + 237 + 在此基础上,Rust 提供了 ``expect`` 属性,更进一步。如果警告没有产生,它会让编译器 238 + 发出警告。例如,以下代码将确保当 ``f()`` 在某处被调用时,我们必须移除该属性: 239 + 240 + .. code-block:: rust 241 + 242 + #[expect(dead_code)] 243 + fn f() {} 244 + 245 + 如果我们不这样做,编译器会发出警告:: 246 + 247 + warning: this lint expectation is unfulfilled 248 + --> x.rs:3:10 249 + | 250 + 3 | #[expect(dead_code)] 251 + | ^^^^^^^^^ 252 + | 253 + = note: `#[warn(unfulfilled_lint_expectations)]` on by default 254 + 255 + 这意味着 ``expect`` 不会在不需要时被遗忘,这可能发生在以下几种情况中: 256 + 257 + - 开发过程中添加的临时属性。 258 + 259 + - 编译器、Clippy 或自定义工具中代码检查提示的改进可能消除误报。 260 + 261 + - 当代码检查提示不再需要时,因为预期它会在某个时候被移除,例如上面的 262 + ``dead_code`` 示例。 263 + 264 + 这也增加了剩余 ``allow`` 的可见性,并减少了误用的可能性。 265 + 266 + 因此,优先使用 ``expect`` 而不是 ``allow``,除非: 267 + 268 + - 条件编译在某些情况下触发警告,在其他情况下不触发。 269 + 270 + 如果与总的相比,只有少数情况触发(或不触发)警告,那么可以考虑使用条件 271 + ``expect``(即 ``cfg_attr(..., expect(...))``)。否则,使用 ``allow`` 可 272 + 能更简单。 273 + 274 + - 在宏内部,不同的调用可能会创建在某些情况下触发警告而在其他情况下不触发的展开代码。 275 + 276 + - 当代码可能在某些架构上触发警告但在其他架构上不触发时,例如到 C FFI 类型的 ``as`` 277 + 转换。 278 + 279 + 作为一个更详细的示例,考虑以下程序: 280 + 281 + .. code-block:: rust 282 + 283 + fn g() {} 284 + 285 + fn main() { 286 + #[cfg(CONFIG_X)] 287 + g(); 288 + } 289 + 290 + 这里,如果 ``CONFIG_X`` 未设置,函数 ``g()`` 是死代码。我们可以在这里使用 291 + ``expect`` 吗? 292 + 293 + .. code-block:: rust 294 + 295 + #[expect(dead_code)] 296 + fn g() {} 297 + 298 + fn main() { 299 + #[cfg(CONFIG_X)] 300 + g(); 301 + } 302 + 303 + 如果 ``CONFIG_X`` 被设置,这将产生代码检查提示,因为在该配置中它不是死代码。因 304 + 此,在这种情况下,我们不能直接使用 ``expect``。 305 + 306 + 一个简单的可能性是使用 ``allow``: 307 + 308 + .. code-block:: rust 309 + 310 + #[allow(dead_code)] 311 + fn g() {} 312 + 313 + fn main() { 314 + #[cfg(CONFIG_X)] 315 + g(); 316 + } 317 + 318 + 另一种方法是使用条件 ``expect``: 319 + 320 + .. code-block:: rust 321 + 322 + #[cfg_attr(not(CONFIG_X), expect(dead_code))] 323 + fn g() {} 324 + 325 + fn main() { 326 + #[cfg(CONFIG_X)] 327 + g(); 328 + } 329 + 330 + 这将确保如果有人在某处引入了对 ``g()`` 的另一个调用(例如无条件的),那么将会被发现 331 + 它不再是死代码。然而, ``cfg_attr`` 比简单的 ``allow`` 更复杂。 332 + 333 + 因此,当涉及多个配置或者代码检查提示可能由于非局部更改(如 ``dead_code``)而触发 334 + 时,使用条件 ``expect`` 可能不值得。 335 + 336 + 有关 Rust 中诊断的更多信息,请参阅: 337 + 338 + https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html 339 + 340 + 错误处理 341 + -------- 342 + 343 + 有关 Rust for Linux 特定错误处理的背景和指南,请参阅: 344 + 345 + https://rust.docs.kernel.org/kernel/error/type.Result.html#error-codes-in-c-and-rust
-17
Documentation/translations/zh_CN/rust/index.rst
··· 12 12 13 13 与内核中的Rust有关的文档。若要开始在内核中使用Rust,请阅读 quick-start.rst 指南。 14 14 15 - Rust 实验 16 - --------- 17 - Rust 支持在 v6.1 版本中合并到主线,以帮助确定 Rust 作为一种语言是否适合内核, 18 - 即是否值得进行权衡。 19 - 20 - 目前,Rust 支持主要面向对 Rust 支持感兴趣的内核开发人员和维护者, 21 - 以便他们可以开始处理抽象和驱动程序,并帮助开发基础设施和工具。 22 - 23 - 如果您是终端用户,请注意,目前没有适合或旨在生产使用的内置驱动程序或模块, 24 - 并且 Rust 支持仍处于开发/实验阶段,尤其是对于特定内核配置。 25 15 26 16 代码文档 27 17 -------- ··· 40 50 testing 41 51 42 52 你还可以在 :doc:`../../../process/kernel-docs` 中找到 Rust 的学习材料。 43 - 44 - .. only:: subproject and html 45 - 46 - Indices 47 - ======= 48 - 49 - * :ref:`genindex`
+148 -42
Documentation/translations/zh_CN/rust/quick-start.rst
··· 13 13 14 14 本文介绍了如何开始使用Rust进行内核开发。 15 15 16 + 安装内核开发所需的 Rust 工具链有几种方式。一种简单的方式是使用 Linux 发行版的软件包 17 + (如果它们合适的话)——下面的第一节解释了这种方法。这种方法的一个优势是,通常发行版会 18 + 匹配 Rust 和 Clang 所使用的 LLVM。 19 + 20 + 另一种方式是使用 `kernel.org <https://kernel.org/pub/tools/llvm/rust/>`_ 上提 21 + 供的预构建稳定版本的 LLVM+Rust。这些与 :ref:`获取 LLVM <zh_cn_getting_llvm>` 中的精 22 + 简快速 LLVM 工具链相同,并添加了 Rust for Linux 支持的 Rust 版本。提供了两套工具 23 + 链:"最新 LLVM" 和 "匹配 LLVM"(请参阅链接了解更多信息)。 24 + 25 + 或者,接下来的两个 "依赖" 章节将解释每个组件以及如何通过 ``rustup``、Rust 的独立 26 + 安装程序或从源码构建来安装它们。 27 + 28 + 本文档的其余部分解释了有关如何入门的其他方面。 29 + 30 + 31 + 发行版 32 + ------ 33 + 34 + Arch Linux 35 + ********** 36 + 37 + Arch Linux 提供较新的 Rust 版本,因此通常开箱即用,例如:: 38 + 39 + pacman -S rust rust-src rust-bindgen 40 + 41 + 42 + Debian 43 + ****** 44 + 45 + Debian 13(Trixie)以及 Testing 和 Debian Unstable(Sid)提供较新的 Rust 版 46 + 本,因此通常开箱即用,例如:: 47 + 48 + apt install rustc rust-src bindgen rustfmt rust-clippy 49 + 50 + 51 + Fedora Linux 52 + ************ 53 + 54 + Fedora Linux 提供较新的 Rust 版本,因此通常开箱即用,例如:: 55 + 56 + dnf install rust rust-src bindgen-cli rustfmt clippy 57 + 58 + 59 + Gentoo Linux 60 + ************ 61 + 62 + Gentoo Linux(尤其是 testing 分支)提供较新的 Rust 版本,因此通常开箱即用, 63 + 例如:: 64 + 65 + USE='rust-src rustfmt clippy' emerge dev-lang/rust dev-util/bindgen 66 + 67 + 可能需要设置 ``LIBCLANG_PATH``。 68 + 69 + 70 + Nix 71 + *** 72 + 73 + Nix(unstable 频道)提供较新的 Rust 版本,因此通常开箱即用,例如:: 74 + 75 + { pkgs ? import <nixpkgs> {} }: 76 + pkgs.mkShell { 77 + nativeBuildInputs = with pkgs; [ rustc rust-bindgen rustfmt clippy ]; 78 + RUST_LIB_SRC = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; 79 + } 80 + 81 + 82 + openSUSE 83 + ******** 84 + 85 + openSUSE Slowroll 和 openSUSE Tumbleweed 提供较新的 Rust 版本,因此通常开箱 86 + 即用,例如:: 87 + 88 + zypper install rust rust1.79-src rust-bindgen clang 89 + 90 + 91 + Ubuntu 92 + ****** 93 + 94 + 25.04 95 + ~~~~~ 96 + 97 + 最新的 Ubuntu 版本提供较新的 Rust 版本,因此通常开箱即用,例如:: 98 + 99 + apt install rustc rust-src bindgen rustfmt rust-clippy 100 + 101 + 此外,需要设置 ``RUST_LIB_SRC``,例如:: 102 + 103 + RUST_LIB_SRC=/usr/src/rustc-$(rustc --version | cut -d' ' -f2)/library 104 + 105 + 为方便起见,可以将 ``RUST_LIB_SRC`` 导出到全局环境中。 106 + 107 + 108 + 24.04 LTS 及更早版本 109 + ~~~~~~~~~~~~~~~~~~~~ 110 + 111 + 虽然 Ubuntu 24.04 LTS 及更早版本仍然提供较新的 Rust 版本,但它们需要一些额外的配 112 + 置,使用带版本号的软件包,例如:: 113 + 114 + apt install rustc-1.80 rust-1.80-src bindgen-0.65 rustfmt-1.80 \ 115 + rust-1.80-clippy 116 + ln -s /usr/lib/rust-1.80/bin/rustfmt /usr/bin/rustfmt-1.80 117 + ln -s /usr/lib/rust-1.80/bin/clippy-driver /usr/bin/clippy-driver-1.80 118 + 119 + 这些软件包都不会将其工具设置为默认值;因此应该显式指定它们,例如:: 120 + 121 + make LLVM=1 RUSTC=rustc-1.80 RUSTDOC=rustdoc-1.80 RUSTFMT=rustfmt-1.80 \ 122 + CLIPPY_DRIVER=clippy-driver-1.80 BINDGEN=bindgen-0.65 123 + 124 + 或者,修改 ``PATH`` 变量将 Rust 1.80 的二进制文件放在前面,并将 ``bindgen`` 设 125 + 置为默认值,例如:: 126 + 127 + PATH=/usr/lib/rust-1.80/bin:$PATH 128 + update-alternatives --install /usr/bin/bindgen bindgen \ 129 + /usr/bin/bindgen-0.65 100 130 + update-alternatives --set bindgen /usr/bin/bindgen-0.65 131 + 132 + 使用带版本号的软件包时需要设置 ``RUST_LIB_SRC``,例如:: 133 + 134 + RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.80 --version | cut -d' ' -f2)/library 135 + 136 + 为方便起见,可以将 ``RUST_LIB_SRC`` 导出到全局环境中。 137 + 138 + 此外, ``bindgen-0.65`` 在较新的版本(24.04 LTS 和 24.10)中可用,但在更早的版 139 + 本(20.04 LTS 和 22.04 LTS)中可能不可用,因此可能需要手动构建 ``bindgen`` 140 + (请参见下文)。 141 + 16 142 17 143 构建依赖 18 144 -------- 19 145 20 146 本节描述了如何获取构建所需的工具。 21 - 22 - 其中一些依赖也许可以从Linux发行版中获得,包名可能是 ``rustc`` , ``rust-src`` , 23 - ``rust-bindgen`` 等。然而,在写这篇文章的时候,它们很可能还不够新,除非发行版跟踪最 24 - 新的版本。 25 147 26 148 为了方便检查是否满足要求,可以使用以下目标:: 27 149 ··· 156 34 rustc 157 35 ***** 158 36 159 - 需要一个特定版本的Rust编译器。较新的版本可能会也可能不会工作,因为就目前而言,内核依赖 160 - 于一些不稳定的Rust特性。 37 + 需要一个较新版本的Rust编译器。 161 38 162 39 如果使用的是 ``rustup`` ,请进入内核编译目录(或者用 ``--path=<build-dir>`` 参数 163 - 来 ``设置`` sub-command)并运行:: 40 + 来 ``设置`` sub-command),例如运行:: 164 41 165 - rustup override set $(scripts/min-tool-version.sh rustc) 42 + rustup override set stable 166 43 167 - +这将配置你的工作目录使用正确版本的 ``rustc``,而不影响你的默认工具链。 44 + 这将配置你的工作目录使用给定版本的 ``rustc``,而不影响你的默认工具链。 168 45 169 46 请注意覆盖应用当前的工作目录(和它的子目录)。 170 47 ··· 175 54 Rust标准库源代码 176 55 **************** 177 56 178 - Rust标准库的源代码是必需的,因为构建系统会交叉编译 ``core`` 和 ``alloc`` 。 57 + Rust标准库的源代码是必需的,因为构建系统会交叉编译 ``core`` 。 179 58 180 59 如果正在使用 ``rustup`` ,请运行:: 181 60 ··· 185 64 186 65 否则,如果使用独立的安装程序,可以将Rust源码树下载到安装工具链的文件夹中:: 187 66 188 - curl -L "https://static.rust-lang.org/dist/rust-src-$(scripts/min-tool-version.sh rustc).tar.gz" | 189 - tar -xzf - -C "$(rustc --print sysroot)/lib" \ 190 - "rust-src-$(scripts/min-tool-version.sh rustc)/rust-src/lib/" \ 191 - --strip-components=3 67 + curl -L "https://static.rust-lang.org/dist/rust-src-$(rustc --version | cut -d' ' -f2).tar.gz" | 68 + tar -xzf - -C "$(rustc --print sysroot)/lib" \ 69 + "rust-src-$(rustc --version | cut -d' ' -f2)/rust-src/lib/" \ 70 + --strip-components=3 192 71 193 72 在这种情况下,以后升级Rust编译器版本需要手动更新这个源代码树(这可以通过移除 194 73 ``$(rustc --print sysroot)/lib/rustlib/src/rust`` ,然后重新执行上 ··· 218 97 bindgen 219 98 ******* 220 99 221 - 内核的C端绑定是在构建时使用 ``bindgen`` 工具生成的。这需要特定的版本。 100 + 内核的C端绑定是在构建时使用 ``bindgen`` 工具生成的。 222 101 223 - 通过以下方式安装它(注意,这将从源码下载并构建该工具):: 102 + 例如,通过以下方式安装它(注意,这将从源码下载并构建该工具):: 224 103 225 - cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen-cli 104 + cargo install --locked bindgen-cli 226 105 227 - ``bindgen`` 需要找到合适的 ``libclang`` 才能工作。如果没有找到(或者找到的 228 - ``libclang`` 与应该使用的 ``libclang`` 不同),则可以使用 ``clang-sys`` 229 - 理解的环境变量(Rust绑定创建的 ``bindgen`` 用来访问 ``libclang``): 106 + ``bindgen`` 使用 ``clang-sys`` crate 来查找合适的 ``libclang`` (可以静态链 107 + 接、动态链接或在运行时加载)。默认情况下,上面的 ``cargo`` 命令会生成一个在运行时 108 + 加载 ``libclang`` 的 ``bindgen`` 二进制文件。如果没有找到(或者应该使用与找到的 109 + 不同的 ``libclang``),可以调整该过程,例如使用 ``LIBCLANG_PATH`` 环境变量。详 110 + 情请参阅 ``clang-sys`` 的文档: 230 111 112 + https://github.com/KyleMayes/clang-sys#linking 231 113 232 - * ``LLVM_CONFIG_PATH`` 可以指向一个 ``llvm-config`` 可执行文件。 233 - 234 - * 或者 ``LIBCLANG_PATH`` 可以指向 ``libclang`` 共享库或包含它的目录。 235 - 236 - * 或者 ``CLANG_PATH`` 可以指向 ``clang`` 可执行文件。 237 - 238 - 详情请参阅 ``clang-sys`` 的文档: 114 + https://github.com/KyleMayes/clang-sys#environment-variables 239 115 240 116 241 117 开发依赖 ··· 267 149 rustup component add clippy 268 150 269 151 独立的安装程序也带有 ``clippy`` 。 270 - 271 - 272 - cargo 273 - ***** 274 - 275 - ``cargo`` 是Rust的本地构建系统。目前需要它来运行测试,因为它被用来构建一个自定义的标准 276 - 库,其中包含了内核中自定义 ``alloc`` 所提供的设施。测试可以使用 ``rusttest`` Make 目标 277 - 来运行。 278 - 279 - 如果使用的是 ``rustup`` ,所有的配置文件都已经安装了该工具,因此不需要再做什么。 280 - 281 - 独立的安装程序也带有 ``cargo`` 。 282 152 283 153 284 154 rustdoc ··· 329 223 如果使用的是GDB/Binutils,而Rust符号没有被demangled,原因是工具链还不支持Rust的新v0 330 224 mangling方案。有几个办法可以解决: 331 225 332 - - 安装一个较新的版本(GDB >= 10.2, Binutils >= 2.36)。 226 + - 安装一个较新的版本(GDB >= 10.2, Binutils >= 2.36)。 333 227 334 - - 一些版本的GDB(例如vanilla GDB 10.1)能够使用嵌入在调试信息(``CONFIG_DEBUG_INFO``) 335 - 中的pre-demangled的名字。 228 + - 一些版本的GDB(例如vanilla GDB 10.1)能够使用嵌入在调试信息(``CONFIG_DEBUG_INFO``) 229 + 中的pre-demangled的名字。
+2 -2
Documentation/translations/zh_CN/scheduler/sched-design-CFS.rst
··· 144 144 145 145 - yield_task(...) 146 146 147 - 这个函数的行为基本上是出队,紧接着入队,除非compat_yield sysctl被开启。在那种情况下, 148 - 它将调度实体放在红黑树的最右端。 147 + 此函数通过将当前任务在运行队列中的位置后移来让出 CPU, 148 + 使得其他可运行的任务优先被调度。 149 149 150 150 - wakeup_preempt(...) 151 151
+1 -1
Documentation/translations/zh_TW/admin-guide/README.rst
··· 33 33 34 34 雖然Linux最初是爲32位的x86 PC機(386或更高版本)開發的,但今天它也能運行在 35 35 (至少)Compaq Alpha AXP、Sun SPARC與UltraSPARC、Motorola 68000、PowerPC、 36 - PowerPC64、ARM、Hitachi SuperH、Cell、IBM S/390、MIPS、HP PA-RISC、Intel 36 + PowerPC64、ARM、Hitachi SuperH、Cell、IBM S/390、MIPS、HP PA-RISC、Intel 37 37 IA-64、DEC VAX、AMD x86-64 Xtensa和ARC架構上。 38 38 39 39 Linux很容易移植到大多數通用的32位或64位體系架構,只要它們有一個分頁內存管理
+1 -1
Documentation/translations/zh_TW/process/4.Coding.rst
··· 219 219 可以在 https://sparse.wiki.kernel.org/index.php/Main_page 找到), 220 220 然後可以通過在make命令中添加“C=1”在代碼上運行它。 221 221 222 - “Coccinelle”工具 :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>` 222 + “Coccinelle”工具 :ref:`https://coccinelle.gitlabpages.inria.fr/website/ <devtools_coccinelle>` 223 223 能夠發現各種潛在的編碼問題;它還可以爲這些問題提出修復方案。在 224 224 scripts/coccinelle目錄下已經打包了相當多的內核“語義補丁”;運行 225 225 “make coccicheck”將運行這些語義補丁並報告發現的任何問題。有關詳細信息,請參閱
+8 -2
MAINTAINERS
··· 7688 7688 L: linux-doc@vger.kernel.org 7689 7689 S: Maintained 7690 7690 F: Documentation/sphinx/ 7691 - F: tools/lib/python/* 7692 7691 F: tools/docs/ 7692 + F: tools/lib/python/* 7693 + F: tools/unittests/* 7693 7694 7694 7695 DOCUMENTATION/ITALIAN 7695 7696 M: Federico Vaga <federico.vaga@vaga.pv.it> ··· 14775 14774 F: tools/memory-model/ 14776 14775 14777 14776 LINUX-NEXT TREE 14778 - M: Stephen Rothwell <sfr@canb.auug.org.au> 14779 14777 M: Mark Brown <broonie@kernel.org> 14780 14778 L: linux-next@vger.kernel.org 14781 14779 S: Supported ··· 21013 21013 S: Maintained 21014 21014 F: drivers/pnp/ 21015 21015 F: include/linux/pnp.h 21016 + 21017 + PORTUGUESE (BRAZILIAN) TRANSLATION 21018 + M: Daniel Pereira <danielmaraboo@gmail.com> 21019 + L: linux-doc@vger.kernel.org 21020 + S: Maintained 21021 + F: Documentation/translations/pt_BR/ 21016 21022 21017 21023 PORTWELL EC DRIVER 21018 21024 M: Yen-Chi Huang <jesse.huang@portwell.com.tw>
+42 -21
scripts/ver_linux
··· 7 7 8 8 BEGIN { 9 9 usage = "If some fields are empty or look unusual you may have an old version.\n" 10 - usage = usage "Compare to the current minimal requirements in Documentation/Changes.\n" 10 + usage = usage "Compare to the current minimal requirements in Documentation/process/changes.rst\n" 11 11 print usage 12 12 13 13 system("uname -a") ··· 17 17 libc = "libc[.]so[.][0-9]+$" 18 18 libcpp = "(libg|stdc)[+]+[.]so([.][0-9]+)+$" 19 19 20 + printversion("bash", version("bash --version")) 21 + printversion("bc", version("bc --version")) 22 + printversion("bindgen", version("bindgen --version")) 23 + printversion("binutils", version("ld -v")) 24 + printversion("bison", version("bison --version")) 25 + printversion("btrfs-progs", version("btrfs --version")) 26 + printversion("Clang", version("clang --version")) 27 + printversion("Console-tools", version("loadkeys -V")) 28 + printversion("Dynamic linker (ldd)", version("ldd --version")) 29 + printversion("e2fsprogs", version("e2fsck -V")) 30 + printversion("flex", version("flex --version")) 31 + printversion("gdb", version("gdb -version")) 32 + printversion("GNU awk", version("gawk --version")) 20 33 printversion("GNU C", version("gcc -dumpversion")) 21 - printversion("GNU Make", version("make --version")) 22 - printversion("Binutils", version("ld -v")) 23 - printversion("Util-linux", version("mount --version")) 24 - printversion("Mount", version("mount --version")) 25 - printversion("Module-init-tools", version("depmod -V")) 26 - printversion("E2fsprogs", version("tune2fs")) 27 - printversion("Jfsutils", version("fsck.jfs -V")) 28 - printversion("Xfsprogs", version("xfs_db -V")) 29 - printversion("Pcmciautils", version("pccardctl -V")) 30 - printversion("Pcmcia-cs", version("cardmgr -V")) 31 - printversion("Quota-tools", version("quota -V")) 32 - printversion("PPP", version("pppd --version")) 34 + printversion("GNU make", version("make --version")) 35 + printversion("GNU tar", version("tar --version")) 36 + printversion("GRUB2", version("grub2-install --version")) 37 + printversion("GRUB", version("grub-install --version")) 38 + printversion("gtags", version("gtags --version")) 39 + printversion("iptables", version("iptables -V")) 33 40 printversion("Isdn4k-utils", version("isdnctrl")) 34 - printversion("Nfs-utils", version("showmount --version")) 35 - printversion("Bison", version("bison --version")) 36 - printversion("Flex", version("flex --version")) 41 + printversion("jfsutils", version("fsck.jfs -V")) 42 + printversion("Kbd", version("loadkeys -V")) 43 + printversion("kmod", version("kmod -V")) 37 44 38 45 while ("ldconfig -p 2>/dev/null" | getline > 0) 39 46 if ($NF ~ libc || $NF ~ libcpp) 40 47 if (!seen[ver = version("readlink " $NF)]++) 41 48 printversion("Linux C" ($NF ~ libcpp? "++" : "") " Library", ver) 42 49 43 - printversion("Dynamic linker (ldd)", version("ldd --version")) 44 - printversion("Procps", version("ps --version")) 50 + printversion("mcelog", version("mcelog --version")) 51 + printversion("mkimage", version("mkimage --version")) 52 + printversion("Module-init-tools", version("depmod -V")) 53 + printversion("Mount", version("mount --version")) 45 54 printversion("Net-tools", version("ifconfig --version")) 46 - printversion("Kbd", version("loadkeys -V")) 47 - printversion("Console-tools", version("loadkeys -V")) 55 + printversion("nfs-utils", version("showmount --version")) 56 + printversion("openssl", version("openssl version")) 57 + printversion("pahole", version("pahole --version")) 58 + printversion("Pcmcia-cs", version("cardmgr -V")) 59 + printversion("pcmciautils", version("pccardctl -V")) 60 + printversion("PPP", version("pppd --version")) 61 + printversion("procps", version("ps --version")) 62 + printversion("Python", version("python3 -V")) 63 + printversion("quota-tools", version("quota -V")) 64 + printversion("Rust", version("rustc --version")) 48 65 printversion("Sh-utils", version("expr --v")) 49 - printversion("Udev", version("udevadm --version")) 66 + printversion("Sphinx", version("sphinx-build --version")) 67 + printversion("squashfs-tools", version("mksquashfs -version")) 68 + printversion("udev", version("udevadm --version")) 69 + printversion("util-linux", version("mount --version")) 50 70 printversion("Wireless-tools", version("iwconfig --version")) 71 + printversion("xfsprogs", version("xfs_db -V")) 51 72 52 73 while ("sort /proc/modules" | getline > 0) { 53 74 mods = mods sep $1
+17 -5
tools/docs/checktransupdate.py
··· 13 13 This will print all the files that need to be updated or translated in the zh_CN locale. 14 14 - tools/docs/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst 15 15 This will only print the status of the specified file. 16 + - tools/docs/checktransupdate.py Documentation/translations/zh_CN/dev-tools 17 + This will print the status of all files under the directory. 16 18 17 19 The output is something like: 18 20 Documentation/dev-tools/kfence.rst ··· 78 76 (2) Update the translation through commit HASH (TITLE) 79 77 """ 80 78 # catch flag for 12-bit commit hash 81 - HASH = r'([0-9a-f]{12})' 79 + hash_re = r'([0-9a-f]{12})' 82 80 # pattern 1: contains "update to commit HASH" 83 - pat_update_to = re.compile(rf'update to commit {HASH}') 81 + pat_update_to = re.compile(rf'update to commit {hash_re}') 84 82 # pattern 2: contains "Update the translation through commit HASH" 85 - pat_update_translation = re.compile(rf'Update the translation through commit {HASH}') 83 + pat_update_translation = re.compile(rf'Update the translation through commit {hash_re}') 86 84 87 85 origin_commit_hash = None 88 86 for line in t_from_head["message"]: ··· 133 131 opath = get_origin_path(file_path) 134 132 135 133 if not os.path.isfile(opath): 136 - logging.error("Cannot find the origin path for {file_path}") 134 + logging.error("Cannot find the origin path for %s", file_path) 137 135 return 138 136 139 137 o_from_head = get_latest_commit_from(opath, "HEAD") ··· 264 262 help='Set the logging file (default: checktransupdate.log)') 265 263 266 264 parser.add_argument( 267 - "files", nargs="*", help="Files to check, if not specified, check all files" 265 + "files", nargs="*", help="Files or directories to check, if not specified, check all files" 268 266 ) 269 267 args = parser.parse_args() 270 268 ··· 295 293 if args.print_missing_translations: 296 294 logging.info(os.path.relpath(os.path.abspath(file), linux_path)) 297 295 logging.info("No translation in the locale of %s\n", args.locale) 296 + else: 297 + # check if the files are directories or files 298 + new_files = [] 299 + for file in files: 300 + if os.path.isfile(file): 301 + new_files.append(file) 302 + elif os.path.isdir(file): 303 + # for directories, list all files in the directory and its subfolders 304 + new_files.extend(list_files_with_excluding_folders(file, [], "rst")) 305 + files = new_files 298 306 299 307 files = list(map(lambda x: os.path.relpath(os.path.abspath(x), linux_path), files)) 300 308
+508
tools/docs/kdoc_diff
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Copyright(c) 2026: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + # 5 + # pylint: disable=R0903,R0912,R0913,R0914,R0915,R0917 6 + 7 + """ 8 + docdiff - Check differences between kernel‑doc output between two different 9 + commits. 10 + 11 + Examples 12 + -------- 13 + 14 + Compare the kernel‑doc output between the last two 5.15 releases:: 15 + 16 + $ kdoc_diff v6.18..v6.19 17 + 18 + Both outputs are cached 19 + 20 + Force a complete documentation scan and clean any previous cache from 21 + 6.19 to the current HEAD:: 22 + 23 + $ kdoc_diff 6.19.. --full --clean 24 + 25 + Check differences only on a single driver since origin/main:: 26 + 27 + $ kdoc_diff origin/main drivers/media 28 + 29 + Generate an YAML file and use it to check for regressions:: 30 + 31 + $ kdoc_diff HEAD~ drivers/media --regression 32 + 33 + 34 + """ 35 + 36 + import os 37 + import sys 38 + import argparse 39 + import subprocess 40 + import shutil 41 + import re 42 + import signal 43 + 44 + from glob import iglob 45 + 46 + 47 + SRC_DIR = os.path.dirname(os.path.realpath(__file__)) 48 + WORK_DIR = os.path.abspath(os.path.join(SRC_DIR, "../..")) 49 + 50 + KDOC_BINARY = os.path.join(SRC_DIR, "kernel-doc") 51 + KDOC_PARSER_TEST = os.path.join(WORK_DIR, "tools/unittests/test_kdoc_parser.py") 52 + 53 + CACHE_DIR = ".doc_diff_cache" 54 + YAML_NAME = "out.yaml" 55 + 56 + DIR_NAME = { 57 + "full": os.path.join(CACHE_DIR, "full"), 58 + "partial": os.path.join(CACHE_DIR, "partial"), 59 + "no-cache": os.path.join(CACHE_DIR, "no_cache"), 60 + "tmp": os.path.join(CACHE_DIR, "__tmp__"), 61 + } 62 + 63 + class GitHelper: 64 + """Handles all Git operations""" 65 + 66 + def __init__(self, work_dir=None): 67 + self.work_dir = work_dir 68 + 69 + def is_inside_repository(self): 70 + """Check if we're inside a Git repository""" 71 + try: 72 + output = subprocess.check_output(["git", "rev-parse", 73 + "--is-inside-work-tree"], 74 + cwd=self.work_dir, 75 + stderr=subprocess.STDOUT, 76 + universal_newlines=True) 77 + 78 + return output.strip() == "true" 79 + except subprocess.CalledProcessError: 80 + return False 81 + 82 + def is_valid_commit(self, commit_hash): 83 + """ 84 + Validate that a ref (branch, tag, commit hash, etc.) can be 85 + resolved to a commit. 86 + """ 87 + try: 88 + subprocess.check_output(["git", "rev-parse", commit_hash], 89 + cwd=self.work_dir, 90 + stderr=subprocess.STDOUT) 91 + return True 92 + except subprocess.CalledProcessError: 93 + return False 94 + 95 + def get_short_hash(self, commit_hash): 96 + """Get short commit hash""" 97 + try: 98 + return subprocess.check_output(["git", "rev-parse", "--short", 99 + commit_hash], 100 + cwd=self.work_dir, 101 + stderr=subprocess.STDOUT, 102 + universal_newlines=True).strip() 103 + except subprocess.CalledProcessError: 104 + return "" 105 + 106 + def has_uncommitted_changes(self): 107 + """Check for uncommitted changes""" 108 + try: 109 + subprocess.check_output(["git", "diff-index", 110 + "--quiet", "HEAD", "--"], 111 + cwd=self.work_dir, 112 + stderr=subprocess.STDOUT) 113 + return False 114 + except subprocess.CalledProcessError: 115 + return True 116 + 117 + def get_current_branch(self): 118 + """Get current branch name""" 119 + return subprocess.check_output(["git", "branch", "--show-current"], 120 + cwd=self.work_dir, 121 + universal_newlines=True).strip() 122 + 123 + def checkout_commit(self, commit_hash, quiet=True): 124 + """Checkout a commit safely""" 125 + args = ["git", "checkout", "-f"] 126 + if quiet: 127 + args.append("-q") 128 + args.append(commit_hash) 129 + try: 130 + subprocess.check_output(args, cwd=self.work_dir, 131 + stderr=subprocess.STDOUT) 132 + 133 + # Double-check if branch actually switched 134 + branch = self.get_short_hash("HEAD") 135 + if commit_hash != branch: 136 + raise RuntimeError(f"Branch changed to '{branch}' instead of '{commit_hash}'") 137 + 138 + return True 139 + except subprocess.CalledProcessError as e: 140 + print(f"ERROR: Failed to checkout {commit_hash}: {e}", 141 + file=sys.stderr) 142 + return False 143 + 144 + 145 + class CacheManager: 146 + """Manages persistent cache directories""" 147 + 148 + def __init__(self, work_dir): 149 + self.work_dir = work_dir 150 + 151 + def initialize(self): 152 + """Create cache directories if they don't exist""" 153 + for dir_path in DIR_NAME.values(): 154 + abs_path = os.path.join(self.work_dir, dir_path) 155 + if not os.path.exists(abs_path): 156 + os.makedirs(abs_path, exist_ok=True, mode=0o755) 157 + 158 + def get_commit_cache(self, commit_hash, path): 159 + """Generate cache path for a commit""" 160 + hash_short = GitHelper(self.work_dir).get_short_hash(commit_hash) 161 + if not hash_short: 162 + hash_short = commit_hash 163 + 164 + return os.path.join(path, hash_short) 165 + 166 + class KernelDocRunner: 167 + """Runs kernel-doc documentation generator""" 168 + 169 + def __init__(self, work_dir, kdoc_binary): 170 + self.work_dir = work_dir 171 + self.kdoc_binary = kdoc_binary 172 + self.kdoc_files = None 173 + 174 + def find_kdoc_references(self): 175 + """Find all files marked with kernel-doc:: directives""" 176 + if self.kdoc_files: 177 + print("Using cached Kdoc refs") 178 + return self.kdoc_files 179 + 180 + print("Finding kernel-doc entries in Documentation...") 181 + 182 + files = os.path.join(self.work_dir, 'Documentation/**/*.rst') 183 + pattern = re.compile(r"^\.\.\s+kernel-doc::\s*(\S+)") 184 + kdoc_files = set() 185 + 186 + for file_path in iglob(files, recursive=True): 187 + try: 188 + with open(file_path, 'r', encoding='utf-8') as fp: 189 + for line in fp: 190 + match = pattern.match(line.strip()) 191 + if match: 192 + kdoc_files.add(match.group(1)) 193 + 194 + except OSError: 195 + continue 196 + 197 + self.kdoc_files = list(kdoc_files) 198 + 199 + return self.kdoc_files 200 + 201 + def gen_yaml(self, yaml_file, kdoc_files): 202 + """Runs kernel-doc to generate a yaml file with man and rst.""" 203 + cmd = [self.kdoc_binary, "--man", "--rst", "--yaml", yaml_file] 204 + cmd += kdoc_files 205 + 206 + print(f"YAML regression test file will be stored at: {yaml_file}") 207 + 208 + try: 209 + subprocess.check_call(cmd, cwd=self.work_dir, 210 + stdout=subprocess.DEVNULL, 211 + stderr=subprocess.DEVNULL) 212 + except subprocess.CalledProcessError: 213 + return False 214 + 215 + return True 216 + 217 + def run_unittest(self, yaml_file): 218 + """Run unit tests with the generated yaml file""" 219 + cmd = [KDOC_PARSER_TEST, "-q", "--yaml", yaml_file] 220 + result = subprocess.run(cmd, cwd=self.work_dir) 221 + 222 + if result.returncode: 223 + print("To check for problems, try to run it again with -v\n") 224 + print("Use -k <regex> to filter results\n\n\t$", end="") 225 + print(" ".join(cmd) + "\n") 226 + 227 + return True 228 + 229 + def normal_run(self, tmp_dir, output_dir, kdoc_files): 230 + """Generate man, rst and errors, storing them at tmp_dir.""" 231 + os.makedirs(tmp_dir, exist_ok=True) 232 + 233 + try: 234 + with open(os.path.join(tmp_dir, "man.log"), "w", encoding="utf-8") as out: 235 + subprocess.check_call([self.kdoc_binary, "--man"] + kdoc_files, 236 + cwd=self.work_dir, 237 + stdout=out, stderr=subprocess.DEVNULL) 238 + 239 + with open(os.path.join(tmp_dir, "rst.log"), "w", encoding="utf-8") as out: 240 + with open(os.path.join(tmp_dir, "err.log"), "w", encoding="utf-8") as err: 241 + subprocess.check_call([self.kdoc_binary, "--rst"] + kdoc_files, 242 + cwd=self.work_dir, 243 + stdout=out, stderr=err) 244 + except subprocess.CalledProcessError: 245 + return False 246 + 247 + if output_dir: 248 + os.replace(tmp_dir, output_dir) 249 + 250 + return True 251 + 252 + def run(self, commit_hash, tmp_dir, output_dir, kdoc_files, is_regression, 253 + is_end): 254 + """Run kernel-doc on its several ways""" 255 + if not kdoc_files: 256 + raise RuntimeError("No kernel-doc references found") 257 + 258 + git_helper = GitHelper(self.work_dir) 259 + if not git_helper.checkout_commit(commit_hash, quiet=True): 260 + raise RuntimeError(f"ERROR: can't checkout commit {commit_hash}") 261 + 262 + print(f"Processing {commit_hash}...") 263 + 264 + if not is_regression: 265 + return self.normal_run(tmp_dir, output_dir, kdoc_files) 266 + 267 + yaml_file = os.path.join(tmp_dir, YAML_NAME) 268 + 269 + if not is_end: 270 + return self.gen_yaml(yaml_file, kdoc_files) 271 + 272 + return self.run_unittest(yaml_file) 273 + 274 + class DiffManager: 275 + """Compare documentation output directories with an external diff.""" 276 + def __init__(self, diff_tool="diff", diff_args=None): 277 + self.diff_tool = diff_tool 278 + # default: unified, no context, ignore whitespace changes 279 + self.diff_args = diff_args or ["-u0", "-w"] 280 + 281 + def diff_directories(self, dir1, dir2): 282 + """Compare two directories using an external diff.""" 283 + print(f"\nDiffing {dir1} and {dir2}:") 284 + 285 + dir1_files = set() 286 + dir2_files = set() 287 + has_diff = False 288 + 289 + for root, _, files in os.walk(dir1): 290 + for file in files: 291 + dir1_files.add(os.path.relpath(os.path.join(root, file), dir1)) 292 + for root, _, files in os.walk(dir2): 293 + for file in files: 294 + dir2_files.add(os.path.relpath(os.path.join(root, file), dir2)) 295 + 296 + common_files = sorted(dir1_files & dir2_files) 297 + for file in common_files: 298 + f1 = os.path.join(dir1, file) 299 + f2 = os.path.join(dir2, file) 300 + 301 + cmd = [self.diff_tool] + self.diff_args + [f1, f2] 302 + try: 303 + result = subprocess.run( 304 + cmd, capture_output=True, text=True, check=False 305 + ) 306 + if result.stdout: 307 + has_diff = True 308 + print(f"\n{file}") 309 + print(result.stdout, end="") 310 + except FileNotFoundError: 311 + print(f"ERROR: {self.diff_tool} not found") 312 + sys.exit(1) 313 + 314 + # Show files that exist only in one directory 315 + only_in_dir1 = dir1_files - dir2_files 316 + only_in_dir2 = dir2_files - dir1_files 317 + if only_in_dir1 or only_in_dir2: 318 + has_diff = True 319 + print("\nDifferential files:") 320 + for f in sorted(only_in_dir1): 321 + print(f" - {f} (only in {dir1})") 322 + for f in sorted(only_in_dir2): 323 + print(f" + {f} (only in {dir2})") 324 + 325 + if not has_diff: 326 + print("\nNo differences between those two commits") 327 + 328 + 329 + class SignalHandler(): 330 + """Signal handler class.""" 331 + 332 + def restore(self, force_exit=False): 333 + """Restore original HEAD state.""" 334 + if self.restored: 335 + return 336 + 337 + print(f"Restoring original branch: {self.original_head}") 338 + try: 339 + subprocess.check_call( 340 + ["git", "checkout", "-f", self.original_head], 341 + cwd=self.git_helper.work_dir, 342 + stderr=subprocess.STDOUT, 343 + ) 344 + except subprocess.CalledProcessError as e: 345 + print(f"Failed to restore: {e}", file=sys.stderr) 346 + 347 + for sig, handler in self.old_handler.items(): 348 + signal.signal(sig, handler) 349 + 350 + self.restored = True 351 + 352 + if force_exit: 353 + sys.exit(1) 354 + 355 + def signal_handler(self, sig, _): 356 + """Handle interrupt signals.""" 357 + print(f"\nSignal {sig} received. Restoring original state...") 358 + 359 + self.restore(force_exit=True) 360 + 361 + def __enter__(self): 362 + """Allow using it via with command.""" 363 + for sig in [signal.SIGINT, signal.SIGTERM]: 364 + self.old_handler[sig] = signal.getsignal(sig) 365 + signal.signal(sig, self.signal_handler) 366 + 367 + return self 368 + 369 + def __exit__(self, *args): 370 + """Restore signals at the end of with block.""" 371 + self.restore() 372 + 373 + def __init__(self, git_helper, original_head): 374 + self.git_helper = git_helper 375 + self.original_head = original_head 376 + self.old_handler = {} 377 + self.restored = False 378 + 379 + def parse_commit_range(value): 380 + """Handle a commit range.""" 381 + if ".." not in value: 382 + begin = value 383 + end = "HEAD" 384 + else: 385 + begin, _, end = value.partition("..") 386 + if not end: 387 + end = "HEAD" 388 + 389 + if not begin: 390 + raise argparse.ArgumentTypeError("Need a commit begginning") 391 + 392 + 393 + print(f"Range: {begin} to {end}") 394 + 395 + return begin, end 396 + 397 + 398 + def main(): 399 + """Main code""" 400 + parser = argparse.ArgumentParser(description="Compare kernel documentation between commits") 401 + parser.add_argument("commits", type=parse_commit_range, 402 + help="commit range like old..new") 403 + parser.add_argument("files", nargs="*", 404 + help="files to process – if supplied the --full flag is ignored") 405 + 406 + parser.add_argument("--full", "-f", action="store_true", 407 + help="Force a full scan of Documentation/*") 408 + 409 + parser.add_argument("--regression", "-r", action="store_true", 410 + help="Use YAML format to check for regressions") 411 + 412 + parser.add_argument("--work-dir", "-w", default=WORK_DIR, 413 + help="work dir (default: %(default)s)") 414 + 415 + parser.add_argument("--clean", "-c", action="store_true", 416 + help="Clean caches") 417 + 418 + args = parser.parse_args() 419 + 420 + if args.files and args.full: 421 + raise argparse.ArgumentError(args.full, 422 + "cannot combine '--full' with an explicit file list") 423 + 424 + work_dir = os.path.abspath(args.work_dir) 425 + 426 + # Initialize cache 427 + cache = CacheManager(work_dir) 428 + cache.initialize() 429 + 430 + # Validate git repository 431 + git_helper = GitHelper(work_dir) 432 + if not git_helper.is_inside_repository(): 433 + raise RuntimeError("Must run inside Git repository") 434 + 435 + old_commit, new_commit = args.commits 436 + 437 + old_commit = git_helper.get_short_hash(old_commit) 438 + new_commit = git_helper.get_short_hash(new_commit) 439 + 440 + # Validate commits 441 + for commit in [old_commit, new_commit]: 442 + if not git_helper.is_valid_commit(commit): 443 + raise RuntimeError(f"Commit '{commit}' does not exist") 444 + 445 + # Check for uncommitted changes 446 + if git_helper.has_uncommitted_changes(): 447 + raise RuntimeError("Uncommitted changes present. Commit or stash first.") 448 + 449 + runner = KernelDocRunner(git_helper.work_dir, KDOC_BINARY) 450 + 451 + # Get files to be parsed 452 + cache_msg = " (results will be cached)" 453 + if args.full: 454 + kdoc_files = ["."] 455 + diff_type = "full" 456 + print(f"Parsing all files at {work_dir}") 457 + if not args.files: 458 + diff_type = "partial" 459 + kdoc_files = runner.find_kdoc_references() 460 + print(f"Parsing files with kernel-doc markups at {work_dir}/Documentation") 461 + else: 462 + diff_type = "no-cache" 463 + cache_msg = "" 464 + kdoc_files = args.files 465 + 466 + tmp_dir = DIR_NAME["tmp"] 467 + out_path = DIR_NAME[diff_type] 468 + 469 + if not args.regression: 470 + print(f"Output will be stored at: {out_path}{cache_msg}") 471 + 472 + # Just in case - should never happen in practice 473 + if not kdoc_files: 474 + raise argparse.ArgumentError(args.files, 475 + "No kernel-doc references found") 476 + 477 + original_head = git_helper.get_current_branch() 478 + 479 + old_cache = cache.get_commit_cache(old_commit, out_path) 480 + new_cache = cache.get_commit_cache(new_commit, out_path) 481 + 482 + with SignalHandler(git_helper, original_head): 483 + if args.clean or diff_type == "no-cache": 484 + for cache_dir in [old_cache, new_cache]: 485 + if cache_dir and os.path.exists(cache_dir): 486 + shutil.rmtree(cache_dir) 487 + 488 + if args.regression or not os.path.exists(old_cache): 489 + old_success = runner.run(old_commit, tmp_dir, old_cache, kdoc_files, 490 + args.regression, False) 491 + else: 492 + old_success = True 493 + 494 + if args.regression or not os.path.exists(new_cache): 495 + new_success = runner.run(new_commit, tmp_dir, new_cache, kdoc_files, 496 + args.regression, True) 497 + else: 498 + new_success = True 499 + 500 + if not (old_success and new_success): 501 + raise RuntimeError("Failed to generate documentation") 502 + 503 + if not args.regression: 504 + diff_manager = DiffManager() 505 + diff_manager.diff_directories(old_cache, new_cache) 506 + 507 + if __name__ == "__main__": 508 + main()
+40 -9
tools/docs/kernel-doc
··· 210 210 help="Enable debug messages") 211 211 212 212 parser.add_argument("-M", "-modulename", "--modulename", 213 - default="Kernel API", 214 213 help="Allow setting a module name at the output.") 215 214 216 215 parser.add_argument("-l", "-enable-lineno", "--enable_lineno", ··· 240 241 help=EXPORT_FILE_DESC) 241 242 242 243 # 243 - # Output format mutually-exclusive group 244 + # Output format 244 245 # 245 - out_group = parser.add_argument_group("Output format selection (mutually exclusive)") 246 - 247 - out_fmt = out_group.add_mutually_exclusive_group() 246 + out_fmt = parser.add_argument_group("Output format selection (mutually exclusive)") 248 247 249 248 out_fmt.add_argument("-m", "-man", "--man", action="store_true", 250 249 help="Output troff manual page format.") ··· 250 253 help="Output reStructuredText format (default).") 251 254 out_fmt.add_argument("-N", "-none", "--none", action="store_true", 252 255 help="Do not output documentation, only warnings.") 256 + 257 + out_fmt.add_argument("-y", "--yaml-file", "--yaml", 258 + help="Stores kernel-doc output on a yaml file.") 259 + out_fmt.add_argument("-k", "--kdoc-item", "--kdoc", action="store_true", 260 + help="Store KdocItem inside yaml file. Ued together with --yaml.") 261 + 253 262 254 263 # 255 264 # Output selection mutually-exclusive group ··· 327 324 from kdoc.kdoc_files import KernelFiles # pylint: disable=C0415 328 325 from kdoc.kdoc_output import RestFormat, ManFormat # pylint: disable=C0415 329 326 330 - if args.man: 331 - out_style = ManFormat(modulename=args.modulename) 332 - elif args.none: 327 + yaml_content = set() 328 + if args.yaml_file: 333 329 out_style = None 330 + 331 + if args.man: 332 + yaml_content |= {"man"} 333 + 334 + if args.rst: 335 + yaml_content |= {"rst"} 336 + 337 + if args.kdoc_item or not yaml_content: 338 + yaml_content |= {"KdocItem"} 339 + 334 340 else: 335 - out_style = RestFormat() 341 + n_outputs = 0 342 + 343 + if args.man: 344 + out_style = ManFormat(modulename=args.modulename) 345 + n_outputs += 1 346 + 347 + if args.none: 348 + out_style = None 349 + n_outputs += 1 350 + 351 + if args.rst or n_outputs == 0: 352 + n_outputs += 1 353 + out_style = RestFormat() 354 + 355 + if n_outputs > 1: 356 + parser.error("Those arguments are muttually exclusive: --man, --rst, --none, except when generating a YAML file.") 357 + 358 + elif not n_outputs: 359 + out_style = RestFormat() 336 360 337 361 kfiles = KernelFiles(verbose=args.verbose, 362 + yaml_file=args.yaml_file, yaml_content=yaml_content, 338 363 out_style=out_style, werror=args.werror, 339 364 wreturn=args.wreturn, wshort_desc=args.wshort_desc, 340 365 wcontents_before_sections=args.wcontents_before_sections)
+12 -5
tools/docs/sphinx-build-wrapper
··· 238 238 self.latexopts = os.environ.get("LATEXOPTS", "") 239 239 240 240 if not verbose: 241 - verbose = bool(os.environ.get("KBUILD_VERBOSE", "") != "") 241 + try: 242 + verbose = bool(int(os.environ.get("KBUILD_VERBOSE", 0))) 243 + except ValueError: 244 + # Handles an eventual case where verbosity is not a number 245 + # like KBUILD_VERBOSE="" 246 + verbose = False 242 247 243 248 if verbose is not None: 244 249 self.verbose = verbose ··· 581 576 """ 582 577 583 578 re_kernel_doc = re.compile(r"^\.\.\s+kernel-doc::\s*(\S+)") 584 - re_man = re.compile(r'^\.TH "[^"]*" (\d+) "([^"]*)"') 585 579 586 580 if docs_dir == src_dir: 587 581 # ··· 620 616 fp = None 621 617 try: 622 618 for line in result.stdout.split("\n"): 623 - match = re_man.match(line) 624 - if not match: 619 + if not line.startswith(".TH"): 625 620 if fp: 626 621 fp.write(line + '\n') 627 622 continue ··· 628 625 if fp: 629 626 fp.close() 630 627 631 - fname = f"{output_dir}/{match.group(2)}.{match.group(1)}" 628 + # Use shlex here, as it handles well parameters with commas 629 + args = shlex.split(line) 630 + fname = f"{args[1]}.{args[2]}" 631 + fname = fname.replace("/", " ") 632 + fname = f"{output_dir}/{fname}" 632 633 633 634 if self.verbose: 634 635 print(f"Creating {fname}")
+2 -2
tools/lib/python/jobserver.py
··· 8 8 """ 9 9 Interacts with the POSIX jobserver during the Kernel build time. 10 10 11 - A "normal" jobserver task, like the one initiated by a make subrocess would do: 11 + A "normal" jobserver task, like the one initiated by a make subprocess would do: 12 12 13 13 - open read/write file descriptors to communicate with the job server; 14 14 - ask for one slot by calling:: 15 15 16 16 claim = os.read(reader, 1) 17 17 18 - - when the job finshes, call:: 18 + - when the job finishes, call:: 19 19 20 20 os.write(writer, b"+") # os.write(writer, claim) 21 21
+662
tools/lib/python/kdoc/c_lex.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + 5 + """ 6 + Regular expression ancillary classes. 7 + 8 + Those help caching regular expressions and do matching for kernel-doc. 9 + 10 + Please notice that the code here may rise exceptions to indicate bad 11 + usage inside kdoc to indicate problems at the replace pattern. 12 + 13 + Other errors are logged via log instance. 14 + """ 15 + 16 + import logging 17 + import re 18 + 19 + from copy import copy 20 + 21 + from .kdoc_re import KernRe 22 + 23 + log = logging.getLogger(__name__) 24 + 25 + def tokenizer_set_log(logger, prefix = ""): 26 + """ 27 + Replace the module‑level logger with a LoggerAdapter that 28 + prepends *prefix* to every message. 29 + """ 30 + global log 31 + 32 + class PrefixAdapter(logging.LoggerAdapter): 33 + """ 34 + Ancillary class to set prefix on all message logs. 35 + """ 36 + def process(self, msg, kwargs): 37 + return f"{prefix}{msg}", kwargs 38 + 39 + # Wrap the provided logger in our adapter 40 + log = PrefixAdapter(logger, {"prefix": prefix}) 41 + 42 + class CToken(): 43 + """ 44 + Data class to define a C token. 45 + """ 46 + 47 + # Tokens that can be used by the parser. Works like an C enum. 48 + 49 + COMMENT = 0 #: A standard C or C99 comment, including delimiter. 50 + STRING = 1 #: A string, including quotation marks. 51 + CHAR = 2 #: A character, including apostophes. 52 + NUMBER = 3 #: A number. 53 + PUNC = 4 #: A puntuation mark: / ``,`` / ``.``. 54 + BEGIN = 5 #: A begin character: ``{`` / ``[`` / ``(``. 55 + END = 6 #: A end character: ``}`` / ``]`` / ``)``. 56 + CPP = 7 #: A preprocessor macro. 57 + HASH = 8 #: The hash character - useful to handle other macros. 58 + OP = 9 #: A C operator (add, subtract, ...). 59 + STRUCT = 10 #: A ``struct`` keyword. 60 + UNION = 11 #: An ``union`` keyword. 61 + ENUM = 12 #: A ``struct`` keyword. 62 + TYPEDEF = 13 #: A ``typedef`` keyword. 63 + NAME = 14 #: A name. Can be an ID or a type. 64 + SPACE = 15 #: Any space characters, including new lines 65 + ENDSTMT = 16 #: End of an statement (``;``). 66 + 67 + BACKREF = 17 #: Not a valid C sequence, but used at sub regex patterns. 68 + 69 + MISMATCH = 255 #: an error indicator: should never happen in practice. 70 + 71 + # Dict to convert from an enum interger into a string. 72 + _name_by_val = {v: k for k, v in dict(vars()).items() if isinstance(v, int)} 73 + 74 + # Dict to convert from string to an enum-like integer value. 75 + _name_to_val = {k: v for v, k in _name_by_val.items()} 76 + 77 + @staticmethod 78 + def to_name(val): 79 + """Convert from an integer value from CToken enum into a string""" 80 + 81 + return CToken._name_by_val.get(val, f"UNKNOWN({val})") 82 + 83 + @staticmethod 84 + def from_name(name): 85 + """Convert a string into a CToken enum value""" 86 + if name in CToken._name_to_val: 87 + return CToken._name_to_val[name] 88 + 89 + return CToken.MISMATCH 90 + 91 + 92 + def __init__(self, kind, value=None, pos=0, 93 + brace_level=0, paren_level=0, bracket_level=0): 94 + self.kind = kind 95 + self.value = value 96 + self.pos = pos 97 + self.level = (bracket_level, paren_level, brace_level) 98 + 99 + def __repr__(self): 100 + name = self.to_name(self.kind) 101 + if isinstance(self.value, str): 102 + value = '"' + self.value + '"' 103 + else: 104 + value = self.value 105 + 106 + return f"CToken(CToken.{name}, {value}, {self.pos}, {self.level})" 107 + 108 + #: Regexes to parse C code, transforming it into tokens. 109 + RE_SCANNER_LIST = [ 110 + # 111 + # Note that \s\S is different than .*, as it also catches \n 112 + # 113 + (CToken.COMMENT, r"//[^\n]*|/\*[\s\S]*?\*/"), 114 + 115 + (CToken.STRING, r'"(?:\\.|[^"\\])*"'), 116 + (CToken.CHAR, r"'(?:\\.|[^'\\])'"), 117 + 118 + (CToken.NUMBER, r"0[xX][\da-fA-F]+[uUlL]*|0[0-7]+[uUlL]*|" 119 + r"\d+(?:\.\d*)?(?:[eE][+-]?\d+)?[fFlL]*"), 120 + 121 + (CToken.ENDSTMT, r"(?:\s+;|;)"), 122 + 123 + (CToken.PUNC, r"[,\.]"), 124 + 125 + (CToken.BEGIN, r"[\[\(\{]"), 126 + 127 + (CToken.END, r"[\]\)\}]"), 128 + 129 + (CToken.CPP, r"#\s*(?:define|include|ifdef|ifndef|if|else|elif|endif|undef|pragma)\b"), 130 + 131 + (CToken.HASH, r"#"), 132 + 133 + (CToken.OP, r"\+\+|\-\-|\->|==|\!=|<=|>=|&&|\|\||<<|>>|\+=|\-=|\*=|/=|%=" 134 + r"|&=|\|=|\^=|[=\+\-\*/%<>&\|\^~!\?\:]"), 135 + 136 + (CToken.STRUCT, r"\bstruct\b"), 137 + (CToken.UNION, r"\bunion\b"), 138 + (CToken.ENUM, r"\benum\b"), 139 + (CToken.TYPEDEF, r"\btypedef\b"), 140 + 141 + (CToken.NAME, r"[A-Za-z_]\w*"), 142 + 143 + (CToken.SPACE, r"\s+"), 144 + 145 + (CToken.BACKREF, r"\\\d+"), 146 + 147 + (CToken.MISMATCH,r"."), 148 + ] 149 + 150 + def fill_re_scanner(token_list): 151 + """Ancillary routine to convert RE_SCANNER_LIST into a finditer regex""" 152 + re_tokens = [] 153 + 154 + for kind, pattern in token_list: 155 + name = CToken.to_name(kind) 156 + re_tokens.append(f"(?P<{name}>{pattern})") 157 + 158 + return KernRe("|".join(re_tokens), re.MULTILINE | re.DOTALL) 159 + 160 + #: Handle C continuation lines. 161 + RE_CONT = KernRe(r"\\\n") 162 + 163 + RE_COMMENT_START = KernRe(r'/\*\s*') 164 + 165 + #: tokenizer regex. Will be filled at the first CTokenizer usage. 166 + RE_SCANNER = fill_re_scanner(RE_SCANNER_LIST) 167 + 168 + 169 + class CTokenizer(): 170 + """ 171 + Scan C statements and definitions and produce tokens. 172 + 173 + When converted to string, it drops comments and handle public/private 174 + values, respecting depth. 175 + """ 176 + 177 + # This class is inspired and follows the basic concepts of: 178 + # https://docs.python.org/3/library/re.html#writing-a-tokenizer 179 + 180 + def __init__(self, source=None): 181 + """ 182 + Create a regular expression to handle RE_SCANNER_LIST. 183 + 184 + While I generally don't like using regex group naming via: 185 + (?P<name>...) 186 + 187 + in this particular case, it makes sense, as we can pick the name 188 + when matching a code via RE_SCANNER. 189 + """ 190 + 191 + # 192 + # Store logger to allow parser classes to re-use it 193 + # 194 + global log 195 + self.log = log 196 + 197 + self.tokens = [] 198 + 199 + if not source: 200 + return 201 + 202 + if isinstance(source, list): 203 + self.tokens = source 204 + return 205 + 206 + # 207 + # While we could just use _tokenize directly via interator, 208 + # As we'll need to use the tokenizer several times inside kernel-doc 209 + # to handle macro transforms, cache the results on a list, as 210 + # re-using it is cheaper than having to parse everytime. 211 + # 212 + for tok in self._tokenize(source): 213 + self.tokens.append(tok) 214 + 215 + def _tokenize(self, source): 216 + """ 217 + Iterator that parses ``source``, splitting it into tokens, as defined 218 + at ``self.RE_SCANNER_LIST``. 219 + 220 + The interactor returns a CToken class object. 221 + """ 222 + 223 + # Handle continuation lines. Note that kdoc_parser already has a 224 + # logic to do that. Still, let's keep it for completeness, as we might 225 + # end re-using this tokenizer outsize kernel-doc some day - or we may 226 + # eventually remove from there as a future cleanup. 227 + source = RE_CONT.sub("", source) 228 + 229 + brace_level = 0 230 + paren_level = 0 231 + bracket_level = 0 232 + 233 + for match in RE_SCANNER.finditer(source): 234 + kind = CToken.from_name(match.lastgroup) 235 + pos = match.start() 236 + value = match.group() 237 + 238 + if kind == CToken.MISMATCH: 239 + log.error(f"Unexpected token '{value}' on pos {pos}:\n\t'{source}'") 240 + elif kind == CToken.BEGIN: 241 + if value == '(': 242 + paren_level += 1 243 + elif value == '[': 244 + bracket_level += 1 245 + else: # value == '{' 246 + brace_level += 1 247 + 248 + elif kind == CToken.END: 249 + if value == ')' and paren_level > 0: 250 + paren_level -= 1 251 + elif value == ']' and bracket_level > 0: 252 + bracket_level -= 1 253 + elif brace_level > 0: # value == '}' 254 + brace_level -= 1 255 + 256 + yield CToken(kind, value, pos, 257 + brace_level, paren_level, bracket_level) 258 + 259 + def __str__(self): 260 + out="" 261 + show_stack = [True] 262 + 263 + for i, tok in enumerate(self.tokens): 264 + if tok.kind == CToken.BEGIN: 265 + show_stack.append(show_stack[-1]) 266 + 267 + elif tok.kind == CToken.END: 268 + prev = show_stack[-1] 269 + if len(show_stack) > 1: 270 + show_stack.pop() 271 + 272 + if not prev and show_stack[-1]: 273 + # 274 + # Try to preserve indent 275 + # 276 + out += "\t" * (len(show_stack) - 1) 277 + 278 + out += str(tok.value) 279 + continue 280 + 281 + elif tok.kind == CToken.COMMENT: 282 + comment = RE_COMMENT_START.sub("", tok.value) 283 + 284 + if comment.startswith("private:"): 285 + show_stack[-1] = False 286 + show = False 287 + elif comment.startswith("public:"): 288 + show_stack[-1] = True 289 + 290 + continue 291 + 292 + if not show_stack[-1]: 293 + continue 294 + 295 + if i < len(self.tokens) - 1: 296 + next_tok = self.tokens[i + 1] 297 + 298 + # Do some cleanups before ";" 299 + 300 + if tok.kind == CToken.SPACE and next_tok.kind == CToken.ENDSTMT: 301 + continue 302 + 303 + if tok.kind == CToken.ENDSTMT and next_tok.kind == tok.kind: 304 + continue 305 + 306 + out += str(tok.value) 307 + 308 + return out 309 + 310 + 311 + class CTokenArgs: 312 + """ 313 + Ancillary class to help using backrefs from sub matches. 314 + 315 + If the highest backref contain a "+" at the last element, 316 + the logic will be greedy, picking all other delims. 317 + 318 + This is needed to parse struct_group macros with end with ``MEMBERS...``. 319 + """ 320 + def __init__(self, sub_str): 321 + self.sub_groups = set() 322 + self.max_group = -1 323 + self.greedy = None 324 + 325 + for m in KernRe(r'\\(\d+)([+]?)').finditer(sub_str): 326 + group = int(m.group(1)) 327 + if m.group(2) == "+": 328 + if self.greedy and self.greedy != group: 329 + raise ValueError("There are multiple greedy patterns!") 330 + self.greedy = group 331 + 332 + self.sub_groups.add(group) 333 + self.max_group = max(self.max_group, group) 334 + 335 + if self.greedy: 336 + if self.greedy != self.max_group: 337 + raise ValueError("Greedy pattern is not the last one!") 338 + 339 + sub_str = KernRe(r'(\\\d+)[+]').sub(r"\1", sub_str) 340 + 341 + self.sub_str = sub_str 342 + self.sub_tokeninzer = CTokenizer(sub_str) 343 + 344 + def groups(self, new_tokenizer): 345 + r""" 346 + Create replacement arguments for backrefs like: 347 + 348 + ``\0``, ``\1``, ``\2``, ... ``\{number}`` 349 + 350 + It also accepts a ``+`` character to the highest backref, like 351 + ``\4+``. When used, the backref will be greedy, picking all other 352 + arguments afterwards. 353 + 354 + The logic is smart enough to only go up to the maximum required 355 + argument, even if there are more. 356 + 357 + If there is a backref for an argument above the limit, it will 358 + raise an exception. Please notice that, on C, square brackets 359 + don't have any separator on it. Trying to use ``\1``..``\n`` for 360 + brackets also raise an exception. 361 + """ 362 + 363 + level = (0, 0, 0) 364 + 365 + if self.max_group < 0: 366 + return level, [] 367 + 368 + tokens = new_tokenizer.tokens 369 + 370 + # 371 + # Fill \0 with the full token contents 372 + # 373 + groups_list = [ [] ] 374 + 375 + if 0 in self.sub_groups: 376 + inner_level = 0 377 + 378 + for i in range(0, len(tokens)): 379 + tok = tokens[i] 380 + 381 + if tok.kind == CToken.BEGIN: 382 + inner_level += 1 383 + 384 + # 385 + # Discard first begin 386 + # 387 + if not groups_list[0]: 388 + continue 389 + elif tok.kind == CToken.END: 390 + inner_level -= 1 391 + if inner_level < 0: 392 + break 393 + 394 + if inner_level: 395 + groups_list[0].append(tok) 396 + 397 + if not self.max_group: 398 + return level, groups_list 399 + 400 + delim = None 401 + 402 + # 403 + # Ignore everything before BEGIN. The value of begin gives the 404 + # delimiter to be used for the matches 405 + # 406 + for i in range(0, len(tokens)): 407 + tok = tokens[i] 408 + if tok.kind == CToken.BEGIN: 409 + if tok.value == "{": 410 + delim = ";" 411 + elif tok.value == "(": 412 + delim = "," 413 + else: 414 + self.log.error(fr"Can't handle \1..\n on {sub_str}") 415 + 416 + level = tok.level 417 + break 418 + 419 + pos = 1 420 + groups_list.append([]) 421 + 422 + inner_level = 0 423 + for i in range(i + 1, len(tokens)): 424 + tok = tokens[i] 425 + 426 + if tok.kind == CToken.BEGIN: 427 + inner_level += 1 428 + if tok.kind == CToken.END: 429 + inner_level -= 1 430 + if inner_level < 0: 431 + break 432 + 433 + if tok.kind in [CToken.PUNC, CToken.ENDSTMT] and delim == tok.value: 434 + pos += 1 435 + if self.greedy and pos > self.max_group: 436 + pos -= 1 437 + else: 438 + groups_list.append([]) 439 + 440 + if pos > self.max_group: 441 + break 442 + 443 + continue 444 + 445 + groups_list[pos].append(tok) 446 + 447 + if pos < self.max_group: 448 + log.error(fr"{self.sub_str} groups are up to {pos} instead of {self.max_group}") 449 + 450 + return level, groups_list 451 + 452 + def tokens(self, new_tokenizer): 453 + level, groups = self.groups(new_tokenizer) 454 + 455 + new = CTokenizer() 456 + 457 + for tok in self.sub_tokeninzer.tokens: 458 + if tok.kind == CToken.BACKREF: 459 + group = int(tok.value[1:]) 460 + 461 + for group_tok in groups[group]: 462 + new_tok = copy(group_tok) 463 + 464 + new_level = [0, 0, 0] 465 + 466 + for i in range(0, len(level)): 467 + new_level[i] = new_tok.level[i] + level[i] 468 + 469 + new_tok.level = tuple(new_level) 470 + 471 + new.tokens += [ new_tok ] 472 + else: 473 + new.tokens += [ tok ] 474 + 475 + return new.tokens 476 + 477 + 478 + class CMatch: 479 + """ 480 + Finding nested delimiters is hard with regular expressions. It is 481 + even harder on Python with its normal re module, as there are several 482 + advanced regular expressions that are missing. 483 + 484 + This is the case of this pattern:: 485 + 486 + '\\bSTRUCT_GROUP(\\(((?:(?>[^)(]+)|(?1))*)\\))[^;]*;' 487 + 488 + which is used to properly match open/close parentheses of the 489 + string search STRUCT_GROUP(), 490 + 491 + Add a class that counts pairs of delimiters, using it to match and 492 + replace nested expressions. 493 + 494 + The original approach was suggested by: 495 + 496 + https://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex 497 + 498 + Although I re-implemented it to make it more generic and match 3 types 499 + of delimiters. The logic checks if delimiters are paired. If not, it 500 + will ignore the search string. 501 + """ 502 + 503 + 504 + def __init__(self, regex, delim="("): 505 + self.regex = KernRe("^" + regex + r"\b") 506 + self.start_delim = delim 507 + 508 + def _search(self, tokenizer): 509 + """ 510 + Finds paired blocks for a regex that ends with a delimiter. 511 + 512 + The suggestion of using finditer to match pairs came from: 513 + https://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex 514 + but I ended using a different implementation to align all three types 515 + of delimiters and seek for an initial regular expression. 516 + 517 + The algorithm seeks for open/close paired delimiters and places them 518 + into a stack, yielding a start/stop position of each match when the 519 + stack is zeroed. 520 + 521 + The algorithm should work fine for properly paired lines, but will 522 + silently ignore end delimiters that precede a start delimiter. 523 + This should be OK for kernel-doc parser, as unaligned delimiters 524 + would cause compilation errors. So, we don't need to raise exceptions 525 + to cover such issues. 526 + """ 527 + 528 + start = None 529 + started = False 530 + 531 + import sys 532 + 533 + stack = [] 534 + 535 + for i, tok in enumerate(tokenizer.tokens): 536 + if start is None: 537 + if tok.kind == CToken.NAME and self.regex.match(tok.value): 538 + start = i 539 + stack.append((start, tok.level)) 540 + started = False 541 + 542 + continue 543 + 544 + if not started: 545 + if tok.kind == CToken.SPACE: 546 + continue 547 + 548 + if tok.kind == CToken.BEGIN and tok.value == self.start_delim: 549 + started = True 550 + continue 551 + 552 + # Name only token without BEGIN/END 553 + if i > start: 554 + i -= 1 555 + yield start, i 556 + start = None 557 + 558 + if tok.kind == CToken.END and tok.level == stack[-1][1]: 559 + start, level = stack.pop() 560 + 561 + yield start, i 562 + start = None 563 + 564 + # 565 + # If an END zeroing levels is not there, return remaining stuff 566 + # This is meant to solve cases where the caller logic might be 567 + # picking an incomplete block. 568 + # 569 + if start and stack: 570 + if started: 571 + s = str(tokenizer) 572 + log.warning(f"can't find a final end at {s}") 573 + 574 + yield start, len(tokenizer.tokens) 575 + 576 + def search(self, source): 577 + """ 578 + This is similar to re.search: 579 + 580 + It matches a regex that it is followed by a delimiter, 581 + returning occurrences only if all delimiters are paired. 582 + """ 583 + 584 + if isinstance(source, CTokenizer): 585 + tokenizer = source 586 + is_token = True 587 + else: 588 + tokenizer = CTokenizer(source) 589 + is_token = False 590 + 591 + for start, end in self._search(tokenizer): 592 + new_tokenizer = CTokenizer(tokenizer.tokens[start:end + 1]) 593 + 594 + if is_token: 595 + yield new_tokenizer 596 + else: 597 + yield str(new_tokenizer) 598 + 599 + def sub(self, sub_str, source, count=0): 600 + """ 601 + This is similar to re.sub: 602 + 603 + It matches a regex that it is followed by a delimiter, 604 + replacing occurrences only if all delimiters are paired. 605 + 606 + if the sub argument contains:: 607 + 608 + r'\0' 609 + 610 + it will work just like re: it places there the matched paired data 611 + with the delimiter stripped. 612 + 613 + If count is different than zero, it will replace at most count 614 + items. 615 + """ 616 + if isinstance(source, CTokenizer): 617 + is_token = True 618 + tokenizer = source 619 + else: 620 + is_token = False 621 + tokenizer = CTokenizer(source) 622 + 623 + # Detect if sub_str contains sub arguments 624 + 625 + args_match = CTokenArgs(sub_str) 626 + 627 + new_tokenizer = CTokenizer() 628 + pos = 0 629 + n = 0 630 + 631 + # 632 + # NOTE: the code below doesn't consider overlays at sub. 633 + # We may need to add some extra unit tests to check if those 634 + # would cause problems. When replacing by "", this should not 635 + # be a problem, but other transformations could be problematic 636 + # 637 + for start, end in self._search(tokenizer): 638 + new_tokenizer.tokens += tokenizer.tokens[pos:start] 639 + 640 + new = CTokenizer(tokenizer.tokens[start:end + 1]) 641 + 642 + new_tokenizer.tokens += args_match.tokens(new) 643 + 644 + pos = end + 1 645 + 646 + n += 1 647 + if count and n >= count: 648 + break 649 + 650 + new_tokenizer.tokens += tokenizer.tokens[pos:] 651 + 652 + if not is_token: 653 + return str(new_tokenizer) 654 + 655 + return new_tokenizer 656 + 657 + def __repr__(self): 658 + """ 659 + Returns a displayable version of the class init. 660 + """ 661 + 662 + return f'CMatch("{self.regex.regex.pattern}")'
+120 -35
tools/lib/python/kdoc/kdoc_files.py
··· 9 9 to generate documentation. 10 10 """ 11 11 12 - import argparse 13 12 import logging 14 13 import os 15 14 import re 16 15 17 16 from kdoc.kdoc_parser import KernelDoc 17 + from kdoc.xforms_lists import CTransforms 18 18 from kdoc.kdoc_output import OutputFormat 19 + from kdoc.kdoc_yaml_file import KDocTestFile 19 20 20 21 21 22 class GlobSourceFiles: ··· 87 86 file_not_found_cb(fname) 88 87 89 88 89 + class KdocConfig(): 90 + """ 91 + Stores all configuration attributes that kdoc_parser and kdoc_output 92 + needs. 93 + """ 94 + def __init__(self, verbose=False, werror=False, wreturn=False, 95 + wshort_desc=False, wcontents_before_sections=False, 96 + logger=None): 97 + 98 + self.verbose = verbose 99 + self.werror = werror 100 + self.wreturn = wreturn 101 + self.wshort_desc = wshort_desc 102 + self.wcontents_before_sections = wcontents_before_sections 103 + 104 + if logger: 105 + self.log = logger 106 + else: 107 + self.log = logging.getLogger(__file__) 108 + 109 + self.warning = self.log.warning 110 + 90 111 class KernelFiles(): 91 112 """ 92 113 Parse kernel-doc tags on multiple kernel source files. 93 114 94 - There are two type of parsers defined here: 115 + This is the main entry point to run kernel-doc. This class is initialized 116 + using a series of optional arguments: 117 + 118 + ``verbose`` 119 + If True, enables kernel-doc verbosity. Default: False. 120 + 121 + ``out_style`` 122 + Class to be used to format output. If None (default), 123 + only report errors. 124 + 125 + ``xforms`` 126 + Transforms to be applied to C prototypes and data structs. 127 + If not specified, defaults to xforms = CFunction() 128 + 129 + ``werror`` 130 + If True, treat warnings as errors, retuning an error code on warnings. 131 + 132 + Default: False. 133 + 134 + ``wreturn`` 135 + If True, warns about the lack of a return markup on functions. 136 + 137 + Default: False. 138 + ``wshort_desc`` 139 + If True, warns if initial short description is missing. 140 + 141 + Default: False. 142 + 143 + ``wcontents_before_sections`` 144 + If True, warn if there are contents before sections (deprecated). 145 + This option is kept just for backward-compatibility, but it does 146 + nothing, neither here nor at the original Perl script. 147 + 148 + Default: False. 149 + 150 + ``logger`` 151 + Optional logger class instance. 152 + 153 + If not specified, defaults to use: ``logging.getLogger("kernel-doc")`` 154 + 155 + ``yaml_file`` 156 + If defined, stores the output inside a YAML file. 157 + 158 + ``yaml_content`` 159 + Defines what will be inside the YAML file. 160 + 161 + Note: 162 + There are two type of parsers defined here: 163 + 95 164 - self.parse_file(): parses both kernel-doc markups and 96 165 ``EXPORT_SYMBOL*`` macros; 97 166 - self.process_export_file(): parses only ``EXPORT_SYMBOL*`` macros. ··· 188 117 if fname in self.files: 189 118 return 190 119 191 - doc = KernelDoc(self.config, fname) 120 + if self.test_file: 121 + store_src = True 122 + else: 123 + store_src = False 124 + 125 + doc = KernelDoc(self.config, fname, self.xforms, store_src=store_src) 192 126 export_table, entries = doc.parse_kdoc() 193 127 194 128 self.export_table[fname] = export_table ··· 229 153 230 154 self.error(f"Cannot find file {fname}") 231 155 232 - def __init__(self, verbose=False, out_style=None, 156 + def __init__(self, verbose=False, out_style=None, xforms=None, 233 157 werror=False, wreturn=False, wshort_desc=False, 234 158 wcontents_before_sections=False, 235 - logger=None): 159 + yaml_file=None, yaml_content=None, logger=None): 236 160 """ 237 161 Initialize startup variables and parse all files. 238 162 """ 239 163 240 164 if not verbose: 241 - verbose = bool(os.environ.get("KBUILD_VERBOSE", 0)) 165 + try: 166 + verbose = bool(int(os.environ.get("KBUILD_VERBOSE", 0))) 167 + except ValueError: 168 + # Handles an eventual case where verbosity is not a number 169 + # like KBUILD_VERBOSE="" 170 + verbose = False 242 171 243 172 if out_style is None: 244 173 out_style = OutputFormat() ··· 262 181 if kdoc_werror: 263 182 werror = kdoc_werror 264 183 184 + if not logger: 185 + logger = logging.getLogger("kernel-doc") 186 + else: 187 + logger = logger 188 + 265 189 # Some variables are global to the parser logic as a whole as they are 266 190 # used to send control configuration to KernelDoc class. As such, 267 191 # those variables are read-only inside the KernelDoc. 268 - self.config = argparse.Namespace 192 + self.config = KdocConfig(verbose, werror, wreturn, wshort_desc, 193 + wcontents_before_sections, logger) 269 194 270 - self.config.verbose = verbose 271 - self.config.werror = werror 272 - self.config.wreturn = wreturn 273 - self.config.wshort_desc = wshort_desc 274 - self.config.wcontents_before_sections = wcontents_before_sections 275 - 276 - if not logger: 277 - self.config.log = logging.getLogger("kernel-doc") 278 - else: 279 - self.config.log = logger 280 - 195 + # Override log warning, as we want to count errors 281 196 self.config.warning = self.warning 197 + 198 + if yaml_file: 199 + self.test_file = KDocTestFile(self.config, yaml_file, yaml_content) 200 + else: 201 + self.test_file = None 202 + 203 + if xforms: 204 + self.xforms = xforms 205 + else: 206 + self.xforms = CTransforms() 282 207 283 208 self.config.src_tree = os.environ.get("SRCTREE", None) 284 209 285 210 # Initialize variables that are internal to KernelFiles 286 211 287 212 self.out_style = out_style 213 + self.out_style.set_config(self.config) 288 214 289 215 self.errors = 0 290 216 self.results = {} ··· 334 246 returning kernel-doc markups on each interaction. 335 247 """ 336 248 337 - self.out_style.set_config(self.config) 338 - 339 249 if not filenames: 340 250 filenames = sorted(self.results.keys()) 341 251 ··· 353 267 for s in symbol: 354 268 function_table.add(s) 355 269 356 - self.out_style.set_filter(export, internal, symbol, nosymbol, 357 - function_table, enable_lineno, 358 - no_doc_sections) 359 - 360 - msg = "" 361 270 if fname not in self.results: 362 271 self.config.log.warning("No kernel-doc for file %s", fname) 363 272 continue 364 273 365 274 symbols = self.results[fname] 366 - self.out_style.set_symbols(symbols) 367 275 368 - for arg in symbols: 369 - m = self.out_msg(fname, arg.name, arg) 276 + if self.test_file: 277 + self.test_file.set_filter(export, internal, symbol, nosymbol, 278 + function_table, enable_lineno, 279 + no_doc_sections) 370 280 371 - if m is None: 372 - ln = arg.get("ln", 0) 373 - dtype = arg.get('type', "") 281 + self.test_file.output_symbols(fname, symbols) 374 282 375 - self.config.log.warning("%s:%d Can't handle %s", 376 - fname, ln, dtype) 377 - else: 378 - msg += m 283 + continue 379 284 285 + self.out_style.set_filter(export, internal, symbol, nosymbol, 286 + function_table, enable_lineno, 287 + no_doc_sections) 288 + 289 + msg = self.out_style.output_symbols(fname, symbols) 380 290 if msg: 381 291 yield fname, msg 292 + 293 + if self.test_file: 294 + self.test_file.write()
+41 -4
tools/lib/python/kdoc/kdoc_item.py
··· 14 14 then pass into the output modules. 15 15 """ 16 16 17 - def __init__(self, name, fname, type, start_line, **other_stuff): 17 + def __init__(self, name, fname, type, start_line, 18 + **other_stuff): 18 19 self.name = name 19 20 self.fname = fname 20 21 self.type = type ··· 23 22 self.sections = {} 24 23 self.sections_start_lines = {} 25 24 self.parameterlist = [] 26 - self.parameterdesc_start_lines = [] 25 + self.parameterdesc_start_lines = {} 27 26 self.parameterdescs = {} 28 27 self.parametertypes = {} 28 + 29 + self.warnings = [] 30 + 29 31 # 30 32 # Just save everything else into our own dict so that the output 31 33 # side can grab it directly as before. As we move things into more 32 34 # structured data, this will, hopefully, fade away. 33 35 # 34 - self.other_stuff = other_stuff 36 + known_keys = { 37 + 'declaration_start_line', 38 + 'sections', 39 + 'sections_start_lines', 40 + 'parameterlist', 41 + 'parameterdesc_start_lines', 42 + 'parameterdescs', 43 + 'parametertypes', 44 + 'warnings', 45 + } 46 + 47 + self.other_stuff = {} 48 + for k, v in other_stuff.items(): 49 + if k in known_keys: 50 + setattr(self, k, v) # real attribute 51 + else: 52 + self.other_stuff[k] = v 35 53 36 54 def get(self, key, default = None): 37 55 """ ··· 61 41 def __getitem__(self, key): 62 42 return self.get(key) 63 43 44 + def __repr__(self): 45 + return f"KdocItem({self.name}, {self.fname}, {self.type}, {self.declaration_start_line})" 46 + 47 + @classmethod 48 + def from_dict(cls, d): 49 + """Create a KdocItem from a plain dict.""" 50 + 51 + cp = d.copy() 52 + name = cp.pop('name', None) 53 + fname = cp.pop('fname', None) 54 + type = cp.pop('type', None) 55 + start_line = cp.pop('start_line', 1) 56 + other_stuff = cp.pop('other_stuff', {}) 57 + 58 + # Everything that’s left goes straight to __init__ 59 + return cls(name, fname, type, start_line, **cp, **other_stuff) 60 + 64 61 # 65 62 # Tracking of section and parameter information. 66 63 # ··· 86 49 Set sections and start lines. 87 50 """ 88 51 self.sections = sections 89 - self.section_start_lines = start_lines 52 + self.sections_start_lines = start_lines 90 53 91 54 def set_params(self, names, descs, types, starts): 92 55 """
+302 -22
tools/lib/python/kdoc/kdoc_output.py
··· 222 222 223 223 return None 224 224 225 + def output_symbols(self, fname, symbols): 226 + """ 227 + Handles a set of KdocItem symbols. 228 + """ 229 + self.set_symbols(symbols) 230 + 231 + msg = "" 232 + for arg in symbols: 233 + m = self.msg(fname, arg.name, arg) 234 + 235 + if m is None: 236 + ln = arg.get("ln", 0) 237 + dtype = arg.get('type', "") 238 + 239 + self.config.log.warning("%s:%d Can't handle %s", 240 + fname, ln, dtype) 241 + else: 242 + msg += m 243 + 244 + return msg 245 + 225 246 # Virtual methods to be overridden by inherited classes 226 247 # At the base class, those do nothing. 227 248 def set_symbols(self, symbols): ··· 389 368 else: 390 369 self.data += f'{self.lineprefix}**{section}**\n\n' 391 370 392 - self.print_lineno(args.section_start_lines.get(section, 0)) 371 + self.print_lineno(args.sections_start_lines.get(section, 0)) 393 372 self.output_highlight(text) 394 373 self.data += "\n" 395 374 self.data += "\n" ··· 513 492 def out_var(self, fname, name, args): 514 493 oldprefix = self.lineprefix 515 494 ln = args.declaration_start_line 516 - full_proto = args.other_stuff["full_proto"] 495 + full_proto = args.other_stuff.get("full_proto") 496 + if not full_proto: 497 + raise KeyError(f"Can't find full proto for {name} variable") 517 498 518 499 self.lineprefix = " " 519 500 ··· 603 580 604 581 605 582 class ManFormat(OutputFormat): 606 - """Consts and functions used by man pages output.""" 583 + """ 584 + Consts and functions used by man pages output. 585 + 586 + This class has one mandatory parameter and some optional ones, which 587 + are needed to define the title header contents: 588 + 589 + ``modulename`` 590 + Defines the module name to be used at the troff ``.TH`` output. 591 + 592 + This argument is optional. If not specified, it will be filled 593 + with the directory which contains the documented file. 594 + 595 + ``section`` 596 + Usually a numeric value from 0 to 9, but man pages also accept 597 + some strings like "p". 598 + 599 + Defauls to ``9`` 600 + 601 + ``manual`` 602 + Defaults to ``Kernel API Manual``. 603 + 604 + The above controls the output of teh corresponding fields on troff 605 + title headers, which will be filled like this:: 606 + 607 + .TH "{name}" {section} "{date}" "{modulename}" "{manual}" 608 + 609 + where ``name``` will match the API symbol name, and ``date`` will be 610 + either the date where the Kernel was compiled or the current date 611 + """ 607 612 608 613 highlights = ( 609 614 (type_constant, r"\1"), ··· 658 607 "%m %d %Y", 659 608 ] 660 609 661 - def __init__(self, modulename): 610 + def modulename(self, args): 611 + if self._modulename: 612 + return self._modulename 613 + 614 + return os.path.dirname(args.fname) 615 + 616 + def emit_th(self, name, args): 617 + """Emit a title header line.""" 618 + title = name.strip() 619 + module = self.modulename(args) 620 + 621 + self.data += f'.TH "{title}" {self.section} "{self.date}" ' 622 + self.data += f'"{module}" "{self.manual}"\n' 623 + 624 + def __init__(self, modulename=None, section="9", manual="Kernel API Manual"): 662 625 """ 663 626 Creates class variables. 664 627 ··· 681 616 """ 682 617 683 618 super().__init__() 684 - self.modulename = modulename 619 + 620 + self._modulename = modulename 621 + self.section = section 622 + self.manual = manual 623 + 685 624 self.symbols = [] 686 625 687 626 dt = None ··· 701 632 if not dt: 702 633 dt = datetime.now() 703 634 704 - self.man_date = dt.strftime("%B %Y") 635 + self.date = dt.strftime("%B %Y") 705 636 706 637 def arg_name(self, args, name): 707 638 """ ··· 716 647 dtype = args.type 717 648 718 649 if dtype == "doc": 719 - return self.modulename 650 + return name 651 + # return os.path.basename(self.modulename(args)) 720 652 721 653 if dtype in ["function", "typedef"]: 722 654 return name ··· 767 697 768 698 return self.data 769 699 700 + def emit_table(self, colspec_row, rows): 701 + 702 + if not rows: 703 + return "" 704 + 705 + out = "" 706 + colspec = "\t".join(["l"] * len(rows[0])) 707 + 708 + out += "\n.TS\n" 709 + out += "box;\n" 710 + out += f"{colspec}.\n" 711 + 712 + if colspec_row: 713 + out_row = [] 714 + 715 + for text in colspec_row: 716 + out_row.append(f"\\fB{text}\\fP") 717 + 718 + out += "\t".join(out_row) + "\n_\n" 719 + 720 + for r in rows: 721 + out += "\t".join(r) + "\n" 722 + 723 + out += ".TE\n" 724 + 725 + return out 726 + 727 + def grid_table(self, lines, start): 728 + """ 729 + Ancillary function to help handling a grid table inside the text. 730 + """ 731 + 732 + i = start + 1 733 + rows = [] 734 + colspec_row = None 735 + 736 + while i < len(lines): 737 + line = lines[i] 738 + 739 + if KernRe(r"^\s*\|.*\|\s*$").match(line): 740 + parts = [] 741 + 742 + for p in line.strip('|').split('|'): 743 + parts.append(p.strip()) 744 + 745 + rows.append(parts) 746 + 747 + elif KernRe(r'^\+\=[\+\=]+\+\s*$').match(line): 748 + if rows and rows[0]: 749 + if not colspec_row: 750 + colspec_row = [""] * len(rows[0]) 751 + 752 + for j in range(0, len(rows[0])): 753 + content = [] 754 + for row in rows: 755 + content.append(row[j]) 756 + 757 + colspec_row[j] = " ".join(content) 758 + 759 + rows = [] 760 + 761 + elif KernRe(r"^\s*\+[-+]+\+.*$").match(line): 762 + pass 763 + 764 + else: 765 + break 766 + 767 + i += 1 768 + 769 + return i, self.emit_table(colspec_row, rows) 770 + 771 + def simple_table(self, lines, start): 772 + """ 773 + Ancillary function to help handling a simple table inside the text. 774 + """ 775 + 776 + i = start 777 + rows = [] 778 + colspec_row = None 779 + 780 + pos = [] 781 + for m in KernRe(r'\=+').finditer(lines[i]): 782 + pos.append((m.start(), m.end() - 1)) 783 + 784 + i += 1 785 + while i < len(lines): 786 + line = lines[i] 787 + 788 + if KernRe(r"^\s*[\=]+[ \t\=]+$").match(line): 789 + i += 1 790 + break 791 + 792 + elif KernRe(r'^[\s=]+$').match(line): 793 + if rows and rows[0]: 794 + if not colspec_row: 795 + colspec_row = [""] * len(rows[0]) 796 + 797 + for j in range(0, len(rows[0])): 798 + content = [] 799 + for row in rows: 800 + content.append(row[j]) 801 + 802 + colspec_row[j] = " ".join(content) 803 + 804 + rows = [] 805 + 806 + else: 807 + row = [""] * len(pos) 808 + 809 + for j in range(0, len(pos)): 810 + start, end = pos[j] 811 + 812 + row[j] = line[start:end].strip() 813 + 814 + rows.append(row) 815 + 816 + i += 1 817 + 818 + return i, self.emit_table(colspec_row, rows) 819 + 820 + def code_block(self, lines, start): 821 + """ 822 + Ensure that code blocks won't be messed up at the output. 823 + 824 + By default, troff join lines at the same paragraph. Disable it, 825 + on code blocks. 826 + """ 827 + 828 + line = lines[start] 829 + 830 + if "code-block" in line: 831 + out = "\n.nf\n" 832 + elif line.startswith("..") and line.endswith("::"): 833 + # 834 + # Handle note, warning, error, ... markups 835 + # 836 + line = line[2:-1].strip().upper() 837 + out = f"\n.nf\n\\fB{line}\\fP\n" 838 + elif line.endswith("::"): 839 + out = line[:-1] 840 + out += "\n.nf\n" 841 + else: 842 + # Just in case. Should never happen in practice 843 + out = "\n.nf\n" 844 + 845 + i = start + 1 846 + ident = None 847 + 848 + while i < len(lines): 849 + line = lines[i] 850 + 851 + m = KernRe(r"\S").match(line) 852 + if not m: 853 + out += line + "\n" 854 + i += 1 855 + continue 856 + 857 + pos = m.start() 858 + if not ident: 859 + if pos > 0: 860 + ident = pos 861 + else: 862 + out += "\n.fi\n" 863 + if i > start + 1: 864 + return i - 1, out 865 + else: 866 + # Just in case. Should never happen in practice 867 + return i, out 868 + 869 + if pos >= ident: 870 + out += line + "\n" 871 + i += 1 872 + continue 873 + 874 + break 875 + 876 + out += "\n.fi\n" 877 + return i, out 878 + 770 879 def output_highlight(self, block): 771 880 """ 772 881 Outputs a C symbol that may require being highlighted with ··· 957 708 if isinstance(contents, list): 958 709 contents = "\n".join(contents) 959 710 960 - for line in contents.strip("\n").split("\n"): 961 - line = KernRe(r"^\s*").sub("", line) 962 - if not line: 963 - continue 711 + lines = contents.strip("\n").split("\n") 712 + i = 0 964 713 965 - if line[0] == ".": 966 - self.data += "\\&" + line + "\n" 714 + while i < len(lines): 715 + org_line = lines[i] 716 + 717 + line = KernRe(r"^\s*").sub("", org_line) 718 + 719 + if line: 720 + if KernRe(r"^\+\-[-+]+\+.*$").match(line): 721 + i, text = self.grid_table(lines, i) 722 + self.data += text 723 + continue 724 + 725 + if KernRe(r"^\=+[ \t]\=[ \t\=]+$").match(line): 726 + i, text = self.simple_table(lines, i) 727 + self.data += text 728 + continue 729 + 730 + if line.endswith("::") or KernRe(r"\.\.\s+code-block.*::").match(line): 731 + i, text = self.code_block(lines, i) 732 + self.data += text 733 + continue 734 + 735 + if line[0] == ".": 736 + self.data += "\\&" + line + "\n" 737 + i += 1 738 + continue 739 + 740 + # 741 + # Handle lists 742 + # 743 + line = KernRe(r'^[-*]\s+').sub(r'.IP \[bu]\n', line) 744 + line = KernRe(r'^(\d+|a-z)[\.\)]\s+').sub(r'.IP \1\n', line) 967 745 else: 968 - self.data += line + "\n" 746 + line = ".PP\n" 747 + 748 + i += 1 749 + 750 + self.data += line + "\n" 969 751 970 752 def out_doc(self, fname, name, args): 971 753 if not self.check_doc(name, args): ··· 1004 724 1005 725 out_name = self.arg_name(args, name) 1006 726 1007 - self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" 727 + self.emit_th(out_name, args) 1008 728 1009 729 for section, text in args.sections.items(): 1010 730 self.data += f'.SH "{section}"' + "\n" ··· 1014 734 1015 735 out_name = self.arg_name(args, name) 1016 736 1017 - self.data += f'.TH "{name}" 9 "{out_name}" "{self.man_date}" "Kernel Hacker\'s Manual" LINUX' + "\n" 737 + self.emit_th(out_name, args) 1018 738 1019 739 self.data += ".SH NAME\n" 1020 740 self.data += f"{name} \\- {args['purpose']}\n" ··· 1060 780 def out_enum(self, fname, name, args): 1061 781 out_name = self.arg_name(args, name) 1062 782 1063 - self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" 783 + self.emit_th(out_name, args) 1064 784 1065 785 self.data += ".SH NAME\n" 1066 786 self.data += f"enum {name} \\- {args['purpose']}\n" ··· 1093 813 out_name = self.arg_name(args, name) 1094 814 full_proto = args.other_stuff["full_proto"] 1095 815 1096 - self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" 816 + self.emit_th(out_name, args) 1097 817 1098 818 self.data += ".SH NAME\n" 1099 819 self.data += f"{name} \\- {args['purpose']}\n" ··· 1110 830 self.output_highlight(text) 1111 831 1112 832 def out_typedef(self, fname, name, args): 1113 - module = self.modulename 833 + module = self.modulename(args) 1114 834 purpose = args.get('purpose') 1115 835 out_name = self.arg_name(args, name) 1116 836 1117 - self.data += f'.TH "{module}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" 837 + self.emit_th(out_name, args) 1118 838 1119 839 self.data += ".SH NAME\n" 1120 840 self.data += f"typedef {name} \\- {purpose}\n" ··· 1124 844 self.output_highlight(text) 1125 845 1126 846 def out_struct(self, fname, name, args): 1127 - module = self.modulename 847 + module = self.modulename(args) 1128 848 purpose = args.get('purpose') 1129 849 definition = args.get('definition') 1130 850 out_name = self.arg_name(args, name) 1131 851 1132 - self.data += f'.TH "{module}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" 852 + self.emit_th(out_name, args) 1133 853 1134 854 self.data += ".SH NAME\n" 1135 855 self.data += f"{args.type} {name} \\- {purpose}\n"
+91 -201
tools/lib/python/kdoc/kdoc_parser.py
··· 13 13 import re 14 14 from pprint import pformat 15 15 16 - from kdoc.kdoc_re import NestedMatch, KernRe 16 + from kdoc.c_lex import CTokenizer, tokenizer_set_log 17 + from kdoc.kdoc_re import KernRe 17 18 from kdoc.kdoc_item import KdocItem 18 19 19 20 # ··· 71 70 cache = False) 72 71 73 72 # 74 - # Here begins a long set of transformations to turn structure member prefixes 75 - # and macro invocations into something we can parse and generate kdoc for. 76 - # 77 - struct_args_pattern = r'([^,)]+)' 78 - 79 - struct_xforms = [ 80 - # Strip attributes 81 - (KernRe(r"__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)", flags=re.I | re.S, cache=False), ' '), 82 - (KernRe(r'\s*__aligned\s*\([^;]*\)', re.S), ' '), 83 - (KernRe(r'\s*__counted_by\s*\([^;]*\)', re.S), ' '), 84 - (KernRe(r'\s*__counted_by_(le|be)\s*\([^;]*\)', re.S), ' '), 85 - (KernRe(r'\s*__packed\s*', re.S), ' '), 86 - (KernRe(r'\s*CRYPTO_MINALIGN_ATTR', re.S), ' '), 87 - (KernRe(r'\s*__private', re.S), ' '), 88 - (KernRe(r'\s*__rcu', re.S), ' '), 89 - (KernRe(r'\s*____cacheline_aligned_in_smp', re.S), ' '), 90 - (KernRe(r'\s*____cacheline_aligned', re.S), ' '), 91 - (KernRe(r'\s*__cacheline_group_(begin|end)\([^\)]+\);'), ''), 92 - # 93 - # Unwrap struct_group macros based on this definition: 94 - # __struct_group(TAG, NAME, ATTRS, MEMBERS...) 95 - # which has variants like: struct_group(NAME, MEMBERS...) 96 - # Only MEMBERS arguments require documentation. 97 - # 98 - # Parsing them happens on two steps: 99 - # 100 - # 1. drop struct group arguments that aren't at MEMBERS, 101 - # storing them as STRUCT_GROUP(MEMBERS) 102 - # 103 - # 2. remove STRUCT_GROUP() ancillary macro. 104 - # 105 - # The original logic used to remove STRUCT_GROUP() using an 106 - # advanced regex: 107 - # 108 - # \bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*; 109 - # 110 - # with two patterns that are incompatible with 111 - # Python re module, as it has: 112 - # 113 - # - a recursive pattern: (?1) 114 - # - an atomic grouping: (?>...) 115 - # 116 - # I tried a simpler version: but it didn't work either: 117 - # \bSTRUCT_GROUP\(([^\)]+)\)[^;]*; 118 - # 119 - # As it doesn't properly match the end parenthesis on some cases. 120 - # 121 - # So, a better solution was crafted: there's now a NestedMatch 122 - # class that ensures that delimiters after a search are properly 123 - # matched. So, the implementation to drop STRUCT_GROUP() will be 124 - # handled in separate. 125 - # 126 - (KernRe(r'\bstruct_group\s*\(([^,]*,)', re.S), r'STRUCT_GROUP('), 127 - (KernRe(r'\bstruct_group_attr\s*\(([^,]*,){2}', re.S), r'STRUCT_GROUP('), 128 - (KernRe(r'\bstruct_group_tagged\s*\(([^,]*),([^,]*),', re.S), r'struct \1 \2; STRUCT_GROUP('), 129 - (KernRe(r'\b__struct_group\s*\(([^,]*,){3}', re.S), r'STRUCT_GROUP('), 130 - # 131 - # Replace macros 132 - # 133 - # TODO: use NestedMatch for FOO($1, $2, ...) matches 134 - # 135 - # it is better to also move those to the NestedMatch logic, 136 - # to ensure that parentheses will be properly matched. 137 - # 138 - (KernRe(r'__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)', re.S), 139 - r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'), 140 - (KernRe(r'DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)', re.S), 141 - r'DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)'), 142 - (KernRe(r'DECLARE_BITMAP\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + r'\)', 143 - re.S), r'unsigned long \1[BITS_TO_LONGS(\2)]'), 144 - (KernRe(r'DECLARE_HASHTABLE\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + r'\)', 145 - re.S), r'unsigned long \1[1 << ((\2) - 1)]'), 146 - (KernRe(r'DECLARE_KFIFO\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + 147 - r',\s*' + struct_args_pattern + r'\)', re.S), r'\2 *\1'), 148 - (KernRe(r'DECLARE_KFIFO_PTR\s*\(' + struct_args_pattern + r',\s*' + 149 - struct_args_pattern + r'\)', re.S), r'\2 *\1'), 150 - (KernRe(r'(?:__)?DECLARE_FLEX_ARRAY\s*\(' + struct_args_pattern + r',\s*' + 151 - struct_args_pattern + r'\)', re.S), r'\1 \2[]'), 152 - (KernRe(r'DEFINE_DMA_UNMAP_ADDR\s*\(' + struct_args_pattern + r'\)', re.S), r'dma_addr_t \1'), 153 - (KernRe(r'DEFINE_DMA_UNMAP_LEN\s*\(' + struct_args_pattern + r'\)', re.S), r'__u32 \1'), 154 - ] 155 - # 156 - # Regexes here are guaranteed to have the end delimiter matching 157 - # the start delimiter. Yet, right now, only one replace group 158 - # is allowed. 159 - # 160 - struct_nested_prefixes = [ 161 - (re.compile(r'\bSTRUCT_GROUP\('), r'\1'), 162 - ] 163 - 164 - # 165 - # Transforms for function prototypes 166 - # 167 - function_xforms = [ 168 - (KernRe(r"^static +"), ""), 169 - (KernRe(r"^extern +"), ""), 170 - (KernRe(r"^asmlinkage +"), ""), 171 - (KernRe(r"^inline +"), ""), 172 - (KernRe(r"^__inline__ +"), ""), 173 - (KernRe(r"^__inline +"), ""), 174 - (KernRe(r"^__always_inline +"), ""), 175 - (KernRe(r"^noinline +"), ""), 176 - (KernRe(r"^__FORTIFY_INLINE +"), ""), 177 - (KernRe(r"__init +"), ""), 178 - (KernRe(r"__init_or_module +"), ""), 179 - (KernRe(r"__exit +"), ""), 180 - (KernRe(r"__deprecated +"), ""), 181 - (KernRe(r"__flatten +"), ""), 182 - (KernRe(r"__meminit +"), ""), 183 - (KernRe(r"__must_check +"), ""), 184 - (KernRe(r"__weak +"), ""), 185 - (KernRe(r"__sched +"), ""), 186 - (KernRe(r"_noprof"), ""), 187 - (KernRe(r"__always_unused *"), ""), 188 - (KernRe(r"__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +"), ""), 189 - (KernRe(r"__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +"), ""), 190 - (KernRe(r"__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +"), ""), 191 - (KernRe(r"DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)"), r"\1, \2"), 192 - (KernRe(r"__attribute_const__ +"), ""), 193 - (KernRe(r"__attribute__\s*\(\((?:[\w\s]+(?:\([^)]*\))?\s*,?)+\)\)\s+"), ""), 194 - ] 195 - 196 - # 197 73 # Ancillary functions 198 74 # 199 - 200 - def apply_transforms(xforms, text): 201 - """ 202 - Apply a set of transforms to a block of text. 203 - """ 204 - for search, subst in xforms: 205 - text = search.sub(subst, text) 206 - return text 207 75 208 76 multi_space = KernRe(r'\s\s+') 209 77 def trim_whitespace(s): ··· 85 215 """ 86 216 Remove ``struct``/``enum`` members that have been marked "private". 87 217 """ 88 - # First look for a "public:" block that ends a private region, then 89 - # handle the "private until the end" case. 90 - # 91 - text = KernRe(r'/\*\s*private:.*?/\*\s*public:.*?\*/', flags=re.S).sub('', text) 92 - text = KernRe(r'/\*\s*private:.*', flags=re.S).sub('', text) 93 - # 94 - # We needed the comments to do the above, but now we can take them out. 95 - # 96 - return KernRe(r'\s*/\*.*?\*/\s*', flags=re.S).sub('', text).strip() 218 + 219 + tokens = CTokenizer(text) 220 + return str(tokens) 97 221 98 222 class state: 99 223 """ ··· 140 276 self.parametertypes = {} 141 277 self.parameterdesc_start_lines = {} 142 278 143 - self.section_start_lines = {} 279 + self.sections_start_lines = {} 144 280 self.sections = {} 145 281 146 282 self.anon_struct_union = False ··· 220 356 self.sections[name] += '\n' + contents 221 357 else: 222 358 self.sections[name] = contents 223 - self.section_start_lines[name] = self.new_start_line 359 + self.sections_start_lines[name] = self.new_start_line 224 360 self.new_start_line = 0 225 361 226 362 # self.config.log.debug("Section: %s : %s", name, pformat(vars(self))) ··· 246 382 #: String to write when a parameter is not described. 247 383 undescribed = "-- undescribed --" 248 384 249 - def __init__(self, config, fname): 385 + def __init__(self, config, fname, xforms, store_src=False): 250 386 """Initialize internal variables""" 251 387 252 388 self.fname = fname 253 389 self.config = config 390 + self.xforms = xforms 391 + self.store_src = store_src 392 + 393 + tokenizer_set_log(self.config.log, f"{self.fname}: CMatch: ") 254 394 255 395 # Initial state for the state machines 256 396 self.state = state.NORMAL ··· 317 449 for section in ["Description", "Return"]: 318 450 if section in sections and not sections[section].rstrip(): 319 451 del sections[section] 320 - item.set_sections(sections, self.entry.section_start_lines) 452 + item.set_sections(sections, self.entry.sections_start_lines) 321 453 item.set_params(self.entry.parameterlist, self.entry.parameterdescs, 322 454 self.entry.parametertypes, 323 455 self.entry.parameterdesc_start_lines) ··· 717 849 return declaration 718 850 719 851 720 - def dump_struct(self, ln, proto): 852 + def dump_struct(self, ln, proto, source): 721 853 """ 722 854 Store an entry for a ``struct`` or ``union`` 723 855 """ 724 856 # 725 857 # Do the basic parse to get the pieces of the declaration. 726 858 # 859 + source = source 860 + proto = trim_private_members(proto) 727 861 struct_parts = self.split_struct_proto(proto) 728 862 if not struct_parts: 729 863 self.emit_msg(ln, f"{proto} error: Cannot parse struct or union!") ··· 739 869 # 740 870 # Go through the list of members applying all of our transformations. 741 871 # 742 - members = trim_private_members(members) 743 - members = apply_transforms(struct_xforms, members) 872 + members = self.xforms.apply("struct", members) 744 873 745 - nested = NestedMatch() 746 - for search, sub in struct_nested_prefixes: 747 - members = nested.sub(search, sub, members) 748 874 # 749 875 # Deal with embedded struct and union members, and drop enums entirely. 750 876 # ··· 754 888 declaration_name) 755 889 self.check_sections(ln, declaration_name, decl_type) 756 890 self.output_declaration(decl_type, declaration_name, 891 + source=source, 757 892 definition=self.format_struct_decl(declaration), 758 893 purpose=self.entry.declaration_purpose) 759 894 760 - def dump_enum(self, ln, proto): 895 + def dump_enum(self, ln, proto, source): 761 896 """ 762 897 Store an ``enum`` inside self.entries array. 763 898 """ ··· 766 899 # Strip preprocessor directives. Note that this depends on the 767 900 # trailing semicolon we added in process_proto_type(). 768 901 # 902 + source = source 903 + proto = trim_private_members(proto) 769 904 proto = KernRe(r'#\s*((define|ifdef|if)\s+|endif)[^;]*;', flags=re.S).sub('', proto) 770 905 # 771 906 # Parse out the name and members of the enum. Typedef form first. ··· 775 906 r = KernRe(r'typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;') 776 907 if r.search(proto): 777 908 declaration_name = r.group(2) 778 - members = trim_private_members(r.group(1)) 909 + members = r.group(1) 779 910 # 780 911 # Failing that, look for a straight enum 781 912 # ··· 783 914 r = KernRe(r'enum\s+(\w*)\s*\{(.*)\}') 784 915 if r.match(proto): 785 916 declaration_name = r.group(1) 786 - members = trim_private_members(r.group(2)) 917 + members = r.group(2) 787 918 # 788 919 # OK, this isn't going to work. 789 920 # ··· 812 943 member_set = set() 813 944 members = KernRe(r'\([^;)]*\)').sub('', members) 814 945 for arg in members.split(','): 815 - if not arg: 816 - continue 817 946 arg = KernRe(r'^\s*(\w+).*').sub(r'\1', arg) 947 + if not arg.strip(): 948 + continue 949 + 818 950 self.entry.parameterlist.append(arg) 819 951 if arg not in self.entry.parameterdescs: 820 952 self.entry.parameterdescs[arg] = self.undescribed ··· 831 961 f"Excess enum value '@{k}' description in '{declaration_name}'") 832 962 833 963 self.output_declaration('enum', declaration_name, 964 + source=source, 834 965 purpose=self.entry.declaration_purpose) 835 966 836 - def dump_var(self, ln, proto): 967 + def dump_var(self, ln, proto, source): 837 968 """ 838 969 Store variables that are part of kAPI. 839 970 """ 840 971 VAR_ATTRIBS = [ 841 972 "extern", 973 + "const", 842 974 ] 843 - OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?" 844 - 845 - sub_prefixes = [ 846 - (KernRe(r"__read_mostly"), ""), 847 - (KernRe(r"__ro_after_init"), ""), 848 - (KernRe(r"(?://.*)$"), ""), 849 - (KernRe(r"(?:/\*.*\*/)"), ""), 850 - (KernRe(r";$"), ""), 851 - (KernRe(r"=.*"), ""), 852 - ] 975 + OPTIONAL_VAR_ATTR = r"^(?:\b(?:" +"|".join(VAR_ATTRIBS) +r")\b\s*)*" 853 976 854 977 # 855 978 # Store the full prototype before modifying it 856 979 # 980 + source = source 857 981 full_proto = proto 858 982 declaration_name = None 859 983 ··· 868 1004 # Drop comments and macros to have a pure C prototype 869 1005 # 870 1006 if not declaration_name: 871 - for r, sub in sub_prefixes: 872 - proto = r.sub(sub, proto) 1007 + proto = self.xforms.apply("var", proto) 873 1008 874 1009 proto = proto.rstrip() 875 1010 ··· 878 1015 879 1016 default_val = None 880 1017 881 - r= KernRe(OPTIONAL_VAR_ATTR + r"\w.*\s+(?:\*+)?([\w_]+)\s*[\d\]\[]*\s*(=.*)?") 1018 + r= KernRe(OPTIONAL_VAR_ATTR + r"\s*[\w_\s]*\s+(?:\*+)?([\w_]+)\s*[\d\]\[]*\s*(=.*)?") 882 1019 if r.match(proto): 883 1020 if not declaration_name: 884 1021 declaration_name = r.group(1) 885 1022 886 1023 default_val = r.group(2) 887 1024 else: 888 - r= KernRe(OPTIONAL_VAR_ATTR + r"(?:\w.*)?\s+(?:\*+)?(?:[\w_]+)\s*[\d\]\[]*\s*(=.*)?") 889 - if r.match(proto): 890 - default_val = r.group(1) 1025 + r= KernRe(OPTIONAL_VAR_ATTR + r"(?:[\w_\s]*)?\s+(?:\*+)?(?:[\w_]+)\s*[\d\]\[]*\s*(=.*)?") 891 1026 1027 + if r.match(proto): 1028 + default_val = r.group(1) 892 1029 if not declaration_name: 893 1030 self.emit_msg(ln,f"{proto}: can't parse variable") 894 1031 return ··· 897 1034 default_val = default_val.lstrip("=").strip() 898 1035 899 1036 self.output_declaration("var", declaration_name, 1037 + source=source, 900 1038 full_proto=full_proto, 901 1039 default_val=default_val, 902 1040 purpose=self.entry.declaration_purpose) 903 1041 904 - def dump_declaration(self, ln, prototype): 1042 + def dump_declaration(self, ln, prototype, source): 905 1043 """ 906 1044 Store a data declaration inside self.entries array. 907 1045 """ 908 1046 909 1047 if self.entry.decl_type == "enum": 910 - self.dump_enum(ln, prototype) 1048 + self.dump_enum(ln, prototype, source) 911 1049 elif self.entry.decl_type == "typedef": 912 - self.dump_typedef(ln, prototype) 1050 + self.dump_typedef(ln, prototype, source) 913 1051 elif self.entry.decl_type in ["union", "struct"]: 914 - self.dump_struct(ln, prototype) 1052 + self.dump_struct(ln, prototype, source) 915 1053 elif self.entry.decl_type == "var": 916 - self.dump_var(ln, prototype) 1054 + self.dump_var(ln, prototype, source) 917 1055 else: 918 1056 # This would be a bug 919 1057 self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}') 920 1058 921 - def dump_function(self, ln, prototype): 1059 + def dump_function(self, ln, prototype, source): 922 1060 """ 923 1061 Store a function or function macro inside self.entries array. 924 1062 """ 925 1063 1064 + source = source 926 1065 found = func_macro = False 927 1066 return_type = '' 928 1067 decl_type = 'function' 929 - # 930 - # Apply the initial transformations. 931 - # 932 - prototype = apply_transforms(function_xforms, prototype) 1068 + 933 1069 # 934 1070 # If we have a macro, remove the "#define" at the front. 935 1071 # ··· 947 1085 declaration_name = r.group(1) 948 1086 func_macro = True 949 1087 found = True 1088 + else: 1089 + # 1090 + # Apply the initial transformations. 1091 + # 1092 + prototype = self.xforms.apply("func", prototype) 950 1093 951 1094 # Yes, this truly is vile. We are looking for: 952 1095 # 1. Return type (may be nothing if we're looking at a macro) ··· 1017 1150 # Store the result. 1018 1151 # 1019 1152 self.output_declaration(decl_type, declaration_name, 1153 + source=source, 1020 1154 typedef=('typedef' in return_type), 1021 1155 functiontype=return_type, 1022 1156 purpose=self.entry.declaration_purpose, 1023 1157 func_macro=func_macro) 1024 1158 1025 1159 1026 - def dump_typedef(self, ln, proto): 1160 + def dump_typedef(self, ln, proto, source): 1027 1161 """ 1028 1162 Store a ``typedef`` inside self.entries array. 1029 1163 """ ··· 1034 1166 typedef_type = r'typedef((?:\s+[\w*]+\b){0,7}\s+(?:\w+\b|\*+))\s*' 1035 1167 typedef_ident = r'\*?\s*(\w\S+)\s*' 1036 1168 typedef_args = r'\s*\((.*)\);' 1169 + 1170 + source = source 1037 1171 1038 1172 typedef1 = KernRe(typedef_type + r'\(' + typedef_ident + r'\)' + typedef_args) 1039 1173 typedef2 = KernRe(typedef_type + typedef_ident + typedef_args) ··· 1057 1187 self.create_parameter_list(ln, 'function', args, ',', declaration_name) 1058 1188 1059 1189 self.output_declaration('function', declaration_name, 1190 + source=source, 1060 1191 typedef=True, 1061 1192 functiontype=return_type, 1062 1193 purpose=self.entry.declaration_purpose) ··· 1075 1204 return 1076 1205 1077 1206 self.output_declaration('typedef', declaration_name, 1207 + source=source, 1078 1208 purpose=self.entry.declaration_purpose) 1079 1209 return 1080 1210 ··· 1113 1241 function_set.add(symbol) 1114 1242 return True 1115 1243 1116 - def process_normal(self, ln, line): 1244 + def process_normal(self, ln, line, source): 1117 1245 """ 1118 1246 STATE_NORMAL: looking for the ``/**`` to begin everything. 1119 1247 """ ··· 1127 1255 # next line is always the function name 1128 1256 self.state = state.NAME 1129 1257 1130 - def process_name(self, ln, line): 1258 + def process_name(self, ln, line, source): 1131 1259 """ 1132 1260 STATE_NAME: Looking for the "name - description" line 1133 1261 """ ··· 1260 1388 return False 1261 1389 1262 1390 1263 - def process_decl(self, ln, line): 1391 + def process_decl(self, ln, line, source): 1264 1392 """ 1265 1393 STATE_DECLARATION: We've seen the beginning of a declaration. 1266 1394 """ ··· 1289 1417 self.emit_msg(ln, f"bad line: {line}") 1290 1418 1291 1419 1292 - def process_special(self, ln, line): 1420 + def process_special(self, ln, line, source): 1293 1421 """ 1294 1422 STATE_SPECIAL_SECTION: a section ending with a blank line. 1295 1423 """ ··· 1340 1468 # Unknown line, ignore 1341 1469 self.emit_msg(ln, f"bad line: {line}") 1342 1470 1343 - def process_body(self, ln, line): 1471 + def process_body(self, ln, line, source): 1344 1472 """ 1345 1473 STATE_BODY: the bulk of a kerneldoc comment. 1346 1474 """ ··· 1354 1482 # Unknown line, ignore 1355 1483 self.emit_msg(ln, f"bad line: {line}") 1356 1484 1357 - def process_inline_name(self, ln, line): 1485 + def process_inline_name(self, ln, line, source): 1358 1486 """STATE_INLINE_NAME: beginning of docbook comments within a prototype.""" 1359 1487 1360 1488 if doc_inline_sect.search(line): ··· 1367 1495 elif doc_content.search(line): 1368 1496 self.emit_msg(ln, f"Incorrect use of kernel-doc format: {line}") 1369 1497 self.state = state.PROTO 1498 + 1499 + # 1500 + # Don't let it add partial comments at the code, as breaks the 1501 + # logic meant to remove comments from prototypes. 1502 + # 1503 + self.process_proto_type(ln, "/**\n" + line, source) 1370 1504 # else ... ?? 1371 1505 1372 - def process_inline_text(self, ln, line): 1506 + def process_inline_text(self, ln, line, source): 1373 1507 """STATE_INLINE_TEXT: docbook comments within a prototype.""" 1374 1508 1375 1509 if doc_inline_end.search(line): ··· 1461 1583 1462 1584 return proto 1463 1585 1464 - def process_proto_function(self, ln, line): 1586 + def process_proto_function(self, ln, line, source): 1465 1587 """Ancillary routine to process a function prototype.""" 1466 1588 1467 1589 # strip C99-style comments to end of line ··· 1503 1625 # 1504 1626 # ... and we're done 1505 1627 # 1506 - self.dump_function(ln, self.entry.prototype) 1628 + self.dump_function(ln, self.entry.prototype, source) 1507 1629 self.reset_state(ln) 1508 1630 1509 - def process_proto_type(self, ln, line): 1631 + def process_proto_type(self, ln, line, source): 1510 1632 """ 1511 1633 Ancillary routine to process a type. 1512 1634 """ ··· 1536 1658 elif chunk == '}': 1537 1659 self.entry.brcount -= 1 1538 1660 elif chunk == ';' and self.entry.brcount <= 0: 1539 - self.dump_declaration(ln, self.entry.prototype) 1661 + self.dump_declaration(ln, self.entry.prototype, source) 1540 1662 self.reset_state(ln) 1541 1663 return 1542 1664 # ··· 1545 1667 # 1546 1668 self.entry.prototype += ' ' 1547 1669 1548 - def process_proto(self, ln, line): 1670 + def process_proto(self, ln, line, source): 1549 1671 """STATE_PROTO: reading a function/whatever prototype.""" 1550 1672 1551 1673 if doc_inline_oneline.search(line): ··· 1557 1679 self.state = state.INLINE_NAME 1558 1680 1559 1681 elif self.entry.decl_type == 'function': 1560 - self.process_proto_function(ln, line) 1682 + self.process_proto_function(ln, line, source) 1561 1683 1562 1684 else: 1563 - self.process_proto_type(ln, line) 1685 + self.process_proto_type(ln, line, source) 1564 1686 1565 - def process_docblock(self, ln, line): 1687 + def process_docblock(self, ln, line, source): 1566 1688 """STATE_DOCBLOCK: within a ``DOC:`` block.""" 1567 1689 1568 1690 if doc_end.search(line): 1569 1691 self.dump_section() 1570 - self.output_declaration("doc", self.entry.identifier) 1692 + self.output_declaration("doc", self.entry.identifier, 1693 + source=source) 1571 1694 self.reset_state(ln) 1572 1695 1573 1696 elif doc_content.search(line): ··· 1619 1740 prev = "" 1620 1741 prev_ln = None 1621 1742 export_table = set() 1743 + self.state = state.NORMAL 1744 + source = "" 1622 1745 1623 1746 try: 1624 1747 with open(self.fname, "r", encoding="utf8", ··· 1647 1766 ln, state.name[self.state], 1648 1767 line) 1649 1768 1769 + if self.store_src: 1770 + if source and self.state == state.NORMAL: 1771 + source = "" 1772 + elif self.state != state.NORMAL: 1773 + source += line + "\n" 1774 + 1650 1775 # This is an optimization over the original script. 1651 1776 # There, when export_file was used for the same file, 1652 1777 # it was read twice. Here, we use the already-existing ··· 1660 1773 # 1661 1774 if (self.state != state.NORMAL) or \ 1662 1775 not self.process_export(export_table, line): 1776 + prev_state = self.state 1663 1777 # Hand this line to the appropriate state handler 1664 - self.state_actions[self.state](self, ln, line) 1778 + self.state_actions[self.state](self, ln, line, source) 1779 + if prev_state == state.NORMAL and self.state != state.NORMAL: 1780 + source += line + "\n" 1665 1781 1666 1782 self.emit_unused_warnings() 1667 1783
+37 -168
tools/lib/python/kdoc/kdoc_re.py
··· 52 52 return self.regex.pattern 53 53 54 54 def __repr__(self): 55 - return f're.compile("{self.regex.pattern}")' 55 + """ 56 + Returns a displayable version of the class init. 57 + """ 58 + 59 + flag_map = { 60 + re.IGNORECASE: "re.I", 61 + re.MULTILINE: "re.M", 62 + re.DOTALL: "re.S", 63 + re.VERBOSE: "re.X", 64 + } 65 + 66 + flags = [] 67 + for flag, name in flag_map.items(): 68 + if self.regex.flags & flag: 69 + flags.append(name) 70 + 71 + flags_name = " | ".join(flags) 72 + 73 + max_len = 60 74 + pattern = "" 75 + for pos in range(0, len(self.regex.pattern), max_len): 76 + pattern += '"' + self.regex.pattern[pos:max_len + pos] + '" ' 77 + 78 + if flags_name: 79 + return f'KernRe({pattern}, {flags_name})' 80 + else: 81 + return f'KernRe({pattern})' 56 82 57 83 def __add__(self, other): 58 84 """ ··· 103 77 104 78 self.last_match = self.regex.search(string) 105 79 return self.last_match 80 + 81 + def finditer(self, string): 82 + """ 83 + Alias to re.finditer. 84 + """ 85 + 86 + return self.regex.finditer(string) 106 87 107 88 def findall(self, string): 108 89 """ ··· 139 106 140 107 return self.last_match.group(num) 141 108 142 - 143 - class NestedMatch: 144 - """ 145 - Finding nested delimiters is hard with regular expressions. It is 146 - even harder on Python with its normal re module, as there are several 147 - advanced regular expressions that are missing. 148 - 149 - This is the case of this pattern:: 150 - 151 - '\\bSTRUCT_GROUP(\\(((?:(?>[^)(]+)|(?1))*)\\))[^;]*;' 152 - 153 - which is used to properly match open/close parentheses of the 154 - string search STRUCT_GROUP(), 155 - 156 - Add a class that counts pairs of delimiters, using it to match and 157 - replace nested expressions. 158 - 159 - The original approach was suggested by: 160 - 161 - https://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex 162 - 163 - Although I re-implemented it to make it more generic and match 3 types 164 - of delimiters. The logic checks if delimiters are paired. If not, it 165 - will ignore the search string. 166 - """ 167 - 168 - # TODO: make NestedMatch handle multiple match groups 169 - # 170 - # Right now, regular expressions to match it are defined only up to 171 - # the start delimiter, e.g.: 172 - # 173 - # \bSTRUCT_GROUP\( 174 - # 175 - # is similar to: STRUCT_GROUP\((.*)\) 176 - # except that the content inside the match group is delimiter-aligned. 177 - # 178 - # The content inside parentheses is converted into a single replace 179 - # group (e.g. r`\1'). 180 - # 181 - # It would be nice to change such definition to support multiple 182 - # match groups, allowing a regex equivalent to: 183 - # 184 - # FOO\((.*), (.*), (.*)\) 185 - # 186 - # it is probably easier to define it not as a regular expression, but 187 - # with some lexical definition like: 188 - # 189 - # FOO(arg1, arg2, arg3) 190 - 191 - DELIMITER_PAIRS = { 192 - '{': '}', 193 - '(': ')', 194 - '[': ']', 195 - } 196 - 197 - RE_DELIM = re.compile(r'[\{\}\[\]\(\)]') 198 - 199 - def _search(self, regex, line): 109 + def groups(self): 200 110 """ 201 - Finds paired blocks for a regex that ends with a delimiter. 202 - 203 - The suggestion of using finditer to match pairs came from: 204 - https://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex 205 - but I ended using a different implementation to align all three types 206 - of delimiters and seek for an initial regular expression. 207 - 208 - The algorithm seeks for open/close paired delimiters and places them 209 - into a stack, yielding a start/stop position of each match when the 210 - stack is zeroed. 211 - 212 - The algorithm should work fine for properly paired lines, but will 213 - silently ignore end delimiters that precede a start delimiter. 214 - This should be OK for kernel-doc parser, as unaligned delimiters 215 - would cause compilation errors. So, we don't need to raise exceptions 216 - to cover such issues. 111 + Returns the group results of the last match 217 112 """ 218 113 219 - stack = [] 220 - 221 - for match_re in regex.finditer(line): 222 - start = match_re.start() 223 - offset = match_re.end() 224 - 225 - d = line[offset - 1] 226 - if d not in self.DELIMITER_PAIRS: 227 - continue 228 - 229 - end = self.DELIMITER_PAIRS[d] 230 - stack.append(end) 231 - 232 - for match in self.RE_DELIM.finditer(line[offset:]): 233 - pos = match.start() + offset 234 - 235 - d = line[pos] 236 - 237 - if d in self.DELIMITER_PAIRS: 238 - end = self.DELIMITER_PAIRS[d] 239 - 240 - stack.append(end) 241 - continue 242 - 243 - # Does the end delimiter match what is expected? 244 - if stack and d == stack[-1]: 245 - stack.pop() 246 - 247 - if not stack: 248 - yield start, offset, pos + 1 249 - break 250 - 251 - def search(self, regex, line): 252 - """ 253 - This is similar to re.search: 254 - 255 - It matches a regex that it is followed by a delimiter, 256 - returning occurrences only if all delimiters are paired. 257 - """ 258 - 259 - for t in self._search(regex, line): 260 - 261 - yield line[t[0]:t[2]] 262 - 263 - def sub(self, regex, sub, line, count=0): 264 - r""" 265 - This is similar to re.sub: 266 - 267 - It matches a regex that it is followed by a delimiter, 268 - replacing occurrences only if all delimiters are paired. 269 - 270 - if the sub argument contains:: 271 - 272 - r'\1' 273 - 274 - it will work just like re: it places there the matched paired data 275 - with the delimiter stripped. 276 - 277 - If count is different than zero, it will replace at most count 278 - items. 279 - """ 280 - out = "" 281 - 282 - cur_pos = 0 283 - n = 0 284 - 285 - for start, end, pos in self._search(regex, line): 286 - out += line[cur_pos:start] 287 - 288 - # Value, ignoring start/end delimiters 289 - value = line[end:pos - 1] 290 - 291 - # replaces \1 at the sub string, if \1 is used there 292 - new_sub = sub 293 - new_sub = new_sub.replace(r'\1', value) 294 - 295 - out += new_sub 296 - 297 - # Drop end ';' if any 298 - if line[pos] == ';': 299 - pos += 1 300 - 301 - cur_pos = pos 302 - n += 1 303 - 304 - if count and count >= n: 305 - break 306 - 307 - # Append the remaining string 308 - l = len(line) 309 - out += line[cur_pos:l] 310 - 311 - return out 114 + return self.last_match.groups()
+178
tools/lib/python/kdoc/kdoc_yaml_file.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Copyright(c) 2026: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + 5 + import os 6 + 7 + from kdoc.kdoc_output import ManFormat, RestFormat 8 + 9 + 10 + class KDocTestFile(): 11 + """ 12 + Handles the logic needed to store kernel‑doc output inside a YAML file. 13 + Useful for unit tests and regression tests. 14 + """ 15 + 16 + def __init__(self, config, yaml_file, yaml_content): 17 + # 18 + # Bail out early if yaml is not available 19 + # 20 + try: 21 + import yaml 22 + except ImportError: 23 + sys.exit("Warning: yaml package not available. Aborting it.") 24 + 25 + self.config = config 26 + self.test_file = os.path.expanduser(yaml_file) 27 + self.yaml_content = yaml_content 28 + self.test_names = set() 29 + 30 + self.tests = [] 31 + 32 + out_dir = os.path.dirname(self.test_file) 33 + if out_dir and not os.path.isdir(out_dir): 34 + sys.exit(f"Directory {out_dir} doesn't exist.") 35 + 36 + self.out_style = [] 37 + 38 + if "man" in self.yaml_content: 39 + out_style = ManFormat() 40 + out_style.set_config(self.config) 41 + 42 + self.out_style.append(out_style) 43 + 44 + if "rst" in self.yaml_content: 45 + out_style = RestFormat() 46 + out_style.set_config(self.config) 47 + 48 + self.out_style.append(out_style) 49 + 50 + def set_filter(self, export, internal, symbol, nosymbol, 51 + function_table, enable_lineno, no_doc_sections): 52 + """ 53 + Set filters at the output classes. 54 + """ 55 + for out_style in self.out_style: 56 + out_style.set_filter(export, internal, symbol, 57 + nosymbol, function_table, 58 + enable_lineno, no_doc_sections) 59 + 60 + @staticmethod 61 + def get_kdoc_item(arg, start_line=1): 62 + 63 + d = vars(arg) 64 + 65 + declaration_start_line = d.get("declaration_start_line") 66 + if not declaration_start_line: 67 + return d 68 + 69 + d["declaration_start_line"] = start_line 70 + 71 + parameterdesc_start_lines = d.get("parameterdesc_start_lines") 72 + if parameterdesc_start_lines: 73 + for key in parameterdesc_start_lines: 74 + ln = parameterdesc_start_lines[key] 75 + ln += start_line - declaration_start_line 76 + 77 + parameterdesc_start_lines[key] = ln 78 + 79 + sections_start_lines = d.get("sections_start_lines") 80 + if sections_start_lines: 81 + for key in sections_start_lines: 82 + ln = sections_start_lines[key] 83 + ln += start_line - declaration_start_line 84 + 85 + sections_start_lines[key] = ln 86 + 87 + return d 88 + 89 + def output_symbols(self, fname, symbols): 90 + """ 91 + Store source, symbols and output strings at self.tests. 92 + """ 93 + 94 + # 95 + # KdocItem needs to be converted into dicts 96 + # 97 + kdoc_item = [] 98 + expected = [] 99 + 100 + # 101 + # Source code didn't produce any symbol 102 + # 103 + if not symbols: 104 + return 105 + 106 + expected_dict = {} 107 + start_line=1 108 + 109 + for arg in symbols: 110 + source = arg.get("source", "") 111 + 112 + if arg and "KdocItem" in self.yaml_content: 113 + msg = self.get_kdoc_item(arg) 114 + 115 + other_stuff = msg.get("other_stuff", {}) 116 + if "source" in other_stuff: 117 + del other_stuff["source"] 118 + 119 + expected_dict["kdoc_item"] = msg 120 + 121 + base_name = arg.name 122 + if not base_name: 123 + base_name = fname 124 + base_name = base_name.lower().replace(".", "_").replace("/", "_") 125 + 126 + 127 + # Don't add duplicated names 128 + i = 0 129 + name = base_name 130 + while name in self.test_names: 131 + i += 1 132 + name = f"{base_name}_{i:03d}" 133 + 134 + self.test_names.add(name) 135 + 136 + for out_style in self.out_style: 137 + if isinstance(out_style, ManFormat): 138 + key = "man" 139 + else: 140 + key = "rst" 141 + 142 + expected_dict[key]= out_style.output_symbols(fname, [arg]).strip() 143 + 144 + test = { 145 + "name": name, 146 + "description": f"{fname} line {arg.declaration_start_line}", 147 + "fname": fname, 148 + "source": source, 149 + "expected": [expected_dict] 150 + } 151 + 152 + self.tests.append(test) 153 + 154 + expected_dict = {} 155 + 156 + def write(self): 157 + """ 158 + Output the content of self.tests to self.test_file. 159 + """ 160 + import yaml 161 + 162 + # Helper function to better handle multilines 163 + def str_presenter(dumper, data): 164 + if "\n" in data: 165 + return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|") 166 + 167 + return dumper.represent_scalar("tag:yaml.org,2002:str", data) 168 + 169 + # Register the representer 170 + yaml.add_representer(str, str_presenter) 171 + 172 + data = {"tests": self.tests} 173 + 174 + with open(self.test_file, "w", encoding="utf-8") as fp: 175 + yaml.dump(data, fp, 176 + sort_keys=False, width=120, indent=2, 177 + default_flow_style=False, allow_unicode=True, 178 + explicit_start=False, explicit_end=False)
+153
tools/lib/python/kdoc/xforms_lists.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Copyright(c) 2026: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + 5 + import re 6 + 7 + from kdoc.kdoc_re import KernRe 8 + from kdoc.c_lex import CMatch, CTokenizer 9 + 10 + struct_args_pattern = r"([^,)]+)" 11 + 12 + 13 + class CTransforms: 14 + """ 15 + Data class containing a long set of transformations to turn 16 + structure member prefixes, and macro invocations and variables 17 + into something we can parse and generate kdoc for. 18 + """ 19 + 20 + # 21 + # NOTE: 22 + # Due to performance reasons, place CMatch rules before KernRe, 23 + # as this avoids running the C parser every time. 24 + # 25 + 26 + #: Transforms for structs and unions. 27 + struct_xforms = [ 28 + (CMatch("__attribute__"), ""), 29 + (CMatch("__aligned"), ""), 30 + (CMatch("__counted_by"), ""), 31 + (CMatch("__counted_by_(le|be)"), ""), 32 + (CMatch("__guarded_by"), ""), 33 + (CMatch("__pt_guarded_by"), ""), 34 + (CMatch("__packed"), ""), 35 + (CMatch("CRYPTO_MINALIGN_ATTR"), ""), 36 + (CMatch("__private"), ""), 37 + (CMatch("__rcu"), ""), 38 + (CMatch("____cacheline_aligned_in_smp"), ""), 39 + (CMatch("____cacheline_aligned"), ""), 40 + (CMatch("__cacheline_group_(?:begin|end)"), ""), 41 + (CMatch("__ETHTOOL_DECLARE_LINK_MODE_MASK"), r"DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)"), 42 + (CMatch("DECLARE_PHY_INTERFACE_MASK",),r"DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)"), 43 + (CMatch("DECLARE_BITMAP"), r"unsigned long \1[BITS_TO_LONGS(\2)]"), 44 + (CMatch("DECLARE_HASHTABLE"), r"unsigned long \1[1 << ((\2) - 1)]"), 45 + (CMatch("DECLARE_KFIFO"), r"\2 *\1"), 46 + (CMatch("DECLARE_KFIFO_PTR"), r"\2 *\1"), 47 + (CMatch("(?:__)?DECLARE_FLEX_ARRAY"), r"\1 \2[]"), 48 + (CMatch("DEFINE_DMA_UNMAP_ADDR"), r"dma_addr_t \1"), 49 + (CMatch("DEFINE_DMA_UNMAP_LEN"), r"__u32 \1"), 50 + (CMatch("VIRTIO_DECLARE_FEATURES"), r"union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }"), 51 + (CMatch("__cond_acquires"), ""), 52 + (CMatch("__cond_releases"), ""), 53 + (CMatch("__acquires"), ""), 54 + (CMatch("__releases"), ""), 55 + (CMatch("__must_hold"), ""), 56 + (CMatch("__must_not_hold"), ""), 57 + (CMatch("__must_hold_shared"), ""), 58 + (CMatch("__cond_acquires_shared"), ""), 59 + (CMatch("__acquires_shared"), ""), 60 + (CMatch("__releases_shared"), ""), 61 + (CMatch("__attribute__"), ""), 62 + 63 + # 64 + # Macro __struct_group() creates an union with an anonymous 65 + # and a non-anonymous struct, depending on the parameters. We only 66 + # need one of those at kernel-doc, as we won't be documenting the same 67 + # members twice. 68 + # 69 + (CMatch("struct_group"), r"struct { \2+ };"), 70 + (CMatch("struct_group_attr"), r"struct { \3+ };"), 71 + (CMatch("struct_group_tagged"), r"struct { \3+ };"), 72 + (CMatch("__struct_group"), r"struct { \4+ };"), 73 + ] 74 + 75 + #: Transforms for function prototypes. 76 + function_xforms = [ 77 + (CMatch("static"), ""), 78 + (CMatch("extern"), ""), 79 + (CMatch("asmlinkage"), ""), 80 + (CMatch("inline"), ""), 81 + (CMatch("__inline__"), ""), 82 + (CMatch("__inline"), ""), 83 + (CMatch("__always_inline"), ""), 84 + (CMatch("noinline"), ""), 85 + (CMatch("__FORTIFY_INLINE"), ""), 86 + (CMatch("__init"), ""), 87 + (CMatch("__init_or_module"), ""), 88 + (CMatch("__exit"), ""), 89 + (CMatch("__deprecated"), ""), 90 + (CMatch("__flatten"), ""), 91 + (CMatch("__meminit"), ""), 92 + (CMatch("__must_check"), ""), 93 + (CMatch("__weak"), ""), 94 + (CMatch("__sched"), ""), 95 + (CMatch("__always_unused"), ""), 96 + (CMatch("__printf"), ""), 97 + (CMatch("__(?:re)?alloc_size"), ""), 98 + (CMatch("__diagnose_as"), ""), 99 + (CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"), 100 + (CMatch("__no_context_analysis"), ""), 101 + (CMatch("__attribute_const__"), ""), 102 + (CMatch("__attribute__"), ""), 103 + 104 + # 105 + # HACK: this is similar to process_export() hack. It is meant to 106 + # drop _noproof from function name. See for instance: 107 + # ahash_request_alloc kernel-doc declaration at include/crypto/hash.h. 108 + # 109 + (KernRe("_noprof"), ""), 110 + ] 111 + 112 + #: Transforms for variable prototypes. 113 + var_xforms = [ 114 + (CMatch("__read_mostly"), ""), 115 + (CMatch("__ro_after_init"), ""), 116 + (CMatch("__guarded_by"), ""), 117 + (CMatch("__pt_guarded_by"), ""), 118 + (CMatch("LIST_HEAD"), r"struct list_head \1"), 119 + 120 + (KernRe(r"(?://.*)$"), ""), 121 + (KernRe(r"(?:/\*.*\*/)"), ""), 122 + (KernRe(r";$"), ""), 123 + ] 124 + 125 + #: Transforms main dictionary used at apply_transforms(). 126 + xforms = { 127 + "struct": struct_xforms, 128 + "func": function_xforms, 129 + "var": var_xforms, 130 + } 131 + 132 + def apply(self, xforms_type, source): 133 + """ 134 + Apply a set of transforms to a block of source. 135 + 136 + As tokenizer is used here, this function also remove comments 137 + at the end. 138 + """ 139 + if xforms_type not in self.xforms: 140 + return source 141 + 142 + if isinstance(source, str): 143 + source = CTokenizer(source) 144 + 145 + for search, subst in self.xforms[xforms_type]: 146 + # 147 + # KernRe only accept strings. 148 + # 149 + if isinstance(search, KernRe): 150 + source = str(source) 151 + 152 + source = search.sub(subst, source) 153 + return str(source)
+363
tools/lib/python/unittest_helper.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Copyright(c) 2025-2026: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + # 5 + # pylint: disable=C0103,R0912,R0914,E1101 6 + 7 + """ 8 + Provides helper functions and classes execute python unit tests. 9 + 10 + Those help functions provide a nice colored output summary of each 11 + executed test and, when a test fails, it shows the different in diff 12 + format when running in verbose mode, like:: 13 + 14 + $ tools/unittests/nested_match.py -v 15 + ... 16 + Traceback (most recent call last): 17 + File "/new_devel/docs/tools/unittests/nested_match.py", line 69, in test_count_limit 18 + self.assertEqual(replaced, "bar(a); bar(b); foo(c)") 19 + ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 20 + AssertionError: 'bar(a) foo(b); foo(c)' != 'bar(a); bar(b); foo(c)' 21 + - bar(a) foo(b); foo(c) 22 + ? ^^^^ 23 + + bar(a); bar(b); foo(c) 24 + ? ^^^^^ 25 + ... 26 + 27 + It also allows filtering what tests will be executed via ``-k`` parameter. 28 + 29 + Typical usage is to do:: 30 + 31 + from unittest_helper import run_unittest 32 + ... 33 + 34 + if __name__ == "__main__": 35 + run_unittest(__file__) 36 + 37 + If passing arguments is needed, on a more complex scenario, it can be 38 + used like on this example:: 39 + 40 + from unittest_helper import TestUnits, run_unittest 41 + ... 42 + env = {'sudo': ""} 43 + ... 44 + if __name__ == "__main__": 45 + runner = TestUnits() 46 + base_parser = runner.parse_args() 47 + base_parser.add_argument('--sudo', action='store_true', 48 + help='Enable tests requiring sudo privileges') 49 + 50 + args = base_parser.parse_args() 51 + 52 + # Update module-level flag 53 + if args.sudo: 54 + env['sudo'] = "1" 55 + 56 + # Run tests with customized arguments 57 + runner.run(__file__, parser=base_parser, args=args, env=env) 58 + """ 59 + 60 + import argparse 61 + import atexit 62 + import os 63 + import re 64 + import unittest 65 + import sys 66 + 67 + from unittest.mock import patch 68 + 69 + 70 + class Summary(unittest.TestResult): 71 + """ 72 + Overrides ``unittest.TestResult`` class to provide a nice colored 73 + summary. When in verbose mode, displays actual/expected difference in 74 + unified diff format. 75 + """ 76 + def __init__(self, *args, **kwargs): 77 + super().__init__(*args, **kwargs) 78 + 79 + #: Dictionary to store organized test results. 80 + self.test_results = {} 81 + 82 + #: max length of the test names. 83 + self.max_name_length = 0 84 + 85 + def startTest(self, test): 86 + super().startTest(test) 87 + test_id = test.id() 88 + parts = test_id.split(".") 89 + 90 + # Extract module, class, and method names 91 + if len(parts) >= 3: 92 + module_name = parts[-3] 93 + else: 94 + module_name = "" 95 + if len(parts) >= 2: 96 + class_name = parts[-2] 97 + else: 98 + class_name = "" 99 + 100 + method_name = parts[-1] 101 + 102 + # Build the hierarchical structure 103 + if module_name not in self.test_results: 104 + self.test_results[module_name] = {} 105 + 106 + if class_name not in self.test_results[module_name]: 107 + self.test_results[module_name][class_name] = [] 108 + 109 + # Track maximum test name length for alignment 110 + display_name = f"{method_name}:" 111 + 112 + self.max_name_length = max(len(display_name), self.max_name_length) 113 + 114 + def _record_test(self, test, status): 115 + test_id = test.id() 116 + parts = test_id.split(".") 117 + if len(parts) >= 3: 118 + module_name = parts[-3] 119 + else: 120 + module_name = "" 121 + if len(parts) >= 2: 122 + class_name = parts[-2] 123 + else: 124 + class_name = "" 125 + method_name = parts[-1] 126 + self.test_results[module_name][class_name].append((method_name, status)) 127 + 128 + def addSuccess(self, test): 129 + super().addSuccess(test) 130 + self._record_test(test, "OK") 131 + 132 + def addFailure(self, test, err): 133 + super().addFailure(test, err) 134 + self._record_test(test, "FAIL") 135 + 136 + def addError(self, test, err): 137 + super().addError(test, err) 138 + self._record_test(test, "ERROR") 139 + 140 + def addSkip(self, test, reason): 141 + super().addSkip(test, reason) 142 + self._record_test(test, f"SKIP ({reason})") 143 + 144 + def printResults(self, verbose): 145 + """ 146 + Print results using colors if tty. 147 + """ 148 + # Check for ANSI color support 149 + use_color = sys.stdout.isatty() 150 + COLORS = { 151 + "OK": "\033[32m", # Green 152 + "FAIL": "\033[31m", # Red 153 + "SKIP": "\033[1;33m", # Yellow 154 + "PARTIAL": "\033[33m", # Orange 155 + "EXPECTED_FAIL": "\033[36m", # Cyan 156 + "reset": "\033[0m", # Reset to default terminal color 157 + } 158 + if not use_color: 159 + for c in COLORS: 160 + COLORS[c] = "" 161 + 162 + # Calculate maximum test name length 163 + if not self.test_results: 164 + return 165 + try: 166 + lengths = [] 167 + for module in self.test_results.values(): 168 + for tests in module.values(): 169 + for test_name, _ in tests: 170 + lengths.append(len(test_name) + 1) # +1 for colon 171 + max_length = max(lengths) + 2 # Additional padding 172 + except ValueError: 173 + sys.exit("Test list is empty") 174 + 175 + # Print results 176 + for module_name, classes in self.test_results.items(): 177 + if verbose: 178 + print(f"{module_name}:") 179 + for class_name, tests in classes.items(): 180 + if verbose: 181 + print(f" {class_name}:") 182 + for test_name, status in tests: 183 + if not verbose and status in [ "OK", "EXPECTED_FAIL" ]: 184 + continue 185 + 186 + # Get base status without reason for SKIP 187 + if status.startswith("SKIP"): 188 + status_code = status.split()[0] 189 + else: 190 + status_code = status 191 + color = COLORS.get(status_code, "") 192 + print( 193 + f" {test_name + ':':<{max_length}}{color}{status}{COLORS['reset']}" 194 + ) 195 + if verbose: 196 + print() 197 + 198 + # Print summary 199 + print(f"\nRan {self.testsRun} tests", end="") 200 + if hasattr(self, "timeTaken"): 201 + print(f" in {self.timeTaken:.3f}s", end="") 202 + print() 203 + 204 + if not self.wasSuccessful(): 205 + print(f"\n{COLORS['FAIL']}FAILED (", end="") 206 + failures = getattr(self, "failures", []) 207 + errors = getattr(self, "errors", []) 208 + if failures: 209 + print(f"failures={len(failures)}", end="") 210 + if errors: 211 + if failures: 212 + print(", ", end="") 213 + print(f"errors={len(errors)}", end="") 214 + print(f"){COLORS['reset']}") 215 + 216 + 217 + def flatten_suite(suite): 218 + """Flatten test suite hierarchy.""" 219 + tests = [] 220 + for item in suite: 221 + if isinstance(item, unittest.TestSuite): 222 + tests.extend(flatten_suite(item)) 223 + else: 224 + tests.append(item) 225 + return tests 226 + 227 + 228 + class TestUnits: 229 + """ 230 + Helper class to set verbosity level. 231 + 232 + This class discover test files, import its unittest classes and 233 + executes the test on it. 234 + """ 235 + def parse_args(self): 236 + """Returns a parser for command line arguments.""" 237 + parser = argparse.ArgumentParser(description="Test runner with regex filtering") 238 + parser.add_argument("-v", "--verbose", action="count", default=1) 239 + parser.add_argument("-q", "--quiet", action="store_true") 240 + parser.add_argument("-f", "--failfast", action="store_true") 241 + parser.add_argument("-k", "--keyword", 242 + help="Regex pattern to filter test methods") 243 + return parser 244 + 245 + def run(self, caller_file=None, pattern=None, 246 + suite=None, parser=None, args=None, env=None): 247 + """ 248 + Execute all tests from the unity test file. 249 + 250 + It contains several optional parameters: 251 + 252 + ``caller_file``: 253 + - name of the file that contains test. 254 + 255 + typical usage is to place __file__ at the caller test, e.g.:: 256 + 257 + if __name__ == "__main__": 258 + TestUnits().run(__file__) 259 + 260 + ``pattern``: 261 + - optional pattern to match multiple file names. Defaults 262 + to basename of ``caller_file``. 263 + 264 + ``suite``: 265 + - an unittest suite initialized by the caller using 266 + ``unittest.TestLoader().discover()``. 267 + 268 + ``parser``: 269 + - an argparse parser. If not defined, this helper will create 270 + one. 271 + 272 + ``args``: 273 + - an ``argparse.Namespace`` data filled by the caller. 274 + 275 + ``env``: 276 + - environment variables that will be passed to the test suite 277 + 278 + At least ``caller_file`` or ``suite`` must be used, otherwise a 279 + ``TypeError`` will be raised. 280 + """ 281 + if not args: 282 + if not parser: 283 + parser = self.parse_args() 284 + args = parser.parse_args() 285 + 286 + if not caller_file and not suite: 287 + raise TypeError("Either caller_file or suite is needed at TestUnits") 288 + 289 + if args.quiet: 290 + verbose = 0 291 + else: 292 + verbose = args.verbose 293 + 294 + if not env: 295 + env = os.environ.copy() 296 + 297 + env["VERBOSE"] = f"{verbose}" 298 + 299 + patcher = patch.dict(os.environ, env) 300 + patcher.start() 301 + # ensure it gets stopped after 302 + atexit.register(patcher.stop) 303 + 304 + 305 + if verbose >= 2: 306 + unittest.TextTestRunner(verbosity=verbose).run = lambda suite: suite 307 + 308 + # Load ONLY tests from the calling file 309 + if not suite: 310 + if not pattern: 311 + pattern = caller_file 312 + 313 + loader = unittest.TestLoader() 314 + suite = loader.discover(start_dir=os.path.dirname(caller_file), 315 + pattern=os.path.basename(caller_file)) 316 + 317 + # Flatten the suite for environment injection 318 + tests_to_inject = flatten_suite(suite) 319 + 320 + # Filter tests by method name if -k specified 321 + if args.keyword: 322 + try: 323 + pattern = re.compile(args.keyword) 324 + filtered_suite = unittest.TestSuite() 325 + for test in tests_to_inject: # Use the pre-flattened list 326 + method_name = test.id().split(".")[-1] 327 + if pattern.search(method_name): 328 + filtered_suite.addTest(test) 329 + suite = filtered_suite 330 + except re.error as e: 331 + sys.stderr.write(f"Invalid regex pattern: {e}\n") 332 + sys.exit(1) 333 + else: 334 + # Maintain original suite structure if no keyword filtering 335 + suite = unittest.TestSuite(tests_to_inject) 336 + 337 + if verbose >= 2: 338 + resultclass = None 339 + else: 340 + resultclass = Summary 341 + 342 + runner = unittest.TextTestRunner(verbosity=args.verbose, 343 + resultclass=resultclass, 344 + failfast=args.failfast) 345 + result = runner.run(suite) 346 + if resultclass: 347 + result.printResults(verbose) 348 + 349 + sys.exit(not result.wasSuccessful()) 350 + 351 + 352 + def run_unittest(fname): 353 + """ 354 + Basic usage of TestUnits class. 355 + 356 + Use it when there's no need to pass any extra argument to the tests 357 + with. The recommended way is to place this at the end of each 358 + unittest module:: 359 + 360 + if __name__ == "__main__": 361 + run_unittest(__file__) 362 + """ 363 + TestUnits().run(fname)
+156
tools/unittests/kdoc-test-schema.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Copyright(c) 2026: Mauro Carvalho Chehab <mchehab@kernel.org>. 3 + 4 + # KDoc Test File Schema 5 + 6 + # This schema contains objects and properties needed to run kernel-doc 7 + # self-tests. 8 + 9 + $schema: "http://json-schema.org/draft-07/schema#" 10 + 11 + tests: 12 + type: array 13 + minItems: 1 14 + description: | 15 + A list of kernel-doc tests. 16 + 17 + properties: 18 + type: object 19 + properties: 20 + name: 21 + type: string 22 + description: | 23 + Test name. Should be an unique identifier within the schema. 24 + Don't prepend it with "test", as the dynamic test creation will 25 + do it. 26 + 27 + description: 28 + type: string 29 + description: | 30 + Test description 31 + 32 + source: 33 + type: string 34 + description: | 35 + C source code that should be parsed by kernel-doc. 36 + 37 + fname: 38 + type: string 39 + description: | 40 + The filename that contains the element. 41 + When placing real testcases, please use here the name of 42 + the C file (or header) from where the source code was picked. 43 + 44 + exports: 45 + type: array 46 + items: { type: string } 47 + description: | 48 + A list of export identifiers that are expected when parsing source. 49 + 50 + expected: 51 + type: array 52 + minItems: 1 53 + description: | 54 + A list of expected values. This list consists on objects to check 55 + both kdoc_parser and/or kdoc_output objects. 56 + 57 + items: 58 + type: object 59 + properties: 60 + # 61 + # kdoc_item 62 + # 63 + kdoc_item: 64 + type: object 65 + description: | 66 + Object expected to represent the C source code after parsed 67 + by tools/lib/python/kdoc/kdoc_parser.py KernelDoc class. 68 + See tools/lib/python/kdoc/kdoc_item.py for its contents. 69 + 70 + properties: 71 + name: 72 + type: string 73 + description: | 74 + The name of the identifier (function name, struct name, etc). 75 + type: 76 + type: string 77 + description: | 78 + Type of the object, as filled by kdoc_parser. can be: 79 + - enum 80 + - typedef 81 + - union 82 + - struct 83 + - var 84 + - function 85 + declaration_start_line: 86 + type: integer 87 + description: | 88 + The line number where the kernel-doc markup started. 89 + The first line of the code is line number 1. 90 + sections: 91 + type: object 92 + additionalProperties: { type: string } 93 + description: | 94 + Sections inside the kernel-doc markups: 95 + - "description" 96 + - "return" 97 + - any other part of the markup that starts with "something:" 98 + sections_start_lines: 99 + type: object 100 + additionalProperties: { type: integer } 101 + description: | 102 + a list of section names and the starting line of it. 103 + parameterlist: 104 + type: array 105 + items: { type: string } 106 + description: | 107 + Ordered list of parameter names. 108 + 109 + parameterdesc_start_lines: 110 + type: object 111 + additionalProperties: { type: integer } 112 + description: | 113 + Mapping from parameter name to the line where its 114 + description starts. 115 + parameterdescs: 116 + type: object 117 + additionalProperties: { type: string } 118 + description: | 119 + Mapping from parameter name to its description. 120 + 121 + parametertypes: 122 + type: object 123 + additionalProperties: { type: string } 124 + description: | 125 + Mapping from parameter name to its type. 126 + 127 + other_stuff: 128 + type: object 129 + additionalProperties: {} 130 + description: | 131 + Extra properties that will be stored at the item. 132 + Should match what kdoc_output expects. 133 + 134 + required: 135 + - name 136 + - type 137 + - declaration_start_line 138 + 139 + rst: 140 + type: string 141 + description: | 142 + The expected output for RestOutput class. 143 + 144 + man: 145 + type: string 146 + description: | 147 + The expected output for ManOutput class. 148 + 149 + anyOf: 150 + required: kdoc_item 151 + required: source 152 + 153 + required: 154 + - name 155 + - fname 156 + - expected
+1698
tools/unittests/kdoc-test.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Copyright (c) 2026: Mauro Carvalho Chehab <mchehab@kernel.org> 3 + 4 + # Test cases for the dynamic tests. 5 + # Useful to test if kernel-doc classes are doing what it is expected. 6 + # 7 + 8 + tests: 9 + - name: func1 10 + fname: mock_functions.c 11 + description: "Simplest function test: do nothing, just rst output" 12 + 13 + source: | 14 + /** 15 + * func1 - Not exported function 16 + * @arg1: @arg1 does nothing 17 + * 18 + * Does nothing 19 + * 20 + * return: 21 + * always return 0. 22 + */ 23 + int func1(char *arg1) { return 0; }; 24 + 25 + expected: 26 + - rst: | 27 + .. c:function:: int func1 (char *arg1) 28 + 29 + Not exported function 30 + 31 + .. container:: kernelindent 32 + 33 + **Parameters** 34 + 35 + ``char *arg1`` 36 + **arg1** does nothing 37 + 38 + **Description** 39 + 40 + Does nothing 41 + 42 + **Return** 43 + 44 + always return 0. 45 + 46 + # TODO: how to handle timestamps at .TH? 47 + man: | 48 + .TH "func1" 9 "February 2026" "" "Kernel API Manual" 49 + .SH NAME 50 + func1 \- Not exported function 51 + .SH SYNOPSIS 52 + .B "int" func1 53 + .BI "(char *arg1 " ");" 54 + .SH ARGUMENTS 55 + .IP "arg1" 12 56 + \fIarg1\fP does nothing 57 + .SH "DESCRIPTION" 58 + Does nothing 59 + .SH "RETURN" 60 + always return 0. 61 + .SH "SEE ALSO" 62 + .PP 63 + Kernel file \fBmock_functions.c\fR 64 + 65 + - name: func2 66 + fname: func2.c 67 + description: Simple test with exports 68 + 69 + source: | 70 + /** 71 + * func2() - Exported function 72 + * @arg1: @arg1 does nothing 73 + * 74 + * Does nothing 75 + * 76 + * return: 77 + * always return 0. 78 + */ 79 + int func2(char *arg1) { return 0; }; 80 + EXPORT_SYMBOL(func2); 81 + 82 + exports: func2 83 + expected: 84 + - kdoc_item: 85 + name: func2 86 + type: function 87 + declaration_start_line: 1 88 + 89 + sections: 90 + Description: | 91 + Does nothing 92 + 93 + Return: | 94 + always return 0. 95 + 96 + sections_start_lines: 97 + Description: 3 98 + Return: 6 99 + 100 + parameterdescs: 101 + arg1: | 102 + @arg1 does nothing 103 + parameterlist: 104 + - arg1 105 + parameterdesc_start_lines: 106 + arg1: 2 107 + parametertypes: 108 + arg1: char *arg1 109 + 110 + other_stuff: 111 + func_macro: false 112 + functiontype: int 113 + purpose: "Exported function" 114 + typedef: false 115 + 116 + rst: | 117 + .. c:function:: int func2 (char *arg1) 118 + 119 + Exported function 120 + 121 + .. container:: kernelindent 122 + 123 + **Parameters** 124 + 125 + ``char *arg1`` 126 + **arg1** does nothing 127 + 128 + **Description** 129 + 130 + Does nothing 131 + 132 + **Return** 133 + 134 + always return 0. 135 + 136 + man: | 137 + .TH "func2" 9 "February 2026" "" "Kernel API Manual" 138 + .SH NAME 139 + func2 \- Exported function 140 + .SH SYNOPSIS 141 + .B "int" func2 142 + .BI "(char *arg1 " ");" 143 + .SH ARGUMENTS 144 + .IP "arg1" 12 145 + \fIarg1\fP does nothing 146 + .SH "DESCRIPTION" 147 + Does nothing 148 + .SH "RETURN" 149 + always return 0. 150 + .SH "SEE ALSO" 151 + .PP 152 + Kernel file \fBfunc2.c\fR 153 + 154 + - name: doc_with_complex_table 155 + description: Test if complex tables are handled 156 + fname: mock.c 157 + source: | 158 + /** 159 + * DOC: Supported input formats and encodings 160 + * 161 + * Depending on the Hardware configuration of the Controller IP, it supports 162 + * a subset of the following input formats and encodings on its internal 163 + * 48bit bus. 164 + * 165 + * +----------------------+----------------------------------+------------------------------+ 166 + * | Format Name | Format Code | Encodings | 167 + * +======================+==================================+==============================+ 168 + * | RGB 4:4:4 8bit | ``MEDIA_BUS_FMT_RGB888_1X24`` | ``V4L2_YCBCR_ENC_DEFAULT`` | 169 + * +----------------------+----------------------------------+------------------------------+ 170 + * | RGB 4:4:4 10bits | ``MEDIA_BUS_FMT_RGB101010_1X30`` | ``V4L2_YCBCR_ENC_DEFAULT`` | 171 + * +----------------------+----------------------------------+------------------------------+ 172 + */ 173 + expected: 174 + - man: | 175 + .TH "Supported input formats and encodings" 9 "March 2026" "" "Kernel API Manual" 176 + .SH "Supported input formats and encodings" 177 + Depending on the Hardware configuration of the Controller IP, it supports 178 + a subset of the following input formats and encodings on its internal 179 + 48bit bus. 180 + .PP 181 + 182 + 183 + .TS 184 + box; 185 + l l l. 186 + \fBFormat Name\fP \fBFormat Code\fP \fBEncodings\fP 187 + _ 188 + RGB 4:4:4 8bit ``MEDIA_BUS_FMT_RGB888_1X24 V4L2_YCBCR_ENC_DEFAULT 189 + RGB 4:4:4 10bits MEDIA_BUS_FMT_RGB101010_1X30 V4L2_YCBCR_ENC_DEFAULT`` 190 + .TE 191 + .SH "SEE ALSO" 192 + .PP 193 + Kernel file \fBmock.c\fR 194 + 195 + rst: |- 196 + .. _Supported input formats and encodings: 197 + **Supported input formats and encodings** 198 + Depending on the Hardware configuration of the Controller IP, it supports 199 + a subset of the following input formats and encodings on its internal 200 + 48bit bus. 201 + +----------------------+----------------------------------+------------------------------+ 202 + | Format Name | Format Code | Encodings | 203 + +======================+==================================+==============================+ 204 + | RGB 4:4:4 8bit | ``MEDIA_BUS_FMT_RGB888_1X24`` | ``V4L2_YCBCR_ENC_DEFAULT`` | 205 + +----------------------+----------------------------------+------------------------------+ 206 + | RGB 4:4:4 10bits | ``MEDIA_BUS_FMT_RGB101010_1X30`` | ``V4L2_YCBCR_ENC_DEFAULT`` | 207 + +----------------------+----------------------------------+------------------------------+ 208 + - name: func_with_ascii_artwork 209 + description: Test if ascii artwork is properly output 210 + fname: mock.c 211 + source: | 212 + /** 213 + * add_cxl_resources() - reflect CXL fixed memory windows in iomem_resource 214 + * @cxl_res: A standalone resource tree where each CXL window is a sibling 215 + * 216 + * Walk each CXL window in @cxl_res and add it to iomem_resource potentially 217 + * expanding its boundaries to ensure that any conflicting resources become 218 + * children. If a window is expanded it may then conflict with a another window 219 + * entry and require the window to be truncated or trimmed. Consider this 220 + * situation:: 221 + * 222 + * |-- "CXL Window 0" --||----- "CXL Window 1" -----| 223 + * |--------------- "System RAM" -------------| 224 + * 225 + * ...where platform firmware has established as System RAM resource across 2 226 + * windows, but has left some portion of window 1 for dynamic CXL region 227 + * provisioning. In this case "Window 0" will span the entirety of the "System 228 + * RAM" span, and "CXL Window 1" is truncated to the remaining tail past the end 229 + * of that "System RAM" resource. 230 + */ 231 + static int add_cxl_resources(struct resource *cxl_res); 232 + expected: 233 + - man: |- 234 + .TH "add_cxl_resources" 9 "March 2026" "" "Kernel API Manual" 235 + .SH NAME 236 + add_cxl_resources \- reflect CXL fixed memory windows in iomem_resource 237 + .SH SYNOPSIS 238 + .B "int" add_cxl_resources 239 + .BI "(struct resource *cxl_res " ");" 240 + .SH ARGUMENTS 241 + .IP "cxl_res" 12 242 + A standalone resource tree where each CXL window is a sibling 243 + .SH "DESCRIPTION" 244 + Walk each CXL window in \fIcxl_res\fP and add it to iomem_resource potentially 245 + expanding its boundaries to ensure that any conflicting resources become 246 + children. If a window is expanded it may then conflict with a another window 247 + entry and require the window to be truncated or trimmed. Consider this 248 + situation: 249 + .nf 250 + 251 + |-- "CXL Window 0" --||----- "CXL Window 1" -----| 252 + |--------------- "System RAM" -------------| 253 + 254 + 255 + .fi 256 + .PP 257 + 258 + \&...where platform firmware has established as System RAM resource across 2 259 + windows, but has left some portion of window 1 for dynamic CXL region 260 + provisioning. In this case "Window 0" will span the entirety of the "System 261 + RAM" span, and "CXL Window 1" is truncated to the remaining tail past the end 262 + of that "System RAM" resource. 263 + .SH "SEE ALSO" 264 + .PP 265 + Kernel file \fBmock.c\fR 266 + rst: | 267 + .. c:function:: int add_cxl_resources (struct resource *cxl_res) 268 + 269 + reflect CXL fixed memory windows in iomem_resource 270 + 271 + .. container:: kernelindent 272 + 273 + **Parameters** 274 + 275 + ``struct resource *cxl_res`` 276 + A standalone resource tree where each CXL window is a sibling 277 + 278 + **Description** 279 + 280 + Walk each CXL window in **cxl_res** and add it to iomem_resource potentially 281 + expanding its boundaries to ensure that any conflicting resources become 282 + children. If a window is expanded it may then conflict with a another window 283 + entry and require the window to be truncated or trimmed. Consider this 284 + situation:: 285 + 286 + |-- "CXL Window 0" --||----- "CXL Window 1" -----| 287 + |--------------- "System RAM" -------------| 288 + 289 + ...where platform firmware has established as System RAM resource across 2 290 + windows, but has left some portion of window 1 for dynamic CXL region 291 + provisioning. In this case "Window 0" will span the entirety of the "System 292 + RAM" span, and "CXL Window 1" is truncated to the remaining tail past the end 293 + of that "System RAM" resource. 294 + 295 + - name: simple_tables 296 + description: Test formatting two simple tables 297 + fname: mock.c 298 + source: | 299 + /** 300 + * bitmap_onto - translate one bitmap relative to another 301 + * @dst: resulting translated bitmap 302 + * @orig: original untranslated bitmap 303 + * @relmap: bitmap relative to which translated 304 + * @bits: number of bits in each of these bitmaps 305 + * 306 + * =============== ============== ================= 307 + * @orig tmp @dst 308 + * 0 0 40 309 + * 1 1 41 310 + * =============== ============== ================= 311 + * 312 + * And: 313 + * 314 + * =============== ============== ================= 315 + * @orig tmp @dst 316 + * =============== ============== ================= 317 + * 9 9 95 318 + * 10 0 40 [#f1]_ 319 + * =============== ============== ================= 320 + */ 321 + void bitmap_onto(unsigned long *dst, const unsigned long *orig, 322 + const unsigned long *relmap, unsigned int bits); 323 + expected: 324 + - man: | 325 + .TH "bitmap_onto" 9 "March 2026" "" "Kernel API Manual" 326 + .SH NAME 327 + bitmap_onto \- translate one bitmap relative to another 328 + .SH SYNOPSIS 329 + .B "void" bitmap_onto 330 + .BI "(unsigned long *dst " "," 331 + .BI "const unsigned long *orig " "," 332 + .BI "const unsigned long *relmap " "," 333 + .BI "unsigned int bits " ");" 334 + .SH ARGUMENTS 335 + .IP "dst" 12 336 + resulting translated bitmap 337 + .IP "orig" 12 338 + original untranslated bitmap 339 + .IP "relmap" 12 340 + bitmap relative to which translated 341 + .IP "bits" 12 342 + number of bits in each of these bitmaps 343 + .SH "DESCRIPTION" 344 + 345 + .TS 346 + box; 347 + l l l. 348 + \fIorig\fP tmp \fIdst\fP 349 + 0 0 40 350 + 1 1 41 351 + .TE 352 + .PP 353 + 354 + And: 355 + .PP 356 + 357 + 358 + .TS 359 + box; 360 + l l l. 361 + \fIorig\fP tmp \fIdst\fP 362 + .TE 363 + 9 9 95 364 + 10 0 40 [#f1]_ 365 + .SH "SEE ALSO" 366 + .PP 367 + Kernel file \fBmock.c\fR 368 + 369 + rst: | 370 + .. c:function:: void bitmap_onto (unsigned long *dst, const unsigned long *orig, const unsigned long *relmap, unsigned int bits) 371 + 372 + translate one bitmap relative to another 373 + 374 + .. container:: kernelindent 375 + 376 + **Parameters** 377 + 378 + ``unsigned long *dst`` 379 + resulting translated bitmap 380 + 381 + ``const unsigned long *orig`` 382 + original untranslated bitmap 383 + 384 + ``const unsigned long *relmap`` 385 + bitmap relative to which translated 386 + 387 + ``unsigned int bits`` 388 + number of bits in each of these bitmaps 389 + 390 + **Description** 391 + 392 + =============== ============== ================= 393 + **orig** tmp **dst** 394 + 0 0 40 395 + 1 1 41 396 + =============== ============== ================= 397 + 398 + And: 399 + 400 + =============== ============== ================= 401 + **orig** tmp **dst** 402 + =============== ============== ================= 403 + 9 9 95 404 + 10 0 40 [#f1]_ 405 + =============== ============== ================= 406 + 407 + # 408 + # Variable tests from Randy Dunlap's testset 409 + # 410 + - name: unsigned_long_var_on_uppercase 411 + description: Test an unsigned long varaible in uppercase 412 + fname: mock-vars.c 413 + source: | 414 + /** 415 + * var ROOT_DEV - system root device 416 + * 417 + * @ROOT_DEV is either the successful root device or the root device 418 + * that failed boot in the boot failure message. 419 + */ 420 + unsigned long ROOT_DEV; 421 + expected: 422 + - man: | 423 + .TH "var ROOT_DEV" 9 "February 2026" "" "Kernel API Manual" 424 + .SH NAME 425 + ROOT_DEV \- system root device 426 + .SH SYNOPSIS 427 + unsigned long ROOT_DEV; 428 + .SH "Description" 429 + \fIROOT_DEV\fP is either the successful root device or the root device 430 + that failed boot in the boot failure message. 431 + .SH "SEE ALSO" 432 + .PP 433 + Kernel file \fBmock-vars.c\fR 434 + rst: | 435 + .. c:macro:: ROOT_DEV 436 + 437 + ``unsigned long ROOT_DEV;`` 438 + 439 + system root device 440 + 441 + **Description** 442 + 443 + **ROOT_DEV** is either the successful root device or the root device 444 + that failed boot in the boot failure message. 445 + - name: enum_var 446 + description: Test an enum var with __read_mostly 447 + fname: mock-vars.c 448 + source: | 449 + /** 450 + * var system_state - system state used during boot or suspend/hibernate/resume 451 + * 452 + * @system_state can be used during boot to determine if it is safe to 453 + * make certain calls to other parts of the kernel. It can also be used 454 + * during suspend/hibernate or resume to determine the order of actions 455 + * that need to be executed. The numerical values of system_state are 456 + * sometimes used in numerical ordering tests, so the relative values 457 + * must not be altered. 458 + */ 459 + enum system_states system_state __read_mostly; 460 + expected: 461 + - man: | 462 + .TH "var system_state" 9 "February 2026" "" "Kernel API Manual" 463 + .SH NAME 464 + system_state \- system state used during boot or suspend/hibernate/resume 465 + .SH SYNOPSIS 466 + enum system_states system_state __read_mostly; 467 + .SH "Description" 468 + \fIsystem_state\fP can be used during boot to determine if it is safe to 469 + make certain calls to other parts of the kernel. It can also be used 470 + during suspend/hibernate or resume to determine the order of actions 471 + that need to be executed. The numerical values of system_state are 472 + sometimes used in numerical ordering tests, so the relative values 473 + must not be altered. 474 + .SH "SEE ALSO" 475 + .PP 476 + Kernel file \fBmock-vars.c\fR 477 + rst: | 478 + .. c:macro:: system_state 479 + 480 + ``enum system_states system_state __read_mostly;`` 481 + 482 + system state used during boot or suspend/hibernate/resume 483 + 484 + **Description** 485 + 486 + **system_state** can be used during boot to determine if it is safe to 487 + make certain calls to other parts of the kernel. It can also be used 488 + during suspend/hibernate or resume to determine the order of actions 489 + that need to be executed. The numerical values of system_state are 490 + sometimes used in numerical ordering tests, so the relative values 491 + must not be altered. 492 + - name: char_pointer_var 493 + description: Test char * var with __ro_after_init 494 + fname: mock-vars.c 495 + source: | 496 + /** 497 + * var saved_command_line - kernel's command line, saved from use at 498 + * any later time in the kernel. 499 + */ 500 + char *saved_command_line __ro_after_init; 501 + expected: 502 + - man: | 503 + .TH "var saved_command_line" 9 "February 2026" "" "Kernel API Manual" 504 + .SH NAME 505 + saved_command_line \- kernel's command line, saved from use at any later time in the kernel. 506 + .SH SYNOPSIS 507 + char *saved_command_line __ro_after_init; 508 + .SH "SEE ALSO" 509 + .PP 510 + Kernel file \fBmock-vars.c\fR 511 + rst: | 512 + .. c:macro:: saved_command_line 513 + 514 + ``char *saved_command_line __ro_after_init;`` 515 + 516 + kernel's command line, saved from use at any later time in the kernel. 517 + - name: unsigned_long_with_default 518 + description: Test an unsigned long var that is set to a default value 519 + fname: mock-vars.c 520 + source: | 521 + /** 522 + * var loop_per_jiffy - calculated loop count needed to consume one jiffy 523 + * of time 524 + */ 525 + unsigned long loops_per_jiffy = (1<<12); 526 + expected: 527 + - man: | 528 + .TH "var loops_per_jiffy" 9 "February 2026" "" "Kernel API Manual" 529 + .SH NAME 530 + loops_per_jiffy \- calculated loop count needed to consume one jiffy of time 531 + .SH SYNOPSIS 532 + unsigned long loops_per_jiffy = (1<<12); 533 + .SH "Initialization" 534 + default: (1<<12) 535 + .SH "SEE ALSO" 536 + .PP 537 + Kernel file \fBmock-vars.c\fR 538 + rst: | 539 + .. c:macro:: loops_per_jiffy 540 + 541 + ``unsigned long loops_per_jiffy = (1<<12);`` 542 + 543 + calculated loop count needed to consume one jiffy of time 544 + 545 + **Initialization** 546 + 547 + default: ``(1<<12)`` 548 + - name: unsigned_long 549 + description: test a simple unsigned long variable. 550 + fname: mock-vars.c 551 + source: | 552 + /** 553 + * var preset_lpj - lpj (loops per jiffy) value set from kernel 554 + * command line using "lpj=VALUE" 555 + * 556 + * See Documentation/admin-guide/kernel-parameters.txt ("lpj=") for details. 557 + */ 558 + unsigned long preset_lpj; 559 + expected: 560 + - man: | 561 + .TH "var preset_lpj" 9 "February 2026" "" "Kernel API Manual" 562 + .SH NAME 563 + preset_lpj \- lpj (loops per jiffy) value set from kernel command line using "lpj=VALUE" 564 + .SH SYNOPSIS 565 + unsigned long preset_lpj; 566 + .SH "Description" 567 + See Documentation/admin-guide/kernel-parameters.txt ("lpj=") for details. 568 + .SH "SEE ALSO" 569 + .PP 570 + Kernel file \fBmock-vars.c\fR 571 + rst: | 572 + .. c:macro:: preset_lpj 573 + 574 + ``unsigned long preset_lpj;`` 575 + 576 + lpj (loops per jiffy) value set from kernel command line using "lpj=VALUE" 577 + 578 + **Description** 579 + 580 + See Documentation/admin-guide/kernel-parameters.txt ("lpj=") for details. 581 + - name: char_array 582 + description: test a char array variable 583 + fname: mock-vars.c 584 + source: | 585 + /** 586 + * var linux_proc_banner - text used from /proc/version file 587 + * 588 + * * first %s is sysname (e.g., "Linux") 589 + * * second %s is release 590 + * * third %s is version 591 + */ 592 + char linux_proc_banner[]; 593 + expected: 594 + - man: | 595 + .TH "var linux_proc_banner" 9 "February 2026" "" "Kernel API Manual" 596 + .SH NAME 597 + linux_proc_banner \- text used from /proc/version file 598 + .SH SYNOPSIS 599 + char linux_proc_banner[]; 600 + .SH "Description" 601 + .IP \[bu] 602 + first s is sysname (e.g., "Linux") 603 + .IP \[bu] 604 + second s is release 605 + .IP \[bu] 606 + third s is version 607 + .SH "SEE ALSO" 608 + .PP 609 + Kernel file \fBmock-vars.c\fR 610 + rst: | 611 + .. c:macro:: linux_proc_banner 612 + 613 + ``char linux_proc_banner[];`` 614 + 615 + text used from /proc/version file 616 + 617 + **Description** 618 + 619 + * first ``s`` is sysname (e.g., "Linux") 620 + * second ``s`` is release 621 + * third ``s`` is version 622 + - name: const_char_array 623 + description: test a const char array variable 624 + fname: mock-vars.c 625 + source: | 626 + /** 627 + * var linux_banner - Linux boot banner, usually printed at boot time 628 + */ 629 + const char linux_banner[]; 630 + expected: 631 + - man: | 632 + .TH "var linux_banner" 9 "February 2026" "" "Kernel API Manual" 633 + .SH NAME 634 + linux_banner \- Linux boot banner, usually printed at boot time 635 + .SH SYNOPSIS 636 + const char linux_banner[]; 637 + .SH "SEE ALSO" 638 + .PP 639 + Kernel file \fBmock-vars.c\fR 640 + rst: | 641 + .. c:macro:: linux_banner 642 + 643 + ``const char linux_banner[];`` 644 + 645 + Linux boot banner, usually printed at boot time 646 + - name: static_atomic64_t_var 647 + description: test a static atomi64_t variable 648 + fname: mock-vars.c 649 + source: | 650 + /** 651 + * var diskseq - unique sequence number for block device instances 652 + * 653 + * Allows userspace to associate uevents to the lifetime of a device 654 + */ 655 + static atomic64_t diskseq; 656 + expected: 657 + - man: | 658 + .TH "var diskseq" 9 "February 2026" "" "Kernel API Manual" 659 + .SH NAME 660 + diskseq \- unique sequence number for block device instances 661 + .SH SYNOPSIS 662 + static atomic64_t diskseq; 663 + .SH "Description" 664 + Allows userspace to associate uevents to the lifetime of a device 665 + .SH "SEE ALSO" 666 + .PP 667 + Kernel file \fBmock-vars.c\fR 668 + rst: | 669 + .. c:macro:: diskseq 670 + 671 + ``static atomic64_t diskseq;`` 672 + 673 + unique sequence number for block device instances 674 + 675 + **Description** 676 + 677 + Allows userspace to associate uevents to the lifetime of a device 678 + - name: unsigned_long_on_init 679 + description: test an unsigned long var at "init" with a different timestamp. 680 + fname: init/mock-vars.c 681 + source: | 682 + /** 683 + * var rtnl_mutex - historical global lock for networking control operations. 684 + * 685 + * @rtnl_mutex is used to serialize rtnetlink requests 686 + * and protect all kernel internal data structures related to networking. 687 + * 688 + * See Documentation/networking/netdevices.rst for details. 689 + * Often known as the rtnl_lock, although rtnl_lock is a kernel function. 690 + */ 691 + unsigned long rtnl_mutex; 692 + expected: 693 + - man: | 694 + .TH "var rtnl_mutex" 9 "February 2026" "init" "Kernel API Manual" 695 + .SH NAME 696 + rtnl_mutex \- historical global lock for networking control operations. 697 + .SH SYNOPSIS 698 + unsigned long rtnl_mutex; 699 + .SH "Description" 700 + \fIrtnl_mutex\fP is used to serialize rtnetlink requests 701 + and protect all kernel internal data structures related to networking. 702 + .PP 703 + 704 + See Documentation/networking/netdevices.rst for details. 705 + Often known as the rtnl_lock, although rtnl_lock is a kernel function. 706 + .SH "SEE ALSO" 707 + .PP 708 + Kernel file \fBinit/mock-vars.c\fR 709 + rst: | 710 + .. c:macro:: rtnl_mutex 711 + 712 + ``unsigned long rtnl_mutex;`` 713 + 714 + historical global lock for networking control operations. 715 + 716 + **Description** 717 + 718 + **rtnl_mutex** is used to serialize rtnetlink requests 719 + and protect all kernel internal data structures related to networking. 720 + 721 + See Documentation/networking/netdevices.rst for details. 722 + Often known as the rtnl_lock, although rtnl_lock is a kernel function. 723 + 724 + 725 + - name: struct_kcov 726 + fname: mock_tests/kdoc-drop-ctx-lock.c 727 + source: | 728 + /** 729 + * struct kcov - kcov descriptor (one per opened debugfs file). 730 + * State transitions of the descriptor: 731 + * 732 + * - initial state after open() 733 + * - then there must be a single ioctl(KCOV_INIT_TRACE) call 734 + * - then, mmap() call (several calls are allowed but not useful) 735 + * - then, ioctl(KCOV_ENABLE, arg), where arg is 736 + * KCOV_TRACE_PC - to trace only the PCs 737 + * or 738 + * KCOV_TRACE_CMP - to trace only the comparison operands 739 + * - then, ioctl(KCOV_DISABLE) to disable the task. 740 + * 741 + * Enabling/disabling ioctls can be repeated (only one task a time allowed). 742 + */ 743 + struct kcov { 744 + /** 745 + * @refcount: Reference counter. We keep one for: 746 + * - opened file descriptor 747 + * - task with enabled coverage (we can't unwire it from another task) 748 + * - each code section for remote coverage collection 749 + */ 750 + refcount_t refcount; 751 + /** 752 + * @lock: The lock protects mode, size, area and t. 753 + */ 754 + spinlock_t lock; 755 + /** 756 + * @mode: the kcov_mode 757 + */ 758 + enum kcov_mode mode __guarded_by(&lock); 759 + /** 760 + * @size: Size of arena (in long's). 761 + */ 762 + unsigned int size __guarded_by(&lock); 763 + /** 764 + * @area: Coverage buffer shared with user space. 765 + */ 766 + void *area __guarded_by(&lock); 767 + /** 768 + * @t: Task for which we collect coverage, or NULL. 769 + */ 770 + struct task_struct *t __guarded_by(&lock); 771 + /** 772 + * @remote: Collecting coverage from remote (background) threads. 773 + */ 774 + bool remote; 775 + /** 776 + * @remote_size: Size of remote area (in long's). 777 + */ 778 + unsigned int remote_size; 779 + /** 780 + * @sequence: Sequence is incremented each time kcov is reenabled, 781 + * used by kcov_remote_stop(), see the comment there. 782 + */ 783 + int sequence; 784 + }; 785 + expected: 786 + - man: | 787 + .TH "struct kcov" 9 "February 2026" "mock_tests" "Kernel API Manual" 788 + .SH NAME 789 + struct kcov \- kcov descriptor (one per opened debugfs file). State transitions of the descriptor: 790 + .SH SYNOPSIS 791 + struct kcov { 792 + .br 793 + .BI " refcount_t refcount;" 794 + .br 795 + .BI " spinlock_t lock;" 796 + .br 797 + .BI " enum kcov_mode mode;" 798 + .br 799 + .BI " unsigned int size;" 800 + .br 801 + .BI " void *area;" 802 + .br 803 + .BI " struct task_struct *t;" 804 + .br 805 + .BI " bool remote;" 806 + .br 807 + .BI " unsigned int remote_size;" 808 + .br 809 + .BI " int sequence;" 810 + .br 811 + .BI " 812 + }; 813 + .br 814 + 815 + .SH Members 816 + .IP "refcount" 12 817 + Reference counter. We keep one for: 818 + .IP \[bu] 819 + opened file descriptor 820 + .IP \[bu] 821 + task with enabled coverage (we can't unwire it from another task) 822 + .IP \[bu] 823 + each code section for remote coverage collection 824 + .IP "lock" 12 825 + The lock protects mode, size, area and t. 826 + .IP "mode" 12 827 + the kcov_mode 828 + .IP "size" 12 829 + Size of arena (in long's). 830 + .IP "area" 12 831 + Coverage buffer shared with user space. 832 + .IP "t" 12 833 + Task for which we collect coverage, or NULL. 834 + .IP "remote" 12 835 + Collecting coverage from remote (background) threads. 836 + .IP "remote_size" 12 837 + Size of remote area (in long's). 838 + .IP "sequence" 12 839 + Sequence is incremented each time kcov is reenabled, 840 + used by \fBkcov_remote_stop\fP, see the comment there. 841 + .SH "Description" 842 + .IP \[bu] 843 + initial state after \fBopen\fP 844 + .IP \[bu] 845 + then there must be a single ioctl(KCOV_INIT_TRACE) call 846 + .IP \[bu] 847 + then, \fBmmap\fP call (several calls are allowed but not useful) 848 + .IP \[bu] 849 + then, ioctl(KCOV_ENABLE, arg), where arg is 850 + KCOV_TRACE_PC - to trace only the PCs 851 + or 852 + KCOV_TRACE_CMP - to trace only the comparison operands 853 + .IP \[bu] 854 + then, ioctl(KCOV_DISABLE) to disable the task. 855 + .PP 856 + 857 + Enabling/disabling ioctls can be repeated (only one task a time allowed). 858 + .SH "SEE ALSO" 859 + .PP 860 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 861 + rst: | 862 + .. c:struct:: kcov 863 + 864 + kcov descriptor (one per opened debugfs file). State transitions of the descriptor: 865 + 866 + .. container:: kernelindent 867 + 868 + **Definition**:: 869 + 870 + struct kcov { 871 + refcount_t refcount; 872 + spinlock_t lock; 873 + enum kcov_mode mode; 874 + unsigned int size; 875 + void *area; 876 + struct task_struct *t; 877 + bool remote; 878 + unsigned int remote_size; 879 + int sequence; 880 + }; 881 + 882 + **Members** 883 + 884 + ``refcount`` 885 + Reference counter. We keep one for: 886 + - opened file descriptor 887 + - task with enabled coverage (we can't unwire it from another task) 888 + - each code section for remote coverage collection 889 + 890 + ``lock`` 891 + The lock protects mode, size, area and t. 892 + 893 + ``mode`` 894 + the kcov_mode 895 + 896 + ``size`` 897 + Size of arena (in long's). 898 + 899 + ``area`` 900 + Coverage buffer shared with user space. 901 + 902 + ``t`` 903 + Task for which we collect coverage, or NULL. 904 + 905 + ``remote`` 906 + Collecting coverage from remote (background) threads. 907 + 908 + ``remote_size`` 909 + Size of remote area (in long's). 910 + 911 + ``sequence`` 912 + Sequence is incremented each time kcov is reenabled, 913 + used by kcov_remote_stop(), see the comment there. 914 + 915 + 916 + **Description** 917 + 918 + - initial state after open() 919 + - then there must be a single ioctl(KCOV_INIT_TRACE) call 920 + - then, mmap() call (several calls are allowed but not useful) 921 + - then, ioctl(KCOV_ENABLE, arg), where arg is 922 + KCOV_TRACE_PC - to trace only the PCs 923 + or 924 + KCOV_TRACE_CMP - to trace only the comparison operands 925 + - then, ioctl(KCOV_DISABLE) to disable the task. 926 + 927 + Enabling/disabling ioctls can be repeated (only one task a time allowed). 928 + 929 + - name: pool_offset 930 + description: mock_tests/kdoc-drop-ctx-lock.c line 83 931 + fname: mock_tests/kdoc-drop-ctx-lock.c 932 + source: | 933 + /** 934 + * var pool_offset - Offset to the unused space in the currently used pool. 935 + * 936 + */ 937 + size_t pool_offset __guarded_by(&pool_lock) = DEPOT_POOL_SIZE; 938 + expected: 939 + - man: | 940 + .TH "var pool_offset" 9 "February 2026" "mock_tests" "Kernel API Manual" 941 + .SH NAME 942 + pool_offset \- Offset to the unused space in the currently used pool. 943 + .SH SYNOPSIS 944 + size_t pool_offset __guarded_by(&pool_lock) = DEPOT_POOL_SIZE; 945 + .SH "Initialization" 946 + default: DEPOT_POOL_SIZE 947 + .SH "SEE ALSO" 948 + .PP 949 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 950 + rst: | 951 + .. c:macro:: pool_offset 952 + 953 + ``size_t pool_offset __guarded_by(&pool_lock) = DEPOT_POOL_SIZE;`` 954 + 955 + Offset to the unused space in the currently used pool. 956 + 957 + **Initialization** 958 + 959 + default: ``DEPOT_POOL_SIZE`` 960 + - name: free_stacks 961 + description: mock_tests/kdoc-drop-ctx-lock.c line 88 962 + fname: mock_tests/kdoc-drop-ctx-lock.c 963 + source: | 964 + /** 965 + * var free_stacks - Freelist of stack records within stack_pools. 966 + * 967 + */ 968 + __guarded_by(&pool_lock) LIST_HEAD(free_stacks); 969 + expected: 970 + - man: | 971 + .TH "var free_stacks" 9 "February 2026" "mock_tests" "Kernel API Manual" 972 + .SH NAME 973 + free_stacks \- Freelist of stack records within stack_pools. 974 + .SH SYNOPSIS 975 + __guarded_by(&pool_lock) LIST_HEAD(free_stacks); 976 + .SH "SEE ALSO" 977 + .PP 978 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 979 + rst: | 980 + .. c:macro:: free_stacks 981 + 982 + ``__guarded_by(&pool_lock) LIST_HEAD(free_stacks);`` 983 + 984 + Freelist of stack records within stack_pools. 985 + - name: stack_pools 986 + description: mock_tests/kdoc-drop-ctx-lock.c line 94 987 + fname: mock_tests/kdoc-drop-ctx-lock.c 988 + source: | 989 + /** 990 + * var stack_pools - Array of memory regions that store stack records. 991 + * 992 + */ 993 + void **stack_pools __pt_guarded_by(&pool_lock); 994 + expected: 995 + - man: | 996 + .TH "var stack_pools" 9 "February 2026" "mock_tests" "Kernel API Manual" 997 + .SH NAME 998 + stack_pools \- Array of memory regions that store stack records. 999 + .SH SYNOPSIS 1000 + void **stack_pools __pt_guarded_by(&pool_lock); 1001 + .SH "SEE ALSO" 1002 + .PP 1003 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1004 + rst: | 1005 + .. c:macro:: stack_pools 1006 + 1007 + ``void **stack_pools __pt_guarded_by(&pool_lock);`` 1008 + 1009 + Array of memory regions that store stack records. 1010 + - name: prepare_report_consumer 1011 + description: mock_tests/kdoc-drop-ctx-lock.c line 103 1012 + fname: mock_tests/kdoc-drop-ctx-lock.c 1013 + source: | 1014 + /** 1015 + * prepare_report_consumer - prepare the report consumer 1016 + * @flags: flags 1017 + * @ai: not that AI 1018 + * @other_info: yes that 1019 + */ 1020 + bool prepare_report_consumer(unsigned long *flags, 1021 + const struct access_info *ai, 1022 + struct other_info *other_info) 1023 + __cond_acquires(true, &report_lock) 1024 + { 1025 + expected: 1026 + - man: | 1027 + .TH "prepare_report_consumer" 9 "February 2026" "mock_tests" "Kernel API Manual" 1028 + .SH NAME 1029 + prepare_report_consumer \- prepare the report consumer 1030 + .SH SYNOPSIS 1031 + .B "bool" prepare_report_consumer 1032 + .BI "(unsigned long *flags " "," 1033 + .BI "const struct access_info *ai " "," 1034 + .BI "struct other_info *other_info " ");" 1035 + .SH ARGUMENTS 1036 + .IP "flags" 12 1037 + flags 1038 + .IP "ai" 12 1039 + not that AI 1040 + .IP "other_info" 12 1041 + yes that 1042 + .SH "SEE ALSO" 1043 + .PP 1044 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1045 + rst: | 1046 + .. c:function:: bool prepare_report_consumer (unsigned long *flags, const struct access_info *ai, struct other_info *other_info) 1047 + 1048 + prepare the report consumer 1049 + 1050 + .. container:: kernelindent 1051 + 1052 + **Parameters** 1053 + 1054 + ``unsigned long *flags`` 1055 + flags 1056 + 1057 + ``const struct access_info *ai`` 1058 + not that AI 1059 + 1060 + ``struct other_info *other_info`` 1061 + yes that 1062 + - name: tcp_sigpool_start 1063 + description: mock_tests/kdoc-drop-ctx-lock.c line 117 1064 + fname: mock_tests/kdoc-drop-ctx-lock.c 1065 + source: | 1066 + /** 1067 + * tcp_sigpool_start - start a tcp message of @id, using @c 1068 + * @id: TCP message ID 1069 + * @c: the &tcp_sigpool to use 1070 + */ 1071 + int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) __cond_acquires(0, RCU_BH) 1072 + { 1073 + expected: 1074 + - man: | 1075 + .TH "tcp_sigpool_start" 9 "February 2026" "mock_tests" "Kernel API Manual" 1076 + .SH NAME 1077 + tcp_sigpool_start \- start a tcp message of @id, using @c 1078 + .SH SYNOPSIS 1079 + .B "int" tcp_sigpool_start 1080 + .BI "(unsigned int id " "," 1081 + .BI "struct tcp_sigpool *c " ");" 1082 + .SH ARGUMENTS 1083 + .IP "id" 12 1084 + TCP message ID 1085 + .IP "c" 12 1086 + the \fItcp_sigpool\fP to use 1087 + .SH "SEE ALSO" 1088 + .PP 1089 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1090 + rst: | 1091 + .. c:function:: int tcp_sigpool_start (unsigned int id, struct tcp_sigpool *c) 1092 + 1093 + start a tcp message of **id**, using **c** 1094 + 1095 + .. container:: kernelindent 1096 + 1097 + **Parameters** 1098 + 1099 + ``unsigned int id`` 1100 + TCP message ID 1101 + 1102 + ``struct tcp_sigpool *c`` 1103 + the :c:type:`tcp_sigpool` to use 1104 + - name: undo_report_consumer 1105 + description: mock_tests/kdoc-drop-ctx-lock.c line 129 1106 + fname: mock_tests/kdoc-drop-ctx-lock.c 1107 + source: | 1108 + /** 1109 + * undo_report_consumer - teardown a report consumer 1110 + * @flags: those flags 1111 + * @ai: not that AI 1112 + * @other_info: yes that 1113 + */ 1114 + bool undo_report_consumer(unsigned long *flags, 1115 + const struct access_info *ai, 1116 + struct other_info *other_info) 1117 + __cond_releases(true, &report_lock) 1118 + { 1119 + expected: 1120 + - man: | 1121 + .TH "undo_report_consumer" 9 "February 2026" "mock_tests" "Kernel API Manual" 1122 + .SH NAME 1123 + undo_report_consumer \- teardown a report consumer 1124 + .SH SYNOPSIS 1125 + .B "bool" undo_report_consumer 1126 + .BI "(unsigned long *flags " "," 1127 + .BI "const struct access_info *ai " "," 1128 + .BI "struct other_info *other_info " ");" 1129 + .SH ARGUMENTS 1130 + .IP "flags" 12 1131 + those flags 1132 + .IP "ai" 12 1133 + not that AI 1134 + .IP "other_info" 12 1135 + yes that 1136 + .SH "SEE ALSO" 1137 + .PP 1138 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1139 + rst: | 1140 + .. c:function:: bool undo_report_consumer (unsigned long *flags, const struct access_info *ai, struct other_info *other_info) 1141 + 1142 + teardown a report consumer 1143 + 1144 + .. container:: kernelindent 1145 + 1146 + **Parameters** 1147 + 1148 + ``unsigned long *flags`` 1149 + those flags 1150 + 1151 + ``const struct access_info *ai`` 1152 + not that AI 1153 + 1154 + ``struct other_info *other_info`` 1155 + yes that 1156 + - name: debugfs_enter_cancellation 1157 + description: mock_tests/kdoc-drop-ctx-lock.c line 143 1158 + fname: mock_tests/kdoc-drop-ctx-lock.c 1159 + source: | 1160 + /** 1161 + * debugfs_enter_cancellation - begin a cancellation operation on @file 1162 + * @file: the target file 1163 + * @cancellation: the operation to execute 1164 + */ 1165 + void debugfs_enter_cancellation(struct file *file, 1166 + struct debugfs_cancellation *cancellation) __acquires(cancellation) 1167 + { } 1168 + expected: 1169 + - man: | 1170 + .TH "debugfs_enter_cancellation" 9 "February 2026" "mock_tests" "Kernel API Manual" 1171 + .SH NAME 1172 + debugfs_enter_cancellation \- begin a cancellation operation on @file 1173 + .SH SYNOPSIS 1174 + .B "void" debugfs_enter_cancellation 1175 + .BI "(struct file *file " "," 1176 + .BI "struct debugfs_cancellation *cancellation " ");" 1177 + .SH ARGUMENTS 1178 + .IP "file" 12 1179 + the target file 1180 + .IP "cancellation" 12 1181 + the operation to execute 1182 + .SH "SEE ALSO" 1183 + .PP 1184 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1185 + rst: | 1186 + .. c:function:: void debugfs_enter_cancellation (struct file *file, struct debugfs_cancellation *cancellation) 1187 + 1188 + begin a cancellation operation on **file** 1189 + 1190 + .. container:: kernelindent 1191 + 1192 + **Parameters** 1193 + 1194 + ``struct file *file`` 1195 + the target file 1196 + 1197 + ``struct debugfs_cancellation *cancellation`` 1198 + the operation to execute 1199 + - name: debugfs_leave_cancellation 1200 + description: mock_tests/kdoc-drop-ctx-lock.c line 152 1201 + fname: mock_tests/kdoc-drop-ctx-lock.c 1202 + source: | 1203 + /** 1204 + * debugfs_leave_cancellation - wrapup the cancellation operation on @file 1205 + * @file: the target file 1206 + * @cancellation: the operation to wrapup 1207 + */ 1208 + void debugfs_leave_cancellation(struct file *file, 1209 + struct debugfs_cancellation *cancellation) __releases(cancellation) 1210 + { } 1211 + expected: 1212 + - man: | 1213 + .TH "debugfs_leave_cancellation" 9 "February 2026" "mock_tests" "Kernel API Manual" 1214 + .SH NAME 1215 + debugfs_leave_cancellation \- wrapup the cancellation operation on @file 1216 + .SH SYNOPSIS 1217 + .B "void" debugfs_leave_cancellation 1218 + .BI "(struct file *file " "," 1219 + .BI "struct debugfs_cancellation *cancellation " ");" 1220 + .SH ARGUMENTS 1221 + .IP "file" 12 1222 + the target file 1223 + .IP "cancellation" 12 1224 + the operation to wrapup 1225 + .SH "SEE ALSO" 1226 + .PP 1227 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1228 + rst: | 1229 + .. c:function:: void debugfs_leave_cancellation (struct file *file, struct debugfs_cancellation *cancellation) 1230 + 1231 + wrapup the cancellation operation on **file** 1232 + 1233 + .. container:: kernelindent 1234 + 1235 + **Parameters** 1236 + 1237 + ``struct file *file`` 1238 + the target file 1239 + 1240 + ``struct debugfs_cancellation *cancellation`` 1241 + the operation to wrapup 1242 + - name: acpi_os_acquire_lock 1243 + description: mock_tests/kdoc-drop-ctx-lock.c line 161 1244 + fname: mock_tests/kdoc-drop-ctx-lock.c 1245 + source: | 1246 + /** 1247 + * acpi_os_acquire_lock - Acquire a spinlock. 1248 + * @lockp: pointer to the spinlock_t. 1249 + */ 1250 + acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp) 1251 + __acquires(lockp) 1252 + { 1253 + expected: 1254 + - man: | 1255 + .TH "acpi_os_acquire_lock" 9 "February 2026" "mock_tests" "Kernel API Manual" 1256 + .SH NAME 1257 + acpi_os_acquire_lock \- Acquire a spinlock. 1258 + .SH SYNOPSIS 1259 + .B "acpi_cpu_flags" acpi_os_acquire_lock 1260 + .BI "(acpi_spinlock lockp " ");" 1261 + .SH ARGUMENTS 1262 + .IP "lockp" 12 1263 + pointer to the spinlock_t. 1264 + .SH "SEE ALSO" 1265 + .PP 1266 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1267 + rst: | 1268 + .. c:function:: acpi_cpu_flags acpi_os_acquire_lock (acpi_spinlock lockp) 1269 + 1270 + Acquire a spinlock. 1271 + 1272 + .. container:: kernelindent 1273 + 1274 + **Parameters** 1275 + 1276 + ``acpi_spinlock lockp`` 1277 + pointer to the spinlock_t. 1278 + - name: acpi_os_release_lock 1279 + description: mock_tests/kdoc-drop-ctx-lock.c line 172 1280 + fname: mock_tests/kdoc-drop-ctx-lock.c 1281 + source: | 1282 + /** 1283 + * acpi_os_release_lock - Release a spinlock. 1284 + * @lockp: pointer to the spinlock_t. 1285 + * @not_used: these flags are not used. 1286 + */ 1287 + void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags not_used) 1288 + __releases(lockp) 1289 + { 1290 + expected: 1291 + - man: | 1292 + .TH "acpi_os_release_lock" 9 "February 2026" "mock_tests" "Kernel API Manual" 1293 + .SH NAME 1294 + acpi_os_release_lock \- Release a spinlock. 1295 + .SH SYNOPSIS 1296 + .B "void" acpi_os_release_lock 1297 + .BI "(acpi_spinlock lockp " "," 1298 + .BI "acpi_cpu_flags not_used " ");" 1299 + .SH ARGUMENTS 1300 + .IP "lockp" 12 1301 + pointer to the spinlock_t. 1302 + .IP "not_used" 12 1303 + these flags are not used. 1304 + .SH "SEE ALSO" 1305 + .PP 1306 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1307 + rst: | 1308 + .. c:function:: void acpi_os_release_lock (acpi_spinlock lockp, acpi_cpu_flags not_used) 1309 + 1310 + Release a spinlock. 1311 + 1312 + .. container:: kernelindent 1313 + 1314 + **Parameters** 1315 + 1316 + ``acpi_spinlock lockp`` 1317 + pointer to the spinlock_t. 1318 + 1319 + ``acpi_cpu_flags not_used`` 1320 + these flags are not used. 1321 + - name: tx 1322 + description: mock_tests/kdoc-drop-ctx-lock.c line 183 1323 + fname: mock_tests/kdoc-drop-ctx-lock.c 1324 + source: | 1325 + /** 1326 + * tx - transmit message ID @id 1327 + * @id: message ID to transmit 1328 + */ 1329 + int tx(int id) __must_hold(&txlock) 1330 + { 1331 + expected: 1332 + - man: | 1333 + .TH "tx" 9 "February 2026" "mock_tests" "Kernel API Manual" 1334 + .SH NAME 1335 + tx \- transmit message ID @id 1336 + .SH SYNOPSIS 1337 + .B "int" tx 1338 + .BI "(int id " ");" 1339 + .SH ARGUMENTS 1340 + .IP "id" 12 1341 + message ID to transmit 1342 + .SH "SEE ALSO" 1343 + .PP 1344 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1345 + rst: | 1346 + .. c:function:: int tx (int id) 1347 + 1348 + transmit message ID **id** 1349 + 1350 + .. container:: kernelindent 1351 + 1352 + **Parameters** 1353 + 1354 + ``int id`` 1355 + message ID to transmit 1356 + - name: contend_for_bm 1357 + description: mock_tests/kdoc-drop-ctx-lock.c line 192 1358 + fname: mock_tests/kdoc-drop-ctx-lock.c 1359 + source: | 1360 + /** 1361 + * contend_for_bm - try to become the bus master 1362 + * @card: the &fw_card (describes the bus) 1363 + */ 1364 + enum bm_contention_outcome contend_for_bm(struct fw_card *card) 1365 + __must_hold(&card->lock) 1366 + { 1367 + expected: 1368 + - man: | 1369 + .TH "contend_for_bm" 9 "February 2026" "mock_tests" "Kernel API Manual" 1370 + .SH NAME 1371 + contend_for_bm \- try to become the bus master 1372 + .SH SYNOPSIS 1373 + .B "enum bm_contention_outcome" contend_for_bm 1374 + .BI "(struct fw_card *card " ");" 1375 + .SH ARGUMENTS 1376 + .IP "card" 12 1377 + the \fIfw_card\fP (describes the bus) 1378 + .SH "SEE ALSO" 1379 + .PP 1380 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1381 + rst: | 1382 + .. c:function:: enum bm_contention_outcome contend_for_bm (struct fw_card *card) 1383 + 1384 + try to become the bus master 1385 + 1386 + .. container:: kernelindent 1387 + 1388 + **Parameters** 1389 + 1390 + ``struct fw_card *card`` 1391 + the :c:type:`fw_card` (describes the bus) 1392 + - name: prepare_report_producer 1393 + description: mock_tests/kdoc-drop-ctx-lock.c line 202 1394 + fname: mock_tests/kdoc-drop-ctx-lock.c 1395 + source: | 1396 + /** 1397 + * prepare_report_producer - prepare the report producer 1398 + * @flags: still flags 1399 + * @ai: some AI 1400 + * @other_info: Populate @other_info; requires that the provided 1401 + * @other_info not in use. 1402 + */ 1403 + void prepare_report_producer(unsigned long *flags, 1404 + const struct access_info *ai, 1405 + struct other_info *other_info) 1406 + __must_not_hold(&report_lock) 1407 + { } 1408 + expected: 1409 + - man: | 1410 + .TH "prepare_report_producer" 9 "February 2026" "mock_tests" "Kernel API Manual" 1411 + .SH NAME 1412 + prepare_report_producer \- prepare the report producer 1413 + .SH SYNOPSIS 1414 + .B "void" prepare_report_producer 1415 + .BI "(unsigned long *flags " "," 1416 + .BI "const struct access_info *ai " "," 1417 + .BI "struct other_info *other_info " ");" 1418 + .SH ARGUMENTS 1419 + .IP "flags" 12 1420 + still flags 1421 + .IP "ai" 12 1422 + some AI 1423 + .IP "other_info" 12 1424 + Populate \fIother_info\fP; requires that the provided 1425 + \fIother_info\fP not in use. 1426 + .SH "SEE ALSO" 1427 + .PP 1428 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1429 + rst: | 1430 + .. c:function:: void prepare_report_producer (unsigned long *flags, const struct access_info *ai, struct other_info *other_info) 1431 + 1432 + prepare the report producer 1433 + 1434 + .. container:: kernelindent 1435 + 1436 + **Parameters** 1437 + 1438 + ``unsigned long *flags`` 1439 + still flags 1440 + 1441 + ``const struct access_info *ai`` 1442 + some AI 1443 + 1444 + ``struct other_info *other_info`` 1445 + Populate **other_info**; requires that the provided 1446 + **other_info** not in use. 1447 + - name: crypto_alg_lookup 1448 + description: mock_tests/kdoc-drop-ctx-lock.c line 215 1449 + fname: mock_tests/kdoc-drop-ctx-lock.c 1450 + source: | 1451 + /** 1452 + * __crypto_alg_lookup() - lookup the algorithm by name/type/mask 1453 + * @name: name to search for 1454 + * @type: type to search for 1455 + * @mask: mask to match 1456 + */ 1457 + struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, 1458 + u32 mask) 1459 + __must_hold_shared(&crypto_alg_sem) 1460 + { 1461 + expected: 1462 + - man: | 1463 + .TH "__crypto_alg_lookup" 9 "February 2026" "mock_tests" "Kernel API Manual" 1464 + .SH NAME 1465 + __crypto_alg_lookup \- lookup the algorithm by name/type/mask 1466 + .SH SYNOPSIS 1467 + .B "struct crypto_alg *" __crypto_alg_lookup 1468 + .BI "(const char *name " "," 1469 + .BI "u32 type " "," 1470 + .BI "u32 mask " ");" 1471 + .SH ARGUMENTS 1472 + .IP "name" 12 1473 + name to search for 1474 + .IP "type" 12 1475 + type to search for 1476 + .IP "mask" 12 1477 + mask to match 1478 + .SH "SEE ALSO" 1479 + .PP 1480 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1481 + rst: | 1482 + .. c:function:: struct crypto_alg * __crypto_alg_lookup (const char *name, u32 type, u32 mask) 1483 + 1484 + lookup the algorithm by name/type/mask 1485 + 1486 + .. container:: kernelindent 1487 + 1488 + **Parameters** 1489 + 1490 + ``const char *name`` 1491 + name to search for 1492 + 1493 + ``u32 type`` 1494 + type to search for 1495 + 1496 + ``u32 mask`` 1497 + mask to match 1498 + - name: down_read_trylock 1499 + description: mock_tests/kdoc-drop-ctx-lock.c line 228 1500 + fname: mock_tests/kdoc-drop-ctx-lock.c 1501 + source: | 1502 + /** 1503 + * down_read_trylock - trylock for reading 1504 + * @sem: the semaphore to try to lock 1505 + * 1506 + * Returns: 1 if successful, 0 if contention 1507 + */ 1508 + extern int down_read_trylock(struct rw_semaphore *sem) __cond_acquires_shared(true, sem); 1509 + expected: 1510 + - man: | 1511 + .TH "down_read_trylock" 9 "February 2026" "mock_tests" "Kernel API Manual" 1512 + .SH NAME 1513 + down_read_trylock \- trylock for reading 1514 + .SH SYNOPSIS 1515 + .B "int" down_read_trylock 1516 + .BI "(struct rw_semaphore *sem " ");" 1517 + .SH ARGUMENTS 1518 + .IP "sem" 12 1519 + the semaphore to try to lock 1520 + .SH "RETURN" 1521 + 1 if successful, 0 if contention 1522 + .SH "SEE ALSO" 1523 + .PP 1524 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1525 + rst: | 1526 + .. c:function:: int down_read_trylock (struct rw_semaphore *sem) 1527 + 1528 + trylock for reading 1529 + 1530 + .. container:: kernelindent 1531 + 1532 + **Parameters** 1533 + 1534 + ``struct rw_semaphore *sem`` 1535 + the semaphore to try to lock 1536 + 1537 + **Return** 1538 + 1539 + 1 if successful, 0 if contention 1540 + - name: tomoyo_read_lock 1541 + description: mock_tests/kdoc-drop-ctx-lock.c line 236 1542 + fname: mock_tests/kdoc-drop-ctx-lock.c 1543 + source: | 1544 + /** 1545 + * tomoyo_read_lock - Take lock for protecting policy. 1546 + * 1547 + * Returns: index number for tomoyo_read_unlock(). 1548 + */ 1549 + int tomoyo_read_lock(void) 1550 + __acquires_shared(&tomoyo_ss) 1551 + { 1552 + expected: 1553 + - man: | 1554 + .TH "tomoyo_read_lock" 9 "February 2026" "mock_tests" "Kernel API Manual" 1555 + .SH NAME 1556 + tomoyo_read_lock \- Take lock for protecting policy. 1557 + .SH SYNOPSIS 1558 + .B "int" tomoyo_read_lock 1559 + .BI "(void " ");" 1560 + .SH ARGUMENTS 1561 + .IP "void" 12 1562 + no arguments 1563 + .SH "RETURN" 1564 + index number for \fBtomoyo_read_unlock\fP. 1565 + .SH "SEE ALSO" 1566 + .PP 1567 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1568 + rst: | 1569 + .. c:function:: int tomoyo_read_lock (void) 1570 + 1571 + Take lock for protecting policy. 1572 + 1573 + .. container:: kernelindent 1574 + 1575 + **Parameters** 1576 + 1577 + ``void`` 1578 + no arguments 1579 + 1580 + **Return** 1581 + 1582 + index number for tomoyo_read_unlock(). 1583 + - name: tomoyo_read_unlock 1584 + description: mock_tests/kdoc-drop-ctx-lock.c line 247 1585 + fname: mock_tests/kdoc-drop-ctx-lock.c 1586 + source: | 1587 + /** 1588 + * tomoyo_read_unlock - Release lock for protecting policy. 1589 + * 1590 + * @idx: Index number returned by tomoyo_read_lock(). 1591 + */ 1592 + void tomoyo_read_unlock(int idx) 1593 + __releases_shared(&tomoyo_ss) 1594 + { } 1595 + expected: 1596 + - man: | 1597 + .TH "tomoyo_read_unlock" 9 "February 2026" "mock_tests" "Kernel API Manual" 1598 + .SH NAME 1599 + tomoyo_read_unlock \- Release lock for protecting policy. 1600 + .SH SYNOPSIS 1601 + .B "void" tomoyo_read_unlock 1602 + .BI "(int idx " ");" 1603 + .SH ARGUMENTS 1604 + .IP "idx" 12 1605 + Index number returned by \fBtomoyo_read_lock\fP. 1606 + .SH "SEE ALSO" 1607 + .PP 1608 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1609 + rst: | 1610 + .. c:function:: void tomoyo_read_unlock (int idx) 1611 + 1612 + Release lock for protecting policy. 1613 + 1614 + .. container:: kernelindent 1615 + 1616 + **Parameters** 1617 + 1618 + ``int idx`` 1619 + Index number returned by tomoyo_read_lock(). 1620 + - name: c_stop 1621 + description: mock_tests/kdoc-drop-ctx-lock.c line 256 1622 + fname: mock_tests/kdoc-drop-ctx-lock.c 1623 + source: | 1624 + /** 1625 + * c_stop - stop the seq_file iteration 1626 + * @m: the &struct seq_file 1627 + * @p: handle 1628 + */ 1629 + void c_stop(struct seq_file *m, void *p) 1630 + __releases_shared(&crypto_alg_sem) 1631 + { } 1632 + expected: 1633 + - man: | 1634 + .TH "c_stop" 9 "February 2026" "mock_tests" "Kernel API Manual" 1635 + .SH NAME 1636 + c_stop \- stop the seq_file iteration 1637 + .SH SYNOPSIS 1638 + .B "void" c_stop 1639 + .BI "(struct seq_file *m " "," 1640 + .BI "void *p " ");" 1641 + .SH ARGUMENTS 1642 + .IP "m" 12 1643 + the \fIstruct seq_file\fP 1644 + .IP "p" 12 1645 + handle 1646 + .SH "SEE ALSO" 1647 + .PP 1648 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1649 + rst: | 1650 + .. c:function:: void c_stop (struct seq_file *m, void *p) 1651 + 1652 + stop the seq_file iteration 1653 + 1654 + .. container:: kernelindent 1655 + 1656 + **Parameters** 1657 + 1658 + ``struct seq_file *m`` 1659 + the :c:type:`struct seq_file <seq_file>` 1660 + 1661 + ``void *p`` 1662 + handle 1663 + - name: spin_lock 1664 + description: mock_tests/kdoc-drop-ctx-lock.c line 265 1665 + fname: mock_tests/kdoc-drop-ctx-lock.c 1666 + source: | 1667 + /** 1668 + * spin_lock - spin until the @lock is acquired 1669 + * @lock: the spinlock 1670 + */ 1671 + void spin_lock(spinlock_t *lock) 1672 + __acquires(lock) __no_context_analysis 1673 + { } 1674 + expected: 1675 + - man: | 1676 + .TH "spin_lock" 9 "February 2026" "mock_tests" "Kernel API Manual" 1677 + .SH NAME 1678 + spin_lock \- spin until the @lock is acquired 1679 + .SH SYNOPSIS 1680 + .B "void" spin_lock 1681 + .BI "(spinlock_t *lock " ");" 1682 + .SH ARGUMENTS 1683 + .IP "lock" 12 1684 + the spinlock 1685 + .SH "SEE ALSO" 1686 + .PP 1687 + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR 1688 + rst: | 1689 + .. c:function:: void spin_lock (spinlock_t *lock) 1690 + 1691 + spin until the **lock** is acquired 1692 + 1693 + .. container:: kernelindent 1694 + 1695 + **Parameters** 1696 + 1697 + ``spinlock_t *lock`` 1698 + the spinlock
+17
tools/unittests/run.py
··· 1 + #!/bin/env python3 2 + import os 3 + import unittest 4 + import sys 5 + 6 + TOOLS_DIR=os.path.join(os.path.dirname(os.path.realpath(__file__)), "..") 7 + sys.path.insert(0, TOOLS_DIR) 8 + 9 + from lib.python.unittest_helper import TestUnits 10 + 11 + if __name__ == "__main__": 12 + loader = unittest.TestLoader() 13 + 14 + suite = loader.discover(start_dir=os.path.join(TOOLS_DIR, "unittests"), 15 + pattern="test*.py") 16 + 17 + TestUnits().run("", suite=suite)
+821
tools/unittests/test_cmatch.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Copyright(c) 2026: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + # 5 + # pylint: disable=C0413,R0904 6 + 7 + 8 + """ 9 + Unit tests for kernel-doc CMatch. 10 + """ 11 + 12 + import os 13 + import re 14 + import sys 15 + import unittest 16 + 17 + 18 + # Import Python modules 19 + 20 + SRC_DIR = os.path.dirname(os.path.realpath(__file__)) 21 + sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) 22 + 23 + from kdoc.c_lex import CMatch 24 + from kdoc.kdoc_re import KernRe 25 + from unittest_helper import run_unittest 26 + 27 + # 28 + # Override unittest.TestCase to better compare diffs ignoring whitespaces 29 + # 30 + class TestCaseDiff(unittest.TestCase): 31 + """ 32 + Disable maximum limit on diffs and add a method to better 33 + handle diffs with whitespace differences. 34 + """ 35 + 36 + @classmethod 37 + def setUpClass(cls): 38 + """Ensure that there won't be limit for diffs""" 39 + cls.maxDiff = None 40 + 41 + 42 + # 43 + # Tests doing with different macros 44 + # 45 + 46 + class TestSearch(TestCaseDiff): 47 + """ 48 + Test search mechanism 49 + """ 50 + 51 + def test_search_acquires_simple(self): 52 + line = "__acquires(ctx) foo();" 53 + result = ", ".join(CMatch("__acquires").search(line)) 54 + self.assertEqual(result, "__acquires(ctx)") 55 + 56 + def test_search_acquires_multiple(self): 57 + line = "__acquires(ctx) __acquires(other) bar();" 58 + result = ", ".join(CMatch("__acquires").search(line)) 59 + self.assertEqual(result, "__acquires(ctx), __acquires(other)") 60 + 61 + def test_search_acquires_nested_paren(self): 62 + line = "__acquires((ctx1, ctx2)) baz();" 63 + result = ", ".join(CMatch("__acquires").search(line)) 64 + self.assertEqual(result, "__acquires((ctx1, ctx2))") 65 + 66 + def test_search_must_hold(self): 67 + line = "__must_hold(&lock) do_something();" 68 + result = ", ".join(CMatch("__must_hold").search(line)) 69 + self.assertEqual(result, "__must_hold(&lock)") 70 + 71 + def test_search_must_hold_shared(self): 72 + line = "__must_hold_shared(RCU) other();" 73 + result = ", ".join(CMatch("__must_hold_shared").search(line)) 74 + self.assertEqual(result, "__must_hold_shared(RCU)") 75 + 76 + def test_search_no_false_positive(self): 77 + line = "call__acquires(foo); // should stay intact" 78 + result = ", ".join(CMatch(r"__acquires").search(line)) 79 + self.assertEqual(result, "") 80 + 81 + def test_search_no_macro_remains(self): 82 + line = "do_something_else();" 83 + result = ", ".join(CMatch("__acquires").search(line)) 84 + self.assertEqual(result, "") 85 + 86 + def test_search_no_function(self): 87 + line = "something" 88 + result = ", ".join(CMatch(line).search(line)) 89 + self.assertEqual(result, "") 90 + 91 + # 92 + # Override unittest.TestCase to better compare diffs ignoring whitespaces 93 + # 94 + class TestCaseDiff(unittest.TestCase): 95 + """ 96 + Disable maximum limit on diffs and add a method to better 97 + handle diffs with whitespace differences. 98 + """ 99 + 100 + @classmethod 101 + def setUpClass(cls): 102 + """Ensure that there won't be limit for diffs""" 103 + cls.maxDiff = None 104 + 105 + def assertLogicallyEqual(self, a, b): 106 + """ 107 + Compare two results ignoring multiple whitespace differences. 108 + 109 + This is useful to check more complex matches picked from examples. 110 + On a plus side, we also don't need to use dedent. 111 + Please notice that line breaks still need to match. We might 112 + remove it at the regex, but this way, checking the diff is easier. 113 + """ 114 + a = re.sub(r"[\t ]+", " ", a.strip()) 115 + b = re.sub(r"[\t ]+", " ", b.strip()) 116 + 117 + a = re.sub(r"\s+\n", "\n", a) 118 + b = re.sub(r"\s+\n", "\n", b) 119 + 120 + a = re.sub(" ;", ";", a) 121 + b = re.sub(" ;", ";", b) 122 + 123 + self.assertEqual(a, b) 124 + 125 + # 126 + # Tests doing with different macros 127 + # 128 + 129 + class TestSubMultipleMacros(TestCaseDiff): 130 + """ 131 + Tests doing with different macros. 132 + 133 + Here, we won't use assertLogicallyEqual. Instead, we'll check if each 134 + of the expected patterns are present at the answer. 135 + """ 136 + 137 + def test_acquires_simple(self): 138 + """Simple replacement test with __acquires""" 139 + line = "__acquires(ctx) foo();" 140 + result = CMatch(r"__acquires").sub("REPLACED", line) 141 + 142 + self.assertEqual("REPLACED foo();", result) 143 + 144 + def test_acquires_multiple(self): 145 + """Multiple __acquires""" 146 + line = "__acquires(ctx) __acquires(other) bar();" 147 + result = CMatch(r"__acquires").sub("REPLACED", line) 148 + 149 + self.assertEqual("REPLACED REPLACED bar();", result) 150 + 151 + def test_acquires_nested_paren(self): 152 + """__acquires with nested pattern""" 153 + line = "__acquires((ctx1, ctx2)) baz();" 154 + result = CMatch(r"__acquires").sub("REPLACED", line) 155 + 156 + self.assertEqual("REPLACED baz();", result) 157 + 158 + def test_must_hold(self): 159 + """__must_hold with a pointer""" 160 + line = "__must_hold(&lock) do_something();" 161 + result = CMatch(r"__must_hold").sub("REPLACED", line) 162 + 163 + self.assertNotIn("__must_hold(", result) 164 + self.assertIn("do_something();", result) 165 + 166 + def test_must_hold_shared(self): 167 + """__must_hold with an upercase defined value""" 168 + line = "__must_hold_shared(RCU) other();" 169 + result = CMatch(r"__must_hold_shared").sub("REPLACED", line) 170 + 171 + self.assertNotIn("__must_hold_shared(", result) 172 + self.assertIn("other();", result) 173 + 174 + def test_no_false_positive(self): 175 + """ 176 + Ensure that unrelated text containing similar patterns is preserved 177 + """ 178 + line = "call__acquires(foo); // should stay intact" 179 + result = CMatch(r"\b__acquires").sub("REPLACED", line) 180 + 181 + self.assertLogicallyEqual(result, "call__acquires(foo);") 182 + 183 + def test_mixed_macros(self): 184 + """Add a mix of macros""" 185 + line = "__acquires(ctx) __releases(ctx) __must_hold(&lock) foo();" 186 + 187 + result = CMatch(r"__acquires").sub("REPLACED", line) 188 + result = CMatch(r"__releases").sub("REPLACED", result) 189 + result = CMatch(r"__must_hold").sub("REPLACED", result) 190 + 191 + self.assertNotIn("__acquires(", result) 192 + self.assertNotIn("__releases(", result) 193 + self.assertNotIn("__must_hold(", result) 194 + 195 + self.assertIn("foo();", result) 196 + 197 + def test_no_macro_remains(self): 198 + """Ensures that unmatched macros are untouched""" 199 + line = "do_something_else();" 200 + result = CMatch(r"__acquires").sub("REPLACED", line) 201 + 202 + self.assertEqual(result, line) 203 + 204 + def test_no_function(self): 205 + """Ensures that no functions will remain untouched""" 206 + line = "something" 207 + result = CMatch(line).sub("REPLACED", line) 208 + 209 + self.assertEqual(result, line) 210 + 211 + # 212 + # Check if the diff is logically equivalent. To simplify, the tests here 213 + # use a single macro name for all replacements. 214 + # 215 + 216 + class TestSubSimple(TestCaseDiff): 217 + """ 218 + Test argument replacements. 219 + 220 + Here, the function name can be anything. So, we picked __attribute__(), 221 + to mimic a macro found at the Kernel, but none of the replacements her 222 + has any relationship with the Kernel usage. 223 + """ 224 + 225 + MACRO = "__attribute__" 226 + 227 + @classmethod 228 + def setUpClass(cls): 229 + """Define a CMatch to be used for all tests""" 230 + cls.matcher = CMatch(cls.MACRO) 231 + 232 + def test_sub_with_capture(self): 233 + """Test all arguments replacement with a single arg""" 234 + line = f"{self.MACRO}(&ctx)\nfoo();" 235 + 236 + result = self.matcher.sub(r"ACQUIRED(\0)", line) 237 + 238 + self.assertLogicallyEqual("ACQUIRED(&ctx)\nfoo();", result) 239 + 240 + def test_sub_zero_placeholder(self): 241 + """Test all arguments replacement with a multiple args""" 242 + line = f"{self.MACRO}(arg1, arg2)\nbar();" 243 + 244 + result = self.matcher.sub(r"REPLACED(\0)", line) 245 + 246 + self.assertLogicallyEqual("REPLACED(arg1, arg2)\nbar();", result) 247 + 248 + def test_sub_single_placeholder(self): 249 + """Single replacement rule for \1""" 250 + line = f"{self.MACRO}(ctx, boo)\nfoo();" 251 + result = self.matcher.sub(r"ACQUIRED(\1)", line) 252 + 253 + self.assertLogicallyEqual("ACQUIRED(ctx)\nfoo();", result) 254 + 255 + def test_sub_multiple_placeholders(self): 256 + """Replacement rule for both \1 and \2""" 257 + line = f"{self.MACRO}(arg1, arg2)\nbar();" 258 + result = self.matcher.sub(r"REPLACE(\1, \2)", line) 259 + 260 + self.assertLogicallyEqual("REPLACE(arg1, arg2)\nbar();", result) 261 + 262 + def test_sub_mixed_placeholders(self): 263 + """Replacement rule for \0, \1 and additional text""" 264 + line = f"{self.MACRO}(foo, bar)\nbaz();" 265 + result = self.matcher.sub(r"ALL(\0) FIRST(\1)", line) 266 + 267 + self.assertLogicallyEqual("ALL(foo, bar) FIRST(foo)\nbaz();", result) 268 + 269 + def test_sub_no_placeholder(self): 270 + """Replacement without placeholders""" 271 + line = f"{self.MACRO}(arg)\nfoo();" 272 + result = self.matcher.sub(r"NO_BACKREFS()", line) 273 + 274 + self.assertLogicallyEqual("NO_BACKREFS()\nfoo();", result) 275 + 276 + def test_sub_count_parameter(self): 277 + """Verify that the algorithm stops after the requested count""" 278 + line = f"{self.MACRO}(a1) x();\n{self.MACRO}(a2) y();" 279 + result = self.matcher.sub(r"ONLY_FIRST(\1) ", line, count=1) 280 + 281 + self.assertLogicallyEqual(f"ONLY_FIRST(a1) x();\n{self.MACRO}(a2) y();", 282 + result) 283 + 284 + def test_strip_multiple_acquires(self): 285 + """Check if spaces between removed delimiters will be dropped""" 286 + line = f"int {self.MACRO}(1) {self.MACRO}(2 ) {self.MACRO}(3) foo;" 287 + result = self.matcher.sub("", line) 288 + 289 + self.assertLogicallyEqual(result, "int foo;") 290 + 291 + def test_rise_early_greedy(self): 292 + line = f"{self.MACRO}(a, b, c, d);" 293 + sub = r"\1, \2+, \3" 294 + 295 + with self.assertRaises(ValueError): 296 + result = self.matcher.sub(sub, line) 297 + 298 + def test_rise_multiple_greedy(self): 299 + line = f"{self.MACRO}(a, b, c, d);" 300 + sub = r"\1, \2+, \3+" 301 + 302 + with self.assertRaises(ValueError): 303 + result = self.matcher.sub(sub, line) 304 + 305 + # 306 + # Test replacements with slashrefs 307 + # 308 + 309 + 310 + class TestSubWithLocalXforms(TestCaseDiff): 311 + """ 312 + Test diferent usecase patterns found at the Kernel. 313 + 314 + Here, replacements using both CMatch and KernRe can be tested, 315 + as it will import the actual replacement rules used by kernel-doc. 316 + """ 317 + 318 + struct_xforms = [ 319 + (CMatch("__attribute__"), ' '), 320 + (CMatch('__aligned'), ' '), 321 + (CMatch('__counted_by'), ' '), 322 + (CMatch('__counted_by_(le|be)'), ' '), 323 + (CMatch('__guarded_by'), ' '), 324 + (CMatch('__pt_guarded_by'), ' '), 325 + 326 + (CMatch('__cacheline_group_(begin|end)'), ''), 327 + 328 + (CMatch('struct_group'), r'\2'), 329 + (CMatch('struct_group_attr'), r'\3'), 330 + (CMatch('struct_group_tagged'), r'struct \1 { \3+ } \2;'), 331 + (CMatch('__struct_group'), r'\4'), 332 + 333 + (CMatch('__ETHTOOL_DECLARE_LINK_MODE_MASK'), r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'), 334 + (CMatch('DECLARE_PHY_INTERFACE_MASK',), r'DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)'), 335 + (CMatch('DECLARE_BITMAP'), r'unsigned long \1[BITS_TO_LONGS(\2)]'), 336 + 337 + (CMatch('DECLARE_HASHTABLE'), r'unsigned long \1[1 << ((\2) - 1)]'), 338 + (CMatch('DECLARE_KFIFO'), r'\2 *\1'), 339 + (CMatch('DECLARE_KFIFO_PTR'), r'\2 *\1'), 340 + (CMatch('(?:__)?DECLARE_FLEX_ARRAY'), r'\1 \2[]'), 341 + (CMatch('DEFINE_DMA_UNMAP_ADDR'), r'dma_addr_t \1'), 342 + (CMatch('DEFINE_DMA_UNMAP_LEN'), r'__u32 \1'), 343 + (CMatch('VIRTIO_DECLARE_FEATURES'), r'union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }'), 344 + ] 345 + 346 + function_xforms = [ 347 + (CMatch('__printf'), ""), 348 + (CMatch('__(?:re)?alloc_size'), ""), 349 + (CMatch("__diagnose_as"), ""), 350 + (CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"), 351 + 352 + (CMatch("__cond_acquires"), ""), 353 + (CMatch("__cond_releases"), ""), 354 + (CMatch("__acquires"), ""), 355 + (CMatch("__releases"), ""), 356 + (CMatch("__must_hold"), ""), 357 + (CMatch("__must_not_hold"), ""), 358 + (CMatch("__must_hold_shared"), ""), 359 + (CMatch("__cond_acquires_shared"), ""), 360 + (CMatch("__acquires_shared"), ""), 361 + (CMatch("__releases_shared"), ""), 362 + (CMatch("__attribute__"), ""), 363 + ] 364 + 365 + var_xforms = [ 366 + (CMatch('__guarded_by'), ""), 367 + (CMatch('__pt_guarded_by'), ""), 368 + (CMatch("LIST_HEAD"), r"struct list_head \1"), 369 + ] 370 + 371 + #: Transforms main dictionary used at apply_transforms(). 372 + xforms = { 373 + "struct": struct_xforms, 374 + "func": function_xforms, 375 + "var": var_xforms, 376 + } 377 + 378 + @classmethod 379 + def apply_transforms(cls, xform_type, text): 380 + """ 381 + Mimic the behavior of kdoc_parser.apply_transforms() method. 382 + 383 + For each element of STRUCT_XFORMS, apply apply_transforms. 384 + 385 + There are two parameters: 386 + 387 + - ``xform_type`` 388 + Can be ``func``, ``struct`` or ``var``; 389 + - ``text`` 390 + The text where the sub patterns from CTransforms will be applied. 391 + """ 392 + for search, subst in cls.xforms.get(xform_type): 393 + text = search.sub(subst, text) 394 + 395 + return text.strip() 396 + 397 + cls.matcher = CMatch(r"struct_group[\w\_]*") 398 + 399 + def test_struct_group(self): 400 + """ 401 + Test struct_group using a pattern from 402 + drivers/net/ethernet/asix/ax88796c_main.h. 403 + """ 404 + line = """ 405 + struct tx_pkt_info { 406 + struct_group(tx_overhead, 407 + struct tx_sop_header sop; 408 + struct tx_segment_header seg; 409 + ); 410 + struct tx_eop_header eop; 411 + u16 pkt_len; 412 + u16 seq_num; 413 + }; 414 + """ 415 + expected = """ 416 + struct tx_pkt_info { 417 + struct tx_sop_header sop; 418 + struct tx_segment_header seg; 419 + struct tx_eop_header eop; 420 + u16 pkt_len; 421 + u16 seq_num; 422 + }; 423 + """ 424 + 425 + result = self.apply_transforms("struct", line) 426 + self.assertLogicallyEqual(result, expected) 427 + 428 + def test_struct_group_attr(self): 429 + """ 430 + Test two struct_group_attr using patterns from fs/smb/client/cifspdu.h. 431 + """ 432 + line = """ 433 + typedef struct smb_com_open_rsp { 434 + struct smb_hdr hdr; /* wct = 34 BB */ 435 + __u8 AndXCommand; 436 + __u8 AndXReserved; 437 + __le16 AndXOffset; 438 + __u8 OplockLevel; 439 + __u16 Fid; 440 + __le32 CreateAction; 441 + struct_group_attr(common_attributes,, 442 + __le64 CreationTime; 443 + __le64 LastAccessTime; 444 + __le64 LastWriteTime; 445 + __le64 ChangeTime; 446 + __le32 FileAttributes; 447 + ); 448 + __le64 AllocationSize; 449 + __le64 EndOfFile; 450 + __le16 FileType; 451 + __le16 DeviceState; 452 + __u8 DirectoryFlag; 453 + __u16 ByteCount; /* bct = 0 */ 454 + } OPEN_RSP; 455 + typedef struct { 456 + struct_group_attr(common_attributes,, 457 + __le64 CreationTime; 458 + __le64 LastAccessTime; 459 + __le64 LastWriteTime; 460 + __le64 ChangeTime; 461 + __le32 Attributes; 462 + ); 463 + __u32 Pad1; 464 + __le64 AllocationSize; 465 + __le64 EndOfFile; 466 + __le32 NumberOfLinks; 467 + __u8 DeletePending; 468 + __u8 Directory; 469 + __u16 Pad2; 470 + __le32 EASize; 471 + __le32 FileNameLength; 472 + union { 473 + char __pad; 474 + DECLARE_FLEX_ARRAY(char, FileName); 475 + }; 476 + } FILE_ALL_INFO; /* level 0x107 QPathInfo */ 477 + """ 478 + expected = """ 479 + typedef struct smb_com_open_rsp { 480 + struct smb_hdr hdr; 481 + __u8 AndXCommand; 482 + __u8 AndXReserved; 483 + __le16 AndXOffset; 484 + __u8 OplockLevel; 485 + __u16 Fid; 486 + __le32 CreateAction; 487 + __le64 CreationTime; 488 + __le64 LastAccessTime; 489 + __le64 LastWriteTime; 490 + __le64 ChangeTime; 491 + __le32 FileAttributes; 492 + __le64 AllocationSize; 493 + __le64 EndOfFile; 494 + __le16 FileType; 495 + __le16 DeviceState; 496 + __u8 DirectoryFlag; 497 + __u16 ByteCount; 498 + } OPEN_RSP; 499 + typedef struct { 500 + __le64 CreationTime; 501 + __le64 LastAccessTime; 502 + __le64 LastWriteTime; 503 + __le64 ChangeTime; 504 + __le32 Attributes; 505 + __u32 Pad1; 506 + __le64 AllocationSize; 507 + __le64 EndOfFile; 508 + __le32 NumberOfLinks; 509 + __u8 DeletePending; 510 + __u8 Directory; 511 + __u16 Pad2; 512 + __le32 EASize; 513 + __le32 FileNameLength; 514 + union { 515 + char __pad; 516 + char FileName[]; 517 + }; 518 + } FILE_ALL_INFO; 519 + """ 520 + 521 + result = self.apply_transforms("struct", line) 522 + self.assertLogicallyEqual(result, expected) 523 + 524 + def test_raw_struct_group(self): 525 + """ 526 + Test a __struct_group pattern from include/uapi/cxl/features.h. 527 + """ 528 + line = """ 529 + struct cxl_mbox_get_sup_feats_out { 530 + __struct_group(cxl_mbox_get_sup_feats_out_hdr, hdr, /* empty */, 531 + __le16 num_entries; 532 + __le16 supported_feats; 533 + __u8 reserved[4]; 534 + ); 535 + struct cxl_feat_entry ents[] __counted_by_le(num_entries); 536 + } __attribute__ ((__packed__)); 537 + """ 538 + expected = """ 539 + struct cxl_mbox_get_sup_feats_out { 540 + __le16 num_entries; 541 + __le16 supported_feats; 542 + __u8 reserved[4]; 543 + struct cxl_feat_entry ents[]; 544 + }; 545 + """ 546 + 547 + result = self.apply_transforms("struct", line) 548 + self.assertLogicallyEqual(result, expected) 549 + 550 + def test_raw_struct_group_tagged(self): 551 + r""" 552 + Test cxl_regs with struct_group_tagged patterns from drivers/cxl/cxl.h. 553 + 554 + NOTE: 555 + 556 + This one has actually a violation from what kernel-doc would 557 + expect: Kernel-doc regex expects only 3 members, but this is 558 + actually defined as:: 559 + 560 + #define struct_group_tagged(TAG, NAME, MEMBERS...) 561 + 562 + The replace expression there is:: 563 + 564 + struct \1 { \3 } \2; 565 + 566 + but it should be really something like:: 567 + 568 + struct \1 { \3 \4 \5 \6 \7 \8 ... } \2; 569 + 570 + a later fix would be needed to address it. 571 + 572 + """ 573 + line = """ 574 + struct cxl_regs { 575 + struct_group_tagged(cxl_component_regs, component, 576 + void __iomem *hdm_decoder; 577 + void __iomem *ras; 578 + ); 579 + 580 + 581 + /* This is actually a violation: too much commas */ 582 + struct_group_tagged(cxl_device_regs, device_regs, 583 + void __iomem *status, *mbox, *memdev; 584 + ); 585 + 586 + struct_group_tagged(cxl_pmu_regs, pmu_regs, 587 + void __iomem *pmu; 588 + ); 589 + 590 + struct_group_tagged(cxl_rch_regs, rch_regs, 591 + void __iomem *dport_aer; 592 + ); 593 + 594 + struct_group_tagged(cxl_rcd_regs, rcd_regs, 595 + void __iomem *rcd_pcie_cap; 596 + ); 597 + }; 598 + """ 599 + expected = """ 600 + struct cxl_regs { 601 + struct cxl_component_regs { 602 + void __iomem *hdm_decoder; 603 + void __iomem *ras; 604 + } component; 605 + 606 + struct cxl_device_regs { 607 + void __iomem *status, *mbox, *memdev; 608 + } device_regs; 609 + 610 + struct cxl_pmu_regs { 611 + void __iomem *pmu; 612 + } pmu_regs; 613 + 614 + struct cxl_rch_regs { 615 + void __iomem *dport_aer; 616 + } rch_regs; 617 + 618 + struct cxl_rcd_regs { 619 + void __iomem *rcd_pcie_cap; 620 + } rcd_regs; 621 + }; 622 + """ 623 + 624 + result = self.apply_transforms("struct", line) 625 + self.assertLogicallyEqual(result, expected) 626 + 627 + def test_struct_group_tagged_with_private(self): 628 + """ 629 + Replace struct_group_tagged with private, using the same regex 630 + for the replacement as what happens in xforms_lists.py. 631 + 632 + As the private removal happens outside NestedGroup class, we manually 633 + dropped the remaining part of the struct, to simulate what happens 634 + at kdoc_parser. 635 + 636 + Taken from include/net/page_pool/types.h 637 + """ 638 + line = """ 639 + struct page_pool_params { 640 + struct_group_tagged(page_pool_params_slow, slow, 641 + struct net_device *netdev; 642 + unsigned int queue_idx; 643 + unsigned int flags; 644 + /* private: only under "slow" struct */ 645 + unsigned int ignored; 646 + ); 647 + /* Struct below shall not be ignored */ 648 + struct_group_tagged(page_pool_params_fast, fast, 649 + unsigned int order; 650 + unsigned int pool_size; 651 + int nid; 652 + struct device *dev; 653 + struct napi_struct *napi; 654 + enum dma_data_direction dma_dir; 655 + unsigned int max_len; 656 + unsigned int offset; 657 + ); 658 + }; 659 + """ 660 + expected = """ 661 + struct page_pool_params { 662 + struct page_pool_params_slow { 663 + struct net_device *netdev; 664 + unsigned int queue_idx; 665 + unsigned int flags; 666 + } slow; 667 + struct page_pool_params_fast { 668 + unsigned int order; 669 + unsigned int pool_size; 670 + int nid; 671 + struct device *dev; 672 + struct napi_struct *napi; 673 + enum dma_data_direction dma_dir; 674 + unsigned int max_len; 675 + unsigned int offset; 676 + } fast; 677 + }; 678 + """ 679 + 680 + result = self.apply_transforms("struct", line) 681 + self.assertLogicallyEqual(result, expected) 682 + 683 + def test_struct_kcov(self): 684 + """ 685 + """ 686 + line = """ 687 + struct kcov { 688 + refcount_t refcount; 689 + spinlock_t lock; 690 + enum kcov_mode mode __guarded_by(&lock); 691 + unsigned int size __guarded_by(&lock); 692 + void *area __guarded_by(&lock); 693 + struct task_struct *t __guarded_by(&lock); 694 + bool remote; 695 + unsigned int remote_size; 696 + int sequence; 697 + }; 698 + """ 699 + expected = """ 700 + """ 701 + 702 + result = self.apply_transforms("struct", line) 703 + self.assertLogicallyEqual(result, expected) 704 + 705 + 706 + def test_struct_kcov(self): 707 + """ 708 + Test a struct from kernel/kcov.c. 709 + """ 710 + line = """ 711 + struct kcov { 712 + refcount_t refcount; 713 + spinlock_t lock; 714 + enum kcov_mode mode __guarded_by(&lock); 715 + unsigned int size __guarded_by(&lock); 716 + void *area __guarded_by(&lock); 717 + struct task_struct *t __guarded_by(&lock); 718 + bool remote; 719 + unsigned int remote_size; 720 + int sequence; 721 + }; 722 + """ 723 + expected = """ 724 + struct kcov { 725 + refcount_t refcount; 726 + spinlock_t lock; 727 + enum kcov_mode mode; 728 + unsigned int size; 729 + void *area; 730 + struct task_struct *t; 731 + bool remote; 732 + unsigned int remote_size; 733 + int sequence; 734 + }; 735 + """ 736 + 737 + result = self.apply_transforms("struct", line) 738 + self.assertLogicallyEqual(result, expected) 739 + 740 + def test_vars_stackdepot(self): 741 + """ 742 + Test guarded_by on vars from lib/stackdepot.c. 743 + """ 744 + line = """ 745 + size_t pool_offset __guarded_by(&pool_lock) = DEPOT_POOL_SIZE; 746 + __guarded_by(&pool_lock) LIST_HEAD(free_stacks); 747 + void **stack_pools __pt_guarded_by(&pool_lock); 748 + """ 749 + expected = """ 750 + size_t pool_offset = DEPOT_POOL_SIZE; 751 + struct list_head free_stacks; 752 + void **stack_pools; 753 + """ 754 + 755 + result = self.apply_transforms("var", line) 756 + self.assertLogicallyEqual(result, expected) 757 + 758 + def test_functions_with_acquires_and_releases(self): 759 + """ 760 + Test guarded_by on vars from lib/stackdepot.c. 761 + """ 762 + line = """ 763 + bool prepare_report_consumer(unsigned long *flags, 764 + const struct access_info *ai, 765 + struct other_info *other_info) \ 766 + __cond_acquires(true, &report_lock); 767 + 768 + int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) \ 769 + __cond_acquires(0, RCU_BH); 770 + 771 + bool undo_report_consumer(unsigned long *flags, 772 + const struct access_info *ai, 773 + struct other_info *other_info) \ 774 + __cond_releases(true, &report_lock); 775 + 776 + void debugfs_enter_cancellation(struct file *file, 777 + struct debugfs_cancellation *c) \ 778 + __acquires(cancellation); 779 + 780 + void debugfs_leave_cancellation(struct file *file, 781 + struct debugfs_cancellation *c) \ 782 + __releases(cancellation); 783 + 784 + acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp) \ 785 + __acquires(lockp); 786 + 787 + void acpi_os_release_lock(acpi_spinlock lockp, 788 + acpi_cpu_flags not_used) \ 789 + __releases(lockp) 790 + """ 791 + expected = """ 792 + bool prepare_report_consumer(unsigned long *flags, 793 + const struct access_info *ai, 794 + struct other_info *other_info); 795 + 796 + int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c); 797 + 798 + bool undo_report_consumer(unsigned long *flags, 799 + const struct access_info *ai, 800 + struct other_info *other_info); 801 + 802 + void debugfs_enter_cancellation(struct file *file, 803 + struct debugfs_cancellation *c); 804 + 805 + void debugfs_leave_cancellation(struct file *file, 806 + struct debugfs_cancellation *c); 807 + 808 + acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp); 809 + 810 + void acpi_os_release_lock(acpi_spinlock lockp, 811 + acpi_cpu_flags not_used) 812 + """ 813 + 814 + result = self.apply_transforms("func", line) 815 + self.assertLogicallyEqual(result, expected) 816 + 817 + # 818 + # Run all tests 819 + # 820 + if __name__ == "__main__": 821 + run_unittest(__file__)
+560
tools/unittests/test_kdoc_parser.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Copyright(c) 2026: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + # 5 + # pylint: disable=C0200,C0413,W0102,R0914 6 + 7 + """ 8 + Unit tests for kernel-doc parser. 9 + """ 10 + 11 + import logging 12 + import os 13 + import re 14 + import shlex 15 + import sys 16 + import unittest 17 + 18 + from textwrap import dedent 19 + from unittest.mock import patch, MagicMock, mock_open 20 + 21 + import yaml 22 + 23 + SRC_DIR = os.path.dirname(os.path.realpath(__file__)) 24 + sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) 25 + 26 + from kdoc.kdoc_files import KdocConfig 27 + from kdoc.kdoc_item import KdocItem 28 + from kdoc.kdoc_parser import KernelDoc 29 + from kdoc.kdoc_output import RestFormat, ManFormat 30 + 31 + from kdoc.xforms_lists import CTransforms 32 + 33 + from unittest_helper import TestUnits 34 + 35 + 36 + # 37 + # Test file 38 + # 39 + TEST_FILE = os.path.join(SRC_DIR, "kdoc-test.yaml") 40 + 41 + env = { 42 + "yaml_file": TEST_FILE 43 + } 44 + 45 + # 46 + # Ancillary logic to clean whitespaces 47 + # 48 + #: Regex to help cleaning whitespaces 49 + RE_WHITESPC = re.compile(r"[ \t]++") 50 + RE_BEGINSPC = re.compile(r"^\s+", re.MULTILINE) 51 + RE_ENDSPC = re.compile(r"\s+$", re.MULTILINE) 52 + 53 + def clean_whitespc(val, relax_whitespace=False): 54 + """ 55 + Cleanup whitespaces to avoid false positives. 56 + 57 + By default, strip only bein/end whitespaces, but, when relax_whitespace 58 + is true, also replace multiple whitespaces in the middle. 59 + """ 60 + 61 + if isinstance(val, str): 62 + val = val.strip() 63 + if relax_whitespace: 64 + val = RE_WHITESPC.sub(" ", val) 65 + val = RE_BEGINSPC.sub("", val) 66 + val = RE_ENDSPC.sub("", val) 67 + elif isinstance(val, list): 68 + val = [clean_whitespc(item, relax_whitespace) for item in val] 69 + elif isinstance(val, dict): 70 + val = {k: clean_whitespc(v, relax_whitespace) for k, v in val.items()} 71 + return val 72 + 73 + # 74 + # Helper classes to help mocking with logger and config 75 + # 76 + class MockLogging(logging.Handler): 77 + """ 78 + Simple class to store everything on a list 79 + """ 80 + 81 + def __init__(self, level=logging.NOTSET): 82 + super().__init__(level) 83 + self.messages = [] 84 + self.formatter = logging.Formatter() 85 + 86 + def emit(self, record: logging.LogRecord) -> None: 87 + """ 88 + Append a formatted record to self.messages. 89 + """ 90 + try: 91 + # The `format` method uses the handler's formatter. 92 + message = self.format(record) 93 + self.messages.append(message) 94 + except Exception: 95 + self.handleError(record) 96 + 97 + class MockKdocConfig(KdocConfig): 98 + def __init__(self, *args, **kwargs): 99 + super().__init__(*args, **kwargs) 100 + 101 + self.log = logging.getLogger(__file__) 102 + self.handler = MockLogging() 103 + self.log.addHandler(self.handler) 104 + 105 + def warning(self, msg): 106 + """Ancillary routine to output a warning and increment error count.""" 107 + 108 + self.log.warning(msg) 109 + 110 + # 111 + # Helper class to generate KdocItem and validate its contents 112 + # 113 + # TODO: check self.config.handler.messages content 114 + # 115 + class GenerateKdocItem(unittest.TestCase): 116 + """ 117 + Base class to run KernelDoc parser class 118 + """ 119 + 120 + DEFAULT = vars(KdocItem("", "", "", 0)) 121 + 122 + config = MockKdocConfig() 123 + xforms = CTransforms() 124 + 125 + def setUp(self): 126 + self.maxDiff = None 127 + 128 + def run_test(self, source, __expected_list, exports={}, fname="test.c", 129 + relax_whitespace=False): 130 + """ 131 + Stores expected values and patch the test to use source as 132 + a "file" input. 133 + """ 134 + debug_level = int(os.getenv("VERBOSE", "0")) 135 + source = dedent(source) 136 + 137 + # Ensure that default values will be there 138 + expected_list = [] 139 + for e in __expected_list: 140 + if not isinstance(e, dict): 141 + e = vars(e) 142 + 143 + new_e = self.DEFAULT.copy() 144 + new_e["fname"] = fname 145 + for key, value in e.items(): 146 + new_e[key] = value 147 + 148 + expected_list.append(new_e) 149 + 150 + patcher = patch('builtins.open', 151 + new_callable=mock_open, read_data=source) 152 + 153 + kernel_doc = KernelDoc(self.config, fname, self.xforms) 154 + 155 + with patcher: 156 + export_table, entries = kernel_doc.parse_kdoc() 157 + 158 + self.assertEqual(export_table, exports) 159 + self.assertEqual(len(entries), len(expected_list)) 160 + 161 + for i in range(0, len(entries)): 162 + 163 + entry = entries[i] 164 + expected = expected_list[i] 165 + self.assertNotEqual(expected, None) 166 + self.assertNotEqual(expected, {}) 167 + self.assertIsInstance(entry, KdocItem) 168 + 169 + d = vars(entry) 170 + 171 + other_stuff = d.get("other_stuff", {}) 172 + if "source" in other_stuff: 173 + del other_stuff["source"] 174 + 175 + for key, value in expected.items(): 176 + if key == "other_stuff": 177 + if "source" in value: 178 + del value["source"] 179 + 180 + result = clean_whitespc(d[key], relax_whitespace) 181 + value = clean_whitespc(value, relax_whitespace) 182 + 183 + if debug_level > 1: 184 + sys.stderr.write(f"{key}: assert('{result}' == '{value}')\n") 185 + 186 + self.assertEqual(result, value, msg=f"at {key}") 187 + 188 + # 189 + # Ancillary function that replicates kdoc_files way to generate output 190 + # 191 + def cleanup_timestamp(text): 192 + lines = text.split("\n") 193 + 194 + for i, line in enumerate(lines): 195 + if not line.startswith('.TH'): 196 + continue 197 + 198 + parts = shlex.split(line) 199 + if len(parts) > 3: 200 + parts[3] = "" 201 + 202 + lines[i] = " ".join(parts) 203 + 204 + 205 + return "\n".join(lines) 206 + 207 + def gen_output(fname, out_style, symbols, expected, 208 + config=None, relax_whitespace=False): 209 + """ 210 + Use the output class to return an output content from KdocItem symbols. 211 + """ 212 + 213 + if not config: 214 + config = MockKdocConfig() 215 + 216 + out_style.set_config(config) 217 + 218 + msg = out_style.output_symbols(fname, symbols) 219 + 220 + result = clean_whitespc(msg, relax_whitespace) 221 + result = cleanup_timestamp(result) 222 + 223 + expected = clean_whitespc(expected, relax_whitespace) 224 + expected = cleanup_timestamp(expected) 225 + 226 + return result, expected 227 + 228 + # 229 + # Classes to be used by dynamic test generation from YAML 230 + # 231 + class CToKdocItem(GenerateKdocItem): 232 + def setUp(self): 233 + self.maxDiff = None 234 + 235 + def run_parser_test(self, source, symbols, exports, fname): 236 + if isinstance(symbols, dict): 237 + symbols = [symbols] 238 + 239 + if isinstance(exports, str): 240 + exports=set([exports]) 241 + elif isinstance(exports, list): 242 + exports=set(exports) 243 + 244 + self.run_test(source, symbols, exports=exports, 245 + fname=fname, relax_whitespace=True) 246 + 247 + class KdocItemToMan(unittest.TestCase): 248 + out_style = ManFormat() 249 + 250 + def setUp(self): 251 + self.maxDiff = None 252 + 253 + def run_out_test(self, fname, symbols, expected): 254 + """ 255 + Generate output using out_style, 256 + """ 257 + result, expected = gen_output(fname, self.out_style, 258 + symbols, expected) 259 + 260 + self.assertEqual(result, expected) 261 + 262 + class KdocItemToRest(unittest.TestCase): 263 + out_style = RestFormat() 264 + 265 + def setUp(self): 266 + self.maxDiff = None 267 + 268 + def run_out_test(self, fname, symbols, expected): 269 + """ 270 + Generate output using out_style, 271 + """ 272 + result, expected = gen_output(fname, self.out_style, symbols, 273 + expected, relax_whitespace=True) 274 + 275 + self.assertEqual(result, expected) 276 + 277 + 278 + class CToMan(unittest.TestCase): 279 + out_style = ManFormat() 280 + config = MockKdocConfig() 281 + xforms = CTransforms() 282 + 283 + def setUp(self): 284 + self.maxDiff = None 285 + 286 + def run_out_test(self, fname, source, expected): 287 + """ 288 + Generate output using out_style, 289 + """ 290 + patcher = patch('builtins.open', 291 + new_callable=mock_open, read_data=source) 292 + 293 + kernel_doc = KernelDoc(self.config, fname, self.xforms) 294 + 295 + with patcher: 296 + export_table, entries = kernel_doc.parse_kdoc() 297 + 298 + result, expected = gen_output(fname, self.out_style, 299 + entries, expected, config=self.config) 300 + 301 + self.assertEqual(result, expected) 302 + 303 + 304 + class CToRest(unittest.TestCase): 305 + out_style = RestFormat() 306 + config = MockKdocConfig() 307 + xforms = CTransforms() 308 + 309 + def setUp(self): 310 + self.maxDiff = None 311 + 312 + def run_out_test(self, fname, source, expected): 313 + """ 314 + Generate output using out_style, 315 + """ 316 + patcher = patch('builtins.open', 317 + new_callable=mock_open, read_data=source) 318 + 319 + kernel_doc = KernelDoc(self.config, fname, self.xforms) 320 + 321 + with patcher: 322 + export_table, entries = kernel_doc.parse_kdoc() 323 + 324 + result, expected = gen_output(fname, self.out_style, entries, 325 + expected, relax_whitespace=True, 326 + config=self.config) 327 + 328 + self.assertEqual(result, expected) 329 + 330 + 331 + # 332 + # Selftest class 333 + # 334 + class TestSelfValidate(GenerateKdocItem): 335 + """ 336 + Tests to check if logic inside GenerateKdocItem.run_test() is working. 337 + """ 338 + 339 + SOURCE = """ 340 + /** 341 + * function3: Exported function 342 + * @arg1: @arg1 does nothing 343 + * 344 + * Does nothing 345 + * 346 + * return: 347 + * always return 0. 348 + */ 349 + int function3(char *arg1) { return 0; }; 350 + EXPORT_SYMBOL(function3); 351 + """ 352 + 353 + EXPECTED = [{ 354 + 'name': 'function3', 355 + 'type': 'function', 356 + 'declaration_start_line': 2, 357 + 358 + 'sections_start_lines': { 359 + 'Description': 4, 360 + 'Return': 7, 361 + }, 362 + 'sections': { 363 + 'Description': 'Does nothing\n\n', 364 + 'Return': '\nalways return 0.\n' 365 + }, 366 + 367 + 'sections_start_lines': { 368 + 'Description': 4, 369 + 'Return': 7, 370 + }, 371 + 372 + 'parameterdescs': {'arg1': '@arg1 does nothing\n'}, 373 + 'parameterlist': ['arg1'], 374 + 'parameterdesc_start_lines': {'arg1': 3}, 375 + 'parametertypes': {'arg1': 'char *arg1'}, 376 + 377 + 'other_stuff': { 378 + 'func_macro': False, 379 + 'functiontype': 'int', 380 + 'purpose': 'Exported function', 381 + 'typedef': False 382 + }, 383 + }] 384 + 385 + EXPORTS = {"function3"} 386 + 387 + def test_parse_pass(self): 388 + """ 389 + Test if export_symbol is properly handled. 390 + """ 391 + self.run_test(self.SOURCE, self.EXPECTED, self.EXPORTS) 392 + 393 + @unittest.expectedFailure 394 + def test_no_exports(self): 395 + """ 396 + Test if export_symbol is properly handled. 397 + """ 398 + self.run_test(self.SOURCE, [], {}) 399 + 400 + @unittest.expectedFailure 401 + def test_with_empty_expected(self): 402 + """ 403 + Test if export_symbol is properly handled. 404 + """ 405 + self.run_test(self.SOURCE, [], self.EXPORTS) 406 + 407 + @unittest.expectedFailure 408 + def test_with_unfilled_expected(self): 409 + """ 410 + Test if export_symbol is properly handled. 411 + """ 412 + self.run_test(self.SOURCE, [{}], self.EXPORTS) 413 + 414 + @unittest.expectedFailure 415 + def test_with_default_expected(self): 416 + """ 417 + Test if export_symbol is properly handled. 418 + """ 419 + self.run_test(self.SOURCE, [self.DEFAULT.copy()], self.EXPORTS) 420 + 421 + # 422 + # Class and logic to create dynamic tests from YAML 423 + # 424 + 425 + class KernelDocDynamicTests(): 426 + """ 427 + Dynamically create a set of tests from a YAML file. 428 + """ 429 + 430 + @classmethod 431 + def create_parser_test(cls, name, fname, source, symbols, exports): 432 + """ 433 + Return a function that will be attached to the test class. 434 + """ 435 + def test_method(self): 436 + """Lambda-like function to run tests with provided vars""" 437 + self.run_parser_test(source, symbols, exports, fname) 438 + 439 + test_method.__name__ = f"test_gen_{name}" 440 + 441 + setattr(CToKdocItem, test_method.__name__, test_method) 442 + 443 + @classmethod 444 + def create_out_test(cls, name, fname, symbols, out_type, data): 445 + """ 446 + Return a function that will be attached to the test class. 447 + """ 448 + def test_method(self): 449 + """Lambda-like function to run tests with provided vars""" 450 + self.run_out_test(fname, symbols, data) 451 + 452 + test_method.__name__ = f"test_{out_type}_{name}" 453 + 454 + if out_type == "man": 455 + setattr(KdocItemToMan, test_method.__name__, test_method) 456 + else: 457 + setattr(KdocItemToRest, test_method.__name__, test_method) 458 + 459 + @classmethod 460 + def create_src2out_test(cls, name, fname, source, out_type, data): 461 + """ 462 + Return a function that will be attached to the test class. 463 + """ 464 + def test_method(self): 465 + """Lambda-like function to run tests with provided vars""" 466 + self.run_out_test(fname, source, data) 467 + 468 + test_method.__name__ = f"test_{out_type}_{name}" 469 + 470 + if out_type == "man": 471 + setattr(CToMan, test_method.__name__, test_method) 472 + else: 473 + setattr(CToRest, test_method.__name__, test_method) 474 + 475 + @classmethod 476 + def create_tests(cls): 477 + """ 478 + Iterate over all scenarios and add a method to the class for each. 479 + 480 + The logic in this function assumes a valid test that are compliant 481 + with kdoc-test-schema.yaml. There is an unit test to check that. 482 + As such, it picks mandatory values directly, and uses get() for the 483 + optional ones. 484 + """ 485 + 486 + test_file = os.environ.get("yaml_file", TEST_FILE) 487 + 488 + with open(test_file, encoding="utf-8") as fp: 489 + testset = yaml.safe_load(fp) 490 + 491 + tests = testset["tests"] 492 + 493 + for idx, test in enumerate(tests): 494 + name = test["name"] 495 + fname = test["fname"] 496 + source = test["source"] 497 + expected_list = test["expected"] 498 + 499 + exports = test.get("exports", []) 500 + 501 + # 502 + # The logic below allows setting up to 5 types of test: 503 + # 1. from source to kdoc_item: test KernelDoc class; 504 + # 2. from kdoc_item to man: test ManOutput class; 505 + # 3. from kdoc_item to rst: test RestOutput class; 506 + # 4. from source to man without checking expected KdocItem; 507 + # 5. from source to rst without checking expected KdocItem. 508 + # 509 + for expected in expected_list: 510 + kdoc_item = expected.get("kdoc_item") 511 + man = expected.get("man", []) 512 + rst = expected.get("rst", []) 513 + 514 + if kdoc_item: 515 + if isinstance(kdoc_item, dict): 516 + kdoc_item = [kdoc_item] 517 + 518 + symbols = [] 519 + 520 + for arg in kdoc_item: 521 + arg["fname"] = fname 522 + arg["start_line"] = 1 523 + 524 + symbols.append(KdocItem.from_dict(arg)) 525 + 526 + if source: 527 + cls.create_parser_test(name, fname, source, 528 + symbols, exports) 529 + 530 + if man: 531 + cls.create_out_test(name, fname, symbols, "man", man) 532 + 533 + if rst: 534 + cls.create_out_test(name, fname, symbols, "rst", rst) 535 + 536 + elif source: 537 + if man: 538 + cls.create_src2out_test(name, fname, source, "man", man) 539 + 540 + if rst: 541 + cls.create_src2out_test(name, fname, source, "rst", rst) 542 + 543 + KernelDocDynamicTests.create_tests() 544 + 545 + # 546 + # Run all tests 547 + # 548 + if __name__ == "__main__": 549 + runner = TestUnits() 550 + parser = runner.parse_args() 551 + parser.add_argument("-y", "--yaml-file", "--yaml", 552 + help='Name of the yaml file to load') 553 + 554 + args = parser.parse_args() 555 + 556 + if args.yaml_file: 557 + env["yaml_file"] = os.path.expanduser(args.yaml_file) 558 + 559 + # Run tests with customized arguments 560 + runner.run(__file__, parser=parser, args=args, env=env)
+94
tools/unittests/test_kdoc_test_schema.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + """ 4 + Unit‑test driver for kernel‑doc YAML tests. 5 + 6 + Two kinds of tests are defined: 7 + 8 + * **Schema‑validation tests** – if ``jsonschema`` is available, the 9 + YAML files in this directory are validated against the JSON‑Schema 10 + described in ``kdoc-test-schema.yaml``. When the library is not 11 + present, a warning is emitted and the validation step is simply 12 + skipped – the dynamic kernel‑doc tests still run. 13 + 14 + * **Kernel‑doc tests** – dynamically generate one test method per 15 + scenario in ``kdoc-test.yaml``. Each method simply forwards 16 + the data to ``self.run_test`` – you only need to implement that 17 + helper in your own code. 18 + 19 + File names are kept as module‑level constants so that the 20 + implementation stays completely independent of ``pathlib``. 21 + """ 22 + 23 + import os 24 + import sys 25 + import warnings 26 + import yaml 27 + import unittest 28 + from typing import Any, Dict, List 29 + 30 + SRC_DIR = os.path.dirname(os.path.realpath(__file__)) 31 + sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) 32 + 33 + from unittest_helper import run_unittest 34 + 35 + 36 + # 37 + # Files to read 38 + # 39 + BASE = os.path.realpath(os.path.dirname(__file__)) 40 + 41 + SCHEMA_FILE = os.path.join(BASE, "kdoc-test-schema.yaml") 42 + TEST_FILE = os.path.join(BASE, "kdoc-test.yaml") 43 + 44 + # 45 + # Schema‑validation test 46 + # 47 + class TestYAMLSchemaValidation(unittest.TestCase): 48 + """ 49 + Checks if TEST_FILE matches SCHEMA_FILE. 50 + """ 51 + 52 + @classmethod 53 + def setUpClass(cls): 54 + """ 55 + Import jsonschema if available. 56 + """ 57 + 58 + try: 59 + from jsonschema import Draft7Validator 60 + except ImportError: 61 + print("Warning: jsonschema package not available. Skipping schema validation") 62 + cls.validator = None 63 + return 64 + 65 + with open(SCHEMA_FILE, encoding="utf-8") as fp: 66 + cls.schema = yaml.safe_load(fp) 67 + 68 + cls.validator = Draft7Validator(cls.schema) 69 + 70 + def test_kdoc_test_yaml_followsschema(self): 71 + """ 72 + Run jsonschema validation if the validator is available. 73 + If not, emit a warning and return without failing. 74 + """ 75 + if self.validator is None: 76 + return 77 + 78 + with open(TEST_FILE, encoding="utf-8") as fp: 79 + data = yaml.safe_load(fp) 80 + 81 + errors = self.validator.iter_errors(data) 82 + 83 + msgs = [] 84 + for error in errors: 85 + msgs.append(error.message) 86 + 87 + if msgs: 88 + self.fail("Schema validation failed:\n\t" + "\n\t".join(msgs)) 89 + 90 + # -------------------------------------------------------------------- 91 + # Entry point 92 + # -------------------------------------------------------------------- 93 + if __name__ == "__main__": 94 + run_unittest(__file__)
+469
tools/unittests/test_tokenizer.py
··· 1 + #!/usr/bin/env python3 2 + 3 + """ 4 + Unit tests for struct/union member extractor class. 5 + """ 6 + 7 + 8 + import os 9 + import re 10 + import unittest 11 + import sys 12 + 13 + from unittest.mock import MagicMock 14 + 15 + SRC_DIR = os.path.dirname(os.path.realpath(__file__)) 16 + sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) 17 + 18 + from kdoc.c_lex import CToken, CTokenizer 19 + from unittest_helper import run_unittest 20 + 21 + # 22 + # List of tests. 23 + # 24 + # The code will dynamically generate one test for each key on this dictionary. 25 + # 26 + def tokens_to_list(tokens): 27 + tuples = [] 28 + 29 + for tok in tokens: 30 + if tok.kind == CToken.SPACE: 31 + continue 32 + 33 + tuples += [(tok.kind, tok.value, tok.level)] 34 + 35 + return tuples 36 + 37 + 38 + def make_tokenizer_test(name, data): 39 + """ 40 + Create a test named ``name`` using parameters given by ``data`` dict. 41 + """ 42 + 43 + def test(self): 44 + """In-lined lambda-like function to run the test""" 45 + 46 + # 47 + # Check if logger is working 48 + # 49 + if "log_msg" in data: 50 + with self.assertLogs() as cm: 51 + tokenizer = CTokenizer(data["source"]) 52 + 53 + msg_found = False 54 + for result in cm.output: 55 + if data["log_msg"] in result: 56 + msg_found = True 57 + 58 + self.assertTrue(msg_found, f"Missing log {data['log_msg']}") 59 + 60 + return 61 + 62 + # 63 + # Check if tokenizer is producing expected results 64 + # 65 + tokens = CTokenizer(data["source"]).tokens 66 + 67 + result = tokens_to_list(tokens) 68 + expected = tokens_to_list(data["expected"]) 69 + 70 + self.assertEqual(result, expected, msg=f"{name}") 71 + 72 + return test 73 + 74 + #: Tokenizer tests. 75 + TESTS_TOKENIZER = { 76 + "__run__": make_tokenizer_test, 77 + 78 + "basic_tokens": { 79 + "source": """ 80 + int a; // comment 81 + float b = 1.23; 82 + """, 83 + "expected": [ 84 + CToken(CToken.NAME, "int"), 85 + CToken(CToken.NAME, "a"), 86 + CToken(CToken.ENDSTMT, ";"), 87 + CToken(CToken.COMMENT, "// comment"), 88 + CToken(CToken.NAME, "float"), 89 + CToken(CToken.NAME, "b"), 90 + CToken(CToken.OP, "="), 91 + CToken(CToken.NUMBER, "1.23"), 92 + CToken(CToken.ENDSTMT, ";"), 93 + ], 94 + }, 95 + 96 + "depth_counters": { 97 + "source": """ 98 + struct X { 99 + int arr[10]; 100 + func(a[0], (b + c)); 101 + } 102 + """, 103 + "expected": [ 104 + CToken(CToken.STRUCT, "struct"), 105 + CToken(CToken.NAME, "X"), 106 + CToken(CToken.BEGIN, "{", brace_level=1), 107 + 108 + CToken(CToken.NAME, "int", brace_level=1), 109 + CToken(CToken.NAME, "arr", brace_level=1), 110 + CToken(CToken.BEGIN, "[", brace_level=1, bracket_level=1), 111 + CToken(CToken.NUMBER, "10", brace_level=1, bracket_level=1), 112 + CToken(CToken.END, "]", brace_level=1), 113 + CToken(CToken.ENDSTMT, ";", brace_level=1), 114 + CToken(CToken.NAME, "func", brace_level=1), 115 + CToken(CToken.BEGIN, "(", brace_level=1, paren_level=1), 116 + CToken(CToken.NAME, "a", brace_level=1, paren_level=1), 117 + CToken(CToken.BEGIN, "[", brace_level=1, paren_level=1, bracket_level=1), 118 + CToken(CToken.NUMBER, "0", brace_level=1, paren_level=1, bracket_level=1), 119 + CToken(CToken.END, "]", brace_level=1, paren_level=1), 120 + CToken(CToken.PUNC, ",", brace_level=1, paren_level=1), 121 + CToken(CToken.BEGIN, "(", brace_level=1, paren_level=2), 122 + CToken(CToken.NAME, "b", brace_level=1, paren_level=2), 123 + CToken(CToken.OP, "+", brace_level=1, paren_level=2), 124 + CToken(CToken.NAME, "c", brace_level=1, paren_level=2), 125 + CToken(CToken.END, ")", brace_level=1, paren_level=1), 126 + CToken(CToken.END, ")", brace_level=1), 127 + CToken(CToken.ENDSTMT, ";", brace_level=1), 128 + CToken(CToken.END, "}"), 129 + ], 130 + }, 131 + 132 + "mismatch_error": { 133 + "source": "int a$ = 5;", # $ is illegal 134 + "log_msg": "Unexpected token", 135 + }, 136 + } 137 + 138 + def make_private_test(name, data): 139 + """ 140 + Create a test named ``name`` using parameters given by ``data`` dict. 141 + """ 142 + 143 + def test(self): 144 + """In-lined lambda-like function to run the test""" 145 + tokens = CTokenizer(data["source"]) 146 + result = str(tokens) 147 + 148 + # 149 + # Avoid whitespace false positives 150 + # 151 + result = re.sub(r"\s++", " ", result).strip() 152 + expected = re.sub(r"\s++", " ", data["trimmed"]).strip() 153 + 154 + msg = f"failed when parsing this source:\n{data['source']}" 155 + self.assertEqual(result, expected, msg=msg) 156 + 157 + return test 158 + 159 + #: Tests to check if CTokenizer is handling properly public/private comments. 160 + TESTS_PRIVATE = { 161 + # 162 + # Simplest case: no private. Ensure that trimming won't affect struct 163 + # 164 + "__run__": make_private_test, 165 + "no private": { 166 + "source": """ 167 + struct foo { 168 + int a; 169 + int b; 170 + int c; 171 + }; 172 + """, 173 + "trimmed": """ 174 + struct foo { 175 + int a; 176 + int b; 177 + int c; 178 + }; 179 + """, 180 + }, 181 + 182 + # 183 + # Play "by the books" by always having a public in place 184 + # 185 + 186 + "balanced_private": { 187 + "source": """ 188 + struct foo { 189 + int a; 190 + /* private: */ 191 + int b; 192 + /* public: */ 193 + int c; 194 + }; 195 + """, 196 + "trimmed": """ 197 + struct foo { 198 + int a; 199 + int c; 200 + }; 201 + """, 202 + }, 203 + 204 + "balanced_non_greddy_private": { 205 + "source": """ 206 + struct foo { 207 + int a; 208 + /* private: */ 209 + int b; 210 + /* public: */ 211 + int c; 212 + /* private: */ 213 + int d; 214 + /* public: */ 215 + int e; 216 + 217 + }; 218 + """, 219 + "trimmed": """ 220 + struct foo { 221 + int a; 222 + int c; 223 + int e; 224 + }; 225 + """, 226 + }, 227 + 228 + "balanced_inner_private": { 229 + "source": """ 230 + struct foo { 231 + struct { 232 + int a; 233 + /* private: ignore below */ 234 + int b; 235 + /* public: but this should not be ignored */ 236 + }; 237 + int b; 238 + }; 239 + """, 240 + "trimmed": """ 241 + struct foo { 242 + struct { 243 + int a; 244 + }; 245 + int b; 246 + }; 247 + """, 248 + }, 249 + 250 + # 251 + # Test what happens if there's no public after private place 252 + # 253 + 254 + "unbalanced_private": { 255 + "source": """ 256 + struct foo { 257 + int a; 258 + /* private: */ 259 + int b; 260 + int c; 261 + }; 262 + """, 263 + "trimmed": """ 264 + struct foo { 265 + int a; 266 + }; 267 + """, 268 + }, 269 + 270 + "unbalanced_inner_private": { 271 + "source": """ 272 + struct foo { 273 + struct { 274 + int a; 275 + /* private: ignore below */ 276 + int b; 277 + /* but this should not be ignored */ 278 + }; 279 + int b; 280 + }; 281 + """, 282 + "trimmed": """ 283 + struct foo { 284 + struct { 285 + int a; 286 + }; 287 + int b; 288 + }; 289 + """, 290 + }, 291 + 292 + "unbalanced_struct_group_tagged_with_private": { 293 + "source": """ 294 + struct page_pool_params { 295 + struct_group_tagged(page_pool_params_fast, fast, 296 + unsigned int order; 297 + unsigned int pool_size; 298 + int nid; 299 + struct device *dev; 300 + struct napi_struct *napi; 301 + enum dma_data_direction dma_dir; 302 + unsigned int max_len; 303 + unsigned int offset; 304 + }; 305 + struct_group_tagged(page_pool_params_slow, slow, 306 + struct net_device *netdev; 307 + unsigned int queue_idx; 308 + unsigned int flags; 309 + /* private: used by test code only */ 310 + void (*init_callback)(netmem_ref netmem, void *arg); 311 + void *init_arg; 312 + }; 313 + }; 314 + """, 315 + "trimmed": """ 316 + struct page_pool_params { 317 + struct_group_tagged(page_pool_params_fast, fast, 318 + unsigned int order; 319 + unsigned int pool_size; 320 + int nid; 321 + struct device *dev; 322 + struct napi_struct *napi; 323 + enum dma_data_direction dma_dir; 324 + unsigned int max_len; 325 + unsigned int offset; 326 + }; 327 + struct_group_tagged(page_pool_params_slow, slow, 328 + struct net_device *netdev; 329 + unsigned int queue_idx; 330 + unsigned int flags; 331 + }; 332 + }; 333 + """, 334 + }, 335 + 336 + "unbalanced_two_struct_group_tagged_first_with_private": { 337 + "source": """ 338 + struct page_pool_params { 339 + struct_group_tagged(page_pool_params_slow, slow, 340 + struct net_device *netdev; 341 + unsigned int queue_idx; 342 + unsigned int flags; 343 + /* private: used by test code only */ 344 + void (*init_callback)(netmem_ref netmem, void *arg); 345 + void *init_arg; 346 + }; 347 + struct_group_tagged(page_pool_params_fast, fast, 348 + unsigned int order; 349 + unsigned int pool_size; 350 + int nid; 351 + struct device *dev; 352 + struct napi_struct *napi; 353 + enum dma_data_direction dma_dir; 354 + unsigned int max_len; 355 + unsigned int offset; 356 + }; 357 + }; 358 + """, 359 + "trimmed": """ 360 + struct page_pool_params { 361 + struct_group_tagged(page_pool_params_slow, slow, 362 + struct net_device *netdev; 363 + unsigned int queue_idx; 364 + unsigned int flags; 365 + }; 366 + struct_group_tagged(page_pool_params_fast, fast, 367 + unsigned int order; 368 + unsigned int pool_size; 369 + int nid; 370 + struct device *dev; 371 + struct napi_struct *napi; 372 + enum dma_data_direction dma_dir; 373 + unsigned int max_len; 374 + unsigned int offset; 375 + }; 376 + }; 377 + """, 378 + }, 379 + "unbalanced_without_end_of_line": { 380 + "source": """ \ 381 + struct page_pool_params { \ 382 + struct_group_tagged(page_pool_params_slow, slow, \ 383 + struct net_device *netdev; \ 384 + unsigned int queue_idx; \ 385 + unsigned int flags; 386 + /* private: used by test code only */ 387 + void (*init_callback)(netmem_ref netmem, void *arg); \ 388 + void *init_arg; \ 389 + }; \ 390 + struct_group_tagged(page_pool_params_fast, fast, \ 391 + unsigned int order; \ 392 + unsigned int pool_size; \ 393 + int nid; \ 394 + struct device *dev; \ 395 + struct napi_struct *napi; \ 396 + enum dma_data_direction dma_dir; \ 397 + unsigned int max_len; \ 398 + unsigned int offset; \ 399 + }; \ 400 + }; 401 + """, 402 + "trimmed": """ 403 + struct page_pool_params { 404 + struct_group_tagged(page_pool_params_slow, slow, 405 + struct net_device *netdev; 406 + unsigned int queue_idx; 407 + unsigned int flags; 408 + }; 409 + struct_group_tagged(page_pool_params_fast, fast, 410 + unsigned int order; 411 + unsigned int pool_size; 412 + int nid; 413 + struct device *dev; 414 + struct napi_struct *napi; 415 + enum dma_data_direction dma_dir; 416 + unsigned int max_len; 417 + unsigned int offset; 418 + }; 419 + }; 420 + """, 421 + }, 422 + } 423 + 424 + #: Dict containing all test groups fror CTokenizer 425 + TESTS = { 426 + "TestPublicPrivate": TESTS_PRIVATE, 427 + "TestTokenizer": TESTS_TOKENIZER, 428 + } 429 + 430 + def setUp(self): 431 + self.maxDiff = None 432 + 433 + def build_test_class(group_name, table): 434 + """ 435 + Dynamically creates a class instance using type() as a generator 436 + for a new class derivated from unittest.TestCase. 437 + 438 + We're opting to do it inside a function to avoid the risk of 439 + changing the globals() dictionary. 440 + """ 441 + 442 + class_dict = { 443 + "setUp": setUp 444 + } 445 + 446 + run = table["__run__"] 447 + 448 + for test_name, data in table.items(): 449 + if test_name == "__run__": 450 + continue 451 + 452 + class_dict[f"test_{test_name}"] = run(test_name, data) 453 + 454 + cls = type(group_name, (unittest.TestCase,), class_dict) 455 + 456 + return cls.__name__, cls 457 + 458 + # 459 + # Create classes and add them to the global dictionary 460 + # 461 + for group, table in TESTS.items(): 462 + t = build_test_class(group, table) 463 + globals()[t[0]] = t[1] 464 + 465 + # 466 + # main 467 + # 468 + if __name__ == "__main__": 469 + run_unittest(__file__)