History

Merge tag 'docs-6.18' of git://git.lwn.net/linux

Pull documentation updates from Jonathan Corbet: "It has been a relatively busy cycle in docsland, with changes all over: - Bring the kernel memory-model docs into the Sphinx build in the "literal include" mode. - Lots of build-infrastructure work, further cleaning up long-term kernel-doc technical debt. The sphinx-pre-install tool has been converted to Python and updated for current systems. - A new tool to detect when documents have been moved and generate HTML redirects; this can be used on kernel.org (or any other site hosting the rendered docs) to avoid breaking links. - Automated processing of the YAML files describing the netlink protocol. - A significant update of the maintainer's PGP guide. ... and a seemingly endless series of typo fixes, build-problem fixes, etc" * tag 'docs-6.18' of git://git.lwn.net/linux: (193 commits) Documentation/features: Update feature lists for 6.17-rc7 docs: remove cdomain.py Documentation/process: submitting-patches: fix typo in "were do" docs: dev-tools/lkmm: Fix typo of missing file extension Documentation: trace: histogram: Convert ftrace docs cross-reference Documentation: trace: histogram-design: Wrap introductory note in note:: directive Documentation: trace: historgram-design: Separate sched_waking histogram section heading and the following diagram Documentation: trace: histogram-design: Trim trailing vertices in diagram explanation text Documentation: trace: histogram: Fix histogram trigger subsection number order docs: driver-api: fix spelling of "buses". Documentation: fbcon: Use admonition directives Documentation: fbcon: Reindent 8th step of attach/detach/unload Documentation: fbcon: Add boot options and attach/detach/unload section headings docs: filesystems: sysfs: add remaining top level sysfs directory descriptions docs: filesystems: sysfs: clarify symlink destinations in dev and bus/devices descriptions docs: filesystems: sysfs: remove top level sysfs net directory docs: maintainer: Fix ambiguous subheading formatting docs: kdoc: a few more dump_typedef() tweaks docs: kdoc: remove redundant comment stripping in dump_typedef() docs: kdoc: remove some dead code in dump_typedef() ...

Linus Torvalds committed 1 year ago

Commit ee2fe812 parents 50647a1 99510c3173 files · +7050 −3564Browse files

Unified · Split

173 files
  1. .pylintrc +1 −1
  2. Documentation/.renames.txt +1191 −0
  3. Documentation/Makefile +7 −4
  4. Documentation/PCI/endpoint/pci-endpoint-cfs.rst +2 −2
  5. Documentation/PCI/endpoint/pci-endpoint.rst +3 −3
  6. Documentation/RCU/lockdep.rst +1 −1
  7. Documentation/RCU/stallwarn.rst +1 −1
  8. Documentation/admin-guide/LSM/SafeSetID.rst +1 −1
  9. Documentation/admin-guide/RAS/main.rst +1 −1
  10. Documentation/admin-guide/aoe/udev.txt +3 −3
  11. Documentation/admin-guide/blockdev/paride.rst +1 −1
  12. Documentation/admin-guide/device-mapper/vdo-design.rst +1 −1
  13. Documentation/admin-guide/ext4.rst +1 −1
  14. Documentation/admin-guide/hw-vuln/mds.rst +1 −1
  15. Documentation/admin-guide/hw-vuln/spectre.rst +3 −3
  16. Documentation/admin-guide/kdump/kdump.rst +1 −1
  17. Documentation/admin-guide/kernel-parameters.rst +3 −1
  18. Documentation/admin-guide/kernel-parameters.txt +6 −6
  19. Documentation/admin-guide/laptops/laptop-mode.rst +4 −4
  20. Documentation/admin-guide/laptops/sonypi.rst +1 −1
  21. Documentation/admin-guide/md.rst +1 −1
  22. Documentation/admin-guide/media/imx.rst +1 −1
  23. Documentation/admin-guide/media/si4713.rst +3 −3
  24. Documentation/admin-guide/mm/damon/usage.rst +1 −1
  25. Documentation/admin-guide/nfs/nfsroot.rst +1 −1
  26. Documentation/admin-guide/perf/hisi-pmu.rst +2 −2
  27. Documentation/admin-guide/quickly-build-trimmed-linux.rst +2 −2
  28. Documentation/admin-guide/reporting-issues.rst +2 −2
  29. Documentation/admin-guide/sysctl/fs.rst +2 −2
  30. Documentation/admin-guide/sysctl/index.rst +12 −6
  31. Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst +1 −1
  32. Documentation/arch/arm/stm32/stm32f746-overview.rst +1 −1
  33. Documentation/arch/arm/stm32/stm32f769-overview.rst +1 −1
  34. Documentation/arch/arm/stm32/stm32h743-overview.rst +1 −1
  35. Documentation/arch/arm/stm32/stm32h750-overview.rst +1 −1
  36. Documentation/arch/arm/stm32/stm32mp13-overview.rst +1 −1
  37. Documentation/arch/arm/stm32/stm32mp151-overview.rst +1 −1
  38. Documentation/arch/loongarch/irq-chip-model.rst +2 −2
  39. Documentation/arch/powerpc/eeh-pci-error-recovery.rst +0 −1
  40. Documentation/arch/x86/cpuinfo.rst +1 −1
  41. Documentation/conf.py +61 −45
  42. Documentation/core-api/folio_queue.rst +1 −1
  43. Documentation/core-api/index.rst +1 −0
  44. Documentation/core-api/irq/irq-affinity.rst +3 −3
  45. Documentation/core-api/irq/irq-domain.rst +19 −19
  46. Documentation/core-api/printk-formats.rst +1 −1
  47. Documentation/core-api/real-time/architecture-porting.rst +109 −0
  48. Documentation/core-api/real-time/differences.rst +242 −0
  49. Documentation/core-api/real-time/index.rst +16 −0
  50. Documentation/core-api/real-time/theory.rst +116 −0
  51. Documentation/dev-tools/autofdo.rst +2 −2
  52. Documentation/dev-tools/index.rst +1 −0
  53. Documentation/dev-tools/ktap.rst +4 −1
  54. Documentation/dev-tools/lkmm/docs/access-marking.rst +11 −0
  55. Documentation/dev-tools/lkmm/docs/cheatsheet.rst +11 −0
  56. Documentation/dev-tools/lkmm/docs/control-dependencies.rst +11 −0
  57. Documentation/dev-tools/lkmm/docs/explanation.rst +11 −0
  58. Documentation/dev-tools/lkmm/docs/glossary.rst +11 −0
  59. Documentation/dev-tools/lkmm/docs/herd-representation.rst +11 −0
  60. Documentation/dev-tools/lkmm/docs/index.rst +21 −0
  61. Documentation/dev-tools/lkmm/docs/litmus-tests.rst +11 −0
  62. Documentation/dev-tools/lkmm/docs/locking.rst +11 −0
  63. Documentation/dev-tools/lkmm/docs/ordering.rst +11 −0
  64. Documentation/dev-tools/lkmm/docs/readme.rst +11 −0
  65. Documentation/dev-tools/lkmm/docs/recipes.rst +11 −0
  66. Documentation/dev-tools/lkmm/docs/references.rst +11 −0
  67. Documentation/dev-tools/lkmm/docs/simple.rst +11 −0
  68. Documentation/dev-tools/lkmm/index.rst +15 −0
  69. Documentation/dev-tools/lkmm/readme.rst +11 −0
  70. Documentation/devicetree/bindings/submitting-patches.rst +1 −1
  71. Documentation/driver-api/cxl/devices/device-types.rst +1 −1
  72. Documentation/driver-api/cxl/platform/example-configurations/one-dev-per-hb.rst +1 −1
  73. Documentation/driver-api/device-io.rst +2 −2
  74. Documentation/driver-api/driver-model/overview.rst +1 −1
  75. Documentation/driver-api/driver-model/platform.rst +1 −1
  76. Documentation/driver-api/eisa.rst +3 −3
  77. Documentation/driver-api/i3c/protocol.rst +2 −2
  78. Documentation/driver-api/ipmi.rst +2 −2
  79. Documentation/driver-api/media/tx-rx.rst +2 −2
  80. Documentation/driver-api/nvdimm/nvdimm.rst +1 −1
  81. Documentation/driver-api/pin-control.rst +6 −4
  82. Documentation/driver-api/pm/devices.rst +2 −2
  83. Documentation/driver-api/scsi.rst +2 −2
  84. Documentation/driver-api/spi.rst +1 −1
  85. Documentation/driver-api/thermal/exynos_thermal_emulation.rst +7 −7
  86. Documentation/driver-api/usb/hotplug.rst +1 −1
  87. Documentation/driver-api/usb/index.rst +1 −0
  88. Documentation/driver-api/usb/usb.rst +2 −2
  89. Documentation/fb/fbcon.rst +24 −18
  90. Documentation/features/core/eBPF-JIT/arch-support.txt +2 −2
  91. Documentation/features/core/mseal_sys_mappings/arch-support.txt +1 −1
  92. Documentation/features/core/thread-info-in-task/arch-support.txt +1 −1
  93. Documentation/features/core/tracehook/arch-support.txt +1 −1
  94. Documentation/features/perf/kprobes-event/arch-support.txt +1 −1
  95. Documentation/features/time/clockevents/arch-support.txt +1 −1
  96. Documentation/filesystems/erofs.rst +1 −1
  97. Documentation/filesystems/ext4/atomic_writes.rst +3 −3
  98. Documentation/filesystems/gfs2-glocks.rst +1 −1
  99. Documentation/filesystems/hpfs.rst +1 −1
  100. Documentation/filesystems/iomap/operations.rst +1 −1
  101. Documentation/filesystems/ocfs2-online-filecheck.rst +10 −10
  102. Documentation/filesystems/proc.rst +0 −21
  103. Documentation/filesystems/propagate_umount.txt +3 −3
  104. Documentation/filesystems/resctrl.rst +1 −1
  105. Documentation/filesystems/sharedsubtree.rst +671 −676
  106. Documentation/filesystems/sysfs.rst +19 −6
  107. Documentation/filesystems/xfs/xfs-online-fsck-design.rst +4 −4
  108. Documentation/locking/locktypes.rst +21 −0
  109. Documentation/locking/seqlock.rst +2 −0
  110. Documentation/maintainer/configure-git.rst +0 −28
  111. Documentation/maintainer/maintainer-entry-profile.rst +2 −0
  112. Documentation/mm/physical_memory.rst +2 −0
  113. Documentation/networking/can.rst +1 −1
  114. Documentation/networking/device_drivers/ethernet/ti/am65_nuss_cpsw_switchdev.rst +1 −1
  115. Documentation/networking/device_drivers/ethernet/ti/cpsw_switchdev.rst +1 −1
  116. Documentation/networking/rds.rst +1 −1
  117. Documentation/power/pci.rst +2 −2
  118. Documentation/power/suspend-and-cpuhotplug.rst +1 −1
  119. Documentation/process/5.Posting.rst +3 −4
  120. Documentation/process/changes.rst +8 −1
  121. Documentation/process/maintainer-pgp-guide.rst +75 −83
  122. Documentation/process/submitting-patches.rst +3 −3
  123. Documentation/sphinx/automarkup.py +1 −1
  124. Documentation/sphinx/cdomain.py +0 −247
  125. Documentation/sphinx/kernel_feat.py +3 −1
  126. Documentation/sphinx/kernel_include.py +392 −136
  127. Documentation/sphinx/maintainers_include.py +3 −1
  128. Documentation/sphinx/parse-headers.pl +0 −404
  129. Documentation/sphinx/templates/kernel-toc.html +2 −1
  130. Documentation/sphinx/templates/translations.html +2 −2
  131. Documentation/staging/remoteproc.rst +1 −1
  132. Documentation/trace/boottime-trace.rst +1 −1
  133. Documentation/trace/debugging.rst +1 −1
  134. Documentation/trace/events.rst +4 −4
  135. Documentation/trace/fprobe.rst +1 −1
  136. Documentation/trace/ftrace-uses.rst +1 −1
  137. Documentation/trace/ftrace.rst +7 −7
  138. Documentation/trace/histogram-design.rst +89 −86
  139. Documentation/trace/histogram.rst +20 −20
  140. Documentation/trace/rv/monitor_synthesis.rst +1 −1
  141. Documentation/translations/it_IT/process/changes.rst +0 −14
  142. Documentation/userspace-api/media/Makefile +0 −64
  143. Documentation/userspace-api/media/cec/cec-header.rst +3 −2
  144. Documentation/userspace-api/media/cec/cec.h.rst.exceptions +0 −0
  145. Documentation/userspace-api/media/dvb/ca.h.rst.exceptions +0 −0
  146. Documentation/userspace-api/media/dvb/dmx.h.rst.exceptions +0 −0
  147. Documentation/userspace-api/media/dvb/frontend.h.rst.exceptions +0 −0
  148. Documentation/userspace-api/media/dvb/headers.rst +13 −4
  149. Documentation/userspace-api/media/dvb/net.h.rst.exceptions +0 −0
  150. Documentation/userspace-api/media/mediactl/media-header.rst +3 −2
  151. Documentation/userspace-api/media/mediactl/media.h.rst.exceptions +0 −0
  152. Documentation/userspace-api/media/rc/lirc-header.rst +3 −1
  153. Documentation/userspace-api/media/rc/lirc.h.rst.exceptions +0 −0
  154. Documentation/userspace-api/media/v4l/videodev.rst +3 −1
  155. Documentation/userspace-api/media/v4l/videodev2.h.rst.exceptions +0 −0
  156. Documentation/virt/kvm/review-checklist.rst +1 −1
  157. Documentation/w1/masters/ds2482.rst +1 −1
  158. Documentation/w1/masters/index.rst +1 −1
  159. Documentation/w1/slaves/index.rst +1 −1
  160. MAINTAINERS +3 −0
  161. Makefile +3 −2
  162. fs/btrfs/tree-log.c +1 −1
  163. scripts/kernel-doc.py +24 −10
  164. scripts/lib/kdoc/kdoc_parser.py +414 −434
  165. scripts/selinux/install_policy.sh +1 −1
  166. scripts/sphinx-build-wrapper +719 −0
  167. scripts/sphinx-pre-install +1617 −1052
  168. tools/docs/gen-redirects.py +54 −0
  169. tools/docs/gen-renames.py +130 −0
  170. tools/docs/lib/__init__.py +0 −0
  171. tools/docs/lib/enrich_formatter.py +70 −0
  172. tools/docs/lib/parse_data_structs.py +452 −0
  173. tools/docs/parse-headers.py +60 −0
.pylintrc+1−1
@@ -1,2 +1,2 @@
11 [MASTER]
2−init-hook='import sys; sys.path += ["scripts/lib/kdoc", "scripts/lib/abi"]'
2+init-hook='import sys; sys.path += ["scripts/lib/kdoc", "scripts/lib/abi", "tools/docs/lib"]'
Documentation/.renames.txt+1191−0
@@ -0,0 +1,1191 @@
1+80211/cfg80211 driver-api/80211/cfg80211
2+80211/index driver-api/80211/index
3+80211/introduction driver-api/80211/introduction
4+80211/mac80211 driver-api/80211/mac80211
5+80211/mac80211-advanced driver-api/80211/mac80211-advanced
6+EDID/howto admin-guide/edid
7+PCI/picebus-howto PCI/pciebus-howto
8+RAS/address-translation admin-guide/RAS/address-translation
9+RAS/error-decoding admin-guide/RAS/error-decoding
10+RAS/ras admin-guide/RAS/error-decoding
11+accelerators/ocxl userspace-api/accelerators/ocxl
12+admin-guide/gpio/sysfs userspace-api/gpio/sysfs
13+admin-guide/l1tf admin-guide/hw-vuln/l1tf
14+admin-guide/media/v4l-with-ir admin-guide/media/remote-controller
15+admin-guide/ras admin-guide/RAS/main
16+admin-guide/security-bugs process/security-bugs
17+aoe/aoe admin-guide/aoe/aoe
18+aoe/examples admin-guide/aoe/examples
19+aoe/index admin-guide/aoe/index
20+aoe/todo admin-guide/aoe/todo
21+arc/arc arch/arc/arc
22+arc/features arch/arc/features
23+arc/index arch/arc/index
24+arch/x86/resctrl filesystems/resctrl
25+arm/arm arch/arm/arm
26+arm/booting arch/arm/booting
27+arm/cluster-pm-race-avoidance arch/arm/cluster-pm-race-avoidance
28+arm/features arch/arm/features
29+arm/firmware arch/arm/firmware
30+arm/google/chromebook-boot-flow arch/arm/google/chromebook-boot-flow
31+arm/index arch/arm/index
32+arm/interrupts arch/arm/interrupts
33+arm/ixp4xx arch/arm/ixp4xx
34+arm/kernel_mode_neon arch/arm/kernel_mode_neon
35+arm/kernel_user_helpers arch/arm/kernel_user_helpers
36+arm/keystone/knav-qmss arch/arm/keystone/knav-qmss
37+arm/keystone/overview arch/arm/keystone/overview
38+arm/marvel arch/arm/marvell
39+arm/marvell arch/arm/marvell
40+arm/mem_alignment arch/arm/mem_alignment
41+arm/memory arch/arm/memory
42+arm/microchip arch/arm/microchip
43+arm/netwinder arch/arm/netwinder
44+arm/nwfpe/index arch/arm/nwfpe/index
45+arm/nwfpe/netwinder-fpe arch/arm/nwfpe/netwinder-fpe
46+arm/nwfpe/notes arch/arm/nwfpe/notes
47+arm/nwfpe/nwfpe arch/arm/nwfpe/nwfpe
48+arm/nwfpe/todo arch/arm/nwfpe/todo
49+arm/omap/dss arch/arm/omap/dss
50+arm/omap/index arch/arm/omap/index
51+arm/omap/omap arch/arm/omap/omap
52+arm/omap/omap_pm arch/arm/omap/omap_pm
53+arm/porting arch/arm/porting
54+arm/pxa/mfp arch/arm/pxa/mfp
55+arm/sa1100/assabet arch/arm/sa1100/assabet
56+arm/sa1100/cerf arch/arm/sa1100/cerf
57+arm/sa1100/index arch/arm/sa1100/index
58+arm/sa1100/lart arch/arm/sa1100/lart
59+arm/sa1100/serial_uart arch/arm/sa1100/serial_uart
60+arm/samsung/bootloader-interface arch/arm/samsung/bootloader-interface
61+arm/samsung/gpio arch/arm/samsung/gpio
62+arm/samsung/index arch/arm/samsung/index
63+arm/samsung/overview arch/arm/samsung/overview
64+arm/setup arch/arm/setup
65+arm/spear/overview arch/arm/spear/overview
66+arm/sti/overview arch/arm/sti/overview
67+arm/sti/stih407-overview arch/arm/sti/stih407-overview
68+arm/sti/stih418-overview arch/arm/sti/stih418-overview
69+arm/stm32/overview arch/arm/stm32/overview
70+arm/stm32/stm32-dma-mdma-chaining arch/arm/stm32/stm32-dma-mdma-chaining
71+arm/stm32/stm32f429-overview arch/arm/stm32/stm32f429-overview
72+arm/stm32/stm32f746-overview arch/arm/stm32/stm32f746-overview
73+arm/stm32/stm32f769-overview arch/arm/stm32/stm32f769-overview
74+arm/stm32/stm32h743-overview arch/arm/stm32/stm32h743-overview
75+arm/stm32/stm32h750-overview arch/arm/stm32/stm32h750-overview
76+arm/stm32/stm32mp13-overview arch/arm/stm32/stm32mp13-overview
77+arm/stm32/stm32mp151-overview arch/arm/stm32/stm32mp151-overview
78+arm/stm32/stm32mp157-overview arch/arm/stm32/stm32mp157-overview
79+arm/sunxi arch/arm/sunxi
80+arm/sunxi/clocks arch/arm/sunxi/clocks
81+arm/swp_emulation arch/arm/swp_emulation
82+arm/tcm arch/arm/tcm
83+arm/uefi arch/arm/uefi
84+arm/vfp/release-notes arch/arm/vfp/release-notes
85+arm/vlocks arch/arm/vlocks
86+arm64/acpi_object_usage arch/arm64/acpi_object_usage
87+arm64/amu arch/arm64/amu
88+arm64/arm-acpi arch/arm64/arm-acpi
89+arm64/asymmetric-32bit arch/arm64/asymmetric-32bit
90+arm64/booting arch/arm64/booting
91+arm64/cpu-feature-registers arch/arm64/cpu-feature-registers
92+arm64/elf_hwcaps arch/arm64/elf_hwcaps
93+arm64/features arch/arm64/features
94+arm64/hugetlbpage arch/arm64/hugetlbpage
95+arm64/index arch/arm64/index
96+arm64/legacy_instructions arch/arm64/legacy_instructions
97+arm64/memory arch/arm64/memory
98+arm64/memory-tagging-extension arch/arm64/memory-tagging-extension
99+arm64/perf arch/arm64/perf
100+arm64/pointer-authentication arch/arm64/pointer-authentication
101+arm64/silicon-errata arch/arm64/silicon-errata
102+arm64/sme arch/arm64/sme
103+arm64/sve arch/arm64/sve
104+arm64/tagged-address-abi arch/arm64/tagged-address-abi
105+arm64/tagged-pointers arch/arm64/tagged-pointers
106+asm-annotations core-api/asm-annotations
107+auxdisplay/lcd-panel-cgram admin-guide/lcd-panel-cgram
108+backlight/lp855x-driver driver-api/backlight/lp855x-driver
109+blockdev/drbd/data-structure-v9 admin-guide/blockdev/drbd/data-structure-v9
110+blockdev/drbd/figures admin-guide/blockdev/drbd/figures
111+blockdev/drbd/index admin-guide/blockdev/drbd/index
112+blockdev/floppy admin-guide/blockdev/floppy
113+blockdev/index admin-guide/blockdev/index
114+blockdev/nbd admin-guide/blockdev/nbd
115+blockdev/paride admin-guide/blockdev/paride
116+blockdev/ramdisk admin-guide/blockdev/ramdisk
117+blockdev/zram admin-guide/blockdev/zram
118+bpf/README bpf/index
119+bpf/bpf_lsm bpf/prog_lsm
120+bpf/instruction-set bpf/standardization/instruction-set
121+bpf/libbpf/libbpf bpf/libbpf/index
122+bpf/standardization/linux-notes bpf/linux-notes
123+bus-devices/ti-gpmc driver-api/memory-devices/ti-gpmc
124+cgroup-v1/blkio-controller admin-guide/cgroup-v1/blkio-controller
125+cgroup-v1/cgroups admin-guide/cgroup-v1/cgroups
126+cgroup-v1/cpuacct admin-guide/cgroup-v1/cpuacct
127+cgroup-v1/cpusets admin-guide/cgroup-v1/cpusets
128+cgroup-v1/devices admin-guide/cgroup-v1/devices
129+cgroup-v1/freezer-subsystem admin-guide/cgroup-v1/freezer-subsystem
130+cgroup-v1/hugetlb admin-guide/cgroup-v1/hugetlb
131+cgroup-v1/index admin-guide/cgroup-v1/index
132+cgroup-v1/memcg_test admin-guide/cgroup-v1/memcg_test
133+cgroup-v1/memory admin-guide/cgroup-v1/memory
134+cgroup-v1/net_cls admin-guide/cgroup-v1/net_cls
135+cgroup-v1/net_prio admin-guide/cgroup-v1/net_prio
136+cgroup-v1/pids admin-guide/cgroup-v1/pids
137+cgroup-v1/rdma admin-guide/cgroup-v1/rdma
138+cma/debugfs admin-guide/mm/cma_debugfs
139+connector/connector driver-api/connector
140+console/console driver-api/console
141+core-api/gcc-plugins kbuild/gcc-plugins
142+core-api/ioctl driver-api/ioctl
143+core-api/memory-hotplug-notifier core-api/memory-hotplug
144+dev-tools/gdb-kernel-debugging process/debugging/gdb-kernel-debugging
145+dev-tools/kgdb process/debugging/kgdb
146+dev-tools/tools dev-tools/index
147+development-process/1.Intro process/1.Intro
148+development-process/2.Process process/2.Process
149+development-process/3.Early-stage process/3.Early-stage
150+development-process/4.Coding process/4.Coding
151+development-process/5.Posting process/5.Posting
152+development-process/6.Followthrough process/6.Followthrough
153+development-process/7.AdvancedTopics process/7.AdvancedTopics
154+development-process/8.Conclusion process/8.Conclusion
155+development-process/development-process process/development-process
156+development-process/index process/index
157+device-mapper/cache admin-guide/device-mapper/cache
158+device-mapper/cache-policies admin-guide/device-mapper/cache-policies
159+device-mapper/delay admin-guide/device-mapper/delay
160+device-mapper/dm-crypt admin-guide/device-mapper/dm-crypt
161+device-mapper/dm-flakey admin-guide/device-mapper/dm-flakey
162+device-mapper/dm-init admin-guide/device-mapper/dm-init
163+device-mapper/dm-integrity admin-guide/device-mapper/dm-integrity
164+device-mapper/dm-io admin-guide/device-mapper/dm-io
165+device-mapper/dm-log admin-guide/device-mapper/dm-log
166+device-mapper/dm-queue-length admin-guide/device-mapper/dm-queue-length
167+device-mapper/dm-raid admin-guide/device-mapper/dm-raid
168+device-mapper/dm-service-time admin-guide/device-mapper/dm-service-time
169+device-mapper/dm-uevent admin-guide/device-mapper/dm-uevent
170+device-mapper/dm-zoned admin-guide/device-mapper/dm-zoned
171+device-mapper/era admin-guide/device-mapper/era
172+device-mapper/index admin-guide/device-mapper/index
173+device-mapper/kcopyd admin-guide/device-mapper/kcopyd
174+device-mapper/linear admin-guide/device-mapper/linear
175+device-mapper/log-writes admin-guide/device-mapper/log-writes
176+device-mapper/persistent-data admin-guide/device-mapper/persistent-data
177+device-mapper/snapshot admin-guide/device-mapper/snapshot
178+device-mapper/statistics admin-guide/device-mapper/statistics
179+device-mapper/striped admin-guide/device-mapper/striped
180+device-mapper/switch admin-guide/device-mapper/switch
181+device-mapper/thin-provisioning admin-guide/device-mapper/thin-provisioning
182+device-mapper/unstriped admin-guide/device-mapper/unstriped
183+device-mapper/verity admin-guide/device-mapper/verity
184+device-mapper/writecache admin-guide/device-mapper/writecache
185+device-mapper/zero admin-guide/device-mapper/zero
186+devicetree/writing-schema devicetree/bindings/writing-schema
187+driver-api/bt8xxgpio driver-api/gpio/bt8xxgpio
188+driver-api/cxl/access-coordinates driver-api/cxl/linux/access-coordinates
189+driver-api/cxl/memory-devices driver-api/cxl/theory-of-operation
190+driver-api/dcdbas userspace-api/dcdbas
191+driver-api/dell_rbu admin-guide/dell_rbu
192+driver-api/edid admin-guide/edid
193+driver-api/gpio driver-api/gpio/index
194+driver-api/hte/tegra194-hte driver-api/hte/tegra-hte
195+driver-api/isapnp userspace-api/isapnp
196+driver-api/media/drivers/v4l-drivers/zoran driver-api/media/drivers/zoran
197+driver-api/mtd/intel-spi driver-api/mtd/spi-intel
198+driver-api/pci driver-api/pci/pci
199+driver-api/pinctl driver-api/pin-control
200+driver-api/rapidio admin-guide/rapidio
201+driver-api/serial/moxa-smartio driver-api/tty/moxa-smartio
202+driver-api/serial/n_gsm driver-api/tty/n_gsm
203+driver-api/serial/tty driver-api/tty/tty_ldisc
204+driver-api/thermal/intel_powerclamp admin-guide/thermal/intel_powerclamp
205+driver-api/usb driver-api/usb/usb
206+driver-model/binding driver-api/driver-model/binding
207+driver-model/bus driver-api/driver-model/bus
208+driver-model/design-patterns driver-api/driver-model/design-patterns
209+driver-model/device driver-api/driver-model/device
210+driver-model/devres driver-api/driver-model/devres
211+driver-model/driver driver-api/driver-model/driver
212+driver-model/index driver-api/driver-model/index
213+driver-model/overview driver-api/driver-model/overview
214+driver-model/platform driver-api/driver-model/platform
215+driver-model/porting driver-api/driver-model/porting
216+early-userspace/buffer-format driver-api/early-userspace/buffer-format
217+early-userspace/early_userspace_support driver-api/early-userspace/early_userspace_support
218+early-userspace/index driver-api/early-userspace/index
219+errseq core-api/errseq
220+filesystems/binderfs admin-guide/binderfs
221+filesystems/cifs/cifsd filesystems/smb/ksmbd
222+filesystems/cifs/cifsroot filesystems/smb/cifsroot
223+filesystems/cifs/index filesystems/smb/index
224+filesystems/cifs/ksmbd filesystems/smb/ksmbd
225+filesystems/ext4/ext4 admin-guide/ext4
226+filesystems/ext4/ondisk/about filesystems/ext4/about
227+filesystems/ext4/ondisk/allocators filesystems/ext4/allocators
228+filesystems/ext4/ondisk/attributes filesystems/ext4/attributes
229+filesystems/ext4/ondisk/bigalloc filesystems/ext4/bigalloc
230+filesystems/ext4/ondisk/bitmaps filesystems/ext4/bitmaps
231+filesystems/ext4/ondisk/blockgroup filesystems/ext4/blockgroup
232+filesystems/ext4/ondisk/blockmap filesystems/ext4/blockmap
233+filesystems/ext4/ondisk/blocks filesystems/ext4/blocks
234+filesystems/ext4/ondisk/checksums filesystems/ext4/checksums
235+filesystems/ext4/ondisk/directory filesystems/ext4/directory
236+filesystems/ext4/ondisk/dynamic filesystems/ext4/dynamic
237+filesystems/ext4/ondisk/eainode filesystems/ext4/eainode
238+filesystems/ext4/ondisk/globals filesystems/ext4/globals
239+filesystems/ext4/ondisk/group_descr filesystems/ext4/group_descr
240+filesystems/ext4/ondisk/ifork filesystems/ext4/ifork
241+filesystems/ext4/ondisk/inlinedata filesystems/ext4/inlinedata
242+filesystems/ext4/ondisk/inodes filesystems/ext4/inodes
243+filesystems/ext4/ondisk/journal filesystems/ext4/journal
244+filesystems/ext4/ondisk/mmp filesystems/ext4/mmp
245+filesystems/ext4/ondisk/overview filesystems/ext4/overview
246+filesystems/ext4/ondisk/special_inodes filesystems/ext4/special_inodes
247+filesystems/ext4/ondisk/super filesystems/ext4/super
248+filesystems/sysfs-pci PCI/sysfs-pci
249+filesystems/sysfs-tagging networking/sysfs-tagging
250+filesystems/xfs-delayed-logging-design filesystems/xfs/xfs-delayed-logging-design
251+filesystems/xfs-maintainer-entry-profile filesystems/xfs/xfs-maintainer-entry-profile
252+filesystems/xfs-online-fsck-design filesystems/xfs/xfs-online-fsck-design
253+filesystems/xfs-self-describing-metadata filesystems/xfs/xfs-self-describing-metadata
254+gpio/index admin-guide/gpio/index
255+gpio/sysfs userspace-api/gpio/sysfs
256+gpu/amdgpu gpu/amdgpu/index
257+hte/hte driver-api/hte/hte
258+hte/index driver-api/hte/index
259+hte/tegra194-hte driver-api/hte/tegra-hte
260+input/alps input/devices/alps
261+input/amijoy input/devices/amijoy
262+input/appletouch input/devices/appletouch
263+input/atarikbd input/devices/atarikbd
264+input/bcm5974 input/devices/bcm5974
265+input/cma3000_d0x input/devices/cma3000_d0x
266+input/cs461x input/devices/cs461x
267+input/edt-ft5x06 input/devices/edt-ft5x06
268+input/elantech input/devices/elantech
269+input/iforce-protocol input/devices/iforce-protocol
270+input/joystick input/joydev/joystick
271+input/joystick-api input/joydev/joystick-api
272+input/joystick-parport input/devices/joystick-parport
273+input/ntrig input/devices/ntrig
274+input/rotary-encoder input/devices/rotary-encoder
275+input/sentelic input/devices/sentelic
276+input/walkera0701 input/devices/walkera0701
277+input/xpad input/devices/xpad
278+input/yealink input/devices/yealink
279+interconnect/interconnect driver-api/interconnect
280+ioctl/botching-up-ioctls process/botching-up-ioctls
281+ioctl/cdrom userspace-api/ioctl/cdrom
282+ioctl/hdio userspace-api/ioctl/hdio
283+ioctl/index userspace-api/ioctl/index
284+ioctl/ioctl-decoding userspace-api/ioctl/ioctl-decoding
285+ioctl/ioctl-number userspace-api/ioctl/ioctl-number
286+kbuild/namespaces core-api/symbol-namespaces
287+kdump/index admin-guide/kdump/index
288+kdump/kdump admin-guide/kdump/kdump
289+kdump/vmcoreinfo admin-guide/kdump/vmcoreinfo
290+kernel-documentation doc-guide/kernel-doc
291+laptops/asus-laptop admin-guide/laptops/asus-laptop
292+laptops/disk-shock-protection admin-guide/laptops/disk-shock-protection
293+laptops/index admin-guide/laptops/index
294+laptops/laptop-mode admin-guide/laptops/laptop-mode
295+laptops/lg-laptop admin-guide/laptops/lg-laptop
296+laptops/sony-laptop admin-guide/laptops/sony-laptop
297+laptops/sonypi admin-guide/laptops/sonypi
298+laptops/thinkpad-acpi admin-guide/laptops/thinkpad-acpi
299+laptops/toshiba_haps admin-guide/laptops/toshiba_haps
300+loongarch/booting arch/loongarch/booting
301+loongarch/features arch/loongarch/features
302+loongarch/index arch/loongarch/index
303+loongarch/introduction arch/loongarch/introduction
304+loongarch/irq-chip-model arch/loongarch/irq-chip-model
305+m68k/buddha-driver arch/m68k/buddha-driver
306+m68k/features arch/m68k/features
307+m68k/index arch/m68k/index
308+m68k/kernel-options arch/m68k/kernel-options
309+md/index driver-api/md/index
310+md/md-cluster driver-api/md/md-cluster
311+md/raid5-cache driver-api/md/raid5-cache
312+md/raid5-ppl driver-api/md/raid5-ppl
313+media/dvb-drivers/avermedia admin-guide/media/avermedia
314+media/dvb-drivers/bt8xx admin-guide/media/bt8xx
315+media/dvb-drivers/ci admin-guide/media/ci
316+media/dvb-drivers/contributors driver-api/media/drivers/contributors
317+media/dvb-drivers/dvb-usb driver-api/media/drivers/dvb-usb
318+media/dvb-drivers/faq admin-guide/media/faq
319+media/dvb-drivers/frontends driver-api/media/drivers/frontends
320+media/dvb-drivers/index driver-api/media/drivers/index
321+media/dvb-drivers/lmedm04 admin-guide/media/lmedm04
322+media/dvb-drivers/opera-firmware admin-guide/media/opera-firmware
323+media/dvb-drivers/technisat admin-guide/media/technisat
324+media/dvb-drivers/ttusb-dec admin-guide/media/ttusb-dec
325+media/intro userspace-api/media/intro
326+media/kapi/cec-core driver-api/media/cec-core
327+media/kapi/dtv-ca driver-api/media/dtv-ca
328+media/kapi/dtv-common driver-api/media/dtv-common
329+media/kapi/dtv-core driver-api/media/dtv-core
330+media/kapi/dtv-demux driver-api/media/dtv-demux
331+media/kapi/dtv-frontend driver-api/media/dtv-frontend
332+media/kapi/dtv-net driver-api/media/dtv-net
333+media/kapi/mc-core driver-api/media/mc-core
334+media/kapi/rc-core driver-api/media/rc-core
335+media/kapi/v4l2-async driver-api/media/v4l2-async
336+media/kapi/v4l2-common driver-api/media/v4l2-common
337+media/kapi/v4l2-controls driver-api/media/v4l2-controls
338+media/kapi/v4l2-core driver-api/media/v4l2-core
339+media/kapi/v4l2-dev driver-api/media/v4l2-dev
340+media/kapi/v4l2-device driver-api/media/v4l2-device
341+media/kapi/v4l2-dv-timings driver-api/media/v4l2-dv-timings
342+media/kapi/v4l2-event driver-api/media/v4l2-event
343+media/kapi/v4l2-fh driver-api/media/v4l2-fh
344+media/kapi/v4l2-flash-led-class driver-api/media/v4l2-flash-led-class
345+media/kapi/v4l2-fwnode driver-api/media/v4l2-fwnode
346+media/kapi/v4l2-intro driver-api/media/v4l2-intro
347+media/kapi/v4l2-mc driver-api/media/v4l2-mc
348+media/kapi/v4l2-mediabus driver-api/media/v4l2-mediabus
349+media/kapi/v4l2-mem2mem driver-api/media/v4l2-mem2mem
350+media/kapi/v4l2-rect driver-api/media/v4l2-rect
351+media/kapi/v4l2-subdev driver-api/media/v4l2-subdev
352+media/kapi/v4l2-tuner driver-api/media/v4l2-tuner
353+media/kapi/v4l2-tveeprom driver-api/media/v4l2-tveeprom
354+media/kapi/v4l2-videobuf2 driver-api/media/v4l2-videobuf2
355+media/media_kapi driver-api/media/index
356+media/media_uapi userspace-api/media/index
357+media/uapi/cec/cec-api userspace-api/media/cec/cec-api
358+media/uapi/cec/cec-func-close userspace-api/media/cec/cec-func-close
359+media/uapi/cec/cec-func-ioctl userspace-api/media/cec/cec-func-ioctl
360+media/uapi/cec/cec-func-open userspace-api/media/cec/cec-func-open
361+media/uapi/cec/cec-func-poll userspace-api/media/cec/cec-func-poll
362+media/uapi/cec/cec-funcs userspace-api/media/cec/cec-funcs
363+media/uapi/cec/cec-header userspace-api/media/cec/cec-header
364+media/uapi/cec/cec-intro userspace-api/media/cec/cec-intro
365+media/uapi/cec/cec-ioc-adap-g-caps userspace-api/media/cec/cec-ioc-adap-g-caps
366+media/uapi/cec/cec-ioc-adap-g-conn-info userspace-api/media/cec/cec-ioc-adap-g-conn-info
367+media/uapi/cec/cec-ioc-adap-g-log-addrs userspace-api/media/cec/cec-ioc-adap-g-log-addrs
368+media/uapi/cec/cec-ioc-adap-g-phys-addr userspace-api/media/cec/cec-ioc-adap-g-phys-addr
369+media/uapi/cec/cec-ioc-dqevent userspace-api/media/cec/cec-ioc-dqevent
370+media/uapi/cec/cec-ioc-g-mode userspace-api/media/cec/cec-ioc-g-mode
371+media/uapi/cec/cec-ioc-receive userspace-api/media/cec/cec-ioc-receive
372+media/uapi/cec/cec-pin-error-inj userspace-api/media/cec/cec-pin-error-inj
373+media/uapi/dvb/ca userspace-api/media/dvb/ca
374+media/uapi/dvb/ca-fclose userspace-api/media/dvb/ca-fclose
375+media/uapi/dvb/ca-fopen userspace-api/media/dvb/ca-fopen
376+media/uapi/dvb/ca-get-cap userspace-api/media/dvb/ca-get-cap
377+media/uapi/dvb/ca-get-descr-info userspace-api/media/dvb/ca-get-descr-info
378+media/uapi/dvb/ca-get-msg userspace-api/media/dvb/ca-get-msg
379+media/uapi/dvb/ca-get-slot-info userspace-api/media/dvb/ca-get-slot-info
380+media/uapi/dvb/ca-reset userspace-api/media/dvb/ca-reset
381+media/uapi/dvb/ca-send-msg userspace-api/media/dvb/ca-send-msg
382+media/uapi/dvb/ca-set-descr userspace-api/media/dvb/ca-set-descr
383+media/uapi/dvb/ca_data_types userspace-api/media/dvb/ca_data_types
384+media/uapi/dvb/ca_function_calls userspace-api/media/dvb/ca_function_calls
385+media/uapi/dvb/ca_high_level userspace-api/media/dvb/ca_high_level
386+media/uapi/dvb/demux userspace-api/media/dvb/demux
387+media/uapi/dvb/dmx-add-pid userspace-api/media/dvb/dmx-add-pid
388+media/uapi/dvb/dmx-expbuf userspace-api/media/dvb/dmx-expbuf
389+media/uapi/dvb/dmx-fclose userspace-api/media/dvb/dmx-fclose
390+media/uapi/dvb/dmx-fopen userspace-api/media/dvb/dmx-fopen
391+media/uapi/dvb/dmx-fread userspace-api/media/dvb/dmx-fread
392+media/uapi/dvb/dmx-fwrite userspace-api/media/dvb/dmx-fwrite
393+media/uapi/dvb/dmx-get-pes-pids userspace-api/media/dvb/dmx-get-pes-pids
394+media/uapi/dvb/dmx-get-stc userspace-api/media/dvb/dmx-get-stc
395+media/uapi/dvb/dmx-mmap userspace-api/media/dvb/dmx-mmap
396+media/uapi/dvb/dmx-munmap userspace-api/media/dvb/dmx-munmap
397+media/uapi/dvb/dmx-qbuf userspace-api/media/dvb/dmx-qbuf
398+media/uapi/dvb/dmx-querybuf userspace-api/media/dvb/dmx-querybuf
399+media/uapi/dvb/dmx-remove-pid userspace-api/media/dvb/dmx-remove-pid
400+media/uapi/dvb/dmx-reqbufs userspace-api/media/dvb/dmx-reqbufs
401+media/uapi/dvb/dmx-set-buffer-size userspace-api/media/dvb/dmx-set-buffer-size
402+media/uapi/dvb/dmx-set-filter userspace-api/media/dvb/dmx-set-filter
403+media/uapi/dvb/dmx-set-pes-filter userspace-api/media/dvb/dmx-set-pes-filter
404+media/uapi/dvb/dmx-start userspace-api/media/dvb/dmx-start
405+media/uapi/dvb/dmx-stop userspace-api/media/dvb/dmx-stop
406+media/uapi/dvb/dmx_fcalls userspace-api/media/dvb/dmx_fcalls
407+media/uapi/dvb/dmx_types userspace-api/media/dvb/dmx_types
408+media/uapi/dvb/dvb-fe-read-status userspace-api/media/dvb/dvb-fe-read-status
409+media/uapi/dvb/dvb-frontend-event userspace-api/media/dvb/dvb-frontend-event
410+media/uapi/dvb/dvb-frontend-parameters userspace-api/media/dvb/dvb-frontend-parameters
411+media/uapi/dvb/dvbapi userspace-api/media/dvb/dvbapi
412+media/uapi/dvb/dvbproperty userspace-api/media/dvb/dvbproperty
413+media/uapi/dvb/examples userspace-api/media/dvb/examples
414+media/uapi/dvb/fe-bandwidth-t userspace-api/media/dvb/fe-bandwidth-t
415+media/uapi/dvb/fe-diseqc-recv-slave-reply userspace-api/media/dvb/fe-diseqc-recv-slave-reply
416+media/uapi/dvb/fe-diseqc-reset-overload userspace-api/media/dvb/fe-diseqc-reset-overload
417+media/uapi/dvb/fe-diseqc-send-burst userspace-api/media/dvb/fe-diseqc-send-burst
418+media/uapi/dvb/fe-diseqc-send-master-cmd userspace-api/media/dvb/fe-diseqc-send-master-cmd
419+media/uapi/dvb/fe-dishnetwork-send-legacy-cmd userspace-api/media/dvb/fe-dishnetwork-send-legacy-cmd
420+media/uapi/dvb/fe-enable-high-lnb-voltage userspace-api/media/dvb/fe-enable-high-lnb-voltage
421+media/uapi/dvb/fe-get-event userspace-api/media/dvb/fe-get-event
422+media/uapi/dvb/fe-get-frontend userspace-api/media/dvb/fe-get-frontend
423+media/uapi/dvb/fe-get-info userspace-api/media/dvb/fe-get-info
424+media/uapi/dvb/fe-get-property userspace-api/media/dvb/fe-get-property
425+media/uapi/dvb/fe-read-ber userspace-api/media/dvb/fe-read-ber
426+media/uapi/dvb/fe-read-signal-strength userspace-api/media/dvb/fe-read-signal-strength
427+media/uapi/dvb/fe-read-snr userspace-api/media/dvb/fe-read-snr
428+media/uapi/dvb/fe-read-status userspace-api/media/dvb/fe-read-status
429+media/uapi/dvb/fe-read-uncorrected-blocks userspace-api/media/dvb/fe-read-uncorrected-blocks
430+media/uapi/dvb/fe-set-frontend userspace-api/media/dvb/fe-set-frontend
431+media/uapi/dvb/fe-set-frontend-tune-mode userspace-api/media/dvb/fe-set-frontend-tune-mode
432+media/uapi/dvb/fe-set-tone userspace-api/media/dvb/fe-set-tone
433+media/uapi/dvb/fe-set-voltage userspace-api/media/dvb/fe-set-voltage
434+media/uapi/dvb/fe-type-t userspace-api/media/dvb/fe-type-t
435+media/uapi/dvb/fe_property_parameters userspace-api/media/dvb/fe_property_parameters
436+media/uapi/dvb/frontend userspace-api/media/dvb/frontend
437+media/uapi/dvb/frontend-header userspace-api/media/dvb/frontend-header
438+media/uapi/dvb/frontend-property-cable-systems userspace-api/media/dvb/frontend-property-cable-systems
439+media/uapi/dvb/frontend-property-satellite-systems userspace-api/media/dvb/frontend-property-satellite-systems
440+media/uapi/dvb/frontend-property-terrestrial-systems userspace-api/media/dvb/frontend-property-terrestrial-systems
441+media/uapi/dvb/frontend-stat-properties userspace-api/media/dvb/frontend-stat-properties
442+media/uapi/dvb/frontend_f_close userspace-api/media/dvb/frontend_f_close
443+media/uapi/dvb/frontend_f_open userspace-api/media/dvb/frontend_f_open
444+media/uapi/dvb/frontend_fcalls userspace-api/media/dvb/frontend_fcalls
445+media/uapi/dvb/frontend_legacy_api userspace-api/media/dvb/frontend_legacy_api
446+media/uapi/dvb/frontend_legacy_dvbv3_api userspace-api/media/dvb/frontend_legacy_dvbv3_api
447+media/uapi/dvb/headers userspace-api/media/dvb/headers
448+media/uapi/dvb/intro userspace-api/media/dvb/intro
449+media/uapi/dvb/legacy_dvb_apis userspace-api/media/dvb/legacy_dvb_apis
450+media/uapi/dvb/net userspace-api/media/dvb/net
451+media/uapi/dvb/net-add-if userspace-api/media/dvb/net-add-if
452+media/uapi/dvb/net-get-if userspace-api/media/dvb/net-get-if
453+media/uapi/dvb/net-remove-if userspace-api/media/dvb/net-remove-if
454+media/uapi/dvb/net-types userspace-api/media/dvb/net-types
455+media/uapi/dvb/query-dvb-frontend-info userspace-api/media/dvb/query-dvb-frontend-info
456+media/uapi/fdl-appendix userspace-api/media/fdl-appendix
457+media/uapi/gen-errors userspace-api/media/gen-errors
458+media/uapi/mediactl/media-controller userspace-api/media/mediactl/media-controller
459+media/uapi/mediactl/media-controller-intro userspace-api/media/mediactl/media-controller-intro
460+media/uapi/mediactl/media-controller-model userspace-api/media/mediactl/media-controller-model
461+media/uapi/mediactl/media-func-close userspace-api/media/mediactl/media-func-close
462+media/uapi/mediactl/media-func-ioctl userspace-api/media/mediactl/media-func-ioctl
463+media/uapi/mediactl/media-func-open userspace-api/media/mediactl/media-func-open
464+media/uapi/mediactl/media-funcs userspace-api/media/mediactl/media-funcs
465+media/uapi/mediactl/media-header userspace-api/media/mediactl/media-header
466+media/uapi/mediactl/media-ioc-device-info userspace-api/media/mediactl/media-ioc-device-info
467+media/uapi/mediactl/media-ioc-enum-entities userspace-api/media/mediactl/media-ioc-enum-entities
468+media/uapi/mediactl/media-ioc-enum-links userspace-api/media/mediactl/media-ioc-enum-links
469+media/uapi/mediactl/media-ioc-g-topology userspace-api/media/mediactl/media-ioc-g-topology
470+media/uapi/mediactl/media-ioc-request-alloc userspace-api/media/mediactl/media-ioc-request-alloc
471+media/uapi/mediactl/media-ioc-setup-link userspace-api/media/mediactl/media-ioc-setup-link
472+media/uapi/mediactl/media-request-ioc-queue userspace-api/media/mediactl/media-request-ioc-queue
473+media/uapi/mediactl/media-request-ioc-reinit userspace-api/media/mediactl/media-request-ioc-reinit
474+media/uapi/mediactl/media-types userspace-api/media/mediactl/media-types
475+media/uapi/mediactl/request-api userspace-api/media/mediactl/request-api
476+media/uapi/mediactl/request-func-close userspace-api/media/mediactl/request-func-close
477+media/uapi/mediactl/request-func-ioctl userspace-api/media/mediactl/request-func-ioctl
478+media/uapi/mediactl/request-func-poll userspace-api/media/mediactl/request-func-poll
479+media/uapi/rc/keytable.c userspace-api/media/rc/keytable.c
480+media/uapi/rc/lirc-dev userspace-api/media/rc/lirc-dev
481+media/uapi/rc/lirc-dev-intro userspace-api/media/rc/lirc-dev-intro
482+media/uapi/rc/lirc-func userspace-api/media/rc/lirc-func
483+media/uapi/rc/lirc-get-features userspace-api/media/rc/lirc-get-features
484+media/uapi/rc/lirc-get-rec-mode userspace-api/media/rc/lirc-get-rec-mode
485+media/uapi/rc/lirc-get-rec-resolution userspace-api/media/rc/lirc-get-rec-resolution
486+media/uapi/rc/lirc-get-send-mode userspace-api/media/rc/lirc-get-send-mode
487+media/uapi/rc/lirc-get-timeout userspace-api/media/rc/lirc-get-timeout
488+media/uapi/rc/lirc-header userspace-api/media/rc/lirc-header
489+media/uapi/rc/lirc-read userspace-api/media/rc/lirc-read
490+media/uapi/rc/lirc-set-measure-carrier-mode userspace-api/media/rc/lirc-set-measure-carrier-mode
491+media/uapi/rc/lirc-set-rec-carrier userspace-api/media/rc/lirc-set-rec-carrier
492+media/uapi/rc/lirc-set-rec-carrier-range userspace-api/media/rc/lirc-set-rec-carrier-range
493+media/uapi/rc/lirc-set-rec-timeout userspace-api/media/rc/lirc-set-rec-timeout
494+media/uapi/rc/lirc-set-send-carrier userspace-api/media/rc/lirc-set-send-carrier
495+media/uapi/rc/lirc-set-send-duty-cycle userspace-api/media/rc/lirc-set-send-duty-cycle
496+media/uapi/rc/lirc-set-transmitter-mask userspace-api/media/rc/lirc-set-transmitter-mask
497+media/uapi/rc/lirc-set-wideband-receiver userspace-api/media/rc/lirc-set-wideband-receiver
498+media/uapi/rc/lirc-write userspace-api/media/rc/lirc-write
499+media/uapi/rc/rc-intro userspace-api/media/rc/rc-intro
500+media/uapi/rc/rc-protos userspace-api/media/rc/rc-protos
501+media/uapi/rc/rc-sysfs-nodes userspace-api/media/rc/rc-sysfs-nodes
502+media/uapi/rc/rc-table-change userspace-api/media/rc/rc-table-change
503+media/uapi/rc/rc-tables userspace-api/media/rc/rc-tables
504+media/uapi/rc/remote_controllers userspace-api/media/rc/remote_controllers
505+media/uapi/v4l/app-pri userspace-api/media/v4l/app-pri
506+media/uapi/v4l/audio userspace-api/media/v4l/audio
507+media/uapi/v4l/biblio userspace-api/media/v4l/biblio
508+media/uapi/v4l/buffer userspace-api/media/v4l/buffer
509+media/uapi/v4l/capture-example userspace-api/media/v4l/capture-example
510+media/uapi/v4l/capture.c userspace-api/media/v4l/capture.c
511+media/uapi/v4l/colorspaces userspace-api/media/v4l/colorspaces
512+media/uapi/v4l/colorspaces-defs userspace-api/media/v4l/colorspaces-defs
513+media/uapi/v4l/colorspaces-details userspace-api/media/v4l/colorspaces-details
514+media/uapi/v4l/common userspace-api/media/v4l/common
515+media/uapi/v4l/common-defs userspace-api/media/v4l/common-defs
516+media/uapi/v4l/compat userspace-api/media/v4l/compat
517+media/uapi/v4l/control userspace-api/media/v4l/control
518+media/uapi/v4l/crop userspace-api/media/v4l/crop
519+media/uapi/v4l/depth-formats userspace-api/media/v4l/depth-formats
520+media/uapi/v4l/dev-capture userspace-api/media/v4l/dev-capture
521+media/uapi/v4l/dev-codec userspace-api/media/v4l/dev-mem2mem
522+media/uapi/v4l/dev-decoder userspace-api/media/v4l/dev-decoder
523+media/uapi/v4l/dev-event userspace-api/media/v4l/dev-event
524+media/uapi/v4l/dev-mem2mem userspace-api/media/v4l/dev-mem2mem
525+media/uapi/v4l/dev-meta userspace-api/media/v4l/dev-meta
526+media/uapi/v4l/dev-osd userspace-api/media/v4l/dev-osd
527+media/uapi/v4l/dev-output userspace-api/media/v4l/dev-output
528+media/uapi/v4l/dev-overlay userspace-api/media/v4l/dev-overlay
529+media/uapi/v4l/dev-radio userspace-api/media/v4l/dev-radio
530+media/uapi/v4l/dev-raw-vbi userspace-api/media/v4l/dev-raw-vbi
531+media/uapi/v4l/dev-rds userspace-api/media/v4l/dev-rds
532+media/uapi/v4l/dev-sdr userspace-api/media/v4l/dev-sdr
533+media/uapi/v4l/dev-sliced-vbi userspace-api/media/v4l/dev-sliced-vbi
534+media/uapi/v4l/dev-stateless-decoder userspace-api/media/v4l/dev-stateless-decoder
535+media/uapi/v4l/dev-subdev userspace-api/media/v4l/dev-subdev
536+media/uapi/v4l/dev-touch userspace-api/media/v4l/dev-touch
537+media/uapi/v4l/devices userspace-api/media/v4l/devices
538+media/uapi/v4l/diff-v4l userspace-api/media/v4l/diff-v4l
539+media/uapi/v4l/dmabuf userspace-api/media/v4l/dmabuf
540+media/uapi/v4l/dv-timings userspace-api/media/v4l/dv-timings
541+media/uapi/v4l/ext-ctrls-camera userspace-api/media/v4l/ext-ctrls-camera
542+media/uapi/v4l/ext-ctrls-codec userspace-api/media/v4l/ext-ctrls-codec
543+media/uapi/v4l/ext-ctrls-detect userspace-api/media/v4l/ext-ctrls-detect
544+media/uapi/v4l/ext-ctrls-dv userspace-api/media/v4l/ext-ctrls-dv
545+media/uapi/v4l/ext-ctrls-flash userspace-api/media/v4l/ext-ctrls-flash
546+media/uapi/v4l/ext-ctrls-fm-rx userspace-api/media/v4l/ext-ctrls-fm-rx
547+media/uapi/v4l/ext-ctrls-fm-tx userspace-api/media/v4l/ext-ctrls-fm-tx
548+media/uapi/v4l/ext-ctrls-image-process userspace-api/media/v4l/ext-ctrls-image-process
549+media/uapi/v4l/ext-ctrls-image-source userspace-api/media/v4l/ext-ctrls-image-source
550+media/uapi/v4l/ext-ctrls-jpeg userspace-api/media/v4l/ext-ctrls-jpeg
551+media/uapi/v4l/ext-ctrls-rf-tuner userspace-api/media/v4l/ext-ctrls-rf-tuner
552+media/uapi/v4l/extended-controls userspace-api/media/v4l/extended-controls
553+media/uapi/v4l/field-order userspace-api/media/v4l/field-order
554+media/uapi/v4l/format userspace-api/media/v4l/format
555+media/uapi/v4l/func-close userspace-api/media/v4l/func-close
556+media/uapi/v4l/func-ioctl userspace-api/media/v4l/func-ioctl
557+media/uapi/v4l/func-mmap userspace-api/media/v4l/func-mmap
558+media/uapi/v4l/func-munmap userspace-api/media/v4l/func-munmap
559+media/uapi/v4l/func-open userspace-api/media/v4l/func-open
560+media/uapi/v4l/func-poll userspace-api/media/v4l/func-poll
561+media/uapi/v4l/func-read userspace-api/media/v4l/func-read
562+media/uapi/v4l/func-select userspace-api/media/v4l/func-select
563+media/uapi/v4l/func-write userspace-api/media/v4l/func-write
564+media/uapi/v4l/hist-v4l2 userspace-api/media/v4l/hist-v4l2
565+media/uapi/v4l/hsv-formats userspace-api/media/v4l/hsv-formats
566+media/uapi/v4l/io userspace-api/media/v4l/io
567+media/uapi/v4l/libv4l userspace-api/media/v4l/libv4l
568+media/uapi/v4l/libv4l-introduction userspace-api/media/v4l/libv4l-introduction
569+media/uapi/v4l/meta-formats userspace-api/media/v4l/meta-formats
570+media/uapi/v4l/mmap userspace-api/media/v4l/mmap
571+media/uapi/v4l/open userspace-api/media/v4l/open
572+media/uapi/v4l/pixfmt userspace-api/media/v4l/pixfmt
573+media/uapi/v4l/pixfmt-002 userspace-api/media/v4l/pixfmt-v4l2
574+media/uapi/v4l/pixfmt-003 userspace-api/media/v4l/pixfmt-v4l2-mplane
575+media/uapi/v4l/pixfmt-004 userspace-api/media/v4l/pixfmt-intro
576+media/uapi/v4l/pixfmt-006 userspace-api/media/v4l/colorspaces-defs
577+media/uapi/v4l/pixfmt-007 userspace-api/media/v4l/colorspaces-details
578+media/uapi/v4l/pixfmt-013 userspace-api/media/v4l/pixfmt-compressed
579+media/uapi/v4l/pixfmt-bayer userspace-api/media/v4l/pixfmt-bayer
580+media/uapi/v4l/pixfmt-cnf4 userspace-api/media/v4l/pixfmt-cnf4
581+media/uapi/v4l/pixfmt-compressed userspace-api/media/v4l/pixfmt-compressed
582+media/uapi/v4l/pixfmt-indexed userspace-api/media/v4l/pixfmt-indexed
583+media/uapi/v4l/pixfmt-intro userspace-api/media/v4l/pixfmt-intro
584+media/uapi/v4l/pixfmt-inzi userspace-api/media/v4l/pixfmt-inzi
585+media/uapi/v4l/pixfmt-m420 userspace-api/media/v4l/pixfmt-m420
586+media/uapi/v4l/pixfmt-meta-d4xx userspace-api/media/v4l/metafmt-d4xx
587+media/uapi/v4l/pixfmt-meta-intel-ipu3 userspace-api/media/v4l/metafmt-intel-ipu3
588+media/uapi/v4l/pixfmt-meta-uvc userspace-api/media/v4l/metafmt-uvc
589+media/uapi/v4l/pixfmt-meta-vivid userspace-api/media/v4l/metafmt-vivid
590+media/uapi/v4l/pixfmt-meta-vsp1-hgo userspace-api/media/v4l/metafmt-vsp1-hgo
591+media/uapi/v4l/pixfmt-meta-vsp1-hgt userspace-api/media/v4l/metafmt-vsp1-hgt
592+media/uapi/v4l/pixfmt-packed-hsv userspace-api/media/v4l/pixfmt-packed-hsv
593+media/uapi/v4l/pixfmt-packed-yuv userspace-api/media/v4l/pixfmt-packed-yuv
594+media/uapi/v4l/pixfmt-reserved userspace-api/media/v4l/pixfmt-reserved
595+media/uapi/v4l/pixfmt-rgb userspace-api/media/v4l/pixfmt-rgb
596+media/uapi/v4l/pixfmt-sbggr16 userspace-api/media/v4l/pixfmt-srggb16
597+media/uapi/v4l/pixfmt-sdr-cs08 userspace-api/media/v4l/pixfmt-sdr-cs08
598+media/uapi/v4l/pixfmt-sdr-cs14le userspace-api/media/v4l/pixfmt-sdr-cs14le
599+media/uapi/v4l/pixfmt-sdr-cu08 userspace-api/media/v4l/pixfmt-sdr-cu08
600+media/uapi/v4l/pixfmt-sdr-cu16le userspace-api/media/v4l/pixfmt-sdr-cu16le
601+media/uapi/v4l/pixfmt-sdr-pcu16be userspace-api/media/v4l/pixfmt-sdr-pcu16be
602+media/uapi/v4l/pixfmt-sdr-pcu18be userspace-api/media/v4l/pixfmt-sdr-pcu18be
603+media/uapi/v4l/pixfmt-sdr-pcu20be userspace-api/media/v4l/pixfmt-sdr-pcu20be
604+media/uapi/v4l/pixfmt-sdr-ru12le userspace-api/media/v4l/pixfmt-sdr-ru12le
605+media/uapi/v4l/pixfmt-srggb10 userspace-api/media/v4l/pixfmt-srggb10
606+media/uapi/v4l/pixfmt-srggb10-ipu3 userspace-api/media/v4l/pixfmt-srggb10-ipu3
607+media/uapi/v4l/pixfmt-srggb10alaw8 userspace-api/media/v4l/pixfmt-srggb10alaw8
608+media/uapi/v4l/pixfmt-srggb10dpcm8 userspace-api/media/v4l/pixfmt-srggb10dpcm8
609+media/uapi/v4l/pixfmt-srggb10p userspace-api/media/v4l/pixfmt-srggb10p
610+media/uapi/v4l/pixfmt-srggb12 userspace-api/media/v4l/pixfmt-srggb12
611+media/uapi/v4l/pixfmt-srggb12p userspace-api/media/v4l/pixfmt-srggb12p
612+media/uapi/v4l/pixfmt-srggb14 userspace-api/media/v4l/pixfmt-srggb14
613+media/uapi/v4l/pixfmt-srggb14p userspace-api/media/v4l/pixfmt-srggb14p
614+media/uapi/v4l/pixfmt-srggb16 userspace-api/media/v4l/pixfmt-srggb16
615+media/uapi/v4l/pixfmt-srggb8 userspace-api/media/v4l/pixfmt-srggb8
616+media/uapi/v4l/pixfmt-tch-td08 userspace-api/media/v4l/pixfmt-tch-td08
617+media/uapi/v4l/pixfmt-tch-td16 userspace-api/media/v4l/pixfmt-tch-td16
618+media/uapi/v4l/pixfmt-tch-tu08 userspace-api/media/v4l/pixfmt-tch-tu08
619+media/uapi/v4l/pixfmt-tch-tu16 userspace-api/media/v4l/pixfmt-tch-tu16
620+media/uapi/v4l/pixfmt-uv8 userspace-api/media/v4l/pixfmt-uv8
621+media/uapi/v4l/pixfmt-v4l2 userspace-api/media/v4l/pixfmt-v4l2
622+media/uapi/v4l/pixfmt-v4l2-mplane userspace-api/media/v4l/pixfmt-v4l2-mplane
623+media/uapi/v4l/pixfmt-y12i userspace-api/media/v4l/pixfmt-y12i
624+media/uapi/v4l/pixfmt-y8i userspace-api/media/v4l/pixfmt-y8i
625+media/uapi/v4l/pixfmt-z16 userspace-api/media/v4l/pixfmt-z16
626+media/uapi/v4l/planar-apis userspace-api/media/v4l/planar-apis
627+media/uapi/v4l/querycap userspace-api/media/v4l/querycap
628+media/uapi/v4l/rw userspace-api/media/v4l/rw
629+media/uapi/v4l/sdr-formats userspace-api/media/v4l/sdr-formats
630+media/uapi/v4l/selection-api userspace-api/media/v4l/selection-api
631+media/uapi/v4l/selection-api-002 userspace-api/media/v4l/selection-api-intro
632+media/uapi/v4l/selection-api-003 userspace-api/media/v4l/selection-api-targets
633+media/uapi/v4l/selection-api-004 userspace-api/media/v4l/selection-api-configuration
634+media/uapi/v4l/selection-api-005 userspace-api/media/v4l/selection-api-vs-crop-api
635+media/uapi/v4l/selection-api-006 userspace-api/media/v4l/selection-api-examples
636+media/uapi/v4l/selection-api-configuration userspace-api/media/v4l/selection-api-configuration
637+media/uapi/v4l/selection-api-examples userspace-api/media/v4l/selection-api-examples
638+media/uapi/v4l/selection-api-intro userspace-api/media/v4l/selection-api-intro
639+media/uapi/v4l/selection-api-targets userspace-api/media/v4l/selection-api-targets
640+media/uapi/v4l/selection-api-vs-crop-api userspace-api/media/v4l/selection-api-vs-crop-api
641+media/uapi/v4l/selections-common userspace-api/media/v4l/selections-common
642+media/uapi/v4l/standard userspace-api/media/v4l/standard
643+media/uapi/v4l/streaming-par userspace-api/media/v4l/streaming-par
644+media/uapi/v4l/subdev-formats userspace-api/media/v4l/subdev-formats
645+media/uapi/v4l/tch-formats userspace-api/media/v4l/tch-formats
646+media/uapi/v4l/tuner userspace-api/media/v4l/tuner
647+media/uapi/v4l/user-func userspace-api/media/v4l/user-func
648+media/uapi/v4l/userp userspace-api/media/v4l/userp
649+media/uapi/v4l/v4l2 userspace-api/media/v4l/v4l2
650+media/uapi/v4l/v4l2-selection-flags userspace-api/media/v4l/v4l2-selection-flags
651+media/uapi/v4l/v4l2-selection-targets userspace-api/media/v4l/v4l2-selection-targets
652+media/uapi/v4l/v4l2grab-example userspace-api/media/v4l/v4l2grab-example
653+media/uapi/v4l/v4l2grab.c userspace-api/media/v4l/v4l2grab.c
654+media/uapi/v4l/video userspace-api/media/v4l/video
655+media/uapi/v4l/videodev userspace-api/media/v4l/videodev
656+media/uapi/v4l/vidioc-create-bufs userspace-api/media/v4l/vidioc-create-bufs
657+media/uapi/v4l/vidioc-cropcap userspace-api/media/v4l/vidioc-cropcap
658+media/uapi/v4l/vidioc-dbg-g-chip-info userspace-api/media/v4l/vidioc-dbg-g-chip-info
659+media/uapi/v4l/vidioc-dbg-g-register userspace-api/media/v4l/vidioc-dbg-g-register
660+media/uapi/v4l/vidioc-decoder-cmd userspace-api/media/v4l/vidioc-decoder-cmd
661+media/uapi/v4l/vidioc-dqevent userspace-api/media/v4l/vidioc-dqevent
662+media/uapi/v4l/vidioc-dv-timings-cap userspace-api/media/v4l/vidioc-dv-timings-cap
663+media/uapi/v4l/vidioc-encoder-cmd userspace-api/media/v4l/vidioc-encoder-cmd
664+media/uapi/v4l/vidioc-enum-dv-timings userspace-api/media/v4l/vidioc-enum-dv-timings
665+media/uapi/v4l/vidioc-enum-fmt userspace-api/media/v4l/vidioc-enum-fmt
666+media/uapi/v4l/vidioc-enum-frameintervals userspace-api/media/v4l/vidioc-enum-frameintervals
667+media/uapi/v4l/vidioc-enum-framesizes userspace-api/media/v4l/vidioc-enum-framesizes
668+media/uapi/v4l/vidioc-enum-freq-bands userspace-api/media/v4l/vidioc-enum-freq-bands
669+media/uapi/v4l/vidioc-enumaudio userspace-api/media/v4l/vidioc-enumaudio
670+media/uapi/v4l/vidioc-enumaudioout userspace-api/media/v4l/vidioc-enumaudioout
671+media/uapi/v4l/vidioc-enuminput userspace-api/media/v4l/vidioc-enuminput
672+media/uapi/v4l/vidioc-enumoutput userspace-api/media/v4l/vidioc-enumoutput
673+media/uapi/v4l/vidioc-enumstd userspace-api/media/v4l/vidioc-enumstd
674+media/uapi/v4l/vidioc-expbuf userspace-api/media/v4l/vidioc-expbuf
675+media/uapi/v4l/vidioc-g-audio userspace-api/media/v4l/vidioc-g-audio
676+media/uapi/v4l/vidioc-g-audioout userspace-api/media/v4l/vidioc-g-audioout
677+media/uapi/v4l/vidioc-g-crop userspace-api/media/v4l/vidioc-g-crop
678+media/uapi/v4l/vidioc-g-ctrl userspace-api/media/v4l/vidioc-g-ctrl
679+media/uapi/v4l/vidioc-g-dv-timings userspace-api/media/v4l/vidioc-g-dv-timings
680+media/uapi/v4l/vidioc-g-edid userspace-api/media/v4l/vidioc-g-edid
681+media/uapi/v4l/vidioc-g-enc-index userspace-api/media/v4l/vidioc-g-enc-index
682+media/uapi/v4l/vidioc-g-ext-ctrls userspace-api/media/v4l/vidioc-g-ext-ctrls
683+media/uapi/v4l/vidioc-g-fbuf userspace-api/media/v4l/vidioc-g-fbuf
684+media/uapi/v4l/vidioc-g-fmt userspace-api/media/v4l/vidioc-g-fmt
685+media/uapi/v4l/vidioc-g-frequency userspace-api/media/v4l/vidioc-g-frequency
686+media/uapi/v4l/vidioc-g-input userspace-api/media/v4l/vidioc-g-input
687+media/uapi/v4l/vidioc-g-jpegcomp userspace-api/media/v4l/vidioc-g-jpegcomp
688+media/uapi/v4l/vidioc-g-modulator userspace-api/media/v4l/vidioc-g-modulator
689+media/uapi/v4l/vidioc-g-output userspace-api/media/v4l/vidioc-g-output
690+media/uapi/v4l/vidioc-g-parm userspace-api/media/v4l/vidioc-g-parm
691+media/uapi/v4l/vidioc-g-priority userspace-api/media/v4l/vidioc-g-priority
692+media/uapi/v4l/vidioc-g-selection userspace-api/media/v4l/vidioc-g-selection
693+media/uapi/v4l/vidioc-g-sliced-vbi-cap userspace-api/media/v4l/vidioc-g-sliced-vbi-cap
694+media/uapi/v4l/vidioc-g-std userspace-api/media/v4l/vidioc-g-std
695+media/uapi/v4l/vidioc-g-tuner userspace-api/media/v4l/vidioc-g-tuner
696+media/uapi/v4l/vidioc-log-status userspace-api/media/v4l/vidioc-log-status
697+media/uapi/v4l/vidioc-overlay userspace-api/media/v4l/vidioc-overlay
698+media/uapi/v4l/vidioc-prepare-buf userspace-api/media/v4l/vidioc-prepare-buf
699+media/uapi/v4l/vidioc-qbuf userspace-api/media/v4l/vidioc-qbuf
700+media/uapi/v4l/vidioc-query-dv-timings userspace-api/media/v4l/vidioc-query-dv-timings
701+media/uapi/v4l/vidioc-querybuf userspace-api/media/v4l/vidioc-querybuf
702+media/uapi/v4l/vidioc-querycap userspace-api/media/v4l/vidioc-querycap
703+media/uapi/v4l/vidioc-queryctrl userspace-api/media/v4l/vidioc-queryctrl
704+media/uapi/v4l/vidioc-querystd userspace-api/media/v4l/vidioc-querystd
705+media/uapi/v4l/vidioc-reqbufs userspace-api/media/v4l/vidioc-reqbufs
706+media/uapi/v4l/vidioc-s-hw-freq-seek userspace-api/media/v4l/vidioc-s-hw-freq-seek
707+media/uapi/v4l/vidioc-streamon userspace-api/media/v4l/vidioc-streamon
708+media/uapi/v4l/vidioc-subdev-enum-frame-interval userspace-api/media/v4l/vidioc-subdev-enum-frame-interval
709+media/uapi/v4l/vidioc-subdev-enum-frame-size userspace-api/media/v4l/vidioc-subdev-enum-frame-size
710+media/uapi/v4l/vidioc-subdev-enum-mbus-code userspace-api/media/v4l/vidioc-subdev-enum-mbus-code
711+media/uapi/v4l/vidioc-subdev-g-crop userspace-api/media/v4l/vidioc-subdev-g-crop
712+media/uapi/v4l/vidioc-subdev-g-fmt userspace-api/media/v4l/vidioc-subdev-g-fmt
713+media/uapi/v4l/vidioc-subdev-g-frame-interval userspace-api/media/v4l/vidioc-subdev-g-frame-interval
714+media/uapi/v4l/vidioc-subdev-g-selection userspace-api/media/v4l/vidioc-subdev-g-selection
715+media/uapi/v4l/vidioc-subscribe-event userspace-api/media/v4l/vidioc-subscribe-event
716+media/uapi/v4l/yuv-formats userspace-api/media/v4l/yuv-formats
717+media/v4l-drivers/au0828-cardlist admin-guide/media/au0828-cardlist
718+media/v4l-drivers/bttv admin-guide/media/bttv
719+media/v4l-drivers/bttv-cardlist admin-guide/media/bttv-cardlist
720+media/v4l-drivers/bttv-devel driver-api/media/drivers/bttv-devel
721+media/v4l-drivers/cafe_ccic admin-guide/media/cafe_ccic
722+media/v4l-drivers/cardlist admin-guide/media/cardlist
723+media/v4l-drivers/cx2341x driver-api/media/drivers/cx2341x-devel
724+media/v4l-drivers/cx2341x-devel driver-api/media/drivers/cx2341x-devel
725+media/v4l-drivers/cx2341x-uapi userspace-api/media/drivers/cx2341x-uapi
726+media/v4l-drivers/cx23885-cardlist admin-guide/media/cx23885-cardlist
727+media/v4l-drivers/cx88 admin-guide/media/cx88
728+media/v4l-drivers/cx88-cardlist admin-guide/media/cx88-cardlist
729+media/v4l-drivers/cx88-devel driver-api/media/drivers/cx88-devel
730+media/v4l-drivers/em28xx-cardlist admin-guide/media/em28xx-cardlist
731+media/v4l-drivers/fimc admin-guide/media/fimc
732+media/v4l-drivers/fimc-devel driver-api/media/drivers/fimc-devel
733+media/v4l-drivers/fourcc userspace-api/media/v4l/fourcc
734+media/v4l-drivers/gspca-cardlist admin-guide/media/gspca-cardlist
735+media/v4l-drivers/imx admin-guide/media/imx
736+media/v4l-drivers/imx-uapi userspace-api/media/drivers/imx-uapi
737+media/v4l-drivers/imx7 admin-guide/media/imx7
738+media/v4l-drivers/index userspace-api/media/drivers/index
739+media/v4l-drivers/ipu3 admin-guide/media/ipu3
740+media/v4l-drivers/ivtv admin-guide/media/ivtv
741+media/v4l-drivers/ivtv-cardlist admin-guide/media/ivtv-cardlist
742+media/v4l-drivers/max2175 userspace-api/media/drivers/max2175
743+media/v4l-drivers/omap3isp admin-guide/media/omap3isp
744+media/v4l-drivers/omap3isp-uapi userspace-api/media/drivers/omap3isp-uapi
745+media/v4l-drivers/philips admin-guide/media/philips
746+media/v4l-drivers/pvrusb2 driver-api/media/drivers/pvrusb2
747+media/v4l-drivers/pxa_camera driver-api/media/drivers/pxa_camera
748+media/v4l-drivers/qcom_camss admin-guide/media/qcom_camss
749+media/v4l-drivers/radiotrack driver-api/media/drivers/radiotrack
750+media/v4l-drivers/rcar-fdp1 admin-guide/media/rcar-fdp1
751+media/v4l-drivers/saa7134 admin-guide/media/saa7134
752+media/v4l-drivers/saa7134-cardlist admin-guide/media/saa7134-cardlist
753+media/v4l-drivers/saa7134-devel driver-api/media/drivers/saa7134-devel
754+media/v4l-drivers/saa7164-cardlist admin-guide/media/saa7164-cardlist
755+media/v4l-drivers/sh_mobile_ceu_camera driver-api/media/drivers/sh_mobile_ceu_camera
756+media/v4l-drivers/si470x admin-guide/media/si470x
757+media/v4l-drivers/si4713 admin-guide/media/si4713
758+media/v4l-drivers/si476x admin-guide/media/si476x
759+media/v4l-drivers/tuner-cardlist admin-guide/media/tuner-cardlist
760+media/v4l-drivers/tuners driver-api/media/drivers/tuners
761+media/v4l-drivers/uvcvideo userspace-api/media/drivers/uvcvideo
762+media/v4l-drivers/v4l-with-ir admin-guide/media/remote-controller
763+media/v4l-drivers/vimc admin-guide/media/vimc
764+media/v4l-drivers/vimc-devel driver-api/media/drivers/vimc-devel
765+media/v4l-drivers/vivid admin-guide/media/vivid
766+media/v4l-drivers/zoran driver-api/media/drivers/zoran
767+memory-devices/ti-emif driver-api/memory-devices/ti-emif
768+mips/booting arch/mips/booting
769+mips/features arch/mips/features
770+mips/index arch/mips/index
771+mips/ingenic-tcu arch/mips/ingenic-tcu
772+mm/slub admin-guide/mm/slab
773+mmc/index driver-api/mmc/index
774+mmc/mmc-async-req driver-api/mmc/mmc-async-req
775+mmc/mmc-dev-attrs driver-api/mmc/mmc-dev-attrs
776+mmc/mmc-dev-parts driver-api/mmc/mmc-dev-parts
777+mmc/mmc-tools driver-api/mmc/mmc-tools
778+mtd/index driver-api/mtd/index
779+mtd/intel-spi driver-api/mtd/spi-intel
780+mtd/nand_ecc driver-api/mtd/nand_ecc
781+mtd/spi-nor driver-api/mtd/spi-nor
782+namespaces/compatibility-list admin-guide/namespaces/compatibility-list
783+namespaces/index admin-guide/namespaces/index
784+namespaces/resource-control admin-guide/namespaces/resource-control
785+networking/altera_tse networking/device_drivers/ethernet/altera/altera_tse
786+networking/baycom networking/device_drivers/hamradio/baycom
787+networking/bpf_flow_dissector bpf/prog_flow_dissector
788+networking/cxacru networking/device_drivers/atm/cxacru
789+networking/defza networking/device_drivers/fddi/defza
790+networking/device_drivers/3com/3c509 networking/device_drivers/ethernet/3com/3c509
791+networking/device_drivers/3com/vortex networking/device_drivers/ethernet/3com/vortex
792+networking/device_drivers/amazon/ena networking/device_drivers/ethernet/amazon/ena
793+networking/device_drivers/aquantia/atlantic networking/device_drivers/ethernet/aquantia/atlantic
794+networking/device_drivers/chelsio/cxgb networking/device_drivers/ethernet/chelsio/cxgb
795+networking/device_drivers/cirrus/cs89x0 networking/device_drivers/ethernet/cirrus/cs89x0
796+networking/device_drivers/davicom/dm9000 networking/device_drivers/ethernet/davicom/dm9000
797+networking/device_drivers/dec/dmfe networking/device_drivers/ethernet/dec/dmfe
798+networking/device_drivers/dlink/dl2k networking/device_drivers/ethernet/dlink/dl2k
799+networking/device_drivers/freescale/dpaa networking/device_drivers/ethernet/freescale/dpaa
800+networking/device_drivers/freescale/dpaa2/dpio-driver networking/device_drivers/ethernet/freescale/dpaa2/dpio-driver
801+networking/device_drivers/freescale/dpaa2/ethernet-driver networking/device_drivers/ethernet/freescale/dpaa2/ethernet-driver
802+networking/device_drivers/freescale/dpaa2/index networking/device_drivers/ethernet/freescale/dpaa2/index
803+networking/device_drivers/freescale/dpaa2/mac-phy-support networking/device_drivers/ethernet/freescale/dpaa2/mac-phy-support
804+networking/device_drivers/freescale/dpaa2/overview networking/device_drivers/ethernet/freescale/dpaa2/overview
805+networking/device_drivers/freescale/gianfar networking/device_drivers/ethernet/freescale/gianfar
806+networking/device_drivers/google/gve networking/device_drivers/ethernet/google/gve
807+networking/device_drivers/intel/e100 networking/device_drivers/ethernet/intel/e100
808+networking/device_drivers/intel/e1000 networking/device_drivers/ethernet/intel/e1000
809+networking/device_drivers/intel/e1000e networking/device_drivers/ethernet/intel/e1000e
810+networking/device_drivers/intel/fm10k networking/device_drivers/ethernet/intel/fm10k
811+networking/device_drivers/intel/i40e networking/device_drivers/ethernet/intel/i40e
812+networking/device_drivers/intel/iavf networking/device_drivers/ethernet/intel/iavf
813+networking/device_drivers/intel/ice networking/device_drivers/ethernet/intel/ice
814+networking/device_drivers/intel/igb networking/device_drivers/ethernet/intel/igb
815+networking/device_drivers/intel/igbvf networking/device_drivers/ethernet/intel/igbvf
816+networking/device_drivers/intel/ipw2100 networking/device_drivers/wifi/intel/ipw2100
817+networking/device_drivers/intel/ipw2200 networking/device_drivers/wifi/intel/ipw2200
818+networking/device_drivers/intel/ixgbe networking/device_drivers/ethernet/intel/ixgbe
819+networking/device_drivers/intel/ixgbevf networking/device_drivers/ethernet/intel/ixgbevf
820+networking/device_drivers/marvell/octeontx2 networking/device_drivers/ethernet/marvell/octeontx2
821+networking/device_drivers/microsoft/netvsc networking/device_drivers/ethernet/microsoft/netvsc
822+networking/device_drivers/neterion/s2io networking/device_drivers/ethernet/neterion/s2io
823+networking/device_drivers/netronome/nfp networking/device_drivers/ethernet/netronome/nfp
824+networking/device_drivers/pensando/ionic networking/device_drivers/ethernet/pensando/ionic
825+networking/device_drivers/qualcomm/rmnet networking/device_drivers/cellular/qualcomm/rmnet
826+networking/device_drivers/smsc/smc9 networking/device_drivers/ethernet/smsc/smc9
827+networking/device_drivers/stmicro/stmmac networking/device_drivers/ethernet/stmicro/stmmac
828+networking/device_drivers/ti/cpsw networking/device_drivers/ethernet/ti/cpsw
829+networking/device_drivers/ti/cpsw_switchdev networking/device_drivers/ethernet/ti/cpsw_switchdev
830+networking/device_drivers/ti/tlan networking/device_drivers/ethernet/ti/tlan
831+networking/devlink-trap networking/devlink/devlink-trap
832+networking/dpaa2/dpio-driver networking/device_drivers/ethernet/freescale/dpaa2/dpio-driver
833+networking/dpaa2/ethernet-driver networking/device_drivers/ethernet/freescale/dpaa2/ethernet-driver
834+networking/dpaa2/index networking/device_drivers/ethernet/freescale/dpaa2/index
835+networking/dpaa2/overview networking/device_drivers/ethernet/freescale/dpaa2/overview
836+networking/e100 networking/device_drivers/ethernet/intel/e100
837+networking/e1000 networking/device_drivers/ethernet/intel/e1000
838+networking/e1000e networking/device_drivers/ethernet/intel/e1000e
839+networking/fm10k networking/device_drivers/ethernet/intel/fm10k
840+networking/fore200e networking/device_drivers/atm/fore200e
841+networking/hinic networking/device_drivers/ethernet/huawei/hinic
842+networking/i40e networking/device_drivers/ethernet/intel/i40e
843+networking/iavf networking/device_drivers/ethernet/intel/iavf
844+networking/ice networking/device_drivers/ethernet/intel/ice
845+networking/igb networking/device_drivers/ethernet/intel/igb
846+networking/igbvf networking/device_drivers/ethernet/intel/igbvf
847+networking/iphase networking/device_drivers/atm/iphase
848+networking/ixgbe networking/device_drivers/ethernet/intel/ixgbe
849+networking/ixgbevf networking/device_drivers/ethernet/intel/ixgbevf
850+networking/netdev-FAQ process/maintainer-netdev
851+networking/skfp networking/device_drivers/fddi/skfp
852+networking/z8530drv networking/device_drivers/hamradio/z8530drv
853+nfc/index driver-api/nfc/index
854+nfc/nfc-hci driver-api/nfc/nfc-hci
855+nfc/nfc-pn544 driver-api/nfc/nfc-pn544
856+nios2/features arch/nios2/features
857+nios2/index arch/nios2/index
858+nios2/nios2 arch/nios2/nios2
859+nvdimm/btt driver-api/nvdimm/btt
860+nvdimm/index driver-api/nvdimm/index
861+nvdimm/nvdimm driver-api/nvdimm/nvdimm
862+nvdimm/security driver-api/nvdimm/security
863+nvmem/nvmem driver-api/nvmem
864+openrisc/features arch/openrisc/features
865+openrisc/index arch/openrisc/index
866+openrisc/openrisc_port arch/openrisc/openrisc_port
867+openrisc/todo arch/openrisc/todo
868+parisc/debugging arch/parisc/debugging
869+parisc/features arch/parisc/features
870+parisc/index arch/parisc/index
871+parisc/registers arch/parisc/registers
872+perf/arm-ccn admin-guide/perf/arm-ccn
873+perf/arm_dsu_pmu admin-guide/perf/arm_dsu_pmu
874+perf/hisi-pmu admin-guide/perf/hisi-pmu
875+perf/index admin-guide/perf/index
876+perf/qcom_l2_pmu admin-guide/perf/qcom_l2_pmu
877+perf/qcom_l3_pmu admin-guide/perf/qcom_l3_pmu
878+perf/thunderx2-pmu admin-guide/perf/thunderx2-pmu
879+perf/xgene-pmu admin-guide/perf/xgene-pmu
880+phy/samsung-usb2 driver-api/phy/samsung-usb2
881+powerpc/associativity arch/powerpc/associativity
882+powerpc/booting arch/powerpc/booting
883+powerpc/bootwrapper arch/powerpc/bootwrapper
884+powerpc/cpu_families arch/powerpc/cpu_families
885+powerpc/cpu_features arch/powerpc/cpu_features
886+powerpc/dawr-power9 arch/powerpc/dawr-power9
887+powerpc/dexcr arch/powerpc/dexcr
888+powerpc/dscr arch/powerpc/dscr
889+powerpc/eeh-pci-error-recovery arch/powerpc/eeh-pci-error-recovery
890+powerpc/elf_hwcaps arch/powerpc/elf_hwcaps
891+powerpc/elfnote arch/powerpc/elfnote
892+powerpc/features arch/powerpc/features
893+powerpc/firmware-assisted-dump arch/powerpc/firmware-assisted-dump
894+powerpc/hvcs arch/powerpc/hvcs
895+powerpc/imc arch/powerpc/imc
896+powerpc/index arch/powerpc/index
897+powerpc/isa-versions arch/powerpc/isa-versions
898+powerpc/kaslr-booke32 arch/powerpc/kaslr-booke32
899+powerpc/mpc52xx arch/powerpc/mpc52xx
900+powerpc/papr_hcalls arch/powerpc/papr_hcalls
901+powerpc/pci_iov_resource_on_powernv arch/powerpc/pci_iov_resource_on_powernv
902+powerpc/pmu-ebb arch/powerpc/pmu-ebb
903+powerpc/ptrace arch/powerpc/ptrace
904+powerpc/qe_firmware arch/powerpc/qe_firmware
905+powerpc/syscall64-abi arch/powerpc/syscall64-abi
906+powerpc/transactional_memory arch/powerpc/transactional_memory
907+powerpc/ultravisor arch/powerpc/ultravisor
908+powerpc/vas-api arch/powerpc/vas-api
909+powerpc/vcpudispatch_stats arch/powerpc/vcpudispatch_stats
910+powerpc/vmemmap_dedup arch/powerpc/vmemmap_dedup
911+process/clang-format dev-tools/clang-format
912+process/magic-number staging/magic-number
913+process/unaligned-memory-access core-api/unaligned-memory-access
914+rapidio/index driver-api/rapidio/index
915+rapidio/mport_cdev driver-api/rapidio/mport_cdev
916+rapidio/rapidio driver-api/rapidio/rapidio
917+rapidio/rio_cm driver-api/rapidio/rio_cm
918+rapidio/sysfs driver-api/rapidio/sysfs
919+rapidio/tsi721 driver-api/rapidio/tsi721
920+riscv/acpi arch/riscv/acpi
921+riscv/boot arch/riscv/boot
922+riscv/boot-image-header arch/riscv/boot-image-header
923+riscv/features arch/riscv/features
924+riscv/hwprobe arch/riscv/hwprobe
925+riscv/index arch/riscv/index
926+riscv/patch-acceptance arch/riscv/patch-acceptance
927+riscv/uabi arch/riscv/uabi
928+riscv/vector arch/riscv/vector
929+riscv/vm-layout arch/riscv/vm-layout
930+s390/3270 arch/s390/3270
931+s390/cds arch/s390/cds
932+s390/common_io arch/s390/common_io
933+s390/driver-model arch/s390/driver-model
934+s390/features arch/s390/features
935+s390/index arch/s390/index
936+s390/monreader arch/s390/monreader
937+s390/pci arch/s390/pci
938+s390/qeth arch/s390/qeth
939+s390/s390dbf arch/s390/s390dbf
940+s390/text_files arch/s390/text_files
941+s390/vfio-ap arch/s390/vfio-ap
942+s390/vfio-ap-locking arch/s390/vfio-ap-locking
943+s390/vfio-ccw arch/s390/vfio-ccw
944+s390/zfcpdump arch/s390/zfcpdump
945+security/LSM security/lsm-development
946+security/LSM-sctp security/SCTP
947+serial/driver driver-api/serial/driver
948+serial/index driver-api/serial/index
949+serial/moxa-smartio driver-api/tty/moxa-smartio
950+serial/n_gsm driver-api/tty/n_gsm
951+serial/serial-iso7816 driver-api/serial/serial-iso7816
952+serial/serial-rs485 driver-api/serial/serial-rs485
953+serial/tty driver-api/tty/tty_ldisc
954+sh/booting arch/sh/booting
955+sh/features arch/sh/features
956+sh/index arch/sh/index
957+sh/new-machine arch/sh/new-machine
958+sh/register-banks arch/sh/register-banks
959+sparc/adi arch/sparc/adi
960+sparc/console arch/sparc/console
961+sparc/features arch/sparc/features
962+sparc/index arch/sparc/index
963+sparc/oradax/oracle-dax arch/sparc/oradax/oracle-dax
964+staging/kprobes trace/kprobes
965+sysctl/abi admin-guide/sysctl/abi
966+sysctl/fs admin-guide/sysctl/fs
967+sysctl/index admin-guide/sysctl/index
968+sysctl/kernel admin-guide/sysctl/kernel
969+sysctl/net admin-guide/sysctl/net
970+sysctl/sunrpc admin-guide/sysctl/sunrpc
971+sysctl/user admin-guide/sysctl/user
972+sysctl/vm admin-guide/sysctl/vm
973+thermal/cpu-cooling-api driver-api/thermal/cpu-cooling-api
974+thermal/exynos_thermal driver-api/thermal/exynos_thermal
975+thermal/exynos_thermal_emulation driver-api/thermal/exynos_thermal_emulation
976+thermal/index driver-api/thermal/index
977+thermal/intel_powerclamp admin-guide/thermal/intel_powerclamp
978+thermal/nouveau_thermal driver-api/thermal/nouveau_thermal
979+thermal/power_allocator driver-api/thermal/power_allocator
980+thermal/sysfs-api driver-api/thermal/sysfs-api
981+thermal/x86_pkg_temperature_thermal driver-api/thermal/x86_pkg_temperature_thermal
982+tpm/index security/tpm/index
983+tpm/tpm_vtpm_proxy security/tpm/tpm_vtpm_proxy
984+trace/coresight trace/coresight/coresight
985+trace/coresight-cpu-debug trace/coresight/coresight-cpu-debug
986+trace/rv/da_monitor_synthesis trace/rv/monitor_synthesis
987+translations/it_IT/admin-guide/security-bugs translations/it_IT/process/security-bugs
988+translations/it_IT/process/clang-format translations/it_IT/dev-tools/clang-format
989+translations/it_IT/process/magic-number translations/it_IT/staging/magic-number
990+translations/it_IT/riscv/patch-acceptance translations/it_IT/arch/riscv/patch-acceptance
991+translations/ja_JP/howto translations/ja_JP/process/howto
992+translations/ko_KR/howto translations/ko_KR/process/howto
993+translations/sp_SP/howto translations/sp_SP/process/howto
994+translations/sp_SP/submitting-patches translations/sp_SP/process/submitting-patches
995+translations/zh_CN/admin-guide/security-bugs translations/zh_CN/process/security-bugs
996+translations/zh_CN/arch translations/zh_CN/arch/index
997+translations/zh_CN/arm64/amu translations/zh_CN/arch/arm64/amu
998+translations/zh_CN/arm64/elf_hwcaps translations/zh_CN/arch/arm64/elf_hwcaps
999+translations/zh_CN/arm64/hugetlbpage translations/zh_CN/arch/arm64/hugetlbpage
1000+translations/zh_CN/arm64/index translations/zh_CN/arch/arm64/index
1001+translations/zh_CN/arm64/perf translations/zh_CN/arch/arm64/perf
1002+translations/zh_CN/coding-style translations/zh_CN/process/coding-style
1003+translations/zh_CN/loongarch/booting translations/zh_CN/arch/loongarch/booting
1004+translations/zh_CN/loongarch/features translations/zh_CN/arch/loongarch/features
1005+translations/zh_CN/loongarch/index translations/zh_CN/arch/loongarch/index
1006+translations/zh_CN/loongarch/introduction translations/zh_CN/arch/loongarch/introduction
1007+translations/zh_CN/loongarch/irq-chip-model translations/zh_CN/arch/loongarch/irq-chip-model
1008+translations/zh_CN/mips/booting translations/zh_CN/arch/mips/booting
1009+translations/zh_CN/mips/features translations/zh_CN/arch/mips/features
1010+translations/zh_CN/mips/index translations/zh_CN/arch/mips/index
1011+translations/zh_CN/mips/ingenic-tcu translations/zh_CN/arch/mips/ingenic-tcu
1012+translations/zh_CN/openrisc/index translations/zh_CN/arch/openrisc/index
1013+translations/zh_CN/openrisc/openrisc_port translations/zh_CN/arch/openrisc/openrisc_port
1014+translations/zh_CN/openrisc/todo translations/zh_CN/arch/openrisc/todo
1015+translations/zh_CN/parisc/debugging translations/zh_CN/arch/parisc/debugging
1016+translations/zh_CN/parisc/index translations/zh_CN/arch/parisc/index
1017+translations/zh_CN/parisc/registers translations/zh_CN/arch/parisc/registers
1018+translations/zh_CN/riscv/boot-image-header translations/zh_CN/arch/riscv/boot-image-header
1019+translations/zh_CN/riscv/index translations/zh_CN/arch/riscv/index
1020+translations/zh_CN/riscv/patch-acceptance translations/zh_CN/arch/riscv/patch-acceptance
1021+translations/zh_CN/riscv/vm-layout translations/zh_CN/arch/riscv/vm-layout
1022+translations/zh_CN/vm/active_mm translations/zh_CN/mm/active_mm
1023+translations/zh_CN/vm/balance translations/zh_CN/mm/balance
1024+translations/zh_CN/vm/damon/api translations/zh_CN/mm/damon/api
1025+translations/zh_CN/vm/damon/design translations/zh_CN/mm/damon/design
1026+translations/zh_CN/vm/damon/faq translations/zh_CN/mm/damon/faq
1027+translations/zh_CN/vm/damon/index translations/zh_CN/mm/damon/index
1028+translations/zh_CN/vm/free_page_reporting translations/zh_CN/mm/free_page_reporting
1029+translations/zh_CN/vm/highmem translations/zh_CN/mm/highmem
1030+translations/zh_CN/vm/hmm translations/zh_CN/mm/hmm
1031+translations/zh_CN/vm/hugetlbfs_reserv translations/zh_CN/mm/hugetlbfs_reserv
1032+translations/zh_CN/vm/hwpoison translations/zh_CN/mm/hwpoison
1033+translations/zh_CN/vm/index translations/zh_CN/mm/index
1034+translations/zh_CN/vm/ksm translations/zh_CN/mm/ksm
1035+translations/zh_CN/vm/memory-model translations/zh_CN/mm/memory-model
1036+translations/zh_CN/vm/mmu_notifier translations/zh_CN/mm/mmu_notifier
1037+translations/zh_CN/vm/numa translations/zh_CN/mm/numa
1038+translations/zh_CN/vm/overcommit-accounting translations/zh_CN/mm/overcommit-accounting
1039+translations/zh_CN/vm/page_frags translations/zh_CN/mm/page_frags
1040+translations/zh_CN/vm/page_owner translations/zh_CN/mm/page_owner
1041+translations/zh_CN/vm/page_table_check translations/zh_CN/mm/page_table_check
1042+translations/zh_CN/vm/remap_file_pages translations/zh_CN/mm/remap_file_pages
1043+translations/zh_CN/vm/split_page_table_lock translations/zh_CN/mm/split_page_table_lock
1044+translations/zh_CN/vm/zsmalloc translations/zh_CN/mm/zsmalloc
1045+translations/zh_TW/arm64/amu translations/zh_TW/arch/arm64/amu
1046+translations/zh_TW/arm64/elf_hwcaps translations/zh_TW/arch/arm64/elf_hwcaps
1047+translations/zh_TW/arm64/hugetlbpage translations/zh_TW/arch/arm64/hugetlbpage
1048+translations/zh_TW/arm64/index translations/zh_TW/arch/arm64/index
1049+translations/zh_TW/arm64/perf translations/zh_TW/arch/arm64/perf
1050+tty/device_drivers/oxsemi-tornado misc-devices/oxsemi-tornado
1051+tty/index driver-api/tty/index
1052+tty/n_tty driver-api/tty/n_tty
1053+tty/tty_buffer driver-api/tty/tty_buffer
1054+tty/tty_driver driver-api/tty/tty_driver
1055+tty/tty_internals driver-api/tty/tty_internals
1056+tty/tty_ldisc driver-api/tty/tty_ldisc
1057+tty/tty_port driver-api/tty/tty_port
1058+tty/tty_struct driver-api/tty/tty_struct
1059+usb/typec driver-api/usb/typec
1060+usb/usb3-debug-port driver-api/usb/usb3-debug-port
1061+userspace-api/media/drivers/st-vgxy61 userspace-api/media/drivers/vgxy61
1062+userspace-api/media/v4l/pixfmt-meta-d4xx userspace-api/media/v4l/metafmt-d4xx
1063+userspace-api/media/v4l/pixfmt-meta-intel-ipu3 userspace-api/media/v4l/metafmt-intel-ipu3
1064+userspace-api/media/v4l/pixfmt-meta-rkisp1 userspace-api/media/v4l/metafmt-rkisp1
1065+userspace-api/media/v4l/pixfmt-meta-uvc userspace-api/media/v4l/metafmt-uvc
1066+userspace-api/media/v4l/pixfmt-meta-vivid userspace-api/media/v4l/metafmt-vivid
1067+userspace-api/media/v4l/pixfmt-meta-vsp1-hgo userspace-api/media/v4l/metafmt-vsp1-hgo
1068+userspace-api/media/v4l/pixfmt-meta-vsp1-hgt userspace-api/media/v4l/metafmt-vsp1-hgt
1069+virt/coco/sevguest virt/coco/sev-guest
1070+virt/kvm/amd-memory-encryption virt/kvm/x86/amd-memory-encryption
1071+virt/kvm/arm/psci virt/kvm/arm/fw-pseudo-registers
1072+virt/kvm/cpuid virt/kvm/x86/cpuid
1073+virt/kvm/hypercalls virt/kvm/x86/hypercalls
1074+virt/kvm/mmu virt/kvm/x86/mmu
1075+virt/kvm/msr virt/kvm/x86/msr
1076+virt/kvm/nested-vmx virt/kvm/x86/nested-vmx
1077+virt/kvm/running-nested-guests virt/kvm/x86/running-nested-guests
1078+virt/kvm/s390-diag virt/kvm/s390/s390-diag
1079+virt/kvm/s390-pv virt/kvm/s390/s390-pv
1080+virt/kvm/s390-pv-boot virt/kvm/s390/s390-pv-boot
1081+virt/kvm/timekeeping virt/kvm/x86/timekeeping
1082+virt/kvm/x86/halt-polling virt/kvm/halt-polling
1083+virtual/index virt/index
1084+virtual/kvm/amd-memory-encryption virt/kvm/x86/amd-memory-encryption
1085+virtual/kvm/cpuid virt/kvm/x86/cpuid
1086+virtual/kvm/index virt/kvm/index
1087+virtual/kvm/vcpu-requests virt/kvm/vcpu-requests
1088+virtual/paravirt_ops virt/paravirt_ops
1089+vm/active_mm mm/active_mm
1090+vm/arch_pgtable_helpers mm/arch_pgtable_helpers
1091+vm/balance mm/balance
1092+vm/bootmem mm/bootmem
1093+vm/damon/api mm/damon/api
1094+vm/damon/design mm/damon/design
1095+vm/damon/faq mm/damon/faq
1096+vm/damon/index mm/damon/index
1097+vm/free_page_reporting mm/free_page_reporting
1098+vm/highmem mm/highmem
1099+vm/hmm mm/hmm
1100+vm/hugetlbfs_reserv mm/hugetlbfs_reserv
1101+vm/hugetlbpage admin-guide/mm/hugetlbpage
1102+vm/hwpoison mm/hwpoison
1103+vm/idle_page_tracking admin-guide/mm/idle_page_tracking
1104+vm/index mm/index
1105+vm/ksm mm/ksm
1106+vm/memory-model mm/memory-model
1107+vm/mmu_notifier mm/mmu_notifier
1108+vm/numa mm/numa
1109+vm/numa_memory_policy admin-guide/mm/numa_memory_policy
1110+vm/oom mm/oom
1111+vm/overcommit-accounting mm/overcommit-accounting
1112+vm/page_allocation mm/page_allocation
1113+vm/page_cache mm/page_cache
1114+vm/page_frags mm/page_frags
1115+vm/page_migration mm/page_migration
1116+vm/page_owner mm/page_owner
1117+vm/page_reclaim mm/page_reclaim
1118+vm/page_table_check mm/page_table_check
1119+vm/page_tables mm/page_tables
1120+vm/pagemap admin-guide/mm/pagemap
1121+vm/physical_memory mm/physical_memory
1122+vm/process_addrs mm/process_addrs
1123+vm/remap_file_pages mm/remap_file_pages
1124+vm/shmfs mm/shmfs
1125+vm/slab mm/slab
1126+vm/slub admin-guide/mm/slab
1127+vm/soft-dirty admin-guide/mm/soft-dirty
1128+vm/split_page_table_lock mm/split_page_table_lock
1129+vm/swap mm/swap
1130+vm/swap_numa admin-guide/mm/swap_numa
1131+vm/transhuge mm/transhuge
1132+vm/unevictable-lru mm/unevictable-lru
1133+vm/userfaultfd admin-guide/mm/userfaultfd
1134+vm/vmalloc mm/vmalloc
1135+vm/vmalloced-kernel-stacks mm/vmalloced-kernel-stacks
1136+vm/vmemmap_dedup mm/vmemmap_dedup
1137+vm/zsmalloc mm/zsmalloc
1138+vm/zswap admin-guide/mm/zswap
1139+watch_queue core-api/watch_queue
1140+x86/amd-memory-encryption arch/x86/amd-memory-encryption
1141+x86/amd_hsmp arch/x86/amd_hsmp
1142+x86/boot arch/x86/boot
1143+x86/booting-dt arch/x86/booting-dt
1144+x86/buslock arch/x86/buslock
1145+x86/cpuinfo arch/x86/cpuinfo
1146+x86/earlyprintk arch/x86/earlyprintk
1147+x86/elf_auxvec arch/x86/elf_auxvec
1148+x86/entry_64 arch/x86/entry_64
1149+x86/exception-tables arch/x86/exception-tables
1150+x86/features arch/x86/features
1151+x86/i386/IO-APIC arch/x86/i386/IO-APIC
1152+x86/i386/index arch/x86/i386/index
1153+x86/ifs arch/x86/ifs
1154+x86/index arch/x86/index
1155+x86/intel-hfi arch/x86/intel-hfi
1156+x86/intel_txt arch/x86/intel_txt
1157+x86/iommu arch/x86/iommu
1158+x86/kernel-stacks arch/x86/kernel-stacks
1159+x86/mds arch/x86/mds
1160+x86/microcode arch/x86/microcode
1161+x86/mtrr arch/x86/mtrr
1162+x86/orc-unwinder arch/x86/orc-unwinder
1163+x86/pat arch/x86/pat
1164+x86/protection-keys core-api/protection-keys
1165+x86/pti arch/x86/pti
1166+x86/resctrl filesystems/resctrl
1167+x86/resctrl_ui filesystems/resctrl
1168+x86/sgx arch/x86/sgx
1169+x86/sva arch/x86/sva
1170+x86/tdx arch/x86/tdx
1171+x86/tlb arch/x86/tlb
1172+x86/topology arch/x86/topology
1173+x86/tsx_async_abort arch/x86/tsx_async_abort
1174+x86/usb-legacy-support arch/x86/usb-legacy-support
1175+x86/x86_64/5level-paging arch/x86/x86_64/5level-paging
1176+x86/x86_64/cpu-hotplug-spec arch/x86/x86_64/cpu-hotplug-spec
1177+x86/x86_64/fake-numa-for-cpusets arch/x86/x86_64/fake-numa-for-cpusets
1178+x86/x86_64/fsgs arch/x86/x86_64/fsgs
1179+x86/x86_64/index arch/x86/x86_64/index
1180+x86/x86_64/machinecheck arch/x86/x86_64/machinecheck
1181+x86/x86_64/mm arch/x86/x86_64/mm
1182+x86/x86_64/uefi arch/x86/x86_64/uefi
1183+x86/xstate arch/x86/xstate
1184+x86/zero-page arch/x86/zero-page
1185+xilinx/eemi driver-api/xilinx/eemi
1186+xilinx/index driver-api/xilinx/index
1187+xtensa/atomctl arch/xtensa/atomctl
1188+xtensa/booting arch/xtensa/booting
1189+xtensa/features arch/xtensa/features
1190+xtensa/index arch/xtensa/index
1191+xtensa/mmu arch/xtensa/mmu
Documentation/Makefile+7−4
@@ -60,8 +60,8 @@ ifeq ($(HAVE_LATEXMK),1) · 59 unmodified lines
6060 endif #HAVE_LATEXMK
6161
6262 # Internal variables.
63−PAPEROPT_a4 = -D latex_paper_size=a4
64−PAPEROPT_letter = -D latex_paper_size=letter
63+PAPEROPT_a4 = -D latex_elements.papersize=a4paper
64+PAPEROPT_letter = -D latex_elements.papersize=letterpaper
6565 ALLSPHINXOPTS = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC)
6666 ALLSPHINXOPTS += $(PAPEROPT_$(PAPER)) $(SPHINXOPTS)
6767 ifneq ($(wildcard $(srctree)/.config),)
@@ -87,7 +87,7 @@ loop_cmd = $(echo-cmd) $(cmd_$(1)) || exit; · 19 unmodified lines
8787 PYTHONPYCACHEPREFIX ?= $(abspath $(BUILDDIR)/__pycache__)
8888
8989 quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
90− cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/userspace-api/media $2 && \
90+ cmd_sphinx = \
9191 PYTHONPYCACHEPREFIX="$(PYTHONPYCACHEPREFIX)" \
9292 BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(src)/$5/$(SPHINX_CONF)) \
9393 $(PYTHON3) $(srctree)/scripts/jobserver-exec \
@@ -108,6 +108,9 @@ htmldocs: · 14 unmodified lines
108108 @$(srctree)/scripts/sphinx-pre-install --version-check
109109 @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
110110
111+htmldocs-redirects: $(srctree)/Documentation/.renames.txt
112+ @tools/docs/gen-redirects.py --output $(BUILDDIR) < $<
113+
111114 # If Rust support is available and .config exists, add rustdoc generated contents.
112115 # If there are any, the errors from this make rustdoc will be displayed but
113116 # won't stop the execution of htmldocs
@@ -171,11 +174,11 @@ refcheckdocs: · 57 unmodified lines
171174
172175 cleandocs:
173176 $(Q)rm -rf $(BUILDDIR)
174− $(Q)$(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/userspace-api/media clean
175177
176178 dochelp:
177179 @echo ' Linux kernel internal documentation in different formats from ReST:'
178180 @echo ' htmldocs - HTML'
181+ @echo ' htmldocs-redirects - generate HTML redirects for moved pages'
179182 @echo ' texinfodocs - Texinfo'
180183 @echo ' infodocs - Info'
181184 @echo ' latexdocs - LaTeX'
Documentation/PCI/endpoint/pci-endpoint-cfs.rst+2−2
@@ -86,7 +86,7 @@ The <EPF Device> directory can have a list of symbolic links · 85 unmodified lines
8686 be created by the user to represent the virtual functions that are bound to
8787 the physical function. In the above directory structure <EPF Device 11> is a
8888 physical function and <EPF Device 31> is a virtual function. An EPF device once
89−it's linked to another EPF device, cannot be linked to a EPC device.
89+it's linked to another EPF device, cannot be linked to an EPC device.
9090
9191 EPC Device
9292 ==========
@@ -108,7 +108,7 @@ entries corresponding to EPC device will be created by the EPC core. · 15 unmodified lines
108108 The <EPC Device> directory will have a list of symbolic links to
109109 <EPF Device>. These symbolic links should be created by the user to
110110 represent the functions present in the endpoint device. Only <EPF Device>
111−that represents a physical function can be linked to a EPC device.
111+that represents a physical function can be linked to an EPC device.
112112
113113 The <EPC Device> directory will also have a *start* field. Once
114114 "1" is written to this field, the endpoint device will be ready to
Documentation/PCI/endpoint/pci-endpoint.rst+3−3
@@ -197,8 +197,8 @@ by the PCI endpoint function driver. · 196 unmodified lines
197197 * pci_epf_register_driver()
198198
199199 The PCI Endpoint Function driver should implement the following ops:
200− * bind: ops to perform when a EPC device has been bound to EPF device
201− * unbind: ops to perform when a binding has been lost between a EPC
200+ * bind: ops to perform when an EPC device has been bound to EPF device
201+ * unbind: ops to perform when a binding has been lost between an EPC
202202 device and EPF device
203203 * add_cfs: optional ops to create function specific configfs
204204 attributes
@@ -251,7 +251,7 @@ pci-ep-cfs.c can be used as reference for using these APIs. · 46 unmodified lines
251251 * pci_epf_bind()
252252
253253 pci_epf_bind() should be invoked when the EPF device has been bound to
254− a EPC device.
254+ an EPC device.
255255
256256 * pci_epf_unbind()
257257
Documentation/RCU/lockdep.rst+1−1
@@ -106,7 +106,7 @@ or the RCU-protected data that it points to can change concurrently. · 105 unmodified lines
106106 Like rcu_dereference(), when lockdep is enabled, RCU list and hlist
107107 traversal primitives check for being called from within an RCU read-side
108108 critical section. However, a lockdep expression can be passed to them
109−as a additional optional argument. With this lockdep expression, these
109+as an additional optional argument. With this lockdep expression, these
110110 traversal primitives will complain only if the lockdep expression is
111111 false and they are called from outside any RCU read-side critical section.
112112
Documentation/RCU/stallwarn.rst+1−1
@@ -119,7 +119,7 @@ warnings: · 118 unmodified lines
119119 uncommon in large datacenter. In one memorable case some decades
120120 back, a CPU failed in a running system, becoming unresponsive,
121121 but not causing an immediate crash. This resulted in a series
122− of RCU CPU stall warnings, eventually leading the realization
122+ of RCU CPU stall warnings, eventually leading to the realization
123123 that the CPU had failed.
124124
125125 The RCU, RCU-sched, RCU-tasks, and RCU-tasks-trace implementations have
Documentation/admin-guide/LSM/SafeSetID.rst+1−1
@@ -41,7 +41,7 @@ namespace). The higher level goal is to allow for uid-based sandboxing of system · 40 unmodified lines
4141 services without having to give out CAP_SETUID all over the place just so that
4242 non-root programs can drop to even-lesser-privileged uids. This is especially
4343 relevant when one non-root daemon on the system should be allowed to spawn other
44−processes as different uids, but its undesirable to give the daemon a
44+processes as different uids, but it's undesirable to give the daemon a
4545 basically-root-equivalent CAP_SETUID.
4646
4747
Documentation/admin-guide/RAS/main.rst+1−1
@@ -253,7 +253,7 @@ interface. · 252 unmodified lines
253253 Some architectures have ECC detectors for L1, L2 and L3 caches,
254254 along with DMA engines, fabric switches, main data path switches,
255255 interconnections, and various other hardware data paths. If the hardware
256−reports it, then a edac_device device probably can be constructed to
256+reports it, then an edac_device device probably can be constructed to
257257 harvest and present that to userspace.
258258
259259
Documentation/admin-guide/aoe/udev.txt+3−3
@@ -2,7 +2,7 @@ · 1 unmodified line
22 # They may be installed along the following lines. Check the section
33 # 8 udev manpage to see whether your udev supports SUBSYSTEM, and
44 # whether it uses one or two equal signs for SUBSYSTEM and KERNEL.
5−#
5+#
66 # ecashin@makki ~$ su
77 # Password:
88 # bash# find /etc -type f -name udev.conf
@@ -13,7 +13,7 @@ · 4 unmodified lines
1313 # 10-wacom.rules 50-udev.rules
1414 # bash# cp /path/to/linux/Documentation/admin-guide/aoe/udev.txt \
1515 # /etc/udev/rules.d/60-aoe.rules
16−#
16+#
1717
1818 # aoe char devices
1919 SUBSYSTEM=="aoe", KERNEL=="discover", NAME="etherd/%k", GROUP="disk", MODE="0220"
@@ -22,5 +22,5 @@ SUBSYSTEM=="aoe", KERNEL=="interfaces", NAME="etherd/%k", GROUP="disk", MODE="02 · 2 unmodified lines
2222 SUBSYSTEM=="aoe", KERNEL=="revalidate", NAME="etherd/%k", GROUP="disk", MODE="0220"
2323 SUBSYSTEM=="aoe", KERNEL=="flush", NAME="etherd/%k", GROUP="disk", MODE="0220"
2424
25−# aoe block devices
25+# aoe block devices
2626 KERNEL=="etherd*", GROUP="disk"
Documentation/admin-guide/blockdev/paride.rst+1−1
@@ -118,7 +118,7 @@ and high-level drivers that you would use: · 117 unmodified lines
118118 ================ ============ ========
119119
120120 All parports and all protocol drivers are probed automatically unless probe=0
121−parameter is used. So just "modprobe epat" is enough for a Imation SuperDisk
121+parameter is used. So just "modprobe epat" is enough for an Imation SuperDisk
122122 drive to work.
123123
124124 Manual device creation::
Documentation/admin-guide/device-mapper/vdo-design.rst+1−1
@@ -600,7 +600,7 @@ lock and return itself to the pool. · 599 unmodified lines
600600 All storage within vdo is managed as 4KB blocks, but it can accept writes
601601 as small as 512 bytes. Processing a write that is smaller than 4K requires
602602 a read-modify-write operation that reads the relevant 4K block, copies the
603−new data over the approriate sectors of the block, and then launches a
603+new data over the appropriate sectors of the block, and then launches a
604604 write operation for the modified data block. The read and write stages of
605605 this operation are nearly identical to the normal read and write
606606 operations, and a single data_vio is used throughout this operation.
Documentation/admin-guide/ext4.rst+1−1
@@ -398,7 +398,7 @@ There are 3 different data modes: · 397 unmodified lines
398398 * writeback mode
399399
400400 In data=writeback mode, ext4 does not journal data at all. This mode provides
401− a similar level of journaling as that of XFS, JFS, and ReiserFS in its default
401+ a similar level of journaling as that of XFS and JFS in its default
402402 mode - metadata journaling. A crash+recovery can cause incorrect data to
403403 appear in files which were written shortly before the crash. This mode will
404404 typically provide the best ext4 performance.
Documentation/admin-guide/hw-vuln/mds.rst+1−1
@@ -214,7 +214,7 @@ XEON PHI specific considerations · 213 unmodified lines
214214 command line with the 'ring3mwait=disable' command line option.
215215
216216 XEON PHI is not affected by the other MDS variants and MSBDS is mitigated
217− before the CPU enters a idle state. As XEON PHI is not affected by L1TF
217+ before the CPU enters an idle state. As XEON PHI is not affected by L1TF
218218 either disabling SMT is not required for full protection.
219219
220220 .. _mds_smt_control:
Documentation/admin-guide/hw-vuln/spectre.rst+3−3
@@ -664,7 +664,7 @@ Intel white papers: · 663 unmodified lines
664664
665665 .. _spec_ref1:
666666
667−[1] `Intel analysis of speculative execution side channels <https://newsroom.intel.com/wp-content/uploads/sites/11/2018/01/Intel-Analysis-of-Speculative-Execution-Side-Channels.pdf>`_.
667+[1] `Intel analysis of speculative execution side channels <https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/analysis-of-speculative-execution-side-channels-white-paper.pdf>`_.
668668
669669 .. _spec_ref2:
670670
@@ -682,7 +682,7 @@ AMD white papers: · 11 unmodified lines
682682
683683 .. _spec_ref5:
684684
685−[5] `AMD64 technology indirect branch control extension <https://developer.amd.com/wp-content/resources/Architecture_Guidelines_Update_Indirect_Branch_Control.pdf>`_.
685+[5] `AMD64 technology indirect branch control extension <https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/white-papers/111006-architecture-guidelines-update-amd64-technology-indirect-branch-control-extension.pdf>`_.
686686
687687 .. _spec_ref6:
688688
@@ -708,7 +708,7 @@ MIPS white paper: · 19 unmodified lines
708708
709709 .. _spec_ref10:
710710
711−[10] `MIPS: response on speculative execution and side channel vulnerabilities <https://www.mips.com/blog/mips-response-on-speculative-execution-and-side-channel-vulnerabilities/>`_.
711+[10] `MIPS: response on speculative execution and side channel vulnerabilities <https://web.archive.org/web/20220512003005if_/https://www.mips.com/blog/mips-response-on-speculative-execution-and-side-channel-vulnerabilities/>`_.
712712
713713 Academic papers:
714714
Documentation/admin-guide/kdump/kdump.rst+1−1
@@ -471,7 +471,7 @@ Notes on loading the dump-capture kernel: · 470 unmodified lines
471471 performance degradation. To enable multi-cpu support, you should bring up an
472472 SMP dump-capture kernel and specify maxcpus/nr_cpus options while loading it.
473473
474−* For s390x there are two kdump modes: If a ELF header is specified with
474+* For s390x there are two kdump modes: If an ELF header is specified with
475475 the elfcorehdr= kernel parameter, it is used by the kdump kernel as it
476476 is done on all other architectures. If no elfcorehdr= kernel parameter is
477477 specified, the s390x kdump kernel dynamically creates the header. The
Documentation/admin-guide/kernel-parameters.rst+3−1
@@ -1,3 +1,5 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
13 .. _kernelparameters:
24
35 The kernel's command-line parameters
@@ -213,7 +215,7 @@ need or coordination with <Documentation/arch/x86/boot.rst>. · 209 unmodified lines
213215 There are also arch-specific kernel-parameters not documented here.
214216
215217 Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
216−a trailing = on the name of any parameter states that that parameter will
218+a trailing = on the name of any parameter states that the parameter will
217219 be entered as an environment variable, whereas its absence indicates that
218220 it will appear as a kernel argument readable via /proc/cmdline by programs
219221 running once the system is up.
Documentation/admin-guide/kernel-parameters.txt+6−6
@@ -3705,7 +3705,7 @@ · 3704 unmodified lines
37053705 looking for corruption. Enabling this will
37063706 both detect corruption and prevent the kernel
37073707 from using the memory being corrupted.
3708− However, its intended as a diagnostic tool; if
3708+ However, it's intended as a diagnostic tool; if
37093709 repeatable BIOS-originated corruption always
37103710 affects the same memory, you can use memmap=
37113711 to prevent the kernel from using that memory.
@@ -7400,7 +7400,7 @@ · 3688 unmodified lines
74007400 (converted into nanoseconds). Fast, but
74017401 depending on the architecture, may not be
74027402 in sync between CPUs.
7403− global - Event time stamps are synchronize across
7403+ global - Event time stamps are synchronized across
74047404 CPUs. May be slower than the local clock,
74057405 but better for some race conditions.
74067406 counter - Simple counting of events (1, 2, ..)
@@ -7520,12 +7520,12 @@ · 113 unmodified lines
75207520 section.
75217521
75227522 trace_trigger=[trigger-list]
7523− [FTRACE] Add a event trigger on specific events.
7523+ [FTRACE] Add an event trigger on specific events.
75247524 Set a trigger on top of a specific event, with an optional
75257525 filter.
75267526
7527− The format is is "trace_trigger=<event>.<trigger>[ if <filter>],..."
7528− Where more than one trigger may be specified that are comma deliminated.
7527+ The format is "trace_trigger=<event>.<trigger>[ if <filter>],..."
7528+ Where more than one trigger may be specified that are comma delimited.
75297529
75307530 For example:
75317531
@@ -7533,7 +7533,7 @@ · 1 unmodified line
75337533
75347534 The above will enable the "stacktrace" trigger on the "sched_switch"
75357535 event but only trigger it if the "prev_state" of the "sched_switch"
7536− event is "2" (TASK_UNINTERUPTIBLE).
7536+ event is "2" (TASK_UNINTERRUPTIBLE).
75377537
75387538 See also "Event triggers" in Documentation/trace/events.rst
75397539
Documentation/admin-guide/laptops/laptop-mode.rst+4−4
@@ -61,7 +61,7 @@ Caveats · 60 unmodified lines
6161 Check your drive's rating, and don't wear down your drive's lifetime if you
6262 don't need to.
6363
64−* If you mount some of your ext3/reiserfs filesystems with the -n option, then
64+* If you mount some of your ext3 filesystems with the -n option, then
6565 the control script will not be able to remount them correctly. You must set
6666 DO_REMOUNTS=0 in the control script, otherwise it will remount them with the
6767 wrong options -- or it will fail because it cannot write to /etc/mtab.
@@ -96,7 +96,7 @@ control script increases dirty_expire_centisecs and dirty_writeback_centisecs in · 28 unmodified lines
9696 dirtied are not forced to be written to disk as often. The control script also
9797 changes the dirty background ratio, so that background writeback of dirty pages
9898 is not done anymore. Combined with a higher commit value (also 10 minutes) for
99−ext3 or ReiserFS filesystems (also done automatically by the control script),
99+ext3 filesystem (also done automatically by the control script),
100100 this results in concentration of disk activity in a small time interval which
101101 occurs only once every 10 minutes, or whenever the disk is forced to spin up by
102102 a cache miss. The disk can then be spun down in the periods of inactivity.
@@ -587,7 +587,7 @@ Control script:: · 484 unmodified lines
587587 FST=$(deduce_fstype $MP)
588588 fi
589589 case "$FST" in
590− "ext3"|"reiserfs")
590+ "ext3")
591591 PARSEDOPTS="$(parse_mount_opts commit "$OPTS")"
592592 mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE$NOATIME_OPT
593593 ;;
@@ -647,7 +647,7 @@ Control script:: · 53 unmodified lines
647647 FST=$(deduce_fstype $MP)
648648 fi
649649 case "$FST" in
650− "ext3"|"reiserfs")
650+ "ext3")
651651 PARSEDOPTS="$(parse_mount_opts_wfstab $DEV commit $OPTS)"
652652 PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $PARSEDOPTS)"
653653 mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
Documentation/admin-guide/laptops/sonypi.rst+1−1
@@ -25,7 +25,7 @@ generate, like: · 24 unmodified lines
2525 (when available)
2626
2727 Those events (see linux/sonypi.h) can be polled using the character device node
28−/dev/sonypi (major 10, minor auto allocated or specified as a option).
28+/dev/sonypi (major 10, minor auto allocated or specified as an option).
2929 A simple daemon which translates the jogdial movements into mouse wheel events
3030 can be downloaded at: <http://popies.net/sonypi/>
3131
Documentation/admin-guide/md.rst+1−1
@@ -794,7 +794,7 @@ These currently include: · 793 unmodified lines
794794
795795 journal_mode (currently raid5 only)
796796 The cache mode for raid5. raid5 could include an extra disk for
797− caching. The mode can be "write-throuth" and "write-back". The
797+ caching. The mode can be "write-through" or "write-back". The
798798 default is "write-through".
799799
800800 ppl_write_hint
Documentation/admin-guide/media/imx.rst+1−1
@@ -96,7 +96,7 @@ Some of the features of this driver include: · 95 unmodified lines
9696 motion compensation modes: low, medium, and high motion. Pipelines are
9797 defined that allow sending frames to the VDIC subdev directly from the
9898 CSI. There is also support in the future for sending frames to the
99− VDIC from memory buffers via a output/mem2mem devices.
99+ VDIC from memory buffers via output/mem2mem devices.
100100
101101 - Includes a Frame Interval Monitor (FIM) that can correct vertical sync
102102 problems with the ADV718x video decoders.
Documentation/admin-guide/media/si4713.rst+3−3
@@ -13,7 +13,7 @@ Contact: Eduardo Valentin <eduardo.valentin@nokia.com> · 12 unmodified lines
1313 Information about the Device
1414 ----------------------------
1515
16−This chip is a Silicon Labs product. It is a I2C device, currently on 0x63 address.
16+This chip is a Silicon Labs product. It is an I2C device, currently on 0x63 address.
1717 Basically, it has transmission and signal noise level measurement features.
1818
1919 The Si4713 integrates transmit functions for FM broadcast stereo transmission.
@@ -28,7 +28,7 @@ Users must comply with local regulations on radio frequency (RF) transmission. · 8 unmodified lines
2828 Device driver description
2929 -------------------------
3030
31−There are two modules to handle this device. One is a I2C device driver
31+There are two modules to handle this device. One is an I2C device driver
3232 and the other is a platform driver.
3333
3434 The I2C device driver exports a v4l2-subdev interface to the kernel.
@@ -113,7 +113,7 @@ Here is a summary of them: · 78 unmodified lines
113113 - acomp_attack_time - Sets the attack time for audio dynamic range control.
114114 - acomp_release_time - Sets the release time for audio dynamic range control.
115115
116−* Limiter setups audio deviation limiter feature. Once a over deviation occurs,
116+* Limiter sets up the audio deviation limiter feature. Once an over deviation occurs,
117117 it is possible to adjust the front-end gain of the audio input and always
118118 prevent over deviation.
119119
Documentation/admin-guide/mm/damon/usage.rst+1−1
@@ -360,7 +360,7 @@ The directory for the :ref:`quotas <damon_design_damos_quotas>` of the given · 359 unmodified lines
360360 DAMON-based operation scheme.
361361
362362 Under ``quotas`` directory, four files (``ms``, ``bytes``,
363−``reset_interval_ms``, ``effective_bytes``) and two directores (``weights`` and
363+``reset_interval_ms``, ``effective_bytes``) and two directories (``weights`` and
364364 ``goals``) exist.
365365
366366 You can set the ``time quota`` in milliseconds, ``size quota`` in bytes, and
Documentation/admin-guide/nfs/nfsroot.rst+1−1
@@ -342,7 +342,7 @@ They depend on various facilities being available: · 341 unmodified lines
342342 When using pxelinux, the kernel image is specified using
343343 "kernel <relative-path-below /tftpboot>". The nfsroot parameters
344344 are passed to the kernel by adding them to the "append" line.
345− It is common to use serial console in conjunction with pxeliunx,
345+ It is common to use serial console in conjunction with pxelinux,
346346 see Documentation/admin-guide/serial-console.rst for more information.
347347
348348 For more information on isolinux, including how to create bootdisks
Documentation/admin-guide/perf/hisi-pmu.rst+2−2
@@ -110,8 +110,8 @@ uring channel. It is 2 bits. Some important codes are as follows: · 109 unmodified lines
110110 - 2'b11: count the events which sent to the uring_ext (MATA) channel;
111111 - 2'b01: is the same as 2'b11;
112112 - 2'b10: count the events which sent to the uring (non-MATA) channel;
113−- 2'b00: default value, count the events which sent to the both uring and
114− uring_ext channel;
113+- 2'b00: default value, count the events which sent to both uring and
114+ uring_ext channels;
115115
116116 6. ch: NoC PMU supports filtering the event counts of certain transaction
117117 channel with this option. The current supported channels are as follows:
Documentation/admin-guide/quickly-build-trimmed-linux.rst+2−2
@@ -273,7 +273,7 @@ again. · 272 unmodified lines
273273 does nothing at all; in that case you have to manually install your kernel,
274274 as outlined in the reference section.
275275
276− If you are running a immutable Linux distribution, check its documentation
276+ If you are running an immutable Linux distribution, check its documentation
277277 and the web to find out how to install your own kernel there.
278278
279279 [:ref:`details<install>`]
@@ -884,7 +884,7 @@ When a build error occurs, it might be caused by some aspect of your machine's · 604 unmodified lines
884884 setup that often can be fixed quickly; other times though the problem lies in
885885 the code and can only be fixed by a developer. A close examination of the
886886 failure messages coupled with some research on the internet will often tell you
887−which of the two it is. To perform such a investigation, restart the build
887+which of the two it is. To perform such an investigation, restart the build
888888 process like this::
889889
890890 make V=1
Documentation/admin-guide/reporting-issues.rst+2−2
@@ -611,7 +611,7 @@ better place. · 610 unmodified lines
611611
612612 How to read the MAINTAINERS file
613613 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
614−To illustrate how to use the :ref:`MAINTAINERS <maintainers>` file, lets assume
614+To illustrate how to use the :ref:`MAINTAINERS <maintainers>` file, let's assume
615615 the WiFi in your Laptop suddenly misbehaves after updating the kernel. In that
616616 case it's likely an issue in the WiFi driver. Obviously it could also be some
617617 code it builds upon, but unless you suspect something like that stick to the
@@ -1543,7 +1543,7 @@ as well, because that will speed things up. · 925 unmodified lines
15431543
15441544 And note, it helps developers a great deal if you can specify the exact version
15451545 that introduced the problem. Hence if possible within a reasonable time frame,
1546−try to find that version using vanilla kernels. Lets assume something broke when
1546+try to find that version using vanilla kernels. Let's assume something broke when
15471547 your distributor released a update from Linux kernel 5.10.5 to 5.10.8. Then as
15481548 instructed above go and check the latest kernel from that version line, say
15491549 5.10.9. If it shows the problem, try a vanilla 5.10.5 to ensure that no patches
Documentation/admin-guide/sysctl/fs.rst+2−2
@@ -164,8 +164,8 @@ pipe-user-pages-soft · 163 unmodified lines
164164 --------------------
165165
166166 Maximum total number of pages a non-privileged user may allocate for pipes
167−before the pipe size gets limited to a single page. Once this limit is reached,
168−new pipes will be limited to a single page in size for this user in order to
167+before the pipe size gets limited to two pages. Once this limit is reached,
168+new pipes will be limited to two pages in size for this user in order to
169169 limit total memory usage, and trying to increase them using ``fcntl()`` will be
170170 denied until usage goes below the limit again. The default value allows to
171171 allocate up to 1024 pipes at their default size. When set to 0, no limit is
Documentation/admin-guide/sysctl/index.rst+12−6
@@ -66,25 +66,31 @@ This documentation is about: · 65 unmodified lines
6666
6767 =============== ===============================================================
6868 abi/ execution domains & personalities
69−debug/ <empty>
70−dev/ device specific information (eg dev/cdrom/info)
69+<$ARCH> tuning controls for various CPU architecture (e.g. csky, s390)
70+crypto/ <undocumented>
71+debug/ <undocumented>
72+dev/ device specific information (e.g. dev/cdrom/info)
7173 fs/ specific filesystems
7274 filehandle, inode, dentry and quota tuning
7375 binfmt_misc <Documentation/admin-guide/binfmt-misc.rst>
7476 kernel/ global kernel info / tuning
7577 miscellaneous stuff
78+ some architecture-specific controls
79+ security (LSM) stuff
7680 net/ networking stuff, for documentation look in:
7781 <Documentation/networking/>
7882 proc/ <empty>
7983 sunrpc/ SUN Remote Procedure Call (NFS)
84+user/ Per user namespace limits
8085 vm/ memory management tuning
8186 buffer and cache management
82−user/ Per user per user namespace limits
87+xen/ <undocumented>
8388 =============== ===============================================================
8489
85−These are the subdirs I have on my system. There might be more
86−or other subdirs in another setup. If you see another dir, I'd
87−really like to hear about it :-)
90+These are the subdirs I have on my system or have been discovered by
91+searching through the source code. There might be more or other subdirs
92+in another setup. If you see another dir, I'd really like to hear about
93+it :-)
8894
8995 .. toctree::
9096 :maxdepth: 1
Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst+1−1
@@ -1757,7 +1757,7 @@ or all of these tasks: · 1756 unmodified lines
17571757 to your bootloader's configuration.
17581758
17591759 You have to take care of some or all of the tasks yourself, if your
1760−distribution lacks a installkernel script or does only handle part of them.
1760+distribution lacks an installkernel script or does only handle part of them.
17611761 Consult the distribution's documentation for details. If in doubt, install the
17621762 kernel manually::
17631763
Documentation/arch/arm/stm32/stm32f746-overview.rst+1−1
@@ -15,7 +15,7 @@ It features: · 14 unmodified lines
1515 - SD/MMC/SDIO support
1616 - Ethernet controller
1717 - USB OTFG FS & HS controllers
18−- I2C, SPI, CAN busses support
18+- I2C, SPI, CAN buses support
1919 - Several 16 & 32 bits general purpose timers
2020 - Serial Audio interface
2121 - LCD controller
Documentation/arch/arm/stm32/stm32f769-overview.rst+1−1
@@ -15,7 +15,7 @@ It features: · 14 unmodified lines
1515 - SD/MMC/SDIO support*2
1616 - Ethernet controller
1717 - USB OTFG FS & HS controllers
18−- I2C*4, SPI*6, CAN*3 busses support
18+- I2C*4, SPI*6, CAN*3 buses support
1919 - Several 16 & 32 bits general purpose timers
2020 - Serial Audio interface*2
2121 - LCD controller
Documentation/arch/arm/stm32/stm32h743-overview.rst+1−1
@@ -15,7 +15,7 @@ It features: · 14 unmodified lines
1515 - SD/MMC/SDIO support
1616 - Ethernet controller
1717 - USB OTFG FS & HS controllers
18−- I2C, SPI, CAN busses support
18+- I2C, SPI, CAN buses support
1919 - Several 16 & 32 bits general purpose timers
2020 - Serial Audio interface
2121 - LCD controller
Documentation/arch/arm/stm32/stm32h750-overview.rst+1−1
@@ -15,7 +15,7 @@ It features: · 14 unmodified lines
1515 - SD/MMC/SDIO support
1616 - Ethernet controller
1717 - USB OTFG FS & HS controllers
18−- I2C, SPI, CAN busses support
18+- I2C, SPI, CAN buses support
1919 - Several 16 & 32 bits general purpose timers
2020 - Serial Audio interface
2121 - LCD controller
Documentation/arch/arm/stm32/stm32mp13-overview.rst+1−1
@@ -24,7 +24,7 @@ More details: · 23 unmodified lines
2424 - ADC/DAC
2525 - USB EHCI/OHCI controllers
2626 - USB OTG
27−- I2C, SPI, CAN busses support
27+- I2C, SPI, CAN buses support
2828 - Several general purpose timers
2929 - Serial Audio interface
3030 - LCD controller
Documentation/arch/arm/stm32/stm32mp151-overview.rst+1−1
@@ -23,7 +23,7 @@ More details: · 22 unmodified lines
2323 - ADC/DAC
2424 - USB EHCI/OHCI controllers
2525 - USB OTG
26−- I2C, SPI busses support
26+- I2C, SPI buses support
2727 - Several general purpose timers
2828 - Serial Audio interface
2929 - LCD-TFT controller
Documentation/arch/loongarch/irq-chip-model.rst+2−2
@@ -139,13 +139,13 @@ Feature EXTIOI_HAS_INT_ENCODE is part of standard EIOINTC. If it is 1, it · 138 unmodified lines
139139 indicates that CPU Interrupt Pin selection can be normal method rather than
140140 bitmap method, so interrupt can be routed to IP0 - IP15.
141141
142−Feature EXTIOI_HAS_CPU_ENCODE is entension of V-EIOINTC. If it is 1, it
142+Feature EXTIOI_HAS_CPU_ENCODE is extension of V-EIOINTC. If it is 1, it
143143 indicates that CPU selection can be normal method rather than bitmap method,
144144 so interrupt can be routed to CPU0 - CPU255.
145145
146146 EXTIOI_VIRT_CONFIG
147147 ------------------
148−This register is read-write register, for compatibility intterupt routed uses
148+This register is read-write register, for compatibility interrupt routed uses
149149 the default method which is the same with standard EIOINTC. If the bit is set
150150 with 1, it indicated HW to use normal method rather than bitmap method.
151151
Documentation/arch/powerpc/eeh-pci-error-recovery.rst+0−1
@@ -315,7 +315,6 @@ network daemons and file systems that didn't need to be disturbed. · 314 unmodified lines
315315 ideally, the reset should happen at or below the block layer,
316316 so that the file systems are not disturbed.
317317
318− Reiserfs does not tolerate errors returned from the block device.
319318 Ext3fs seems to be tolerant, retrying reads/writes until it does
320319 succeed. Both have been only lightly tested in this scenario.
321320
Documentation/arch/x86/cpuinfo.rst+1−1
@@ -11,7 +11,7 @@ The list of feature flags in /proc/cpuinfo is not complete and · 10 unmodified lines
1111 represents an ill-fated attempt from long time ago to put feature flags
1212 in an easy to find place for userspace.
1313
14−However, the amount of feature flags is growing by the CPU generation,
14+However, the number of feature flags is growing with each CPU generation,
1515 leading to unparseable and unwieldy /proc/cpuinfo.
1616
1717 What is more, those feature flags do not even need to be in that file
Documentation/conf.py+61−45
@@ -9,6 +9,8 @@ import os · 8 unmodified lines
99 import shutil
1010 import sys
1111
12+from textwrap import dedent
13+
1214 import sphinx
1315
1416 # If extensions (or modules to document with autodoc) are in another directory,
@@ -51,11 +53,13 @@ else: · 36 unmodified lines
5153 dyn_exclude_patterns.append("devicetree/bindings/**.yaml")
5254 dyn_exclude_patterns.append("core-api/kho/bindings/**.yaml")
5355
54−# Properly handle include/exclude patterns
55−# ----------------------------------------
56+# Properly handle directory patterns and LaTeX docs
57+# -------------------------------------------------
5658
57−def update_patterns(app, config):
59+def config_init(app, config):
5860 """
61+ Initialize path-dependent variabled
62+
5963 On Sphinx, all directories are relative to what it is passed as
6064 SOURCEDIR parameter for sphinx-build. Due to that, all patterns
6165 that have directory names on it need to be dynamically set, after
@@ -86,6 +90,38 @@ def update_patterns(app, config): · 24 unmodified lines
8690
8791 config.exclude_patterns.append(rel_path)
8892
93+ # LaTeX and PDF output require a list of documents with are dependent
94+ # of the app.srcdir. Add them here
95+
96+ # When SPHINXDIRS is used, we just need to get index.rst, if it exists
97+ if not os.path.samefile(doctree, app.srcdir):
98+ doc = os.path.basename(app.srcdir)
99+ fname = "index"
100+ if os.path.exists(os.path.join(app.srcdir, fname + ".rst")):
101+ latex_documents.append((fname, doc + ".tex",
102+ "Linux %s Documentation" % doc.capitalize(),
103+ "The kernel development community",
104+ "manual"))
105+ return
106+
107+ # When building all docs, or when a main index.rst doesn't exist, seek
108+ # for it on subdirectories
109+ for doc in os.listdir(app.srcdir):
110+ fname = os.path.join(doc, "index")
111+ if not os.path.exists(os.path.join(app.srcdir, fname + ".rst")):
112+ continue
113+
114+ has = False
115+ for l in latex_documents:
116+ if l[0] == fname:
117+ has = True
118+ break
119+
120+ if not has:
121+ latex_documents.append((fname, doc + ".tex",
122+ "Linux %s Documentation" % doc.capitalize(),
123+ "The kernel development community",
124+ "manual"))
89125
90126 # helper
91127 # ------
@@ -234,7 +270,7 @@ author = "The kernel development community" · 142 unmodified lines
234270 # |version| and |release|, also used in various other places throughout the
235271 # built documents.
236272 #
237−# In a normal build, version and release are are set to KERNELVERSION and
273+# In a normal build, version and release are set to KERNELVERSION and
238274 # KERNELRELEASE, respectively, from the Makefile via Sphinx command line
239275 # arguments.
240276 #
@@ -420,19 +456,25 @@ htmlhelp_basename = "TheLinuxKerneldoc" · 179 unmodified lines
420456 latex_elements = {
421457 # The paper size ('letterpaper' or 'a4paper').
422458 "papersize": "a4paper",
459+ "passoptionstopackages": dedent(r"""
460+ \PassOptionsToPackage{svgnames}{xcolor}
461+ """),
423462 # The font size ('10pt', '11pt' or '12pt').
424463 "pointsize": "11pt",
464+ # Needed to generate a .ind file
465+ "printindex": r"\footnotesize\raggedright\printindex",
425466 # Latex figure (float) alignment
426467 # 'figure_align': 'htbp',
427468 # Don't mangle with UTF-8 chars
469+ "fontenc": "",
428470 "inputenc": "",
429471 "utf8extra": "",
430472 # Set document margins
431− "sphinxsetup": """
473+ "sphinxsetup": dedent(r"""
432474 hmargin=0.5in, vmargin=1in,
433475 parsedliteralwraps=true,
434476 verbatimhintsturnover=false,
435− """,
477+ """),
436478 #
437479 # Some of our authors are fond of deep nesting; tell latex to
438480 # cope.
@@ -440,48 +482,22 @@ latex_elements = { · 1 unmodified line
440482 "maxlistdepth": "10",
441483 # For CJK One-half spacing, need to be in front of hyperref
442484 "extrapackages": r"\usepackage{setspace}",
443− # Additional stuff for the LaTeX preamble.
444− "preamble": """
445− % Use some font with UTF-8 support with XeLaTeX
446− \\usepackage{fontspec}
447− \\setsansfont{DejaVu Sans}
448− \\setromanfont{DejaVu Serif}
449− \\setmonofont{DejaVu Sans Mono}
450− """,
451−}
452−
453−# Load kerneldoc specific LaTeX settings
454−latex_elements["preamble"] += """
485+ "fontpkg": dedent(r"""
486+ \usepackage{fontspec}
487+ \setmainfont{DejaVu Serif}
488+ \setsansfont{DejaVu Sans}
489+ \setmonofont{DejaVu Sans Mono}
490+ \newfontfamily\headingfont{DejaVu Serif}
491+ """),
492+ "preamble": dedent(r"""
455493 % Load kerneldoc specific LaTeX settings
456− \\input{kerneldoc-preamble.sty}
457−"""
494+ \input{kerneldoc-preamble.sty}
495+ """)
496+}
458497
459−# Grouping the document tree into LaTeX files. List of tuples
460−# (source start file, target name, title,
461−# author, documentclass [howto, manual, or own class]).
462−# Sorted in alphabetical order
498+# This will be filled up by config-inited event
463499 latex_documents = []
464500
465−# Add all other index files from Documentation/ subdirectories
466−for fn in os.listdir("."):
467− doc = os.path.join(fn, "index")
468− if os.path.exists(doc + ".rst"):
469− has = False
470− for l in latex_documents:
471− if l[0] == doc:
472− has = True
473− break
474− if not has:
475− latex_documents.append(
476− (
477− doc,
478− fn + ".tex",
479− "Linux %s Documentation" % fn.capitalize(),
480− "The kernel development community",
481− "manual",
482− )
483− )
484−
485501 # The name of an image file (relative to this directory) to place at the top of
486502 # the title page.
487503 # latex_logo = None
@@ -577,4 +593,4 @@ loadConfig(globals()) · 89 unmodified lines
577593 def setup(app):
578594 """Patterns need to be updated at init time on older Sphinx versions"""
579595
580− app.connect('config-inited', update_patterns)
596+ app.connect('config-inited', config_init)
Documentation/core-api/folio_queue.rst+1−1
@@ -44,7 +44,7 @@ Each segment in the list also stores: · 43 unmodified lines
4444 * the size of each folio and
4545 * three 1-bit marks per folio,
4646
47−but hese should not be accessed directly as the underlying data structure may
47+but these should not be accessed directly as the underlying data structure may
4848 change, but rather the access functions outlined below should be used.
4949
5050 The facility can be made accessible by::
Documentation/core-api/index.rst+1−0
@@ -24,6 +24,7 @@ it. · 23 unmodified lines
2424 printk-index
2525 symbol-namespaces
2626 asm-annotations
27+ real-time/index
2728
2829 Data structures and low-level utilities
2930 =======================================
Documentation/core-api/irq/irq-affinity.rst+3−3
@@ -9,9 +9,9 @@ ChangeLog: · 8 unmodified lines
99
1010 /proc/irq/IRQ#/smp_affinity and /proc/irq/IRQ#/smp_affinity_list specify
1111 which target CPUs are permitted for a given IRQ source. It's a bitmask
12−(smp_affinity) or cpu list (smp_affinity_list) of allowed CPUs. It's not
12+(smp_affinity) or CPU list (smp_affinity_list) of allowed CPUs. It's not
1313 allowed to turn off all CPUs, and if an IRQ controller does not support
14−IRQ affinity then the value will not change from the default of all cpus.
14+IRQ affinity then the value will not change from the default of all CPUs.
1515
1616 /proc/irq/default_smp_affinity specifies default affinity mask that applies
1717 to all non-active IRQs. Once IRQ is allocated/activated its affinity bitmask
@@ -60,7 +60,7 @@ Now lets restrict that IRQ to CPU(4-7). · 42 unmodified lines
6060 This time around IRQ44 was delivered only to the last four processors.
6161 i.e counters for the CPU0-3 did not change.
6262
63−Here is an example of limiting that same irq (44) to cpus 1024 to 1031::
63+Here is an example of limiting that same IRQ (44) to CPUs 1024 to 1031::
6464
6565 [root@moon 44]# echo 1024-1031 > smp_affinity_list
6666 [root@moon 44]# cat smp_affinity_list
Documentation/core-api/irq/irq-domain.rst+19−19
@@ -18,8 +18,8 @@ handlers as irqchips. I.e. in effect cascading interrupt controllers. · 17 unmodified lines
1818 So in the past, IRQ numbers could be chosen so that they match the
1919 hardware IRQ line into the root interrupt controller (i.e. the
2020 component actually firing the interrupt line to the CPU). Nowadays,
21−this number is just a number and the number loose all kind of
22−correspondence to hardware interrupt numbers.
21+this number is just a number and the number has no
22+relationship to hardware interrupt numbers.
2323
2424 For this reason, we need a mechanism to separate controller-local
2525 interrupt numbers, called hardware IRQs, from Linux IRQ numbers.
@@ -77,15 +77,15 @@ Once a mapping has been established, it can be retrieved or used via a · 51 unmodified lines
7777 variety of methods:
7878
7979 - irq_resolve_mapping() returns a pointer to the irq_desc structure
80− for a given domain and hwirq number, and NULL if there was no
80+ for a given domain and hwirq number, or NULL if there was no
8181 mapping.
8282 - irq_find_mapping() returns a Linux IRQ number for a given domain and
83− hwirq number, and 0 if there was no mapping
83+ hwirq number, or 0 if there was no mapping
8484 - generic_handle_domain_irq() handles an interrupt described by a
8585 domain and a hwirq number
8686
87−Note that irq domain lookups must happen in contexts that are
88−compatible with a RCU read-side critical section.
87+Note that irq_domain lookups must happen in contexts that are
88+compatible with an RCU read-side critical section.
8989
9090 The irq_create_mapping() function must be called *at least once*
9191 before any call to irq_find_mapping(), lest the descriptor will not
@@ -100,7 +100,7 @@ Types of irq_domain Mappings · 8 unmodified lines
100100 ============================
101101
102102 There are several mechanisms available for reverse mapping from hwirq
103−to Linux irq, and each mechanism uses a different allocation function.
103+to Linux IRQ, and each mechanism uses a different allocation function.
104104 Which reverse map type should be used depends on the use case. Each
105105 of the reverse map types are described below:
106106
@@ -111,13 +111,13 @@ Linear · 4 unmodified lines
111111
112112 irq_domain_create_linear()
113113
114−The linear reverse map maintains a fixed size table indexed by the
114+The linear reverse map maintains a fixed-size table indexed by the
115115 hwirq number. When a hwirq is mapped, an irq_desc is allocated for
116116 the hwirq, and the IRQ number is stored in the table.
117117
118118 The Linear map is a good choice when the maximum number of hwirqs is
119119 fixed and a relatively small number (~ < 256). The advantages of this
120−map are fixed time lookup for IRQ numbers, and irq_descs are only
120+map are fixed-time lookup for IRQ numbers, and irq_descs are only
121121 allocated for in-use IRQs. The disadvantage is that the table must be
122122 as large as the largest possible hwirq number.
123123
@@ -134,7 +134,7 @@ The irq_domain maintains a radix tree map from hwirq numbers to Linux · 10 unmodified lines
134134 IRQs. When an hwirq is mapped, an irq_desc is allocated and the
135135 hwirq is used as the lookup key for the radix tree.
136136
137−The tree map is a good choice if the hwirq number can be very large
137+The Tree map is a good choice if the hwirq number can be very large
138138 since it doesn't need to allocate a table as large as the largest
139139 hwirq number. The disadvantage is that hwirq to IRQ number lookup is
140140 dependent on how many entries are in the table.
@@ -169,10 +169,10 @@ Legacy · 28 unmodified lines
169169
170170 The Legacy mapping is a special case for drivers that already have a
171171 range of irq_descs allocated for the hwirqs. It is used when the
172−driver cannot be immediately converted to use the linear mapping. For
172+driver cannot be immediately converted to use the Linear mapping. For
173173 example, many embedded system board support files use a set of #defines
174174 for IRQ numbers that are passed to struct device registrations. In that
175−case the Linux IRQ numbers cannot be dynamically assigned and the legacy
175+case the Linux IRQ numbers cannot be dynamically assigned and the Legacy
176176 mapping should be used.
177177
178178 As the name implies, the \*_legacy() functions are deprecated and only
@@ -180,15 +180,15 @@ exist to ease the support of ancient platforms. No new users should be · 1 unmodified line
180180 added. Same goes for the \*_simple() functions when their use results
181181 in the legacy behaviour.
182182
183−The legacy map assumes a contiguous range of IRQ numbers has already
183+The Legacy map assumes a contiguous range of IRQ numbers has already
184184 been allocated for the controller and that the IRQ number can be
185185 calculated by adding a fixed offset to the hwirq number, and
186186 visa-versa. The disadvantage is that it requires the interrupt
187187 controller to manage IRQ allocations and it requires an irq_desc to be
188188 allocated for every hwirq, even if it is unused.
189189
190−The legacy map should only be used if fixed IRQ mappings must be
191−supported. For example, ISA controllers would use the legacy map for
190+The Legacy map should only be used if fixed IRQ mappings must be
191+supported. For example, ISA controllers would use the Legacy map for
192192 mapping Linux IRQs 0-15 so that existing ISA drivers get the correct IRQ
193193 numbers.
194194
@@ -197,7 +197,7 @@ which will use a legacy domain only if an IRQ range is supplied by the · 2 unmodified lines
197197 system and will otherwise use a linear domain mapping. The semantics of
198198 this call are such that if an IRQ range is specified then descriptors
199199 will be allocated on-the-fly for it, and if no range is specified it
200−will fall through to irq_domain_create_linear() which means *no* irq
200+will fall through to irq_domain_create_linear() which means *no* IRQ
201201 descriptors will be allocated.
202202
203203 A typical use case for simple domains is where an irqchip provider
@@ -214,7 +214,7 @@ Hierarchy IRQ Domain · 10 unmodified lines
214214
215215 On some architectures, there may be multiple interrupt controllers
216216 involved in delivering an interrupt from the device to the target CPU.
217−Let's look at a typical interrupt delivering path on x86 platforms::
217+Let's look at a typical interrupt delivery path on x86 platforms::
218218
219219 Device --> IOAPIC -> Interrupt remapping Controller -> Local APIC -> CPU
220220
@@ -227,8 +227,8 @@ There are three interrupt controllers involved: · 6 unmodified lines
227227 To support such a hardware topology and make software architecture match
228228 hardware architecture, an irq_domain data structure is built for each
229229 interrupt controller and those irq_domains are organized into hierarchy.
230−When building irq_domain hierarchy, the irq_domain near to the device is
231−child and the irq_domain near to CPU is parent. So a hierarchy structure
230+When building irq_domain hierarchy, the irq_domain nearest the device is
231+child and the irq_domain nearest the CPU is parent. So a hierarchy structure
232232 as below will be built for the example above::
233233
234234 CPU Vector irq_domain (root irq_domain to manage CPU vectors)
Documentation/core-api/printk-formats.rst+1−1
@@ -521,7 +521,7 @@ Fwnode handles · 520 unmodified lines
521521
522522 %pfw[fP]
523523
524−For printing information on fwnode handles. The default is to print the full
524+For printing information on an fwnode_handle. The default is to print the full
525525 node name, including the path. The modifiers are functionally equivalent to
526526 %pOF above.
527527
Documentation/core-api/real-time/architecture-porting.rst+109−0
@@ -0,0 +1,109 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+=============================================
4+Porting an architecture to support PREEMPT_RT
5+=============================================
6+
7+:Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
8+
9+This list outlines the architecture specific requirements that must be
10+implemented in order to enable PREEMPT_RT. Once all required features are
11+implemented, ARCH_SUPPORTS_RT can be selected in architecture’s Kconfig to make
12+PREEMPT_RT selectable.
13+Many prerequisites (genirq support for example) are enforced by the common code
14+and are omitted here.
15+
16+The optional features are not strictly required but it is worth to consider
17+them.
18+
19+Requirements
20+------------
21+
22+Forced threaded interrupts
23+ CONFIG_IRQ_FORCED_THREADING must be selected. Any interrupts that must
24+ remain in hard-IRQ context must be marked with IRQF_NO_THREAD. This
25+ requirement applies for instance to clocksource event interrupts,
26+ perf interrupts and cascading interrupt-controller handlers.
27+
28+PREEMPTION support
29+ Kernel preemption must be supported and requires that
30+ CONFIG_ARCH_NO_PREEMPT remain unselected. Scheduling requests, such as those
31+ issued from an interrupt or other exception handler, must be processed
32+ immediately.
33+
34+POSIX CPU timers and KVM
35+ POSIX CPU timers must expire from thread context rather than directly within
36+ the timer interrupt. This behavior is enabled by setting the configuration
37+ option CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK.
38+ When KVM is enabled, CONFIG_KVM_XFER_TO_GUEST_WORK must also be set to ensure
39+ that any pending work, such as POSIX timer expiration, is handled before
40+ transitioning into guest mode.
41+
42+Hard-IRQ and Soft-IRQ stacks
43+ Soft interrupts are handled in the thread context in which they are raised. If
44+ a soft interrupt is triggered from hard-IRQ context, its execution is deferred
45+ to the ksoftirqd thread. Preemption is never disabled during soft interrupt
46+ handling, which makes soft interrupts preemptible.
47+ If an architecture provides a custom __do_softirq() implementation that uses a
48+ separate stack, it must select CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK. The
49+ functionality should only be enabled when CONFIG_SOFTIRQ_ON_OWN_STACK is set.
50+
51+FPU and SIMD access in kernel mode
52+ FPU and SIMD registers are typically not used in kernel mode and are therefore
53+ not saved during kernel preemption. As a result, any kernel code that uses
54+ these registers must be enclosed within a kernel_fpu_begin() and
55+ kernel_fpu_end() section.
56+ The kernel_fpu_begin() function usually invokes local_bh_disable() to prevent
57+ interruptions from softirqs and to disable regular preemption. This allows the
58+ protected code to run safely in both thread and softirq contexts.
59+ On PREEMPT_RT kernels, however, kernel_fpu_begin() must not call
60+ local_bh_disable(). Instead, it should use preempt_disable(), since softirqs
61+ are always handled in thread context under PREEMPT_RT. In this case, disabling
62+ preemption alone is sufficient.
63+ The crypto subsystem operates on memory pages and requires users to "walk and
64+ map" these pages while processing a request. This operation must occur outside
65+ the kernel_fpu_begin()/ kernel_fpu_end() section because it requires preemption
66+ to be enabled. These preemption points are generally sufficient to avoid
67+ excessive scheduling latency.
68+
69+Exception handlers
70+ Exception handlers, such as the page fault handler, typically enable interrupts
71+ early, before invoking any generic code to process the exception. This is
72+ necessary because handling a page fault may involve operations that can sleep.
73+ Enabling interrupts is especially important on PREEMPT_RT, where certain
74+ locks, such as spinlock_t, become sleepable. For example, handling an
75+ invalid opcode may result in sending a SIGILL signal to the user task. A
76+ debug excpetion will send a SIGTRAP signal.
77+ In both cases, if the exception occurred in user space, it is safe to enable
78+ interrupts early. Sending a signal requires both interrupts and kernel
79+ preemption to be enabled.
80+
81+Optional features
82+-----------------
83+
84+Timer and clocksource
85+ A high-resolution clocksource and clockevents device are recommended. The
86+ clockevents device should support the CLOCK_EVT_FEAT_ONESHOT feature for
87+ optimal timer behavior. In most cases, microsecond-level accuracy is
88+ sufficient
89+
90+Lazy preemption
91+ This mechanism allows an in-kernel scheduling request for non-real-time tasks
92+ to be delayed until the task is about to return to user space. It helps avoid
93+ preempting a task that holds a sleeping lock at the time of the scheduling
94+ request.
95+ With CONFIG_GENERIC_IRQ_ENTRY enabled, supporting this feature requires
96+ defining a bit for TIF_NEED_RESCHED_LAZY, preferably near TIF_NEED_RESCHED.
97+
98+Serial console with NBCON
99+ With PREEMPT_RT enabled, all console output is handled by a dedicated thread
100+ rather than directly from the context in which printk() is invoked. This design
101+ allows printk() to be safely used in atomic contexts.
102+ However, this also means that if the kernel crashes and cannot switch to the
103+ printing thread, no output will be visible preventing the system from printing
104+ its final messages.
105+ There are exceptions for immediate output, such as during panic() handling. To
106+ support this, the console driver must implement new-style lock handling. This
107+ involves setting the CON_NBCON flag in console::flags and providing
108+ implementations for the write_atomic, write_thread, device_lock, and
109+ device_unlock callbacks.
Documentation/core-api/real-time/differences.rst+242−0
@@ -0,0 +1,242 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+===========================
4+How realtime kernels differ
5+===========================
6+
7+:Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
8+
9+Preface
10+=======
11+
12+With forced-threaded interrupts and sleeping spin locks, code paths that
13+previously caused long scheduling latencies have been made preemptible and
14+moved into process context. This allows the scheduler to manage them more
15+effectively and respond to higher-priority tasks with reduced latency.
16+
17+The following chapters provide an overview of key differences between a
18+PREEMPT_RT kernel and a standard, non-PREEMPT_RT kernel.
19+
20+Locking
21+=======
22+
23+Spinning locks such as spinlock_t are used to provide synchronization for data
24+structures accessed from both interrupt context and process context. For this
25+reason, locking functions are also available with the _irq() or _irqsave()
26+suffixes, which disable interrupts before acquiring the lock. This ensures that
27+the lock can be safely acquired in process context when interrupts are enabled.
28+
29+However, on a PREEMPT_RT system, interrupts are forced-threaded and no longer
30+run in hard IRQ context. As a result, there is no need to disable interrupts as
31+part of the locking procedure when using spinlock_t.
32+
33+For low-level core components such as interrupt handling, the scheduler, or the
34+timer subsystem the kernel uses raw_spinlock_t. This lock type preserves
35+traditional semantics: it disables preemption and, when used with _irq() or
36+_irqsave(), also disables interrupts. This ensures proper synchronization in
37+critical sections that must remain non-preemptible or with interrupts disabled.
38+
39+Execution context
40+=================
41+
42+Interrupt handling in a PREEMPT_RT system is invoked in process context through
43+the use of threaded interrupts. Other parts of the kernel also shift their
44+execution into threaded context by different mechanisms. The goal is to keep
45+execution paths preemptible, allowing the scheduler to interrupt them when a
46+higher-priority task needs to run.
47+
48+Below is an overview of the kernel subsystems involved in this transition to
49+threaded, preemptible execution.
50+
51+Interrupt handling
52+------------------
53+
54+All interrupts are forced-threaded in a PREEMPT_RT system. The exceptions are
55+interrupts that are requested with the IRQF_NO_THREAD, IRQF_PERCPU, or
56+IRQF_ONESHOT flags.
57+
58+The IRQF_ONESHOT flag is used together with threaded interrupts, meaning those
59+registered using request_threaded_irq() and providing only a threaded handler.
60+Its purpose is to keep the interrupt line masked until the threaded handler has
61+completed.
62+
63+If a primary handler is also provided in this case, it is essential that the
64+handler does not acquire any sleeping locks, as it will not be threaded. The
65+handler should be minimal and must avoid introducing delays, such as
66+busy-waiting on hardware registers.
67+
68+
69+Soft interrupts, bottom half handling
70+-------------------------------------
71+
72+Soft interrupts are raised by the interrupt handler and are executed after the
73+handler returns. Since they run in thread context, they can be preempted by
74+other threads. Do not assume that softirq context runs with preemption
75+disabled. This means you must not rely on mechanisms like local_bh_disable() in
76+process context to protect per-CPU variables. Because softirq handlers are
77+preemptible under PREEMPT_RT, this approach does not provide reliable
78+synchronization.
79+
80+If this kind of protection is required for performance reasons, consider using
81+local_lock_nested_bh(). On non-PREEMPT_RT kernels, this allows lockdep to
82+verify that bottom halves are disabled. On PREEMPT_RT systems, it adds the
83+necessary locking to ensure proper protection.
84+
85+Using local_lock_nested_bh() also makes the locking scope explicit and easier
86+for readers and maintainers to understand.
87+
88+
89+per-CPU variables
90+-----------------
91+
92+Protecting access to per-CPU variables solely by using preempt_disable() should
93+be avoided, especially if the critical section has unbounded runtime or may
94+call APIs that can sleep.
95+
96+If using a spinlock_t is considered too costly for performance reasons,
97+consider using local_lock_t. On non-PREEMPT_RT configurations, this introduces
98+no runtime overhead when lockdep is disabled. With lockdep enabled, it verifies
99+that the lock is only acquired in process context and never from softirq or
100+hard IRQ context.
101+
102+On a PREEMPT_RT kernel, local_lock_t is implemented using a per-CPU spinlock_t,
103+which provides safe local protection for per-CPU data while keeping the system
104+preemptible.
105+
106+Because spinlock_t on PREEMPT_RT does not disable preemption, it cannot be used
107+to protect per-CPU data by relying on implicit preemption disabling. If this
108+inherited preemption disabling is essential and if local_lock_t cannot be used
109+due to performance constraints, brevity of the code, or abstraction boundaries
110+within an API then preempt_disable_nested() may be a suitable alternative. On
111+non-PREEMPT_RT kernels, it verifies with lockdep that preemption is already
112+disabled. On PREEMPT_RT, it explicitly disables preemption.
113+
114+Timers
115+------
116+
117+By default, an hrtimer is executed in hard interrupt context. The exception is
118+timers initialized with the HRTIMER_MODE_SOFT flag, which are executed in
119+softirq context.
120+
121+On a PREEMPT_RT kernel, this behavior is reversed: hrtimers are executed in
122+softirq context by default, typically within the ktimersd thread. This thread
123+runs at the lowest real-time priority, ensuring it executes before any
124+SCHED_OTHER tasks but does not interfere with higher-priority real-time
125+threads. To explicitly request execution in hard interrupt context on
126+PREEMPT_RT, the timer must be marked with the HRTIMER_MODE_HARD flag.
127+
128+Memory allocation
129+-----------------
130+
131+The memory allocation APIs, such as kmalloc() and alloc_pages(), require a
132+gfp_t flag to indicate the allocation context. On non-PREEMPT_RT kernels, it is
133+necessary to use GFP_ATOMIC when allocating memory from interrupt context or
134+from sections where preemption is disabled. This is because the allocator must
135+not sleep in these contexts waiting for memory to become available.
136+
137+However, this approach does not work on PREEMPT_RT kernels. The memory
138+allocator in PREEMPT_RT uses sleeping locks internally, which cannot be
139+acquired when preemption is disabled. Fortunately, this is generally not a
140+problem, because PREEMPT_RT moves most contexts that would traditionally run
141+with preemption or interrupts disabled into threaded context, where sleeping is
142+allowed.
143+
144+What remains problematic is code that explicitly disables preemption or
145+interrupts. In such cases, memory allocation must be performed outside the
146+critical section.
147+
148+This restriction also applies to memory deallocation routines such as kfree()
149+and free_pages(), which may also involve internal locking and must not be
150+called from non-preemptible contexts.
151+
152+IRQ work
153+--------
154+
155+The irq_work API provides a mechanism to schedule a callback in interrupt
156+context. It is designed for use in contexts where traditional scheduling is not
157+possible, such as from within NMI handlers or from inside the scheduler, where
158+using a workqueue would be unsafe.
159+
160+On non-PREEMPT_RT systems, all irq_work items are executed immediately in
161+interrupt context. Items marked with IRQ_WORK_LAZY are deferred until the next
162+timer tick but are still executed in interrupt context.
163+
164+On PREEMPT_RT systems, the execution model changes. Because irq_work callbacks
165+may acquire sleeping locks or have unbounded execution time, they are handled
166+in thread context by a per-CPU irq_work kernel thread. This thread runs at the
167+lowest real-time priority, ensuring it executes before any SCHED_OTHER tasks
168+but does not interfere with higher-priority real-time threads.
169+
170+The exception are work items marked with IRQ_WORK_HARD_IRQ, which are still
171+executed in hard interrupt context. Lazy items (IRQ_WORK_LAZY) continue to be
172+deferred until the next timer tick and are also executed by the irq_work/
173+thread.
174+
175+RCU callbacks
176+-------------
177+
178+RCU callbacks are invoked by default in softirq context. Their execution is
179+important because, depending on the use case, they either free memory or ensure
180+progress in state transitions. Running these callbacks as part of the softirq
181+chain can lead to undesired situations, such as contention for CPU resources
182+with other SCHED_OTHER tasks when executed within ksoftirqd.
183+
184+To avoid running callbacks in softirq context, the RCU subsystem provides a
185+mechanism to execute them in process context instead. This behavior can be
186+enabled by setting the boot command-line parameter rcutree.use_softirq=0. This
187+setting is enforced in kernels configured with PREEMPT_RT.
188+
189+Spin until ready
190+================
191+
192+The "spin until ready" pattern involves repeatedly checking (spinning on) the
193+state of a data structure until it becomes available. This pattern assumes that
194+preemption, soft interrupts, or interrupts are disabled. If the data structure
195+is marked busy, it is presumed to be in use by another CPU, and spinning should
196+eventually succeed as that CPU makes progress.
197+
198+Some examples are hrtimer_cancel() or timer_delete_sync(). These functions
199+cancel timers that execute with interrupts or soft interrupts disabled. If a
200+thread attempts to cancel a timer and finds it active, spinning until the
201+callback completes is safe because the callback can only run on another CPU and
202+will eventually finish.
203+
204+On PREEMPT_RT kernels, however, timer callbacks run in thread context. This
205+introduces a challenge: a higher-priority thread attempting to cancel the timer
206+may preempt the timer callback thread. Since the scheduler cannot migrate the
207+callback thread to another CPU due to affinity constraints, spinning can result
208+in livelock even on multiprocessor systems.
209+
210+To avoid this, both the canceling and callback sides must use a handshake
211+mechanism that supports priority inheritance. This allows the canceling thread
212+to suspend until the callback completes, ensuring forward progress without
213+risking livelock.
214+
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
217+blocked writer.
218+
219+Sequence locks
220+--------------
221+
222+Sequence counters and sequential locks are documented in
223+Documentation/locking/seqlock.rst.
224+
225+The interface has been extended to ensure proper preemption states for the
226+writer and spinning reader contexts. This is achieved by embedding the writer
227+serialization lock directly into the sequence counter type, resulting in
228+composite types such as seqcount_spinlock_t or seqcount_mutex_t.
229+
230+These composite types allow readers to detect an ongoing write and actively
231+boost the writer’s priority to help it complete its update instead of spinning
232+and waiting for its completion.
233+
234+If the plain seqcount_t is used, extra care must be taken to synchronize the
235+reader with the writer during updates. The writer must ensure its update is
236+serialized and non-preemptible relative to the reader. This cannot be achieved
237+using a regular spinlock_t because spinlock_t on PREEMPT_RT does not disable
238+preemption. In such cases, using seqcount_spinlock_t is the preferred solution.
239+
240+However, if there is no spinning involved i.e., if the reader only needs to
241+detect whether a write has started and not serialize against it then using
242+seqcount_t is reasonable.
Documentation/core-api/real-time/index.rst+16−0
@@ -0,0 +1,16 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+=====================
4+Real-time preemption
5+=====================
6+
7+This documentation is intended for Linux kernel developers and contributors
8+interested in the inner workings of PREEMPT_RT. It explains key concepts and
9+the required changes compared to a non-PREEMPT_RT configuration.
10+
11+.. toctree::
12+ :maxdepth: 2
13+
14+ theory
15+ differences
16+ architecture-porting
Documentation/core-api/real-time/theory.rst+116−0
@@ -0,0 +1,116 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+=====================
4+Theory of operation
5+=====================
6+
7+:Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
8+
9+Preface
10+=======
11+
12+PREEMPT_RT transforms the Linux kernel into a real-time kernel. It achieves
13+this by replacing locking primitives, such as spinlock_t, with a preemptible
14+and priority-inheritance aware implementation known as rtmutex, and by enforcing
15+the use of threaded interrupts. As a result, the kernel becomes fully
16+preemptible, with the exception of a few critical code paths, including entry
17+code, the scheduler, and low-level interrupt handling routines.
18+
19+This transformation places the majority of kernel execution contexts under the
20+control of the scheduler and significantly increasing the number of preemption
21+points. Consequently, it reduces the latency between a high-priority task
22+becoming runnable and its actual execution on the CPU.
23+
24+Scheduling
25+==========
26+
27+The core principles of Linux scheduling and the associated user-space API are
28+documented in the man page sched(7)
29+`sched(7) <https://man7.org/linux/man-pages/man7/sched.7.html>`_.
30+By default, the Linux kernel uses the SCHED_OTHER scheduling policy. Under
31+this policy, a task is preempted when the scheduler determines that it has
32+consumed a fair share of CPU time relative to other runnable tasks. However,
33+the policy does not guarantee immediate preemption when a new SCHED_OTHER task
34+becomes runnable. The currently running task may continue executing.
35+
36+This behavior differs from that of real-time scheduling policies such as
37+SCHED_FIFO. When a task with a real-time policy becomes runnable, the
38+scheduler immediately selects it for execution if it has a higher priority than
39+the currently running task. The task continues to run until it voluntarily
40+yields the CPU, typically by blocking on an event.
41+
42+Sleeping spin locks
43+===================
44+
45+The various lock types and their behavior under real-time configurations are
46+described in detail in Documentation/locking/locktypes.rst.
47+In a non-PREEMPT_RT configuration, a spinlock_t is acquired by first disabling
48+preemption and then actively spinning until the lock becomes available. Once
49+the lock is released, preemption is enabled. From a real-time perspective,
50+this approach is undesirable because disabling preemption prevents the
51+scheduler from switching to a higher-priority task, potentially increasing
52+latency.
53+
54+To address this, PREEMPT_RT replaces spinning locks with sleeping spin locks
55+that do not disable preemption. On PREEMPT_RT, spinlock_t is implemented using
56+rtmutex. Instead of spinning, a task attempting to acquire a contended lock
57+disables CPU migration, donates its priority to the lock owner (priority
58+inheritance), and voluntarily schedules out while waiting for the lock to
59+become available.
60+
61+Disabling CPU migration provides the same effect as disabling preemption, while
62+still allowing preemption and ensuring that the task continues to run on the
63+same CPU while holding a sleeping lock.
64+
65+Priority inheritance
66+====================
67+
68+Lock types such as spinlock_t and mutex_t in a PREEMPT_RT enabled kernel are
69+implemented on top of rtmutex, which provides support for priority inheritance
70+(PI). When a task blocks on such a lock, the PI mechanism temporarily
71+propagates the blocked task’s scheduling parameters to the lock owner.
72+
73+For example, if a SCHED_FIFO task A blocks on a lock currently held by a
74+SCHED_OTHER task B, task A’s scheduling policy and priority are temporarily
75+inherited by task B. After this inheritance, task A is put to sleep while
76+waiting for the lock, and task B effectively becomes the highest-priority task
77+in the system. This allows B to continue executing, make progress, and
78+eventually release the lock.
79+
80+Once B releases the lock, it reverts to its original scheduling parameters, and
81+task A can resume execution.
82+
83+Threaded interrupts
84+===================
85+
86+Interrupt handlers are another source of code that executes with preemption
87+disabled and outside the control of the scheduler. To bring interrupt handling
88+under scheduler control, PREEMPT_RT enforces threaded interrupt handlers.
89+
90+With forced threading, interrupt handling is split into two stages. The first
91+stage, the primary handler, is executed in IRQ context with interrupts disabled.
92+Its sole responsibility is to wake the associated threaded handler. The second
93+stage, the threaded handler, is the function passed to request_irq() as the
94+interrupt handler. It runs in process context, scheduled by the kernel.
95+
96+From waking the interrupt thread until threaded handling is completed, the
97+interrupt source is masked in the interrupt controller. This ensures that the
98+device interrupt remains pending but does not retrigger the CPU, allowing the
99+system to exit IRQ context and handle the interrupt in a scheduled thread.
100+
101+By default, the threaded handler executes with the SCHED_FIFO scheduling policy
102+and a priority of 50 (MAX_RT_PRIO / 2), which is midway between the minimum and
103+maximum real-time priorities.
104+
105+If the threaded interrupt handler raises any soft interrupts during its
106+execution, those soft interrupt routines are invoked after the threaded handler
107+completes, within the same thread. Preemption remains enabled during the
108+execution of the soft interrupt handler.
109+
110+Summary
111+=======
112+
113+By using sleeping locks and forced-threaded interrupts, PREEMPT_RT
114+significantly reduces sections of code where interrupts or preemption is
115+disabled, allowing the scheduler to preempt the current execution context and
116+switch to a higher-priority task.
Documentation/dev-tools/autofdo.rst+2−2
@@ -131,11 +131,11 @@ Here is an example workflow for AutoFDO kernel: · 130 unmodified lines
131131
132132 For Zen3::
133133
134− $ cat proc/cpuinfo | grep " brs"
134+ $ cat /proc/cpuinfo | grep " brs"
135135
136136 For Zen4::
137137
138− $ cat proc/cpuinfo | grep amd_lbr_v2
138+ $ cat /proc/cpuinfo | grep amd_lbr_v2
139139
140140 The following command generated the perf data file::
141141
Documentation/dev-tools/index.rst+1−0
@@ -29,6 +29,7 @@ Documentation/process/debugging/index.rst · 28 unmodified lines
2929 ubsan
3030 kmemleak
3131 kcsan
32+ lkmm/index
3233 kfence
3334 kselftest
3435 kunit/index
Documentation/dev-tools/ktap.rst+4−1
@@ -5,7 +5,7 @@ The Kernel Test Anything Protocol (KTAP), version 1 · 4 unmodified lines
55 ===================================================
66
77 TAP, or the Test Anything Protocol is a format for specifying test results used
8−by a number of projects. It's website and specification are found at this `link
8+by a number of projects. Its website and specification are found at this `link
99 <https://testanything.org/>`_. The Linux Kernel largely uses TAP output for test
1010 results. However, Kernel testing frameworks have special needs for test results
1111 which don't align with the original TAP specification. Thus, a "Kernel TAP"
@@ -20,6 +20,7 @@ machine-readable, whereas the diagnostic data is unstructured and is there to · 8 unmodified lines
2020 aid human debugging.
2121
2222 KTAP output is built from four different types of lines:
23+
2324 - Version lines
2425 - Plan lines
2526 - Test case result lines
@@ -38,6 +39,7 @@ All KTAP-formatted results begin with a "version line" which specifies which · 12 unmodified lines
3839 version of the (K)TAP standard the result is compliant with.
3940
4041 For example:
42+
4143 - "KTAP version 1"
4244 - "TAP version 13"
4345 - "TAP version 14"
@@ -276,6 +278,7 @@ Example KTAP output · 232 unmodified lines
276278 This output defines the following hierarchy:
277279
278280 A single test called "main_test", which fails, and has three subtests:
281+
279282 - "example_test_1", which passes, and has one subtest:
280283
281284 - "test_1", which passes, and outputs the diagnostic message "test_1: initializing test_1"
Documentation/dev-tools/lkmm/docs/access-marking.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Access Marking
4+--------------
5+
6+Literal include of ``tools/memory-model/Documentation/access-marking.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/access-marking.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/cheatsheet.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Cheatsheet
4+----------
5+
6+Literal include of ``tools/memory-model/Documentation/cheatsheet.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/cheatsheet.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/control-dependencies.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Control Dependencies
4+--------------------
5+
6+Literal include of ``tools/memory-model/Documentation/control-dependencies.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/control-dependencies.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/explanation.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Explanation
4+-----------
5+
6+Literal include of ``tools/memory-model/Documentation/explanation.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/explanation.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/glossary.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Glossary
4+--------
5+
6+Literal include of ``tools/memory-model/Documentation/glossary.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/glossary.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/herd-representation.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+herd-representation
4+-------------------
5+
6+Literal include of ``tools/memory-model/Documentation/herd-representation.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/herd-representation.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/index.rst+21−0
@@ -0,0 +1,21 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Documentation
4+=============
5+
6+.. toctree::
7+ :maxdepth: 1
8+
9+ readme
10+ simple
11+ ordering
12+ litmus-tests
13+ locking
14+ recipes
15+ control-dependencies
16+ access-marking
17+ cheatsheet
18+ explanation
19+ herd-representation
20+ glossary
21+ references
Documentation/dev-tools/lkmm/docs/litmus-tests.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Litmus Tests
4+------------
5+
6+Literal include of ``tools/memory-model/Documentation/litmus-tests.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/litmus-tests.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/locking.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Locking
4+-------
5+
6+Literal include of ``tools/memory-model/Documentation/locking.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/locking.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/ordering.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Ordering
4+--------
5+
6+Literal include of ``tools/memory-model/Documentation/ordering.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/ordering.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/readme.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+README (for LKMM Documentation)
4+-------------------------------
5+
6+Literal include of ``tools/memory-model/Documentation/README``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/README
11+ :literal:
Documentation/dev-tools/lkmm/docs/recipes.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Recipes
4+-------
5+
6+Literal include of ``tools/memory-model/Documentation/recipes.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/recipes.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/references.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+References
4+----------
5+
6+Literal include of ``tools/memory-model/Documentation/references.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/references.txt
11+ :literal:
Documentation/dev-tools/lkmm/docs/simple.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+Simple
4+------
5+
6+Literal include of ``tools/memory-model/Documentation/simple.txt``.
7+
8+------------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/Documentation/simple.txt
11+ :literal:
Documentation/dev-tools/lkmm/index.rst+15−0
@@ -0,0 +1,15 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+============================================
4+Linux Kernel Memory Consistency Model (LKMM)
5+============================================
6+
7+This section literally renders documents under ``tools/memory-model/``
8+and ``tools/memory-model/Documentation/``, which are maintained in
9+the *pure* plain text form.
10+
11+.. toctree::
12+ :maxdepth: 2
13+
14+ readme
15+ docs/index
Documentation/dev-tools/lkmm/readme.rst+11−0
@@ -0,0 +1,11 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+README (for LKMM)
4+=================
5+
6+Literal include of ``tools/memory-model/README``.
7+
8+------------------------------------------------------------
9+
10+.. kernel-include:: tools/memory-model/README
11+ :literal:
Documentation/devicetree/bindings/submitting-patches.rst+1−1
@@ -66,7 +66,7 @@ I. For patch submitters · 65 unmodified lines
6666 any DTS patches, regardless whether using existing or new bindings, should
6767 be placed at the end of patchset to indicate no dependency of drivers on
6868 the DTS. DTS will be anyway applied through separate tree or branch, so
69− different order would indicate the serie is non-bisectable.
69+ different order would indicate the series is non-bisectable.
7070
7171 If a driver subsystem maintainer prefers to apply entire set, instead of
7272 their relevant portion of patchset, please split the DTS patches into
Documentation/driver-api/cxl/devices/device-types.rst+1−1
@@ -22,7 +22,7 @@ The basic interaction protocol, similar to PCIe configuration mechanisms. · 21 unmodified lines
2222 Typically used for initialization, configuration, and I/O access for anything
2323 other than memory (CXL.mem) or cache (CXL.cache) operations.
2424
25−The Linux CXL driver exposes access to .io functionalty via the various sysfs
25+The Linux CXL driver exposes access to .io functionality via the various sysfs
2626 interfaces and /dev/cxl/ devices (which exposes direct access to device
2727 mailboxes).
2828
Documentation/driver-api/cxl/platform/example-configurations/one-dev-per-hb.rst+1−1
@@ -10,7 +10,7 @@ has a single CXL memory expander with a 4GB of memory. · 9 unmodified lines
1010 Things to note:
1111
1212 * Cross-Bridge interleave is not being used.
13−* The expanders are in two separate but adjascent memory regions.
13+* The expanders are in two separate but adjacent memory regions.
1414 * This CEDT/SRAT describes one node per device
1515 * The expanders have the same performance and will be in the same memory tier.
1616
Documentation/driver-api/device-io.rst+2−2
@@ -16,7 +16,7 @@ Bus-Independent Device Accesses · 15 unmodified lines
1616 Introduction
1717 ============
1818
19−Linux provides an API which abstracts performing IO across all busses
19+Linux provides an API which abstracts performing IO across all buses
2020 and devices, allowing device drivers to be written independently of bus
2121 type.
2222
@@ -71,7 +71,7 @@ can be compiler optimised, you can use __readb() and friends to · 48 unmodified lines
7171 indicate the relaxed ordering. Use this with care.
7272
7373 While the basic functions are defined to be synchronous with respect to
74−each other and ordered with respect to each other the busses the devices
74+each other and ordered with respect to each other the buses the devices
7575 sit on may themselves have asynchronicity. In particular many authors
7676 are burned by the fact that PCI bus writes are posted asynchronously. A
7777 driver author must issue a read from the same device to ensure that
Documentation/driver-api/driver-model/overview.rst+1−1
@@ -22,7 +22,7 @@ uniformity across the different bus types. · 21 unmodified lines
2222
2323 The current driver model provides a common, uniform data model for describing
2424 a bus and the devices that can appear under the bus. The unified bus
25−model includes a set of common attributes which all busses carry, and a set
25+model includes a set of common attributes which all buses carry, and a set
2626 of common callbacks, such as device discovery during bus probing, bus
2727 shutdown, bus power management, etc.
2828
Documentation/driver-api/driver-model/platform.rst+1−1
@@ -4,7 +4,7 @@ Platform Devices and Drivers · 3 unmodified lines
44
55 See <linux/platform_device.h> for the driver model interface to the
66 platform bus: platform_device, and platform_driver. This pseudo-bus
7−is used to connect devices on busses with minimal infrastructure,
7+is used to connect devices on buses with minimal infrastructure,
88 like those used to integrate peripherals on many system-on-chip
99 processors, or some "legacy" PC interconnects; as opposed to large
1010 formally specified ones like PCI or USB.
Documentation/driver-api/eisa.rst+3−3
@@ -8,9 +8,9 @@ This document groups random notes about porting EISA drivers to the · 7 unmodified lines
88 new EISA/sysfs API.
99
1010 Starting from version 2.5.59, the EISA bus is almost given the same
11−status as other much more mainstream busses such as PCI or USB. This
11+status as other much more mainstream buses such as PCI or USB. This
1212 has been possible through sysfs, which defines a nice enough set of
13−abstractions to manage busses, devices and drivers.
13+abstractions to manage buses, devices and drivers.
1414
1515 Although the new API is quite simple to use, converting existing
1616 drivers to the new infrastructure is not an easy task (mostly because
@@ -205,7 +205,7 @@ Random notes · 188 unmodified lines
205205 Converting an EISA driver to the new API mostly involves *deleting*
206206 code (since probing is now in the core EISA code). Unfortunately, most
207207 drivers share their probing routine between ISA, and EISA. Special
208−care must be taken when ripping out the EISA code, so other busses
208+care must be taken when ripping out the EISA code, so other buses
209209 won't suffer from these surgical strikes...
210210
211211 You *must not* expect any EISA device to be detected when returning
Documentation/driver-api/i3c/protocol.rst+2−2
@@ -165,8 +165,8 @@ The first thing attached to an HDR command is the HDR mode. There are currently · 164 unmodified lines
165165 for more details):
166166
167167 * HDR-DDR: Double Data Rate mode
168−* HDR-TSP: Ternary Symbol Pure. Only usable on busses with no I2C devices
169−* HDR-TSL: Ternary Symbol Legacy. Usable on busses with I2C devices
168+* HDR-TSP: Ternary Symbol Pure. Only usable on buses with no I2C devices
169+* HDR-TSL: Ternary Symbol Legacy. Usable on buses with I2C devices
170170
171171 When sending an HDR command, the whole bus has to enter HDR mode, which is done
172172 using a broadcast CCC command.
Documentation/driver-api/ipmi.rst+2−2
@@ -617,12 +617,12 @@ Note that the address you give here is the I2C address, not the IPMI · 616 unmodified lines
617617 address. So if you want your MC address to be 0x60, you put 0x30
618618 here. See the I2C driver info for more details.
619619
620−Command bridging to other IPMB busses through this interface does not
620+Command bridging to other IPMB buses through this interface does not
621621 work. The receive message queue is not implemented, by design. There
622622 is only one receive message queue on a BMC, and that is meant for the
623623 host drivers, not something on the IPMB bus.
624624
625−A BMC may have multiple IPMB busses, which bus your device sits on
625+A BMC may have multiple IPMB buses, which bus your device sits on
626626 depends on how the system is wired. You can fetch the channels with
627627 "ipmitool channel info <n>" where <n> is the channel, with the
628628 channels being 0-7 and try the IPMB channels.
Documentation/driver-api/media/tx-rx.rst+2−2
@@ -12,7 +12,7 @@ CSI-2 receiver in an SoC. · 11 unmodified lines
1212 Bus types
1313 ---------
1414
15−The following busses are the most common. This section discusses these two only.
15+The following buses are the most common. This section discusses these two only.
1616
1717 MIPI CSI-2
1818 ^^^^^^^^^^
@@ -36,7 +36,7 @@ Transmitter drivers · 17 unmodified lines
3636
3737 Transmitter drivers generally need to provide the receiver drivers with the
3838 configuration of the transmitter. What is required depends on the type of the
39−bus. These are common for both busses.
39+bus. These are common for both buses.
4040
4141 Media bus pixel code
4242 ^^^^^^^^^^^^^^^^^^^^
Documentation/driver-api/nvdimm/nvdimm.rst+1−1
@@ -230,7 +230,7 @@ LIBNVDIMM/LIBNDCTL: Bus · 229 unmodified lines
230230 A bus has a 1:1 relationship with an NFIT. The current expectation for
231231 ACPI based systems is that there is only ever one platform-global NFIT.
232232 That said, it is trivial to register multiple NFITs, the specification
233−does not preclude it. The infrastructure supports multiple busses and
233+does not preclude it. The infrastructure supports multiple buses and
234234 we use this capability to test multiple NFIT configurations in the unit
235235 test.
236236
Documentation/driver-api/pin-control.rst+6−4
@@ -1202,22 +1202,24 @@ default state like this: · 1201 unmodified lines
12021202 {
12031203 /* Allocate a state holder named "foo" etc */
12041204 struct foo_state *foo = ...;
1205+ int ret;
12051206
12061207 foo->p = devm_pinctrl_get(&device);
12071208 if (IS_ERR(foo->p)) {
1208− /* FIXME: clean up "foo" here */
1209− return PTR_ERR(foo->p);
1209+ ret = PTR_ERR(foo->p);
1210+ foo->p = NULL;
1211+ return ret;
12101212 }
12111213
12121214 foo->s = pinctrl_lookup_state(foo->p, PINCTRL_STATE_DEFAULT);
12131215 if (IS_ERR(foo->s)) {
1214− /* FIXME: clean up "foo" here */
1216+ devm_pinctrl_put(foo->p);
12151217 return PTR_ERR(foo->s);
12161218 }
12171219
12181220 ret = pinctrl_select_state(foo->p, foo->s);
12191221 if (ret < 0) {
1220− /* FIXME: clean up "foo" here */
1222+ devm_pinctrl_put(foo->p);
12211223 return ret;
12221224 }
12231225 }
Documentation/driver-api/pm/devices.rst+2−2
@@ -255,7 +255,7 @@ get registered: a child can never be registered, probed or resumed before · 254 unmodified lines
255255 its parent; and can't be removed or suspended after that parent.
256256
257257 The policy is that the device hierarchy should match hardware bus topology.
258−[Or at least the control bus, for devices which use multiple busses.]
258+[Or at least the control bus, for devices which use multiple buses.]
259259 In particular, this means that a device registration may fail if the parent of
260260 the device is suspending (i.e. has been chosen by the PM core as the next
261261 device to suspend) or has already suspended, as well as after all of the other
@@ -493,7 +493,7 @@ states, like S3). · 231 unmodified lines
493493
494494 Drivers must also be prepared to notice that the device has been removed
495495 while the system was powered down, whenever that's physically possible.
496−PCMCIA, MMC, USB, Firewire, SCSI, and even IDE are common examples of busses
496+PCMCIA, MMC, USB, Firewire, SCSI, and even IDE are common examples of buses
497497 where common Linux platforms will see such removal. Details of how drivers
498498 will notice and handle such removals are currently bus-specific, and often
499499 involve a separate thread.
Documentation/driver-api/scsi.rst+2−2
@@ -18,7 +18,7 @@ optical drives, test equipment, and medical devices) to a host computer. · 17 unmodified lines
1818
1919 Although the old parallel (fast/wide/ultra) SCSI bus has largely fallen
2020 out of use, the SCSI command set is more widely used than ever to
21−communicate with devices over a number of different busses.
21+communicate with devices over a number of different buses.
2222
2323 The `SCSI protocol <https://www.t10.org/scsi-3.htm>`__ is a big-endian
2424 peer-to-peer packet based protocol. SCSI commands are 6, 10, 12, or 16
@@ -286,7 +286,7 @@ Parallel SCSI (SPI) transport class · 261 unmodified lines
286286 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
287287
288288 The file drivers/scsi/scsi_transport_spi.c defines transport
289−attributes for traditional (fast/wide/ultra) SCSI busses.
289+attributes for traditional (fast/wide/ultra) SCSI buses.
290290
291291 .. kernel-doc:: drivers/scsi/scsi_transport_spi.c
292292 :export:
Documentation/driver-api/spi.rst+1−1
@@ -13,7 +13,7 @@ additional chipselect line is usually active-low (nCS); four signals are · 12 unmodified lines
1313 normally used for each peripheral, plus sometimes an interrupt.
1414
1515 The SPI bus facilities listed here provide a generalized interface to
16−declare SPI busses and devices, manage them according to the standard
16+declare SPI buses and devices, manage them according to the standard
1717 Linux driver model, and perform input/output operations. At this time,
1818 only "master" side interfaces are supported, where Linux talks to SPI
1919 peripherals and does not implement such a peripheral itself. (Interfaces
Documentation/driver-api/thermal/exynos_thermal_emulation.rst+7−7
@@ -28,13 +28,13 @@ changed into it. · 27 unmodified lines
2828 delay of changing temperature. However, this node only uses same delay
2929 of real sensing time, 938us.)
3030
31−Exynos emulation mode requires synchronous of value changing and
32−enabling. It means when you want to update the any value of delay or
33−next temperature, then you have to enable emulation mode at the same
34−time. (Or you have to keep the mode enabling.) If you don't, it fails to
35−change the value to updated one and just use last succeessful value
36−repeatedly. That's why this node gives users the right to change
37−termerpature only. Just one interface makes it more simply to use.
31+Exynos emulation mode requires that value changes and enabling are performed
32+synchronously. This means that when you want to update any value, such as the
33+delay or the next temperature, you must enable emulation mode at the same
34+time (or keep the mode enabled). If you do not, the value will fail to update
35+and the last successful value will continue to be used. For this reason,
36+this node only allows users to change the temperature. Providing a single
37+interface makes it simpler to use.
3838
3939 Disabling emulation mode only requires writing value 0 to sysfs node.
4040
Documentation/driver-api/usb/hotplug.rst+1−1
@@ -5,7 +5,7 @@ Linux Hotplugging · 4 unmodified lines
55 =================
66
77
8−In hotpluggable busses like USB (and Cardbus PCI), end-users plug devices
8+In hotpluggable buses like USB (and Cardbus PCI), end-users plug devices
99 into the bus with power on. In most cases, users expect the devices to become
1010 immediately usable. That means the system must do many things, including:
1111
Documentation/driver-api/usb/index.rst+1−0
@@ -3,6 +3,7 @@ Linux USB API · 2 unmodified lines
33 =============
44
55 .. toctree::
6+ :maxdepth: 1
67
78 usb
89 gadget
Documentation/driver-api/usb/usb.rst+2−2
@@ -13,7 +13,7 @@ structure, with the host as the root (the system's master), hubs as · 12 unmodified lines
1313 interior nodes, and peripherals as leaves (and slaves). Modern PCs
1414 support several such trees of USB devices, usually
1515 a few USB 3.0 (5 GBit/s) or USB 3.1 (10 GBit/s) and some legacy
16−USB 2.0 (480 MBit/s) busses just in case.
16+USB 2.0 (480 MBit/s) buses just in case.
1717
1818 That master/slave asymmetry was designed-in for a number of reasons, one
1919 being ease of use. It is not physically possible to mistake upstream and
@@ -42,7 +42,7 @@ two. One is intended for *general-purpose* drivers (exposed through · 22 unmodified lines
4242 driver frameworks), and the other is for drivers that are *part of the
4343 core*. Such core drivers include the *hub* driver (which manages trees
4444 of USB devices) and several different kinds of *host controller
45−drivers*, which control individual busses.
45+drivers*, which control individual buses.
4646
4747 The device model seen by USB drivers is relatively complex.
4848
Documentation/fb/fbcon.rst+24−18
@@ -39,11 +39,13 @@ Also, you will need to select at least one compiled-in font, but if · 38 unmodified lines
3939 you don't do anything, the kernel configuration tool will select one for you,
4040 usually an 8x16 font.
4141
42−GOTCHA: A common bug report is enabling the framebuffer without enabling the
43−framebuffer console. Depending on the driver, you may get a blanked or
44−garbled display, but the system still boots to completion. If you are
45−fortunate to have a driver that does not alter the graphics chip, then you
46−will still get a VGA console.
42+.. admonition:: GOTCHA
43+
44+ A common bug report is enabling the framebuffer without enabling the
45+ framebuffer console. Depending on the driver, you may get a blanked or
46+ garbled display, but the system still boots to completion. If you are
47+ fortunate to have a driver that does not alter the graphics chip, then you
48+ will still get a VGA console.
4749
4850 B. Loading
4951 ==========
@@ -74,6 +76,7 @@ Possible scenarios: · 24 unmodified lines
7476 over the console.
7577
7678 C. Boot options
79+===============
7780
7881 The framebuffer console has several, largely unknown, boot options
7982 that can change its behavior.
@@ -116,9 +119,10 @@ C. Boot options · 36 unmodified lines
116119 outside the given range will still be controlled by the standard
117120 console driver.
118121
119− NOTE: For x86 machines, the standard console is the VGA console which
120− is typically located on the same video card. Thus, the consoles that
121− are controlled by the VGA console will be garbled.
122+ .. note::
123+ For x86 machines, the standard console is the VGA console which
124+ is typically located on the same video card. Thus, the consoles that
125+ are controlled by the VGA console will be garbled.
122126
123127 4. fbcon=rotate:<n>
124128
@@ -140,10 +144,11 @@ C. Boot options · 15 unmodified lines
140144 Console rotation will only become available if Framebuffer Console
141145 Rotation support is compiled in your kernel.
142146
143− NOTE: This is purely console rotation. Any other applications that
144− use the framebuffer will remain at their 'normal' orientation.
145− Actually, the underlying fb driver is totally ignorant of console
146− rotation.
147+ .. note::
148+ This is purely console rotation. Any other applications that
149+ use the framebuffer will remain at their 'normal' orientation.
150+ Actually, the underlying fb driver is totally ignorant of console
151+ rotation.
147152
148153 5. fbcon=margin:<color>
149154
@@ -172,7 +177,8 @@ C. Boot options · 22 unmodified lines
172177 The value 'n' overrides the number of bootup logos. 0 disables the
173178 logo, and -1 gives the default which is the number of online CPUs.
174179
175−C. Attaching, Detaching and Unloading
180+D. Attaching, Detaching and Unloading
181+=====================================
176182
177183 Before going on to how to attach, detach and unload the framebuffer console, an
178184 illustration of the dependencies may help.
@@ -249,11 +255,11 @@ restored properly. The following is one of the several methods that you can do: · 70 unmodified lines
249255 echo 1 > /sys/class/vtconsole/vtcon1/bind
250256
251257 8. Once fbcon is unbound, all drivers registered to the system will also
252−become unbound. This means that fbcon and individual framebuffer drivers
253−can be unloaded or reloaded at will. Reloading the drivers or fbcon will
254−automatically bind the console, fbcon and the drivers together. Unloading
255−all the drivers without unloading fbcon will make it impossible for the
256−console to bind fbcon.
258+ become unbound. This means that fbcon and individual framebuffer drivers
259+ can be unloaded or reloaded at will. Reloading the drivers or fbcon will
260+ automatically bind the console, fbcon and the drivers together. Unloading
261+ all the drivers without unloading fbcon will make it impossible for the
262+ console to bind fbcon.
257263
258264 Notes for vesafb users:
259265 =======================
Documentation/features/core/eBPF-JIT/arch-support.txt+2−2
@@ -7,7 +7,7 @@ · 6 unmodified lines
77 | arch |status|
88 -----------------------
99 | alpha: | TODO |
10− | arc: | TODO |
10+ | arc: | ok |
1111 | arm: | ok |
1212 | arm64: | ok |
1313 | csky: | TODO |
@@ -18,7 +18,7 @@ · 4 unmodified lines
1818 | mips: | ok |
1919 | nios2: | TODO |
2020 | openrisc: | TODO |
21− | parisc: | TODO |
21+ | parisc: | ok |
2222 | powerpc: | ok |
2323 | riscv: | ok |
2424 | s390: | ok |
Documentation/features/core/mseal_sys_mappings/arch-support.txt+1−1
@@ -20,7 +20,7 @@ · 19 unmodified lines
2020 | openrisc: | N/A |
2121 | parisc: | TODO |
2222 | powerpc: | TODO |
23− | riscv: | TODO |
23+ | riscv: | ok |
2424 | s390: | ok |
2525 | sh: | N/A |
2626 | sparc: | TODO |
Documentation/features/core/thread-info-in-task/arch-support.txt+1−1
@@ -24,7 +24,7 @@ · 23 unmodified lines
2424 | s390: | ok |
2525 | sh: | TODO |
2626 | sparc: | TODO |
27− | um: | TODO |
27+ | um: | ok |
2828 | x86: | ok |
2929 | xtensa: | TODO |
3030 -----------------------
Documentation/features/core/tracehook/arch-support.txt+1−1
@@ -24,7 +24,7 @@ · 23 unmodified lines
2424 | s390: | ok |
2525 | sh: | ok |
2626 | sparc: | ok |
27− | um: | TODO |
27+ | um: | ok |
2828 | x86: | ok |
2929 | xtensa: | ok |
3030 -----------------------
Documentation/features/perf/kprobes-event/arch-support.txt+1−1
@@ -17,7 +17,7 @@ · 16 unmodified lines
1717 | microblaze: | TODO |
1818 | mips: | ok |
1919 | nios2: | TODO |
20− | openrisc: | TODO |
20+ | openrisc: | ok |
2121 | parisc: | ok |
2222 | powerpc: | ok |
2323 | riscv: | ok |
Documentation/features/time/clockevents/arch-support.txt+1−1
@@ -18,7 +18,7 @@ · 17 unmodified lines
1818 | mips: | ok |
1919 | nios2: | ok |
2020 | openrisc: | ok |
21− | parisc: | TODO |
21+ | parisc: | ok |
2222 | powerpc: | ok |
2323 | riscv: | ok |
2424 | s390: | ok |
Documentation/filesystems/erofs.rst+1−1
@@ -116,7 +116,7 @@ cache_strategy=%s Select a strategy for cached decompression from now on: · 115 unmodified lines
116116 cluster for further reading. It still does
117117 in-place I/O decompression for the rest
118118 compressed physical clusters;
119− readaround Cache the both ends of incomplete compressed
119+ readaround Cache both ends of incomplete compressed
120120 physical clusters for further reading.
121121 It still does in-place I/O decompression
122122 for the rest compressed physical clusters.
Documentation/filesystems/ext4/atomic_writes.rst+3−3
@@ -14,7 +14,7 @@ I/O) on regular files with extents, provided the underlying storage device · 13 unmodified lines
1414 supports hardware atomic writes. This is supported in the following two ways:
1515
1616 1. **Single-fsblock Atomic Writes**:
17− EXT4's supports atomic write operations with a single filesystem block since
17+ EXT4 supports atomic write operations with a single filesystem block since
1818 v6.13. In this the atomic write unit minimum and maximum sizes are both set
1919 to filesystem blocksize.
2020 e.g. doing atomic write of 16KB with 16KB filesystem blocksize on 64KB
@@ -50,7 +50,7 @@ Multi-fsblock Implementation Details · 29 unmodified lines
5050
5151 The bigalloc feature changes ext4 to allocate in units of multiple filesystem
5252 blocks, also known as clusters. With bigalloc each bit within block bitmap
53−represents cluster (power of 2 number of blocks) rather than individual
53+represents a cluster (power of 2 number of blocks) rather than individual
5454 filesystem blocks.
5555 EXT4 supports multi-fsblock atomic writes with bigalloc, subject to the
5656 following constraints. The minimum atomic write size is the larger of the fs
@@ -189,7 +189,7 @@ The write must be aligned to the filesystem's block size and not exceed the · 132 unmodified lines
189189 filesystem's maximum atomic write unit size.
190190 See ``generic_atomic_write_valid()`` for more details.
191191
192−``statx()`` system call with ``STATX_WRITE_ATOMIC`` flag can provides following
192+``statx()`` system call with ``STATX_WRITE_ATOMIC`` flag can provide following
193193 details:
194194
195195 * ``stx_atomic_write_unit_min``: Minimum size of an atomic write request.
Documentation/filesystems/gfs2-glocks.rst+1−1
@@ -105,7 +105,7 @@ go_unlocked Yes No · 104 unmodified lines
105105 Operations must not drop either the bit lock or the spinlock
106106 if its held on entry. go_dump and do_demote_ok must never block.
107107 Note that go_dump will only be called if the glock's state
108− indicates that it is caching uptodate data.
108+ indicates that it is caching up-to-date data.
109109
110110 Glock locking order within GFS2:
111111
Documentation/filesystems/hpfs.rst+1−1
@@ -65,7 +65,7 @@ are case sensitive, so for example when you create a file FOO, you can use · 64 unmodified lines
6565 'cat FOO', 'cat Foo', 'cat foo' or 'cat F*' but not 'cat f*'. Note, that you
6666 also won't be able to compile linux kernel (and maybe other things) on HPFS
6767 because kernel creates different files with names like bootsect.S and
68−bootsect.s. When searching for file thats name has characters >= 128, codepages
68+bootsect.s. When searching for file whose name has characters >= 128, codepages
6969 are used - see below.
7070 OS/2 ignores dots and spaces at the end of file name, so this driver does as
7171 well. If you create 'a. ...', the file 'a' will be created, but you can still
Documentation/filesystems/iomap/operations.rst+1−1
@@ -321,7 +321,7 @@ The fields are as follows: · 320 unmodified lines
321321 - ``writeback_submit``: Submit the previous built writeback context.
322322 Block based file systems should use the iomap_ioend_writeback_submit
323323 helper, other file system can implement their own.
324− File systems can optionall to hook into writeback bio submission.
324+ File systems can optionally hook into writeback bio submission.
325325 This might include pre-write space accounting updates, or installing
326326 a custom ``->bi_end_io`` function for internal purposes, such as
327327 deferring the ioend completion to a workqueue to run metadata update
Documentation/filesystems/ocfs2-online-filecheck.rst+10−10
@@ -58,33 +58,33 @@ inode, fixing inode and setting the size of result record history. · 57 unmodified lines
5858 # echo "<inode>" > /sys/fs/ocfs2/<devname>/filecheck/check
5959 # cat /sys/fs/ocfs2/<devname>/filecheck/check
6060
61−The output is like this::
61+ The output is like this::
6262
6363 INO DONE ERROR
6464 39502 1 GENERATION
6565
66− <INO> lists the inode numbers.
67− <DONE> indicates whether the operation has been finished.
68− <ERROR> says what kind of errors was found. For the detailed error numbers,
69− please refer to the file linux/fs/ocfs2/filecheck.h.
66+ <INO> lists the inode numbers.
67+ <DONE> indicates whether the operation has been finished.
68+ <ERROR> says what kind of errors was found. For the detailed error numbers,
69+ please refer to the file linux/fs/ocfs2/filecheck.h.
7070
7171 2. If you determine to fix this inode, do::
7272
7373 # echo "<inode>" > /sys/fs/ocfs2/<devname>/filecheck/fix
7474 # cat /sys/fs/ocfs2/<devname>/filecheck/fix
7575
76−The output is like this:::
76+ The output is like this::
7777
7878 INO DONE ERROR
7979 39502 1 SUCCESS
8080
81−This time, the <ERROR> column indicates whether this fix is successful or not.
81+ This time, the <ERROR> column indicates whether this fix is successful or not.
8282
8383 3. The record cache is used to store the history of check/fix results. It's
84−default size is 10, and can be adjust between the range of 10 ~ 100. You can
85−adjust the size like this::
84+ default size is 10, and can be adjust between the range of 10 ~ 100. You can
85+ adjust the size like this::
8686
87− # echo "<size>" > /sys/fs/ocfs2/<devname>/filecheck/set
87+ # echo "<size>" > /sys/fs/ocfs2/<devname>/filecheck/set
8888
8989 Fixing stuff
9090 ============
Documentation/filesystems/proc.rst+0−21
@@ -61,19 +61,6 @@ Preface · 60 unmodified lines
6161 0.1 Introduction/Credits
6262 ------------------------
6363
64−This documentation is part of a soon (or so we hope) to be released book on
65−the SuSE Linux distribution. As there is no complete documentation for the
66−/proc file system and we've used many freely available sources to write these
67−chapters, it seems only fair to give the work back to the Linux community.
68−This work is based on the 2.2.* kernel version and the upcoming 2.4.*. I'm
69−afraid it's still far from complete, but we hope it will be useful. As far as
70−we know, it is the first 'all-in-one' document about the /proc file system. It
71−is focused on the Intel x86 hardware, so if you are looking for PPC, ARM,
72−SPARC, AXP, etc., features, you probably won't find what you are looking for.
73−It also only covers IPv4 networking, not IPv6 nor other protocols - sorry. But
74−additions and patches are welcome and will be added to this document if you
75−mail them to Bodo.
76−
7764 We'd like to thank Alan Cox, Rik van Riel, and Alexey Kuznetsov and a lot of
7865 other people for help compiling this documentation. We'd also like to extend a
7966 special thank you to Andi Kleen for documentation, which we relied on heavily
@@ -81,17 +68,9 @@ to create this document, as well as the additional information he provided. · 1 unmodified line
8168 Thanks to everybody else who contributed source or docs to the Linux kernel
8269 and helped create a great piece of software... :)
8370
84−If you have any comments, corrections or additions, please don't hesitate to
85−contact Bodo Bauer at bb@ricochet.net. We'll be happy to add them to this
86−document.
87−
8871 The latest version of this document is available online at
8972 https://www.kernel.org/doc/html/latest/filesystems/proc.html
9073
91−If the above direction does not works for you, you could try the kernel
92−mailing list at linux-kernel@vger.kernel.org and/or try to reach me at
93−comandante@zaralinux.com.
94−
9574 0.2 Legal Stuff
9675 ---------------
9776
Documentation/filesystems/propagate_umount.txt+3−3
@@ -286,7 +286,7 @@ Trim_one(m) · 285 unmodified lines
286286 strip the "seen by Trim_ancestors" mark from m
287287 remove m from the Candidates list
288288 return
289−
289+
290290 remove_this = false
291291 found = false
292292 for each n in children(m)
@@ -312,7 +312,7 @@ Trim_ancestors(m) · 19 unmodified lines
312312 }
313313
314314 Terminating condition in the loop in Trim_ancestors() is correct,
315−since that that loop will never run into p belonging to U - p is always
315+since that loop will never run into p belonging to U - p is always
316316 an ancestor of argument of Trim_one() and since U is closed, the argument
317317 of Trim_one() would also have to belong to U. But Trim_one() is never
318318 called for elements of U. In other words, p belongs to S if and only
@@ -361,7 +361,7 @@ such removals. · 42 unmodified lines
361361 Proof: suppose S was non-shifting, x is a locked element of S, parent of x
362362 is not in S and S - {x} is not non-shifting. Then there is an element m
363363 in S - {x} and a subtree mounted strictly inside m, such that m contains
364−an element not in in S - {x}. Since S is non-shifting, everything in
364+an element not in S - {x}. Since S is non-shifting, everything in
365365 that subtree must belong to S. But that means that this subtree must
366366 contain x somewhere *and* that parent of x either belongs that subtree
367367 or is equal to m. Either way it must belong to S. Contradiction.
Documentation/filesystems/resctrl.rst+1−1
@@ -769,7 +769,7 @@ this would be dependent on number of cores the benchmark is run on. · 768 unmodified lines
769769 depending on # of threads:
770770
771771 For the same SKU in #1, a 'single thread, with 10% bandwidth' and '4
772−thread, with 10% bandwidth' can consume upto 10GBps and 40GBps although
772+thread, with 10% bandwidth' can consume up to 10GBps and 40GBps although
773773 they have same percentage bandwidth of 10%. This is simply because as
774774 threads start using more cores in an rdtgroup, the actual bandwidth may
775775 increase or vary although user specified bandwidth percentage is same.
Documentation/filesystems/sharedsubtree.rst+671−676
@@ -31,965 +31,960 @@ and versioned filesystem. · 30 unmodified lines
3131 -----------
3232
3333 Shared subtree provides four different flavors of mounts; struct vfsmount to be
34−precise
34+precise:
3535
36− a. shared mount
37− b. slave mount
38− c. private mount
39− d. unbindable mount
4036
37+a) A **shared mount** can be replicated to as many mountpoints and all the
38+ replicas continue to be exactly same.
4139
42−2a) A shared mount can be replicated to as many mountpoints and all the
43−replicas continue to be exactly same.
40+ Here is an example:
4441
45− Here is an example:
42+ Let's say /mnt has a mount that is shared::
4643
47− Let's say /mnt has a mount that is shared::
44+ # mount --make-shared /mnt
4845
49− mount --make-shared /mnt
46+ .. note::
47+ mount(8) command now supports the --make-shared flag,
48+ so the sample 'smount' program is no longer needed and has been
49+ removed.
5050
51− Note: mount(8) command now supports the --make-shared flag,
52− so the sample 'smount' program is no longer needed and has been
53− removed.
51+ ::
5452
55− ::
53+ # mount --bind /mnt /tmp
5654
57− # mount --bind /mnt /tmp
55+ The above command replicates the mount at /mnt to the mountpoint /tmp
56+ and the contents of both the mounts remain identical.
5857
59− The above command replicates the mount at /mnt to the mountpoint /tmp
60− and the contents of both the mounts remain identical.
58+ ::
6159
62− ::
60+ #ls /mnt
61+ a b c
6362
64− #ls /mnt
65− a b c
63+ #ls /tmp
64+ a b c
6665
67− #ls /tmp
68− a b c
66+ Now let's say we mount a device at /tmp/a::
6967
70− Now let's say we mount a device at /tmp/a::
68+ # mount /dev/sd0 /tmp/a
7169
72− # mount /dev/sd0 /tmp/a
70+ # ls /tmp/a
71+ t1 t2 t3
7372
74− #ls /tmp/a
75− t1 t2 t3
73+ # ls /mnt/a
74+ t1 t2 t3
7675
77− #ls /mnt/a
78− t1 t2 t3
76+ Note that the mount has propagated to the mount at /mnt as well.
7977
80− Note that the mount has propagated to the mount at /mnt as well.
78+ And the same is true even when /dev/sd0 is mounted on /mnt/a. The
79+ contents will be visible under /tmp/a too.
8180
82− And the same is true even when /dev/sd0 is mounted on /mnt/a. The
83− contents will be visible under /tmp/a too.
8481
82+b) A **slave mount** is like a shared mount except that mount and umount events
83+ only propagate towards it.
8584
86−2b) A slave mount is like a shared mount except that mount and umount events
87− only propagate towards it.
85+ All slave mounts have a master mount which is a shared.
8886
89− All slave mounts have a master mount which is a shared.
87+ Here is an example:
9088
91− Here is an example:
89+ Let's say /mnt has a mount which is shared::
9290
93− Let's say /mnt has a mount which is shared.
94− # mount --make-shared /mnt
91+ # mount --make-shared /mnt
9592
96− Let's bind mount /mnt to /tmp
97− # mount --bind /mnt /tmp
93+ Let's bind mount /mnt to /tmp::
9894
99− the new mount at /tmp becomes a shared mount and it is a replica of
100− the mount at /mnt.
95+ # mount --bind /mnt /tmp
10196
102− Now let's make the mount at /tmp; a slave of /mnt
103− # mount --make-slave /tmp
97+ the new mount at /tmp becomes a shared mount and it is a replica of
98+ the mount at /mnt.
10499
105− let's mount /dev/sd0 on /mnt/a
106− # mount /dev/sd0 /mnt/a
100+ Now let's make the mount at /tmp; a slave of /mnt::
107101
108− #ls /mnt/a
109− t1 t2 t3
102+ # mount --make-slave /tmp
110103
111− #ls /tmp/a
112− t1 t2 t3
104+ let's mount /dev/sd0 on /mnt/a::
113105
114− Note the mount event has propagated to the mount at /tmp
106+ # mount /dev/sd0 /mnt/a
115107
116− However let's see what happens if we mount something on the mount at /tmp
108+ # ls /mnt/a
109+ t1 t2 t3
117110
118− # mount /dev/sd1 /tmp/b
111+ # ls /tmp/a
112+ t1 t2 t3
119113
120− #ls /tmp/b
121− s1 s2 s3
114+ Note the mount event has propagated to the mount at /tmp
122115
123− #ls /mnt/b
116+ However let's see what happens if we mount something on the mount at
117+ /tmp::
124118
125− Note how the mount event has not propagated to the mount at
126− /mnt
119+ # mount /dev/sd1 /tmp/b
127120
121+ # ls /tmp/b
122+ s1 s2 s3
128123
129−2c) A private mount does not forward or receive propagation.
124+ # ls /mnt/b
130125
131− This is the mount we are familiar with. Its the default type.
126+ Note how the mount event has not propagated to the mount at
127+ /mnt
132128
133129
134−2d) A unbindable mount is a unbindable private mount
130+c) A **private mount** does not forward or receive propagation.
135131
136− let's say we have a mount at /mnt and we make it unbindable::
132+ This is the mount we are familiar with. Its the default type.
137133
138− # mount --make-unbindable /mnt
139134
140− Let's try to bind mount this mount somewhere else::
135+d) An **unbindable mount** is, as the name suggests, an unbindable private
136+ mount.
141137
142− # mount --bind /mnt /tmp
143− mount: wrong fs type, bad option, bad superblock on /mnt,
144− or too many mounted file systems
138+ let's say we have a mount at /mnt and we make it unbindable::
145139
146− Binding a unbindable mount is a invalid operation.
140+ # mount --make-unbindable /mnt
141+
142+ Let's try to bind mount this mount somewhere else::
143+
144+ # mount --bind /mnt /tmp mount: wrong fs type, bad option, bad
145+ superblock on /mnt, or too many mounted file systems
146+
147+ Binding a unbindable mount is a invalid operation.
147148
148149
149150 3) Setting mount states
150151 -----------------------
151152
152− The mount command (util-linux package) can be used to set mount
153− states::
153+The mount command (util-linux package) can be used to set mount
154+states::
154155
155− mount --make-shared mountpoint
156− mount --make-slave mountpoint
157− mount --make-private mountpoint
158− mount --make-unbindable mountpoint
156+ mount --make-shared mountpoint
157+ mount --make-slave mountpoint
158+ mount --make-private mountpoint
159+ mount --make-unbindable mountpoint
159160
160161
161162 4) Use cases
162163 ------------
163164
164− A) A process wants to clone its own namespace, but still wants to
165− access the CD that got mounted recently.
165+A) A process wants to clone its own namespace, but still wants to
166+ access the CD that got mounted recently.
166167
167− Solution:
168+ Solution:
168169
169− The system administrator can make the mount at /cdrom shared::
170+ The system administrator can make the mount at /cdrom shared::
170171
171− mount --bind /cdrom /cdrom
172− mount --make-shared /cdrom
172+ mount --bind /cdrom /cdrom
173+ mount --make-shared /cdrom
173174
174− Now any process that clones off a new namespace will have a
175− mount at /cdrom which is a replica of the same mount in the
176− parent namespace.
175+ Now any process that clones off a new namespace will have a
176+ mount at /cdrom which is a replica of the same mount in the
177+ parent namespace.
177178
178− So when a CD is inserted and mounted at /cdrom that mount gets
179− propagated to the other mount at /cdrom in all the other clone
180− namespaces.
179+ So when a CD is inserted and mounted at /cdrom that mount gets
180+ propagated to the other mount at /cdrom in all the other clone
181+ namespaces.
181182
182− B) A process wants its mounts invisible to any other process, but
183− still be able to see the other system mounts.
183+B) A process wants its mounts invisible to any other process, but
184+ still be able to see the other system mounts.
184185
185− Solution:
186+ Solution:
186187
187− To begin with, the administrator can mark the entire mount tree
188− as shareable::
188+ To begin with, the administrator can mark the entire mount tree
189+ as shareable::
189190
190− mount --make-rshared /
191+ mount --make-rshared /
191192
192− A new process can clone off a new namespace. And mark some part
193− of its namespace as slave::
193+ A new process can clone off a new namespace. And mark some part
194+ of its namespace as slave::
194195
195− mount --make-rslave /myprivatetree
196+ mount --make-rslave /myprivatetree
196197
197− Hence forth any mounts within the /myprivatetree done by the
198− process will not show up in any other namespace. However mounts
199− done in the parent namespace under /myprivatetree still shows
200− up in the process's namespace.
198+ Hence forth any mounts within the /myprivatetree done by the
199+ process will not show up in any other namespace. However mounts
200+ done in the parent namespace under /myprivatetree still shows
201+ up in the process's namespace.
201202
202203
203− Apart from the above semantics this feature provides the
204− building blocks to solve the following problems:
204+Apart from the above semantics this feature provides the
205+building blocks to solve the following problems:
205206
206− C) Per-user namespace
207+C) Per-user namespace
207208
208− The above semantics allows a way to share mounts across
209− namespaces. But namespaces are associated with processes. If
210− namespaces are made first class objects with user API to
211− associate/disassociate a namespace with userid, then each user
212− could have his/her own namespace and tailor it to his/her
213− requirements. This needs to be supported in PAM.
209+ The above semantics allows a way to share mounts across
210+ namespaces. But namespaces are associated with processes. If
211+ namespaces are made first class objects with user API to
212+ associate/disassociate a namespace with userid, then each user
213+ could have his/her own namespace and tailor it to his/her
214+ requirements. This needs to be supported in PAM.
214215
215− D) Versioned files
216+D) Versioned files
216217
217− If the entire mount tree is visible at multiple locations, then
218− an underlying versioning file system can return different
219− versions of the file depending on the path used to access that
220− file.
218+ If the entire mount tree is visible at multiple locations, then
219+ an underlying versioning file system can return different
220+ versions of the file depending on the path used to access that
221+ file.
221222
222− An example is::
223+ An example is::
223224
224− mount --make-shared /
225− mount --rbind / /view/v1
226− mount --rbind / /view/v2
227− mount --rbind / /view/v3
228− mount --rbind / /view/v4
225+ mount --make-shared /
226+ mount --rbind / /view/v1
227+ mount --rbind / /view/v2
228+ mount --rbind / /view/v3
229+ mount --rbind / /view/v4
229230
230− and if /usr has a versioning filesystem mounted, then that
231− mount appears at /view/v1/usr, /view/v2/usr, /view/v3/usr and
232− /view/v4/usr too
231+ and if /usr has a versioning filesystem mounted, then that
232+ mount appears at /view/v1/usr, /view/v2/usr, /view/v3/usr and
233+ /view/v4/usr too
233234
234− A user can request v3 version of the file /usr/fs/namespace.c
235− by accessing /view/v3/usr/fs/namespace.c . The underlying
236− versioning filesystem can then decipher that v3 version of the
237− filesystem is being requested and return the corresponding
238− inode.
235+ A user can request v3 version of the file /usr/fs/namespace.c
236+ by accessing /view/v3/usr/fs/namespace.c . The underlying
237+ versioning filesystem can then decipher that v3 version of the
238+ filesystem is being requested and return the corresponding
239+ inode.
239240
240241 5) Detailed semantics
241242 ---------------------
242− The section below explains the detailed semantics of
243− bind, rbind, move, mount, umount and clone-namespace operations.
244−
245− Note: the word 'vfsmount' and the noun 'mount' have been used
246− to mean the same thing, throughout this document.
243+The section below explains the detailed semantics of
244+bind, rbind, move, mount, umount and clone-namespace operations.
247245
248−5a) Mount states
246+.. Note::
247+ the word 'vfsmount' and the noun 'mount' have been used
248+ to mean the same thing, throughout this document.
249249
250− A given mount can be in one of the following states
250+a) Mount states
251251
252− 1) shared
253− 2) slave
254− 3) shared and slave
255− 4) private
256− 5) unbindable
252+ A **propagation event** is defined as event generated on a vfsmount
253+ that leads to mount or unmount actions in other vfsmounts.
257254
258− A 'propagation event' is defined as event generated on a vfsmount
259− that leads to mount or unmount actions in other vfsmounts.
255+ A **peer group** is defined as a group of vfsmounts that propagate
256+ events to each other.
260257
261− A 'peer group' is defined as a group of vfsmounts that propagate
262− events to each other.
258+ A given mount can be in one of the following states:
263259
264− (1) Shared mounts
260+ (1) Shared mounts
265261
266− A 'shared mount' is defined as a vfsmount that belongs to a
267− 'peer group'.
262+ A **shared mount** is defined as a vfsmount that belongs to a
263+ peer group.
268264
269− For example::
265+ For example::
270266
271− mount --make-shared /mnt
272− mount --bind /mnt /tmp
267+ mount --make-shared /mnt
268+ mount --bind /mnt /tmp
273269
274− The mount at /mnt and that at /tmp are both shared and belong
275− to the same peer group. Anything mounted or unmounted under
276− /mnt or /tmp reflect in all the other mounts of its peer
277− group.
270+ The mount at /mnt and that at /tmp are both shared and belong
271+ to the same peer group. Anything mounted or unmounted under
272+ /mnt or /tmp reflect in all the other mounts of its peer
273+ group.
278274
279275
280− (2) Slave mounts
276+ (2) Slave mounts
281277
282− A 'slave mount' is defined as a vfsmount that receives
283− propagation events and does not forward propagation events.
278+ A **slave mount** is defined as a vfsmount that receives
279+ propagation events and does not forward propagation events.
284280
285− A slave mount as the name implies has a master mount from which
286− mount/unmount events are received. Events do not propagate from
287− the slave mount to the master. Only a shared mount can be made
288− a slave by executing the following command::
281+ A slave mount as the name implies has a master mount from which
282+ mount/unmount events are received. Events do not propagate from
283+ the slave mount to the master. Only a shared mount can be made
284+ a slave by executing the following command::
289285
290− mount --make-slave mount
286+ mount --make-slave mount
291287
292− A shared mount that is made as a slave is no more shared unless
293− modified to become shared.
288+ A shared mount that is made as a slave is no more shared unless
289+ modified to become shared.
294290
295− (3) Shared and Slave
291+ (3) Shared and Slave
296292
297− A vfsmount can be both shared as well as slave. This state
298− indicates that the mount is a slave of some vfsmount, and
299− has its own peer group too. This vfsmount receives propagation
300− events from its master vfsmount, and also forwards propagation
301− events to its 'peer group' and to its slave vfsmounts.
293+ A vfsmount can be both **shared** as well as **slave**. This state
294+ indicates that the mount is a slave of some vfsmount, and
295+ has its own peer group too. This vfsmount receives propagation
296+ events from its master vfsmount, and also forwards propagation
297+ events to its 'peer group' and to its slave vfsmounts.
302298
303− Strictly speaking, the vfsmount is shared having its own
304− peer group, and this peer-group is a slave of some other
305− peer group.
299+ Strictly speaking, the vfsmount is shared having its own
300+ peer group, and this peer-group is a slave of some other
301+ peer group.
306302
307− Only a slave vfsmount can be made as 'shared and slave' by
308− either executing the following command::
303+ Only a slave vfsmount can be made as 'shared and slave' by
304+ either executing the following command::
309305
310− mount --make-shared mount
306+ mount --make-shared mount
311307
312− or by moving the slave vfsmount under a shared vfsmount.
308+ or by moving the slave vfsmount under a shared vfsmount.
313309
314− (4) Private mount
310+ (4) Private mount
315311
316− A 'private mount' is defined as vfsmount that does not
317− receive or forward any propagation events.
312+ A **private mount** is defined as vfsmount that does not
313+ receive or forward any propagation events.
318314
319− (5) Unbindable mount
315+ (5) Unbindable mount
320316
321− A 'unbindable mount' is defined as vfsmount that does not
322− receive or forward any propagation events and cannot
323− be bind mounted.
317+ A **unbindable mount** is defined as vfsmount that does not
318+ receive or forward any propagation events and cannot
319+ be bind mounted.
324320
325321
326− State diagram:
322+ State diagram:
327323
328− The state diagram below explains the state transition of a mount,
329− in response to various commands::
324+ The state diagram below explains the state transition of a mount,
325+ in response to various commands::
330326
331− -----------------------------------------------------------------------
332− | |make-shared | make-slave | make-private |make-unbindab|
333− --------------|------------|--------------|--------------|-------------|
334− |shared |shared |*slave/private| private | unbindable |
335− | | | | | |
336− |-------------|------------|--------------|--------------|-------------|
337− |slave |shared | **slave | private | unbindable |
338− | |and slave | | | |
339− |-------------|------------|--------------|--------------|-------------|
340− |shared |shared | slave | private | unbindable |
341− |and slave |and slave | | | |
342− |-------------|------------|--------------|--------------|-------------|
343− |private |shared | **private | private | unbindable |
344− |-------------|------------|--------------|--------------|-------------|
345− |unbindable |shared |**unbindable | private | unbindable |
346− ------------------------------------------------------------------------
327+ -----------------------------------------------------------------------
328+ | |make-shared | make-slave | make-private |make-unbindab|
329+ --------------|------------|--------------|--------------|-------------|
330+ |shared |shared |*slave/private| private | unbindable |
331+ | | | | | |
332+ |-------------|------------|--------------|--------------|-------------|
333+ |slave |shared | **slave | private | unbindable |
334+ | |and slave | | | |
335+ |-------------|------------|--------------|--------------|-------------|
336+ |shared |shared | slave | private | unbindable |
337+ |and slave |and slave | | | |
338+ |-------------|------------|--------------|--------------|-------------|
339+ |private |shared | **private | private | unbindable |
340+ |-------------|------------|--------------|--------------|-------------|
341+ |unbindable |shared |**unbindable | private | unbindable |
342+ ------------------------------------------------------------------------
347343
348− * if the shared mount is the only mount in its peer group, making it
349− slave, makes it private automatically. Note that there is no master to
350− which it can be slaved to.
344+ * if the shared mount is the only mount in its peer group, making it
345+ slave, makes it private automatically. Note that there is no master to
346+ which it can be slaved to.
351347
352− ** slaving a non-shared mount has no effect on the mount.
348+ ** slaving a non-shared mount has no effect on the mount.
353349
354− Apart from the commands listed below, the 'move' operation also changes
355− the state of a mount depending on type of the destination mount. Its
356− explained in section 5d.
350+ Apart from the commands listed below, the 'move' operation also changes
351+ the state of a mount depending on type of the destination mount. Its
352+ explained in section 5d.
357353
358−5b) Bind semantics
354+b) Bind semantics
359355
360− Consider the following command::
356+ Consider the following command::
361357
362− mount --bind A/a B/b
358+ mount --bind A/a B/b
363359
364− where 'A' is the source mount, 'a' is the dentry in the mount 'A', 'B'
365− is the destination mount and 'b' is the dentry in the destination mount.
360+ where 'A' is the source mount, 'a' is the dentry in the mount 'A', 'B'
361+ is the destination mount and 'b' is the dentry in the destination mount.
366362
367− The outcome depends on the type of mount of 'A' and 'B'. The table
368− below contains quick reference::
363+ The outcome depends on the type of mount of 'A' and 'B'. The table
364+ below contains quick reference::
369365
370− --------------------------------------------------------------------------
371− | BIND MOUNT OPERATION |
372− |************************************************************************|
373− |source(A)->| shared | private | slave | unbindable |
374− | dest(B) | | | | |
375− | | | | | | |
376− | v | | | | |
377− |************************************************************************|
378− | shared | shared | shared | shared & slave | invalid |
379− | | | | | |
380− |non-shared| shared | private | slave | invalid |
381− **************************************************************************
366+ --------------------------------------------------------------------------
367+ | BIND MOUNT OPERATION |
368+ |************************************************************************|
369+ |source(A)->| shared | private | slave | unbindable |
370+ | dest(B) | | | | |
371+ | | | | | | |
372+ | v | | | | |
373+ |************************************************************************|
374+ | shared | shared | shared | shared & slave | invalid |
375+ | | | | | |
376+ |non-shared| shared | private | slave | invalid |
377+ **************************************************************************
382378
383− Details:
379+ Details:
384380
385− 1. 'A' is a shared mount and 'B' is a shared mount. A new mount 'C'
386− which is clone of 'A', is created. Its root dentry is 'a' . 'C' is
387− mounted on mount 'B' at dentry 'b'. Also new mount 'C1', 'C2', 'C3' ...
388− are created and mounted at the dentry 'b' on all mounts where 'B'
389− propagates to. A new propagation tree containing 'C1',..,'Cn' is
390− created. This propagation tree is identical to the propagation tree of
391− 'B'. And finally the peer-group of 'C' is merged with the peer group
392− of 'A'.
381+ 1. 'A' is a shared mount and 'B' is a shared mount. A new mount 'C'
382+ which is clone of 'A', is created. Its root dentry is 'a' . 'C' is
383+ mounted on mount 'B' at dentry 'b'. Also new mount 'C1', 'C2', 'C3' ...
384+ are created and mounted at the dentry 'b' on all mounts where 'B'
385+ propagates to. A new propagation tree containing 'C1',..,'Cn' is
386+ created. This propagation tree is identical to the propagation tree of
387+ 'B'. And finally the peer-group of 'C' is merged with the peer group
388+ of 'A'.
393389
394− 2. 'A' is a private mount and 'B' is a shared mount. A new mount 'C'
395− which is clone of 'A', is created. Its root dentry is 'a'. 'C' is
396− mounted on mount 'B' at dentry 'b'. Also new mount 'C1', 'C2', 'C3' ...
397− are created and mounted at the dentry 'b' on all mounts where 'B'
398− propagates to. A new propagation tree is set containing all new mounts
399− 'C', 'C1', .., 'Cn' with exactly the same configuration as the
400− propagation tree for 'B'.
390+ 2. 'A' is a private mount and 'B' is a shared mount. A new mount 'C'
391+ which is clone of 'A', is created. Its root dentry is 'a'. 'C' is
392+ mounted on mount 'B' at dentry 'b'. Also new mount 'C1', 'C2', 'C3' ...
393+ are created and mounted at the dentry 'b' on all mounts where 'B'
394+ propagates to. A new propagation tree is set containing all new mounts
395+ 'C', 'C1', .., 'Cn' with exactly the same configuration as the
396+ propagation tree for 'B'.
401397
402− 3. 'A' is a slave mount of mount 'Z' and 'B' is a shared mount. A new
403− mount 'C' which is clone of 'A', is created. Its root dentry is 'a' .
404− 'C' is mounted on mount 'B' at dentry 'b'. Also new mounts 'C1', 'C2',
405− 'C3' ... are created and mounted at the dentry 'b' on all mounts where
406− 'B' propagates to. A new propagation tree containing the new mounts
407− 'C','C1',.. 'Cn' is created. This propagation tree is identical to the
408− propagation tree for 'B'. And finally the mount 'C' and its peer group
409− is made the slave of mount 'Z'. In other words, mount 'C' is in the
410− state 'slave and shared'.
411−
412− 4. 'A' is a unbindable mount and 'B' is a shared mount. This is a
413− invalid operation.
414−
415− 5. 'A' is a private mount and 'B' is a non-shared(private or slave or
416− unbindable) mount. A new mount 'C' which is clone of 'A', is created.
417− Its root dentry is 'a'. 'C' is mounted on mount 'B' at dentry 'b'.
418−
419− 6. 'A' is a shared mount and 'B' is a non-shared mount. A new mount 'C'
420− which is a clone of 'A' is created. Its root dentry is 'a'. 'C' is
421− mounted on mount 'B' at dentry 'b'. 'C' is made a member of the
422− peer-group of 'A'.
423−
424− 7. 'A' is a slave mount of mount 'Z' and 'B' is a non-shared mount. A
425− new mount 'C' which is a clone of 'A' is created. Its root dentry is
426− 'a'. 'C' is mounted on mount 'B' at dentry 'b'. Also 'C' is set as a
427− slave mount of 'Z'. In other words 'A' and 'C' are both slave mounts of
428− 'Z'. All mount/unmount events on 'Z' propagates to 'A' and 'C'. But
429− mount/unmount on 'A' do not propagate anywhere else. Similarly
430− mount/unmount on 'C' do not propagate anywhere else.
431−
432− 8. 'A' is a unbindable mount and 'B' is a non-shared mount. This is a
433− invalid operation. A unbindable mount cannot be bind mounted.
434−
435−5c) Rbind semantics
436−
437− rbind is same as bind. Bind replicates the specified mount. Rbind
438− replicates all the mounts in the tree belonging to the specified mount.
439− Rbind mount is bind mount applied to all the mounts in the tree.
440−
441− If the source tree that is rbind has some unbindable mounts,
442− then the subtree under the unbindable mount is pruned in the new
443− location.
444−
445− eg:
446−
447− let's say we have the following mount tree::
448−
449− A
450− / \
451− B C
452− / \ / \
453− D E F G
454−
455− Let's say all the mount except the mount C in the tree are
456− of a type other than unbindable.
457−
458− If this tree is rbound to say Z
459−
460− We will have the following tree at the new location::
461−
462− Z
463− |
464− A'
465− /
466− B' Note how the tree under C is pruned
467− / \ in the new location.
468− D' E'
469−
470−
471−
472−5d) Move semantics
473−
474− Consider the following command
475−
476− mount --move A B/b
398+ 3. 'A' is a slave mount of mount 'Z' and 'B' is a shared mount. A new
399+ mount 'C' which is clone of 'A', is created. Its root dentry is 'a' .
400+ 'C' is mounted on mount 'B' at dentry 'b'. Also new mounts 'C1', 'C2',
401+ 'C3' ... are created and mounted at the dentry 'b' on all mounts where
402+ 'B' propagates to. A new propagation tree containing the new mounts
403+ 'C','C1',.. 'Cn' is created. This propagation tree is identical to the
404+ propagation tree for 'B'. And finally the mount 'C' and its peer group
405+ is made the slave of mount 'Z'. In other words, mount 'C' is in the
406+ state 'slave and shared'.
407+
408+ 4. 'A' is a unbindable mount and 'B' is a shared mount. This is a
409+ invalid operation.
410+
411+ 5. 'A' is a private mount and 'B' is a non-shared(private or slave or
412+ unbindable) mount. A new mount 'C' which is clone of 'A', is created.
413+ Its root dentry is 'a'. 'C' is mounted on mount 'B' at dentry 'b'.
414+
415+ 6. 'A' is a shared mount and 'B' is a non-shared mount. A new mount 'C'
416+ which is a clone of 'A' is created. Its root dentry is 'a'. 'C' is
417+ mounted on mount 'B' at dentry 'b'. 'C' is made a member of the
418+ peer-group of 'A'.
419+
420+ 7. 'A' is a slave mount of mount 'Z' and 'B' is a non-shared mount. A
421+ new mount 'C' which is a clone of 'A' is created. Its root dentry is
422+ 'a'. 'C' is mounted on mount 'B' at dentry 'b'. Also 'C' is set as a
423+ slave mount of 'Z'. In other words 'A' and 'C' are both slave mounts of
424+ 'Z'. All mount/unmount events on 'Z' propagates to 'A' and 'C'. But
425+ mount/unmount on 'A' do not propagate anywhere else. Similarly
426+ mount/unmount on 'C' do not propagate anywhere else.
427+
428+ 8. 'A' is a unbindable mount and 'B' is a non-shared mount. This is a
429+ invalid operation. A unbindable mount cannot be bind mounted.
430+
431+c) Rbind semantics
432+
433+ rbind is same as bind. Bind replicates the specified mount. Rbind
434+ replicates all the mounts in the tree belonging to the specified mount.
435+ Rbind mount is bind mount applied to all the mounts in the tree.
436+
437+ If the source tree that is rbind has some unbindable mounts,
438+ then the subtree under the unbindable mount is pruned in the new
439+ location.
440+
441+ eg:
442+
443+ let's say we have the following mount tree::
444+
445+ A
446+ / \
447+ B C
448+ / \ / \
449+ D E F G
450+
451+ Let's say all the mount except the mount C in the tree are
452+ of a type other than unbindable.
453+
454+ If this tree is rbound to say Z
455+
456+ We will have the following tree at the new location::
457+
458+ Z
459+ |
460+ A'
461+ /
462+ B' Note how the tree under C is pruned
463+ / \ in the new location.
464+ D' E'
465+
466+
467+
468+d) Move semantics
469+
470+ Consider the following command::
471+
472+ mount --move A B/b
477473
478− where 'A' is the source mount, 'B' is the destination mount and 'b' is
479− the dentry in the destination mount.
474+ where 'A' is the source mount, 'B' is the destination mount and 'b' is
475+ the dentry in the destination mount.
480476
481− The outcome depends on the type of the mount of 'A' and 'B'. The table
482− below is a quick reference::
477+ The outcome depends on the type of the mount of 'A' and 'B'. The table
478+ below is a quick reference::
483479
484− ---------------------------------------------------------------------------
485− | MOVE MOUNT OPERATION |
486− |**************************************************************************
487− | source(A)->| shared | private | slave | unbindable |
488− | dest(B) | | | | |
489− | | | | | | |
490− | v | | | | |
491− |**************************************************************************
492− | shared | shared | shared |shared and slave| invalid |
493− | | | | | |
494− |non-shared| shared | private | slave | unbindable |
495− ***************************************************************************
480+ ---------------------------------------------------------------------------
481+ | MOVE MOUNT OPERATION |
482+ |**************************************************************************
483+ | source(A)->| shared | private | slave | unbindable |
484+ | dest(B) | | | | |
485+ | | | | | | |
486+ | v | | | | |
487+ |**************************************************************************
488+ | shared | shared | shared |shared and slave| invalid |
489+ | | | | | |
490+ |non-shared| shared | private | slave | unbindable |
491+ ***************************************************************************
496492
497− .. Note:: moving a mount residing under a shared mount is invalid.
493+ .. Note:: moving a mount residing under a shared mount is invalid.
498494
499− Details follow:
495+ Details follow:
500496
501− 1. 'A' is a shared mount and 'B' is a shared mount. The mount 'A' is
502− mounted on mount 'B' at dentry 'b'. Also new mounts 'A1', 'A2'...'An'
503− are created and mounted at dentry 'b' on all mounts that receive
504− propagation from mount 'B'. A new propagation tree is created in the
505− exact same configuration as that of 'B'. This new propagation tree
506− contains all the new mounts 'A1', 'A2'... 'An'. And this new
507− propagation tree is appended to the already existing propagation tree
508− of 'A'.
497+ 1. 'A' is a shared mount and 'B' is a shared mount. The mount 'A' is
498+ mounted on mount 'B' at dentry 'b'. Also new mounts 'A1', 'A2'...'An'
499+ are created and mounted at dentry 'b' on all mounts that receive
500+ propagation from mount 'B'. A new propagation tree is created in the
501+ exact same configuration as that of 'B'. This new propagation tree
502+ contains all the new mounts 'A1', 'A2'... 'An'. And this new
503+ propagation tree is appended to the already existing propagation tree
504+ of 'A'.
509505
510− 2. 'A' is a private mount and 'B' is a shared mount. The mount 'A' is
511− mounted on mount 'B' at dentry 'b'. Also new mount 'A1', 'A2'... 'An'
512− are created and mounted at dentry 'b' on all mounts that receive
513− propagation from mount 'B'. The mount 'A' becomes a shared mount and a
514− propagation tree is created which is identical to that of
515− 'B'. This new propagation tree contains all the new mounts 'A1',
516− 'A2'... 'An'.
506+ 2. 'A' is a private mount and 'B' is a shared mount. The mount 'A' is
507+ mounted on mount 'B' at dentry 'b'. Also new mount 'A1', 'A2'... 'An'
508+ are created and mounted at dentry 'b' on all mounts that receive
509+ propagation from mount 'B'. The mount 'A' becomes a shared mount and a
510+ propagation tree is created which is identical to that of
511+ 'B'. This new propagation tree contains all the new mounts 'A1',
512+ 'A2'... 'An'.
517513
518− 3. 'A' is a slave mount of mount 'Z' and 'B' is a shared mount. The
519− mount 'A' is mounted on mount 'B' at dentry 'b'. Also new mounts 'A1',
520− 'A2'... 'An' are created and mounted at dentry 'b' on all mounts that
521− receive propagation from mount 'B'. A new propagation tree is created
522− in the exact same configuration as that of 'B'. This new propagation
523− tree contains all the new mounts 'A1', 'A2'... 'An'. And this new
524− propagation tree is appended to the already existing propagation tree of
525− 'A'. Mount 'A' continues to be the slave mount of 'Z' but it also
526− becomes 'shared'.
514+ 3. 'A' is a slave mount of mount 'Z' and 'B' is a shared mount. The
515+ mount 'A' is mounted on mount 'B' at dentry 'b'. Also new mounts 'A1',
516+ 'A2'... 'An' are created and mounted at dentry 'b' on all mounts that
517+ receive propagation from mount 'B'. A new propagation tree is created
518+ in the exact same configuration as that of 'B'. This new propagation
519+ tree contains all the new mounts 'A1', 'A2'... 'An'. And this new
520+ propagation tree is appended to the already existing propagation tree of
521+ 'A'. Mount 'A' continues to be the slave mount of 'Z' but it also
522+ becomes 'shared'.
527523
528− 4. 'A' is a unbindable mount and 'B' is a shared mount. The operation
529− is invalid. Because mounting anything on the shared mount 'B' can
530− create new mounts that get mounted on the mounts that receive
531− propagation from 'B'. And since the mount 'A' is unbindable, cloning
532− it to mount at other mountpoints is not possible.
524+ 4. 'A' is a unbindable mount and 'B' is a shared mount. The operation
525+ is invalid. Because mounting anything on the shared mount 'B' can
526+ create new mounts that get mounted on the mounts that receive
527+ propagation from 'B'. And since the mount 'A' is unbindable, cloning
528+ it to mount at other mountpoints is not possible.
533529
534− 5. 'A' is a private mount and 'B' is a non-shared(private or slave or
535− unbindable) mount. The mount 'A' is mounted on mount 'B' at dentry 'b'.
530+ 5. 'A' is a private mount and 'B' is a non-shared(private or slave or
531+ unbindable) mount. The mount 'A' is mounted on mount 'B' at dentry 'b'.
536532
537− 6. 'A' is a shared mount and 'B' is a non-shared mount. The mount 'A'
538− is mounted on mount 'B' at dentry 'b'. Mount 'A' continues to be a
539− shared mount.
533+ 6. 'A' is a shared mount and 'B' is a non-shared mount. The mount 'A'
534+ is mounted on mount 'B' at dentry 'b'. Mount 'A' continues to be a
535+ shared mount.
540536
541− 7. 'A' is a slave mount of mount 'Z' and 'B' is a non-shared mount.
542− The mount 'A' is mounted on mount 'B' at dentry 'b'. Mount 'A'
543− continues to be a slave mount of mount 'Z'.
537+ 7. 'A' is a slave mount of mount 'Z' and 'B' is a non-shared mount.
538+ The mount 'A' is mounted on mount 'B' at dentry 'b'. Mount 'A'
539+ continues to be a slave mount of mount 'Z'.
544540
545− 8. 'A' is a unbindable mount and 'B' is a non-shared mount. The mount
546− 'A' is mounted on mount 'B' at dentry 'b'. Mount 'A' continues to be a
547− unbindable mount.
541+ 8. 'A' is a unbindable mount and 'B' is a non-shared mount. The mount
542+ 'A' is mounted on mount 'B' at dentry 'b'. Mount 'A' continues to be a
543+ unbindable mount.
548544
549−5e) Mount semantics
545+e) Mount semantics
550546
551− Consider the following command::
547+ Consider the following command::
552548
553− mount device B/b
549+ mount device B/b
554550
555− 'B' is the destination mount and 'b' is the dentry in the destination
556− mount.
551+ 'B' is the destination mount and 'b' is the dentry in the destination
552+ mount.
557553
558− The above operation is the same as bind operation with the exception
559− that the source mount is always a private mount.
554+ The above operation is the same as bind operation with the exception
555+ that the source mount is always a private mount.
560556
561557
562−5f) Unmount semantics
558+f) Unmount semantics
563559
564− Consider the following command::
560+ Consider the following command::
565561
566− umount A
562+ umount A
567563
568− where 'A' is a mount mounted on mount 'B' at dentry 'b'.
564+ where 'A' is a mount mounted on mount 'B' at dentry 'b'.
569565
570− If mount 'B' is shared, then all most-recently-mounted mounts at dentry
571− 'b' on mounts that receive propagation from mount 'B' and does not have
572− sub-mounts within them are unmounted.
566+ If mount 'B' is shared, then all most-recently-mounted mounts at dentry
567+ 'b' on mounts that receive propagation from mount 'B' and does not have
568+ sub-mounts within them are unmounted.
573569
574− Example: Let's say 'B1', 'B2', 'B3' are shared mounts that propagate to
575− each other.
570+ Example: Let's say 'B1', 'B2', 'B3' are shared mounts that propagate to
571+ each other.
576572
577− let's say 'A1', 'A2', 'A3' are first mounted at dentry 'b' on mount
578− 'B1', 'B2' and 'B3' respectively.
573+ let's say 'A1', 'A2', 'A3' are first mounted at dentry 'b' on mount
574+ 'B1', 'B2' and 'B3' respectively.
579575
580− let's say 'C1', 'C2', 'C3' are next mounted at the same dentry 'b' on
581− mount 'B1', 'B2' and 'B3' respectively.
576+ let's say 'C1', 'C2', 'C3' are next mounted at the same dentry 'b' on
577+ mount 'B1', 'B2' and 'B3' respectively.
582578
583− if 'C1' is unmounted, all the mounts that are most-recently-mounted on
584− 'B1' and on the mounts that 'B1' propagates-to are unmounted.
579+ if 'C1' is unmounted, all the mounts that are most-recently-mounted on
580+ 'B1' and on the mounts that 'B1' propagates-to are unmounted.
585581
586− 'B1' propagates to 'B2' and 'B3'. And the most recently mounted mount
587− on 'B2' at dentry 'b' is 'C2', and that of mount 'B3' is 'C3'.
582+ 'B1' propagates to 'B2' and 'B3'. And the most recently mounted mount
583+ on 'B2' at dentry 'b' is 'C2', and that of mount 'B3' is 'C3'.
588584
589− So all 'C1', 'C2' and 'C3' should be unmounted.
585+ So all 'C1', 'C2' and 'C3' should be unmounted.
590586
591− If any of 'C2' or 'C3' has some child mounts, then that mount is not
592− unmounted, but all other mounts are unmounted. However if 'C1' is told
593− to be unmounted and 'C1' has some sub-mounts, the umount operation is
594− failed entirely.
587+ If any of 'C2' or 'C3' has some child mounts, then that mount is not
588+ unmounted, but all other mounts are unmounted. However if 'C1' is told
589+ to be unmounted and 'C1' has some sub-mounts, the umount operation is
590+ failed entirely.
595591
596−5g) Clone Namespace
592+g) Clone Namespace
597593
598− A cloned namespace contains all the mounts as that of the parent
599− namespace.
594+ A cloned namespace contains all the mounts as that of the parent
595+ namespace.
600596
601− Let's say 'A' and 'B' are the corresponding mounts in the parent and the
602− child namespace.
597+ Let's say 'A' and 'B' are the corresponding mounts in the parent and the
598+ child namespace.
603599
604− If 'A' is shared, then 'B' is also shared and 'A' and 'B' propagate to
605− each other.
600+ If 'A' is shared, then 'B' is also shared and 'A' and 'B' propagate to
601+ each other.
606602
607− If 'A' is a slave mount of 'Z', then 'B' is also the slave mount of
608− 'Z'.
603+ If 'A' is a slave mount of 'Z', then 'B' is also the slave mount of
604+ 'Z'.
609605
610− If 'A' is a private mount, then 'B' is a private mount too.
606+ If 'A' is a private mount, then 'B' is a private mount too.
611607
612− If 'A' is unbindable mount, then 'B' is a unbindable mount too.
608+ If 'A' is unbindable mount, then 'B' is a unbindable mount too.
613609
614610
615611 6) Quiz
616612 -------
617613
618− A. What is the result of the following command sequence?
614+A. What is the result of the following command sequence?
619615
620− ::
616+ ::
621617
622− mount --bind /mnt /mnt
623− mount --make-shared /mnt
624− mount --bind /mnt /tmp
625− mount --move /tmp /mnt/1
618+ mount --bind /mnt /mnt
619+ mount --make-shared /mnt
620+ mount --bind /mnt /tmp
621+ mount --move /tmp /mnt/1
626622
627− what should be the contents of /mnt /mnt/1 /mnt/1/1 should be?
628− Should they all be identical? or should /mnt and /mnt/1 be
629− identical only?
623+ what should be the contents of /mnt /mnt/1 /mnt/1/1 should be?
624+ Should they all be identical? or should /mnt and /mnt/1 be
625+ identical only?
630626
631627
632− B. What is the result of the following command sequence?
628+B. What is the result of the following command sequence?
633629
634− ::
630+ ::
635631
636− mount --make-rshared /
637− mkdir -p /v/1
638− mount --rbind / /v/1
632+ mount --make-rshared /
633+ mkdir -p /v/1
634+ mount --rbind / /v/1
639635
640− what should be the content of /v/1/v/1 be?
636+ what should be the content of /v/1/v/1 be?
641637
642638
643− C. What is the result of the following command sequence?
639+C. What is the result of the following command sequence?
644640
645− ::
641+ ::
646642
647− mount --bind /mnt /mnt
648− mount --make-shared /mnt
649− mkdir -p /mnt/1/2/3 /mnt/1/test
650− mount --bind /mnt/1 /tmp
651− mount --make-slave /mnt
652− mount --make-shared /mnt
653− mount --bind /mnt/1/2 /tmp1
654− mount --make-slave /mnt
643+ mount --bind /mnt /mnt
644+ mount --make-shared /mnt
645+ mkdir -p /mnt/1/2/3 /mnt/1/test
646+ mount --bind /mnt/1 /tmp
647+ mount --make-slave /mnt
648+ mount --make-shared /mnt
649+ mount --bind /mnt/1/2 /tmp1
650+ mount --make-slave /mnt
655651
656− At this point we have the first mount at /tmp and
657− its root dentry is 1. Let's call this mount 'A'
658− And then we have a second mount at /tmp1 with root
659− dentry 2. Let's call this mount 'B'
660− Next we have a third mount at /mnt with root dentry
661− mnt. Let's call this mount 'C'
652+ At this point we have the first mount at /tmp and
653+ its root dentry is 1. Let's call this mount 'A'
654+ And then we have a second mount at /tmp1 with root
655+ dentry 2. Let's call this mount 'B'
656+ Next we have a third mount at /mnt with root dentry
657+ mnt. Let's call this mount 'C'
662658
663− 'B' is the slave of 'A' and 'C' is a slave of 'B'
664− A -> B -> C
659+ 'B' is the slave of 'A' and 'C' is a slave of 'B'
660+ A -> B -> C
665661
666− at this point if we execute the following command
662+ at this point if we execute the following command::
667663
668− mount --bind /bin /tmp/test
664+ mount --bind /bin /tmp/test
669665
670− The mount is attempted on 'A'
666+ The mount is attempted on 'A'
671667
672− will the mount propagate to 'B' and 'C' ?
668+ will the mount propagate to 'B' and 'C' ?
673669
674− what would be the contents of
675− /mnt/1/test be?
670+ what would be the contents of
671+ /mnt/1/test be?
676672
677673 7) FAQ
678674 ------
679675
680− Q1. Why is bind mount needed? How is it different from symbolic links?
681− symbolic links can get stale if the destination mount gets
682− unmounted or moved. Bind mounts continue to exist even if the
683− other mount is unmounted or moved.
676+1. Why is bind mount needed? How is it different from symbolic links?
684677
685− Q2. Why can't the shared subtree be implemented using exportfs?
678+ symbolic links can get stale if the destination mount gets
679+ unmounted or moved. Bind mounts continue to exist even if the
680+ other mount is unmounted or moved.
686681
687− exportfs is a heavyweight way of accomplishing part of what
688− shared subtree can do. I cannot imagine a way to implement the
689− semantics of slave mount using exportfs?
682+2. Why can't the shared subtree be implemented using exportfs?
690683
691− Q3 Why is unbindable mount needed?
684+ exportfs is a heavyweight way of accomplishing part of what
685+ shared subtree can do. I cannot imagine a way to implement the
686+ semantics of slave mount using exportfs?
692687
693− Let's say we want to replicate the mount tree at multiple
694− locations within the same subtree.
688+3. Why is unbindable mount needed?
695689
696− if one rbind mounts a tree within the same subtree 'n' times
697− the number of mounts created is an exponential function of 'n'.
698− Having unbindable mount can help prune the unneeded bind
699− mounts. Here is an example.
690+ Let's say we want to replicate the mount tree at multiple
691+ locations within the same subtree.
700692
701− step 1:
702− let's say the root tree has just two directories with
703− one vfsmount::
693+ if one rbind mounts a tree within the same subtree 'n' times
694+ the number of mounts created is an exponential function of 'n'.
695+ Having unbindable mount can help prune the unneeded bind
696+ mounts. Here is an example.
704697
705− root
706− / \
707− tmp usr
698+ step 1:
699+ let's say the root tree has just two directories with
700+ one vfsmount::
708701
709− And we want to replicate the tree at multiple
710− mountpoints under /root/tmp
702+ root
703+ / \
704+ tmp usr
711705
712− step 2:
713− ::
706+ And we want to replicate the tree at multiple
707+ mountpoints under /root/tmp
714708
709+ step 2:
710+ ::
715711
716− mount --make-shared /root
717712
718− mkdir -p /tmp/m1
713+ mount --make-shared /root
719714
720− mount --rbind /root /tmp/m1
715+ mkdir -p /tmp/m1
721716
722− the new tree now looks like this::
717+ mount --rbind /root /tmp/m1
723718
724− root
725− / \
726− tmp usr
727− /
728− m1
729− / \
730− tmp usr
731− /
732− m1
719+ the new tree now looks like this::
733720
734− it has two vfsmounts
721+ root
722+ / \
723+ tmp usr
724+ /
725+ m1
726+ / \
727+ tmp usr
728+ /
729+ m1
735730
736− step 3:
737− ::
731+ it has two vfsmounts
738732
739− mkdir -p /tmp/m2
740− mount --rbind /root /tmp/m2
733+ step 3:
734+ ::
741735
742− the new tree now looks like this::
736+ mkdir -p /tmp/m2
737+ mount --rbind /root /tmp/m2
743738
744− root
745− / \
746− tmp usr
747− / \
748− m1 m2
749− / \ / \
750− tmp usr tmp usr
751− / \ /
752− m1 m2 m1
753− / \ / \
754− tmp usr tmp usr
755− / / \
756− m1 m1 m2
757− / \
758− tmp usr
759− / \
760− m1 m2
739+ the new tree now looks like this::
761740
762− it has 6 vfsmounts
741+ root
742+ / \
743+ tmp usr
744+ / \
745+ m1 m2
746+ / \ / \
747+ tmp usr tmp usr
748+ / \ /
749+ m1 m2 m1
750+ / \ / \
751+ tmp usr tmp usr
752+ / / \
753+ m1 m1 m2
754+ / \
755+ tmp usr
756+ / \
757+ m1 m2
763758
764− step 4:
765− ::
766− mkdir -p /tmp/m3
767− mount --rbind /root /tmp/m3
759+ it has 6 vfsmounts
768760
769− I won't draw the tree..but it has 24 vfsmounts
761+ step 4:
762+ ::
770763
764+ mkdir -p /tmp/m3
765+ mount --rbind /root /tmp/m3
771766
772− at step i the number of vfsmounts is V[i] = i*V[i-1].
773− This is an exponential function. And this tree has way more
774− mounts than what we really needed in the first place.
767+ I won't draw the tree..but it has 24 vfsmounts
775768
776− One could use a series of umount at each step to prune
777− out the unneeded mounts. But there is a better solution.
778− Unclonable mounts come in handy here.
779769
780− step 1:
781− let's say the root tree has just two directories with
782− one vfsmount::
770+ at step i the number of vfsmounts is V[i] = i*V[i-1].
771+ This is an exponential function. And this tree has way more
772+ mounts than what we really needed in the first place.
783773
784− root
785− / \
786− tmp usr
774+ One could use a series of umount at each step to prune
775+ out the unneeded mounts. But there is a better solution.
776+ Unclonable mounts come in handy here.
787777
788− How do we set up the same tree at multiple locations under
789− /root/tmp
778+ step 1:
779+ let's say the root tree has just two directories with
780+ one vfsmount::
790781
791− step 2:
792− ::
782+ root
783+ / \
784+ tmp usr
793785
786+ How do we set up the same tree at multiple locations under
787+ /root/tmp
794788
795− mount --bind /root/tmp /root/tmp
789+ step 2:
790+ ::
796791
797− mount --make-rshared /root
798− mount --make-unbindable /root/tmp
799792
800− mkdir -p /tmp/m1
793+ mount --bind /root/tmp /root/tmp
801794
802− mount --rbind /root /tmp/m1
795+ mount --make-rshared /root
796+ mount --make-unbindable /root/tmp
803797
804− the new tree now looks like this::
798+ mkdir -p /tmp/m1
805799
806− root
807− / \
808− tmp usr
809− /
810− m1
811− / \
812− tmp usr
800+ mount --rbind /root /tmp/m1
813801
814− step 3:
815− ::
802+ the new tree now looks like this::
816803
817− mkdir -p /tmp/m2
818− mount --rbind /root /tmp/m2
804+ root
805+ / \
806+ tmp usr
807+ /
808+ m1
809+ / \
810+ tmp usr
819811
820− the new tree now looks like this::
812+ step 3:
813+ ::
821814
822− root
823− / \
824− tmp usr
825− / \
826− m1 m2
827− / \ / \
828− tmp usr tmp usr
815+ mkdir -p /tmp/m2
816+ mount --rbind /root /tmp/m2
829817
830− step 4:
831− ::
818+ the new tree now looks like this::
832819
833− mkdir -p /tmp/m3
834− mount --rbind /root /tmp/m3
820+ root
821+ / \
822+ tmp usr
823+ / \
824+ m1 m2
825+ / \ / \
826+ tmp usr tmp usr
835827
836− the new tree now looks like this::
828+ step 4:
829+ ::
837830
838− root
839− / \
840− tmp usr
841− / \ \
842− m1 m2 m3
843− / \ / \ / \
844− tmp usr tmp usr tmp usr
831+ mkdir -p /tmp/m3
832+ mount --rbind /root /tmp/m3
833+
834+ the new tree now looks like this::
835+
836+ root
837+ / \
838+ tmp usr
839+ / \ \
840+ m1 m2 m3
841+ / \ / \ / \
842+ tmp usr tmp usr tmp usr
845843
846844 8) Implementation
847845 -----------------
848846
849−8A) Datastructure
847+A) Datastructure
848+
849+ Several new fields are introduced to struct vfsmount:
850+
851+ ->mnt_share
852+ Links together all the mount to/from which this vfsmount
853+ send/receives propagation events.
850854
851− 4 new fields are introduced to struct vfsmount:
855+ ->mnt_slave_list
856+ Links all the mounts to which this vfsmount propagates
857+ to.
852858
853− * ->mnt_share
854− * ->mnt_slave_list
855− * ->mnt_slave
856− * ->mnt_master
859+ ->mnt_slave
860+ Links together all the slaves that its master vfsmount
861+ propagates to.
857862
858− ->mnt_share
859− links together all the mount to/from which this vfsmount
860− send/receives propagation events.
863+ ->mnt_master
864+ Points to the master vfsmount from which this vfsmount
865+ receives propagation.
861866
862− ->mnt_slave_list
863− links all the mounts to which this vfsmount propagates
864− to.
867+ ->mnt_flags
868+ Takes two more flags to indicate the propagation status of
869+ the vfsmount. MNT_SHARE indicates that the vfsmount is a shared
870+ vfsmount. MNT_UNCLONABLE indicates that the vfsmount cannot be
871+ replicated.
865872
866− ->mnt_slave
867− links together all the slaves that its master vfsmount
868− propagates to.
873+ All the shared vfsmounts in a peer group form a cyclic list through
874+ ->mnt_share.
869875
870− ->mnt_master
871− points to the master vfsmount from which this vfsmount
872− receives propagation.
876+ All vfsmounts with the same ->mnt_master form on a cyclic list anchored
877+ in ->mnt_master->mnt_slave_list and going through ->mnt_slave.
873878
874− ->mnt_flags
875− takes two more flags to indicate the propagation status of
876− the vfsmount. MNT_SHARE indicates that the vfsmount is a shared
877− vfsmount. MNT_UNCLONABLE indicates that the vfsmount cannot be
878− replicated.
879+ ->mnt_master can point to arbitrary (and possibly different) members
880+ of master peer group. To find all immediate slaves of a peer group
881+ you need to go through _all_ ->mnt_slave_list of its members.
882+ Conceptually it's just a single set - distribution among the
883+ individual lists does not affect propagation or the way propagation
884+ tree is modified by operations.
879885
880− All the shared vfsmounts in a peer group form a cyclic list through
881− ->mnt_share.
886+ All vfsmounts in a peer group have the same ->mnt_master. If it is
887+ non-NULL, they form a contiguous (ordered) segment of slave list.
882888
883− All vfsmounts with the same ->mnt_master form on a cyclic list anchored
884− in ->mnt_master->mnt_slave_list and going through ->mnt_slave.
889+ A example propagation tree looks as shown in the figure below.
885890
886− ->mnt_master can point to arbitrary (and possibly different) members
887− of master peer group. To find all immediate slaves of a peer group
888− you need to go through _all_ ->mnt_slave_list of its members.
889− Conceptually it's just a single set - distribution among the
890− individual lists does not affect propagation or the way propagation
891− tree is modified by operations.
891+ .. note::
892+ Though it looks like a forest, if we consider all the shared
893+ mounts as a conceptual entity called 'pnode', it becomes a tree.
892894
893− All vfsmounts in a peer group have the same ->mnt_master. If it is
894− non-NULL, they form a contiguous (ordered) segment of slave list.
895+ ::
895896
896− A example propagation tree looks as shown in the figure below.
897− [ NOTE: Though it looks like a forest, if we consider all the shared
898− mounts as a conceptual entity called 'pnode', it becomes a tree]::
899897
898+ A <--> B <--> C <---> D
899+ /|\ /| |\
900+ / F G J K H I
901+ /
902+ E<-->K
903+ /|\
904+ M L N
900905
901− A <--> B <--> C <---> D
902− /|\ /| |\
903− / F G J K H I
904− /
905− E<-->K
906− /|\
907− M L N
906+ In the above figure A,B,C and D all are shared and propagate to each
907+ other. 'A' has got 3 slave mounts 'E' 'F' and 'G' 'C' has got 2 slave
908+ mounts 'J' and 'K' and 'D' has got two slave mounts 'H' and 'I'.
909+ 'E' is also shared with 'K' and they propagate to each other. And
910+ 'K' has 3 slaves 'M', 'L' and 'N'
908911
909− In the above figure A,B,C and D all are shared and propagate to each
910− other. 'A' has got 3 slave mounts 'E' 'F' and 'G' 'C' has got 2 slave
911− mounts 'J' and 'K' and 'D' has got two slave mounts 'H' and 'I'.
912− 'E' is also shared with 'K' and they propagate to each other. And
913− 'K' has 3 slaves 'M', 'L' and 'N'
912+ A's ->mnt_share links with the ->mnt_share of 'B' 'C' and 'D'
914913
915− A's ->mnt_share links with the ->mnt_share of 'B' 'C' and 'D'
914+ A's ->mnt_slave_list links with ->mnt_slave of 'E', 'K', 'F' and 'G'
916915
917− A's ->mnt_slave_list links with ->mnt_slave of 'E', 'K', 'F' and 'G'
916+ E's ->mnt_share links with ->mnt_share of K
918917
919− E's ->mnt_share links with ->mnt_share of K
918+ 'E', 'K', 'F', 'G' have their ->mnt_master point to struct vfsmount of 'A'
920919
921− 'E', 'K', 'F', 'G' have their ->mnt_master point to struct vfsmount of 'A'
920+ 'M', 'L', 'N' have their ->mnt_master point to struct vfsmount of 'K'
922921
923− 'M', 'L', 'N' have their ->mnt_master point to struct vfsmount of 'K'
922+ K's ->mnt_slave_list links with ->mnt_slave of 'M', 'L' and 'N'
924923
925− K's ->mnt_slave_list links with ->mnt_slave of 'M', 'L' and 'N'
924+ C's ->mnt_slave_list links with ->mnt_slave of 'J' and 'K'
926925
927− C's ->mnt_slave_list links with ->mnt_slave of 'J' and 'K'
926+ J and K's ->mnt_master points to struct vfsmount of C
928927
929− J and K's ->mnt_master points to struct vfsmount of C
928+ and finally D's ->mnt_slave_list links with ->mnt_slave of 'H' and 'I'
930929
931− and finally D's ->mnt_slave_list links with ->mnt_slave of 'H' and 'I'
930+ 'H' and 'I' have their ->mnt_master pointing to struct vfsmount of 'D'.
932931
933− 'H' and 'I' have their ->mnt_master pointing to struct vfsmount of 'D'.
934932
933+ NOTE: The propagation tree is orthogonal to the mount tree.
935934
936− NOTE: The propagation tree is orthogonal to the mount tree.
935+B) Locking:
937936
938−8B Locking:
937+ ->mnt_share, ->mnt_slave, ->mnt_slave_list, ->mnt_master are protected
938+ by namespace_sem (exclusive for modifications, shared for reading).
939939
940− ->mnt_share, ->mnt_slave, ->mnt_slave_list, ->mnt_master are protected
941− by namespace_sem (exclusive for modifications, shared for reading).
940+ Normally we have ->mnt_flags modifications serialized by vfsmount_lock.
941+ There are two exceptions: do_add_mount() and clone_mnt().
942+ The former modifies a vfsmount that has not been visible in any shared
943+ data structures yet.
944+ The latter holds namespace_sem and the only references to vfsmount
945+ are in lists that can't be traversed without namespace_sem.
942946
943− Normally we have ->mnt_flags modifications serialized by vfsmount_lock.
944− There are two exceptions: do_add_mount() and clone_mnt().
945− The former modifies a vfsmount that has not been visible in any shared
946− data structures yet.
947− The latter holds namespace_sem and the only references to vfsmount
948− are in lists that can't be traversed without namespace_sem.
947+C) Algorithm:
949948
950−8C Algorithm:
949+ The crux of the implementation resides in rbind/move operation.
951950
952− The crux of the implementation resides in rbind/move operation.
951+ The overall algorithm breaks the operation into 3 phases: (look at
952+ attach_recursive_mnt() and propagate_mnt())
953953
954− The overall algorithm breaks the operation into 3 phases: (look at
955− attach_recursive_mnt() and propagate_mnt())
954+ 1. Prepare phase.
956955
957− 1. prepare phase.
958− 2. commit phases.
959− 3. abort phases.
956+ For each mount in the source tree:
960957
961− Prepare phase:
958+ a) Create the necessary number of mount trees to
959+ be attached to each of the mounts that receive
960+ propagation from the destination mount.
961+ b) Do not attach any of the trees to its destination.
962+ However note down its ->mnt_parent and ->mnt_mountpoint
963+ c) Link all the new mounts to form a propagation tree that
964+ is identical to the propagation tree of the destination
965+ mount.
962966
963− for each mount in the source tree:
967+ If this phase is successful, there should be 'n' new
968+ propagation trees; where 'n' is the number of mounts in the
969+ source tree. Go to the commit phase
964970
965− a) Create the necessary number of mount trees to
966− be attached to each of the mounts that receive
967− propagation from the destination mount.
968− b) Do not attach any of the trees to its destination.
969− However note down its ->mnt_parent and ->mnt_mountpoint
970− c) Link all the new mounts to form a propagation tree that
971− is identical to the propagation tree of the destination
972− mount.
971+ Also there should be 'm' new mount trees, where 'm' is
972+ the number of mounts to which the destination mount
973+ propagates to.
973974
974− If this phase is successful, there should be 'n' new
975− propagation trees; where 'n' is the number of mounts in the
976− source tree. Go to the commit phase
975+ If any memory allocations fail, go to the abort phase.
977976
978− Also there should be 'm' new mount trees, where 'm' is
979− the number of mounts to which the destination mount
980− propagates to.
977+ 2. Commit phase.
981978
982− if any memory allocations fail, go to the abort phase.
979+ Attach each of the mount trees to their corresponding
980+ destination mounts.
983981
984− Commit phase
985− attach each of the mount trees to their corresponding
986− destination mounts.
982+ 3. Abort phase.
987983
988− Abort phase
989− delete all the newly created trees.
984+ Delete all the newly created trees.
990985
991− .. Note::
992− all the propagation related functionality resides in the file pnode.c
986+ .. Note::
987+ all the propagation related functionality resides in the file pnode.c
993988
994989
995990 ------------------------------------------------------------------------
Documentation/filesystems/sysfs.rst+19−6
@@ -243,8 +243,8 @@ Other notes: · 242 unmodified lines
243243 - show() methods should return the number of bytes printed into the
244244 buffer.
245245
246−- show() should only use sysfs_emit() or sysfs_emit_at() when formatting
247− the value to be returned to user space.
246+- New implementations of show() methods should only use sysfs_emit() or
247+ sysfs_emit_at() when formatting the value to be returned to user space.
248248
249249 - store() should return the number of bytes used from the buffer. If the
250250 entire buffer has been used, just return the count argument.
@@ -299,7 +299,6 @@ The top level sysfs directory looks like:: · 48 unmodified lines
299299 hypervisor/
300300 kernel/
301301 module/
302− net/
303302 power/
304303
305304 devices/ contains a filesystem representation of the device tree. It maps
@@ -313,7 +312,7 @@ kernel. Each bus's directory contains two subdirectories:: · 7 unmodified lines
313312 drivers/
314313
315314 devices/ contains symlinks for each device discovered in the system
316−that point to the device's directory under root/.
315+that point to the device's directory under /sys/devices.
317316
318317 drivers/ contains a directory for each device driver that is loaded
319318 for devices on that particular bus (this assumes that drivers do not
@@ -328,15 +327,29 @@ loaded system modules, for both builtin and loadable modules. · 8 unmodified lines
328327
329328 dev/ contains two directories: char/ and block/. Inside these two
330329 directories there are symlinks named <major>:<minor>. These symlinks
331−point to the sysfs directory for the given device. /sys/dev provides a
330+point to the directories under /sys/devices for each device. /sys/dev provides a
332331 quick way to lookup the sysfs interface for a device from the result of
333332 a stat(2) operation.
334333
335334 More information on driver-model specific features can be found in
336335 Documentation/driver-api/driver-model/.
337336
337+block/ contains symlinks to all the block devices discovered on the system.
338+These symlinks point to directories under /sys/devices.
338339
339−TODO: Finish this section.
340+class/ contains a directory for each device class, grouped by functional type.
341+Each directory in class/ contains symlinks to devices in the /sys/devices directory.
342+
343+firmware/ contains system firmware data and configuration such as firmware tables,
344+ACPI information, and device tree data.
345+
346+hypervisor/ contains virtualization platform information and provides an interface to
347+the underlying hypervisor. It is only present when running on a virtual machine.
348+
349+kernel/ contains runtime kernel parameters, configuration settings, and status.
350+
351+power/ contains power management subsystem information including
352+sleep states, suspend/resume capabilities, and policies.
340353
341354
342355 Current Interfaces
Documentation/filesystems/xfs/xfs-online-fsck-design.rst+4−4
@@ -454,7 +454,7 @@ filesystem so that it can apply pending filesystem updates to the staging · 453 unmodified lines
454454 information.
455455 Once the scan is done, the owning object is re-locked, the live data is used to
456456 write a new ondisk structure, and the repairs are committed atomically.
457−The hooks are disabled and the staging staging area is freed.
457+The hooks are disabled and the staging area is freed.
458458 Finally, the storage from the old data structure are carefully reaped.
459459
460460 Introducing concurrency helps online repair avoid various locking problems, but
@@ -475,7 +475,7 @@ operation, which may cause application failure or an unplanned filesystem · 14 unmodified lines
475475 shutdown.
476476
477477 Inspiration for the secondary metadata repair strategy was drawn from section
478−2.4 of Srinivasan above, and sections 2 ("NSF: Inded Build Without Side-File")
478+2.4 of Srinivasan above, and sections 2 ("NSF: Index Build Without Side-File")
479479 and 3.1.1 ("Duplicate Key Insert Problem") in C. Mohan, `"Algorithms for
480480 Creating Indexes for Very Large Tables Without Quiescing Updates"
481481 <https://dl.acm.org/doi/10.1145/130283.130337>`_, 1992.
@@ -2185,7 +2185,7 @@ The chapter about :ref:`secondary metadata<secondary_metadata>` mentioned that · 1703 unmodified lines
21852185 checking and repairing of secondary metadata commonly requires coordination
21862186 between a live metadata scan of the filesystem and writer threads that are
21872187 updating that metadata.
2188−Keeping the scan data up to date requires requires the ability to propagate
2188+Keeping the scan data up to date requires the ability to propagate
21892189 metadata updates from the filesystem into the data being collected by the scan.
21902190 This *can* be done by appending concurrent updates into a separate log file and
21912191 applying them before writing the new metadata to disk, but this leads to
@@ -4179,7 +4179,7 @@ When the exchange is initiated, the sequence of operations is as follows: · 1987 unmodified lines
41794179 This will be discussed in more detail in subsequent sections.
41804180
41814181 If the filesystem goes down in the middle of an operation, log recovery will
4182−find the most recent unfinished maping exchange log intent item and restart
4182+find the most recent unfinished mapping exchange log intent item and restart
41834183 from there.
41844184 This is how atomic file mapping exchanges guarantees that an outside observer
41854185 will either see the old broken structure or the new one, and never a mismash of
Documentation/locking/locktypes.rst+21−0
@@ -204,6 +204,27 @@ per-CPU data structures on a non PREEMPT_RT kernel. · 203 unmodified lines
204204 local_lock is not suitable to protect against preemption or interrupts on a
205205 PREEMPT_RT kernel due to the PREEMPT_RT specific spinlock_t semantics.
206206
207+CPU local scope and bottom-half
208+-------------------------------
209+
210+Per-CPU variables that are accessed only in softirq context should not rely on
211+the assumption that this context is implicitly protected due to being
212+non-preemptible. In a PREEMPT_RT kernel, softirq context is preemptible, and
213+synchronizing every bottom-half-disabled section via implicit context results
214+in an implicit per-CPU "big kernel lock."
215+
216+A local_lock_t together with local_lock_nested_bh() and
217+local_unlock_nested_bh() for locking operations help to identify the locking
218+scope.
219+
220+When lockdep is enabled, these functions verify that data structure access
221+occurs within softirq context.
222+Unlike local_lock(), local_unlock_nested_bh() does not disable preemption and
223+does not add overhead when used without lockdep.
224+
225+On a PREEMPT_RT kernel, local_lock_t behaves as a real lock and
226+local_unlock_nested_bh() serializes access to the data structure, which allows
227+removal of serialization via local_bh_disable().
207228
208229 raw_spinlock_t and spinlock_t
209230 =============================
Documentation/locking/seqlock.rst+2−0
@@ -1,3 +1,5 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
13 ======================================
24 Sequence counters and sequential locks
35 ======================================
Documentation/maintainer/configure-git.rst+0−28
@@ -28,31 +28,3 @@ You may also like to tell ``gpg`` which ``tty`` to use (add to your shell · 27 unmodified lines
2828 rc file)::
2929
3030 export GPG_TTY=$(tty)
31−
32−
33−Creating commit links to lore.kernel.org
34−----------------------------------------
35−
36−The web site https://lore.kernel.org is meant as a grand archive of all mail
37−list traffic concerning or influencing the kernel development. Storing archives
38−of patches here is a recommended practice, and when a maintainer applies a
39−patch to a subsystem tree, it is a good idea to provide a Link: tag with a
40−reference back to the lore archive so that people that browse the commit
41−history can find related discussions and rationale behind a certain change.
42−The link tag will look like this::
43−
44− Link: https://lore.kernel.org/r/<message-id>
45−
46−This can be configured to happen automatically any time you issue ``git am``
47−by adding the following hook into your git::
48−
49− $ git config am.messageid true
50− $ cat >.git/hooks/applypatch-msg <<'EOF'
51− #!/bin/sh
52− . git-sh-setup
53− perl -pi -e 's|^Message-I[dD]:\s*<?([^>]+)>?$|Link: https://lore.kernel.org/r/$1|g;' "$1"
54− test -x "$GIT_DIR/hooks/commit-msg" &&
55− exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
56− :
57− EOF
58− $ chmod a+x .git/hooks/applypatch-msg
Documentation/maintainer/maintainer-entry-profile.rst+2−0
@@ -59,6 +59,7 @@ week) that patches might be considered for merging and when patches need to · 58 unmodified lines
5959 wait for the next -rc. At a minimum:
6060
6161 - Last -rc for new feature submissions:
62+
6263 New feature submissions targeting the next merge window should have
6364 their first posting for consideration before this point. Patches that
6465 are submitted after this point should be clear that they are targeting
@@ -68,6 +69,7 @@ wait for the next -rc. At a minimum: · 3 unmodified lines
6869 submissions should appear before -rc5.
6970
7071 - Last -rc to merge features: Deadline for merge decisions
72+
7173 Indicate to contributors the point at which an as yet un-applied patch
7274 set will need to wait for the NEXT+1 merge window. Of course there is no
7375 obligation to ever accept any given patchset, but if the review has not
Documentation/mm/physical_memory.rst+2−0
@@ -171,6 +171,8 @@ nodes with particular properties as defined by ``enum node_states``: · 170 unmodified lines
171171 The node has memory(regular, high, movable)
172172 ``N_CPU``
173173 The node has one or more CPUs
174+``N_GENERIC_INITIATOR``
175+ The node has one or more Generic Initiators
174176
175177 For each node that has a property described above, the bit corresponding to the
176178 node ID in the ``node_states[<property>]`` bitmask is set.
Documentation/networking/can.rst+1−1
@@ -539,7 +539,7 @@ CAN Filter Usage Optimisation · 538 unmodified lines
539539 The CAN filters are processed in per-device filter lists at CAN frame
540540 reception time. To reduce the number of checks that need to be performed
541541 while walking through the filter lists the CAN core provides an optimized
542−filter handling when the filter subscription focusses on a single CAN ID.
542+filter handling when the filter subscription focuses on a single CAN ID.
543543
544544 For the possible 2048 SFF CAN identifiers the identifier is used as an index
545545 to access the corresponding subscription list without any further checks.
Documentation/networking/device_drivers/ethernet/ti/am65_nuss_cpsw_switchdev.rst+1−1
@@ -42,7 +42,7 @@ Port's netdev devices have to be in UP before joining to the bridge to avoid · 41 unmodified lines
4242 overwriting of bridge configuration as CPSW switch driver completely reloads its
4343 configuration when first port changes its state to UP.
4444
45−When the both interfaces joined the bridge - CPSW switch driver will enable
45+When both interfaces have joined the bridge - CPSW switch driver will enable
4646 marking packets with offload_fwd_mark flag.
4747
4848 All configuration is implemented via switchdev API.
Documentation/networking/device_drivers/ethernet/ti/cpsw_switchdev.rst+1−1
@@ -92,7 +92,7 @@ Port's netdev devices have to be in UP before joining to the bridge to avoid · 91 unmodified lines
9292 overwriting of bridge configuration as CPSW switch driver copletly reloads its
9393 configuration when first Port changes its state to UP.
9494
95−When the both interfaces joined the bridge - CPSW switch driver will enable
95+When both interfaces have joined the bridge - CPSW switch driver will enable
9696 marking packets with offload_fwd_mark flag unless "ale_bypass=0"
9797
9898 All configuration is implemented via switchdev API.
Documentation/networking/rds.rst+1−1
@@ -339,7 +339,7 @@ The send path · 338 unmodified lines
339339 rds_sendmsg()
340340 - struct rds_message built from incoming data
341341 - CMSGs parsed (e.g. RDMA ops)
342− - transport connection alloced and connected if not already
342+ - transport connection allocated and connected if not already
343343 - rds_message placed on send queue
344344 - send worker awoken
345345
Documentation/power/pci.rst+2−2
@@ -472,7 +472,7 @@ in the device tree from the root bridge to a leaf device contains both of them). · 471 unmodified lines
472472 The pci_pm_suspend_noirq() routine is executed after suspend_device_irqs() has
473473 been called, which means that the device driver's interrupt handler won't be
474474 invoked while this routine is running. It first checks if the device's driver
475−implements legacy PCI suspends routines (Section 3), in which case the legacy
475+implements legacy PCI suspend routines (Section 3), in which case the legacy
476476 late suspend routine is called and its result is returned (the standard
477477 configuration registers of the device are saved if the driver's callback hasn't
478478 done that). Second, if the device driver's struct dev_pm_ops object is not
@@ -544,7 +544,7 @@ result is then returned). · 65 unmodified lines
544544 The resume phase is carried out asynchronously for PCI devices, like the
545545 suspend phase described above, which means that if two PCI devices don't depend
546546 on each other in a known way, the pci_pm_resume() routine may be executed for
547−the both of them in parallel.
547+both of them in parallel.
548548
549549 The pci_pm_complete() routine only executes the device driver's pm->complete()
550550 callback, if defined.
Documentation/power/suspend-and-cpuhotplug.rst+1−1
@@ -13,7 +13,7 @@ infrastructure uses it internally? And where do they share common code? · 12 unmodified lines
1313
1414 Well, a picture is worth a thousand words... So ASCII art follows :-)
1515
16−[This depicts the current design in the kernel, and focusses only on the
16+[This depicts the current design in the kernel, and focuses only on the
1717 interactions involving the freezer and CPU hotplug and also tries to explain
1818 the locking involved. It outlines the notifications involved as well.
1919 But please note that here, only the call paths are illustrated, with the aim
Documentation/process/5.Posting.rst+3−4
@@ -207,10 +207,9 @@ document with a specification implemented by the patch:: · 206 unmodified lines
207207
208208 Link: https://example.com/somewhere.html optional-other-stuff
209209
210−Many maintainers when applying a patch also add this tag to link to the
211−latest public review posting of the patch; often this is automatically done
212−by tools like b4 or a git hook like the one described in
213−'Documentation/maintainer/configure-git.rst'.
210+As per guidance from the Chief Penguin, a Link: tag should only be added to
211+a commit if it leads to useful information that is not found in the commit
212+itself.
214213
215214 If the URL points to a public bug report being fixed by the patch, use the
216215 "Closes:" tag instead::
Documentation/process/changes.rst+8−1
@@ -61,7 +61,7 @@ Sphinx\ [#f1]_ 3.4.3 sphinx-build --version · 60 unmodified lines
6161 GNU tar 1.28 tar --version
6262 gtags (optional) 6.6.5 gtags --version
6363 mkimage (optional) 2017.01 mkimage --version
64−Python (optional) 3.9.x python3 --version
64+Python 3.9.x python3 --version
6565 GNU AWK (optional) 5.1.0 gawk --version
6666 ====================== =============== ========================================
6767
@@ -154,6 +154,13 @@ Perl · 86 unmodified lines
154154 You will need perl 5 and the following modules: ``Getopt::Long``,
155155 ``Getopt::Std``, ``File::Basename``, and ``File::Find`` to build the kernel.
156156
157+Python
158+------
159+
160+Several config options require it: it is required for arm/arm64
161+default configs, CONFIG_LTO_CLANG, some DRM optional configs,
162+the kernel-doc tool, and docs build (Sphinx), among others.
163+
157164 BC
158165 --
159166
Documentation/process/maintainer-pgp-guide.rst+75−83
@@ -49,7 +49,7 @@ hosting infrastructure, regardless of how good the security practices · 48 unmodified lines
4949 for the latter may be.
5050
5151 The above guiding principle is the reason why this guide is needed. We
52−want to make sure that by placing trust into developers we do not simply
52+want to make sure that by placing trust into developers we do not merely
5353 shift the blame for potential future security incidents to someone else.
5454 The goal is to provide a set of guidelines developers can use to create
5555 a secure working environment and safeguard the PGP keys used to
@@ -60,7 +60,7 @@ establish the integrity of the Linux kernel itself. · 4 unmodified lines
6060 PGP tools
6161 =========
6262
63−Use GnuPG 2.2 or later
63+Use GnuPG 2.4 or later
6464 ----------------------
6565
6666 Your distro should already have GnuPG installed by default, you just
@@ -69,9 +69,9 @@ To check, run:: · 2 unmodified lines
6969
7070 $ gpg --version | head -n1
7171
72−If you have version 2.2 or above, then you are good to go. If you have a
73−version that is prior than 2.2, then some commands from this guide may
74−not work.
72+If you have version 2.4 or above, then you are good to go. If you have
73+an earlier version, then you are using a release of GnuPG that is no
74+longer maintained and some commands from this guide may not work.
7575
7676 Configure gpg-agent options
7777 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -199,13 +199,6 @@ separate signing subkey:: · 121 unmodified lines
199199
200200 $ gpg --quick-addkey [fpr] ed25519 sign
201201
202−.. note:: ECC support in GnuPG
203−
204− Note, that if you intend to use a hardware token that does not
205− support ED25519 ECC keys, you should choose "nistp256" instead or
206− "ed25519." See the section below on recommended hardware devices.
207−
208−
209202 Back up your Certify key for disaster recovery
210203 ----------------------------------------------
211204
@@ -213,7 +206,7 @@ The more signatures you have on your PGP key from other developers, the · 1 unmodified line
213206 more reasons you have to create a backup version that lives on something
214207 other than digital media, for disaster recovery reasons.
215208
216−The best way to create a printable hardcopy of your private key is by
209+A good way to create a printable hardcopy of your private key is by
217210 using the ``paperkey`` software written for this very purpose. See ``man
218211 paperkey`` for more details on the output format and its benefits over
219212 other solutions. Paperkey should already be packaged for most
@@ -224,11 +217,11 @@ key:: · 4 unmodified lines
224217
225218 $ gpg --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt
226219
227−Print out that file (or pipe the output straight to lpr), then take a
228−pen and write your passphrase on the margin of the paper. **This is
229−strongly recommended** because the key printout is still encrypted with
230−that passphrase, and if you ever change it you will not remember what it
231−used to be when you had created the backup -- *guaranteed*.
220+Print out that file, then take a pen and write your passphrase on the
221+margin of the paper. **This is strongly recommended** because the key
222+printout is still encrypted with that passphrase, and if you ever change
223+it you will not remember what it used to be when you had created the
224+backup -- *guaranteed*.
232225
233226 Put the resulting printout and the hand-written passphrase into an envelope
234227 and store in a secure and well-protected place, preferably away from your
@@ -236,10 +229,9 @@ home, such as your bank vault. · 1 unmodified line
236229
237230 .. note::
238231
239− Your printer is probably no longer a simple dumb device connected to
240− your parallel port, but since the output is still encrypted with
241− your passphrase, printing out even to "cloud-integrated" modern
242− printers should remain a relatively safe operation.
232+ The key is still encrypted with your passphrase, so printing out
233+ even to "cloud-integrated" modern printers should remain a
234+ relatively safe operation.
243235
244236 Back up your whole GnuPG directory
245237 ----------------------------------
@@ -255,16 +247,17 @@ on these external copies whenever you need to use your Certify key -- · 9 unmodified lines
255247 such as when making changes to your own key or signing other people's
256248 keys after conferences and summits.
257249
258−Start by getting a small USB "thumb" drive (preferably two!) that you
259−will use for backup purposes. You will need to encrypt them using LUKS
260−-- refer to your distro's documentation on how to accomplish this.
250+Start by getting an external media card (preferably two!) that you will
251+use for backup purposes. You will need to create an encrypted partition
252+on this device using LUKS -- refer to your distro's documentation on how
253+to accomplish this.
261254
262255 For the encryption passphrase, you can use the same one as on your
263256 PGP key.
264257
265−Once the encryption process is over, re-insert the USB drive and make
266−sure it gets properly mounted. Copy your entire ``.gnupg`` directory
267−over to the encrypted storage::
258+Once the encryption process is over, re-insert your device and make sure
259+it gets properly mounted. Copy your entire ``.gnupg`` directory over to
260+the encrypted storage::
268261
269262 $ cp -a ~/.gnupg /media/disk/foo/gnupg-backup
270263
@@ -273,11 +266,10 @@ You should now test to make sure everything still works:: · 2 unmodified lines
273266 $ gpg --homedir=/media/disk/foo/gnupg-backup --list-key [fpr]
274267
275268 If you don't get any errors, then you should be good to go. Unmount the
276−USB drive, distinctly label it so you don't blow it away next time you
277−need to use a random USB drive, and put in a safe place -- but not too
278−far away, because you'll need to use it every now and again for things
279−like editing identities, adding or revoking subkeys, or signing other
280−people's keys.
269+device, distinctly label it so you don't overwrite it by accident, and
270+put in a safe place -- but not too far away, because you'll need to use
271+it every now and again for things like editing identities, adding or
272+revoking subkeys, or signing other people's keys.
281273
282274 Remove the Certify key from your homedir
283275 ----------------------------------------
@@ -303,7 +295,7 @@ and store it on offline storage. · 19 unmodified lines
303295 your GnuPG directory in its entirety. What we are about to do will
304296 render your key useless if you do not have a usable backup!
305297
306−First, identify the keygrip of your Certify key::
298+First, identify the "keygrip" of your Certify key::
307299
308300 $ gpg --with-keygrip --list-key [fpr]
309301
@@ -328,8 +320,8 @@ Certify key fingerprint). This will correspond directly to a file in your · 18 unmodified lines
328320 2222000000000000000000000000000000000000.key
329321 3333000000000000000000000000000000000000.key
330322
331−All you have to do is simply remove the .key file that corresponds to
332−the Certify key keygrip::
323+It is sufficient to remove the .key file that corresponds to the Certify
324+key keygrip::
333325
334326 $ cd ~/.gnupg/private-keys-v1.d
335327 $ rm 1111000000000000000000000000000000000000.key
@@ -372,7 +364,7 @@ GnuPG operation is performed, the keys are loaded into system memory and · 36 unmodified lines
372364 can be stolen from there by sufficiently advanced malware (think
373365 Meltdown and Spectre).
374366
375−The best way to completely protect your keys is to move them to a
367+A good way to completely protect your keys is to move them to a
376368 specialized hardware device that is capable of smartcard operations.
377369
378370 The benefits of smartcards
@@ -383,11 +375,11 @@ private keys and performing crypto operations directly on the card · 4 unmodified lines
383375 itself. Because the key contents never leave the smartcard, the
384376 operating system of the computer into which you plug in the hardware
385377 device is not able to retrieve the private keys themselves. This is very
386−different from the encrypted USB storage device we used earlier for
387−backup purposes -- while that USB device is plugged in and mounted, the
378+different from the encrypted media storage device we used earlier for
379+backup purposes -- while that device is plugged in and mounted, the
388380 operating system is able to access the private key contents.
389381
390−Using external encrypted USB media is not a substitute to having a
382+Using external encrypted media is not a substitute to having a
391383 smartcard-capable device.
392384
393385 Available smartcard devices
@@ -398,17 +390,15 @@ easiest is to get a specialized USB device that implements smartcard · 4 unmodified lines
398390 functionality. There are several options available:
399391
400392 - `Nitrokey Start`_: Open hardware and Free Software, based on FSI
401− Japan's `Gnuk`_. One of the few available commercial devices that
402− support ED25519 ECC keys, but offer fewest security features (such as
403− resistance to tampering or some side-channel attacks).
404−- `Nitrokey Pro 2`_: Similar to the Nitrokey Start, but more
405− tamper-resistant and offers more security features. Pro 2 supports ECC
406− cryptography (NISTP).
393+ Japan's `Gnuk`_. One of the cheapest options, but offers fewest
394+ security features (such as resistance to tampering or some
395+ side-channel attacks).
396+- `Nitrokey 3`_: Similar to the Nitrokey Start, but more
397+ tamper-resistant and offers more security features and USB
398+ form-factors. Supports ECC cryptography (ED25519 and NISTP).
407399 - `Yubikey 5`_: proprietary hardware and software, but cheaper than
408− Nitrokey Pro and comes available in the USB-C form that is more useful
409− with newer laptops. Offers additional security features such as FIDO
410− U2F, among others, and now finally supports NISTP and ED25519 ECC
411− keys.
400+ Nitrokey with a similar set of features. Supports ECC cryptography
401+ (ED25519 and NISTP).
412402
413403 Your choice will depend on cost, shipping availability in your
414404 geographical region, and open/proprietary hardware considerations.
@@ -419,8 +409,8 @@ geographical region, and open/proprietary hardware considerations. · 4 unmodified lines
419409 you `qualify for a free Nitrokey Start`_ courtesy of The Linux
420410 Foundation.
421411
422−.. _`Nitrokey Start`: https://shop.nitrokey.com/shop/product/nitrokey-start-6
423−.. _`Nitrokey Pro 2`: https://shop.nitrokey.com/shop/product/nkpr2-nitrokey-pro-2-3
412+.. _`Nitrokey Start`: https://www.nitrokey.com/products/nitrokeys
413+.. _`Nitrokey 3`: https://www.nitrokey.com/products/nitrokeys
424414 .. _`Yubikey 5`: https://www.yubico.com/products/yubikey-5-overview/
425415 .. _Gnuk: https://www.fsij.org/doc-gnuk/
426416 .. _`qualify for a free Nitrokey Start`: https://www.kernel.org/nitrokey-digital-tokens-for-kernel-developers.html
@@ -455,7 +445,7 @@ the smartcard). You so rarely need to use the Admin PIN, that you will · 28 unmodified lines
455445 inevitably forget what it is if you do not record it.
456446
457447 Getting back to the main card menu, you can also set other values (such
458−as name, sex, login data, etc), but it's not necessary and will
448+as name, gender, login data, etc), but it's not necessary and will
459449 additionally leak information about your smartcard should you lose it.
460450
461451 .. note::
@@ -615,7 +605,7 @@ run:: · 153 unmodified lines
615605 You can also use a specific date if that is easier to remember (e.g.
616606 your birthday, January 1st, or Canada Day)::
617607
618− $ gpg --quick-set-expire [fpr] 2025-07-01
608+ $ gpg --quick-set-expire [fpr] 2038-07-01
619609
620610 Remember to send the updated key back to keyservers::
621611
@@ -656,9 +646,9 @@ hundreds of cloned repositories floating around, how does anyone verify · 34 unmodified lines
656646 that their copy of linux.git has not been tampered with by a malicious
657647 third party?
658648
659−Or what happens if a backdoor is discovered in the code and the "Author"
660−line in the commit says it was done by you, while you're pretty sure you
661−had `nothing to do with it`_?
649+Or what happens if malicious code is discovered in the kernel and the
650+"Author" line in the commit says it was done by you, while you're pretty
651+sure you had `nothing to do with it`_?
662652
663653 To address both of these issues, Git introduced PGP integration. Signed
664654 tags prove the repository integrity by assuring that its contents are
@@ -681,8 +671,7 @@ should be used (``[fpr]`` is the fingerprint of your key):: · 16 unmodified lines
681671 How to work with signed tags
682672 ----------------------------
683673
684−To create a signed tag, simply pass the ``-s`` switch to the tag
685−command::
674+To create a signed tag, pass the ``-s`` switch to the tag command::
686675
687676 $ git tag -s [tagname]
688677
@@ -693,7 +682,7 @@ not been maliciously altered. · 4 unmodified lines
693682 How to verify signed tags
694683 ~~~~~~~~~~~~~~~~~~~~~~~~~
695684
696−To verify a signed tag, simply use the ``verify-tag`` command::
685+To verify a signed tag, use the ``verify-tag`` command::
697686
698687 $ git verify-tag [tagname]
699688
@@ -712,9 +701,9 @@ The merge message will contain something like this:: · 12 unmodified lines
712701 # gpg: Signature made [...]
713702 # gpg: Good signature from [...]
714703
715−If you are verifying someone else's git tag, then you will need to
716−import their PGP key. Please refer to the
717−":ref:`verify_identities`" section below.
704+If you are verifying someone else's git tag, you will first need to
705+import their PGP key. Please refer to the ":ref:`verify_identities`"
706+section below.
718707
719708 Configure git to always sign annotated tags
720709 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -728,16 +717,16 @@ configuration option:: · 7 unmodified lines
728717 How to work with signed commits
729718 -------------------------------
730719
731−It is easy to create signed commits, but it is much more difficult to
732−use them in Linux kernel development, since it relies on patches sent to
733−the mailing list, and this workflow does not preserve PGP commit
734−signatures. Furthermore, when rebasing your repository to match
735−upstream, even your own PGP commit signatures will end up discarded. For
736−this reason, most kernel developers don't bother signing their commits
737−and will ignore signed commits in any external repositories that they
738−rely upon in their work.
720+It is also possible to create signed commits, but they have limited
721+usefulness in Linux kernel development. The kernel contribution workflow
722+relies on sending in patches, and converting commits to patches does not
723+preserve git commit signatures. Furthermore, when rebasing your own
724+repository on a newer upstream, PGP commit signatures will end up
725+discarded. For this reason, most kernel developers don't bother signing
726+their commits and will ignore signed commits in any external
727+repositories that they rely upon in their work.
739728
740−However, if you have your working git tree publicly available at some
729+That said, if you have your working git tree publicly available at some
741730 git hosting service (kernel.org, infradead.org, ozlabs.org, or others),
742731 then the recommendation is that you sign all your git commits even if
743732 upstream developers do not directly benefit from this practice.
@@ -748,7 +737,7 @@ We recommend this for the following reasons: · 4 unmodified lines
748737 provenance, even externally maintained trees carrying PGP commit
749738 signatures will be valuable for such purposes.
750739 2. If you ever need to re-clone your local repository (for example,
751− after a disk failure), this lets you easily verify the repository
740+ after reinstalling your system), this lets you verify the repository
752741 integrity before resuming your work.
753742 3. If someone needs to cherry-pick your commits, this allows them to
754743 quickly verify their integrity before applying them.
@@ -756,9 +745,8 @@ We recommend this for the following reasons: · 1 unmodified line
756745 Creating signed commits
757746 ~~~~~~~~~~~~~~~~~~~~~~~
758747
759−To create a signed commit, you just need to pass the ``-S`` flag to the
760−``git commit`` command (it's capital ``-S`` due to collision with
761−another flag)::
748+To create a signed commit, pass the ``-S`` flag to the ``git commit``
749+command (it's capital ``-S`` due to collision with another flag)::
762750
763751 $ git commit -S
764752
@@ -775,7 +763,6 @@ You can tell git to always sign commits:: · 10 unmodified lines
775763
776764 .. _verify_identities:
777765
778−
779766 How to work with signed patches
780767 -------------------------------
781768
@@ -793,6 +780,11 @@ headers (a-la DKIM): · 11 unmodified lines
793780 Installing and configuring patatt
794781 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
795782
783+.. note::
784+
785+ If you use B4 to send in your patches, patatt is already installed
786+ and integrated into your workflow.
787+
796788 Patatt is packaged for many distributions already, so please check there
797789 first. You can also install it from pypi using "``pip install patatt``".
798790
@@ -835,9 +827,9 @@ encounters, for example:: · 36 unmodified lines
835827 How to verify kernel developer identities
836828 =========================================
837829
838−Signing tags and commits is easy, but how does one go about verifying
839−that the key used to sign something belongs to the actual kernel
840−developer and not to a malicious imposter?
830+Signing tags and commits is straightforward, but how does one go about
831+verifying that the key used to sign something belongs to the actual
832+kernel developer and not to a malicious imposter?
841833
842834 Configure auto-key-retrieval using WKD and DANE
843835 -----------------------------------------------
@@ -884,7 +876,7 @@ various software makers dictating who should be your trusted certifying · 40 unmodified lines
884876 entity, PGP leaves this responsibility to each user.
885877
886878 Unfortunately, very few people understand how the Web of Trust works.
887−While it remains an important aspect of the OpenPGP specification,
879+While it is still an important part of the OpenPGP specification,
888880 recent versions of GnuPG (2.2 and above) have implemented an alternative
889881 mechanism called "Trust on First Use" (TOFU). You can think of TOFU as
890882 "the SSH-like approach to trust." With SSH, the first time you connect
@@ -894,8 +886,8 @@ to connect, forcing you to make a decision on whether you choose to · 3 unmodified lines
894886 trust the changed key or not. Similarly, the first time you import
895887 someone's PGP key, it is assumed to be valid. If at any point in the
896888 future GnuPG comes across another key with the same identity, both the
897−previously imported key and the new key will be marked as invalid and
898−you will need to manually figure out which one to keep.
889+previously imported key and the new key will be marked for verification
890+and you will need to manually figure out which one to keep.
899891
900892 We recommend that you use the combined TOFU+PGP trust model (which is
901893 the new default in GnuPG v2). To set it, add (or modify) the
Documentation/process/submitting-patches.rst+3−3
@@ -343,7 +343,7 @@ https://en.wikipedia.org/wiki/Posting_style#Interleaved_style · 342 unmodified lines
343343 As is frequently quoted on the mailing list::
344344
345345 A: http://en.wikipedia.org/wiki/Top_post
346− Q: Were do I find info about this thing called top-posting?
346+ Q: Where do I find info about this thing called top-posting?
347347 A: Because it messes up the order in which people normally read text.
348348 Q: Why is top-posting such a bad thing?
349349 A: Top-posting.
@@ -602,8 +602,8 @@ future. Note, this is one of only three tags you might be able to use without · 252 unmodified lines
602602 explicit permission of the person named (see 'Tagging people requires
603603 permission' below for details).
604604
605−A Fixes: tag indicates that the patch fixes an issue in a previous commit. It
606−is used to make it easy to determine where a bug originated, which can help
605+A Fixes: tag indicates that the patch fixes a bug in a previous commit. It
606+is used to make it easy to determine where an issue originated, which can help
607607 review a bug fix. This tag also assists the stable kernel team in determining
608608 which stable kernel versions should receive your fix. This is the preferred
609609 method for indicating a bug fixed by the patch. See :ref:`describe_changes`
Documentation/sphinx/automarkup.py+1−1
@@ -244,7 +244,7 @@ def add_and_resolve_xref(app, docname, domain, reftype, target, contnode=None): · 243 unmodified lines
244244 return contnode
245245
246246 #
247−# Variant of markup_abi_ref() that warns whan a reference is not found
247+# Variant of markup_abi_ref() that warns when a reference is not found
248248 #
249249 def markup_abi_file_ref(docname, app, match):
250250 return markup_abi_ref(docname, app, match, warning=True)
Documentation/sphinx/cdomain.py+0−247
@@ -1,247 +0,0 @@
1−# -*- coding: utf-8; mode: python -*-
2−# SPDX-License-Identifier: GPL-2.0
3−# pylint: disable=W0141,C0113,C0103,C0325
4−"""
5− cdomain
6− ~~~~~~~
7−
8− Replacement for the sphinx c-domain.
9−
10− :copyright: Copyright (C) 2016 Markus Heiser
11− :license: GPL Version 2, June 1991 see Linux/COPYING for details.
12−
13− List of customizations:
14−
15− * Moved the *duplicate C object description* warnings for function
16− declarations in the nitpicky mode. See Sphinx documentation for
17− the config values for ``nitpick`` and ``nitpick_ignore``.
18−
19− * Add option 'name' to the "c:function:" directive. With option 'name' the
20− ref-name of a function can be modified. E.g.::
21−
22− .. c:function:: int ioctl( int fd, int request )
23− :name: VIDIOC_LOG_STATUS
24−
25− The func-name (e.g. ioctl) remains in the output but the ref-name changed
26− from 'ioctl' to 'VIDIOC_LOG_STATUS'. The function is referenced by::
27−
28− * :c:func:`VIDIOC_LOG_STATUS` or
29− * :any:`VIDIOC_LOG_STATUS` (``:any:`` needs sphinx 1.3)
30−
31− * Handle signatures of function-like macros well. Don't try to deduce
32− arguments types of function-like macros.
33−
34−"""
35−
36−from docutils import nodes
37−from docutils.parsers.rst import directives
38−
39−import sphinx
40−from sphinx import addnodes
41−from sphinx.domains.c import c_funcptr_sig_re, c_sig_re
42−from sphinx.domains.c import CObject as Base_CObject
43−from sphinx.domains.c import CDomain as Base_CDomain
44−from itertools import chain
45−import re
46−
47−__version__ = '1.1'
48−
49−# Namespace to be prepended to the full name
50−namespace = None
51−
52−#
53−# Handle trivial newer c domain tags that are part of Sphinx 3.1 c domain tags
54−# - Store the namespace if ".. c:namespace::" tag is found
55−#
56−RE_namespace = re.compile(r'^\s*..\s*c:namespace::\s*(\S+)\s*$')
57−
58−def markup_namespace(match):
59− global namespace
60−
61− namespace = match.group(1)
62−
63− return ""
64−
65−#
66−# Handle c:macro for function-style declaration
67−#
68−RE_macro = re.compile(r'^\s*..\s*c:macro::\s*(\S+)\s+(\S.*)\s*$')
69−def markup_macro(match):
70− return ".. c:function:: " + match.group(1) + ' ' + match.group(2)
71−
72−#
73−# Handle newer c domain tags that are evaluated as .. c:type: for
74−# backward-compatibility with Sphinx < 3.0
75−#
76−RE_ctype = re.compile(r'^\s*..\s*c:(struct|union|enum|enumerator|alias)::\s*(.*)$')
77−
78−def markup_ctype(match):
79− return ".. c:type:: " + match.group(2)
80−
81−#
82−# Handle newer c domain tags that are evaluated as :c:type: for
83−# backward-compatibility with Sphinx < 3.0
84−#
85−RE_ctype_refs = re.compile(r':c:(var|struct|union|enum|enumerator)::`([^\`]+)`')
86−def markup_ctype_refs(match):
87− return ":c:type:`" + match.group(2) + '`'
88−
89−#
90−# Simply convert :c:expr: and :c:texpr: into a literal block.
91−#
92−RE_expr = re.compile(r':c:(expr|texpr):`([^\`]+)`')
93−def markup_c_expr(match):
94− return '\\ ``' + match.group(2) + '``\\ '
95−
96−#
97−# Parse Sphinx 3.x C markups, replacing them by backward-compatible ones
98−#
99−def c_markups(app, docname, source):
100− result = ""
101− markup_func = {
102− RE_namespace: markup_namespace,
103− RE_expr: markup_c_expr,
104− RE_macro: markup_macro,
105− RE_ctype: markup_ctype,
106− RE_ctype_refs: markup_ctype_refs,
107− }
108−
109− lines = iter(source[0].splitlines(True))
110− for n in lines:
111− match_iterators = [regex.finditer(n) for regex in markup_func]
112− matches = sorted(chain(*match_iterators), key=lambda m: m.start())
113− for m in matches:
114− n = n[:m.start()] + markup_func[m.re](m) + n[m.end():]
115−
116− result = result + n
117−
118− source[0] = result
119−
120−#
121−# Now implements support for the cdomain namespacing logic
122−#
123−
124−def setup(app):
125−
126− # Handle easy Sphinx 3.1+ simple new tags: :c:expr and .. c:namespace::
127− app.connect('source-read', c_markups)
128− app.add_domain(CDomain, override=True)
129−
130− return dict(
131− version = __version__,
132− parallel_read_safe = True,
133− parallel_write_safe = True
134− )
135−
136−class CObject(Base_CObject):
137−
138− """
139− Description of a C language object.
140− """
141− option_spec = {
142− "name" : directives.unchanged
143− }
144−
145− def handle_func_like_macro(self, sig, signode):
146− """Handles signatures of function-like macros.
147−
148− If the objtype is 'function' and the signature ``sig`` is a
149− function-like macro, the name of the macro is returned. Otherwise
150− ``False`` is returned. """
151−
152− global namespace
153−
154− if not self.objtype == 'function':
155− return False
156−
157− m = c_funcptr_sig_re.match(sig)
158− if m is None:
159− m = c_sig_re.match(sig)
160− if m is None:
161− raise ValueError('no match')
162−
163− rettype, fullname, arglist, _const = m.groups()
164− arglist = arglist.strip()
165− if rettype or not arglist:
166− return False
167−
168− arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
169− arglist = [a.strip() for a in arglist.split(",")]
170−
171− # has the first argument a type?
172− if len(arglist[0].split(" ")) > 1:
173− return False
174−
175− # This is a function-like macro, its arguments are typeless!
176− signode += addnodes.desc_name(fullname, fullname)
177− paramlist = addnodes.desc_parameterlist()
178− signode += paramlist
179−
180− for argname in arglist:
181− param = addnodes.desc_parameter('', '', noemph=True)
182− # separate by non-breaking space in the output
183− param += nodes.emphasis(argname, argname)
184− paramlist += param
185−
186− if namespace:
187− fullname = namespace + "." + fullname
188−
189− return fullname
190−
191− def handle_signature(self, sig, signode):
192− """Transform a C signature into RST nodes."""
193−
194− global namespace
195−
196− fullname = self.handle_func_like_macro(sig, signode)
197− if not fullname:
198− fullname = super(CObject, self).handle_signature(sig, signode)
199−
200− if "name" in self.options:
201− if self.objtype == 'function':
202− fullname = self.options["name"]
203− else:
204− # FIXME: handle :name: value of other declaration types?
205− pass
206− else:
207− if namespace:
208− fullname = namespace + "." + fullname
209−
210− return fullname
211−
212− def add_target_and_index(self, name, sig, signode):
213− # for C API items we add a prefix since names are usually not qualified
214− # by a module name and so easily clash with e.g. section titles
215− targetname = 'c.' + name
216− if targetname not in self.state.document.ids:
217− signode['names'].append(targetname)
218− signode['ids'].append(targetname)
219− signode['first'] = (not self.names)
220− self.state.document.note_explicit_target(signode)
221− inv = self.env.domaindata['c']['objects']
222− if (name in inv and self.env.config.nitpicky):
223− if self.objtype == 'function':
224− if ('c:func', name) not in self.env.config.nitpick_ignore:
225− self.state_machine.reporter.warning(
226− 'duplicate C object description of %s, ' % name +
227− 'other instance in ' + self.env.doc2path(inv[name][0]),
228− line=self.lineno)
229− inv[name] = (self.env.docname, self.objtype)
230−
231− indextext = self.get_index_text(name)
232− if indextext:
233− self.indexnode['entries'].append(
234− ('single', indextext, targetname, '', None))
235−
236−class CDomain(Base_CDomain):
237−
238− """C language domain."""
239− name = 'c'
240− label = 'C'
241− directives = {
242− 'function': CObject,
243− 'member': CObject,
244− 'macro': CObject,
245− 'type': CObject,
246− 'var': CObject,
247− }
Documentation/sphinx/kernel_feat.py+3−1
@@ -40,9 +40,11 @@ import sys · 39 unmodified lines
4040 from docutils import nodes, statemachine
4141 from docutils.statemachine import ViewList
4242 from docutils.parsers.rst import directives, Directive
43−from docutils.utils.error_reporting import ErrorString
4443 from sphinx.util.docutils import switch_source_input
4544
45+def ErrorString(exc): # Shamelessly stolen from docutils
46+ return f'{exc.__class__.__name}: {exc}'
47+
4648 __version__ = '1.0'
4749
4850 def setup(app):
Documentation/sphinx/kernel_include.py+392−136
@@ -1,31 +1,82 @@
11 #!/usr/bin/env python3
2−# -*- coding: utf-8; mode: python -*-
32 # SPDX-License-Identifier: GPL-2.0
4−# pylint: disable=R0903, C0330, R0914, R0912, E0401
3+# pylint: disable=R0903, R0912, R0914, R0915, C0209,W0707
4+
55
66 """
7− kernel-include
8− ~~~~~~~~~~~~~~
7+Implementation of the ``kernel-include`` reST-directive.
8+
9+:copyright: Copyright (C) 2016 Markus Heiser
10+:license: GPL Version 2, June 1991 see linux/COPYING for details.
11+
12+The ``kernel-include`` reST-directive is a replacement for the ``include``
13+directive. The ``kernel-include`` directive expand environment variables in
14+the path name and allows to include files from arbitrary locations.
15+
16+.. hint::
17+
18+ Including files from arbitrary locations (e.g. from ``/etc``) is a
19+ security risk for builders. This is why the ``include`` directive from
20+ docutils *prohibit* pathnames pointing to locations *above* the filesystem
21+ tree where the reST document with the include directive is placed.
22+
23+Substrings of the form $name or ${name} are replaced by the value of
24+environment variable name. Malformed variable names and references to
25+non-existing variables are left unchanged.
26+
27+**Supported Sphinx Include Options**:
28+
29+:param literal:
30+ If present, the included file is inserted as a literal block.
31+
32+:param code:
33+ Specify the language for syntax highlighting (e.g., 'c', 'python').
34+
35+:param encoding:
36+ Specify the encoding of the included file (default: 'utf-8').
37+
38+:param tab-width:
39+ Specify the number of spaces that a tab represents.
40+
41+:param start-line:
42+ Line number at which to start including the file (1-based).
43+
44+:param end-line:
45+ Line number at which to stop including the file (inclusive).
46+
47+:param start-after:
48+ Include lines after the first line matching this text.
49+
50+:param end-before:
51+ Include lines before the first line matching this text.
952
10− Implementation of the ``kernel-include`` reST-directive.
53+:param number-lines:
54+ Number the included lines (integer specifies start number).
55+ Only effective with 'literal' or 'code' options.
1156
12− :copyright: Copyright (C) 2016 Markus Heiser
13− :license: GPL Version 2, June 1991 see linux/COPYING for details.
57+:param class:
58+ Specify HTML class attribute for the included content.
1459
15− The ``kernel-include`` reST-directive is a replacement for the ``include``
16− directive. The ``kernel-include`` directive expand environment variables in
17− the path name and allows to include files from arbitrary locations.
60+**Kernel-specific Extensions**:
1861
19− .. hint::
62+:param generate-cross-refs:
63+ If present, instead of directly including the file, it calls
64+ ParseDataStructs() to convert C data structures into cross-references
65+ that link to comprehensive documentation in other ReST files.
2066
21− Including files from arbitrary locations (e.g. from ``/etc``) is a
22− security risk for builders. This is why the ``include`` directive from
23− docutils *prohibit* pathnames pointing to locations *above* the filesystem
24− tree where the reST document with the include directive is placed.
67+:param exception-file:
68+ (Used with generate-cross-refs)
2569
26− Substrings of the form $name or ${name} are replaced by the value of
27− environment variable name. Malformed variable names and references to
28− non-existing variables are left unchanged.
70+ Path to a file containing rules for handling special cases:
71+ - Ignore specific C data structures
72+ - Use alternative reference names
73+ - Specify different reference types
74+
75+:param warn-broken:
76+ (Used with generate-cross-refs)
77+
78+ Enables warnings when auto-generated cross-references don't point to
79+ existing documentation targets.
2980 """
3081
3182 # ==============================================================================
@@ -33,161 +84,366 @@ · 1 unmodified line
3384 # ==============================================================================
3485
3586 import os.path
87+import re
88+import sys
3689
3790 from docutils import io, nodes, statemachine
38−from docutils.utils.error_reporting import SafeString, ErrorString
39−from docutils.parsers.rst import directives
91+from docutils.statemachine import ViewList
92+from docutils.parsers.rst import Directive, directives
4093 from docutils.parsers.rst.directives.body import CodeBlock, NumberLines
41−from docutils.parsers.rst.directives.misc import Include
4294
43−__version__ = '1.0'
95+from sphinx.util import logging
4496
45−# ==============================================================================
46−def setup(app):
47−# ==============================================================================
97+srctree = os.path.abspath(os.environ["srctree"])
98+sys.path.insert(0, os.path.join(srctree, "tools/docs/lib"))
4899
49− app.add_directive("kernel-include", KernelInclude)
50− return dict(
51− version = __version__,
52− parallel_read_safe = True,
53− parallel_write_safe = True
54− )
100+from parse_data_structs import ParseDataStructs
55101
56−# ==============================================================================
57−class KernelInclude(Include):
58−# ==============================================================================
102+__version__ = "1.0"
103+logger = logging.getLogger(__name__)
59104
60− """KernelInclude (``kernel-include``) directive"""
105+RE_DOMAIN_REF = re.compile(r'\\ :(ref|c:type|c:func):`([^<`]+)(?:<([^>]+)>)?`\\')
106+RE_SIMPLE_REF = re.compile(r'`([^`]+)`')
61107
62− def run(self):
63− env = self.state.document.settings.env
64− path = os.path.realpath(
65− os.path.expandvars(self.arguments[0]))
108+def ErrorString(exc): # Shamelessly stolen from docutils
109+ return f'{exc.__class__.__name}: {exc}'
66110
67− # to get a bit security back, prohibit /etc:
68− if path.startswith(os.sep + "etc"):
69− raise self.severe(
70− 'Problems with "%s" directive, prohibited path: %s'
71− % (self.name, path))
72111
73− self.arguments[0] = path
112+# ==============================================================================
113+class KernelInclude(Directive):
114+ """
115+ KernelInclude (``kernel-include``) directive
74116
75− env.note_dependency(os.path.abspath(path))
117+ Most of the stuff here came from Include directive defined at:
118+ docutils/parsers/rst/directives/misc.py
76119
77− #return super(KernelInclude, self).run() # won't work, see HINTs in _run()
78− return self._run()
120+ Yet, overriding the class don't has any benefits: the original class
121+ only have run() and argument list. Not all of them are implemented,
122+ when checked against latest Sphinx version, as with time more arguments
123+ were added.
79124
80− def _run(self):
81− """Include a file as part of the content of this reST file."""
125+ So, keep its own list of supported arguments
126+ """
82127
83− # HINT: I had to copy&paste the whole Include.run method. I'am not happy
84− # with this, but due to security reasons, the Include.run method does
85− # not allow absolute or relative pathnames pointing to locations *above*
86− # the filesystem tree where the reST document is placed.
128+ required_arguments = 1
129+ optional_arguments = 0
130+ final_argument_whitespace = True
131+ option_spec = {
132+ 'literal': directives.flag,
133+ 'code': directives.unchanged,
134+ 'encoding': directives.encoding,
135+ 'tab-width': int,
136+ 'start-line': int,
137+ 'end-line': int,
138+ 'start-after': directives.unchanged_required,
139+ 'end-before': directives.unchanged_required,
140+ # ignored except for 'literal' or 'code':
141+ 'number-lines': directives.unchanged, # integer or None
142+ 'class': directives.class_option,
87143
88− if not self.state.document.settings.file_insertion_enabled:
89− raise self.warning('"%s" directive disabled.' % self.name)
90− source = self.state_machine.input_lines.source(
91− self.lineno - self.state_machine.input_offset - 1)
92− source_dir = os.path.dirname(os.path.abspath(source))
93− path = directives.path(self.arguments[0])
94− if path.startswith('<') and path.endswith('>'):
95− path = os.path.join(self.standard_include_path, path[1:-1])
96− path = os.path.normpath(os.path.join(source_dir, path))
144+ # Arguments that aren't from Sphinx Include directive
145+ 'generate-cross-refs': directives.flag,
146+ 'warn-broken': directives.flag,
147+ 'toc': directives.flag,
148+ 'exception-file': directives.unchanged,
149+ }
97150
98− # HINT: this is the only line I had to change / commented out:
99− #path = utils.relative_path(None, path)
151+ def read_rawtext(self, path, encoding):
152+ """Read and process file content with error handling"""
153+ try:
154+ self.state.document.settings.record_dependencies.add(path)
155+ include_file = io.FileInput(source_path=path,
156+ encoding=encoding,
157+ error_handler=self.state.document.settings.input_encoding_error_handler)
158+ except UnicodeEncodeError:
159+ raise self.severe('Problems with directive path:\n'
160+ 'Cannot encode input file path "%s" '
161+ '(wrong locale?).' % path)
162+ except IOError as error:
163+ raise self.severe('Problems with directive path:\n%s.' % ErrorString(error))
100164
101− encoding = self.options.get(
102− 'encoding', self.state.document.settings.input_encoding)
103− e_handler=self.state.document.settings.input_encoding_error_handler
104− tab_width = self.options.get(
105− 'tab-width', self.state.document.settings.tab_width)
106− try:
107− self.state.document.settings.record_dependencies.add(path)
108− include_file = io.FileInput(source_path=path,
109− encoding=encoding,
110− error_handler=e_handler)
111− except UnicodeEncodeError as error:
112− raise self.severe('Problems with "%s" directive path:\n'
113− 'Cannot encode input file path "%s" '
114− '(wrong locale?).' %
115− (self.name, SafeString(path)))
116− except IOError as error:
117− raise self.severe('Problems with "%s" directive path:\n%s.' %
118− (self.name, ErrorString(error)))
165+ try:
166+ return include_file.read()
167+ except UnicodeError as error:
168+ raise self.severe('Problem with directive:\n%s' % ErrorString(error))
169+
170+ def apply_range(self, rawtext):
171+ """
172+ Handles start-line, end-line, start-after and end-before parameters
173+ """
174+
175+ # Get to-be-included content
119176 startline = self.options.get('start-line', None)
120177 endline = self.options.get('end-line', None)
121178 try:
122179 if startline or (endline is not None):
123− lines = include_file.readlines()
124− rawtext = ''.join(lines[startline:endline])
125− else:
126− rawtext = include_file.read()
180+ lines = rawtext.splitlines()
181+ rawtext = '\n'.join(lines[startline:endline])
127182 except UnicodeError as error:
128− raise self.severe('Problem with "%s" directive:\n%s' %
129− (self.name, ErrorString(error)))
183+ raise self.severe(f'Problem with "{self.name}" directive:\n'
184+ + io.error_string(error))
130185 # start-after/end-before: no restrictions on newlines in match-text,
131186 # and no restrictions on matching inside lines vs. line boundaries
132− after_text = self.options.get('start-after', None)
187+ after_text = self.options.get("start-after", None)
133188 if after_text:
134189 # skip content in rawtext before *and incl.* a matching text
135190 after_index = rawtext.find(after_text)
136191 if after_index < 0:
137192 raise self.severe('Problem with "start-after" option of "%s" '
138− 'directive:\nText not found.' % self.name)
139− rawtext = rawtext[after_index + len(after_text):]
140− before_text = self.options.get('end-before', None)
193+ "directive:\nText not found." % self.name)
194+ rawtext = rawtext[after_index + len(after_text) :]
195+ before_text = self.options.get("end-before", None)
141196 if before_text:
142197 # skip content in rawtext after *and incl.* a matching text
143198 before_index = rawtext.find(before_text)
144199 if before_index < 0:
145200 raise self.severe('Problem with "end-before" option of "%s" '
146− 'directive:\nText not found.' % self.name)
201+ "directive:\nText not found." % self.name)
147202 rawtext = rawtext[:before_index]
148203
204+ return rawtext
205+
206+ def xref_text(self, env, path, tab_width):
207+ """
208+ Read and add contents from a C file parsed to have cross references.
209+
210+ There are two types of supported output here:
211+ - A C source code with cross-references;
212+ - a TOC table containing cross references.
213+ """
214+ parser = ParseDataStructs()
215+ parser.parse_file(path)
216+
217+ if 'exception-file' in self.options:
218+ source_dir = os.path.dirname(os.path.abspath(
219+ self.state_machine.input_lines.source(
220+ self.lineno - self.state_machine.input_offset - 1)))
221+ exceptions_file = os.path.join(source_dir, self.options['exception-file'])
222+ parser.process_exceptions(exceptions_file)
223+
224+ # Store references on a symbol dict to be used at check time
225+ if 'warn-broken' in self.options:
226+ env._xref_files.add(path)
227+
228+ if "toc" not in self.options:
229+
230+ rawtext = ".. parsed-literal::\n\n" + parser.gen_output()
231+ self.apply_range(rawtext)
232+
233+ include_lines = statemachine.string2lines(rawtext, tab_width,
234+ convert_whitespace=True)
235+
236+ # Sphinx always blame the ".. <directive>", so placing
237+ # line numbers here won't make any difference
238+
239+ self.state_machine.insert_input(include_lines, path)
240+ return []
241+
242+ # TOC output is a ReST file, not a literal. So, we can add line
243+ # numbers
244+
245+ rawtext = parser.gen_toc()
246+
149247 include_lines = statemachine.string2lines(rawtext, tab_width,
150248 convert_whitespace=True)
151− if 'literal' in self.options:
152− # Convert tabs to spaces, if `tab_width` is positive.
153− if tab_width >= 0:
154− text = rawtext.expandtabs(tab_width)
155− else:
156− text = rawtext
157− literal_block = nodes.literal_block(rawtext, source=path,
158− classes=self.options.get('class', []))
159− literal_block.line = 1
160− self.add_name(literal_block)
161− if 'number-lines' in self.options:
162− try:
163− startline = int(self.options['number-lines'] or 1)
164− except ValueError:
165− raise self.error(':number-lines: with non-integer '
166− 'start value')
167− endline = startline + len(include_lines)
168− if text.endswith('\n'):
169− text = text[:-1]
170− tokens = NumberLines([([], text)], startline, endline)
171− for classes, value in tokens:
172− if classes:
173− literal_block += nodes.inline(value, value,
174− classes=classes)
175− else:
176− literal_block += nodes.Text(value, value)
177− else:
178− literal_block += nodes.Text(text, text)
179− return [literal_block]
180− if 'code' in self.options:
181− self.options['source'] = path
182− codeblock = CodeBlock(self.name,
183− [self.options.pop('code')], # arguments
184− self.options,
185− include_lines, # content
186− self.lineno,
187− self.content_offset,
188− self.block_text,
189− self.state,
190− self.state_machine)
191− return codeblock.run()
192− self.state_machine.insert_input(include_lines, path)
249+
250+ # Append line numbers data
251+
252+ startline = self.options.get('start-line', None)
253+
254+ result = ViewList()
255+ if startline and startline > 0:
256+ offset = startline - 1
257+ else:
258+ offset = 0
259+
260+ for ln, line in enumerate(include_lines, start=offset):
261+ result.append(line, path, ln)
262+
263+ self.state_machine.insert_input(result, path)
264+
193265 return []
266+
267+ def literal(self, path, tab_width, rawtext):
268+ """Output a literal block"""
269+
270+ # Convert tabs to spaces, if `tab_width` is positive.
271+ if tab_width >= 0:
272+ text = rawtext.expandtabs(tab_width)
273+ else:
274+ text = rawtext
275+ literal_block = nodes.literal_block(rawtext, source=path,
276+ classes=self.options.get("class", []))
277+ literal_block.line = 1
278+ self.add_name(literal_block)
279+ if "number-lines" in self.options:
280+ try:
281+ startline = int(self.options["number-lines"] or 1)
282+ except ValueError:
283+ raise self.error(":number-lines: with non-integer start value")
284+ endline = startline + len(include_lines)
285+ if text.endswith("\n"):
286+ text = text[:-1]
287+ tokens = NumberLines([([], text)], startline, endline)
288+ for classes, value in tokens:
289+ if classes:
290+ literal_block += nodes.inline(value, value,
291+ classes=classes)
292+ else:
293+ literal_block += nodes.Text(value, value)
294+ else:
295+ literal_block += nodes.Text(text, text)
296+ return [literal_block]
297+
298+ def code(self, path, tab_width):
299+ """Output a code block"""
300+
301+ include_lines = statemachine.string2lines(rawtext, tab_width,
302+ convert_whitespace=True)
303+
304+ self.options["source"] = path
305+ codeblock = CodeBlock(self.name,
306+ [self.options.pop("code")], # arguments
307+ self.options,
308+ include_lines,
309+ self.lineno,
310+ self.content_offset,
311+ self.block_text,
312+ self.state,
313+ self.state_machine)
314+ return codeblock.run()
315+
316+ def run(self):
317+ """Include a file as part of the content of this reST file."""
318+ env = self.state.document.settings.env
319+
320+ #
321+ # The include logic accepts only patches relative to the
322+ # Kernel source tree. The logic does check it to prevent
323+ # directory traverse issues.
324+ #
325+
326+ srctree = os.path.abspath(os.environ["srctree"])
327+
328+ path = os.path.expandvars(self.arguments[0])
329+ src_path = os.path.join(srctree, path)
330+
331+ if os.path.isfile(src_path):
332+ base = srctree
333+ path = src_path
334+ else:
335+ raise self.warning(f'File "%s" doesn\'t exist', path)
336+
337+ abs_base = os.path.abspath(base)
338+ abs_full_path = os.path.abspath(os.path.join(base, path))
339+
340+ try:
341+ if os.path.commonpath([abs_full_path, abs_base]) != abs_base:
342+ raise self.severe('Problems with "%s" directive, prohibited path: %s' %
343+ (self.name, path))
344+ except ValueError:
345+ # Paths don't have the same drive (Windows) or other incompatibility
346+ raise self.severe('Problems with "%s" directive, invalid path: %s' %
347+ (self.name, path))
348+
349+ self.arguments[0] = path
350+
351+ #
352+ # Add path location to Sphinx dependencies to ensure proper cache
353+ # invalidation check.
354+ #
355+
356+ env.note_dependency(os.path.abspath(path))
357+
358+ if not self.state.document.settings.file_insertion_enabled:
359+ raise self.warning('"%s" directive disabled.' % self.name)
360+ source = self.state_machine.input_lines.source(self.lineno -
361+ self.state_machine.input_offset - 1)
362+ source_dir = os.path.dirname(os.path.abspath(source))
363+ path = directives.path(self.arguments[0])
364+ if path.startswith("<") and path.endswith(">"):
365+ path = os.path.join(self.standard_include_path, path[1:-1])
366+ path = os.path.normpath(os.path.join(source_dir, path))
367+
368+ # HINT: this is the only line I had to change / commented out:
369+ # path = utils.relative_path(None, path)
370+
371+ encoding = self.options.get("encoding",
372+ self.state.document.settings.input_encoding)
373+ tab_width = self.options.get("tab-width",
374+ self.state.document.settings.tab_width)
375+
376+ # Get optional arguments to related to cross-references generation
377+ if "generate-cross-refs" in self.options:
378+ return self.xref_text(env, path, tab_width)
379+
380+ rawtext = self.read_rawtext(path, encoding)
381+ rawtext = self.apply_range(rawtext)
382+
383+ if "code" in self.options:
384+ return self.code(path, tab_width, rawtext)
385+
386+ return self.literal(path, tab_width, rawtext)
387+
388+# ==============================================================================
389+
390+reported = set()
391+
392+def check_missing_refs(app, env, node, contnode):
393+ """Check broken refs for the files it creates xrefs"""
394+ if not node.source:
395+ return None
396+
397+ try:
398+ xref_files = env._xref_files
399+ except AttributeError:
400+ logger.critical("FATAL: _xref_files not initialized!")
401+ raise
402+
403+ # Only show missing references for kernel-include reference-parsed files
404+ if node.source not in xref_files:
405+ return None
406+
407+ target = node.get('reftarget', '')
408+ domain = node.get('refdomain', 'std')
409+ reftype = node.get('reftype', '')
410+
411+ msg = f"can't link to: {domain}:{reftype}:: {target}"
412+
413+ # Don't duplicate warnings
414+ data = (node.source, msg)
415+ if data in reported:
416+ return None
417+ reported.add(data)
418+
419+ logger.warning(msg, location=node, type='ref', subtype='missing')
420+
421+ return None
422+
423+def merge_xref_info(app, env, docnames, other):
424+ """
425+ As each process modify env._xref_files, we need to merge them back.
426+ """
427+ if not hasattr(other, "_xref_files"):
428+ return
429+ env._xref_files.update(getattr(other, "_xref_files", set()))
430+
431+def init_xref_docs(app, env, docnames):
432+ """Initialize a list of files that we're generating cross references¨"""
433+ app.env._xref_files = set()
434+
435+# ==============================================================================
436+
437+def setup(app):
438+ """Setup Sphinx exension"""
439+
440+ app.connect("env-before-read-docs", init_xref_docs)
441+ app.connect("env-merge-info", merge_xref_info)
442+ app.add_directive("kernel-include", KernelInclude)
443+ app.connect("missing-reference", check_missing_refs)
444+
445+ return {
446+ "version": __version__,
447+ "parallel_read_safe": True,
448+ "parallel_write_safe": True,
449+ }
Documentation/sphinx/maintainers_include.py+3−1
@@ -22,10 +22,12 @@ import re · 21 unmodified lines
2222 import os.path
2323
2424 from docutils import statemachine
25−from docutils.utils.error_reporting import ErrorString
2625 from docutils.parsers.rst import Directive
2726 from docutils.parsers.rst.directives.misc import Include
2827
28+def ErrorString(exc): # Shamelessly stolen from docutils
29+ return f'{exc.__class__.__name}: {exc}'
30+
2931 __version__ = '1.0'
3032
3133 def setup(app):
Documentation/sphinx/parse-headers.pl+0−404
@@ -1,404 +0,0 @@
1−#!/usr/bin/env perl
2−# SPDX-License-Identifier: GPL-2.0
3−# Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@kernel.org>.
4−
5−use strict;
6−use Text::Tabs;
7−use Getopt::Long;
8−use Pod::Usage;
9−
10−my $debug;
11−my $help;
12−my $man;
13−
14−GetOptions(
15− "debug" => \$debug,
16− 'usage|?' => \$help,
17− 'help' => \$man
18−) or pod2usage(2);
19−
20−pod2usage(1) if $help;
21−pod2usage(-exitstatus => 0, -verbose => 2) if $man;
22−pod2usage(2) if (scalar @ARGV < 2 || scalar @ARGV > 3);
23−
24−my ($file_in, $file_out, $file_exceptions) = @ARGV;
25−
26−my $data;
27−my %ioctls;
28−my %defines;
29−my %typedefs;
30−my %enums;
31−my %enum_symbols;
32−my %structs;
33−
34−require Data::Dumper if ($debug);
35−
36−#
37−# read the file and get identifiers
38−#
39−
40−my $is_enum = 0;
41−my $is_comment = 0;
42−open IN, $file_in or die "Can't open $file_in";
43−while (<IN>) {
44− $data .= $_;
45−
46− my $ln = $_;
47− if (!$is_comment) {
48− $ln =~ s,/\*.*(\*/),,g;
49−
50− $is_comment = 1 if ($ln =~ s,/\*.*,,);
51− } else {
52− if ($ln =~ s,^(.*\*/),,) {
53− $is_comment = 0;
54− } else {
55− next;
56− }
57− }
58−
59− if ($is_enum && $ln =~ m/^\s*([_\w][\w\d_]+)\s*[\,=]?/) {
60− my $s = $1;
61− my $n = $1;
62− $n =~ tr/A-Z/a-z/;
63− $n =~ tr/_/-/;
64−
65− $enum_symbols{$s} = "\\ :ref:`$s <$n>`\\ ";
66−
67− $is_enum = 0 if ($is_enum && m/\}/);
68− next;
69− }
70− $is_enum = 0 if ($is_enum && m/\}/);
71−
72− if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+_IO/) {
73− my $s = $1;
74− my $n = $1;
75− $n =~ tr/A-Z/a-z/;
76−
77− $ioctls{$s} = "\\ :ref:`$s <$n>`\\ ";
78− next;
79− }
80−
81− if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+/) {
82− my $s = $1;
83− my $n = $1;
84− $n =~ tr/A-Z/a-z/;
85− $n =~ tr/_/-/;
86−
87− $defines{$s} = "\\ :ref:`$s <$n>`\\ ";
88− next;
89− }
90−
91− if ($ln =~ m/^\s*typedef\s+([_\w][\w\d_]+)\s+(.*)\s+([_\w][\w\d_]+);/) {
92− my $s = $2;
93− my $n = $3;
94−
95− $typedefs{$n} = "\\ :c:type:`$n <$s>`\\ ";
96− next;
97− }
98− if ($ln =~ m/^\s*enum\s+([_\w][\w\d_]+)\s+\{/
99− || $ln =~ m/^\s*enum\s+([_\w][\w\d_]+)$/
100− || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)\s+\{/
101− || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)$/) {
102− my $s = $1;
103−
104− $enums{$s} = "enum :c:type:`$s`\\ ";
105−
106− $is_enum = $1;
107− next;
108− }
109− if ($ln =~ m/^\s*struct\s+([_\w][\w\d_]+)\s+\{/
110− || $ln =~ m/^\s*struct\s+([[_\w][\w\d_]+)$/
111− || $ln =~ m/^\s*typedef\s*struct\s+([_\w][\w\d_]+)\s+\{/
112− || $ln =~ m/^\s*typedef\s*struct\s+([[_\w][\w\d_]+)$/
113− ) {
114− my $s = $1;
115−
116− $structs{$s} = "struct $s\\ ";
117− next;
118− }
119−}
120−close IN;
121−
122−#
123−# Handle multi-line typedefs
124−#
125−
126−my @matches = ($data =~ m/typedef\s+struct\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,
127− $data =~ m/typedef\s+enum\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,);
128−foreach my $m (@matches) {
129− my $s = $m;
130−
131− $typedefs{$s} = "\\ :c:type:`$s`\\ ";
132− next;
133−}
134−
135−#
136−# Handle exceptions, if any
137−#
138−
139−my %def_reftype = (
140− "ioctl" => ":ref",
141− "define" => ":ref",
142− "symbol" => ":ref",
143− "typedef" => ":c:type",
144− "enum" => ":c:type",
145− "struct" => ":c:type",
146−);
147−
148−if ($file_exceptions) {
149− open IN, $file_exceptions or die "Can't read $file_exceptions";
150− while (<IN>) {
151− next if (m/^\s*$/ || m/^\s*#/);
152−
153− # Parsers to ignore a symbol
154−
155− if (m/^ignore\s+ioctl\s+(\S+)/) {
156− delete $ioctls{$1} if (exists($ioctls{$1}));
157− next;
158− }
159− if (m/^ignore\s+define\s+(\S+)/) {
160− delete $defines{$1} if (exists($defines{$1}));
161− next;
162− }
163− if (m/^ignore\s+typedef\s+(\S+)/) {
164− delete $typedefs{$1} if (exists($typedefs{$1}));
165− next;
166− }
167− if (m/^ignore\s+enum\s+(\S+)/) {
168− delete $enums{$1} if (exists($enums{$1}));
169− next;
170− }
171− if (m/^ignore\s+struct\s+(\S+)/) {
172− delete $structs{$1} if (exists($structs{$1}));
173− next;
174− }
175− if (m/^ignore\s+symbol\s+(\S+)/) {
176− delete $enum_symbols{$1} if (exists($enum_symbols{$1}));
177− next;
178− }
179−
180− # Parsers to replace a symbol
181− my ($type, $old, $new, $reftype);
182−
183− if (m/^replace\s+(\S+)\s+(\S+)\s+(\S+)/) {
184− $type = $1;
185− $old = $2;
186− $new = $3;
187− } else {
188− die "Can't parse $file_exceptions: $_";
189− }
190−
191− if ($new =~ m/^\:c\:(data|func|macro|type)\:\`(.+)\`/) {
192− $reftype = ":c:$1";
193− $new = $2;
194− } elsif ($new =~ m/\:ref\:\`(.+)\`/) {
195− $reftype = ":ref";
196− $new = $1;
197− } else {
198− $reftype = $def_reftype{$type};
199− }
200− $new = "$reftype:`$old <$new>`";
201−
202− if ($type eq "ioctl") {
203− $ioctls{$old} = $new if (exists($ioctls{$old}));
204− next;
205− }
206− if ($type eq "define") {
207− $defines{$old} = $new if (exists($defines{$old}));
208− next;
209− }
210− if ($type eq "symbol") {
211− $enum_symbols{$old} = $new if (exists($enum_symbols{$old}));
212− next;
213− }
214− if ($type eq "typedef") {
215− $typedefs{$old} = $new if (exists($typedefs{$old}));
216− next;
217− }
218− if ($type eq "enum") {
219− $enums{$old} = $new if (exists($enums{$old}));
220− next;
221− }
222− if ($type eq "struct") {
223− $structs{$old} = $new if (exists($structs{$old}));
224− next;
225− }
226−
227− die "Can't parse $file_exceptions: $_";
228− }
229−}
230−
231−if ($debug) {
232− print Data::Dumper->Dump([\%ioctls], [qw(*ioctls)]) if (%ioctls);
233− print Data::Dumper->Dump([\%typedefs], [qw(*typedefs)]) if (%typedefs);
234− print Data::Dumper->Dump([\%enums], [qw(*enums)]) if (%enums);
235− print Data::Dumper->Dump([\%structs], [qw(*structs)]) if (%structs);
236− print Data::Dumper->Dump([\%defines], [qw(*defines)]) if (%defines);
237− print Data::Dumper->Dump([\%enum_symbols], [qw(*enum_symbols)]) if (%enum_symbols);
238−}
239−
240−#
241−# Align block
242−#
243−$data = expand($data);
244−$data = " " . $data;
245−$data =~ s/\n/\n /g;
246−$data =~ s/\n\s+$/\n/g;
247−$data =~ s/\n\s+\n/\n\n/g;
248−
249−#
250−# Add escape codes for special characters
251−#
252−$data =~ s,([\_\`\*\<\>\&\\\\:\/\|\%\$\#\{\}\~\^]),\\$1,g;
253−
254−$data =~ s,DEPRECATED,**DEPRECATED**,g;
255−
256−#
257−# Add references
258−#
259−
260−my $start_delim = "[ \n\t\(\=\*\@]";
261−my $end_delim = "(\\s|,|\\\\=|\\\\:|\\;|\\\)|\\}|\\{)";
262−
263−foreach my $r (keys %ioctls) {
264− my $s = $ioctls{$r};
265−
266− $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
267−
268− print "$r -> $s\n" if ($debug);
269−
270− $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
271−}
272−
273−foreach my $r (keys %defines) {
274− my $s = $defines{$r};
275−
276− $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
277−
278− print "$r -> $s\n" if ($debug);
279−
280− $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
281−}
282−
283−foreach my $r (keys %enum_symbols) {
284− my $s = $enum_symbols{$r};
285−
286− $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
287−
288− print "$r -> $s\n" if ($debug);
289−
290− $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
291−}
292−
293−foreach my $r (keys %enums) {
294− my $s = $enums{$r};
295−
296− $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
297−
298− print "$r -> $s\n" if ($debug);
299−
300− $data =~ s/enum\s+($r)$end_delim/$s$2/g;
301−}
302−
303−foreach my $r (keys %structs) {
304− my $s = $structs{$r};
305−
306− $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
307−
308− print "$r -> $s\n" if ($debug);
309−
310− $data =~ s/struct\s+($r)$end_delim/$s$2/g;
311−}
312−
313−foreach my $r (keys %typedefs) {
314− my $s = $typedefs{$r};
315−
316− $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
317−
318− print "$r -> $s\n" if ($debug);
319− $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
320−}
321−
322−$data =~ s/\\ ([\n\s])/\1/g;
323−
324−#
325−# Generate output file
326−#
327−
328−my $title = $file_in;
329−$title =~ s,.*/,,;
330−
331−open OUT, "> $file_out" or die "Can't open $file_out";
332−print OUT ".. -*- coding: utf-8; mode: rst -*-\n\n";
333−print OUT "$title\n";
334−print OUT "=" x length($title);
335−print OUT "\n\n.. parsed-literal::\n\n";
336−print OUT $data;
337−close OUT;
338−
339−__END__
340−
341−=head1 NAME
342−
343−parse_headers.pl - parse a C file, in order to identify functions, structs,
344−enums and defines and create cross-references to a Sphinx book.
345−
346−=head1 SYNOPSIS
347−
348−B<parse_headers.pl> [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>]
349−
350−Where <options> can be: --debug, --help or --usage.
351−
352−=head1 OPTIONS
353−
354−=over 8
355−
356−=item B<--debug>
357−
358−Put the script in verbose mode, useful for debugging.
359−
360−=item B<--usage>
361−
362−Prints a brief help message and exits.
363−
364−=item B<--help>
365−
366−Prints a more detailed help message and exits.
367−
368−=back
369−
370−=head1 DESCRIPTION
371−
372−Convert a C header or source file (C_FILE), into a ReStructured Text
373−included via ..parsed-literal block with cross-references for the
374−documentation files that describe the API. It accepts an optional
375−EXCEPTIONS_FILE with describes what elements will be either ignored or
376−be pointed to a non-default reference.
377−
378−The output is written at the (OUT_FILE).
379−
380−It is capable of identifying defines, functions, structs, typedefs,
381−enums and enum symbols and create cross-references for all of them.
382−It is also capable of distinguish #define used for specifying a Linux
383−ioctl.
384−
385−The EXCEPTIONS_FILE contain two rules to allow ignoring a symbol or
386−to replace the default references by a custom one.
387−
388−Please read Documentation/doc-guide/parse-headers.rst at the Kernel's
389−tree for more details.
390−
391−=head1 BUGS
392−
393−Report bugs to Mauro Carvalho Chehab <mchehab@kernel.org>
394−
395−=head1 COPYRIGHT
396−
397−Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@kernel.org>.
398−
399−License GPLv2: GNU GPL version 2 <https://gnu.org/licenses/gpl.html>.
400−
401−This is free software: you are free to change and redistribute it.
402−There is NO WARRANTY, to the extent permitted by law.
403−
404−=cut
Documentation/sphinx/templates/kernel-toc.html+2−1
@@ -1,4 +1,5 @@
1−<!-- SPDX-License-Identifier: GPL-2.0 -->
1+{# SPDX-License-Identifier: GPL-2.0 #}
2+
23 {# Create a local TOC the kernel way #}
34 <p>
45 <h3 class="kernel-toc-contents">Contents</h3>
Documentation/sphinx/templates/translations.html+2−2
@@ -1,5 +1,5 @@
1−<!-- SPDX-License-Identifier: GPL-2.0 -->
2−<!-- Copyright © 2023, Oracle and/or its affiliates. -->
1+{# SPDX-License-Identifier: GPL-2.0 #}
2+{# Copyright © 2023, Oracle and/or its affiliates. #}
33
44 {# Create a language menu for translations #}
55 {% if languages|length > 0: %}
Documentation/staging/remoteproc.rst+1−1
@@ -104,7 +104,7 @@ Typical usage · 103 unmodified lines
104104 rproc_shutdown(my_rproc);
105105 }
106106
107−API for implementors
107+API for implementers
108108 ====================
109109
110110 ::
Documentation/trace/boottime-trace.rst+1−1
@@ -19,7 +19,7 @@ this uses bootconfig file to describe tracing feature programming. · 18 unmodified lines
1919 Options in the Boot Config
2020 ==========================
2121
22−Here is the list of available options list for boot time tracing in
22+Here is the list of available options for boot time tracing in
2323 boot config file [1]_. All options are under "ftrace." or "kernel."
2424 prefix. See kernel parameters for the options which starts
2525 with "kernel." prefix [2]_.
Documentation/trace/debugging.rst+1−1
@@ -59,7 +59,7 @@ There is various methods of acquiring the state of the system when a kernel · 58 unmodified lines
5959 crash occurs. This could be from the oops message in printk, or one could
6060 use kexec/kdump. But these just show what happened at the time of the crash.
6161 It can be very useful in knowing what happened up to the point of the crash.
62−The tracing ring buffer, by default, is a circular buffer than will
62+The tracing ring buffer, by default, is a circular buffer that will
6363 overwrite older events with newer ones. When a crash happens, the content of
6464 the ring buffer will be all the events that lead up to the crash.
6565
Documentation/trace/events.rst+4−4
@@ -629,8 +629,8 @@ following: · 628 unmodified lines
629629 - tracing synthetic events from in-kernel code
630630 - the low-level "dynevent_cmd" API
631631
632−7.1 Dyamically creating synthetic event definitions
633−---------------------------------------------------
632+7.1 Dynamically creating synthetic event definitions
633+----------------------------------------------------
634634
635635 There are a couple ways to create a new synthetic event from a kernel
636636 module or other kernel code.
@@ -944,8 +944,8 @@ Note that synth_event_trace_end() must be called at the end regardless · 307 unmodified lines
944944 of whether any of the add calls failed (say due to a bad field name
945945 being passed in).
946946
947−7.3 Dyamically creating kprobe and kretprobe event definitions
948−--------------------------------------------------------------
947+7.3 Dynamically creating kprobe and kretprobe event definitions
948+---------------------------------------------------------------
949949
950950 To create a kprobe or kretprobe trace event from kernel code, the
951951 kprobe_event_gen_cmd_start() or kretprobe_event_gen_cmd_start()
Documentation/trace/fprobe.rst+1−1
@@ -81,7 +81,7 @@ Same as ftrace, the registered callbacks will start being called some time · 80 unmodified lines
8181 after the register_fprobe() is called and before it returns. See
8282 :file:`Documentation/trace/ftrace.rst`.
8383
84−Also, the unregister_fprobe() will guarantee that the both enter and exit
84+Also, the unregister_fprobe() will guarantee that both enter and exit
8585 handlers are no longer being called by functions after unregister_fprobe()
8686 returns as same as unregister_ftrace_function().
8787
Documentation/trace/ftrace-uses.rst+1−1
@@ -193,7 +193,7 @@ FTRACE_OPS_FL_RECURSION · 192 unmodified lines
193193 Note, if this flag is set, then the callback will always be called
194194 with preemption disabled. If it is not set, then it is possible
195195 (but not guaranteed) that the callback will be called in
196− preemptable context.
196+ preemptible context.
197197
198198 FTRACE_OPS_FL_IPMODIFY
199199 Requires FTRACE_OPS_FL_SAVE_REGS set. If the callback is to "hijack"
Documentation/trace/ftrace.rst+7−7
@@ -30,7 +30,7 @@ disabled and enabled, as well as for preemption and from a time · 29 unmodified lines
3030 a task is woken to the task is actually scheduled in.
3131
3232 One of the most common uses of ftrace is the event tracing.
33−Throughout the kernel is hundreds of static event points that
33+Throughout the kernel are hundreds of static event points that
3434 can be enabled via the tracefs file system to see what is
3535 going on in certain parts of the kernel.
3636
@@ -383,7 +383,7 @@ of ftrace. Here is a list of some of the key files: · 346 unmodified lines
383383 not be listed in this count.
384384
385385 If the callback registered to be traced by a function with
386− the "save regs" attribute (thus even more overhead), a 'R'
386+ the "save regs" attribute (thus even more overhead), an 'R'
387387 will be displayed on the same line as the function that
388388 is returning registers.
389389
@@ -392,7 +392,7 @@ of ftrace. Here is a list of some of the key files: · 2 unmodified lines
392392 an 'I' will be displayed on the same line as the function that
393393 can be overridden.
394394
395− If a non ftrace trampoline is attached (BPF) a 'D' will be displayed.
395+ If a non-ftrace trampoline is attached (BPF) a 'D' will be displayed.
396396 Note, normal ftrace trampolines can also be attached, but only one
397397 "direct" trampoline can be attached to a given function at a time.
398398
@@ -402,7 +402,7 @@ of ftrace. Here is a list of some of the key files: · 3 unmodified lines
402402
403403 If a function had either the "ip modify" or a "direct" call attached to
404404 it in the past, a 'M' will be shown. This flag is never cleared. It is
405− used to know if a function was every modified by the ftrace infrastructure,
405+ used to know if a function was ever modified by the ftrace infrastructure,
406406 and can be used for debugging.
407407
408408 If the architecture supports it, it will also show what callback
@@ -418,7 +418,7 @@ of ftrace. Here is a list of some of the key files: · 9 unmodified lines
418418
419419 This file contains all the functions that ever had a function callback
420420 to it via the ftrace infrastructure. It has the same format as
421− enabled_functions but shows all functions that have every been
421+ enabled_functions but shows all functions that have ever been
422422 traced.
423423
424424 To see any function that has every been modified by "ip modify" or a
@@ -517,7 +517,7 @@ of ftrace. Here is a list of some of the key files: · 92 unmodified lines
517517 Whenever an event is recorded into the ring buffer, a
518518 "timestamp" is added. This stamp comes from a specified
519519 clock. By default, ftrace uses the "local" clock. This
520− clock is very fast and strictly per cpu, but on some
520+ clock is very fast and strictly per CPU, but on some
521521 systems it may not be monotonic with respect to other
522522 CPUs. In other words, the local clocks may not be in sync
523523 with local clocks on other CPUs.
@@ -868,7 +868,7 @@ Here is the list of current tracers that may be configured. · 344 unmodified lines
868868
869869 "mmiotrace"
870870
871− A special tracer that is used to trace binary module.
871+ A special tracer that is used to trace binary modules.
872872 It will trace all the calls that a module makes to the
873873 hardware. Everything it writes and reads from the I/O
874874 as well.
Documentation/trace/histogram-design.rst+89−86
@@ -11,13 +11,14 @@ histograms work and how the individual pieces map to the data · 10 unmodified lines
1111 structures used to implement them in trace_events_hist.c and
1212 tracing_map.c.
1313
14−Note: All the ftrace histogram command examples assume the working
15− directory is the ftrace /tracing directory. For example::
14+.. note::
15+ All the ftrace histogram command examples assume the working
16+ directory is the ftrace /tracing directory. For example::
1617
1718 # cd /sys/kernel/tracing
1819
19−Also, the histogram output displayed for those commands will be
20−generally be truncated - only enough to make the point is displayed.
20+ Also, the histogram output displayed for those commands will be
21+ generally be truncated - only enough to make the point is displayed.
2122
2223 'hist_debug' trace event files
2324 ==============================
@@ -142,30 +143,30 @@ elements for a couple hypothetical keys and values.:: · 118 unmodified lines
142143 +--------------+ | |
143144 n_keys = n_fields - n_vals | |
144145
145−The hist_data n_vals and n_fields delineate the extent of the fields[] | |
146−array and separate keys from values for the rest of the code. | |
147−
148−Below is a run-time representation of the tracing_map part of the | |
149−histogram, with pointers from various parts of the fields[] array | |
150−to corresponding parts of the tracing_map. | |
151−
152−The tracing_map consists of an array of tracing_map_entrys and a set | |
153−of preallocated tracing_map_elts (abbreviated below as map_entry and | |
154−map_elt). The total number of map_entrys in the hist_data.map array = | |
155−map->max_elts (actually map->map_size but only max_elts of those are | |
156−used. This is a property required by the map_insert() algorithm). | |
157−
158−If a map_entry is unused, meaning no key has yet hashed into it, its | |
159−.key value is 0 and its .val pointer is NULL. Once a map_entry has | |
160−been claimed, the .key value contains the key's hash value and the | |
161−.val member points to a map_elt containing the full key and an entry | |
162−for each key or value in the map_elt.fields[] array. There is an | |
163−entry in the map_elt.fields[] array corresponding to each hist_field | |
164−in the histogram, and this is where the continually aggregated sums | |
165−corresponding to each histogram value are kept. | |
166−
167−The diagram attempts to show the relationship between the | |
168−hist_data.fields[] and the map_elt.fields[] with the links drawn | |
146+The hist_data n_vals and n_fields delineate the extent of the fields[]
147+array and separate keys from values for the rest of the code.
148+
149+Below is a run-time representation of the tracing_map part of the
150+histogram, with pointers from various parts of the fields[] array
151+to corresponding parts of the tracing_map.
152+
153+The tracing_map consists of an array of tracing_map_entrys and a set
154+of preallocated tracing_map_elts (abbreviated below as map_entry and
155+map_elt). The total number of map_entrys in the hist_data.map array =
156+map->max_elts (actually map->map_size but only max_elts of those are
157+used. This is a property required by the map_insert() algorithm).
158+
159+If a map_entry is unused, meaning no key has yet hashed into it, its
160+.key value is 0 and its .val pointer is NULL. Once a map_entry has
161+been claimed, the .key value contains the key's hash value and the
162+.val member points to a map_elt containing the full key and an entry
163+for each key or value in the map_elt.fields[] array. There is an
164+entry in the map_elt.fields[] array corresponding to each hist_field
165+in the histogram, and this is where the continually aggregated sums
166+corresponding to each histogram value are kept.
167+
168+The diagram attempts to show the relationship between the
169+hist_data.fields[] and the map_elt.fields[] with the links drawn
169170 between diagrams::
170171
171172 +-----------+ | |
@@ -380,7 +381,9 @@ entry, ts0, corresponding to the ts0 variable in the sched_waking · 208 unmodified lines
380381 trigger above.
381382
382383 sched_waking histogram
383−----------------------::
384+----------------------
385+
386+.. code-block::
384387
385388 +------------------+
386389 | hist_data |<-------------------------------------------------------+
@@ -440,31 +443,31 @@ sched_waking histogram · 53 unmodified lines
440443 n_keys = n_fields - n_vals | | |
441444 | | |
442445
443−This is very similar to the basic case. In the above diagram, we can | | |
444−see a new .flags member has been added to the struct hist_field | | |
445−struct, and a new entry added to hist_data.fields representing the ts0 | | |
446−variable. For a normal val hist_field, .flags is just 0 (modulo | | |
447−modifier flags), but if the value is defined as a variable, the .flags | | |
448−contains a set FL_VAR bit. | | |
449−
450−As you can see, the ts0 entry's .var.idx member contains the index | | |
451−into the tracing_map_elts' .vars[] array containing variable values. | | |
452−This idx is used whenever the value of the variable is set or read. | | |
453−The map_elt.vars idx assigned to the given variable is assigned and | | |
454−saved in .var.idx by create_tracing_map_fields() after it calls | | |
455−tracing_map_add_var(). | | |
456−
457−Below is a representation of the histogram at run-time, which | | |
458−populates the map, along with correspondence to the above hist_data and | | |
459−hist_field data structures. | | |
460−
461−The diagram attempts to show the relationship between the | | |
462−hist_data.fields[] and the map_elt.fields[] and map_elt.vars[] with | | |
463−the links drawn between diagrams. For each of the map_elts, you can | | |
464−see that the .fields[] members point to the .sum or .offset of a key | | |
465−or val and the .vars[] members point to the value of a variable. The | | |
466−arrows between the two diagrams show the linkages between those | | |
467−tracing_map members and the field definitions in the corresponding | | |
446+This is very similar to the basic case. In the above diagram, we can
447+see a new .flags member has been added to the struct hist_field
448+struct, and a new entry added to hist_data.fields representing the ts0
449+variable. For a normal val hist_field, .flags is just 0 (modulo
450+modifier flags), but if the value is defined as a variable, the .flags
451+contains a set FL_VAR bit.
452+
453+As you can see, the ts0 entry's .var.idx member contains the index
454+into the tracing_map_elts' .vars[] array containing variable values.
455+This idx is used whenever the value of the variable is set or read.
456+The map_elt.vars idx assigned to the given variable is assigned and
457+saved in .var.idx by create_tracing_map_fields() after it calls
458+tracing_map_add_var().
459+
460+Below is a representation of the histogram at run-time, which
461+populates the map, along with correspondence to the above hist_data and
462+hist_field data structures.
463+
464+The diagram attempts to show the relationship between the
465+hist_data.fields[] and the map_elt.fields[] and map_elt.vars[] with
466+the links drawn between diagrams. For each of the map_elts, you can
467+see that the .fields[] members point to the .sum or .offset of a key
468+or val and the .vars[] members point to the value of a variable. The
469+arrows between the two diagrams show the linkages between those
470+tracing_map members and the field definitions in the corresponding
468471 hist_data fields[] members.::
469472
470473 +-----------+ | | |
@@ -565,40 +568,40 @@ hist_data fields[] members.:: · 94 unmodified lines
565568 | | | |
566569 +---------------+ | |
567570
568−For each used map entry, there's a map_elt pointing to an array of | |
569−.vars containing the current value of the variables associated with | |
570−that histogram entry. So in the above, the timestamp associated with | |
571−pid 999 is 113345679876, and the timestamp variable in the same | |
572−.var.idx for pid 4444 is 213499240729. | |
573−
574−sched_switch histogram | |
575−---------------------- | |
576−
577−The sched_switch histogram paired with the above sched_waking | |
578−histogram is shown below. The most important aspect of the | |
579−sched_switch histogram is that it references a variable on the | |
580−sched_waking histogram above. | |
581−
582−The histogram diagram is very similar to the others so far displayed, | |
583−but it adds variable references. You can see the normal hitcount and | |
584−key fields along with a new wakeup_lat variable implemented in the | |
585−same way as the sched_waking ts0 variable, but in addition there's an | |
586−entry with the new FL_VAR_REF (short for HIST_FIELD_FL_VAR_REF) flag. | |
587−
588−Associated with the new var ref field are a couple of new hist_field | |
589−members, var.hist_data and var_ref_idx. For a variable reference, the | |
590−var.hist_data goes with the var.idx, which together uniquely identify | |
591−a particular variable on a particular histogram. The var_ref_idx is | |
592−just the index into the var_ref_vals[] array that caches the values of | |
593−each variable whenever a hist trigger is updated. Those resulting | |
594−values are then finally accessed by other code such as trace action | |
595−code that uses the var_ref_idx values to assign param values. | |
596−
597−The diagram below describes the situation for the sched_switch | |
571+For each used map entry, there's a map_elt pointing to an array of
572+.vars containing the current value of the variables associated with
573+that histogram entry. So in the above, the timestamp associated with
574+pid 999 is 113345679876, and the timestamp variable in the same
575+.var.idx for pid 4444 is 213499240729.
576+
577+sched_switch histogram
578+----------------------
579+
580+The sched_switch histogram paired with the above sched_waking
581+histogram is shown below. The most important aspect of the
582+sched_switch histogram is that it references a variable on the
583+sched_waking histogram above.
584+
585+The histogram diagram is very similar to the others so far displayed,
586+but it adds variable references. You can see the normal hitcount and
587+key fields along with a new wakeup_lat variable implemented in the
588+same way as the sched_waking ts0 variable, but in addition there's an
589+entry with the new FL_VAR_REF (short for HIST_FIELD_FL_VAR_REF) flag.
590+
591+Associated with the new var ref field are a couple of new hist_field
592+members, var.hist_data and var_ref_idx. For a variable reference, the
593+var.hist_data goes with the var.idx, which together uniquely identify
594+a particular variable on a particular histogram. The var_ref_idx is
595+just the index into the var_ref_vals[] array that caches the values of
596+each variable whenever a hist trigger is updated. Those resulting
597+values are then finally accessed by other code such as trace action
598+code that uses the var_ref_idx values to assign param values.
599+
600+The diagram below describes the situation for the sched_switch
598601 histogram referred to before::
599602
600− # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0' >> | |
601− events/sched/sched_switch/trigger | |
603+ # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0' >>
604+ events/sched/sched_switch/trigger
602605 | |
603606 +------------------+ | |
604607 | hist_data | | |
Documentation/trace/histogram.rst+20−20
@@ -186,8 +186,8 @@ Documentation written by Tom Zanussi · 185 unmodified lines
186186 The examples below provide a more concrete illustration of the
187187 concepts and typical usage patterns discussed above.
188188
189−'special' event fields
190−------------------------
189+2.1. 'special' event fields
190+---------------------------
191191
192192 There are a number of 'special event fields' available for use as
193193 keys or values in a hist trigger. These look like and behave as if
@@ -204,16 +204,16 @@ Documentation written by Tom Zanussi · 10 unmodified lines
204204 common_cpu int the cpu on which the event occurred.
205205 ====================== ==== =======================================
206206
207−Extended error information
208−--------------------------
207+2.2. Extended error information
208+-------------------------------
209209
210210 For some error conditions encountered when invoking a hist trigger
211211 command, extended error information is available via the
212− tracing/error_log file. See Error Conditions in
213− :file:`Documentation/trace/ftrace.rst` for details.
212+ tracing/error_log file. See "Error conditions" section in
213+ Documentation/trace/ftrace.rst for details.
214214
215−6.2 'hist' trigger examples
216−---------------------------
215+2.3. 'hist' trigger examples
216+----------------------------
217217
218218 The first set of examples creates aggregations using the kmalloc
219219 event. The fields that can be used for the hist trigger are listed
@@ -840,7 +840,7 @@ Extended error information · 620 unmodified lines
840840
841841 The compound key examples used a key and a sum value (hitcount) to
842842 sort the output, but we can just as easily use two keys instead.
843− Here's an example where we use a compound key composed of the the
843+ Here's an example where we use a compound key composed of the
844844 common_pid and size event fields. Sorting with pid as the primary
845845 key and 'size' as the secondary key allows us to display an
846846 ordered summary of the recvfrom sizes, with counts, received by
@@ -1608,8 +1608,8 @@ Extended error information · 761 unmodified lines
16081608 Entries: 7
16091609 Dropped: 0
16101610
1611−2.2 Inter-event hist triggers
1612−-----------------------------
1611+2.4. Inter-event hist triggers
1612+------------------------------
16131613
16141614 Inter-event hist triggers are hist triggers that combine values from
16151615 one or more other events and create a histogram using that data. Data
@@ -1685,8 +1685,8 @@ pseudo-file. · 69 unmodified lines
16851685
16861686 These features are described in more detail in the following sections.
16871687
1688−2.2.1 Histogram Variables
1689−-------------------------
1688+2.5. Histogram Variables
1689+------------------------
16901690
16911691 Variables are simply named locations used for saving and retrieving
16921692 values between matching events. A 'matching' event is defined as an
@@ -1789,8 +1789,8 @@ or assigned to a variable and referenced in a subsequent expression:: · 96 unmodified lines
17891789
17901790 Variables can even hold stacktraces, which are useful with synthetic events.
17911791
1792−2.2.2 Synthetic Events
1793−----------------------
1792+2.6. Synthetic Events
1793+---------------------
17941794
17951795 Synthetic events are user-defined events generated from hist trigger
17961796 variables or fields associated with one or more other events. Their
@@ -1846,7 +1846,7 @@ the command that defined it with a '!':: · 49 unmodified lines
18461846 At this point, there isn't yet an actual 'wakeup_latency' event
18471847 instantiated in the event subsystem - for this to happen, a 'hist
18481848 trigger action' needs to be instantiated and bound to actual fields
1849−and variables defined on other events (see Section 2.2.3 below on
1849+and variables defined on other events (see Section 2.7. below on
18501850 how that is done using hist trigger 'onmatch' action). Once that is
18511851 done, the 'wakeup_latency' synthetic event instance is created.
18521852
@@ -2094,8 +2094,8 @@ histogram:: · 241 unmodified lines
20942094 Entries: 7
20952095 Dropped: 0
20962096
2097−2.2.3 Hist trigger 'handlers' and 'actions'
2098−-------------------------------------------
2097+2.7. Hist trigger 'handlers' and 'actions'
2098+------------------------------------------
20992099
21002100 A hist trigger 'action' is a function that's executed (in most cases
21012101 conditionally) whenever a histogram entry is added or updated.
@@ -2526,8 +2526,8 @@ The following commonly-used handler.action pairs are available: · 424 unmodified lines
25262526 kworker/3:2-135 [003] d..3 49.823123: sched_switch: prev_comm=kworker/3:2 prev_pid=135 prev_prio=120 prev_state=T ==> next_comm=swapper/3 next_pid=0 next_prio=120
25272527 <idle>-0 [004] ..s7 49.823798: tcp_probe: src=10.0.0.10:54326 dest=23.215.104.193:80 mark=0x0 length=32 snd_nxt=0xe3ae2ff5 snd_una=0xe3ae2ecd snd_cwnd=10 ssthresh=2147483647 snd_wnd=28960 srtt=19604 rcv_wnd=29312
25282528
2529−3. User space creating a trigger
2530−--------------------------------
2529+2.8. User space creating a trigger
2530+----------------------------------
25312531
25322532 Writing into /sys/kernel/tracing/trace_marker writes into the ftrace
25332533 ring buffer. This can also act like an event, by writing into the trigger
Documentation/trace/rv/monitor_synthesis.rst+1−1
@@ -181,7 +181,7 @@ which is the list of atomic propositions present in the LTL specification · 180 unmodified lines
181181 functions interacting with the Buchi automaton.
182182
183183 While generating code, `rvgen` cannot understand the meaning of the atomic
184−propositions. Thus, that task is left for manual work. The recommended pratice
184+propositions. Thus, that task is left for manual work. The recommended practice
185185 is adding tracepoints to places where the atomic propositions change; and in the
186186 tracepoints' handlers: the Buchi automaton is executed using::
187187
Documentation/translations/it_IT/process/changes.rst+0−14
@@ -46,7 +46,6 @@ util-linux 2.10o mount --version · 45 unmodified lines
4646 kmod 13 depmod -V
4747 e2fsprogs 1.41.4 e2fsck -V
4848 jfsutils 1.1.3 fsck.jfs -V
49−reiserfsprogs 3.6.3 reiserfsck -V
5049 xfsprogs 2.6.0 xfs_db -V
5150 squashfs-tools 4.0 mksquashfs -version
5251 btrfs-progs 0.18 btrfsck
@@ -260,14 +259,6 @@ Sono disponibili i seguenti strumenti: · 207 unmodified lines
260259
261260 - sono disponibili altri strumenti per il file-system.
262261
263−Reiserfsprogs
264−-------------
265−
266−Il pacchetto reiserfsprogs dovrebbe essere usato con reiserfs-3.6.x (Linux
267−kernel 2.4.x). Questo è un pacchetto combinato che contiene versioni
268−funzionanti di ``mkreiserfs``, ``resize_reiserfs``, ``debugreiserfs`` e
269−``reiserfsck``. Questi programmi funzionano sulle piattaforme i386 e alpha.
270−
271262 Xfsprogs
272263 --------
273264
@@ -479,11 +470,6 @@ JFSutils · 205 unmodified lines
479470
480471 - <https://jfs.sourceforge.net/>
481472
482−Reiserfsprogs
483−-------------
484−
485−- <https://git.kernel.org/pub/scm/linux/kernel/git/jeffm/reiserfsprogs.git/>
486−
487473 Xfsprogs
488474 --------
489475
Documentation/userspace-api/media/Makefile+0−64
@@ -1,64 +0,0 @@
1−# SPDX-License-Identifier: GPL-2.0
2−
3−# Rules to convert a .h file to inline RST documentation
4−
5−SRC_DIR=$(srctree)/Documentation/userspace-api/media
6−PARSER = $(srctree)/Documentation/sphinx/parse-headers.pl
7−UAPI = $(srctree)/include/uapi/linux
8−KAPI = $(srctree)/include/linux
9−
10−FILES = ca.h.rst dmx.h.rst frontend.h.rst net.h.rst \
11− videodev2.h.rst media.h.rst cec.h.rst lirc.h.rst
12−
13−TARGETS := $(addprefix $(BUILDDIR)/, $(FILES))
14−
15−gen_rst = \
16− echo ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions; \
17− ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions
18−
19−quiet_gen_rst = echo ' PARSE $(patsubst $(srctree)/%,%,$<)'; \
20− ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions
21−
22−silent_gen_rst = ${gen_rst}
23−
24−$(BUILDDIR)/ca.h.rst: ${UAPI}/dvb/ca.h ${PARSER} $(SRC_DIR)/ca.h.rst.exceptions
25− @$($(quiet)gen_rst)
26−
27−$(BUILDDIR)/dmx.h.rst: ${UAPI}/dvb/dmx.h ${PARSER} $(SRC_DIR)/dmx.h.rst.exceptions
28− @$($(quiet)gen_rst)
29−
30−$(BUILDDIR)/frontend.h.rst: ${UAPI}/dvb/frontend.h ${PARSER} $(SRC_DIR)/frontend.h.rst.exceptions
31− @$($(quiet)gen_rst)
32−
33−$(BUILDDIR)/net.h.rst: ${UAPI}/dvb/net.h ${PARSER} $(SRC_DIR)/net.h.rst.exceptions
34− @$($(quiet)gen_rst)
35−
36−$(BUILDDIR)/videodev2.h.rst: ${UAPI}/videodev2.h ${PARSER} $(SRC_DIR)/videodev2.h.rst.exceptions
37− @$($(quiet)gen_rst)
38−
39−$(BUILDDIR)/media.h.rst: ${UAPI}/media.h ${PARSER} $(SRC_DIR)/media.h.rst.exceptions
40− @$($(quiet)gen_rst)
41−
42−$(BUILDDIR)/cec.h.rst: ${UAPI}/cec.h ${PARSER} $(SRC_DIR)/cec.h.rst.exceptions
43− @$($(quiet)gen_rst)
44−
45−$(BUILDDIR)/lirc.h.rst: ${UAPI}/lirc.h ${PARSER} $(SRC_DIR)/lirc.h.rst.exceptions
46− @$($(quiet)gen_rst)
47−
48−# Media build rules
49−
50−.PHONY: all html texinfo epub xml latex
51−
52−all: $(IMGDOT) $(BUILDDIR) ${TARGETS}
53−html: all
54−texinfo: all
55−epub: all
56−xml: all
57−latex: $(IMGPDF) all
58−linkcheck:
59−
60−clean:
61− -rm -f $(DOTTGT) $(IMGTGT) ${TARGETS} 2>/dev/null
62−
63−$(BUILDDIR):
64− $(Q)mkdir -p $@
Documentation/userspace-api/media/cec/cec-header.rst+3−2
@@ -6,5 +6,6 @@ · 5 unmodified lines
66 CEC Header File
77 ***************
88
9−.. kernel-include:: $BUILDDIR/cec.h.rst
10−
9+.. kernel-include:: include/uapi/linux/cec.h
10+ :generate-cross-refs:
11+ :exception-file: cec.h.rst.exceptions
Documentation/userspace-api/media/cec/cec.h.rst.exceptionsrenamed from Documentation/userspace-api/media/cec.h.rst.exceptions+0−0

File renamed without changes.

Documentation/userspace-api/media/dvb/ca.h.rst.exceptionsrenamed from Documentation/userspace-api/media/ca.h.rst.exceptions+0−0

File renamed without changes.

Documentation/userspace-api/media/dvb/dmx.h.rst.exceptionsrenamed from Documentation/userspace-api/media/dmx.h.rst.exceptions+0−0

File renamed without changes.

Documentation/userspace-api/media/dvb/frontend.h.rst.exceptionsrenamed from Documentation/userspace-api/media/frontend.h.rst.exceptions+0−0

File renamed without changes.

Documentation/userspace-api/media/dvb/headers.rst+13−4
@@ -7,10 +7,19 @@ Digital TV uAPI header files · 6 unmodified lines
77 Digital TV uAPI headers
88 ***********************
99
10−.. kernel-include:: $BUILDDIR/frontend.h.rst
10+.. kernel-include:: include/uapi/linux/dvb/frontend.h
11+ :generate-cross-refs:
12+ :exception-file: frontend.h.rst.exceptions
1113
12−.. kernel-include:: $BUILDDIR/dmx.h.rst
14+.. kernel-include:: include/uapi/linux/dvb/dmx.h
15+ :generate-cross-refs:
16+ :exception-file: dmx.h.rst.exceptions
1317
14−.. kernel-include:: $BUILDDIR/ca.h.rst
18+.. kernel-include:: include/uapi/linux/dvb/ca.h
19+ :generate-cross-refs:
20+ :exception-file: ca.h.rst.exceptions
21+
22+.. kernel-include:: include/uapi/linux/dvb/net.h
23+ :generate-cross-refs:
24+ :exception-file: net.h.rst.exceptions
1525
16−.. kernel-include:: $BUILDDIR/net.h.rst
Documentation/userspace-api/media/dvb/net.h.rst.exceptionsrenamed from Documentation/userspace-api/media/net.h.rst.exceptions+0−0

File renamed without changes.

Documentation/userspace-api/media/mediactl/media-header.rst+3−2
@@ -6,5 +6,6 @@ · 5 unmodified lines
66 Media Controller Header File
77 ****************************
88
9−.. kernel-include:: $BUILDDIR/media.h.rst
10−
9+.. kernel-include:: include/uapi/linux/media.h
10+ :generate-cross-refs:
11+ :exception-file: media.h.rst.exceptions
Documentation/userspace-api/media/mediactl/media.h.rst.exceptionsrenamed from Documentation/userspace-api/media/media.h.rst.exceptions+0−0

File renamed without changes.

Documentation/userspace-api/media/rc/lirc-header.rst+3−1
@@ -6,5 +6,7 @@ · 5 unmodified lines
66 LIRC Header File
77 ****************
88
9−.. kernel-include:: $BUILDDIR/lirc.h.rst
9+.. kernel-include:: include/uapi/linux/lirc.h
10+ :generate-cross-refs:
11+ :exception-file: lirc.h.rst.exceptions
1012
Documentation/userspace-api/media/rc/lirc.h.rst.exceptionsrenamed from Documentation/userspace-api/media/lirc.h.rst.exceptions+0−0

File renamed without changes.

Documentation/userspace-api/media/v4l/videodev.rst+3−1
@@ -6,4 +6,6 @@ · 5 unmodified lines
66 Video For Linux Two Header File
77 *******************************
88
9−.. kernel-include:: $BUILDDIR/videodev2.h.rst
9+.. kernel-include:: include/uapi/linux/videodev2.h
10+ :generate-cross-refs:
11+ :exception-file: videodev2.h.rst.exceptions
Documentation/userspace-api/media/v4l/videodev2.h.rst.exceptionsrenamed from Documentation/userspace-api/media/videodev2.h.rst.exceptions+0−0

File renamed without changes.

Documentation/virt/kvm/review-checklist.rst+1−1
@@ -98,7 +98,7 @@ New APIs · 97 unmodified lines
9898 It is important to demonstrate your use case. This can be as simple as
9999 explaining that the feature is already in use on bare metal, or it can be
100100 a proof-of-concept implementation in userspace. The latter need not be
101− open source, though that is of course preferrable for easier testing.
101+ open source, though that is of course preferable for easier testing.
102102 Selftests should test corner cases of the APIs, and should also cover
103103 basic host and guest operation if no open source VMM uses the feature.
104104
Documentation/w1/masters/ds2482.rst+1−1
@@ -22,7 +22,7 @@ Description · 21 unmodified lines
2222 -----------
2323
2424 The Maxim/Dallas Semiconductor DS2482 is a I2C device that provides
25−one (DS2482-100) or eight (DS2482-800) 1-wire busses.
25+one (DS2482-100) or eight (DS2482-800) 1-wire buses.
2626
2727
2828 General Remarks
Documentation/w1/masters/index.rst+1−1
@@ -1,4 +1,4 @@
1−. SPDX-License-Identifier: GPL-2.0
1+.. SPDX-License-Identifier: GPL-2.0
22
33 =====================
44 1-wire Master Drivers
Documentation/w1/slaves/index.rst+1−1
@@ -1,4 +1,4 @@
1−. SPDX-License-Identifier: GPL-2.0
1+.. SPDX-License-Identifier: GPL-2.0
22
33 ====================
44 1-wire Slave Drivers
MAINTAINERS+3−0
@@ -7384,11 +7384,13 @@ P: Documentation/doc-guide/maintainer-profile.rst · 7383 unmodified lines
73847384 T: git git://git.lwn.net/linux.git docs-next
73857385 F: Documentation/
73867386 F: scripts/check-variable-fonts.sh
7387+F: scripts/checktransupdate.py
73877388 F: scripts/documentation-file-ref-check
73887389 F: scripts/get_abi.py
73897390 F: scripts/kernel-doc*
73907391 F: scripts/lib/abi/*
73917392 F: scripts/lib/kdoc/*
7393+F: tools/docs/*
73927394 F: tools/net/ynl/pyynl/lib/doc_generator.py
73937395 F: scripts/sphinx-pre-install
73947396 X: Documentation/ABI/
@@ -14323,6 +14325,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/rcu/linux.git rcu/dev · 6928 unmodified lines
1432314325 F: Documentation/atomic_bitops.txt
1432414326 F: Documentation/atomic_t.txt
1432514327 F: Documentation/core-api/refcount-vs-atomic.rst
14328+F: Documentation/dev-tools/lkmm/
1432614329 F: Documentation/litmus-tests/
1432714330 F: Documentation/memory-barriers.txt
1432814331 F: tools/memory-model/
Makefile+3−2
@@ -1797,8 +1797,9 @@ $(help-board-dirs): help-%: · 1796 unmodified lines
17971797
17981798 # Documentation targets
17991799 # ---------------------------------------------------------------------------
1800−DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \
1801− linkcheckdocs dochelp refcheckdocs texinfodocs infodocs
1800+DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs htmldocs-redirects \
1801+ epubdocs cleandocs linkcheckdocs dochelp refcheckdocs \
1802+ texinfodocs infodocs
18021803 PHONY += $(DOC_TARGETS)
18031804 $(DOC_TARGETS):
18041805 $(Q)$(MAKE) $(build)=Documentation $@
fs/btrfs/tree-log.c+1−1
@@ -5829,7 +5829,7 @@ struct btrfs_dir_list { · 5828 unmodified lines
58295829 * See process_dir_items_leaf() for details about why it is needed.
58305830 * This is a recursive operation - if an existing dentry corresponds to a
58315831 * directory, that directory's new entries are logged too (same behaviour as
5832− * ext3/4, xfs, f2fs, reiserfs, nilfs2). Note that when logging the inodes
5832+ * ext3/4, xfs, f2fs, nilfs2). Note that when logging the inodes
58335833 * the dentries point to we do not acquire their VFS lock, otherwise lockdep
58345834 * complains about the following circular lock dependency / possible deadlock:
58355835 *
scripts/kernel-doc.py+24−10
@@ -2,8 +2,17 @@ · 1 unmodified line
22 # SPDX-License-Identifier: GPL-2.0
33 # Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>.
44 #
5−# pylint: disable=C0103,R0915
6−#
5+# pylint: disable=C0103,R0912,R0914,R0915
6+
7+# NOTE: While kernel-doc requires at least version 3.6 to run, the
8+# command line should work with Python 3.2+ (tested with 3.4).
9+# The rationale is that it shall fail gracefully during Kernel
10+# compilation with older Kernel versions. Due to that:
11+# - encoding line is needed here;
12+# - no f-strings can be used on this file.
13+# - the libraries that require newer versions can only be included
14+# after Python version is checked.
15+
716 # Converted from the kernel-doc script originally written in Perl
817 # under GPLv2, copyrighted since 1998 by the following authors:
918 #
@@ -107,9 +116,6 @@ SRC_DIR = os.path.dirname(os.path.realpath(__file__)) · 97 unmodified lines
107116
108117 sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR))
109118
110−from kdoc_files import KernelFiles # pylint: disable=C0413
111−from kdoc_output import RestFormat, ManFormat # pylint: disable=C0413
112−
113119 DESC = """
114120 Read C language source or header FILEs, extract embedded documentation comments,
115121 and print formatted documentation to standard output.
@@ -273,14 +279,22 @@ def main(): · 157 unmodified lines
273279
274280 python_ver = sys.version_info[:2]
275281 if python_ver < (3,6):
276− logger.warning("Python 3.6 or later is required by kernel-doc")
282+ # Depending on Kernel configuration, kernel-doc --none is called at
283+ # build time. As we don't want to break compilation due to the
284+ # usage of an old Python version, return 0 here.
285+ if args.none:
286+ logger.error("Python 3.6 or later is required by kernel-doc. skipping checks")
287+ sys.exit(0)
277288
278− # Return 0 here to avoid breaking compilation
279− sys.exit(0)
289+ sys.exit("Python 3.6 or later is required by kernel-doc. Aborting.")
280290
281291 if python_ver < (3,7):
282292 logger.warning("Python 3.7 or later is required for correct results")
283293
294+ # Import kernel-doc libraries only after checking Python version
295+ from kdoc_files import KernelFiles # pylint: disable=C0415
296+ from kdoc_output import RestFormat, ManFormat # pylint: disable=C0415
297+
284298 if args.man:
285299 out_style = ManFormat(modulename=args.modulename)
286300 elif args.none:
@@ -308,11 +322,11 @@ def main(): · 21 unmodified lines
308322 sys.exit(0)
309323
310324 if args.werror:
311− print(f"{error_count} warnings as errors")
325+ print("%s warnings as errors" % error_count) # pylint: disable=C0209
312326 sys.exit(error_count)
313327
314328 if args.verbose:
315− print(f"{error_count} errors")
329+ print("%s errors" % error_count) # pylint: disable=C0209
316330
317331 if args.none:
318332 sys.exit(0)
scripts/lib/kdoc/kdoc_parser.py+414−434
@@ -46,7 +46,7 @@ doc_decl = doc_com + KernRe(r'(\w+)', cache=False) · 45 unmodified lines
4646 known_section_names = 'description|context|returns?|notes?|examples?'
4747 known_sections = KernRe(known_section_names, flags = re.I)
4848 doc_sect = doc_com + \
49− KernRe(r'\s*(\@[.\w]+|\@\.\.\.|' + known_section_names + r')\s*:([^:].*)?$',
49+ KernRe(r'\s*(@[.\w]+|@\.\.\.|' + known_section_names + r')\s*:([^:].*)?$',
5050 flags=re.I, cache=False)
5151
5252 doc_content = doc_com_body + KernRe(r'(.*)', cache=False)
@@ -54,13 +54,11 @@ doc_inline_start = KernRe(r'^\s*/\*\*\s*$', cache=False) · 1 unmodified line
5454 doc_inline_sect = KernRe(r'\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)', cache=False)
5555 doc_inline_end = KernRe(r'^\s*\*/\s*$', cache=False)
5656 doc_inline_oneline = KernRe(r'^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$', cache=False)
57−attribute = KernRe(r"__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)",
58− flags=re.I | re.S, cache=False)
5957
6058 export_symbol = KernRe(r'^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*', cache=False)
6159 export_symbol_ns = KernRe(r'^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,\s*"\S+"\)\s*', cache=False)
6260
63−type_param = KernRe(r"\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
61+type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
6462
6563 #
6664 # Tests for the beginning of a kerneldoc block in its various forms.
@@ -74,6 +72,133 @@ doc_begin_func = KernRe(str(doc_com) + # initial " * ' · 7 unmodified lines
7472 r'(?:[-:].*)?$', # description (not captured)
7573 cache = False)
7674
75+#
76+# Here begins a long set of transformations to turn structure member prefixes
77+# and macro invocations into something we can parse and generate kdoc for.
78+#
79+struct_args_pattern = r'([^,)]+)'
80+
81+struct_xforms = [
82+ # Strip attributes
83+ (KernRe(r"__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)", flags=re.I | re.S, cache=False), ' '),
84+ (KernRe(r'\s*__aligned\s*\([^;]*\)', re.S), ' '),
85+ (KernRe(r'\s*__counted_by\s*\([^;]*\)', re.S), ' '),
86+ (KernRe(r'\s*__counted_by_(le|be)\s*\([^;]*\)', re.S), ' '),
87+ (KernRe(r'\s*__packed\s*', re.S), ' '),
88+ (KernRe(r'\s*CRYPTO_MINALIGN_ATTR', 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 parenthesis 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 limiter 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"__deprecated +"), ""),
180+ (KernRe(r"__flatten +"), ""),
181+ (KernRe(r"__meminit +"), ""),
182+ (KernRe(r"__must_check +"), ""),
183+ (KernRe(r"__weak +"), ""),
184+ (KernRe(r"__sched +"), ""),
185+ (KernRe(r"_noprof"), ""),
186+ (KernRe(r"__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +"), ""),
187+ (KernRe(r"__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +"), ""),
188+ (KernRe(r"__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +"), ""),
189+ (KernRe(r"DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)"), r"\1, \2"),
190+ (KernRe(r"__attribute_const__ +"), ""),
191+ (KernRe(r"__attribute__\s*\(\((?:[\w\s]+(?:\([^)]*\))?\s*,?)+\)\)\s+"), ""),
192+]
193+
194+#
195+# Apply a set of transforms to a block of text.
196+#
197+def apply_transforms(xforms, text):
198+ for search, subst in xforms:
199+ text = search.sub(subst, text)
200+ return text
201+
77202 #
78203 # A little helper to get rid of excess white space
79204 #
@@ -81,6 +206,21 @@ multi_space = KernRe(r'\s\s+') · 1 unmodified line
81206 def trim_whitespace(s):
82207 return multi_space.sub(' ', s.strip())
83208
209+#
210+# Remove struct/enum members that have been marked "private".
211+#
212+def trim_private_members(text):
213+ #
214+ # First look for a "public:" block that ends a private region, then
215+ # handle the "private until the end" case.
216+ #
217+ text = KernRe(r'/\*\s*private:.*?/\*\s*public:.*?\*/', flags=re.S).sub('', text)
218+ text = KernRe(r'/\*\s*private:.*', flags=re.S).sub('', text)
219+ #
220+ # We needed the comments to do the above, but now we can take them out.
221+ #
222+ return KernRe(r'\s*/\*.*?\*/\s*', flags=re.S).sub('', text).strip()
223+
84224 class state:
85225 """
86226 State machine enums
@@ -318,36 +458,26 @@ class KernelDoc: · 231 unmodified lines
318458
319459 param = KernRe(r'[\[\)].*').sub('', param, count=1)
320460
321− if dtype == "" and param.endswith("..."):
322− if KernRe(r'\w\.\.\.$').search(param):
323− # For named variable parameters of the form `x...`,
324− # remove the dots
325− param = param[:-3]
326− else:
327− # Handles unnamed variable parameters
328− param = "..."
329−
330− if param not in self.entry.parameterdescs or \
331− not self.entry.parameterdescs[param]:
332−
333− self.entry.parameterdescs[param] = "variable arguments"
334−
335− elif dtype == "" and (not param or param == "void"):
336− param = "void"
337− self.entry.parameterdescs[param] = "no arguments"
338−
339− elif dtype == "" and param in ["struct", "union"]:
340− # Handle unnamed (anonymous) union or struct
341− dtype = param
342− param = "{unnamed_" + param + "}"
343− self.entry.parameterdescs[param] = "anonymous\n"
344− self.entry.anon_struct_union = True
345−
346− # Handle cache group enforcing variables: they do not need
347− # to be described in header files
348− elif "__cacheline_group" in param:
349− # Ignore __cacheline_group_begin and __cacheline_group_end
350− return
461+ #
462+ # Look at various "anonymous type" cases.
463+ #
464+ if dtype == '':
465+ if param.endswith("..."):
466+ if len(param) > 3: # there is a name provided, use that
467+ param = param[:-3]
468+ if not self.entry.parameterdescs.get(param):
469+ self.entry.parameterdescs[param] = "variable arguments"
470+
471+ elif (not param) or param == "void":
472+ param = "void"
473+ self.entry.parameterdescs[param] = "no arguments"
474+
475+ elif param in ["struct", "union"]:
476+ # Handle unnamed (anonymous) union or struct
477+ dtype = param
478+ param = "{unnamed_" + param + "}"
479+ self.entry.parameterdescs[param] = "anonymous\n"
480+ self.entry.anon_struct_union = True
351481
352482 # Warn if parameter has no description
353483 # (but ignore ones starting with # as these are not parameters
@@ -389,9 +519,6 @@ class KernelDoc: · 35 unmodified lines
389519 args = arg_expr.sub(r"\1#", args)
390520
391521 for arg in args.split(splitter):
392− # Strip comments
393− arg = KernRe(r'\/\*.*\*\/').sub('', arg)
394−
395522 # Ignore argument attributes
396523 arg = KernRe(r'\sPOS0?\s').sub(' ', arg)
397524
@@ -407,81 +534,76 @@ class KernelDoc: · 9 unmodified lines
407534 # Treat preprocessor directive as a typeless variable
408535 self.push_parameter(ln, decl_type, arg, "",
409536 "", declaration_name)
410−
537+ #
538+ # The pointer-to-function case.
539+ #
411540 elif KernRe(r'\(.+\)\s*\(').search(arg):
412− # Pointer-to-function
413−
414541 arg = arg.replace('#', ',')
415−
416− r = KernRe(r'[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)')
542+ r = KernRe(r'[^\(]+\(\*?\s*' # Everything up to "(*"
543+ r'([\w\[\].]*)' # Capture the name and possible [array]
544+ r'\s*\)') # Make sure the trailing ")" is there
417545 if r.match(arg):
418546 param = r.group(1)
419547 else:
420548 self.emit_msg(ln, f"Invalid param: {arg}")
421549 param = arg
422−
423− dtype = KernRe(r'([^\(]+\(\*?)\s*' + re.escape(param)).sub(r'\1', arg)
424− self.push_parameter(ln, decl_type, param, dtype,
425− arg, declaration_name)
426−
550+ dtype = arg.replace(param, '')
551+ self.push_parameter(ln, decl_type, param, dtype, arg, declaration_name)
552+ #
553+ # The array-of-pointers case. Dig the parameter name out from the middle
554+ # of the declaration.
555+ #
427556 elif KernRe(r'\(.+\)\s*\[').search(arg):
428− # Array-of-pointers
429−
430− arg = arg.replace('#', ',')
431− r = KernRe(r'[^\(]+\(\s*\*\s*([\w\[\]\.]*?)\s*(\s*\[\s*[\w]+\s*\]\s*)*\)')
557+ r = KernRe(r'[^\(]+\(\s*\*\s*' # Up to "(" and maybe "*"
558+ r'([\w.]*?)' # The actual pointer name
559+ r'\s*(\[\s*\w+\s*\]\s*)*\)') # The [array portion]
432560 if r.match(arg):
433561 param = r.group(1)
434562 else:
435563 self.emit_msg(ln, f"Invalid param: {arg}")
436564 param = arg
437−
438− dtype = KernRe(r'([^\(]+\(\*?)\s*' + re.escape(param)).sub(r'\1', arg)
439−
440− self.push_parameter(ln, decl_type, param, dtype,
441− arg, declaration_name)
442−
565+ dtype = arg.replace(param, '')
566+ self.push_parameter(ln, decl_type, param, dtype, arg, declaration_name)
443567 elif arg:
568+ #
569+ # Clean up extraneous spaces and split the string at commas; the first
570+ # element of the resulting list will also include the type information.
571+ #
444572 arg = KernRe(r'\s*:\s*').sub(":", arg)
445573 arg = KernRe(r'\s*\[').sub('[', arg)
446−
447574 args = KernRe(r'\s*,\s*').split(arg)
448− if args[0] and '*' in args[0]:
449− args[0] = re.sub(r'(\*+)\s*', r' \1', args[0])
450−
451− first_arg = []
452− r = KernRe(r'^(.*\s+)(.*?\[.*\].*)$')
453− if args[0] and r.match(args[0]):
454− args.pop(0)
455− first_arg.extend(r.group(1))
456− first_arg.append(r.group(2))
575+ args[0] = re.sub(r'(\*+)\s*', r' \1', args[0])
576+ #
577+ # args[0] has a string of "type a". If "a" includes an [array]
578+ # declaration, we want to not be fooled by any white space inside
579+ # the brackets, so detect and handle that case specially.
580+ #
581+ r = KernRe(r'^([^[\]]*\s+)(.*)$')
582+ if r.match(args[0]):
583+ args[0] = r.group(2)
584+ dtype = r.group(1)
457585 else:
458− first_arg = KernRe(r'\s+').split(args.pop(0))
459−
460− args.insert(0, first_arg.pop())
461− dtype = ' '.join(first_arg)
586+ # No space in args[0]; this seems wrong but preserves previous behavior
587+ dtype = ''
462588
589+ bitfield_re = KernRe(r'(.*?):(\w+)')
463590 for param in args:
464− if KernRe(r'^(\*+)\s*(.*)').match(param):
465− r = KernRe(r'^(\*+)\s*(.*)')
466− if not r.match(param):
467− self.emit_msg(ln, f"Invalid param: {param}")
468− continue
469−
470− param = r.group(1)
471−
591+ #
592+ # For pointers, shift the star(s) from the variable name to the
593+ # type declaration.
594+ #
595+ r = KernRe(r'^(\*+)\s*(.*)')
596+ if r.match(param):
472597 self.push_parameter(ln, decl_type, r.group(2),
473598 f"{dtype} {r.group(1)}",
474599 arg, declaration_name)
475−
476− elif KernRe(r'(.*?):(\w+)').search(param):
477− r = KernRe(r'(.*?):(\w+)')
478− if not r.match(param):
479− self.emit_msg(ln, f"Invalid param: {param}")
480− continue
481−
600+ #
601+ # Perform a similar shift for bitfields.
602+ #
603+ elif bitfield_re.search(param):
482604 if dtype != "": # Skip unnamed bit-fields
483− self.push_parameter(ln, decl_type, r.group(1),
484− f"{dtype}:{r.group(2)}",
605+ self.push_parameter(ln, decl_type, bitfield_re.group(1),
606+ f"{dtype}:{bitfield_re.group(2)}",
485607 arg, declaration_name)
486608 else:
487609 self.push_parameter(ln, decl_type, param, dtype,
@@ -520,13 +642,11 @@ class KernelDoc: · 32 unmodified lines
520642 self.emit_msg(ln,
521643 f"No description found for return value of '{declaration_name}'")
522644
523− def dump_struct(self, ln, proto):
524− """
525− Store an entry for an struct or union
526− """
527−
645+ #
646+ # Split apart a structure prototype; returns (struct|union, name, members) or None
647+ #
648+ def split_struct_proto(self, proto):
528649 type_pattern = r'(struct|union)'
529−
530650 qualifiers = [
531651 "__attribute__",
532652 "__packed",
@@ -534,288 +654,202 @@ class KernelDoc: · 1 unmodified line
534654 "____cacheline_aligned_in_smp",
535655 "____cacheline_aligned",
536656 ]
537−
538657 definition_body = r'\{(.*)\}\s*' + "(?:" + '|'.join(qualifiers) + ")?"
539− struct_members = KernRe(type_pattern + r'([^\{\};]+)(\{)([^\{\}]*)(\})([^\{\}\;]*)(\;)')
540−
541− # Extract struct/union definition
542− members = None
543− declaration_name = None
544− decl_type = None
545658
546659 r = KernRe(type_pattern + r'\s+(\w+)\s*' + definition_body)
547660 if r.search(proto):
548− decl_type = r.group(1)
549− declaration_name = r.group(2)
550− members = r.group(3)
661+ return (r.group(1), r.group(2), r.group(3))
551662 else:
552663 r = KernRe(r'typedef\s+' + type_pattern + r'\s*' + definition_body + r'\s*(\w+)\s*;')
553−
554664 if r.search(proto):
555− decl_type = r.group(1)
556− declaration_name = r.group(3)
557− members = r.group(2)
558−
559− if not members:
560− self.emit_msg(ln, f"{proto} error: Cannot parse struct or union!")
561− return
562−
563− if self.entry.identifier != declaration_name:
564− self.emit_msg(ln,
565− f"expecting prototype for {decl_type} {self.entry.identifier}. Prototype was for {decl_type} {declaration_name} instead\n")
566− return
567−
568− args_pattern = r'([^,)]+)'
569−
570− sub_prefixes = [
571− (KernRe(r'\/\*\s*private:.*?\/\*\s*public:.*?\*\/', re.S | re.I), ''),
572− (KernRe(r'\/\*\s*private:.*', re.S | re.I), ''),
573−
574− # Strip comments
575− (KernRe(r'\/\*.*?\*\/', re.S), ''),
576−
577− # Strip attributes
578− (attribute, ' '),
579− (KernRe(r'\s*__aligned\s*\([^;]*\)', re.S), ' '),
580− (KernRe(r'\s*__counted_by\s*\([^;]*\)', re.S), ' '),
581− (KernRe(r'\s*__counted_by_(le|be)\s*\([^;]*\)', re.S), ' '),
582− (KernRe(r'\s*__packed\s*', re.S), ' '),
583− (KernRe(r'\s*CRYPTO_MINALIGN_ATTR', re.S), ' '),
584− (KernRe(r'\s*____cacheline_aligned_in_smp', re.S), ' '),
585− (KernRe(r'\s*____cacheline_aligned', re.S), ' '),
586−
587− # Unwrap struct_group macros based on this definition:
588− # __struct_group(TAG, NAME, ATTRS, MEMBERS...)
589− # which has variants like: struct_group(NAME, MEMBERS...)
590− # Only MEMBERS arguments require documentation.
591− #
592− # Parsing them happens on two steps:
593− #
594− # 1. drop struct group arguments that aren't at MEMBERS,
595− # storing them as STRUCT_GROUP(MEMBERS)
596− #
597− # 2. remove STRUCT_GROUP() ancillary macro.
598− #
599− # The original logic used to remove STRUCT_GROUP() using an
600− # advanced regex:
601− #
602− # \bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;
603− #
604− # with two patterns that are incompatible with
605− # Python re module, as it has:
606− #
607− # - a recursive pattern: (?1)
608− # - an atomic grouping: (?>...)
609− #
610− # I tried a simpler version: but it didn't work either:
611− # \bSTRUCT_GROUP\(([^\)]+)\)[^;]*;
612− #
613− # As it doesn't properly match the end parenthesis on some cases.
614− #
615− # So, a better solution was crafted: there's now a NestedMatch
616− # class that ensures that delimiters after a search are properly
617− # matched. So, the implementation to drop STRUCT_GROUP() will be
618− # handled in separate.
619−
620− (KernRe(r'\bstruct_group\s*\(([^,]*,)', re.S), r'STRUCT_GROUP('),
621− (KernRe(r'\bstruct_group_attr\s*\(([^,]*,){2}', re.S), r'STRUCT_GROUP('),
622− (KernRe(r'\bstruct_group_tagged\s*\(([^,]*),([^,]*),', re.S), r'struct \1 \2; STRUCT_GROUP('),
623− (KernRe(r'\b__struct_group\s*\(([^,]*,){3}', re.S), r'STRUCT_GROUP('),
624−
625− # Replace macros
626− #
627− # TODO: use NestedMatch for FOO($1, $2, ...) matches
628− #
629− # it is better to also move those to the NestedMatch logic,
630− # to ensure that parenthesis will be properly matched.
631−
632− (KernRe(r'__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)', re.S), r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'),
633− (KernRe(r'DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)', re.S), r'DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)'),
634− (KernRe(r'DECLARE_BITMAP\s*\(' + args_pattern + r',\s*' + args_pattern + r'\)', re.S), r'unsigned long \1[BITS_TO_LONGS(\2)]'),
635− (KernRe(r'DECLARE_HASHTABLE\s*\(' + args_pattern + r',\s*' + args_pattern + r'\)', re.S), r'unsigned long \1[1 << ((\2) - 1)]'),
636− (KernRe(r'DECLARE_KFIFO\s*\(' + args_pattern + r',\s*' + args_pattern + r',\s*' + args_pattern + r'\)', re.S), r'\2 *\1'),
637− (KernRe(r'DECLARE_KFIFO_PTR\s*\(' + args_pattern + r',\s*' + args_pattern + r'\)', re.S), r'\2 *\1'),
638− (KernRe(r'(?:__)?DECLARE_FLEX_ARRAY\s*\(' + args_pattern + r',\s*' + args_pattern + r'\)', re.S), r'\1 \2[]'),
639− (KernRe(r'DEFINE_DMA_UNMAP_ADDR\s*\(' + args_pattern + r'\)', re.S), r'dma_addr_t \1'),
640− (KernRe(r'DEFINE_DMA_UNMAP_LEN\s*\(' + args_pattern + r'\)', re.S), r'__u32 \1'),
641− (KernRe(r'VIRTIO_DECLARE_FEATURES\s*\(' + args_pattern + r'\)', re.S), r'u64 \1; u64 \1_array[VIRTIO_FEATURES_DWORDS]'),
642− ]
643−
644− # Regexes here are guaranteed to have the end limiter matching
645− # the start delimiter. Yet, right now, only one replace group
646− # is allowed.
647−
648− sub_nested_prefixes = [
649− (re.compile(r'\bSTRUCT_GROUP\('), r'\1'),
650− ]
651−
652− for search, sub in sub_prefixes:
653− members = search.sub(sub, members)
654−
655− nested = NestedMatch()
656−
657− for search, sub in sub_nested_prefixes:
658− members = nested.sub(search, sub, members)
659−
660− # Keeps the original declaration as-is
661− declaration = members
662−
663− # Split nested struct/union elements
664− #
665− # This loop was simpler at the original kernel-doc perl version, as
666− # while ($members =~ m/$struct_members/) { ... }
667− # reads 'members' string on each interaction.
668− #
669− # Python behavior is different: it parses 'members' only once,
670− # creating a list of tuples from the first interaction.
665+ return (r.group(1), r.group(3), r.group(2))
666+ return None
667+ #
668+ # Rewrite the members of a structure or union for easier formatting later on.
669+ # Among other things, this function will turn a member like:
670+ #
671+ # struct { inner_members; } foo;
672+ #
673+ # into:
674+ #
675+ # struct foo; inner_members;
676+ #
677+ def rewrite_struct_members(self, members):
671678 #
672− # On other words, this won't get nested structs.
679+ # Process struct/union members from the most deeply nested outward. The
680+ # trick is in the ^{ below - it prevents a match of an outer struct/union
681+ # until the inner one has been munged (removing the "{" in the process).
673682 #
674− # So, we need to have an extra loop on Python to override such
675− # re limitation.
676−
677− while True:
678− tuples = struct_members.findall(members)
679− if not tuples:
680− break
681−
683+ struct_members = KernRe(r'(struct|union)' # 0: declaration type
684+ r'([^\{\};]+)' # 1: possible name
685+ r'(\{)'
686+ r'([^\{\}]*)' # 3: Contents of declaration
687+ r'(\})'
688+ r'([^\{\};]*)(;)') # 5: Remaining stuff after declaration
689+ tuples = struct_members.findall(members)
690+ while tuples:
682691 for t in tuples:
683692 newmember = ""
684− maintype = t[0]
685− s_ids = t[5]
686− content = t[3]
687−
688− oldmember = "".join(t)
689−
690− for s_id in s_ids.split(','):
693+ oldmember = "".join(t) # Reconstruct the original formatting
694+ dtype, name, lbr, content, rbr, rest, semi = t
695+ #
696+ # Pass through each field name, normalizing the form and formatting.
697+ #
698+ for s_id in rest.split(','):
691699 s_id = s_id.strip()
692−
693− newmember += f"{maintype} {s_id}; "
700+ newmember += f"{dtype} {s_id}; "
701+ #
702+ # Remove bitfield/array/pointer info, getting the bare name.
703+ #
694704 s_id = KernRe(r'[:\[].*').sub('', s_id)
695705 s_id = KernRe(r'^\s*\**(\S+)\s*').sub(r'\1', s_id)
696−
706+ #
707+ # Pass through the members of this inner structure/union.
708+ #
697709 for arg in content.split(';'):
698710 arg = arg.strip()
699−
700− if not arg:
701− continue
702−
703− r = KernRe(r'^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)')
711+ #
712+ # Look for (type)(*name)(args) - pointer to function
713+ #
714+ r = KernRe(r'^([^\(]+\(\*?\s*)([\w.]*)(\s*\).*)')
704715 if r.match(arg):
716+ dtype, name, extra = r.group(1), r.group(2), r.group(3)
705717 # Pointer-to-function
706− dtype = r.group(1)
707− name = r.group(2)
708− extra = r.group(3)
709−
710− if not name:
711− continue
712−
713718 if not s_id:
714719 # Anonymous struct/union
715720 newmember += f"{dtype}{name}{extra}; "
716721 else:
717722 newmember += f"{dtype}{s_id}.{name}{extra}; "
718−
723+ #
724+ # Otherwise a non-function member.
725+ #
719726 else:
720− arg = arg.strip()
721− # Handle bitmaps
727+ #
728+ # Remove bitmap and array portions and spaces around commas
729+ #
722730 arg = KernRe(r':\s*\d+\s*').sub('', arg)
723−
724− # Handle arrays
725731 arg = KernRe(r'\[.*\]').sub('', arg)
726−
727− # Handle multiple IDs
728732 arg = KernRe(r'\s*,\s*').sub(',', arg)
729−
733+ #
734+ # Look for a normal decl - "type name[,name...]"
735+ #
730736 r = KernRe(r'(.*)\s+([\S+,]+)')
731−
732737 if r.search(arg):
733− dtype = r.group(1)
734− names = r.group(2)
738+ for name in r.group(2).split(','):
739+ name = KernRe(r'^\s*\**(\S+)\s*').sub(r'\1', name)
740+ if not s_id:
741+ # Anonymous struct/union
742+ newmember += f"{r.group(1)} {name}; "
743+ else:
744+ newmember += f"{r.group(1)} {s_id}.{name}; "
735745 else:
736746 newmember += f"{arg}; "
737− continue
738−
739− for name in names.split(','):
740− name = KernRe(r'^\s*\**(\S+)\s*').sub(r'\1', name).strip()
741−
742− if not name:
743− continue
744−
745− if not s_id:
746− # Anonymous struct/union
747− newmember += f"{dtype} {name}; "
748− else:
749− newmember += f"{dtype} {s_id}.{name}; "
750−
747+ #
748+ # At the end of the s_id loop, replace the original declaration with
749+ # the munged version.
750+ #
751751 members = members.replace(oldmember, newmember)
752+ #
753+ # End of the tuple loop - search again and see if there are outer members
754+ # that now turn up.
755+ #
756+ tuples = struct_members.findall(members)
757+ return members
752758
753− # Ignore other nested elements, like enums
754− members = re.sub(r'(\{[^\{\}]*\})', '', members)
755−
756− self.create_parameter_list(ln, decl_type, members, ';',
757− declaration_name)
758− self.check_sections(ln, declaration_name, decl_type)
759−
760− # Adjust declaration for better display
759+ #
760+ # Format the struct declaration into a standard form for inclusion in the
761+ # resulting docs.
762+ #
763+ def format_struct_decl(self, declaration):
764+ #
765+ # Insert newlines, get rid of extra spaces.
766+ #
761767 declaration = KernRe(r'([\{;])').sub(r'\1\n', declaration)
762768 declaration = KernRe(r'\}\s+;').sub('};', declaration)
763−
764− # Better handle inlined enums
765− while True:
766− r = KernRe(r'(enum\s+\{[^\}]+),([^\n])')
767− if not r.search(declaration):
768− break
769−
769+ #
770+ # Format inline enums with each member on its own line.
771+ #
772+ r = KernRe(r'(enum\s+\{[^\}]+),([^\n])')
773+ while r.search(declaration):
770774 declaration = r.sub(r'\1,\n\2', declaration)
771−
775+ #
776+ # Now go through and supply the right number of tabs
777+ # for each line.
778+ #
772779 def_args = declaration.split('\n')
773780 level = 1
774781 declaration = ""
775782 for clause in def_args:
783+ clause = KernRe(r'\s+').sub(' ', clause.strip(), count=1)
784+ if clause:
785+ if '}' in clause and level > 1:
786+ level -= 1
787+ if not clause.startswith('#'):
788+ declaration += "\t" * level
789+ declaration += "\t" + clause + "\n"
790+ if "{" in clause and "}" not in clause:
791+ level += 1
792+ return declaration
776793
777− clause = clause.strip()
778− clause = KernRe(r'\s+').sub(' ', clause, count=1)
779−
780− if not clause:
781− continue
782−
783− if '}' in clause and level > 1:
784− level -= 1
785794
786− if not KernRe(r'^\s*#').match(clause):
787− declaration += "\t" * level
795+ def dump_struct(self, ln, proto):
796+ """
797+ Store an entry for an struct or union
798+ """
799+ #
800+ # Do the basic parse to get the pieces of the declaration.
801+ #
802+ struct_parts = self.split_struct_proto(proto)
803+ if not struct_parts:
804+ self.emit_msg(ln, f"{proto} error: Cannot parse struct or union!")
805+ return
806+ decl_type, declaration_name, members = struct_parts
788807
789− declaration += "\t" + clause + "\n"
790− if "{" in clause and "}" not in clause:
791− level += 1
808+ if self.entry.identifier != declaration_name:
809+ self.emit_msg(ln, f"expecting prototype for {decl_type} {self.entry.identifier}. "
810+ f"Prototype was for {decl_type} {declaration_name} instead\n")
811+ return
812+ #
813+ # Go through the list of members applying all of our transformations.
814+ #
815+ members = trim_private_members(members)
816+ members = apply_transforms(struct_xforms, members)
792817
818+ nested = NestedMatch()
819+ for search, sub in struct_nested_prefixes:
820+ members = nested.sub(search, sub, members)
821+ #
822+ # Deal with embedded struct and union members, and drop enums entirely.
823+ #
824+ declaration = members
825+ members = self.rewrite_struct_members(members)
826+ members = re.sub(r'(\{[^\{\}]*\})', '', members)
827+ #
828+ # Output the result and we are done.
829+ #
830+ self.create_parameter_list(ln, decl_type, members, ';',
831+ declaration_name)
832+ self.check_sections(ln, declaration_name, decl_type)
793833 self.output_declaration(decl_type, declaration_name,
794− definition=declaration,
834+ definition=self.format_struct_decl(declaration),
795835 purpose=self.entry.declaration_purpose)
796836
797837 def dump_enum(self, ln, proto):
798838 """
799839 Stores an enum inside self.entries array.
800840 """
801−
802− # Ignore members marked private
803− proto = KernRe(r'\/\*\s*private:.*?\/\*\s*public:.*?\*\/', flags=re.S).sub('', proto)
804− proto = KernRe(r'\/\*\s*private:.*}', flags=re.S).sub('}', proto)
805−
806− # Strip comments
807− proto = KernRe(r'\/\*.*?\*\/', flags=re.S).sub('', proto)
808−
809− # Strip #define macros inside enums
841+ #
842+ # Strip preprocessor directives. Note that this depends on the
843+ # trailing semicolon we added in process_proto_type().
844+ #
810845 proto = KernRe(r'#\s*((define|ifdef|if)\s+|endif)[^;]*;', flags=re.S).sub('', proto)
811−
812846 #
813847 # Parse out the name and members of the enum. Typedef form first.
814848 #
815849 r = KernRe(r'typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;')
816850 if r.search(proto):
817851 declaration_name = r.group(2)
818− members = r.group(1).rstrip()
852+ members = trim_private_members(r.group(1))
819853 #
820854 # Failing that, look for a straight enum
821855 #
@@ -823,7 +857,7 @@ class KernelDoc: · 1 unmodified line
823857 r = KernRe(r'enum\s+(\w*)\s*\{(.*)\}')
824858 if r.match(proto):
825859 declaration_name = r.group(1)
826− members = r.group(2).rstrip()
860+ members = trim_private_members(r.group(2))
827861 #
828862 # OK, this isn't going to work.
829863 #
@@ -892,62 +926,31 @@ class KernelDoc: · 62 unmodified lines
892926 Stores a function of function macro inside self.entries array.
893927 """
894928
895− func_macro = False
929+ found = func_macro = False
896930 return_type = ''
897931 decl_type = 'function'
898−
899− # Prefixes that would be removed
900− sub_prefixes = [
901− (r"^static +", "", 0),
902− (r"^extern +", "", 0),
903− (r"^asmlinkage +", "", 0),
904− (r"^inline +", "", 0),
905− (r"^__inline__ +", "", 0),
906− (r"^__inline +", "", 0),
907− (r"^__always_inline +", "", 0),
908− (r"^noinline +", "", 0),
909− (r"^__FORTIFY_INLINE +", "", 0),
910− (r"__init +", "", 0),
911− (r"__init_or_module +", "", 0),
912− (r"__deprecated +", "", 0),
913− (r"__flatten +", "", 0),
914− (r"__meminit +", "", 0),
915− (r"__must_check +", "", 0),
916− (r"__weak +", "", 0),
917− (r"__sched +", "", 0),
918− (r"_noprof", "", 0),
919− (r"__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +", "", 0),
920− (r"__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +", "", 0),
921− (r"__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +", "", 0),
922− (r"DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)", r"\1, \2", 0),
923− (r"__attribute_const__ +", "", 0),
924−
925− # It seems that Python support for re.X is broken:
926− # At least for me (Python 3.13), this didn't work
927−# (r"""
928−# __attribute__\s*\(\(
929−# (?:
930−# [\w\s]+ # attribute name
931−# (?:\([^)]*\))? # attribute arguments
932−# \s*,? # optional comma at the end
933−# )+
934−# \)\)\s+
935−# """, "", re.X),
936−
937− # So, remove whitespaces and comments from it
938− (r"__attribute__\s*\(\((?:[\w\s]+(?:\([^)]*\))?\s*,?)+\)\)\s+", "", 0),
939− ]
940−
941− for search, sub, flags in sub_prefixes:
942− prototype = KernRe(search, flags).sub(sub, prototype)
943−
944− # Macros are a special case, as they change the prototype format
932+ #
933+ # Apply the initial transformations.
934+ #
935+ prototype = apply_transforms(function_xforms, prototype)
936+ #
937+ # If we have a macro, remove the "#define" at the front.
938+ #
945939 new_proto = KernRe(r"^#\s*define\s+").sub("", prototype)
946940 if new_proto != prototype:
947− is_define_proto = True
948941 prototype = new_proto
949− else:
950− is_define_proto = False
942+ #
943+ # Dispense with the simple "#define A B" case here; the key
944+ # is the space after the name of the symbol being defined.
945+ # NOTE that the seemingly misnamed "func_macro" indicates a
946+ # macro *without* arguments.
947+ #
948+ r = KernRe(r'^(\w+)\s+')
949+ if r.search(prototype):
950+ return_type = ''
951+ declaration_name = r.group(1)
952+ func_macro = True
953+ found = True
951954
952955 # Yes, this truly is vile. We are looking for:
953956 # 1. Return type (may be nothing if we're looking at a macro)
@@ -965,91 +968,73 @@ class KernelDoc: · 11 unmodified lines
965968 # - atomic_set (macro)
966969 # - pci_match_device, __copy_to_user (long return type)
967970
968− name = r'[a-zA-Z0-9_~:]+'
969− prototype_end1 = r'[^\(]*'
970− prototype_end2 = r'[^\{]*'
971− prototype_end = fr'\(({prototype_end1}|{prototype_end2})\)'
972−
973− # Besides compiling, Perl qr{[\w\s]+} works as a non-capturing group.
974− # So, this needs to be mapped in Python with (?:...)? or (?:...)+
975−
971+ name = r'\w+'
976972 type1 = r'(?:[\w\s]+)?'
977973 type2 = r'(?:[\w\s]+\*+)+'
978−
979− found = False
980−
981− if is_define_proto:
982− r = KernRe(r'^()(' + name + r')\s+')
983−
984− if r.search(prototype):
985− return_type = ''
986− declaration_name = r.group(2)
987− func_macro = True
988−
989− found = True
990−
974+ #
975+ # Attempt to match first on (args) with no internal parentheses; this
976+ # lets us easily filter out __acquires() and other post-args stuff. If
977+ # that fails, just grab the rest of the line to the last closing
978+ # parenthesis.
979+ #
980+ proto_args = r'\(([^\(]*|.*)\)'
981+ #
982+ # (Except for the simple macro case) attempt to split up the prototype
983+ # in the various ways we understand.
984+ #
991985 if not found:
992986 patterns = [
993− rf'^()({name})\s*{prototype_end}',
994− rf'^({type1})\s+({name})\s*{prototype_end}',
995− rf'^({type2})\s*({name})\s*{prototype_end}',
987+ rf'^()({name})\s*{proto_args}',
988+ rf'^({type1})\s+({name})\s*{proto_args}',
989+ rf'^({type2})\s*({name})\s*{proto_args}',
996990 ]
997991
998992 for p in patterns:
999993 r = KernRe(p)
1000−
1001994 if r.match(prototype):
1002−
1003995 return_type = r.group(1)
1004996 declaration_name = r.group(2)
1005997 args = r.group(3)
1006−
1007998 self.create_parameter_list(ln, decl_type, args, ',',
1008999 declaration_name)
1009−
10101000 found = True
10111001 break
1002+ #
1003+ # Parsing done; make sure that things are as we expect.
1004+ #
10121005 if not found:
10131006 self.emit_msg(ln,
10141007 f"cannot understand function prototype: '{prototype}'")
10151008 return
1016−
10171009 if self.entry.identifier != declaration_name:
1018− self.emit_msg(ln,
1019− f"expecting prototype for {self.entry.identifier}(). Prototype was for {declaration_name}() instead")
1010+ self.emit_msg(ln, f"expecting prototype for {self.entry.identifier}(). "
1011+ f"Prototype was for {declaration_name}() instead")
10201012 return
1021−
10221013 self.check_sections(ln, declaration_name, "function")
1023−
10241014 self.check_return_section(ln, declaration_name, return_type)
1015+ #
1016+ # Store the result.
1017+ #
1018+ self.output_declaration(decl_type, declaration_name,
1019+ typedef=('typedef' in return_type),
1020+ functiontype=return_type,
1021+ purpose=self.entry.declaration_purpose,
1022+ func_macro=func_macro)
10251023
1026− if 'typedef' in return_type:
1027− self.output_declaration(decl_type, declaration_name,
1028− typedef=True,
1029− functiontype=return_type,
1030− purpose=self.entry.declaration_purpose,
1031− func_macro=func_macro)
1032− else:
1033− self.output_declaration(decl_type, declaration_name,
1034− typedef=False,
1035− functiontype=return_type,
1036− purpose=self.entry.declaration_purpose,
1037− func_macro=func_macro)
10381024
10391025 def dump_typedef(self, ln, proto):
10401026 """
10411027 Stores a typedef inside self.entries array.
10421028 """
1043−
1044− typedef_type = r'((?:\s+[\w\*]+\b){0,7}\s+(?:\w+\b|\*+))\s*'
1029+ #
1030+ # We start by looking for function typedefs.
1031+ #
1032+ typedef_type = r'typedef((?:\s+[\w*]+\b){0,7}\s+(?:\w+\b|\*+))\s*'
10451033 typedef_ident = r'\*?\s*(\w\S+)\s*'
10461034 typedef_args = r'\s*\((.*)\);'
10471035
1048− typedef1 = KernRe(r'typedef' + typedef_type + r'\(' + typedef_ident + r'\)' + typedef_args)
1049− typedef2 = KernRe(r'typedef' + typedef_type + typedef_ident + typedef_args)
1050−
1051− # Strip comments
1052− proto = KernRe(r'/\*.*?\*/', flags=re.S).sub('', proto)
1036+ typedef1 = KernRe(typedef_type + r'\(' + typedef_ident + r'\)' + typedef_args)
1037+ typedef2 = KernRe(typedef_type + typedef_ident + typedef_args)
10531038
10541039 # Parse function typedef prototypes
10551040 for r in [typedef1, typedef2]:
@@ -1065,21 +1050,16 @@ class KernelDoc: · 9 unmodified lines
10651050 f"expecting prototype for typedef {self.entry.identifier}. Prototype was for typedef {declaration_name} instead\n")
10661051 return
10671052
1068− decl_type = 'function'
1069− self.create_parameter_list(ln, decl_type, args, ',', declaration_name)
1053+ self.create_parameter_list(ln, 'function', args, ',', declaration_name)
10701054
1071− self.output_declaration(decl_type, declaration_name,
1055+ self.output_declaration('function', declaration_name,
10721056 typedef=True,
10731057 functiontype=return_type,
10741058 purpose=self.entry.declaration_purpose)
10751059 return
1076−
1077− # Handle nested parentheses or brackets
1078− r = KernRe(r'(\(*.\)\s*|\[*.\]\s*);$')
1079− while r.search(proto):
1080− proto = r.sub('', proto)
1081−
1082− # Parse simple typedefs
1060+ #
1061+ # Not a function, try to parse a simple typedef.
1062+ #
10831063 r = KernRe(r'typedef.*\s+(\w+)\s*;')
10841064 if r.match(proto):
10851065 declaration_name = r.group(1)
@@ -1262,7 +1242,7 @@ class KernelDoc: · 176 unmodified lines
12621242 self.dump_section()
12631243
12641244 # Look for doc_com + <text> + doc_end:
1265− r = KernRe(r'\s*\*\s*[a-zA-Z_0-9:\.]+\*/')
1245+ r = KernRe(r'\s*\*\s*[a-zA-Z_0-9:.]+\*/')
12661246 if r.match(line):
12671247 self.emit_msg(ln, f"suspicious ending line: {line}")
12681248
@@ -1473,7 +1453,7 @@ class KernelDoc: · 204 unmodified lines
14731453 """Ancillary routine to process a function prototype"""
14741454
14751455 # strip C99-style comments to end of line
1476− line = KernRe(r"\/\/.*$", re.S).sub('', line)
1456+ line = KernRe(r"//.*$", re.S).sub('', line)
14771457 #
14781458 # Soak up the line's worth of prototype text, stopping at { or ; if present.
14791459 #
scripts/selinux/install_policy.sh+1−1
@@ -74,7 +74,7 @@ cd /etc/selinux/dummy/contexts/files · 73 unmodified lines
7474 $SF -F file_contexts /
7575
7676 mounts=`cat /proc/$$/mounts | \
77− grep -E "ext[234]|jfs|xfs|reiserfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \
77+ grep -E "ext[234]|jfs|xfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \
7878 awk '{ print $2 '}`
7979 $SF -F file_contexts $mounts
8080
scripts/sphinx-build-wrapper+719−0
@@ -0,0 +1,719 @@
1+#!/usr/bin/env python3
2+# SPDX-License-Identifier: GPL-2.0
3+# Copyright (C) 2025 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
4+#
5+# pylint: disable=R0902, R0912, R0913, R0914, R0915, R0917, C0103
6+#
7+# Converted from docs Makefile and parallel-wrapper.sh, both under
8+# GPLv2, copyrighted since 2008 by the following authors:
9+#
10+# Akira Yokosawa <akiyks@gmail.com>
11+# Arnd Bergmann <arnd@arndb.de>
12+# Breno Leitao <leitao@debian.org>
13+# Carlos Bilbao <carlos.bilbao@amd.com>
14+# Dave Young <dyoung@redhat.com>
15+# Donald Hunter <donald.hunter@gmail.com>
16+# Geert Uytterhoeven <geert+renesas@glider.be>
17+# Jani Nikula <jani.nikula@intel.com>
18+# Jan Stancek <jstancek@redhat.com>
19+# Jonathan Corbet <corbet@lwn.net>
20+# Joshua Clayton <stillcompiling@gmail.com>
21+# Kees Cook <keescook@chromium.org>
22+# Linus Torvalds <torvalds@linux-foundation.org>
23+# Magnus Damm <damm+renesas@opensource.se>
24+# Masahiro Yamada <masahiroy@kernel.org>
25+# Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
26+# Maxim Cournoyer <maxim.cournoyer@gmail.com>
27+# Peter Foley <pefoley2@pefoley.com>
28+# Randy Dunlap <rdunlap@infradead.org>
29+# Rob Herring <robh@kernel.org>
30+# Shuah Khan <shuahkh@osg.samsung.com>
31+# Thorsten Blum <thorsten.blum@toblux.com>
32+# Tomas Winkler <tomas.winkler@intel.com>
33+
34+
35+"""
36+Sphinx build wrapper that handles Kernel-specific business rules:
37+
38+- it gets the Kernel build environment vars;
39+- it determines what's the best parallelism;
40+- it handles SPHINXDIRS
41+
42+This tool ensures that MIN_PYTHON_VERSION is satisfied. If version is
43+below that, it seeks for a new Python version. If found, it re-runs using
44+the newer version.
45+"""
46+
47+import argparse
48+import locale
49+import os
50+import re
51+import shlex
52+import shutil
53+import subprocess
54+import sys
55+
56+from concurrent import futures
57+from glob import glob
58+
59+LIB_DIR = "lib"
60+SRC_DIR = os.path.dirname(os.path.realpath(__file__))
61+
62+sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR))
63+
64+from jobserver import JobserverExec # pylint: disable=C0413
65+
66+
67+def parse_version(version):
68+ """Convert a major.minor.patch version into a tuple"""
69+ return tuple(int(x) for x in version.split("."))
70+
71+def ver_str(version):
72+ """Returns a version tuple as major.minor.patch"""
73+
74+ return ".".join([str(x) for x in version])
75+
76+# Minimal supported Python version needed by Sphinx and its extensions
77+MIN_PYTHON_VERSION = parse_version("3.7")
78+
79+# Default value for --venv parameter
80+VENV_DEFAULT = "sphinx_latest"
81+
82+# List of make targets and its corresponding builder and output directory
83+TARGETS = {
84+ "cleandocs": {
85+ "builder": "clean",
86+ },
87+ "htmldocs": {
88+ "builder": "html",
89+ },
90+ "epubdocs": {
91+ "builder": "epub",
92+ "out_dir": "epub",
93+ },
94+ "texinfodocs": {
95+ "builder": "texinfo",
96+ "out_dir": "texinfo",
97+ },
98+ "infodocs": {
99+ "builder": "texinfo",
100+ "out_dir": "texinfo",
101+ },
102+ "latexdocs": {
103+ "builder": "latex",
104+ "out_dir": "latex",
105+ },
106+ "pdfdocs": {
107+ "builder": "latex",
108+ "out_dir": "latex",
109+ },
110+ "xmldocs": {
111+ "builder": "xml",
112+ "out_dir": "xml",
113+ },
114+ "linkcheckdocs": {
115+ "builder": "linkcheck"
116+ },
117+}
118+
119+# Paper sizes. An empty value will pick the default
120+PAPER = ["", "a4", "letter"]
121+
122+class SphinxBuilder:
123+ """
124+ Handles a sphinx-build target, adding needed arguments to build
125+ with the Kernel.
126+ """
127+
128+ def is_rust_enabled(self):
129+ """Check if rust is enabled at .config"""
130+ config_path = os.path.join(self.srctree, ".config")
131+ if os.path.isfile(config_path):
132+ with open(config_path, "r", encoding="utf-8") as f:
133+ return "CONFIG_RUST=y" in f.read()
134+ return False
135+
136+ def get_path(self, path, abs_path=False):
137+ """
138+ Ancillary routine to handle patches the right way, as shell does.
139+
140+ It first expands "~" and "~user". Then, if patch is not absolute,
141+ join self.srctree. Finally, if requested, convert to abspath.
142+ """
143+
144+ path = os.path.expanduser(path)
145+ if not path.startswith("/"):
146+ path = os.path.join(self.srctree, path)
147+
148+ if abs_path:
149+ return os.path.abspath(path)
150+
151+ return path
152+
153+ def __init__(self, venv=None, verbose=False, n_jobs=None, interactive=None):
154+ """Initialize internal variables"""
155+ self.venv = venv
156+ self.verbose = None
157+
158+ # Normal variables passed from Kernel's makefile
159+ self.kernelversion = os.environ.get("KERNELVERSION", "unknown")
160+ self.kernelrelease = os.environ.get("KERNELRELEASE", "unknown")
161+ self.pdflatex = os.environ.get("PDFLATEX", "xelatex")
162+
163+ if not interactive:
164+ self.latexopts = os.environ.get("LATEXOPTS", "-interaction=batchmode -no-shell-escape")
165+ else:
166+ self.latexopts = os.environ.get("LATEXOPTS", "")
167+
168+ if not verbose:
169+ verbose = bool(os.environ.get("KBUILD_VERBOSE", "") != "")
170+
171+ # Handle SPHINXOPTS evironment
172+ sphinxopts = shlex.split(os.environ.get("SPHINXOPTS", ""))
173+
174+ # As we handle number of jobs and quiet in separate, we need to pick
175+ # it the same way as sphinx-build would pick, so let's use argparse
176+ # do to the right argument expansion
177+ parser = argparse.ArgumentParser()
178+ parser.add_argument('-j', '--jobs', type=int)
179+ parser.add_argument('-q', '--quiet', type=int)
180+
181+ # Other sphinx-build arguments go as-is, so place them
182+ # at self.sphinxopts
183+ sphinx_args, self.sphinxopts = parser.parse_known_args(sphinxopts)
184+ if sphinx_args.quiet == True:
185+ self.verbose = False
186+
187+ if sphinx_args.jobs:
188+ self.n_jobs = sphinx_args.jobs
189+
190+ # Command line arguments was passed, override SPHINXOPTS
191+ if verbose is not None:
192+ self.verbose = verbose
193+
194+ self.n_jobs = n_jobs
195+
196+ # Source tree directory. This needs to be at os.environ, as
197+ # Sphinx extensions and media uAPI makefile needs it
198+ self.srctree = os.environ.get("srctree")
199+ if not self.srctree:
200+ self.srctree = "."
201+ os.environ["srctree"] = self.srctree
202+
203+ # Now that we can expand srctree, get other directories as well
204+ self.sphinxbuild = os.environ.get("SPHINXBUILD", "sphinx-build")
205+ self.kerneldoc = self.get_path(os.environ.get("KERNELDOC",
206+ "scripts/kernel-doc.py"))
207+ self.obj = os.environ.get("obj", "Documentation")
208+ self.builddir = self.get_path(os.path.join(self.obj, "output"),
209+ abs_path=True)
210+
211+ # Media uAPI needs it
212+ os.environ["BUILDDIR"] = self.builddir
213+
214+ # Detect if rust is enabled
215+ self.config_rust = self.is_rust_enabled()
216+
217+ # Get directory locations for LaTeX build toolchain
218+ self.pdflatex_cmd = shutil.which(self.pdflatex)
219+ self.latexmk_cmd = shutil.which("latexmk")
220+
221+ self.env = os.environ.copy()
222+
223+ # If venv parameter is specified, run Sphinx from venv
224+ if venv:
225+ bin_dir = os.path.join(venv, "bin")
226+ if os.path.isfile(os.path.join(bin_dir, "activate")):
227+ # "activate" virtual env
228+ self.env["PATH"] = bin_dir + ":" + self.env["PATH"]
229+ self.env["VIRTUAL_ENV"] = venv
230+ if "PYTHONHOME" in self.env:
231+ del self.env["PYTHONHOME"]
232+ print(f"Setting venv to {venv}")
233+ else:
234+ sys.exit(f"Venv {venv} not found.")
235+
236+ def run_sphinx(self, sphinx_build, build_args, *args, **pwargs):
237+ """
238+ Executes sphinx-build using current python3 command and setting
239+ -j parameter if possible to run the build in parallel.
240+ """
241+
242+ with JobserverExec() as jobserver:
243+ if jobserver.claim:
244+ n_jobs = str(jobserver.claim)
245+ else:
246+ n_jobs = "auto" # Supported since Sphinx 1.7
247+
248+ cmd = []
249+
250+ if self.venv:
251+ cmd.append("python")
252+ else:
253+ cmd.append(sys.executable)
254+
255+ cmd.append(sphinx_build)
256+
257+ # if present, SPHINXOPTS or command line --jobs overrides default
258+ if self.n_jobs:
259+ n_jobs = str(self.n_jobs)
260+
261+ if n_jobs:
262+ cmd += [f"-j{n_jobs}"]
263+
264+ if not self.verbose:
265+ cmd.append("-q")
266+
267+ cmd += self.sphinxopts
268+
269+ cmd += build_args
270+
271+ if self.verbose:
272+ print(" ".join(cmd))
273+
274+ rc = subprocess.call(cmd, *args, **pwargs)
275+
276+ def handle_html(self, css, output_dir):
277+ """
278+ Extra steps for HTML and epub output.
279+
280+ For such targets, we need to ensure that CSS will be properly
281+ copied to the output _static directory
282+ """
283+
284+ if not css:
285+ return
286+
287+ css = os.path.expanduser(css)
288+ if not css.startswith("/"):
289+ css = os.path.join(self.srctree, css)
290+
291+ static_dir = os.path.join(output_dir, "_static")
292+ os.makedirs(static_dir, exist_ok=True)
293+
294+ try:
295+ shutil.copy2(css, static_dir)
296+ except (OSError, IOError) as e:
297+ print(f"Warning: Failed to copy CSS: {e}", file=sys.stderr)
298+
299+ def build_pdf_file(self, latex_cmd, from_dir, path):
300+ """Builds a single pdf file using latex_cmd"""
301+ try:
302+ subprocess.run(latex_cmd + [path],
303+ cwd=from_dir, check=True)
304+
305+ return True
306+ except subprocess.CalledProcessError:
307+ # LaTeX PDF error code is almost useless: it returns
308+ # error codes even when build succeeds but has warnings.
309+ # So, we'll ignore the results
310+ return False
311+
312+ def pdf_parallel_build(self, tex_suffix, latex_cmd, tex_files, n_jobs):
313+ """Build PDF files in parallel if possible"""
314+ builds = {}
315+ build_failed = False
316+ max_len = 0
317+ has_tex = False
318+
319+ # Process files in parallel
320+ with futures.ThreadPoolExecutor(max_workers=n_jobs) as executor:
321+ jobs = {}
322+
323+ for from_dir, pdf_dir, entry in tex_files:
324+ name = entry.name
325+
326+ if not name.endswith(tex_suffix):
327+ continue
328+
329+ name = name[:-len(tex_suffix)]
330+
331+ max_len = max(max_len, len(name))
332+
333+ has_tex = True
334+
335+ future = executor.submit(self.build_pdf_file, latex_cmd,
336+ from_dir, entry.path)
337+ jobs[future] = (from_dir, name, entry.path)
338+
339+ for future in futures.as_completed(jobs):
340+ from_dir, name, path = jobs[future]
341+
342+ pdf_name = name + ".pdf"
343+ pdf_from = os.path.join(from_dir, pdf_name)
344+
345+ try:
346+ success = future.result()
347+
348+ if success and os.path.exists(pdf_from):
349+ pdf_to = os.path.join(pdf_dir, pdf_name)
350+
351+ os.rename(pdf_from, pdf_to)
352+ builds[name] = os.path.relpath(pdf_to, self.builddir)
353+ else:
354+ builds[name] = "FAILED"
355+ build_failed = True
356+ except Exception as e:
357+ builds[name] = f"FAILED ({str(e)})"
358+ build_failed = True
359+
360+ # Handle case where no .tex files were found
361+ if not has_tex:
362+ name = "Sphinx LaTeX builder"
363+ max_len = max(max_len, len(name))
364+ builds[name] = "FAILED (no .tex file was generated)"
365+ build_failed = True
366+
367+ return builds, build_failed, max_len
368+
369+ def handle_pdf(self, output_dirs):
370+ """
371+ Extra steps for PDF output.
372+
373+ As PDF is handled via a LaTeX output, after building the .tex file,
374+ a new build is needed to create the PDF output from the latex
375+ directory.
376+ """
377+ builds = {}
378+ max_len = 0
379+ tex_suffix = ".tex"
380+
381+ # Get all tex files that will be used for PDF build
382+ tex_files = []
383+ for from_dir in output_dirs:
384+ pdf_dir = os.path.join(from_dir, "../pdf")
385+ os.makedirs(pdf_dir, exist_ok=True)
386+
387+ if self.latexmk_cmd:
388+ latex_cmd = [self.latexmk_cmd, f"-{self.pdflatex}"]
389+ else:
390+ latex_cmd = [self.pdflatex]
391+
392+ latex_cmd.extend(shlex.split(self.latexopts))
393+
394+ # Get a list of tex files to process
395+ with os.scandir(from_dir) as it:
396+ for entry in it:
397+ if entry.name.endswith(tex_suffix):
398+ tex_files.append((from_dir, pdf_dir, entry))
399+
400+ # When using make, this won't be used, as the number of jobs comes
401+ # from POSIX jobserver. So, this covers the case where build comes
402+ # from command line. On such case, serialize by default, except if
403+ # the user explicitly sets the number of jobs.
404+ n_jobs = 1
405+
406+ # n_jobs is either an integer or "auto". Only use it if it is a number
407+ if self.n_jobs:
408+ try:
409+ n_jobs = int(self.n_jobs)
410+ except ValueError:
411+ pass
412+
413+ # When using make, jobserver.claim is the number of jobs that were
414+ # used with "-j" and that aren't used by other make targets
415+ with JobserverExec() as jobserver:
416+ n_jobs = 1
417+
418+ # Handle the case when a parameter is passed via command line,
419+ # using it as default, if jobserver doesn't claim anything
420+ if self.n_jobs:
421+ try:
422+ n_jobs = int(self.n_jobs)
423+ except ValueError:
424+ pass
425+
426+ if jobserver.claim:
427+ n_jobs = jobserver.claim
428+
429+ # Build files in parallel
430+ builds, build_failed, max_len = self.pdf_parallel_build(tex_suffix,
431+ latex_cmd,
432+ tex_files,
433+ n_jobs)
434+
435+ msg = "Summary"
436+ msg += "\n" + "=" * len(msg)
437+ print()
438+ print(msg)
439+
440+ for pdf_name, pdf_file in builds.items():
441+ print(f"{pdf_name:<{max_len}}: {pdf_file}")
442+
443+ print()
444+
445+ # return an error if a PDF file is missing
446+
447+ if build_failed:
448+ sys.exit(f"PDF build failed: not all PDF files were created.")
449+ else:
450+ print("All PDF files were built.")
451+
452+ def handle_info(self, output_dirs):
453+ """
454+ Extra steps for Info output.
455+
456+ For texinfo generation, an additional make is needed from the
457+ texinfo directory.
458+ """
459+
460+ for output_dir in output_dirs:
461+ try:
462+ subprocess.run(["make", "info"], cwd=output_dir, check=True)
463+ except subprocess.CalledProcessError as e:
464+ sys.exit(f"Error generating info docs: {e}")
465+
466+ def cleandocs(self, builder):
467+
468+ shutil.rmtree(self.builddir, ignore_errors=True)
469+
470+ def build(self, target, sphinxdirs=None, conf="conf.py",
471+ theme=None, css=None, paper=None):
472+ """
473+ Build documentation using Sphinx. This is the core function of this
474+ module. It prepares all arguments required by sphinx-build.
475+ """
476+
477+ builder = TARGETS[target]["builder"]
478+ out_dir = TARGETS[target].get("out_dir", "")
479+
480+ # Cleandocs doesn't require sphinx-build
481+ if target == "cleandocs":
482+ self.cleandocs(builder)
483+ return
484+
485+ # Other targets require sphinx-build
486+ sphinxbuild = shutil.which(self.sphinxbuild, path=self.env["PATH"])
487+ if not sphinxbuild:
488+ sys.exit(f"Error: {self.sphinxbuild} not found in PATH.\n")
489+
490+ if builder == "latex":
491+ if not self.pdflatex_cmd and not self.latexmk_cmd:
492+ sys.exit("Error: pdflatex or latexmk required for PDF generation")
493+
494+ docs_dir = os.path.abspath(os.path.join(self.srctree, "Documentation"))
495+
496+ # Prepare base arguments for Sphinx build
497+ kerneldoc = self.kerneldoc
498+ if kerneldoc.startswith(self.srctree):
499+ kerneldoc = os.path.relpath(kerneldoc, self.srctree)
500+
501+ # Prepare common Sphinx options
502+ args = [
503+ "-b", builder,
504+ "-c", docs_dir,
505+ ]
506+
507+ if builder == "latex":
508+ if not paper:
509+ paper = PAPER[1]
510+
511+ args.extend(["-D", f"latex_elements.papersize={paper}paper"])
512+
513+ if self.config_rust:
514+ args.extend(["-t", "rustdoc"])
515+
516+ if conf:
517+ self.env["SPHINX_CONF"] = self.get_path(conf, abs_path=True)
518+
519+ if not sphinxdirs:
520+ sphinxdirs = os.environ.get("SPHINXDIRS", ".")
521+
522+ # The sphinx-build tool has a bug: internally, it tries to set
523+ # locale with locale.setlocale(locale.LC_ALL, ''). This causes a
524+ # crash if language is not set. Detect and fix it.
525+ try:
526+ locale.setlocale(locale.LC_ALL, '')
527+ except Exception:
528+ self.env["LC_ALL"] = "C"
529+ self.env["LANG"] = "C"
530+
531+ # sphinxdirs can be a list or a whitespace-separated string
532+ sphinxdirs_list = []
533+ for sphinxdir in sphinxdirs:
534+ if isinstance(sphinxdir, list):
535+ sphinxdirs_list += sphinxdir
536+ else:
537+ for name in sphinxdir.split(" "):
538+ sphinxdirs_list.append(name)
539+
540+ # Build each directory
541+ output_dirs = []
542+ for sphinxdir in sphinxdirs_list:
543+ src_dir = os.path.join(docs_dir, sphinxdir)
544+ doctree_dir = os.path.join(self.builddir, ".doctrees")
545+ output_dir = os.path.join(self.builddir, sphinxdir, out_dir)
546+
547+ # Make directory names canonical
548+ src_dir = os.path.normpath(src_dir)
549+ doctree_dir = os.path.normpath(doctree_dir)
550+ output_dir = os.path.normpath(output_dir)
551+
552+ os.makedirs(doctree_dir, exist_ok=True)
553+ os.makedirs(output_dir, exist_ok=True)
554+
555+ output_dirs.append(output_dir)
556+
557+ build_args = args + [
558+ "-d", doctree_dir,
559+ "-D", f"kerneldoc_bin={kerneldoc}",
560+ "-D", f"version={self.kernelversion}",
561+ "-D", f"release={self.kernelrelease}",
562+ "-D", f"kerneldoc_srctree={self.srctree}",
563+ src_dir,
564+ output_dir,
565+ ]
566+
567+ # Execute sphinx-build
568+ try:
569+ self.run_sphinx(sphinxbuild, build_args, env=self.env)
570+ except Exception as e:
571+ sys.exit(f"Build failed: {e}")
572+
573+ # Ensure that html/epub will have needed static files
574+ if target in ["htmldocs", "epubdocs"]:
575+ self.handle_html(css, output_dir)
576+
577+ # PDF and Info require a second build step
578+ if target == "pdfdocs":
579+ self.handle_pdf(output_dirs)
580+ elif target == "infodocs":
581+ self.handle_info(output_dirs)
582+
583+ @staticmethod
584+ def get_python_version(cmd):
585+ """
586+ Get python version from a Python binary. As we need to detect if
587+ are out there newer python binaries, we can't rely on sys.release here.
588+ """
589+
590+ result = subprocess.run([cmd, "--version"], check=True,
591+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
592+ universal_newlines=True)
593+ version = result.stdout.strip()
594+
595+ match = re.search(r"(\d+\.\d+\.\d+)", version)
596+ if match:
597+ return parse_version(match.group(1))
598+
599+ print(f"Can't parse version {version}")
600+ return (0, 0, 0)
601+
602+ @staticmethod
603+ def find_python():
604+ """
605+ Detect if are out there any python 3.xy version newer than the
606+ current one.
607+
608+ Note: this routine is limited to up to 2 digits for python3. We
609+ may need to update it one day, hopefully on a distant future.
610+ """
611+ patterns = [
612+ "python3.[0-9]",
613+ "python3.[0-9][0-9]",
614+ ]
615+
616+ # Seek for a python binary newer than MIN_PYTHON_VERSION
617+ for path in os.getenv("PATH", "").split(":"):
618+ for pattern in patterns:
619+ for cmd in glob(os.path.join(path, pattern)):
620+ if os.path.isfile(cmd) and os.access(cmd, os.X_OK):
621+ version = SphinxBuilder.get_python_version(cmd)
622+ if version >= MIN_PYTHON_VERSION:
623+ return cmd
624+
625+ return None
626+
627+ @staticmethod
628+ def check_python():
629+ """
630+ Check if the current python binary satisfies our minimal requirement
631+ for Sphinx build. If not, re-run with a newer version if found.
632+ """
633+ cur_ver = sys.version_info[:3]
634+ if cur_ver >= MIN_PYTHON_VERSION:
635+ return
636+
637+ python_ver = ver_str(cur_ver)
638+
639+ new_python_cmd = SphinxBuilder.find_python()
640+ if not new_python_cmd:
641+ sys.exit(f"Python version {python_ver} is not supported anymore.")
642+
643+ # Restart script using the newer version
644+ script_path = os.path.abspath(sys.argv[0])
645+ args = [new_python_cmd, script_path] + sys.argv[1:]
646+
647+ print(f"Python {python_ver} not supported. Changing to {new_python_cmd}")
648+
649+ try:
650+ os.execv(new_python_cmd, args)
651+ except OSError as e:
652+ sys.exit(f"Failed to restart with {new_python_cmd}: {e}")
653+
654+def jobs_type(value):
655+ """
656+ Handle valid values for -j. Accepts Sphinx "-jauto", plus a number
657+ equal or bigger than one.
658+ """
659+ if value is None:
660+ return None
661+
662+ if value.lower() == 'auto':
663+ return value.lower()
664+
665+ try:
666+ if int(value) >= 1:
667+ return value
668+
669+ raise argparse.ArgumentTypeError(f"Minimum jobs is 1, got {value}")
670+ except ValueError:
671+ raise argparse.ArgumentTypeError(f"Must be 'auto' or positive integer, got {value}")
672+
673+def main():
674+ """
675+ Main function. The only mandatory argument is the target. If not
676+ specified, the other arguments will use default values if not
677+ specified at os.environ.
678+ """
679+ parser = argparse.ArgumentParser(description="Kernel documentation builder")
680+
681+ parser.add_argument("target", choices=list(TARGETS.keys()),
682+ help="Documentation target to build")
683+ parser.add_argument("--sphinxdirs", nargs="+",
684+ help="Specific directories to build")
685+ parser.add_argument("--conf", default="conf.py",
686+ help="Sphinx configuration file")
687+
688+ parser.add_argument("--theme", help="Sphinx theme to use")
689+
690+ parser.add_argument("--css", help="Custom CSS file for HTML/EPUB")
691+
692+ parser.add_argument("--paper", choices=PAPER, default=PAPER[0],
693+ help="Paper size for LaTeX/PDF output")
694+
695+ parser.add_argument("-v", "--verbose", action='store_true',
696+ help="place build in verbose mode")
697+
698+ parser.add_argument('-j', '--jobs', type=jobs_type,
699+ help="Sets number of jobs to use with sphinx-build")
700+
701+ parser.add_argument('-i', '--interactive', action='store_true',
702+ help="Change latex default to run in interactive mode")
703+
704+ parser.add_argument("-V", "--venv", nargs='?', const=f'{VENV_DEFAULT}',
705+ default=None,
706+ help=f'If used, run Sphinx from a venv dir (default dir: {VENV_DEFAULT})')
707+
708+ args = parser.parse_args()
709+
710+ SphinxBuilder.check_python()
711+
712+ builder = SphinxBuilder(venv=args.venv, verbose=args.verbose,
713+ n_jobs=args.jobs, interactive=args.interactive)
714+
715+ builder.build(args.target, sphinxdirs=args.sphinxdirs, conf=args.conf,
716+ theme=args.theme, css=args.css, paper=args.paper)
717+
718+if __name__ == "__main__":
719+ main()
scripts/sphinx-pre-install+1617−1052
@@ -1,1056 +1,1621 @@
1−#!/usr/bin/env perl
1+#!/usr/bin/env python3
22 # SPDX-License-Identifier: GPL-2.0-or-later
3−use strict;
4−
5−# Copyright (c) 2017-2020 Mauro Carvalho Chehab <mchehab@kernel.org>
6−#
7−
8−my $prefix = "./";
9−$prefix = "$ENV{'srctree'}/" if ($ENV{'srctree'});
10−
11−my $conf = $prefix . "Documentation/conf.py";
12−my $requirement_file = $prefix . "Documentation/sphinx/requirements.txt";
13−my $virtenv_prefix = "sphinx_";
14−
15−#
16−# Static vars
17−#
18−
19−my %missing;
20−my $system_release;
21−my $need = 0;
22−my $optional = 0;
23−my $need_symlink = 0;
24−my $need_sphinx = 0;
25−my $need_pip = 0;
26−my $need_virtualenv = 0;
27−my $rec_sphinx_upgrade = 0;
28−my $verbose_warn_install = 1;
29−my $install = "";
30−my $virtenv_dir = "";
31−my $python_cmd = "";
32−my $activate_cmd;
33−my $min_version;
34−my $cur_version;
35−my $rec_version = "3.4.3";
36−my $latest_avail_ver;
37−
38−#
39−# Command line arguments
40−#
41−
42−my $pdf = 1;
43−my $virtualenv = 1;
44−my $version_check = 0;
45−
46−#
47−# List of required texlive packages on Fedora and OpenSuse
48−#
49−
50−my %texlive = (
51− 'amsfonts.sty' => 'texlive-amsfonts',
52− 'amsmath.sty' => 'texlive-amsmath',
53− 'amssymb.sty' => 'texlive-amsfonts',
54− 'amsthm.sty' => 'texlive-amscls',
55− 'anyfontsize.sty' => 'texlive-anyfontsize',
56− 'atbegshi.sty' => 'texlive-oberdiek',
57− 'bm.sty' => 'texlive-tools',
58− 'capt-of.sty' => 'texlive-capt-of',
59− 'cmap.sty' => 'texlive-cmap',
60− 'ecrm1000.tfm' => 'texlive-ec',
61− 'eqparbox.sty' => 'texlive-eqparbox',
62− 'eu1enc.def' => 'texlive-euenc',
63− 'fancybox.sty' => 'texlive-fancybox',
64− 'fancyvrb.sty' => 'texlive-fancyvrb',
65− 'float.sty' => 'texlive-float',
66− 'fncychap.sty' => 'texlive-fncychap',
67− 'footnote.sty' => 'texlive-mdwtools',
68− 'framed.sty' => 'texlive-framed',
69− 'luatex85.sty' => 'texlive-luatex85',
70− 'multirow.sty' => 'texlive-multirow',
71− 'needspace.sty' => 'texlive-needspace',
72− 'palatino.sty' => 'texlive-psnfss',
73− 'parskip.sty' => 'texlive-parskip',
74− 'polyglossia.sty' => 'texlive-polyglossia',
75− 'tabulary.sty' => 'texlive-tabulary',
76− 'threeparttable.sty' => 'texlive-threeparttable',
77− 'titlesec.sty' => 'texlive-titlesec',
78− 'ucs.sty' => 'texlive-ucs',
79− 'upquote.sty' => 'texlive-upquote',
80− 'wrapfig.sty' => 'texlive-wrapfig',
81− 'ctexhook.sty' => 'texlive-ctex',
82−);
83−
84−#
85−# Subroutines that checks if a feature exists
86−#
87−
88−sub check_missing(%)
89−{
90− my %map = %{$_[0]};
91−
92− foreach my $prog (sort keys %missing) {
93− my $is_optional = $missing{$prog};
94−
95− # At least on some LTS distros like CentOS 7, texlive doesn't
96− # provide all packages we need. When such distros are
97− # detected, we have to disable PDF output.
98− #
99− # So, we need to ignore the packages that distros would
100− # need for LaTeX to work
101− if ($is_optional == 2 && !$pdf) {
102− $optional--;
103− next;
104− }
105−
106− if ($verbose_warn_install) {
107− if ($is_optional) {
108− print "Warning: better to also install \"$prog\".\n";
109− } else {
110− print "ERROR: please install \"$prog\", otherwise, build won't work.\n";
111− }
112− }
113− if (defined($map{$prog})) {
114− $install .= " " . $map{$prog};
115− } else {
116− $install .= " " . $prog;
117− }
118− }
119−
120− $install =~ s/^\s//;
121−}
122−
123−sub add_package($$)
124−{
125− my $package = shift;
126− my $is_optional = shift;
127−
128− $missing{$package} = $is_optional;
129− if ($is_optional) {
130− $optional++;
131− } else {
132− $need++;
133− }
134−}
135−
136−sub check_missing_file($$$)
137−{
138− my $files = shift;
139− my $package = shift;
140− my $is_optional = shift;
141−
142− for (@$files) {
143− return if(-e $_);
144− }
145−
146− add_package($package, $is_optional);
147−}
148−
149−sub findprog($)
150−{
151− foreach(split(/:/, $ENV{PATH})) {
152− return "$_/$_[0]" if(-x "$_/$_[0]");
153− }
154−}
155−
156−sub find_python_no_venv()
157−{
158− my $prog = shift;
159−
160− my $cur_dir = qx(pwd);
161− $cur_dir =~ s/\s+$//;
162−
163− foreach my $dir (split(/:/, $ENV{PATH})) {
164− next if ($dir =~ m,($cur_dir)/sphinx,);
165− return "$dir/python3" if(-x "$dir/python3");
166− }
167− foreach my $dir (split(/:/, $ENV{PATH})) {
168− next if ($dir =~ m,($cur_dir)/sphinx,);
169− return "$dir/python" if(-x "$dir/python");
170− }
171− return "python";
172−}
173−
174−sub check_program($$)
175−{
176− my $prog = shift;
177− my $is_optional = shift;
178−
179− return $prog if findprog($prog);
180−
181− add_package($prog, $is_optional);
182−}
183−
184−sub check_perl_module($$)
185−{
186− my $prog = shift;
187− my $is_optional = shift;
188−
189− my $err = system("perl -M$prog -e 1 2>/dev/null /dev/null");
190− return if ($err == 0);
191−
192− add_package($prog, $is_optional);
193−}
194−
195−sub check_python_module($$)
196−{
197− my $prog = shift;
198− my $is_optional = shift;
199−
200− return if (!$python_cmd);
201−
202− my $err = system("$python_cmd -c 'import $prog' 2>/dev/null /dev/null");
203− return if ($err == 0);
204−
205− add_package($prog, $is_optional);
206−}
207−
208−sub check_rpm_missing($$)
209−{
210− my @pkgs = @{$_[0]};
211− my $is_optional = $_[1];
212−
213− foreach my $prog(@pkgs) {
214− my $err = system("rpm -q '$prog' 2>/dev/null >/dev/null");
215− add_package($prog, $is_optional) if ($err);
216− }
217−}
218−
219−sub check_pacman_missing($$)
220−{
221− my @pkgs = @{$_[0]};
222− my $is_optional = $_[1];
223−
224− foreach my $prog(@pkgs) {
225− my $err = system("pacman -Q '$prog' 2>/dev/null >/dev/null");
226− add_package($prog, $is_optional) if ($err);
227− }
228−}
229−
230−sub check_missing_tex($)
231−{
232− my $is_optional = shift;
233− my $kpsewhich = findprog("kpsewhich");
234−
235− foreach my $prog(keys %texlive) {
236− my $package = $texlive{$prog};
237− if (!$kpsewhich) {
238− add_package($package, $is_optional);
239− next;
240− }
241− my $file = qx($kpsewhich $prog);
242− add_package($package, $is_optional) if ($file =~ /^\s*$/);
243− }
244−}
245−
246−sub get_sphinx_fname()
247−{
248− if ($ENV{'SPHINXBUILD'}) {
249− return $ENV{'SPHINXBUILD'};
250− }
251−
252− my $fname = "sphinx-build";
253− return $fname if findprog($fname);
254−
255− $fname = "sphinx-build-3";
256− if (findprog($fname)) {
257− $need_symlink = 1;
258− return $fname;
259− }
260−
261− return "";
262−}
263−
264−sub get_sphinx_version($)
265−{
266− my $cmd = shift;
267− my $ver;
268−
269− open IN, "$cmd --version 2>&1 |";
270− while (<IN>) {
271− if (m/^\s*sphinx-build\s+([\d\.]+)((\+\/[\da-f]+)|(b\d+))?$/) {
272− $ver=$1;
273− last;
274− }
275− # Sphinx 1.2.x uses a different format
276− if (m/^\s*Sphinx.*\s+([\d\.]+)$/) {
277− $ver=$1;
278− last;
279− }
280− }
281− close IN;
282− return $ver;
283−}
284−
285−sub check_sphinx()
286−{
287− open IN, $conf or die "Can't open $conf";
288− while (<IN>) {
289− if (m/^\s*needs_sphinx\s*=\s*[\'\"]([\d\.]+)[\'\"]/) {
290− $min_version=$1;
291− last;
292− }
293− }
294− close IN;
295−
296− die "Can't get needs_sphinx version from $conf" if (!$min_version);
297−
298− $virtenv_dir = $virtenv_prefix . "latest";
299−
300− my $sphinx = get_sphinx_fname();
301− if ($sphinx eq "") {
302− $need_sphinx = 1;
303− return;
304− }
305−
306− $cur_version = get_sphinx_version($sphinx);
307− die "$sphinx didn't return its version" if (!$cur_version);
308−
309− if ($cur_version lt $min_version) {
310− printf "ERROR: Sphinx version is %s. It should be >= %s\n",
311− $cur_version, $min_version;
312− $need_sphinx = 1;
313− return;
314− }
315−
316− return if ($cur_version lt $rec_version);
317−
318− # On version check mode, just assume Sphinx has all mandatory deps
319− exit (0) if ($version_check);
320−}
321−
322−#
323−# Ancillary subroutines
324−#
325−
326−sub catcheck($)
327−{
328− my $res = "";
329− $res = qx(cat $_[0]) if (-r $_[0]);
330− return $res;
331−}
332−
333−sub which($)
334−{
335− my $file = shift;
336− my @path = split ":", $ENV{PATH};
337−
338− foreach my $dir(@path) {
339− my $name = $dir.'/'.$file;
340− return $name if (-x $name );
341− }
342− return undef;
343−}
344−
345−#
346−# Subroutines that check distro-specific hints
347−#
348−
349−sub give_debian_hints()
350−{
351− my %map = (
352− "python-sphinx" => "python3-sphinx",
353− "yaml" => "python3-yaml",
354− "ensurepip" => "python3-venv",
355− "virtualenv" => "virtualenv",
356− "dot" => "graphviz",
357− "convert" => "imagemagick",
358− "Pod::Usage" => "perl-modules",
359− "xelatex" => "texlive-xetex",
360− "rsvg-convert" => "librsvg2-bin",
361− );
362−
363− if ($pdf) {
364− check_missing_file(["/usr/share/texlive/texmf-dist/tex/latex/ctex/ctexhook.sty"],
365− "texlive-lang-chinese", 2);
366−
367− check_missing_file(["/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"],
368− "fonts-dejavu", 2);
369−
370− check_missing_file(["/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
371− "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
372− "/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc"],
373− "fonts-noto-cjk", 2);
374− }
375−
376− check_program("dvipng", 2) if ($pdf);
377− check_missing(\%map);
378−
379− return if (!$need && !$optional);
380− printf("You should run:\n") if ($verbose_warn_install);
381− printf("\n\tsudo apt-get install $install\n");
382−}
383−
384−sub give_redhat_hints()
385−{
386− my %map = (
387− "python-sphinx" => "python3-sphinx",
388− "yaml" => "python3-pyyaml",
389− "virtualenv" => "python3-virtualenv",
390− "dot" => "graphviz",
391− "convert" => "ImageMagick",
392− "Pod::Usage" => "perl-Pod-Usage",
393− "xelatex" => "texlive-xetex-bin",
394− "rsvg-convert" => "librsvg2-tools",
395− );
396−
397− my @fedora26_opt_pkgs = (
398− "graphviz-gd", # Fedora 26: needed for PDF support
399− );
400−
401− my @fedora_tex_pkgs = (
402− "texlive-collection-fontsrecommended",
403− "texlive-collection-latex",
404− "texlive-xecjk",
405− "dejavu-sans-fonts",
406− "dejavu-serif-fonts",
407− "dejavu-sans-mono-fonts",
408− );
409−
410− #
411− # Checks valid for RHEL/CentOS version 7.x.
412− #
413− my $old = 0;
414− my $rel;
415− my $noto_sans_redhat = "google-noto-sans-cjk-ttc-fonts";
416− $rel = $1 if ($system_release =~ /(release|Linux)\s+(\d+)/);
417−
418− if (!($system_release =~ /Fedora/)) {
419− $map{"virtualenv"} = "python-virtualenv";
420−
421− if ($rel && $rel < 8) {
422− $old = 1;
423− $pdf = 0;
424−
425− printf("Note: texlive packages on RHEL/CENTOS <= 7 are incomplete. Can't support PDF output\n");
426− printf("If you want to build PDF, please read:\n");
427− printf("\thttps://www.systutorials.com/241660/how-to-install-tex-live-on-centos-7-linux/\n");
428− }
429− } else {
430− if ($rel && $rel < 26) {
431− $old = 1;
432− }
433− if ($rel && $rel >= 38) {
434− $noto_sans_redhat = "google-noto-sans-cjk-fonts";
435− }
436− }
437− if (!$rel) {
438− printf("Couldn't identify release number\n");
439− $old = 1;
440− $pdf = 0;
441− }
442−
443− if ($pdf) {
444− check_missing_file(["/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
445− "/usr/share/fonts/google-noto-sans-cjk-fonts/NotoSansCJK-Regular.ttc"],
446− $noto_sans_redhat, 2);
447− }
448−
449− check_rpm_missing(\@fedora26_opt_pkgs, 2) if ($pdf && !$old);
450− check_rpm_missing(\@fedora_tex_pkgs, 2) if ($pdf);
451− check_missing_tex(2) if ($pdf);
452− check_missing(\%map);
453−
454− return if (!$need && !$optional);
455−
456− if (!$old) {
457− # dnf, for Fedora 18+
458− printf("You should run:\n") if ($verbose_warn_install);
459− printf("\n\tsudo dnf install -y $install\n");
460− } else {
461− # yum, for RHEL (and clones) or Fedora version < 18
462− printf("You should run:\n") if ($verbose_warn_install);
463− printf("\n\tsudo yum install -y $install\n");
464− }
465−}
466−
467−sub give_opensuse_hints()
468−{
469− my %map = (
470− "python-sphinx" => "python3-sphinx",
471− "yaml" => "python3-pyyaml",
472− "virtualenv" => "python3-virtualenv",
473− "dot" => "graphviz",
474− "convert" => "ImageMagick",
475− "Pod::Usage" => "perl-Pod-Usage",
476− "xelatex" => "texlive-xetex-bin",
477− );
478−
479− # On Tumbleweed, this package is also named rsvg-convert
480− $map{"rsvg-convert"} = "rsvg-view" if (!($system_release =~ /Tumbleweed/));
481−
482− my @suse_tex_pkgs = (
483− "texlive-babel-english",
484− "texlive-caption",
485− "texlive-colortbl",
486− "texlive-courier",
487− "texlive-dvips",
488− "texlive-helvetic",
489− "texlive-makeindex",
490− "texlive-metafont",
491− "texlive-metapost",
492− "texlive-palatino",
493− "texlive-preview",
494− "texlive-times",
495− "texlive-zapfchan",
496− "texlive-zapfding",
497− );
498−
499− $map{"latexmk"} = "texlive-latexmk-bin";
500−
501− # FIXME: add support for installing CJK fonts
502− #
503− # I tried hard, but was unable to find a way to install
504− # "Noto Sans CJK SC" on openSUSE
505−
506− check_rpm_missing(\@suse_tex_pkgs, 2) if ($pdf);
507− check_missing_tex(2) if ($pdf);
508− check_missing(\%map);
509−
510− return if (!$need && !$optional);
511− printf("You should run:\n") if ($verbose_warn_install);
512− printf("\n\tsudo zypper install --no-recommends $install\n");
513−}
514−
515−sub give_mageia_hints()
516−{
517− my %map = (
518− "python-sphinx" => "python3-sphinx",
519− "yaml" => "python3-yaml",
520− "virtualenv" => "python3-virtualenv",
521− "dot" => "graphviz",
522− "convert" => "ImageMagick",
523− "Pod::Usage" => "perl-Pod-Usage",
524− "xelatex" => "texlive",
525− "rsvg-convert" => "librsvg2",
526− );
527−
528− my @tex_pkgs = (
529− "texlive-fontsextra",
530− );
531−
532− $map{"latexmk"} = "texlive-collection-basic";
533−
534− my $packager_cmd;
535− my $noto_sans;
536− if ($system_release =~ /OpenMandriva/) {
537− $packager_cmd = "dnf install";
538− $noto_sans = "noto-sans-cjk-fonts";
539− @tex_pkgs = ( "texlive-collection-fontsextra" );
540− } else {
541− $packager_cmd = "urpmi";
542− $noto_sans = "google-noto-sans-cjk-ttc-fonts";
543− }
544−
545−
546− if ($pdf) {
547− check_missing_file(["/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
548− "/usr/share/fonts/TTF/NotoSans-Regular.ttf"],
549− $noto_sans, 2);
550− }
551−
552− check_rpm_missing(\@tex_pkgs, 2) if ($pdf);
553− check_missing(\%map);
554−
555− return if (!$need && !$optional);
556− printf("You should run:\n") if ($verbose_warn_install);
557− printf("\n\tsudo $packager_cmd $install\n");
558−}
559−
560−sub give_arch_linux_hints()
561−{
562− my %map = (
563− "yaml" => "python-yaml",
564− "virtualenv" => "python-virtualenv",
565− "dot" => "graphviz",
566− "convert" => "imagemagick",
567− "xelatex" => "texlive-xetex",
568− "latexmk" => "texlive-core",
569− "rsvg-convert" => "extra/librsvg",
570− );
571−
572− my @archlinux_tex_pkgs = (
573− "texlive-core",
574− "texlive-latexextra",
575− "ttf-dejavu",
576− );
577− check_pacman_missing(\@archlinux_tex_pkgs, 2) if ($pdf);
578−
579− if ($pdf) {
580− check_missing_file(["/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc"],
581− "noto-fonts-cjk", 2);
582− }
583−
584− check_missing(\%map);
585−
586− return if (!$need && !$optional);
587− printf("You should run:\n") if ($verbose_warn_install);
588− printf("\n\tsudo pacman -S $install\n");
589−}
590−
591−sub give_gentoo_hints()
592−{
593− my %map = (
594− "yaml" => "dev-python/pyyaml",
595− "virtualenv" => "dev-python/virtualenv",
596− "dot" => "media-gfx/graphviz",
597− "convert" => "media-gfx/imagemagick",
598− "xelatex" => "dev-texlive/texlive-xetex media-fonts/dejavu",
599− "rsvg-convert" => "gnome-base/librsvg",
600− );
601−
602− check_missing_file(["/usr/share/fonts/dejavu/DejaVuSans.ttf"],
603− "media-fonts/dejavu", 2) if ($pdf);
604−
605− if ($pdf) {
606− check_missing_file(["/usr/share/fonts/noto-cjk/NotoSansCJKsc-Regular.otf",
607− "/usr/share/fonts/noto-cjk/NotoSerifCJK-Regular.ttc"],
608− "media-fonts/noto-cjk", 2);
609− }
610−
611− check_missing(\%map);
612−
613− return if (!$need && !$optional);
614−
615− printf("You should run:\n") if ($verbose_warn_install);
616− printf("\n");
617−
618− my $imagemagick = "media-gfx/imagemagick svg png";
619− my $cairo = "media-gfx/graphviz cairo pdf";
620− my $portage_imagemagick = "/etc/portage/package.use/imagemagick";
621− my $portage_cairo = "/etc/portage/package.use/graphviz";
622−
623− if (qx(grep imagemagick $portage_imagemagick 2>/dev/null) eq "") {
624− printf("\tsudo su -c 'echo \"$imagemagick\" > $portage_imagemagick'\n")
625− }
626− if (qx(grep graphviz $portage_cairo 2>/dev/null) eq "") {
627− printf("\tsudo su -c 'echo \"$cairo\" > $portage_cairo'\n");
628− }
629−
630− printf("\tsudo emerge --ask $install\n");
631−
632−}
633−
634−sub check_distros()
635−{
636− # Distro-specific hints
637− if ($system_release =~ /Red Hat Enterprise Linux/) {
638− give_redhat_hints;
639− return;
640− }
641− if ($system_release =~ /CentOS/) {
642− give_redhat_hints;
643− return;
644− }
645− if ($system_release =~ /Scientific Linux/) {
646− give_redhat_hints;
647− return;
648− }
649− if ($system_release =~ /Oracle Linux Server/) {
650− give_redhat_hints;
651− return;
652− }
653− if ($system_release =~ /Fedora/) {
654− give_redhat_hints;
655− return;
656− }
657− if ($system_release =~ /Ubuntu/) {
658− give_debian_hints;
659− return;
660− }
661− if ($system_release =~ /Debian/) {
662− give_debian_hints;
663− return;
664− }
665− if ($system_release =~ /openSUSE/) {
666− give_opensuse_hints;
667− return;
668− }
669− if ($system_release =~ /Mageia/) {
670− give_mageia_hints;
671− return;
672− }
673− if ($system_release =~ /OpenMandriva/) {
674− give_mageia_hints;
675− return;
676− }
677− if ($system_release =~ /Arch Linux/) {
678− give_arch_linux_hints;
679− return;
680− }
681− if ($system_release =~ /Gentoo/) {
682− give_gentoo_hints;
683− return;
684− }
685−
686− #
687− # Fall-back to generic hint code for other distros
688− # That's far from ideal, specially for LaTeX dependencies.
689− #
690− my %map = (
691− "sphinx-build" => "sphinx"
692− );
693− check_missing_tex(2) if ($pdf);
694− check_missing(\%map);
695− print "I don't know distro $system_release.\n";
696− print "So, I can't provide you a hint with the install procedure.\n";
697− print "There are likely missing dependencies.\n";
698−}
699−
700−#
701−# Common dependencies
3+# Copyright (c) 2017-2025 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
7024 #
5+# pylint: disable=C0103,C0114,C0115,C0116,C0301,C0302
6+# pylint: disable=R0902,R0904,R0911,R0912,R0914,R0915,R1705,R1710,E1121
7+
8+# Note: this script requires at least Python 3.6 to run.
9+# Don't add changes not compatible with it, it is meant to report
10+# incompatible python versions.
11+
12+"""
13+Dependency checker for Sphinx documentation Kernel build.
14+
15+This module provides tools to check for all required dependencies needed to
16+build documentation using Sphinx, including system packages, Python modules
17+and LaTeX packages for PDF generation.
18+
19+It detect packages for a subset of Linux distributions used by Kernel
20+maintainers, showing hints and missing dependencies.
21+
22+The main class SphinxDependencyChecker handles the dependency checking logic
23+and provides recommendations for installing missing packages. It supports both
24+system package installations and Python virtual environments. By default,
25+system pacage install is recommended.
26+"""
27+
28+import argparse
29+import os
30+import re
31+import subprocess
32+import sys
33+from glob import glob
34+
35+
36+def parse_version(version):
37+ """Convert a major.minor.patch version into a tuple"""
38+ return tuple(int(x) for x in version.split("."))
39+
40+
41+def ver_str(version):
42+ """Returns a version tuple as major.minor.patch"""
43+
44+ return ".".join([str(x) for x in version])
45+
46+
47+RECOMMENDED_VERSION = parse_version("3.4.3")
48+MIN_PYTHON_VERSION = parse_version("3.7")
49+
50+
51+class DepManager:
52+ """
53+ Manage package dependencies. There are three types of dependencies:
54+
55+ - System: dependencies required for docs build;
56+ - Python: python dependencies for a native distro Sphinx install;
57+ - PDF: dependencies needed by PDF builds.
58+
59+ Each dependency can be mandatory or optional. Not installing an optional
60+ dependency won't break the build, but will cause degradation at the
61+ docs output.
62+ """
63+
64+ # Internal types of dependencies. Don't use them outside DepManager class.
65+ _SYS_TYPE = 0
66+ _PHY_TYPE = 1
67+ _PDF_TYPE = 2
68+
69+ # Dependencies visible outside the class.
70+ # The keys are tuple with: (type, is_mandatory flag).
71+ #
72+ # Currently we're not using all optional dep types. Yet, we'll keep all
73+ # possible combinations here. They're not many, and that makes easier
74+ # if later needed and for the name() method below
75+
76+ SYSTEM_MANDATORY = (_SYS_TYPE, True)
77+ PYTHON_MANDATORY = (_PHY_TYPE, True)
78+ PDF_MANDATORY = (_PDF_TYPE, True)
79+
80+ SYSTEM_OPTIONAL = (_SYS_TYPE, False)
81+ PYTHON_OPTIONAL = (_PHY_TYPE, False)
82+ PDF_OPTIONAL = (_PDF_TYPE, True)
83+
84+ def __init__(self, pdf):
85+ """
86+ Initialize internal vars:
87+
88+ - missing: missing dependencies list, containing a distro-independent
89+ name for a missing dependency and its type.
90+ - missing_pkg: ancillary dict containing missing dependencies in
91+ distro namespace, organized by type.
92+ - need: total number of needed dependencies. Never cleaned.
93+ - optional: total number of optional dependencies. Never cleaned.
94+ - pdf: Is PDF support enabled?
95+ """
96+ self.missing = {}
97+ self.missing_pkg = {}
98+ self.need = 0
99+ self.optional = 0
100+ self.pdf = pdf
101+
102+ @staticmethod
103+ def name(dtype):
104+ """
105+ Ancillary routine to output a warn/error message reporting
106+ missing dependencies.
107+ """
108+ if dtype[0] == DepManager._SYS_TYPE:
109+ msg = "build"
110+ elif dtype[0] == DepManager._PHY_TYPE:
111+ msg = "Python"
112+ else:
113+ msg = "PDF"
114+
115+ if dtype[1]:
116+ return f"ERROR: {msg} mandatory deps missing"
117+ else:
118+ return f"Warning: {msg} optional deps missing"
119+
120+ @staticmethod
121+ def is_optional(dtype):
122+ """Ancillary routine to report if a dependency is optional"""
123+ return not dtype[1]
124+
125+ @staticmethod
126+ def is_pdf(dtype):
127+ """Ancillary routine to report if a dependency is for PDF generation"""
128+ if dtype[0] == DepManager._PDF_TYPE:
129+ return True
130+
131+ return False
132+
133+ def add_package(self, package, dtype):
134+ """
135+ Add a package at the self.missing() dictionary.
136+ Doesn't update missing_pkg.
137+ """
138+ is_optional = DepManager.is_optional(dtype)
139+ self.missing[package] = dtype
140+ if is_optional:
141+ self.optional += 1
142+ else:
143+ self.need += 1
144+
145+ def del_package(self, package):
146+ """
147+ Remove a package at the self.missing() dictionary.
148+ Doesn't update missing_pkg.
149+ """
150+ if package in self.missing:
151+ del self.missing[package]
152+
153+ def clear_deps(self):
154+ """
155+ Clear dependencies without changing needed/optional.
156+
157+ This is an ackward way to have a separate section to recommend
158+ a package after system main dependencies.
159+
160+ TODO: rework the logic to prevent needing it.
161+ """
162+
163+ self.missing = {}
164+ self.missing_pkg = {}
165+
166+ def check_missing(self, progs):
167+ """
168+ Update self.missing_pkg, using progs dict to convert from the
169+ agnostic package name to distro-specific one.
170+
171+ Returns an string with the packages to be installed, sorted and
172+ with eventual duplicates removed.
173+ """
174+
175+ self.missing_pkg = {}
176+
177+ for prog, dtype in sorted(self.missing.items()):
178+ # At least on some LTS distros like CentOS 7, texlive doesn't
179+ # provide all packages we need. When such distros are
180+ # detected, we have to disable PDF output.
181+ #
182+ # So, we need to ignore the packages that distros would
183+ # need for LaTeX to work
184+ if DepManager.is_pdf(dtype) and not self.pdf:
185+ self.optional -= 1
186+ continue
187+
188+ if not dtype in self.missing_pkg:
189+ self.missing_pkg[dtype] = []
190+
191+ self.missing_pkg[dtype].append(progs.get(prog, prog))
192+
193+ install = []
194+ for dtype, pkgs in self.missing_pkg.items():
195+ install += pkgs
196+
197+ return " ".join(sorted(set(install)))
198+
199+ def warn_install(self):
200+ """
201+ Emit warnings/errors related to missing packages.
202+ """
203+
204+ output_msg = ""
205+
206+ for dtype in sorted(self.missing_pkg.keys()):
207+ progs = " ".join(sorted(set(self.missing_pkg[dtype])))
208+
209+ try:
210+ name = DepManager.name(dtype)
211+ output_msg += f'{name}:\t{progs}\n'
212+ except KeyError:
213+ raise KeyError(f"ERROR!!!: invalid dtype for {progs}: {dtype}")
214+
215+ if output_msg:
216+ print(f"\n{output_msg}")
217+
218+class AncillaryMethods:
219+ """
220+ Ancillary methods that checks for missing dependencies for different
221+ types of types, like binaries, python modules, rpm deps, etc.
222+ """
223+
224+ @staticmethod
225+ def which(prog):
226+ """
227+ Our own implementation of which(). We could instead use
228+ shutil.which(), but this function is simple enough.
229+ Probably faster to use this implementation than to import shutil.
230+ """
231+ for path in os.environ.get("PATH", "").split(":"):
232+ full_path = os.path.join(path, prog)
233+ if os.access(full_path, os.X_OK):
234+ return full_path
235+
236+ return None
237+
238+ @staticmethod
239+ def get_python_version(cmd):
240+ """
241+ Get python version from a Python binary. As we need to detect if
242+ are out there newer python binaries, we can't rely on sys.release here.
243+ """
244+
245+ result = SphinxDependencyChecker.run([cmd, "--version"],
246+ capture_output=True, text=True)
247+ version = result.stdout.strip()
248+
249+ match = re.search(r"(\d+\.\d+\.\d+)", version)
250+ if match:
251+ return parse_version(match.group(1))
252+
253+ print(f"Can't parse version {version}")
254+ return (0, 0, 0)
255+
256+ @staticmethod
257+ def find_python():
258+ """
259+ Detect if are out there any python 3.xy version newer than the
260+ current one.
261+
262+ Note: this routine is limited to up to 2 digits for python3. We
263+ may need to update it one day, hopefully on a distant future.
264+ """
265+ patterns = [
266+ "python3.[0-9]",
267+ "python3.[0-9][0-9]",
268+ ]
269+
270+ # Seek for a python binary newer than MIN_PYTHON_VERSION
271+ for path in os.getenv("PATH", "").split(":"):
272+ for pattern in patterns:
273+ for cmd in glob(os.path.join(path, pattern)):
274+ if os.path.isfile(cmd) and os.access(cmd, os.X_OK):
275+ version = SphinxDependencyChecker.get_python_version(cmd)
276+ if version >= MIN_PYTHON_VERSION:
277+ return cmd
278+
279+ @staticmethod
280+ def check_python():
281+ """
282+ Check if the current python binary satisfies our minimal requirement
283+ for Sphinx build. If not, re-run with a newer version if found.
284+ """
285+ cur_ver = sys.version_info[:3]
286+ if cur_ver >= MIN_PYTHON_VERSION:
287+ ver = ver_str(cur_ver)
288+ print(f"Python version: {ver}")
289+
290+ # This could be useful for debugging purposes
291+ if SphinxDependencyChecker.which("docutils"):
292+ result = SphinxDependencyChecker.run(["docutils", "--version"],
293+ capture_output=True, text=True)
294+ ver = result.stdout.strip()
295+ match = re.search(r"(\d+\.\d+\.\d+)", ver)
296+ if match:
297+ ver = match.group(1)
298+
299+ print(f"Docutils version: {ver}")
300+
301+ return
302+
303+ python_ver = ver_str(cur_ver)
304+
305+ new_python_cmd = SphinxDependencyChecker.find_python()
306+ if not new_python_cmd:
307+ print(f"ERROR: Python version {python_ver} is not spported anymore\n")
308+ print(" Can't find a new version. This script may fail")
309+ return
310+
311+ # Restart script using the newer version
312+ script_path = os.path.abspath(sys.argv[0])
313+ args = [new_python_cmd, script_path] + sys.argv[1:]
314+
315+ print(f"Python {python_ver} not supported. Changing to {new_python_cmd}")
316+
317+ try:
318+ os.execv(new_python_cmd, args)
319+ except OSError as e:
320+ sys.exit(f"Failed to restart with {new_python_cmd}: {e}")
321+
322+ @staticmethod
323+ def run(*args, **kwargs):
324+ """
325+ Excecute a command, hiding its output by default.
326+ Preserve comatibility with older Python versions.
327+ """
328+
329+ capture_output = kwargs.pop('capture_output', False)
330+
331+ if capture_output:
332+ if 'stdout' not in kwargs:
333+ kwargs['stdout'] = subprocess.PIPE
334+ if 'stderr' not in kwargs:
335+ kwargs['stderr'] = subprocess.PIPE
336+ else:
337+ if 'stdout' not in kwargs:
338+ kwargs['stdout'] = subprocess.DEVNULL
339+ if 'stderr' not in kwargs:
340+ kwargs['stderr'] = subprocess.DEVNULL
341+
342+ # Don't break with older Python versions
343+ if 'text' in kwargs and sys.version_info < (3, 7):
344+ kwargs['universal_newlines'] = kwargs.pop('text')
345+
346+ return subprocess.run(*args, **kwargs)
347+
348+class MissingCheckers(AncillaryMethods):
349+ """
350+ Contains some ancillary checkers for different types of binaries and
351+ package managers.
352+ """
353+
354+ def __init__(self, args, texlive):
355+ """
356+ Initialize its internal variables
357+ """
358+ self.pdf = args.pdf
359+ self.virtualenv = args.virtualenv
360+ self.version_check = args.version_check
361+ self.texlive = texlive
362+
363+ self.min_version = (0, 0, 0)
364+ self.cur_version = (0, 0, 0)
365+
366+ self.deps = DepManager(self.pdf)
367+
368+ self.need_symlink = 0
369+ self.need_sphinx = 0
370+
371+ self.verbose_warn_install = 1
372+
373+ self.virtenv_dir = ""
374+ self.install = ""
375+ self.python_cmd = ""
376+
377+ self.virtenv_prefix = ["sphinx_", "Sphinx_" ]
378+
379+ def check_missing_file(self, files, package, dtype):
380+ """
381+ Does the file exists? If not, add it to missing dependencies.
382+ """
383+ for f in files:
384+ if os.path.exists(f):
385+ return
386+ self.deps.add_package(package, dtype)
387+
388+ def check_program(self, prog, dtype):
389+ """
390+ Does the program exists and it is at the PATH?
391+ If not, add it to missing dependencies.
392+ """
393+ found = self.which(prog)
394+ if found:
395+ return found
396+
397+ self.deps.add_package(prog, dtype)
398+
399+ return None
400+
401+ def check_perl_module(self, prog, dtype):
402+ """
403+ Does perl have a dependency? Is it available?
404+ If not, add it to missing dependencies.
405+
406+ Right now, we still need Perl for doc build, as it is required
407+ by some tools called at docs or kernel build time, like:
408+
409+ scripts/documentation-file-ref-check
410+
411+ Also, checkpatch is on Perl.
412+ """
413+
414+ # While testing with lxc download template, one of the
415+ # distros (Oracle) didn't have perl - nor even an option to install
416+ # before installing oraclelinux-release-el9 package.
417+ #
418+ # Check it before running an error. If perl is not there,
419+ # add it as a mandatory package, as some parts of the doc builder
420+ # needs it.
421+ if not self.which("perl"):
422+ self.deps.add_package("perl", DepManager.SYSTEM_MANDATORY)
423+ self.deps.add_package(prog, dtype)
424+ return
425+
426+ try:
427+ self.run(["perl", f"-M{prog}", "-e", "1"], check=True)
428+ except subprocess.CalledProcessError:
429+ self.deps.add_package(prog, dtype)
430+
431+ def check_python_module(self, module, is_optional=False):
432+ """
433+ Does a python module exists outside venv? If not, add it to missing
434+ dependencies.
435+ """
436+ if is_optional:
437+ dtype = DepManager.PYTHON_OPTIONAL
438+ else:
439+ dtype = DepManager.PYTHON_MANDATORY
440+
441+ try:
442+ self.run([self.python_cmd, "-c", f"import {module}"], check=True)
443+ except subprocess.CalledProcessError:
444+ self.deps.add_package(module, dtype)
445+
446+ def check_rpm_missing(self, pkgs, dtype):
447+ """
448+ Does a rpm package exists? If not, add it to missing dependencies.
449+ """
450+ for prog in pkgs:
451+ try:
452+ self.run(["rpm", "-q", prog], check=True)
453+ except subprocess.CalledProcessError:
454+ self.deps.add_package(prog, dtype)
455+
456+ def check_pacman_missing(self, pkgs, dtype):
457+ """
458+ Does a pacman package exists? If not, add it to missing dependencies.
459+ """
460+ for prog in pkgs:
461+ try:
462+ self.run(["pacman", "-Q", prog], check=True)
463+ except subprocess.CalledProcessError:
464+ self.deps.add_package(prog, dtype)
465+
466+ def check_missing_tex(self, is_optional=False):
467+ """
468+ Does a LaTeX package exists? If not, add it to missing dependencies.
469+ """
470+ if is_optional:
471+ dtype = DepManager.PDF_OPTIONAL
472+ else:
473+ dtype = DepManager.PDF_MANDATORY
474+
475+ kpsewhich = self.which("kpsewhich")
476+ for prog, package in self.texlive.items():
477+
478+ # If kpsewhich is not there, just add it to deps
479+ if not kpsewhich:
480+ self.deps.add_package(package, dtype)
481+ continue
482+
483+ # Check if the package is needed
484+ try:
485+ result = self.run(
486+ [kpsewhich, prog], stdout=subprocess.PIPE, text=True, check=True
487+ )
488+
489+ # Didn't find. Add it
490+ if not result.stdout.strip():
491+ self.deps.add_package(package, dtype)
492+
493+ except subprocess.CalledProcessError:
494+ # kpsewhich returned an error. Add it, just in case
495+ self.deps.add_package(package, dtype)
496+
497+ def get_sphinx_fname(self):
498+ """
499+ Gets the binary filename for sphinx-build.
500+ """
501+ if "SPHINXBUILD" in os.environ:
502+ return os.environ["SPHINXBUILD"]
503+
504+ fname = "sphinx-build"
505+ if self.which(fname):
506+ return fname
507+
508+ fname = "sphinx-build-3"
509+ if self.which(fname):
510+ self.need_symlink = 1
511+ return fname
512+
513+ return ""
514+
515+ def get_sphinx_version(self, cmd):
516+ """
517+ Gets sphinx-build version.
518+ """
519+ try:
520+ result = self.run([cmd, "--version"],
521+ stdout=subprocess.PIPE,
522+ stderr=subprocess.STDOUT,
523+ text=True, check=True)
524+ except (subprocess.CalledProcessError, FileNotFoundError):
525+ return None
526+
527+ for line in result.stdout.split("\n"):
528+ match = re.match(r"^sphinx-build\s+([\d\.]+)(?:\+(?:/[\da-f]+)|b\d+)?\s*$", line)
529+ if match:
530+ return parse_version(match.group(1))
531+
532+ match = re.match(r"^Sphinx.*\s+([\d\.]+)\s*$", line)
533+ if match:
534+ return parse_version(match.group(1))
535+
536+ def check_sphinx(self, conf):
537+ """
538+ Checks Sphinx minimal requirements
539+ """
540+ try:
541+ with open(conf, "r", encoding="utf-8") as f:
542+ for line in f:
543+ match = re.match(r"^\s*needs_sphinx\s*=\s*[\'\"]([\d\.]+)[\'\"]", line)
544+ if match:
545+ self.min_version = parse_version(match.group(1))
546+ break
547+ except IOError:
548+ sys.exit(f"Can't open {conf}")
549+
550+ if not self.min_version:
551+ sys.exit(f"Can't get needs_sphinx version from {conf}")
552+
553+ self.virtenv_dir = self.virtenv_prefix[0] + "latest"
554+
555+ sphinx = self.get_sphinx_fname()
556+ if not sphinx:
557+ self.need_sphinx = 1
558+ return
559+
560+ self.cur_version = self.get_sphinx_version(sphinx)
561+ if not self.cur_version:
562+ sys.exit(f"{sphinx} didn't return its version")
563+
564+ if self.cur_version < self.min_version:
565+ curver = ver_str(self.cur_version)
566+ minver = ver_str(self.min_version)
567+
568+ print(f"ERROR: Sphinx version is {curver}. It should be >= {minver}")
569+ self.need_sphinx = 1
570+ return
571+
572+ # On version check mode, just assume Sphinx has all mandatory deps
573+ if self.version_check and self.cur_version >= RECOMMENDED_VERSION:
574+ sys.exit(0)
575+
576+ def catcheck(self, filename):
577+ """
578+ Reads a file if it exists, returning as string.
579+ If not found, returns an empty string.
580+ """
581+ if os.path.exists(filename):
582+ with open(filename, "r", encoding="utf-8") as f:
583+ return f.read().strip()
584+ return ""
585+
586+ def get_system_release(self):
587+ """
588+ Determine the system type. There's no unique way that would work
589+ with all distros with a minimal package install. So, several
590+ methods are used here.
591+
592+ By default, it will use lsb_release function. If not available, it will
593+ fail back to reading the known different places where the distro name
594+ is stored.
595+
596+ Several modern distros now have /etc/os-release, which usually have
597+ a decent coverage.
598+ """
599+
600+ system_release = ""
601+
602+ if self.which("lsb_release"):
603+ result = self.run(["lsb_release", "-d"], capture_output=True, text=True)
604+ system_release = result.stdout.replace("Description:", "").strip()
605+
606+ release_files = [
607+ "/etc/system-release",
608+ "/etc/redhat-release",
609+ "/etc/lsb-release",
610+ "/etc/gentoo-release",
611+ ]
612+
613+ if not system_release:
614+ for f in release_files:
615+ system_release = self.catcheck(f)
616+ if system_release:
617+ break
618+
619+ # This seems more common than LSB these days
620+ if not system_release:
621+ os_var = {}
622+ try:
623+ with open("/etc/os-release", "r", encoding="utf-8") as f:
624+ for line in f:
625+ match = re.match(r"^([\w\d\_]+)=\"?([^\"]*)\"?\n", line)
626+ if match:
627+ os_var[match.group(1)] = match.group(2)
628+
629+ system_release = os_var.get("NAME", "")
630+ if "VERSION_ID" in os_var:
631+ system_release += " " + os_var["VERSION_ID"]
632+ elif "VERSION" in os_var:
633+ system_release += " " + os_var["VERSION"]
634+ except IOError:
635+ pass
636+
637+ if not system_release:
638+ system_release = self.catcheck("/etc/issue")
639+
640+ system_release = system_release.strip()
641+
642+ return system_release
643+
644+class SphinxDependencyChecker(MissingCheckers):
645+ """
646+ Main class for checking Sphinx documentation build dependencies.
647+
648+ - Check for missing system packages;
649+ - Check for missing Python modules;
650+ - Check for missing LaTeX packages needed by PDF generation;
651+ - Propose Sphinx install via Python Virtual environment;
652+ - Propose Sphinx install via distro-specific package install.
653+ """
654+ def __init__(self, args):
655+ """Initialize checker variables"""
656+
657+ # List of required texlive packages on Fedora and OpenSuse
658+ texlive = {
659+ "amsfonts.sty": "texlive-amsfonts",
660+ "amsmath.sty": "texlive-amsmath",
661+ "amssymb.sty": "texlive-amsfonts",
662+ "amsthm.sty": "texlive-amscls",
663+ "anyfontsize.sty": "texlive-anyfontsize",
664+ "atbegshi.sty": "texlive-oberdiek",
665+ "bm.sty": "texlive-tools",
666+ "capt-of.sty": "texlive-capt-of",
667+ "cmap.sty": "texlive-cmap",
668+ "ctexhook.sty": "texlive-ctex",
669+ "ecrm1000.tfm": "texlive-ec",
670+ "eqparbox.sty": "texlive-eqparbox",
671+ "eu1enc.def": "texlive-euenc",
672+ "fancybox.sty": "texlive-fancybox",
673+ "fancyvrb.sty": "texlive-fancyvrb",
674+ "float.sty": "texlive-float",
675+ "fncychap.sty": "texlive-fncychap",
676+ "footnote.sty": "texlive-mdwtools",
677+ "framed.sty": "texlive-framed",
678+ "luatex85.sty": "texlive-luatex85",
679+ "multirow.sty": "texlive-multirow",
680+ "needspace.sty": "texlive-needspace",
681+ "palatino.sty": "texlive-psnfss",
682+ "parskip.sty": "texlive-parskip",
683+ "polyglossia.sty": "texlive-polyglossia",
684+ "tabulary.sty": "texlive-tabulary",
685+ "threeparttable.sty": "texlive-threeparttable",
686+ "titlesec.sty": "texlive-titlesec",
687+ "ucs.sty": "texlive-ucs",
688+ "upquote.sty": "texlive-upquote",
689+ "wrapfig.sty": "texlive-wrapfig",
690+ }
691+
692+ super().__init__(args, texlive)
693+
694+ self.need_pip = False
695+ self.rec_sphinx_upgrade = 0
696+
697+ self.system_release = self.get_system_release()
698+ self.activate_cmd = ""
699+
700+ # Some distros may not have a Sphinx shipped package compatible with
701+ # our minimal requirements
702+ self.package_supported = True
703+
704+ # Recommend a new python version
705+ self.recommend_python = None
706+
707+ # Certain hints are meant to be shown only once
708+ self.distro_msg = None
709+
710+ self.latest_avail_ver = (0, 0, 0)
711+ self.venv_ver = (0, 0, 0)
712+
713+ prefix = os.environ.get("srctree", ".") + "/"
714+
715+ self.conf = prefix + "Documentation/conf.py"
716+ self.requirement_file = prefix + "Documentation/sphinx/requirements.txt"
717+
718+ def get_install_progs(self, progs, cmd, extra=None):
719+ """
720+ Check for missing dependencies using the provided program mapping.
721+
722+ The actual distro-specific programs are mapped via progs argument.
723+ """
724+ install = self.deps.check_missing(progs)
725+
726+ if self.verbose_warn_install:
727+ self.deps.warn_install()
728+
729+ if not install:
730+ return
731+
732+ if cmd:
733+ if self.verbose_warn_install:
734+ msg = "You should run:"
735+ else:
736+ msg = ""
737+
738+ if extra:
739+ msg += "\n\t" + extra.replace("\n", "\n\t")
740+
741+ return(msg + "\n\tsudo " + cmd + " " + install)
742+
743+ return None
744+
745+ #
746+ # Distro-specific hints methods
747+ #
748+
749+ def give_debian_hints(self):
750+ """
751+ Provide package installation hints for Debian-based distros.
752+ """
753+ progs = {
754+ "Pod::Usage": "perl-modules",
755+ "convert": "imagemagick",
756+ "dot": "graphviz",
757+ "ensurepip": "python3-venv",
758+ "python-sphinx": "python3-sphinx",
759+ "rsvg-convert": "librsvg2-bin",
760+ "virtualenv": "virtualenv",
761+ "xelatex": "texlive-xetex",
762+ "yaml": "python3-yaml",
763+ }
764+
765+ if self.pdf:
766+ pdf_pkgs = {
767+ "fonts-dejavu": [
768+ "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
769+ ],
770+ "fonts-noto-cjk": [
771+ "/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
772+ "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
773+ "/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc",
774+ ],
775+ "tex-gyre": [
776+ "/usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty"
777+ ],
778+ "texlive-fonts-recommended": [
779+ "/usr/share/texlive/texmf-dist/fonts/tfm/adobe/zapfding/pzdr.tfm",
780+ ],
781+ "texlive-lang-chinese": [
782+ "/usr/share/texlive/texmf-dist/tex/latex/ctex/ctexhook.sty",
783+ ],
784+ }
785+
786+ for package, files in pdf_pkgs.items():
787+ self.check_missing_file(files, package, DepManager.PDF_MANDATORY)
788+
789+ self.check_program("dvipng", DepManager.PDF_MANDATORY)
790+
791+ if not self.distro_msg:
792+ self.distro_msg = \
793+ "Note: ImageMagick is broken on some distros, affecting PDF output. For more details:\n" \
794+ "\thttps://askubuntu.com/questions/1158894/imagemagick-still-broken-using-with-usr-bin-convert"
795+
796+ return self.get_install_progs(progs, "apt-get install")
797+
798+ def give_redhat_hints(self):
799+ """
800+ Provide package installation hints for RedHat-based distros
801+ (Fedora, RHEL and RHEL-based variants).
802+ """
803+ progs = {
804+ "Pod::Usage": "perl-Pod-Usage",
805+ "convert": "ImageMagick",
806+ "dot": "graphviz",
807+ "python-sphinx": "python3-sphinx",
808+ "rsvg-convert": "librsvg2-tools",
809+ "virtualenv": "python3-virtualenv",
810+ "xelatex": "texlive-xetex-bin",
811+ "yaml": "python3-pyyaml",
812+ }
813+
814+ fedora_tex_pkgs = [
815+ "dejavu-sans-fonts",
816+ "dejavu-sans-mono-fonts",
817+ "dejavu-serif-fonts",
818+ "texlive-collection-fontsrecommended",
819+ "texlive-collection-latex",
820+ "texlive-xecjk",
821+ ]
822+
823+ fedora = False
824+ rel = None
825+
826+ match = re.search(r"(release|Linux)\s+(\d+)", self.system_release)
827+ if match:
828+ rel = int(match.group(2))
829+
830+ if not rel:
831+ print("Couldn't identify release number")
832+ noto_sans_redhat = None
833+ self.pdf = False
834+ elif re.search("Fedora", self.system_release):
835+ # Fedora 38 and upper use this CJK font
836+
837+ noto_sans_redhat = "google-noto-sans-cjk-fonts"
838+ fedora = True
839+ else:
840+ # Almalinux, CentOS, RHEL, ...
841+
842+ # at least up to version 9 (and Fedora < 38), that's the CJK font
843+ noto_sans_redhat = "google-noto-sans-cjk-ttc-fonts"
844+
845+ progs["virtualenv"] = "python-virtualenv"
846+
847+ if not rel or rel < 8:
848+ print("ERROR: Distro not supported. Too old?")
849+ return
850+
851+ # RHEL 8 uses Python 3.6, which is not compatible with
852+ # the build system anymore. Suggest Python 3.11
853+ if rel == 8:
854+ self.check_program("python3.9", DepManager.SYSTEM_MANDATORY)
855+ progs["python3.9"] = "python39"
856+ progs["yaml"] = "python39-pyyaml"
857+
858+ self.recommend_python = True
859+
860+ # There's no python39-sphinx package. Only pip is supported
861+ self.package_supported = False
862+
863+ if not self.distro_msg:
864+ self.distro_msg = \
865+ "Note: RHEL-based distros typically require extra repositories.\n" \
866+ "For most, enabling epel and crb are enough:\n" \
867+ "\tsudo dnf install -y epel-release\n" \
868+ "\tsudo dnf config-manager --set-enabled crb\n" \
869+ "Yet, some may have other required repositories. Those commands could be useful:\n" \
870+ "\tsudo dnf repolist all\n" \
871+ "\tsudo dnf repoquery --available --info <pkgs>\n" \
872+ "\tsudo dnf config-manager --set-enabled '*' # enable all - probably not what you want"
873+
874+ if self.pdf:
875+ pdf_pkgs = [
876+ "/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
877+ "/usr/share/fonts/google-noto-sans-cjk-fonts/NotoSansCJK-Regular.ttc",
878+ ]
879+
880+ self.check_missing_file(pdf_pkgs, noto_sans_redhat, DepManager.PDF_MANDATORY)
881+
882+ self.check_rpm_missing(fedora_tex_pkgs, DepManager.PDF_MANDATORY)
883+
884+ self.check_missing_tex(DepManager.PDF_MANDATORY)
885+
886+ # There's no texlive-ctex on RHEL 8 repositories. This will
887+ # likely affect CJK pdf build only.
888+ if not fedora and rel == 8:
889+ self.deps.del_package("texlive-ctex")
890+
891+ return self.get_install_progs(progs, "dnf install")
892+
893+ def give_opensuse_hints(self):
894+ """
895+ Provide package installation hints for openSUSE-based distros
896+ (Leap and Tumbleweed).
897+ """
898+ progs = {
899+ "Pod::Usage": "perl-Pod-Usage",
900+ "convert": "ImageMagick",
901+ "dot": "graphviz",
902+ "python-sphinx": "python3-sphinx",
903+ "virtualenv": "python3-virtualenv",
904+ "xelatex": "texlive-xetex-bin texlive-dejavu",
905+ "yaml": "python3-pyyaml",
906+ }
907+
908+ suse_tex_pkgs = [
909+ "texlive-babel-english",
910+ "texlive-caption",
911+ "texlive-colortbl",
912+ "texlive-courier",
913+ "texlive-dvips",
914+ "texlive-helvetic",
915+ "texlive-makeindex",
916+ "texlive-metafont",
917+ "texlive-metapost",
918+ "texlive-palatino",
919+ "texlive-preview",
920+ "texlive-times",
921+ "texlive-zapfchan",
922+ "texlive-zapfding",
923+ ]
924+
925+ progs["latexmk"] = "texlive-latexmk-bin"
926+
927+ match = re.search(r"(Leap)\s+(\d+).(\d)", self.system_release)
928+ if match:
929+ rel = int(match.group(2))
930+
931+ # Leap 15.x uses Python 3.6, which is not compatible with
932+ # the build system anymore. Suggest Python 3.11
933+ if rel == 15:
934+ if not self.which(self.python_cmd):
935+ self.check_program("python3.11", DepManager.SYSTEM_MANDATORY)
936+ progs["python3.11"] = "python311"
937+ self.recommend_python = True
938+
939+ progs.update({
940+ "python-sphinx": "python311-Sphinx python311-Sphinx-latex",
941+ "virtualenv": "python311-virtualenv",
942+ "yaml": "python311-PyYAML",
943+ })
944+ else:
945+ # Tumbleweed defaults to Python 3.11
946+
947+ progs.update({
948+ "python-sphinx": "python313-Sphinx python313-Sphinx-latex",
949+ "virtualenv": "python313-virtualenv",
950+ "yaml": "python313-PyYAML",
951+ })
952+
953+ # FIXME: add support for installing CJK fonts
954+ #
955+ # I tried hard, but was unable to find a way to install
956+ # "Noto Sans CJK SC" on openSUSE
957+
958+ if self.pdf:
959+ self.check_rpm_missing(suse_tex_pkgs, DepManager.PDF_MANDATORY)
960+ if self.pdf:
961+ self.check_missing_tex()
962+
963+ return self.get_install_progs(progs, "zypper install --no-recommends")
964+
965+ def give_mageia_hints(self):
966+ """
967+ Provide package installation hints for Mageia and OpenMandriva.
968+ """
969+ progs = {
970+ "Pod::Usage": "perl-Pod-Usage",
971+ "convert": "ImageMagick",
972+ "dot": "graphviz",
973+ "python-sphinx": "python3-sphinx",
974+ "rsvg-convert": "librsvg2",
975+ "virtualenv": "python3-virtualenv",
976+ "xelatex": "texlive",
977+ "yaml": "python3-yaml",
978+ }
979+
980+ tex_pkgs = [
981+ "texlive-fontsextra",
982+ "texlive-fonts-asian",
983+ "fonts-ttf-dejavu",
984+ ]
985+
986+ if re.search(r"OpenMandriva", self.system_release):
987+ packager_cmd = "dnf install"
988+ noto_sans = "noto-sans-cjk-fonts"
989+ tex_pkgs = [
990+ "texlive-collection-basic",
991+ "texlive-collection-langcjk",
992+ "texlive-collection-fontsextra",
993+ "texlive-collection-fontsrecommended"
994+ ]
995+
996+ # Tested on OpenMandriva Lx 4.3
997+ progs["convert"] = "imagemagick"
998+ progs["yaml"] = "python-pyyaml"
999+ progs["python-virtualenv"] = "python-virtualenv"
1000+ progs["python-sphinx"] = "python-sphinx"
1001+ progs["xelatex"] = "texlive"
1002+
1003+ self.check_program("python-virtualenv", DepManager.PYTHON_MANDATORY)
1004+
1005+ # On my tests with openMandriva LX 4.0 docker image, upgraded
1006+ # to 4.3, python-virtualenv package is broken: it is missing
1007+ # ensurepip. Without it, the alternative would be to run:
1008+ # python3 -m venv --without-pip ~/sphinx_latest, but running
1009+ # pip there won't install sphinx at venv.
1010+ #
1011+ # Add a note about that.
1012+
1013+ if not self.distro_msg:
1014+ self.distro_msg = \
1015+ "Notes:\n"\
1016+ "1. for venv, ensurepip could be broken, preventing its install method.\n" \
1017+ "2. at least on OpenMandriva LX 4.3, texlive packages seem broken"
1018+
1019+ else:
1020+ packager_cmd = "urpmi"
1021+ noto_sans = "google-noto-sans-cjk-ttc-fonts"
1022+
1023+ progs["latexmk"] = "texlive-collection-basic"
1024+
1025+ if self.pdf:
1026+ pdf_pkgs = [
1027+ "/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
1028+ "/usr/share/fonts/TTF/NotoSans-Regular.ttf",
1029+ ]
1030+
1031+ self.check_missing_file(pdf_pkgs, noto_sans, DepManager.PDF_MANDATORY)
1032+ self.check_rpm_missing(tex_pkgs, DepManager.PDF_MANDATORY)
1033+
1034+ return self.get_install_progs(progs, packager_cmd)
1035+
1036+ def give_arch_linux_hints(self):
1037+ """
1038+ Provide package installation hints for ArchLinux.
1039+ """
1040+ progs = {
1041+ "convert": "imagemagick",
1042+ "dot": "graphviz",
1043+ "latexmk": "texlive-core",
1044+ "rsvg-convert": "extra/librsvg",
1045+ "virtualenv": "python-virtualenv",
1046+ "xelatex": "texlive-xetex",
1047+ "yaml": "python-yaml",
1048+ }
1049+
1050+ archlinux_tex_pkgs = [
1051+ "texlive-basic",
1052+ "texlive-binextra",
1053+ "texlive-core",
1054+ "texlive-fontsrecommended",
1055+ "texlive-langchinese",
1056+ "texlive-langcjk",
1057+ "texlive-latexextra",
1058+ "ttf-dejavu",
1059+ ]
1060+
1061+ if self.pdf:
1062+ self.check_pacman_missing(archlinux_tex_pkgs,
1063+ DepManager.PDF_MANDATORY)
1064+
1065+ self.check_missing_file(["/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc"],
1066+ "noto-fonts-cjk",
1067+ DepManager.PDF_MANDATORY)
1068+
1069+
1070+ return self.get_install_progs(progs, "pacman -S")
1071+
1072+ def give_gentoo_hints(self):
1073+ """
1074+ Provide package installation hints for Gentoo.
1075+ """
1076+ texlive_deps = [
1077+ "dev-texlive/texlive-fontsrecommended",
1078+ "dev-texlive/texlive-latexextra",
1079+ "dev-texlive/texlive-xetex",
1080+ "media-fonts/dejavu",
1081+ ]
1082+
1083+ progs = {
1084+ "convert": "media-gfx/imagemagick",
1085+ "dot": "media-gfx/graphviz",
1086+ "rsvg-convert": "gnome-base/librsvg",
1087+ "virtualenv": "dev-python/virtualenv",
1088+ "xelatex": " ".join(texlive_deps),
1089+ "yaml": "dev-python/pyyaml",
1090+ "python-sphinx": "dev-python/sphinx",
1091+ }
1092+
1093+ if self.pdf:
1094+ pdf_pkgs = {
1095+ "media-fonts/dejavu": [
1096+ "/usr/share/fonts/dejavu/DejaVuSans.ttf",
1097+ ],
1098+ "media-fonts/noto-cjk": [
1099+ "/usr/share/fonts/noto-cjk/NotoSansCJKsc-Regular.otf",
1100+ "/usr/share/fonts/noto-cjk/NotoSerifCJK-Regular.ttc",
1101+ ],
1102+ }
1103+ for package, files in pdf_pkgs.items():
1104+ self.check_missing_file(files, package, DepManager.PDF_MANDATORY)
1105+
1106+ # Handling dependencies is a nightmare, as Gentoo refuses to emerge
1107+ # some packages if there's no package.use file describing them.
1108+ # To make it worse, compilation flags shall also be present there
1109+ # for some packages. If USE is not perfect, error/warning messages
1110+ # like those are shown:
1111+ #
1112+ # !!! The following binary packages have been ignored due to non matching USE:
1113+ #
1114+ # =media-gfx/graphviz-12.2.1-r1 X pdf -python_single_target_python3_13 qt6 svg
1115+ # =media-gfx/graphviz-12.2.1-r1 X pdf python_single_target_python3_12 -python_single_target_python3_13 qt6 svg
1116+ # =media-gfx/graphviz-12.2.1-r1 X pdf qt6 svg
1117+ # =media-gfx/graphviz-12.2.1-r1 X pdf -python_single_target_python3_10 qt6 svg
1118+ # =media-gfx/graphviz-12.2.1-r1 X pdf -python_single_target_python3_10 python_single_target_python3_12 -python_single_target_python3_13 qt6 svg
1119+ # =media-fonts/noto-cjk-20190416 X
1120+ # =app-text/texlive-core-2024-r1 X cjk -xetex
1121+ # =app-text/texlive-core-2024-r1 X -xetex
1122+ # =app-text/texlive-core-2024-r1 -xetex
1123+ # =dev-libs/zziplib-0.13.79-r1 sdl
1124+ #
1125+ # And will ignore such packages, installing the remaining ones. That
1126+ # affects mostly the image extension and PDF generation.
1127+
1128+ # Package dependencies and the minimal needed args:
1129+ portages = {
1130+ "graphviz": "media-gfx/graphviz",
1131+ "imagemagick": "media-gfx/imagemagick",
1132+ "media-libs": "media-libs/harfbuzz icu",
1133+ "media-fonts": "media-fonts/noto-cjk",
1134+ "texlive": "app-text/texlive-core xetex",
1135+ "zziblib": "dev-libs/zziplib sdl",
1136+ }
1137+
1138+ extra_cmds = ""
1139+ if not self.distro_msg:
1140+ self.distro_msg = "Note: Gentoo requires package.use to be adjusted before emerging packages"
1141+
1142+ use_base = "/etc/portage/package.use"
1143+ files = glob(f"{use_base}/*")
1144+
1145+ for fname, portage in portages.items():
1146+ install = False
1147+
1148+ while install is False:
1149+ if not files:
1150+ # No files under package.usage. Install all
1151+ install = True
1152+ break
1153+
1154+ args = portage.split(" ")
1155+
1156+ name = args.pop(0)
1157+
1158+ cmd = ["grep", "-l", "-E", rf"^{name}\b" ] + files
1159+ result = self.run(cmd, stdout=subprocess.PIPE, text=True)
1160+ if result.returncode or not result.stdout.strip():
1161+ # File containing portage name not found
1162+ install = True
1163+ break
1164+
1165+ # Ensure that needed USE flags are present
1166+ if args:
1167+ match_fname = result.stdout.strip()
1168+ with open(match_fname, 'r', encoding='utf8',
1169+ errors='backslashreplace') as fp:
1170+ for line in fp:
1171+ for arg in args:
1172+ if arg.startswith("-"):
1173+ continue
1174+
1175+ if not re.search(rf"\s*{arg}\b", line):
1176+ # Needed file argument not found
1177+ install = True
1178+ break
1179+
1180+ # Everything looks ok, don't install
1181+ break
1182+
1183+ # emit a code to setup missing USE
1184+ if install:
1185+ extra_cmds += (f"sudo su -c 'echo \"{portage}\" > {use_base}/{fname}'\n")
1186+
1187+ # Now, we can use emerge and let it respect USE
1188+ return self.get_install_progs(progs,
1189+ "emerge --ask --changed-use --binpkg-respect-use=y",
1190+ extra_cmds)
1191+
1192+ def get_install(self):
1193+ """
1194+ OS-specific hints logic. Seeks for a hinter. If found, use it to
1195+ provide package-manager specific install commands.
1196+
1197+ Otherwise, outputs install instructions for the meta-packages.
1198+
1199+ Returns a string with the command to be executed to install the
1200+ the needed packages, if distro found. Otherwise, return just a
1201+ list of packages that require installation.
1202+ """
1203+ os_hints = {
1204+ re.compile("Red Hat Enterprise Linux"): self.give_redhat_hints,
1205+ re.compile("Fedora"): self.give_redhat_hints,
1206+ re.compile("AlmaLinux"): self.give_redhat_hints,
1207+ re.compile("Amazon Linux"): self.give_redhat_hints,
1208+ re.compile("CentOS"): self.give_redhat_hints,
1209+ re.compile("openEuler"): self.give_redhat_hints,
1210+ re.compile("Oracle Linux Server"): self.give_redhat_hints,
1211+ re.compile("Rocky Linux"): self.give_redhat_hints,
1212+ re.compile("Springdale Open Enterprise"): self.give_redhat_hints,
1213+
1214+ re.compile("Ubuntu"): self.give_debian_hints,
1215+ re.compile("Debian"): self.give_debian_hints,
1216+ re.compile("Devuan"): self.give_debian_hints,
1217+ re.compile("Kali"): self.give_debian_hints,
1218+ re.compile("Mint"): self.give_debian_hints,
1219+
1220+ re.compile("openSUSE"): self.give_opensuse_hints,
1221+
1222+ re.compile("Mageia"): self.give_mageia_hints,
1223+ re.compile("OpenMandriva"): self.give_mageia_hints,
1224+
1225+ re.compile("Arch Linux"): self.give_arch_linux_hints,
1226+ re.compile("Gentoo"): self.give_gentoo_hints,
1227+ }
1228+
1229+ # If the OS is detected, use per-OS hint logic
1230+ for regex, os_hint in os_hints.items():
1231+ if regex.search(self.system_release):
1232+ return os_hint()
1233+
1234+ #
1235+ # Fall-back to generic hint code for other distros
1236+ # That's far from ideal, specially for LaTeX dependencies.
1237+ #
1238+ progs = {"sphinx-build": "sphinx"}
1239+ if self.pdf:
1240+ self.check_missing_tex()
1241+
1242+ self.distro_msg = \
1243+ f"I don't know distro {self.system_release}.\n" \
1244+ "So, I can't provide you a hint with the install procedure.\n" \
1245+ "There are likely missing dependencies."
1246+
1247+ return self.get_install_progs(progs, None)
1248+
1249+ #
1250+ # Common dependencies
1251+ #
1252+ def deactivate_help(self):
1253+ """
1254+ Print a helper message to disable a virtual environment.
1255+ """
1256+
1257+ print("\n If you want to exit the virtualenv, you can use:")
1258+ print("\tdeactivate")
1259+
1260+ def get_virtenv(self):
1261+ """
1262+ Give a hint about how to activate an already-existing virtual
1263+ environment containing sphinx-build.
1264+
1265+ Returns a tuble with (activate_cmd_path, sphinx_version) with
1266+ the newest available virtual env.
1267+ """
1268+
1269+ cwd = os.getcwd()
1270+
1271+ activates = []
1272+
1273+ # Add all sphinx prefixes with possible version numbers
1274+ for p in self.virtenv_prefix:
1275+ activates += glob(f"{cwd}/{p}[0-9]*/bin/activate")
1276+
1277+ activates.sort(reverse=True, key=str.lower)
1278+
1279+ # Place sphinx_latest first, if it exists
1280+ for p in self.virtenv_prefix:
1281+ activates = glob(f"{cwd}/{p}*latest/bin/activate") + activates
1282+
1283+ ver = (0, 0, 0)
1284+ for f in activates:
1285+ # Discard too old Sphinx virtual environments
1286+ match = re.search(r"(\d+)\.(\d+)\.(\d+)", f)
1287+ if match:
1288+ ver = (int(match.group(1)), int(match.group(2)), int(match.group(3)))
1289+
1290+ if ver < self.min_version:
1291+ continue
1292+
1293+ sphinx_cmd = f.replace("activate", "sphinx-build")
1294+ if not os.path.isfile(sphinx_cmd):
1295+ continue
1296+
1297+ ver = self.get_sphinx_version(sphinx_cmd)
1298+
1299+ if not ver:
1300+ venv_dir = f.replace("/bin/activate", "")
1301+ print(f"Warning: virtual environment {venv_dir} is not working.\n" \
1302+ "Python version upgrade? Remove it with:\n\n" \
1303+ "\trm -rf {venv_dir}\n\n")
1304+ else:
1305+ if self.need_sphinx and ver >= self.min_version:
1306+ return (f, ver)
1307+ elif parse_version(ver) > self.cur_version:
1308+ return (f, ver)
1309+
1310+ return ("", ver)
1311+
1312+ def recommend_sphinx_upgrade(self):
1313+ """
1314+ Check if Sphinx needs to be upgraded.
1315+
1316+ Returns a tuple with the higest available Sphinx version if found.
1317+ Otherwise, returns None to indicate either that no upgrade is needed
1318+ or no venv was found.
1319+ """
1320+
1321+ # Avoid running sphinx-builds from venv if cur_version is good
1322+ if self.cur_version and self.cur_version >= RECOMMENDED_VERSION:
1323+ self.latest_avail_ver = self.cur_version
1324+ return None
1325+
1326+ # Get the highest version from sphinx_*/bin/sphinx-build and the
1327+ # corresponding command to activate the venv/virtenv
1328+ self.activate_cmd, self.venv_ver = self.get_virtenv()
1329+
1330+ # Store the highest version from Sphinx existing virtualenvs
1331+ if self.activate_cmd and self.venv_ver > self.cur_version:
1332+ self.latest_avail_ver = self.venv_ver
1333+ else:
1334+ if self.cur_version:
1335+ self.latest_avail_ver = self.cur_version
1336+ else:
1337+ self.latest_avail_ver = (0, 0, 0)
1338+
1339+ # As we don't know package version of Sphinx, and there's no
1340+ # virtual environments, don't check if upgrades are needed
1341+ if not self.virtualenv:
1342+ if not self.latest_avail_ver:
1343+ return None
1344+
1345+ return self.latest_avail_ver
1346+
1347+ # Either there are already a virtual env or a new one should be created
1348+ self.need_pip = True
1349+
1350+ if not self.latest_avail_ver:
1351+ return None
1352+
1353+ # Return if the reason is due to an upgrade or not
1354+ if self.latest_avail_ver != (0, 0, 0):
1355+ if self.latest_avail_ver < RECOMMENDED_VERSION:
1356+ self.rec_sphinx_upgrade = 1
1357+
1358+ return self.latest_avail_ver
1359+
1360+ def recommend_package(self):
1361+ """
1362+ Recommend installing Sphinx as a distro-specific package.
1363+ """
1364+
1365+ print("\n2) As a package with:")
1366+
1367+ old_need = self.deps.need
1368+ old_optional = self.deps.optional
1369+
1370+ self.pdf = False
1371+ self.deps.optional = 0
1372+ old_verbose = self.verbose_warn_install
1373+ self.verbose_warn_install = 0
1374+
1375+ self.deps.clear_deps()
1376+
1377+ self.deps.add_package("python-sphinx", DepManager.PYTHON_MANDATORY)
1378+
1379+ cmd = self.get_install()
1380+ if cmd:
1381+ print(cmd)
1382+
1383+ self.deps.need = old_need
1384+ self.deps.optional = old_optional
1385+ self.verbose_warn_install = old_verbose
1386+
1387+ def recommend_sphinx_version(self, virtualenv_cmd):
1388+ """
1389+ Provide recommendations for installing or upgrading Sphinx based
1390+ on current version.
1391+
1392+ The logic here is complex, as it have to deal with different versions:
1393+
1394+ - minimal supported version;
1395+ - minimal PDF version;
1396+ - recommended version.
1397+
1398+ It also needs to work fine with both distro's package and
1399+ venv/virtualenv
1400+ """
1401+
1402+ if self.recommend_python:
1403+ cur_ver = sys.version_info[:3]
1404+ if cur_ver < MIN_PYTHON_VERSION:
1405+ print(f"\nPython version {cur_ver} is incompatible with doc build.\n" \
1406+ "Please upgrade it and re-run.\n")
1407+ return
1408+
1409+ # Version is OK. Nothing to do.
1410+ if self.cur_version != (0, 0, 0) and self.cur_version >= RECOMMENDED_VERSION:
1411+ return
1412+
1413+ if self.latest_avail_ver:
1414+ latest_avail_ver = ver_str(self.latest_avail_ver)
1415+
1416+ if not self.need_sphinx:
1417+ # sphinx-build is present and its version is >= $min_version
1418+
1419+ # only recommend enabling a newer virtenv version if makes sense.
1420+ if self.latest_avail_ver and self.latest_avail_ver > self.cur_version:
1421+ print(f"\nYou may also use the newer Sphinx version {latest_avail_ver} with:")
1422+ if f"{self.virtenv_prefix}" in os.getcwd():
1423+ print("\tdeactivate")
1424+ print(f"\t. {self.activate_cmd}")
1425+ self.deactivate_help()
1426+ return
1427+
1428+ if self.latest_avail_ver and self.latest_avail_ver >= RECOMMENDED_VERSION:
1429+ return
1430+
1431+ if not self.virtualenv:
1432+ # No sphinx either via package or via virtenv. As we can't
1433+ # Compare the versions here, just return, recommending the
1434+ # user to install it from the package distro.
1435+ if not self.latest_avail_ver or self.latest_avail_ver == (0, 0, 0):
1436+ return
1437+
1438+ # User doesn't want a virtenv recommendation, but he already
1439+ # installed one via virtenv with a newer version.
1440+ # So, print commands to enable it
1441+ if self.latest_avail_ver > self.cur_version:
1442+ print(f"\nYou may also use the Sphinx virtualenv version {latest_avail_ver} with:")
1443+ if f"{self.virtenv_prefix}" in os.getcwd():
1444+ print("\tdeactivate")
1445+ print(f"\t. {self.activate_cmd}")
1446+ self.deactivate_help()
1447+ return
1448+ print("\n")
1449+ else:
1450+ if self.need_sphinx:
1451+ self.deps.need += 1
1452+
1453+ # Suggest newer versions if current ones are too old
1454+ if self.latest_avail_ver and self.latest_avail_ver >= self.min_version:
1455+ if self.latest_avail_ver >= RECOMMENDED_VERSION:
1456+ print(f"\nNeed to activate Sphinx (version {latest_avail_ver}) on virtualenv with:")
1457+ print(f"\t. {self.activate_cmd}")
1458+ self.deactivate_help()
1459+ return
1460+
1461+ # Version is above the minimal required one, but may be
1462+ # below the recommended one. So, print warnings/notes
1463+ if self.latest_avail_ver < RECOMMENDED_VERSION:
1464+ print(f"Warning: It is recommended at least Sphinx version {RECOMMENDED_VERSION}.")
1465+
1466+ # At this point, either it needs Sphinx or upgrade is recommended,
1467+ # both via pip
1468+
1469+ if self.rec_sphinx_upgrade:
1470+ if not self.virtualenv:
1471+ print("Instead of install/upgrade Python Sphinx pkg, you could use pip/pypi with:\n\n")
1472+ else:
1473+ print("To upgrade Sphinx, use:\n\n")
1474+ else:
1475+ print("\nSphinx needs to be installed either:\n1) via pip/pypi with:\n")
1476+
1477+ if not virtualenv_cmd:
1478+ print(" Currently not possible.\n")
1479+ print(" Please upgrade Python to a newer version and run this script again")
1480+ else:
1481+ print(f"\t{virtualenv_cmd} {self.virtenv_dir}")
1482+ print(f"\t. {self.virtenv_dir}/bin/activate")
1483+ print(f"\tpip install -r {self.requirement_file}")
1484+ self.deactivate_help()
1485+
1486+ if self.package_supported:
1487+ self.recommend_package()
1488+
1489+ print("\n" \
1490+ " Please note that Sphinx currentlys produce false-positive\n" \
1491+ " warnings when the same name is used for more than one type (functions,\n" \
1492+ " structs, enums,...). This is known Sphinx bug. For more details, see:\n" \
1493+ "\thttps://github.com/sphinx-doc/sphinx/pull/8313")
1494+
1495+ def check_needs(self):
1496+ """
1497+ Main method that checks needed dependencies and provides
1498+ recommendations.
1499+ """
1500+ self.python_cmd = sys.executable
1501+
1502+ # Check if Sphinx is already accessible from current environment
1503+ self.check_sphinx(self.conf)
1504+
1505+ if self.system_release:
1506+ print(f"Detected OS: {self.system_release}.")
1507+ else:
1508+ print("Unknown OS")
1509+ if self.cur_version != (0, 0, 0):
1510+ ver = ver_str(self.cur_version)
1511+ print(f"Sphinx version: {ver}\n")
1512+
1513+ # Check the type of virtual env, depending on Python version
1514+ virtualenv_cmd = None
1515+
1516+ if sys.version_info < MIN_PYTHON_VERSION:
1517+ min_ver = ver_str(MIN_PYTHON_VERSION)
1518+ print(f"ERROR: at least python {min_ver} is required to build the kernel docs")
1519+ self.need_sphinx = 1
1520+
1521+ self.venv_ver = self.recommend_sphinx_upgrade()
1522+
1523+ if self.need_pip:
1524+ if sys.version_info < MIN_PYTHON_VERSION:
1525+ self.need_pip = False
1526+ print("Warning: python version is not supported.")
1527+ else:
1528+ virtualenv_cmd = f"{self.python_cmd} -m venv"
1529+ self.check_python_module("ensurepip")
1530+
1531+ # Check for needed programs/tools
1532+ self.check_perl_module("Pod::Usage", DepManager.SYSTEM_MANDATORY)
1533+
1534+ self.check_program("make", DepManager.SYSTEM_MANDATORY)
1535+ self.check_program("which", DepManager.SYSTEM_MANDATORY)
1536+
1537+ self.check_program("dot", DepManager.SYSTEM_OPTIONAL)
1538+ self.check_program("convert", DepManager.SYSTEM_OPTIONAL)
1539+
1540+ self.check_python_module("yaml")
1541+
1542+ if self.pdf:
1543+ self.check_program("xelatex", DepManager.PDF_MANDATORY)
1544+ self.check_program("rsvg-convert", DepManager.PDF_MANDATORY)
1545+ self.check_program("latexmk", DepManager.PDF_MANDATORY)
1546+
1547+ # Do distro-specific checks and output distro-install commands
1548+ cmd = self.get_install()
1549+ if cmd:
1550+ print(cmd)
1551+
1552+ # If distro requires some special instructions, print here.
1553+ # Please notice that get_install() needs to be called first.
1554+ if self.distro_msg:
1555+ print("\n" + self.distro_msg)
1556+
1557+ if not self.python_cmd:
1558+ if self.need == 1:
1559+ sys.exit("Can't build as 1 mandatory dependency is missing")
1560+ elif self.need:
1561+ sys.exit(f"Can't build as {self.need} mandatory dependencies are missing")
1562+
1563+ # Check if sphinx-build is called sphinx-build-3
1564+ if self.need_symlink:
1565+ sphinx_path = self.which("sphinx-build-3")
1566+ if sphinx_path:
1567+ print(f"\tsudo ln -sf {sphinx_path} /usr/bin/sphinx-build\n")
1568+
1569+ self.recommend_sphinx_version(virtualenv_cmd)
1570+ print("")
1571+
1572+ if not self.deps.optional:
1573+ print("All optional dependencies are met.")
1574+
1575+ if self.deps.need == 1:
1576+ sys.exit("Can't build as 1 mandatory dependency is missing")
1577+ elif self.deps.need:
1578+ sys.exit(f"Can't build as {self.deps.need} mandatory dependencies are missing")
1579+
1580+ print("Needed package dependencies are met.")
1581+
1582+DESCRIPTION = """
1583+Process some flags related to Sphinx installation and documentation build.
1584+"""
1585+
1586+
1587+def main():
1588+ """Main function"""
1589+ parser = argparse.ArgumentParser(description=DESCRIPTION)
1590+
1591+ parser.add_argument(
1592+ "--no-virtualenv",
1593+ action="store_false",
1594+ dest="virtualenv",
1595+ help="Recommend installing Sphinx instead of using a virtualenv",
1596+ )
1597+
1598+ parser.add_argument(
1599+ "--no-pdf",
1600+ action="store_false",
1601+ dest="pdf",
1602+ help="Don't check for dependencies required to build PDF docs",
1603+ )
1604+
1605+ parser.add_argument(
1606+ "--version-check",
1607+ action="store_true",
1608+ dest="version_check",
1609+ help="If version is compatible, don't check for missing dependencies",
1610+ )
7031611
704−sub deactivate_help()
705−{
706− printf "\n If you want to exit the virtualenv, you can use:\n";
707− printf "\tdeactivate\n";
708−}
709−
710−sub get_virtenv()
711−{
712− my $ver;
713− my $min_activate = "$ENV{'PWD'}/${virtenv_prefix}${min_version}/bin/activate";
714− my @activates = glob "$ENV{'PWD'}/${virtenv_prefix}*/bin/activate";
715−
716− @activates = sort {$b cmp $a} @activates;
717−
718− foreach my $f (@activates) {
719− next if ($f lt $min_activate);
720−
721− my $sphinx_cmd = $f;
722− $sphinx_cmd =~ s/activate/sphinx-build/;
723− next if (! -f $sphinx_cmd);
724−
725− my $ver = get_sphinx_version($sphinx_cmd);
726−
727− if (!$ver) {
728− $f =~ s#/bin/activate##;
729− print("Warning: virtual environment $f is not working.\nPython version upgrade? Remove it with:\n\n\trm -rf $f\n\n");
730− }
731−
732− if ($need_sphinx && ($ver ge $min_version)) {
733− return ($f, $ver);
734− } elsif ($ver gt $cur_version) {
735− return ($f, $ver);
736− }
737− }
738− return ("", "");
739−}
740−
741−sub recommend_sphinx_upgrade()
742−{
743− my $venv_ver;
744−
745− # Avoid running sphinx-builds from venv if $cur_version is good
746− if ($cur_version && ($cur_version ge $rec_version)) {
747− $latest_avail_ver = $cur_version;
748− return;
749− }
750−
751− # Get the highest version from sphinx_*/bin/sphinx-build and the
752− # corresponding command to activate the venv/virtenv
753− ($activate_cmd, $venv_ver) = get_virtenv();
754−
755− # Store the highest version from Sphinx existing virtualenvs
756− if (($activate_cmd ne "") && ($venv_ver gt $cur_version)) {
757− $latest_avail_ver = $venv_ver;
758− } else {
759− $latest_avail_ver = $cur_version if ($cur_version);
760− }
761−
762− # As we don't know package version of Sphinx, and there's no
763− # virtual environments, don't check if upgrades are needed
764− if (!$virtualenv) {
765− return if (!$latest_avail_ver);
766− }
767−
768− # Either there are already a virtual env or a new one should be created
769− $need_pip = 1;
770−
771− return if (!$latest_avail_ver);
772−
773− # Return if the reason is due to an upgrade or not
774− if ($latest_avail_ver lt $rec_version) {
775− $rec_sphinx_upgrade = 1;
776− }
777−
778− return $latest_avail_ver;
779−}
780−
781−#
782−# The logic here is complex, as it have to deal with different versions:
783−# - minimal supported version;
784−# - minimal PDF version;
785−# - recommended version.
786−# It also needs to work fine with both distro's package and venv/virtualenv
787−sub recommend_sphinx_version($)
788−{
789− my $virtualenv_cmd = shift;
790−
791− # Version is OK. Nothing to do.
792− if ($cur_version && ($cur_version ge $rec_version)) {
793− return;
794− };
795−
796− if (!$need_sphinx) {
797− # sphinx-build is present and its version is >= $min_version
798−
799− #only recommend enabling a newer virtenv version if makes sense.
800− if ($latest_avail_ver gt $cur_version) {
801− printf "\nYou may also use the newer Sphinx version $latest_avail_ver with:\n";
802− printf "\tdeactivate\n" if ($ENV{'PWD'} =~ /${virtenv_prefix}/);
803− printf "\t. $activate_cmd\n";
804− deactivate_help();
805−
806− return;
807− }
808− return if ($latest_avail_ver ge $rec_version);
809− }
810−
811− if (!$virtualenv) {
812− # No sphinx either via package or via virtenv. As we can't
813− # Compare the versions here, just return, recommending the
814− # user to install it from the package distro.
815− return if (!$latest_avail_ver);
816−
817− # User doesn't want a virtenv recommendation, but he already
818− # installed one via virtenv with a newer version.
819− # So, print commands to enable it
820− if ($latest_avail_ver gt $cur_version) {
821− printf "\nYou may also use the Sphinx virtualenv version $latest_avail_ver with:\n";
822− printf "\tdeactivate\n" if ($ENV{'PWD'} =~ /${virtenv_prefix}/);
823− printf "\t. $activate_cmd\n";
824− deactivate_help();
825−
826− return;
827− }
828− print "\n";
829− } else {
830− $need++ if ($need_sphinx);
831− }
832−
833− # Suggest newer versions if current ones are too old
834− if ($latest_avail_ver && $latest_avail_ver ge $min_version) {
835− # If there's a good enough version, ask the user to enable it
836− if ($latest_avail_ver ge $rec_version) {
837− printf "\nNeed to activate Sphinx (version $latest_avail_ver) on virtualenv with:\n";
838− printf "\t. $activate_cmd\n";
839− deactivate_help();
840−
841− return;
842− }
843−
844− # Version is above the minimal required one, but may be
845− # below the recommended one. So, print warnings/notes
846−
847− if ($latest_avail_ver lt $rec_version) {
848− print "Warning: It is recommended at least Sphinx version $rec_version.\n";
849− }
850− }
851−
852− # At this point, either it needs Sphinx or upgrade is recommended,
853− # both via pip
854−
855− if ($rec_sphinx_upgrade) {
856− if (!$virtualenv) {
857− print "Instead of install/upgrade Python Sphinx pkg, you could use pip/pypi with:\n\n";
858− } else {
859− print "To upgrade Sphinx, use:\n\n";
860− }
861− } else {
862− print "\nSphinx needs to be installed either:\n1) via pip/pypi with:\n\n";
863− }
864−
865− $python_cmd = find_python_no_venv();
866−
867− printf "\t$virtualenv_cmd $virtenv_dir\n";
868−
869− printf "\t. $virtenv_dir/bin/activate\n";
870− printf "\tpip install -r $requirement_file\n";
871− deactivate_help();
872−
873− printf "\n2) As a package with:\n";
874−
875− my $old_need = $need;
876− my $old_optional = $optional;
877− %missing = ();
878− $pdf = 0;
879− $optional = 0;
880− $install = "";
881− $verbose_warn_install = 0;
882−
883− add_package("python-sphinx", 0);
884−
885− check_distros();
886−
887− $need = $old_need;
888− $optional = $old_optional;
889−
890− printf "\n Please note that Sphinx >= 3.0 will currently produce false-positive\n";
891− printf " warning when the same name is used for more than one type (functions,\n";
892− printf " structs, enums,...). This is known Sphinx bug. For more details, see:\n";
893− printf "\thttps://github.com/sphinx-doc/sphinx/pull/8313\n";
894−}
895−
896−sub check_needs()
897−{
898− # Check if Sphinx is already accessible from current environment
899− check_sphinx();
900−
901− if ($system_release) {
902− print "Detected OS: $system_release.\n";
903− } else {
904− print "Unknown OS\n";
905− }
906− printf "Sphinx version: %s\n\n", $cur_version if ($cur_version);
907−
908− # Check python command line, trying first python3
909− $python_cmd = findprog("python3");
910− $python_cmd = check_program("python", 0) if (!$python_cmd);
911−
912− # Check the type of virtual env, depending on Python version
913− if ($python_cmd) {
914− if ($virtualenv) {
915− my $tmp = qx($python_cmd --version 2>&1);
916− if ($tmp =~ m/(\d+\.)(\d+\.)/) {
917− if ($1 < 3) {
918− # Fail if it finds python2 (or worse)
919− die "Python 3 is required to build the kernel docs\n";
920− }
921− if ($1 == 3 && $2 < 3) {
922− # Need Python 3.3 or upper for venv
923− $need_virtualenv = 1;
924− }
925− } else {
926− die "Warning: couldn't identify $python_cmd version!";
927− }
928− } else {
929− add_package("python-sphinx", 0);
930− }
931− }
932−
933− my $venv_ver = recommend_sphinx_upgrade();
934−
935− my $virtualenv_cmd;
936−
937− if ($need_pip) {
938− # Set virtualenv command line, if python < 3.3
939− if ($need_virtualenv) {
940− $virtualenv_cmd = findprog("virtualenv-3");
941− $virtualenv_cmd = findprog("virtualenv-3.5") if (!$virtualenv_cmd);
942− if (!$virtualenv_cmd) {
943− check_program("virtualenv", 0);
944− $virtualenv_cmd = "virtualenv";
945− }
946− } else {
947− $virtualenv_cmd = "$python_cmd -m venv";
948− check_python_module("ensurepip", 0);
949− }
950− }
951−
952− # Check for needed programs/tools
953− check_perl_module("Pod::Usage", 0);
954− check_python_module("yaml", 0);
955− check_program("make", 0);
956− check_program("gcc", 0);
957− check_program("dot", 1);
958− check_program("convert", 1);
959−
960− # Extra PDF files - should use 2 for is_optional
961− check_program("xelatex", 2) if ($pdf);
962− check_program("rsvg-convert", 2) if ($pdf);
963− check_program("latexmk", 2) if ($pdf);
964−
965− # Do distro-specific checks and output distro-install commands
966− check_distros();
967−
968− if (!$python_cmd) {
969− if ($need == 1) {
970− die "Can't build as $need mandatory dependency is missing";
971− } elsif ($need) {
972− die "Can't build as $need mandatory dependencies are missing";
973− }
974− }
975−
976− # Check if sphinx-build is called sphinx-build-3
977− if ($need_symlink) {
978− printf "\tsudo ln -sf %s /usr/bin/sphinx-build\n\n",
979− which("sphinx-build-3");
980− }
981−
982− recommend_sphinx_version($virtualenv_cmd);
983− printf "\n";
984−
985− print "All optional dependencies are met.\n" if (!$optional);
986−
987− if ($need == 1) {
988− die "Can't build as $need mandatory dependency is missing";
989− } elsif ($need) {
990− die "Can't build as $need mandatory dependencies are missing";
991− }
992−
993− print "Needed package dependencies are met.\n";
994−}
995−
996−#
997−# Main
998−#
999−
1000−while (@ARGV) {
1001− my $arg = shift(@ARGV);
1002−
1003− if ($arg eq "--no-virtualenv") {
1004− $virtualenv = 0;
1005− } elsif ($arg eq "--no-pdf"){
1006− $pdf = 0;
1007− } elsif ($arg eq "--version-check"){
1008− $version_check = 1;
1009− } else {
1010− print "Usage:\n\t$0 <--no-virtualenv> <--no-pdf> <--version-check>\n\n";
1011− print "Where:\n";
1012− print "\t--no-virtualenv\t- Recommend installing Sphinx instead of using a virtualenv\n";
1013− print "\t--version-check\t- if version is compatible, don't check for missing dependencies\n";
1014− print "\t--no-pdf\t- don't check for dependencies required to build PDF docs\n\n";
1015− exit -1;
1016− }
1017−}
1018−
1019−#
1020−# Determine the system type. There's no standard unique way that would
1021−# work with all distros with a minimal package install. So, several
1022−# methods are used here.
1023−#
1024−# By default, it will use lsb_release function. If not available, it will
1025−# fail back to reading the known different places where the distro name
1026−# is stored
1027−#
1612+ args = parser.parse_args()
1613+
1614+ checker = SphinxDependencyChecker(args)
10281615
1029−$system_release = qx(lsb_release -d) if which("lsb_release");
1030−$system_release =~ s/Description:\s*// if ($system_release);
1031−$system_release = catcheck("/etc/system-release") if !$system_release;
1032−$system_release = catcheck("/etc/redhat-release") if !$system_release;
1033−$system_release = catcheck("/etc/lsb-release") if !$system_release;
1034−$system_release = catcheck("/etc/gentoo-release") if !$system_release;
1035−
1036−# This seems more common than LSB these days
1037−if (!$system_release) {
1038− my %os_var;
1039− if (open IN, "cat /etc/os-release|") {
1040− while (<IN>) {
1041− if (m/^([\w\d\_]+)=\"?([^\"]*)\"?\n/) {
1042− $os_var{$1}=$2;
1043− }
1044− }
1045− $system_release = $os_var{"NAME"};
1046− if (defined($os_var{"VERSION_ID"})) {
1047− $system_release .= " " . $os_var{"VERSION_ID"} if (defined($os_var{"VERSION_ID"}));
1048− } else {
1049− $system_release .= " " . $os_var{"VERSION"};
1050− }
1051− }
1052−}
1053−$system_release = catcheck("/etc/issue") if !$system_release;
1054−$system_release =~ s/\s+$//;
1055−
1056−check_needs;
1616+ checker.check_python()
1617+ checker.check_needs()
1618+
1619+# Call main if not used as module
1620+if __name__ == "__main__":
1621+ main()
tools/docs/gen-redirects.py+54−0
@@ -0,0 +1,54 @@
1+#! /usr/bin/env python3
2+# SPDX-License-Identifier: GPL-2.0
3+#
4+# Copyright © 2025, Oracle and/or its affiliates.
5+# Author: Vegard Nossum <vegard.nossum@oracle.com>
6+
7+"""Generate HTML redirects for renamed Documentation/**.rst files using
8+the output of tools/docs/gen-renames.py.
9+
10+Example:
11+
12+ tools/docs/gen-redirects.py --output Documentation/output/ < Documentation/.renames.txt
13+"""
14+
15+import argparse
16+import os
17+import sys
18+
19+parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
20+parser.add_argument('-o', '--output', help='output directory')
21+
22+args = parser.parse_args()
23+
24+for line in sys.stdin:
25+ line = line.rstrip('\n')
26+
27+ old_name, new_name = line.split(' ', 2)
28+
29+ old_html_path = os.path.join(args.output, old_name + '.html')
30+ new_html_path = os.path.join(args.output, new_name + '.html')
31+
32+ if not os.path.exists(new_html_path):
33+ print(f"warning: target does not exist: {new_html_path} (redirect from {old_html_path})")
34+ continue
35+
36+ old_html_dir = os.path.dirname(old_html_path)
37+ if not os.path.exists(old_html_dir):
38+ os.makedirs(old_html_dir)
39+
40+ relpath = os.path.relpath(new_name, os.path.dirname(old_name)) + '.html'
41+
42+ with open(old_html_path, 'w') as f:
43+ print(f"""\
44+<!DOCTYPE html>
45+
46+<html lang="en">
47+<head>
48+ <title>This page has moved</title>
49+ <meta http-equiv="refresh" content="0; url={relpath}">
50+</head>
51+<body>
52+<p>This page has moved to <a href="{relpath}">{new_name}</a>.</p>
53+</body>
54+</html>""", file=f)
tools/docs/gen-renames.py+130−0
@@ -0,0 +1,130 @@
1+#! /usr/bin/env python3
2+# SPDX-License-Identifier: GPL-2.0
3+#
4+# Copyright © 2025, Oracle and/or its affiliates.
5+# Author: Vegard Nossum <vegard.nossum@oracle.com>
6+
7+"""Trawl repository history for renames of Documentation/**.rst files.
8+
9+Example:
10+
11+ tools/docs/gen-renames.py --rev HEAD > Documentation/.renames.txt
12+"""
13+
14+import argparse
15+import itertools
16+import os
17+import subprocess
18+import sys
19+
20+parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
21+parser.add_argument('--rev', default='HEAD', help='generate renames up to this revision')
22+
23+args = parser.parse_args()
24+
25+def normalize(path):
26+ prefix = 'Documentation/'
27+ suffix = '.rst'
28+
29+ assert path.startswith(prefix)
30+ assert path.endswith(suffix)
31+
32+ return path[len(prefix):-len(suffix)]
33+
34+class Name(object):
35+ def __init__(self, name):
36+ self.names = [name]
37+
38+ def rename(self, new_name):
39+ self.names.append(new_name)
40+
41+names = {
42+}
43+
44+for line in subprocess.check_output([
45+ 'git', 'log',
46+ '--reverse',
47+ '--oneline',
48+ '--find-renames',
49+ '--diff-filter=RD',
50+ '--name-status',
51+ '--format=commit %H',
52+ # ~v4.8-ish is when Sphinx/.rst was added in the first place
53+ f'v4.8..{args.rev}',
54+ '--',
55+ 'Documentation/'
56+], text=True).splitlines():
57+ # rename
58+ if line.startswith('R'):
59+ _, old, new = line[1:].split('\t', 2)
60+
61+ if old.endswith('.rst') and new.endswith('.rst'):
62+ old = normalize(old)
63+ new = normalize(new)
64+
65+ name = names.get(old)
66+ if name is None:
67+ name = Name(old)
68+ else:
69+ del names[old]
70+
71+ name.rename(new)
72+ names[new] = name
73+
74+ continue
75+
76+ # delete
77+ if line.startswith('D'):
78+ _, old = line.split('\t', 1)
79+
80+ if old.endswith('.rst'):
81+ old = normalize(old)
82+
83+ # TODO: we could save added/modified files as well and propose
84+ # them as alternatives
85+ name = names.get(old)
86+ if name is None:
87+ pass
88+ else:
89+ del names[old]
90+
91+ continue
92+
93+#
94+# Get the set of current files so we can sanity check that we aren't
95+# redirecting any of those
96+#
97+
98+current_files = set()
99+for line in subprocess.check_output([
100+ 'git', 'ls-tree',
101+ '-r',
102+ '--name-only',
103+ args.rev,
104+ 'Documentation/',
105+], text=True).splitlines():
106+ if line.endswith('.rst'):
107+ current_files.add(normalize(line))
108+
109+#
110+# Format/group/output result
111+#
112+
113+result = []
114+for _, v in names.items():
115+ old_names = v.names[:-1]
116+ new_name = v.names[-1]
117+
118+ for old_name in old_names:
119+ if old_name == new_name:
120+ # A file was renamed to its new name twice; don't redirect that
121+ continue
122+
123+ if old_name in current_files:
124+ # A file was recreated with a former name; don't redirect those
125+ continue
126+
127+ result.append((old_name, new_name))
128+
129+for old_name, new_name in sorted(result):
130+ print(f"{old_name} {new_name}")
tools/docs/lib/__init__.py+0−0

Empty file added.

tools/docs/lib/enrich_formatter.py+70−0
@@ -0,0 +1,70 @@
1+#!/usr/bin/env python3
2+# SPDX-License-Identifier: GPL-2.0
3+# Copyright (c) 2025 by Mauro Carvalho Chehab <mchehab@kernel.org>.
4+
5+"""
6+Ancillary argparse HelpFormatter class that works on a similar way as
7+argparse.RawDescriptionHelpFormatter, e.g. description maintains line
8+breaks, but it also implement transformations to the help text. The
9+actual transformations ar given by enrich_text(), if the output is tty.
10+
11+Currently, the follow transformations are done:
12+
13+ - Positional arguments are shown in upper cases;
14+ - if output is TTY, ``var`` and positional arguments are shown prepended
15+ by an ANSI SGR code. This is usually translated to bold. On some
16+ terminals, like, konsole, this is translated into a colored bold text.
17+"""
18+
19+import argparse
20+import re
21+import sys
22+
23+class EnrichFormatter(argparse.HelpFormatter):
24+ """
25+ Better format the output, making easier to identify the positional args
26+ and how they're used at the __doc__ description.
27+ """
28+ def __init__(self, *args, **kwargs):
29+ """Initialize class and check if is TTY"""
30+ super().__init__(*args, **kwargs)
31+ self._tty = sys.stdout.isatty()
32+
33+ def enrich_text(self, text):
34+ """Handle ReST markups (currently, only ``foo``)"""
35+ if self._tty and text:
36+ # Replace ``text`` with ANSI SGR (bold)
37+ return re.sub(r'\`\`(.+?)\`\`',
38+ lambda m: f'\033[1m{m.group(1)}\033[0m', text)
39+ return text
40+
41+ def _fill_text(self, text, width, indent):
42+ """Enrich descriptions with markups on it"""
43+ enriched = self.enrich_text(text)
44+ return "\n".join(indent + line for line in enriched.splitlines())
45+
46+ def _format_usage(self, usage, actions, groups, prefix):
47+ """Enrich positional arguments at usage: line"""
48+
49+ prog = self._prog
50+ parts = []
51+
52+ for action in actions:
53+ if action.option_strings:
54+ opt = action.option_strings[0]
55+ if action.nargs != 0:
56+ opt += f" {action.dest.upper()}"
57+ parts.append(f"[{opt}]")
58+ else:
59+ # Positional argument
60+ parts.append(self.enrich_text(f"``{action.dest.upper()}``"))
61+
62+ usage_text = f"{prefix or 'usage: '} {prog} {' '.join(parts)}\n"
63+ return usage_text
64+
65+ def _format_action_invocation(self, action):
66+ """Enrich argument names"""
67+ if not action.option_strings:
68+ return self.enrich_text(f"``{action.dest.upper()}``")
69+
70+ return ", ".join(action.option_strings)
tools/docs/lib/parse_data_structs.py+452−0
@@ -0,0 +1,452 @@
1+#!/usr/bin/env python3
2+# SPDX-License-Identifier: GPL-2.0
3+# Copyright (c) 2016-2025 by Mauro Carvalho Chehab <mchehab@kernel.org>.
4+# pylint: disable=R0912,R0915
5+
6+"""
7+Parse a source file or header, creating ReStructured Text cross references.
8+
9+It accepts an optional file to change the default symbol reference or to
10+suppress symbols from the output.
11+
12+It is capable of identifying defines, functions, structs, typedefs,
13+enums and enum symbols and create cross-references for all of them.
14+It is also capable of distinguish #define used for specifying a Linux
15+ioctl.
16+
17+The optional rules file contains a set of rules like:
18+
19+ ignore ioctl VIDIOC_ENUM_FMT
20+ replace ioctl VIDIOC_DQBUF vidioc_qbuf
21+ replace define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ :c:type:`v4l2_event_motion_det`
22+"""
23+
24+import os
25+import re
26+import sys
27+
28+
29+class ParseDataStructs:
30+ """
31+ Creates an enriched version of a Kernel header file with cross-links
32+ to each C data structure type.
33+
34+ It is meant to allow having a more comprehensive documentation, where
35+ uAPI headers will create cross-reference links to the code.
36+
37+ It is capable of identifying defines, functions, structs, typedefs,
38+ enums and enum symbols and create cross-references for all of them.
39+ It is also capable of distinguish #define used for specifying a Linux
40+ ioctl.
41+
42+ By default, it create rules for all symbols and defines, but it also
43+ allows parsing an exception file. Such file contains a set of rules
44+ using the syntax below:
45+
46+ 1. Ignore rules:
47+
48+ ignore <type> <symbol>`
49+
50+ Removes the symbol from reference generation.
51+
52+ 2. Replace rules:
53+
54+ replace <type> <old_symbol> <new_reference>
55+
56+ Replaces how old_symbol with a new reference. The new_reference can be:
57+ - A simple symbol name;
58+ - A full Sphinx reference.
59+
60+ On both cases, <type> can be:
61+ - ioctl: for defines that end with _IO*, e.g. ioctl definitions
62+ - define: for other defines
63+ - symbol: for symbols defined within enums;
64+ - typedef: for typedefs;
65+ - enum: for the name of a non-anonymous enum;
66+ - struct: for structs.
67+
68+ Examples:
69+
70+ ignore define __LINUX_MEDIA_H
71+ ignore ioctl VIDIOC_ENUM_FMT
72+ replace ioctl VIDIOC_DQBUF vidioc_qbuf
73+ replace define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ :c:type:`v4l2_event_motion_det`
74+ """
75+
76+ # Parser regexes with multiple ways to capture enums and structs
77+ RE_ENUMS = [
78+ re.compile(r"^\s*enum\s+([\w_]+)\s*\{"),
79+ re.compile(r"^\s*enum\s+([\w_]+)\s*$"),
80+ re.compile(r"^\s*typedef\s*enum\s+([\w_]+)\s*\{"),
81+ re.compile(r"^\s*typedef\s*enum\s+([\w_]+)\s*$"),
82+ ]
83+ RE_STRUCTS = [
84+ re.compile(r"^\s*struct\s+([_\w][\w\d_]+)\s*\{"),
85+ re.compile(r"^\s*struct\s+([_\w][\w\d_]+)$"),
86+ re.compile(r"^\s*typedef\s*struct\s+([_\w][\w\d_]+)\s*\{"),
87+ re.compile(r"^\s*typedef\s*struct\s+([_\w][\w\d_]+)$"),
88+ ]
89+
90+ # FIXME: the original code was written a long time before Sphinx C
91+ # domain to have multiple namespaces. To avoid to much turn at the
92+ # existing hyperlinks, the code kept using "c:type" instead of the
93+ # right types. To change that, we need to change the types not only
94+ # here, but also at the uAPI media documentation.
95+ DEF_SYMBOL_TYPES = {
96+ "ioctl": {
97+ "prefix": "\\ ",
98+ "suffix": "\\ ",
99+ "ref_type": ":ref",
100+ "description": "IOCTL Commands",
101+ },
102+ "define": {
103+ "prefix": "\\ ",
104+ "suffix": "\\ ",
105+ "ref_type": ":ref",
106+ "description": "Macros and Definitions",
107+ },
108+ # We're calling each definition inside an enum as "symbol"
109+ "symbol": {
110+ "prefix": "\\ ",
111+ "suffix": "\\ ",
112+ "ref_type": ":ref",
113+ "description": "Enumeration values",
114+ },
115+ "typedef": {
116+ "prefix": "\\ ",
117+ "suffix": "\\ ",
118+ "ref_type": ":c:type",
119+ "description": "Type Definitions",
120+ },
121+ # This is the description of the enum itself
122+ "enum": {
123+ "prefix": "\\ ",
124+ "suffix": "\\ ",
125+ "ref_type": ":c:type",
126+ "description": "Enumerations",
127+ },
128+ "struct": {
129+ "prefix": "\\ ",
130+ "suffix": "\\ ",
131+ "ref_type": ":c:type",
132+ "description": "Structures",
133+ },
134+ }
135+
136+ def __init__(self, debug: bool = False):
137+ """Initialize internal vars"""
138+ self.debug = debug
139+ self.data = ""
140+
141+ self.symbols = {}
142+
143+ for symbol_type in self.DEF_SYMBOL_TYPES:
144+ self.symbols[symbol_type] = {}
145+
146+ def store_type(self, symbol_type: str, symbol: str,
147+ ref_name: str = None, replace_underscores: bool = True):
148+ """
149+ Stores a new symbol at self.symbols under symbol_type.
150+
151+ By default, underscores are replaced by "-"
152+ """
153+ defs = self.DEF_SYMBOL_TYPES[symbol_type]
154+
155+ prefix = defs.get("prefix", "")
156+ suffix = defs.get("suffix", "")
157+ ref_type = defs.get("ref_type")
158+
159+ # Determine ref_link based on symbol type
160+ if ref_type:
161+ if symbol_type == "enum":
162+ ref_link = f"{ref_type}:`{symbol}`"
163+ else:
164+ if not ref_name:
165+ ref_name = symbol.lower()
166+
167+ # c-type references don't support hash
168+ if ref_type == ":ref" and replace_underscores:
169+ ref_name = ref_name.replace("_", "-")
170+
171+ ref_link = f"{ref_type}:`{symbol} <{ref_name}>`"
172+ else:
173+ ref_link = symbol
174+
175+ self.symbols[symbol_type][symbol] = f"{prefix}{ref_link}{suffix}"
176+
177+ def store_line(self, line):
178+ """Stores a line at self.data, properly indented"""
179+ line = " " + line.expandtabs()
180+ self.data += line.rstrip(" ")
181+
182+ def parse_file(self, file_in: str):
183+ """Reads a C source file and get identifiers"""
184+ self.data = ""
185+ is_enum = False
186+ is_comment = False
187+ multiline = ""
188+
189+ with open(file_in, "r",
190+ encoding="utf-8", errors="backslashreplace") as f:
191+ for line_no, line in enumerate(f):
192+ self.store_line(line)
193+ line = line.strip("\n")
194+
195+ # Handle continuation lines
196+ if line.endswith(r"\\"):
197+ multiline += line[-1]
198+ continue
199+
200+ if multiline:
201+ line = multiline + line
202+ multiline = ""
203+
204+ # Handle comments. They can be multilined
205+ if not is_comment:
206+ if re.search(r"/\*.*", line):
207+ is_comment = True
208+ else:
209+ # Strip C99-style comments
210+ line = re.sub(r"(//.*)", "", line)
211+
212+ if is_comment:
213+ if re.search(r".*\*/", line):
214+ is_comment = False
215+ else:
216+ multiline = line
217+ continue
218+
219+ # At this point, line variable may be a multilined statement,
220+ # if lines end with \ or if they have multi-line comments
221+ # With that, it can safely remove the entire comments,
222+ # and there's no need to use re.DOTALL for the logic below
223+
224+ line = re.sub(r"(/\*.*\*/)", "", line)
225+ if not line.strip():
226+ continue
227+
228+ # It can be useful for debug purposes to print the file after
229+ # having comments stripped and multi-lines grouped.
230+ if self.debug > 1:
231+ print(f"line {line_no + 1}: {line}")
232+
233+ # Now the fun begins: parse each type and store it.
234+
235+ # We opted for a two parsing logic here due to:
236+ # 1. it makes easier to debug issues not-parsed symbols;
237+ # 2. we want symbol replacement at the entire content, not
238+ # just when the symbol is detected.
239+
240+ if is_enum:
241+ match = re.match(r"^\s*([_\w][\w\d_]+)\s*[\,=]?", line)
242+ if match:
243+ self.store_type("symbol", match.group(1))
244+ if "}" in line:
245+ is_enum = False
246+ continue
247+
248+ match = re.match(r"^\s*#\s*define\s+([\w_]+)\s+_IO", line)
249+ if match:
250+ self.store_type("ioctl", match.group(1),
251+ replace_underscores=False)
252+ continue
253+
254+ match = re.match(r"^\s*#\s*define\s+([\w_]+)(\s+|$)", line)
255+ if match:
256+ self.store_type("define", match.group(1))
257+ continue
258+
259+ match = re.match(r"^\s*typedef\s+([_\w][\w\d_]+)\s+(.*)\s+([_\w][\w\d_]+);",
260+ line)
261+ if match:
262+ name = match.group(2).strip()
263+ symbol = match.group(3)
264+ self.store_type("typedef", symbol, ref_name=name)
265+ continue
266+
267+ for re_enum in self.RE_ENUMS:
268+ match = re_enum.match(line)
269+ if match:
270+ self.store_type("enum", match.group(1))
271+ is_enum = True
272+ break
273+
274+ for re_struct in self.RE_STRUCTS:
275+ match = re_struct.match(line)
276+ if match:
277+ self.store_type("struct", match.group(1))
278+ break
279+
280+ def process_exceptions(self, fname: str):
281+ """
282+ Process exceptions file with rules to ignore or replace references.
283+ """
284+ if not fname:
285+ return
286+
287+ name = os.path.basename(fname)
288+
289+ with open(fname, "r", encoding="utf-8", errors="backslashreplace") as f:
290+ for ln, line in enumerate(f):
291+ ln += 1
292+ line = line.strip()
293+ if not line or line.startswith("#"):
294+ continue
295+
296+ # Handle ignore rules
297+ match = re.match(r"^ignore\s+(\w+)\s+(\S+)", line)
298+ if match:
299+ c_type = match.group(1)
300+ symbol = match.group(2)
301+
302+ if c_type not in self.DEF_SYMBOL_TYPES:
303+ sys.exit(f"{name}:{ln}: {c_type} is invalid")
304+
305+ d = self.symbols[c_type]
306+ if symbol in d:
307+ del d[symbol]
308+
309+ continue
310+
311+ # Handle replace rules
312+ match = re.match(r"^replace\s+(\S+)\s+(\S+)\s+(\S+)", line)
313+ if not match:
314+ sys.exit(f"{name}:{ln}: invalid line: {line}")
315+
316+ c_type, old, new = match.groups()
317+
318+ if c_type not in self.DEF_SYMBOL_TYPES:
319+ sys.exit(f"{name}:{ln}: {c_type} is invalid")
320+
321+ reftype = None
322+
323+ # Parse reference type when the type is specified
324+
325+ match = re.match(r"^\:c\:(data|func|macro|type)\:\`(.+)\`", new)
326+ if match:
327+ reftype = f":c:{match.group(1)}"
328+ new = match.group(2)
329+ else:
330+ match = re.search(r"(\:ref)\:\`(.+)\`", new)
331+ if match:
332+ reftype = match.group(1)
333+ new = match.group(2)
334+
335+ # If the replacement rule doesn't have a type, get default
336+ if not reftype:
337+ reftype = self.DEF_SYMBOL_TYPES[c_type].get("ref_type")
338+ if not reftype:
339+ reftype = self.DEF_SYMBOL_TYPES[c_type].get("real_type")
340+
341+ new_ref = f"{reftype}:`{old} <{new}>`"
342+
343+ # Change self.symbols to use the replacement rule
344+ if old in self.symbols[c_type]:
345+ self.symbols[c_type][old] = new_ref
346+ else:
347+ print(f"{name}:{ln}: Warning: can't find {old} {c_type}")
348+
349+ def debug_print(self):
350+ """
351+ Print debug information containing the replacement rules per symbol.
352+ To make easier to check, group them per type.
353+ """
354+ if not self.debug:
355+ return
356+
357+ for c_type, refs in self.symbols.items():
358+ if not refs: # Skip empty dictionaries
359+ continue
360+
361+ print(f"{c_type}:")
362+
363+ for symbol, ref in sorted(refs.items()):
364+ print(f" {symbol} -> {ref}")
365+
366+ print()
367+
368+ def gen_output(self):
369+ """Write the formatted output to a file."""
370+
371+ # Avoid extra blank lines
372+ text = re.sub(r"\s+$", "", self.data) + "\n"
373+ text = re.sub(r"\n\s+\n", "\n\n", text)
374+
375+ # Escape Sphinx special characters
376+ text = re.sub(r"([\_\`\*\<\>\&\\\\:\/\|\%\$\#\{\}\~\^])", r"\\\1", text)
377+
378+ # Source uAPI files may have special notes. Use bold font for them
379+ text = re.sub(r"DEPRECATED", "**DEPRECATED**", text)
380+
381+ # Delimiters to catch the entire symbol after escaped
382+ start_delim = r"([ \n\t\(=\*\@])"
383+ end_delim = r"(\s|,|\\=|\\:|\;|\)|\}|\{)"
384+
385+ # Process all reference types
386+ for ref_dict in self.symbols.values():
387+ for symbol, replacement in ref_dict.items():
388+ symbol = re.escape(re.sub(r"([\_\`\*\<\>\&\\\\:\/])", r"\\\1", symbol))
389+ text = re.sub(fr'{start_delim}{symbol}{end_delim}',
390+ fr'\1{replacement}\2', text)
391+
392+ # Remove "\ " where not needed: before spaces and at the end of lines
393+ text = re.sub(r"\\ ([\n ])", r"\1", text)
394+ text = re.sub(r" \\ ", " ", text)
395+
396+ return text
397+
398+ def gen_toc(self):
399+ """
400+ Create a TOC table pointing to each symbol from the header
401+ """
402+ text = []
403+
404+ # Add header
405+ text.append(".. contents:: Table of Contents")
406+ text.append(" :depth: 2")
407+ text.append(" :local:")
408+ text.append("")
409+
410+ # Sort symbol types per description
411+ symbol_descriptions = []
412+ for k, v in self.DEF_SYMBOL_TYPES.items():
413+ symbol_descriptions.append((v['description'], k))
414+
415+ symbol_descriptions.sort()
416+
417+ # Process each category
418+ for description, c_type in symbol_descriptions:
419+
420+ refs = self.symbols[c_type]
421+ if not refs: # Skip empty categories
422+ continue
423+
424+ text.append(f"{description}")
425+ text.append("-" * len(description))
426+ text.append("")
427+
428+ # Sort symbols alphabetically
429+ for symbol, ref in sorted(refs.items()):
430+ text.append(f"* :{ref}:")
431+
432+ text.append("") # Add empty line between categories
433+
434+ return "\n".join(text)
435+
436+ def write_output(self, file_in: str, file_out: str, toc: bool):
437+ title = os.path.basename(file_in)
438+
439+ if toc:
440+ text = self.gen_toc()
441+ else:
442+ text = self.gen_output()
443+
444+ with open(file_out, "w", encoding="utf-8", errors="backslashreplace") as f:
445+ f.write(".. -*- coding: utf-8; mode: rst -*-\n\n")
446+ f.write(f"{title}\n")
447+ f.write("=" * len(title) + "\n\n")
448+
449+ if not toc:
450+ f.write(".. parsed-literal::\n\n")
451+
452+ f.write(text)
tools/docs/parse-headers.py+60−0
@@ -0,0 +1,60 @@
1+#!/usr/bin/env python3
2+# SPDX-License-Identifier: GPL-2.0
3+# Copyright (c) 2016, 2025 by Mauro Carvalho Chehab <mchehab@kernel.org>.
4+# pylint: disable=C0103
5+
6+"""
7+Convert a C header or source file ``FILE_IN``, into a ReStructured Text
8+included via ..parsed-literal block with cross-references for the
9+documentation files that describe the API. It accepts an optional
10+``FILE_RULES`` file to describes what elements will be either ignored or
11+be pointed to a non-default reference type/name.
12+
13+The output is written at ``FILE_OUT``.
14+
15+It is capable of identifying defines, functions, structs, typedefs,
16+enums and enum symbols and create cross-references for all of them.
17+It is also capable of distinguish #define used for specifying a Linux
18+ioctl.
19+
20+The optional ``FILE_RULES`` contains a set of rules like:
21+
22+ ignore ioctl VIDIOC_ENUM_FMT
23+ replace ioctl VIDIOC_DQBUF vidioc_qbuf
24+ replace define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ :c:type:`v4l2_event_motion_det`
25+"""
26+
27+import argparse
28+
29+from lib.parse_data_structs import ParseDataStructs
30+from lib.enrich_formatter import EnrichFormatter
31+
32+def main():
33+ """Main function"""
34+ parser = argparse.ArgumentParser(description=__doc__,
35+ formatter_class=EnrichFormatter)
36+
37+ parser.add_argument("-d", "--debug", action="count", default=0,
38+ help="Increase debug level. Can be used multiple times")
39+ parser.add_argument("-t", "--toc", action="store_true",
40+ help="instead of a literal block, outputs a TOC table at the RST file")
41+
42+ parser.add_argument("file_in", help="Input C file")
43+ parser.add_argument("file_out", help="Output RST file")
44+ parser.add_argument("file_rules", nargs="?",
45+ help="Exceptions file (optional)")
46+
47+ args = parser.parse_args()
48+
49+ parser = ParseDataStructs(debug=args.debug)
50+ parser.parse_file(args.file_in)
51+
52+ if args.file_rules:
53+ parser.process_exceptions(args.file_rules)
54+
55+ parser.debug_print()
56+ parser.write_output(args.file_in, args.file_out, args.toc)
57+
58+
59+if __name__ == "__main__":
60+ main()