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

Pull documentation updates from Jonathan Corbet:
 "It has been a not-too-busy cycle for docs; here's the highlights:

   - A (hopefully) consensus change to our LLM-attribution requirements,
     removing the specific model name from the Assisted-by tag

   - A couple of new realtime documents

   - Various docs-build-system fixes

   - Ongoing work with the Chinese, Portuguese, and Japanese
     translations

  ...and lots of typo fixes, grammar tweaks, etc"

* tag 'docs-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/docs/linux: (85 commits)
  Doc: admin-guide: pm: Remove unnecessary backticks and fix a spell
  Documentation: Extend the real-time hardware bits with some firmware bits
  docs: pt_BR: Reorganize process/index.rst to follow english structure
  docs: conf.py: fix the 'utf-8' typo
  doc tools: fix 'path' typos
  Documentation: real-time: Add kernel configuration guide
  docs: python: abi_regex: convert adjacent index placeholders
  docs: python: abi_regex: catch the right exception for a bad regex
  docs: sphinx-build-wrapper: include localversion in kernel version string
  Documentation: html: adjust sidebar section titles styling
  Documentation: html: show sections in the sidebar
  checkpatch.pl: adapt to new Assisted-by: format
  MAINTAINERS: update Traditional Chinese documentation maintainers
  docs: pt_BR: process: Translate CVE documentation
  docs: pt_BR: translate the management-style.rst to Brazilian Portuguese
  docs: xforms_lists: support DEFINE_IDTENTRY_IRQ()
  coding-assistants: simplify attribution
  docs: translations: pt_BR: translate email-clients.rst
  docs: pt_BR: process: Translate the security-bugs.rst
  doc:it_IT: align doc-guide translation
  ...
This commit is contained in:
Linus Torvalds
2026-08-20 10:31:50 -07:00
85 changed files with 8031 additions and 616 deletions

View File

@@ -1821,6 +1821,10 @@ S: Am Strand 5
S: D-19063 Schwerin
S: Germany
N: Haowen Hu
E: srcres258@furdevs.cn
D: Traditional Chinese (zh_TW) documentation translation and maintenance
N: Jan Hubicka
E: hubicka@freesoft.cz
E: hubicka@suse.cz

View File

@@ -62,7 +62,7 @@ Users: All users of this interface who wish to be notified when
Note:
The fields should be use a simple notation, compatible with ReST markup.
The fields should use a simple notation, compatible with ReST markup.
Also, the file **should not** have a top-level index, like::
===

View File

@@ -160,7 +160,7 @@ Description:
in trace events, such as CXL DRAM and CXL general media
error records of CXL memory devices.
When readng back these attributes, it returns the current
When reading back these attributes, it returns the current
value of memory requested to be repaired.
bank_group - The bank group of the memory to repair.

View File

@@ -1618,10 +1618,17 @@ Kernel parameters
on all PCI bridges while in the EFI boot stub
efi_no_storage_paranoia [EFI,X86,EARLY]
Using this parameter you can use more than 50% of
your efi variable storage. Use this parameter only if
you are really sure that your UEFI does sane gc and
fulfills the spec otherwise your board may brick.
The kernel reserves 5KB of EFI variable storage for
safety, because some UEFI implementation may fail to
boot if there's insufficient space in the EFI variable
storage.
Using this parameter, you can use the 5KB reservation
in the EFI variable storage.
However, Use this parameter only if you are really
sure that your UEFI does sane gc and fulfills the spec
otherwise your board may brick.
efivar_ssdt= [EFI; X86] Name of an EFI variable that contains an SSDT
that is to be dynamically loaded by Linux. If there are
@@ -6446,9 +6453,9 @@ Kernel parameters
reboot= [KNL]
Format (x86 or x86_64):
[w[arm] | c[old] | h[ard] | s[oft] | g[pio]] | d[efault] \
[[,]s[mp]#### \
[[,]s[mp]####] \
[[,]b[ios] | a[cpi] | k[bd] | t[riple] | e[fi] | p[ci]] \
[[,]f[orce]
[[,]f[orce]]
Where reboot_mode is one of warm (soft) or cold (hard) or gpio
(prefix with 'panic_' to set mode for panic
reboot only),
@@ -6908,7 +6915,7 @@ Kernel parameters
xtime_lock contention on larger systems, and/or RCU lock
contention on all systems with CONFIG_MAXSMP set.
Format: { "0" | "1" }
0 -- disable. (may be 1 via CONFIG_CMDLINE="skew_tick=1"
0 -- disable. (may be 1 via CONFIG_CMDLINE="skew_tick=1")
1 -- enable.
Note: increases power consumption, thus should only be
enabled if running jitter sensitive (HPC/RT) workloads.
@@ -6949,7 +6956,7 @@ Kernel parameters
apic=verbose is specified.
Example: apic=debug show_lapic=all
slab_debug[=options[,slabs][;[options[,slabs]]...] [MM]
slab_debug[=options[,slabs][;[options[,slabs]]...]] [MM]
Enabling slab_debug allows one to determine the
culprit if slab objects become corrupted. Enabling
slab_debug can create guard zones around objects and
@@ -7039,17 +7046,6 @@ Kernel parameters
take as long as they take. Specifying 300,000
for this value provides a 5-minute timeout.
smsc-ircc2.nopnp [HW] Don't use PNP to discover SMC devices
smsc-ircc2.ircc_cfg= [HW] Device configuration I/O port
smsc-ircc2.ircc_sir= [HW] SIR base I/O port
smsc-ircc2.ircc_fir= [HW] FIR base I/O port
smsc-ircc2.ircc_irq= [HW] IRQ line
smsc-ircc2.ircc_dma= [HW] DMA channel
smsc-ircc2.ircc_transceiver= [HW] Transceiver type:
0: Toshiba Satellite 1800 (GP data pin select)
1: Fast pin select (default)
2: ATC IRMode
smt= [KNL,MIPS,S390,EARLY] Set the maximum number of threads
(logical CPUs) to use per physical CPU on systems
capable of symmetric multithreading (SMT). Will

View File

@@ -1239,7 +1239,7 @@ Models:
- Galaxis DVB Card C CI
- Galaxis DVB Card S
- Galaxis DVB Card C
- Galaxis plug.in S [neuer Name: Galaxis DVB Card S CI
- Galaxis plug.in S [new Name: Galaxis DVB Card S CI]
Hauppauge
~~~~~~~~~

View File

@@ -67,7 +67,7 @@ number of times a page is mapped.
* ``/proc/kpageflags``. This file contains a 64-bit set of flags for each
page, indexed by PFN.
The flags are (from ``fs/proc/page.c``, above kpageflags_read):
The flags are (from ``include/uapi/linux/kernel-page-flags.h``):
0. LOCKED
1. ERROR
@@ -264,7 +264,7 @@ The ``struct pm_scan_arg`` is used as the argument of the IOCTL.
provided or not.
3. The range is specified through ``start`` and ``end``.
4. The walk can abort before visiting the complete range such as the user buffer
can get full etc. The walk ending address is specified in``end_walk``.
can get full etc. The walk ending address is specified in ``walk_end``.
5. The output buffer of ``struct page_region`` array and size is specified in
``vec`` and ``vec_len``.
6. The optional maximum requested pages are specified in the ``max_pages``.
@@ -275,7 +275,7 @@ Find pages which have been written and WP them as well::
struct pm_scan_arg arg = {
.size = sizeof(arg),
.flags = PM_SCAN_CHECK_WPASYNC | PM_SCAN_CHECK_WPASYNC,
.flags = PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
..
.category_mask = PAGE_IS_WRITTEN,
.return_mask = PAGE_IS_WRITTEN,
@@ -288,7 +288,7 @@ present or huge::
.size = sizeof(arg),
.flags = 0,
..
.category_mask = PAGE_IS_WRITTEN | PAGE_IS_SWAPPED,
.category_mask = PAGE_IS_WRITTEN | PAGE_IS_FILE,
.category_inverted = PAGE_IS_SWAPPED,
.category_anyof_mask = PAGE_IS_PRESENT | PAGE_IS_HUGE,
.return_mask = PAGE_IS_WRITTEN | PAGE_IS_SWAPPED |

View File

@@ -471,7 +471,7 @@ update the core ranking and set the cpu's priority.
Kernel Parameters
-----------------
``amd-pstate`` peferred core`` has two states: enable and disable.
``amd-pstate`` preferred core has two states: enable and disable.
Enable/disable states can be chosen by different kernel parameters.
Default enable ``amd-pstate`` preferred core.

View File

@@ -61,12 +61,12 @@ manpages_url = 'https://man7.org/linux/man-pages/man{section}/{page}.{section}.h
def config_init(app, config):
"""
Initialize path-dependent variabled
Initialize path-dependent variables
On Sphinx, all directories are relative to what it is passed as
SOURCEDIR parameter for sphinx-build. Due to that, all patterns
that have directory names on it need to be dynamically set, after
converting them to a relative patch.
converting them to a relative path.
As Sphinx doesn't include any patterns outside SOURCEDIR, we should
exclude relative patterns that start with "../".
@@ -287,7 +287,7 @@ author = "The kernel development community"
try:
makefile_version = None
makefile_patchlevel = None
with open("../Makefile", encoding="utf=8") as fp:
with open("../Makefile", encoding="utf-8") as fp:
for line in fp:
key, val = [x.strip() for x in line.split("=", 2)]
if key == "VERSION":

View File

@@ -0,0 +1,11 @@
.. SPDX-License-Identifier: GPL-2.0+
==============
SMP primitives
==============
.. kernel-doc:: include/linux/smp.h
:internal:
.. kernel-doc:: kernel/smp.c
:export:

View File

@@ -508,7 +508,7 @@ call to dma_iova_try_alloc. This can be useful in the unmap path.
Is used to link ranges to the IOVA previously allocated. The start of all
but the first call to dma_iova_link for a given state must be aligned
to the DMA merge boundary returned by ``dma_get_merge_boundary())``, and
to the DMA merge boundary returned by ``dma_get_merge_boundary()``, and
the size of all but the last range must be aligned to the DMA merge boundary
as well.

View File

@@ -143,7 +143,7 @@ Because of this, it's often advantageous to first do an errseq_check to
see if anything has changed, and only later do an
errseq_check_and_advance after taking the lock. e.g.::
if (errseq_check(&wd.wd_err, READ_ONCE(su.s_wd_err)) {
if (errseq_check(&wd.wd_err, READ_ONCE(su.s_wd_err))) {
/* su.s_wd_err is protected by s_wd_err_lock */
spin_lock(&su.s_wd_err_lock);
err = errseq_check_and_advance(&wd.wd_err, &su.s_wd_err);

View File

@@ -81,6 +81,7 @@ Documentation/locking/index.rst for more related documentation.
padata
../RCU/index
wrappers/memory-barriers.rst
SMP
Low-level hardware management
=============================

View File

@@ -458,7 +458,7 @@ The list_move() and list_move_tail() functions can be used to move an entry
from one list to another, to either the start or end respectively.
In the following example, we'll assume we start with two lists ("clowns" and
"sidewalk" in the following initial state "State 0"::
"sidewalk") in the following initial state "State 0"::
.----------------------------------------------------------------.
v |

View File

@@ -240,19 +240,6 @@ This macro returns `true` if the heap is full, otherwise `false`.
**Inline Version:** min_heap_full_inline(heap)
- **min_heap_empty(heap)**: Checks whether the heap is empty.
Complexity: **O(1)**.
.. code-block:: c
bool empty = min_heap_empty(heap);
- `heap`: A pointer to the min-heap to check.
This macro returns `true` if the heap is empty, otherwise `false`.
**Inline Version:** min_heap_empty_inline(heap)
Example Usage
=============

View File

@@ -330,7 +330,7 @@ Here is an example of how to use the fields APIs:
void unpack_your_data(const packed_buf_t *buf, struct data *unpacked)
{
BUILD_BUG_ON(sizeof(*buf) != SIZE;
BUILD_BUG_ON(sizeof(*buf) != SIZE);
unpack_fields(buf, sizeof(*buf), unpacked, fields,
QUIRK_LITTLE_ENDIAN);
@@ -338,7 +338,7 @@ Here is an example of how to use the fields APIs:
void pack_your_data(const struct data *unpacked, packed_buf_t *buf)
{
BUILD_BUG_ON(sizeof(*buf) != SIZE;
BUILD_BUG_ON(sizeof(*buf) != SIZE);
pack_fields(buf, sizeof(*buf), unpacked, fields,
QUIRK_LITTLE_ENDIAN);

View File

@@ -130,3 +130,107 @@ https://github.com/Linutronix/RTC-Testbench.
The goal of this project is to validate real-time network communication. It can
be thought of as a "cyclictest" for networking and also serves as a starting
point for application development.
Firmware
--------
The firmware often plays a significant role in system operation because it can
perform tasks that the kernel cannot directly access, and in some cases it can
even preempt or intercept the kernel.
A common example of firmware assisting the kernel is when it provides a generic
interface to a resource. Instead of accessing an RTC chip through an I2C host
controller, the kernel may query the firmware for the current time, and the
firmware then accesses the RTC behind the scenes.
Firmware can also intercept kernel execution by providing services that
temporarily take control of the system. One example is memory scrubbing, where
the firmware periodically pauses the kernel, reads back portions of system
memory, and then returns control. During this time, the kernel is effectively
interrupted.
In contrast, some systems provide hardware-based memory scrubbing, which
operates independently of firmware or software. See
Documentation/edac/scrub.rst for details.
If the kernel is intercepted for longer periods then these periods can be made
visible with the hardware latency detector. See
Documentation/trace/hwlat_detector.rst.
The kernel can also be intercepted in response to specific events, such as
overheating. In this case, the firmware may throttle the CPU or shut it down
immediately to prevent hardware damage.
Unless the firmware is well documented, it should be thoroughly tested to
uncover any unexpected behaviour.
EFI
~~~~
EFI provides runtime services that act as a communication interface between the
firmware and the operating system. One such service is reading and writing EFI
variables, which are used, for example, to determine the boot source.
Invoking a runtime service may require the architecture to disable kernel
preemption or interrupts during the call. This means the duration of a service
invocation directly affects the systems observable latency. There is also
nothing that prevents a service call from disabling interrupts internally while
it runs.
For these reasons, EFI runtime services are disabled by default on a PREEMPT_RT
kernel. They can still be enabled at boot time or via a Kconfig option if
required.
The native EFI runtime service implementation (where both the EFI service and
the kernel are either 32-bit or 64-bit executables) uses a wrapper mechanism
that invokes the service through a dedicated workqueue. This workqueue is named
efi_runtime, and it can be restricted to a housekeeping CPU using the
``/sys/devices/virtual/workqueue/efi_runtime/cpumask`` sysfs file. Assigning it
to a housekeeping CPU ensures that potentially long service invocations do not
impact the real-time workload which is restricted to other CPUs.
It must also be verified that the runtime services behave as expected. Some
implementations on the x86 architecture pause all other CPUs while one CPU
performs the service call. In such cases, the interruption affects all CPUs,
and restricting the workqueue to a single CPU provides no benefit.
OP-TEE (ARM)
~~~~~~~~~~~~
Execution flows from the normal world (Linux) into the secure world (OP-TEE)
through the secure monitor at EL3. The transition is initiated by the `smc`
(Secure Monitor Call) opcode or the `hvc` (Hypervisor Call) opcode together
with a function identifier. The calling convention defines two types of calls:
**yielding calls** and **fast calls**:
- A **yielding call** unmasks interrupts before handling the requested service,
allowing normal world interrupts to occur.
- A **fast call** handles the requested service atomically, without allowing
interrupts from either the normal world or the secure world.
In addition, the secure world (EL3 and OP-TEE) can receive interrupts routed to
the secure world. While a secure world interrupt is being serviced,
normal world interrupts are masked and cannot preempt the operation.
The transition from normal world to secure monitor to OP-TEE and back introduces
additional latency due to world switching and context save/restore. This
overhead is typically a few microseconds and usually remains within the noise
floor.
It is worth noting that the normal world cannot mask secure interrupts, while
the secure world can mask normal-world interrupts during execution. How OP-TEE
affects real-time workloads depends on whether secure interrupts are enabled
and which OP-TEE services are invoked.
A practical concern is any fast call that runs longer than expected, for
example a function that occasionally performs a long-running cryptographic
computation. Another example that may block in an unexpected way are OP-TEE
drivers that issue RPC requests. An OP-TEE service in the secure world (RPMB
for instance) may need to issue a request back to the normal world (the Linux
driver) in order to complete the operation. While Linux remains preemptible,
the thread that issued the request stays blocked until the RPC completes and
the secure function call returns.
The TF-A project provides documentation on interrupt management:
https://trustedfirmware-a.readthedocs.io/en/latest/design/interrupt-framework-design.html#interrupt-management-framework
The OP-TEE project provides documentation on how interrupts are handled:
https://optee.readthedocs.io/en/latest/architecture/core.html#interrupt-handling

View File

@@ -15,3 +15,4 @@ the required changes compared to a non-PREEMPT_RT configuration.
differences
hardware
architecture-porting
kernel-configuration

View File

@@ -0,0 +1,307 @@
.. SPDX-License-Identifier: GPL-2.0
==============================
Real-Time Kernel configuration
==============================
.. contents:: Table of Contents
:depth: 3
:local:
Introduction
============
This document lists the kernel configuration options that might affect a
real-time kernel's worst-case latency. It is intended for system integrators.
Configuration options
=====================
.. Please keep the configuration listings alphabetically ordered
CPU frequency governors
-----------------------
``CONFIG_CPU_FREQ``
^^^^^^^^^^^^^^^^^^^
:Expectation: enabled
:Severity: *high*
The CPU frequency scaling subsystem ensures that the processor can operate at
its maximum supported frequency. While, in general, bootloaders are tasked
with setting the CPU clock to the highest speed on boot, some do not. It is
thus desirable to keep this option enabled.
.. caution::
A real-time kernel is not about being "as fast as possible", however
real-time requirements may demand that the CPU is clocked at a particular
speed.
``CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:Expectation: enabled
:Severity: *high*
Real-Time workloads expect a fixed CPU frequency during execution. Using the
performance governor is an easy way to achieve that purely from kernel
configuration.
This is not an absolute rule. Some setups might prefer to clock the CPU to
lower speeds due to thermal packaging or other requirements. The key is that
the CPU frequency remains constant once set.
Non-performance CPU frequency governors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:Expectation: disabled
:Severity: *medium*
To ensure reproducible system latency measurements, disable the
non-``PERFORMANCE`` CPU frequency governors whenever possible. This avoids
the risk of unknown userspace tasks implicitly or explicitly setting a
different CPU frequency governor, and thereby changing latency behavior while
the system is running.
If disabling other frequency governors is not an option, use a governor that
keeps the CPU frequency fixed. For example,
``CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE`` can be enabled when userspace is
responsible for setting a *stable* frequency during system initialization.
If a low CPU frequency is desired, then
``CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE`` can be set.
The ``ONDEMAND`` governor should not be enabled on a real-time system. Its
frequency changes depend on workload behavior and can significantly harm
determinism.
For more information, see Documentation/admin-guide/pm/cpufreq.rst
``CONFIG_CPU_IDLE``
-------------------
:Expectation: enabled
:Severity: *info*
CPU idle states (C-states) allow the processor to enter low-power modes during
periods of inactivity. Very-low CPU idle states may require flushing the CPU
caches and lowering or disabling the clocking. This can lower power
consumption, but it also increases the entry and exit latency from such
states.
While disabling this option eliminates cpuidle-related latencies, doing so can
significantly impact hardware longevity, warranty, and thermal behavior.
Users should cap the maximum C-state to C1 instead. For ACPI platforms, this
can be achieved by using the boot parameter [1]_::
processor.max_cstate=1
Higher C-states can be acceptable depending on the user workload's latency
requirements. For ACPI-based platforms, use the ``cpupower idle-info``
command to inspect the available idle states.
For more information, please see:
- ``linux/tools/power/cpupower``
- Documentation/admin-guide/pm/cpuidle.rst
- Documentation/admin-guide/pm/index.rst
``CONFIG_DRM``
--------------
:Expectation: disabled
:Severity: *info*
GPU-accelerated workloads can share system resources with the CPU, including
last-level cache (LLC) and memory bandwidth. Modern integrated GPUs optimize
graphics performance at the expense of CPU determinism.
Examples of affected platforms:
- Intel processors with integrated graphics (Gen9 and later)
- AMD APUs with Radeon Graphics
- Xilinx Zynq UltraScale+ MPSoC EG/EV series
If graphics workloads must run alongside real-time tasks, users must conduct
thorough stress testing using tools like ``glmark2`` while measuring the
overall system latency.
For more information, please check:
- Documentation/core-api/real-time/hardware.rst ("Regarding hardware" section)
- Documentation/filesystems/resctrl.rst
- `Real-Time and Graphics: A Contradiction? <https://web.archive.org/web/20221025085614/https://linutronix.de/PDF/Realtime_and_graphics-acontradiction2021.pdf>`_
``CONFIG_EFI_DISABLE_RUNTIME``
------------------------------
:Expectation: enabled
:Severity: *medium*
EFI is the standard boot and firmware interface for multiple architectures.
EFI runtime services provide callback functions to be called from the kernel;
e.g., as utilized by (``CONFIG_EFI_VARS*``) or (``CONFIG_RTC_DRV_EFI``). For
the former, the kernel calls into EFI to update the EFI variables.
Calling into EFI means invoking firmware callbacks. During such invocations,
the system might not be able to react to interrupts and will thus not be able
to perform a context switch. This can cause significant latency spikes for
the real-time system.
``CONFIG_PREEMPT_RT`` enables this option by default. If this option is
manually disabled at build time, the following boot parameter [1]_ may be used
to disable EFI runtime at boot up::
efi=noruntime
Alternatively, confine EFI runtime service calls to a housekeeping CPU by
restricting the ``efi_runtime`` workqueue CPU affinity. For example, set that
workqueue's affinity to CPU #0 and pin your RT tasks to a different CPU range.
See Documentation/core-api/workqueue.rst
``CONFIG_NO_HZ`` / ``CONFIG_NO_HZ_FULL``
----------------------------------------
:Expectation: disabled
:Severity: *medium*
Tickless operation can increase kernel-to-userspace transition latency due to
the extra accounting and state book-keeping.
*Guidance by real-time workload type:*
- For periodic workloads; e.g., control loops executing every 100 µs, avoid
``NO_HZ`` modes. Consistent kernel ticks are preferable.
- For computation-intensive workloads; e.g. extended userspace execution,
``NO_HZ_FULL`` may be beneficial. In such cases, users should offload the
kernel housekeeping to dedicated CPUs and isolate compute cores.
See also Documentation/timers/no_hz.rst
``CONFIG_PREEMPT_RT``
---------------------
:Expectation: enabled
:Severity: **fatal**
This option must be enabled, or the resulting kernel will not be fully
preemptible and real-time capable.
``CONFIG_TRACING`` (and tracing options)
----------------------------------------
:Expectation: enabled
:Severity: *info*
Shipping kernels with tracing support enabled (but not actively running) is
highly recommended. This will allow the users to extract more information if
latency problems arise. Nonetheless, some tracers do incur latency overhead
just by being enabled.
.. caution::
Users should *not* make use of tracers or trace events during production
real-time kernel operation as they can add considerable overhead and degrade
the system's latency.
``CONFIG_IRQSOFF_TRACER`` and ``CONFIG_PREEMPT_TRACER``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:Expectation: disabled
:Severity: *high*
These tracers do incur measurable latency overhead even when tracing is not
currently active.
Kernel Debug Options
====================
Most kernel debug options add runtime overhead that increases the worst-case
latency.
.. caution::
During development and early testing, users are encouraged to run their
real-time workloads and peripherals with lockdep (:ref:`lockdep`) and other
kernel debug options enabled, for a considerable amount of time. Such
workloads might trigger kernel code paths that were not triggered during the
internal Linux real-time kernel development, thus helping to uncover locking
and other types of kernel bugs.
``CONFIG_DEBUG_ATOMIC_SLEEP``
-----------------------------
:Expectation: allowed
This sanity check catches common kernel programming errors with a tolerable
latency cost. It also increases overall scheduling as each ``might_sleep()``
can lead to a context switch.
``CONFIG_DEBUG_BUGVERBOSE`` and ``CONFIG_DEBUG_INFO*``
------------------------------------------------------
:Expectation: allowed
These options increase the kernel image size but have no latency impact. They
are also essential for meaningful BUG logs, crash dumps, and profiling.
``CONFIG_DEBUG_FS``
-------------------
:Expectation: allowed
This is safe to include in real-time kernels, *provided that debugfs is not
accessed during production runtime*.
``CONFIG_DEBUG_KERNEL``
-----------------------
:Expectation: allowed
Meta-option which allows debug features to be enabled. It has no runtime
impact, but beware of any debug features that it may have implicitly enabled.
``CONFIG_LOCKUP_DETECTOR``
--------------------------
:Expectation: disabled
:Severity: *high*
The lockup detector creates kernel timer callbacks that execute every few
seconds, in hard-IRQ context, even on real-time kernels. These periodic
interrupts can cause latency spikes.
Users should use hardware watchdogs instead, which will provide a similar
functionality without the software-induced latency.
.. _lockdep:
``CONFIG_PROVE_LOCKING``
------------------------
:Expectation: disabled
:Severity: *high*
Proving the correctness of all kernel locking adds substantial overhead and
significantly increases worst-case latency.
Summary
=======
There is no "one size fits all" solution for configuring a real-time Linux
system. Beginning with the system real-time requirements, integrators must
consider the features and functions of the system's hardware, kernel, and
userspace. All such components must be properly configured in order to
establish and constrain the system's maximum latency.
With that in mind, any incorrect real-time kernel configuration could cause a
new maximum latency that shows up at the wrong time and is catastrophic for
the real-time system's latency.
References
==========
.. [1] See Documentation/admin-guide/kernel-parameters.rst

View File

@@ -40,7 +40,7 @@ Available options:
``-r, --runtime RUNTIME``
Container runtime name. Supported runtimes: ``docker``, ``podman``.
Container runtime name. Supported runtimes: ``podman``, ``docker``.
If not specified, the first one found on the system will be used
i.e. Podman if present, otherwise Docker.
@@ -75,8 +75,8 @@ working directory and adjust the user and group id as needed.
The container image which would typically include a compiler toolchain is
provided by the user and selected via the ``-i`` option. The container runtime
can be selected with the ``-r`` option, which can be either ``docker`` or
``podman``. If none is specified, the first one found on the system will be
can be selected with the ``-r`` option, which can be either ``podman`` or
``docker``. If none is specified, the first one found on the system will be
used while giving priority to Podman. Support for other runtimes may be added
later depending on their popularity among users.

View File

@@ -280,7 +280,7 @@ Creating the User
To use the message handler, you must first create a user using
ipmi_create_user. The interface number specifies which SMI you want
to connect to, and you must supply callback functions to be called
when data comes in. This also allows to you pass in a piece of data,
when data comes in. This also allows you to pass in a piece of data,
the handler_data, that will be passed back to you on all calls.
Once you are done, call ipmi_destroy_user() to get rid of the user.

View File

@@ -322,7 +322,4 @@ http://linux-hotplug.sourceforge.net/
linux-usb Mailing List Archives:
https://lore.kernel.org/linux-usb/
Programming Guide for Linux USB Device Drivers:
https://lmu.web.psi.ch/docu/manuals/software_manuals/linux_sl/usb_linux_programming_guide.pdf
USB Home Page: https://www.usb.org

View File

@@ -123,8 +123,7 @@ At mount time, the two directories given as mount options "lowerdir" and
mount -t overlay overlay -olowerdir=/lower,upperdir=/upper,\
workdir=/work /merged
The "workdir" needs to be an empty directory on the same filesystem
as upperdir.
The "workdir" needs to be a directory on the same filesystem as upperdir.
Then whenever a lookup is requested in such a merged directory, the
lookup is performed in each actual directory and the combined result

View File

@@ -513,7 +513,7 @@ In some kernel configurations, the semantics of pages part of a larger
allocation (e.g., THP) can differ: a page is accounted as "private" if all
pages part of the corresponding large allocation are *certainly* mapped in the
same process, even if the page is mapped multiple times in that process. A
page is accounted as "shared" if any page page of the larger allocation
page is accounted as "shared" if any page of the larger allocation
is *maybe* mapped in a different process. In some cases, a large allocation
might be treated as "maybe mapped by multiple processes" even though this
is no longer the case.

View File

@@ -21,6 +21,7 @@ community and getting your work upstream.
.. toctree::
:maxdepth: 1
:caption: Working with the development community
Development process <process/development-process>
Submitting patches <process/submitting-patches>
@@ -37,6 +38,7 @@ kernel.
.. toctree::
:maxdepth: 1
:caption: Internal API manuals
Core API <core-api/index>
Driver APIs <driver-api/index>
@@ -50,6 +52,7 @@ Various other manuals with useful information for all kernel developers.
.. toctree::
:maxdepth: 1
:caption: Development tools and processes
Licensing rules <process/license-rules>
Writing documentation <doc-guide/index>
@@ -71,6 +74,7 @@ developers seeking information on the kernel's user-space APIs.
.. toctree::
:maxdepth: 1
:caption: User-oriented documentation
Administration <admin-guide/index>
Build system <kbuild/index>
@@ -88,6 +92,7 @@ platform firmware.
.. toctree::
:maxdepth: 1
:caption: Firmware-related documentation
Firmware <firmware-guide/index>
Firmware and Devicetree <devicetree/index>
@@ -98,6 +103,7 @@ Architecture-specific documentation
.. toctree::
:maxdepth: 2
:caption: Architecture-specific documentation
CPU architectures <arch/index>
@@ -111,6 +117,7 @@ to reStructuredText format, or are simply too old.
.. toctree::
:maxdepth: 1
:caption: Other documentation
Unsorted documentation <staging/index>
@@ -120,6 +127,7 @@ Translations
.. toctree::
:maxdepth: 2
:caption: Translations
Translations <translations/index>

View File

@@ -471,7 +471,7 @@ to protect the cache and all the objects within it. Here's the code::
obj = __cache_find(id);
if (obj) {
ret = 0;
strcpy(name, obj->name);
strscpy(name, obj->name);
}
mutex_unlock(&cache_lock);
return ret;
@@ -553,7 +553,7 @@ which are taken away, and the ``+`` are lines which are added.
obj = __cache_find(id);
if (obj) {
ret = 0;
strcpy(name, obj->name);
strscpy(name, obj->name);
}
- mutex_unlock(&cache_lock);
+ spin_unlock_irqrestore(&cache_lock, flags);
@@ -676,7 +676,7 @@ Here is the code::
obj = __cache_find(id);
- if (obj) {
- ret = 0;
- strcpy(name, obj->name);
- strscpy(name, obj->name);
- }
+ if (obj)
+ __object_get(obj);
@@ -1317,7 +1317,7 @@ from user context, and can sleep.
- put_user()
- kmalloc(GP_KERNEL) <kmalloc>`
- kmalloc(GFP_KERNEL) <kmalloc>
- mutex_lock_interruptible() and
mutex_lock()

View File

@@ -15,6 +15,10 @@ kernel development process:
* Documentation/process/coding-style.rst
* Documentation/process/submitting-patches.rst
For guidelines on content generated by AI coding assistants see:
* Documentation/process/generated-content.rst
Licensing and Legal Requirements
================================
@@ -43,12 +47,8 @@ When AI tools contribute to kernel development, proper attribution
helps track the evolving role of AI in the development process.
Contributions should include an Assisted-by tag in the following format::
Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]
Assisted-by: LLM [TOOL1] [TOOL2]
Where:
* ``AGENT_NAME`` is the name of the AI tool or framework
* ``MODEL_VERSION`` is the specific model version used
* ``[TOOL1] [TOOL2]`` are optional specialized analysis tools used
(e.g., coccinelle, sparse, smatch, clang-tidy)
@@ -56,7 +56,7 @@ Basic development tools (git, gcc, make, editors) should not be listed.
Example::
Assisted-by: Claude:claude-3-opus coccinelle sparse
Assisted-by: LLM coccinelle sparse
Procedure for finding and fixing bugs
=====================================

View File

@@ -107,3 +107,10 @@ the resulting changes.
If you do so anyway, maintainers are entitled to reject your series
without detailed review.
References
==========
For specific guidelines on AI coding assistants, see:
* Documentation/process/coding-assistants.rst

View File

@@ -404,12 +404,11 @@ patches that are being emailed around.
The sign-off is a simple line at the end of the explanation for the
patch, which certifies that you wrote it or otherwise have the right to
pass it on as an open-source patch. The rules are pretty simple: if you
can certify the below:
can certify the below::
Developer's Certificate of Origin 1.1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
@@ -554,12 +553,11 @@ some testing has been performed, provides a means to locate testers for
future patches, and ensures credit for the testers.
Reviewed-by:, instead, indicates that the patch has been reviewed and found
acceptable according to the Reviewer's Statement:
acceptable according to the Reviewer's Statement::
Reviewer's statement of oversight
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Reviewer's statement of oversight
By offering my Reviewed-by: tag, I state that:
By offering my Reviewed-by: tag, I state that:
(a) I have carried out a technical review of this patch to
evaluate its appropriateness and readiness for inclusion into

View File

@@ -141,7 +141,7 @@ in its previous activation.
find_energy_efficient_cpu() uses compute_energy() to estimate what will be the
energy consumed by the system if the waking task was migrated. compute_energy()
looks at the current utilization landscape of the CPUs and adjusts it to
'simulate' the task migration. The EM framework provides the em_pd_energy() API
'simulate' the task migration. The EM framework provides the em_cpu_energy() API
which computes the expected energy consumption of each performance domain for
the given utilization landscape.

View File

@@ -25,7 +25,8 @@ void calc_runnable_avg_yN_inv(void)
for (i = 0; i < HALFLIFE; i++) {
x = ((1UL<<32)-1)*pow(y, i);
if (i % 6 == 0) printf("\n\t");
if (i % 6 == 0)
printf("\n\t");
printf("0x%8x, ", x);
}
printf("\n};\n\n");

View File

@@ -3,6 +3,8 @@
* CSS tweaks for the Alabaster theme
*/
div.body { max-width: 120em; }
/* Shrink the headers a bit */
div.body h1 { font-size: 180%; }
div.body h2 { font-size: 150%; }
@@ -75,6 +77,19 @@ div.kerneltoc li.current ul { margin-left: 0; }
div.kerneltoc { background-color: #eeeeee; }
div.kerneltoc li.current ul { background-color: white; }
/*
* Hide toctree captions on the welcome page, they should only be shown in the
* sidebar.
*/
section#the-linux-kernel-documentation p.caption { display: none; }
/*
* Make section titles bold in the sidebar, and decrease their bottom margin to
* group them with their subsections.
*/
div.sphinxsidebar p.caption { font-weight: bold; margin-bottom: 0; }
div.sphinxsidebar p.caption + ul { margin-top: 0; }
/*
* The CSS magic to toggle the contents on small screens.
*/
@@ -156,15 +171,6 @@ div.language-selection ul li:hover {
background: #dddddd;
}
/*
* Let long inline literals in paragraph text wrap as needed to prevent
* overflow.
*/
code.docutils.literal span.pre {
white-space: normal;
overflow-wrap: anywhere;
}
/* Let rendered reference links in tables wrap when needed. */
div.body table.docutils a.reference {
overflow-wrap: anywhere;

View File

@@ -161,7 +161,7 @@ class MaintainersParser:
html = KERNELDOC_URL + ename + ".html"
entries[entry] = f'`{ename} <{html}>`_'
else:
entries[entry] = f':doc:`{ename} </{entry}>`'
entries[entry] = f'/{entry}'
return entries
@@ -345,7 +345,10 @@ class MaintainersProfile(Include):
output += f"- {name}: {entry}\n"
self.warning(f"{profile}: Invalid 'P' tag: {entry}\n")
else:
output += f"- {entry}\n"
if not name:
name = entry
output += f"- :doc:`{name} <{entry}>`\n"
#
# Create a hidden TOC table with all profiles. That allows adding

View File

@@ -0,0 +1,59 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-ita.rst
Verificare la necessità di aggiornare le traduzioni
===================================================
Questo script aiuta a tracciare lo stato delle traduzioni della
documentazione nelle diverse lingue, ovvero se la documentazione è
allineata con la controparte inglese.
Come funziona
-------------
Lo script usa il comando ``git log`` per individuare l'ultimo commit in inglese
a partire dal commit della traduzione (in ordine di data dell'autore) e gli
ultimi commit in inglese a partire da HEAD. Se emergono delle differenze, il
file viene considerato non aggiornato, e vengono quindi raccolti e segnalati i
commit che necessitano di un aggiornamento.
Funzionalità implementate
- verifica di tutti i file in una determinata lingua
- verifica di un singolo file o di un insieme di file
- opzioni per modificare il formato dell'output
- tracciamento dello stato di traduzione dei file che non hanno alcuna
traduzione
Utilizzo
--------
::
tools/docs/checktransupdate.py --help
Fate riferimento all'output del messaggio d'aiuto per i dettagli sull'utilizzo.
Esempi
- ``tools/docs/checktransupdate.py -l zh_CN``
Questo stamperà tutti i file che necessitano di un aggiornamento nella
lingua zh_CN.
- ``tools/docs/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst``
Questo stamperà solamente lo stato del file specificato.
L'output sarà quindi qualcosa del genere:
::
Documentation/dev-tools/kfence.rst
No translation in the locale of zh_CN
Documentation/translations/zh_CN/dev-tools/testing-overview.rst
commit 42fb9cfd5b18 ("Documentation: dev-tools: Add link to RV docs")
1 commits needs resolving in total
Funzionalità ancora da implementare
- specificare cartelle in aggiunta ai singoli file

View File

@@ -0,0 +1,319 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-ita.rst
Come contribuire al miglioramento della documentazione del kernel
=================================================================
La documentazione è una parte importante di ogni progetto di sviluppo
software. Una buona documentazione aiuta ad attirare nuovi sviluppatori e
permette a quelli già presenti di lavorare in modo più efficace. Senza una
documentazione di qualità, si spreca molto tempo nel decifrare il codice a
ritroso e si commettono errori altrimenti evitabili.
Sfortunatamente, al momento la documentazione del kernel è ben lontana da
quello che dovrebbe essere per sostenere un progetto di queste dimensioni e
importanza.
Questa guida è per chi vuole contribuire a migliorare questa situazione. I
miglioramenti alla documentazione del kernel possono essere fatti da
sviluppatori con diversi livelli di esperienza; sono un modo relativamente
semplice per imparare il processo di sviluppo del kernel in generale e
trovare il proprio posto nella comunità. Quello che segue è, per la maggior
parte, l'elenco dei compiti che il manutentore della documentazione ritiene
più urgenti.
Le cose da fare nella documentazione
------------------------------------
C'è un elenco infinito di compiti da svolgere per portare la nostra
documentazione al livello in cui dovrebbe essere. Questo elenco contiene
alcuni punti importanti, ma è lungi dall'essere esaustivo; se trovate un
modo diverso per migliorare la documentazione, non esitate!
Correzione degli avvisi
~~~~~~~~~~~~~~~~~~~~~~~
Al momento, la generazione della documentazione produce un numero
incredibile di avvisi. Quando ce ne sono così tanti, è come se non ce ne
fosse nessuno: le persone li ignorano e non si accorgeranno mai quando il
loro lavoro ne aggiunge di nuovi. Per questo motivo, eliminare gli avvisi è
uno dei compiti a più alta priorità nell'elenco delle cose da fare per la
documentazione. Il compito in sé è ragionevolmente semplice, ma va
affrontato nel modo giusto per avere successo.
Gli avvisi emessi da un compilatore per il codice C possono spesso essere
scartati come falsi positivi, portando a patch il cui unico scopo è zittire
il compilatore. Gli avvisi generati dalla documentazione, invece, indicano
quasi sempre un problema reale; farli sparire richiede di comprendere il
problema e correggerlo alla radice. Per questo motivo, le patch che
correggono avvisi nella documentazione non dovrebbero limitarsi a dire "fix
a warning" nel titolo del changelog; dovrebbero invece indicare il problema
reale che è stato corretto.
Un altro punto importante è che gli avvisi nella documentazione sono spesso
generati da problemi nei commenti kerneldoc all'interno del codice C. Anche se
il manutentore della documentazione apprezza l'essere messo in copia sulle
correzioni di questo tipo, in realtà spesso rivolgersi al sottosistema di
documentazione non è il modo migliore di apportare queste modifiche; queste
dovrebbero invece essere inviate al manutentore del sottosistema in questione.
Per esempio, in una generazione della documentazione ho preso, quasi a
caso, un paio di avvisi::
./drivers/devfreq/devfreq.c:1818: warning: bad line:
- Resource-managed devfreq_register_notifier()
./drivers/devfreq/devfreq.c:1854: warning: bad line:
- Resource-managed devfreq_unregister_notifier()
(Le righe sono state divise per essere più leggibili).
Una rapida occhiata al file sorgente indicato sopra ha rivelato un paio di
commenti kerneldoc con questo aspetto::
/**
* devm_devfreq_register_notifier()
- Resource-managed devfreq_register_notifier()
* @dev: The devfreq user device. (parent of devfreq)
* @devfreq: The devfreq object.
* @nb: The notifier block to be unregistered.
* @list: DEVFREQ_TRANSITION_NOTIFIER.
*/
Il problema è l'asterisco mancante, che confonde l'idea semplicistica che il
sistema di generazione abbia idea di come debba essere fatto un blocco di
commento C. Questo problema era presente fin da quando quel commento venne
aggiunto nel 2016, quindi da diversi anni. Correggerlo è stata solo questione di
aggiungere gli asterischi mancanti. Una rapida occhiata alla cronologia di quel
file ha mostrato quale fosse il formato usuale per la riga dell'oggetto, e
``scripts/get_maintainer.pl`` mi ha detto chi dovesse riceverla (basta passare
il percorso delle vostre patch come argomento a scripts/get_maintainer.pl). La
patch risultante era questa::
[PATCH] PM / devfreq: Fix two malformed kerneldoc comments
Two kerneldoc comments in devfreq.c fail to adhere to the required format,
resulting in these doc-build warnings:
./drivers/devfreq/devfreq.c:1818: warning: bad line:
- Resource-managed devfreq_register_notifier()
./drivers/devfreq/devfreq.c:1854: warning: bad line:
- Resource-managed devfreq_unregister_notifier()
Add a couple of missing asterisks and make kerneldoc a little happier.
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
drivers/devfreq/devfreq.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 57f6944d65a6..00c9b80b3d33 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1814,7 +1814,7 @@ static void devm_devfreq_notifier_release(struct device *dev, void *res)
/**
* devm_devfreq_register_notifier()
- - Resource-managed devfreq_register_notifier()
+ * - Resource-managed devfreq_register_notifier()
* @dev: The devfreq user device. (parent of devfreq)
* @devfreq: The devfreq object.
* @nb: The notifier block to be unregistered.
@@ -1850,7 +1850,7 @@ EXPORT_SYMBOL(devm_devfreq_register_notifier);
/**
* devm_devfreq_unregister_notifier()
- - Resource-managed devfreq_unregister_notifier()
+ * - Resource-managed devfreq_unregister_notifier()
* @dev: The devfreq user device. (parent of devfreq)
* @devfreq: The devfreq object.
* @nb: The notifier block to be unregistered.
--
2.24.1
L'intero procedimento ha richiesto solo pochi minuti. Naturalmente, ho poi
scoperto che qualcun altro l'aveva già corretto in un altro albero,
mettendo in luce un'altra lezione: controllate sempre linux-next per
vedere se un problema è già stato risolto prima di mettervici sopra.
Altre correzioni richiederanno più tempo, specialmente quelle relative ai
campi di una struttura o ai parametri di una funzione privi di
documentazione. In questi casi, è necessario capire quale sia il ruolo di
questi campi o parametri e descriverli correttamente. Nel complesso, questo
compito diventa un po' tedioso a volte, ma è molto importante. Se riusciamo
davvero ad eliminare gli avvisi dalla generazione della documentazione,
allora potremo iniziare a pretendere che gli sviluppatori evitino di
aggiungerne di nuovi.
Oltre ai normali avvisi durante la generazione della documentazione, potete
ottenerne di più eseguendo ``make refcheckdocs`` per trovare riferimenti a file
di documentazione inesistenti.
Commenti kerneldoc dimenticati
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Gli sviluppatori sono incoraggiati a scrivere commenti kerneldoc per il
loro codice, ma molti di questi commenti non vengono mai inclusi nella
generazione della documentazione. Questo rende tale informazione più
difficile da trovare e, per esempio, impedisce a Sphinx di generare
collegamenti verso quella documentazione. Aggiungere le direttive
``kernel-doc`` alla documentazione per includere quei commenti può aiutare
la comunità a ottenere il pieno valore del lavoro speso per crearli.
Lo strumento ``tools/docs/find-unused-docs.sh`` può essere usato per
trovare questi commenti dimenticati.
Da notare che il valore maggiore deriva dall'includere la documentazione
per le funzioni e le strutture dati esportate. Molti sottosistemi hanno
anche commenti kerneldoc per uso interno; questi non dovrebbero essere
inclusi nella generazione della documentazione a meno che non vengano
posti in un documento specificamente rivolto agli sviluppatori che
lavorano all'interno del sottosistema in questione.
Correzione dei refusi
~~~~~~~~~~~~~~~~~~~~~
Correggere errori di battitura o di formattazione nella documentazione è
un modo rapido per imparare come creare e inviare patch, ed è un servizio
utile. Sono sempre disposto ad accettare questo tipo di patch. Detto
questo, una volta che ne avete corretti alcuni, considerate di passare a
compiti più avanzati, lasciando qualche refuso per il prossimo principiante
che vorrà occuparsene.
Da notare che alcune cose *non* sono refusi e non dovrebbero essere
"corrette":
- Sia la grafia americana che quella britannica dell'inglese sono
ammesse nella documentazione del kernel. Non c'è bisogno di sostituire
l'una con l'altra.
- La questione se un punto debba essere seguito da uno o due spazi non
va dibattuta nel contesto della documentazione del kernel. Anche
altri argomenti di legittimo disaccordo, come la "virgola di Oxford",
non sono pertinenti qui.
Come per qualsiasi patch a qualsiasi progetto, considerate se la vostra
modifica sta davvero migliorando le cose.
Documentazione datata
~~~~~~~~~~~~~~~~~~~~~
Parte della documentazione del kernel è attuale, mantenuta e utile.
Un'altra parte... non lo è. Documentazione impolverata, vecchia e
imprecisa può fuorviare i lettori e gettare discredito sulla nostra
documentazione nel suo complesso. Qualsiasi cosa si possa fare per
affrontare questi problemi è più che benvenuta.
Ogni volta che lavorate su un documento, considerate se è attuale, se ha
bisogno di essere aggiornato, o se forse dovrebbe essere rimosso del
tutto. Ci sono alcuni segnali d'allarme a cui potete prestare attenzione:
- Riferimenti a kernel della serie 2.x
- Rimandi a repositori su SourceForge
- Nella cronologia, negli ultimi anni, solo correzioni di refusi
- Discussioni su modi di lavorare precedenti a Git
La cosa migliore da fare, ovviamente, sarebbe portare la documentazione a
essere attuale, aggiungendo qualsiasi informazione necessaria. Un lavoro
simile spesso richiede la collaborazione di sviluppatori che conoscono bene
il sottosistema in questione. Gli sviluppatori, quando viene chiesto loro
gentilmente, e quando le loro risposte vengono ascoltate e messe in
pratica, sono spesso più che disposti a collaborare con chi lavora per
migliorare la documentazione.
Alcuni documenti sono senza speranza; a volte troviamo documenti che fanno
riferimento a codice rimosso dal kernel molto tempo fa, per esempio. C'è
una sorprendente resistenza a rimuovere la documentazione obsoleta, ma
dovremmo farlo comunque. Il materiale superfluo nella nostra documentazione
non è d'aiuto a nessuno.
Nei casi in cui, forse, ci sono informazioni utili in un documento
gravemente datato, e non siete in grado di aggiornarlo, la cosa migliore
da fare potrebbe essere aggiungere un avviso all'inizio. Si raccomanda il
seguente testo::
.. warning ::
This document is outdated and in need of attention. Please use
this information with caution, and please consider sending patches
to update it.
In questo modo, almeno i nostri pazientissimi lettori sono stati avvisati
che il documento potrebbe portarli fuori strada.
Coerenza della documentazione
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I veterani di qui ricorderanno i libri su Linux che comparvero sugli
scaffali negli anni '90. Erano semplicemente raccolte di file di
documentazione racimolati da varie fonti in rete. I libri sono (per lo
più) migliorati da allora, ma la documentazione del kernel è ancora per lo
più costruita su quel modello. Sono migliaia di file, quasi ognuno dei
quali è stato scritto in isolamento da tutti gli altri. Non abbiamo un
corpo coerente di documentazione del kernel; abbiamo migliaia di documenti
individuali.
Abbiamo cercato di migliorare la situazione creando un insieme di "libri"
che raggruppano la documentazione per specifici lettori. Questi
includono:
- Documentation/admin-guide/index.rst
- Documentation/core-api/index.rst
- Documentation/driver-api/index.rst
- Documentation/userspace-api/index.rst
Così come questo libro sulla documentazione stessa.
Spostare i documenti nei libri appropriati è un compito importante e deve
continuare. Ci sono, tuttavia, un paio di sfide associate a questo lavoro.
Spostare i file della documentazione, nel breve termine, infastidisce chi vi
lavora; comprensibilmente, non sono entusiasti di questi cambiamenti. Di solito
li si può convincere a spostarli una volta; tuttavia, non vogliamo continuare a
spostarli in giro.
Anche quando tutti i documenti sono al posto giusto, però, siamo solo
riusciti a trasformare un grande cumulo in un gruppo di cumuli più
piccoli. Il lavoro di cercare di tessere insieme tutti quei documenti in
un unico insieme non è ancora iniziato. Se avete idee brillanti su come
potremmo procedere su questo fronte, saremmo più che felici di sentirle.
Miglioramenti al foglio di stile
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Con l'adozione di Sphinx abbiamo un output HTML dall'aspetto molto più gradevole
di quanto avessimo un tempo. Ma è ancora migliorabile; Donald Knuth e Edward
Tufte non ne sarebbero impressionati. Questo richiede di modificare i nostri
fogli di stile per creare un output tipograficamente più solido, accessibile e
leggibile.
Attenzione: se vi assumete questo compito, vi state addentrando nel
classico territorio del "bikeshed". Aspettatevi molte opinioni e
discussioni anche per cambiamenti relativamente ovvi. Questa è, ahimè, la
natura del mondo in cui viviamo.
Generazione di PDF senza LaTeX
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Questo è un compito decisamente non banale per qualcuno con molto tempo a
disposizione e competenze in Python. La catena di strumenti di Sphinx è
relativamente piccola e ben contenuta; è facile da aggiungere a un sistema
di sviluppo. Ma generare output in PDF o EPUB richiede l'installazione di
LaTeX, che non è affatto piccolo o ben contenuto. Sarebbe una bella cosa
da eliminare.
La speranza originale era di usare lo strumento rst2pdf (https://rst2pdf.org/)
per la generazione dei PDF, ma si è scoperto che non era all'altezza del
compito. Il lavoro di sviluppo su rst2pdf sembra però essere ripreso di recente,
il che è un segno di speranza. Se uno sviluppatore adeguatamente motivato lo
migliorasse per far funzionare rst2pdf con la documentazione del kernel, il
mondo gli sarebbe eternamente grato.
Scrivere più documentazione
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Naturalmente, ci sono vaste parti del kernel che sono gravemente prive di
documentazione. Se avete la conoscenza per documentare uno specifico
sottosistema del kernel e il desiderio di farlo, non esitate a scrivere e
inviare il lavoro al kernel. Un numero incalcolabile di
sviluppatori e utenti del kernel vi ringrazierà.

View File

@@ -1,8 +1,5 @@
.. include:: ../disclaimer-ita.rst
.. note:: Per leggere la documentazione originale in inglese:
:ref:`Documentation/doc-guide/index.rst <doc_guide>`
.. _it_doc_guide:
==========================================
@@ -15,10 +12,6 @@ Come scrivere la documentazione del kernel
sphinx
kernel-doc
parse-headers
.. only:: subproject and html
Indices
=======
* :ref:`genindex`
contributing
maintainer-profile
checktransupdate

View File

@@ -1,12 +1,7 @@
.. include:: ../disclaimer-ita.rst
.. note:: Per leggere la documentazione originale in inglese:
:ref:`Documentation/doc-guide/index.rst <doc_guide>`
.. title:: Commenti in kernel-doc
.. _it_kernel_doc:
=================================
Scrivere i commenti in kernel-doc
=================================
@@ -82,11 +77,15 @@ che questo produca alcuna documentazione. Per esempio::
tools/docs/kernel-doc -v -none drivers/foo/bar.c
Il formato della documentazione è verificato della procedura di generazione
del kernel quando viene richiesto di effettuare dei controlli extra con GCC::
Il formato della documentazione dei file ``.c`` è verificato anche dalla
procedura di generazione del kernel quando viene richiesto di effettuare dei
controlli extra con GCC::
make W=n
Tuttavia, il comando precedente non verifica i file d'intestazione. Questi
devono essere controllati separatamente utilizzando ``kernel-doc``.
Documentare le funzioni
------------------------
@@ -172,7 +171,7 @@ Valore di ritorno
~~~~~~~~~~~~~~~~~
Il valore di ritorno, se c'è, viene descritto in una sezione dedicata di nome
``Return``.
``Return`` (o ``Returns``).
.. note::
@@ -202,7 +201,8 @@ Il valore di ritorno, se c'è, viene descritto in una sezione dedicata di nome
Documentare strutture, unioni ed enumerazioni
---------------------------------------------
Generalmente il formato di un commento kernel-doc per struct, union ed enum è::
Generalmente il formato di un commento kernel-doc per ``struct``, ``union``
ed ``enum`` è::
/**
* struct struct_name - Brief description.
@@ -237,6 +237,10 @@ Le etichette ``private:`` e ``public:`` devono essere messe subito dopo
il marcatore di un commento ``/*``. Opzionalmente, possono includere commenti
fra ``:`` e il marcatore di fine commento ``*/``.
Quando ``private:`` viene usata su strutture annidate, si propaga solo alle
strutture/unioni interne.
Esempio::
/**
@@ -280,13 +284,15 @@ Strutture ed unioni annidate
union {
struct {
int memb1;
/* private: nasconde memb2 dalla documentazione */
int memb2;
}
};
/* Qui torna tutto pubblico, l'ambito private è terminato */
struct {
void *memb3;
int memb4;
}
}
};
};
union {
struct {
int memb1;
@@ -366,10 +372,23 @@ Anche i tipi di dato per prototipi di funzione possono essere documentati::
* Description of the type.
*
* Context: Locking context.
* Return: Meaning of the return value.
* Returns: Meaning of the return value.
*/
typedef void (*type_name)(struct v4l2_ctrl *arg1, void *arg2);
Documentazione delle variabili
-------------------------------
Generalmente il formato di un commento kernel-doc per una variabile è
il seguente::
/**
* var var_name - Brief description.
*
* Description of the var_name variable.
*/
extern int var_name;
Documentazione di macro simili a oggetti
----------------------------------------
@@ -433,6 +452,10 @@ del `dominio Sphinx per il C`_.
``%CONST``
Il nome di una costante (nessun riferimento, solo formattazione)
Esempi::
%0 %NULL %-1 %-EFAULT %-EINVAL %-ENOMEM
````literal````
Un blocco di testo che deve essere riportato così com'è. La rappresentazione
finale utilizzerà caratteri a ``spaziatura fissa``.
@@ -484,15 +507,22 @@ la seguente sintassi::
See :c:func:`my custom link text for function foo <foo>`.
See :c:type:`my custom link text for struct bar <bar>`.
Per ulteriori dettagli, consultate la documentazione del `dominio Sphinx per
il C`_.
.. note::
Le variabili non vengono automaticamente collegate tramite riferimenti
incrociati. Per queste, dovete aggiungere esplicitamente un riferimento
incrociato del dominio C.
Commenti per una documentazione generale
----------------------------------------
Al fine d'avere il codice ed i commenti nello stesso file, potete includere
dei blocchi di documentazione kernel-doc con un formato libero invece
che nel formato specifico per funzioni, strutture, unioni, enumerati o tipi
di dato. Per esempio, questo tipo di commento potrebbe essere usato per la
spiegazione delle operazioni di un driver o di una libreria
che nel formato specifico per funzioni, strutture, unioni, enumerati, tipi
di dato o variabili. Per esempio, questo tipo di commento potrebbe essere
usato per la spiegazione delle operazioni di un driver o di una libreria
Questo s'ottiene utilizzando la parola chiave ``DOC:`` a cui viene associato
un titolo.
@@ -565,6 +595,8 @@ identifiers: *[ function/type ...]*
Include la documentazione per ogni *function* e *type* in *source*.
Se non vengono esplicitamente specificate le funzioni da includere, allora
verranno incluse tutte quelle disponibili in *source*.
*type* può essere un identificatore di tipo ``struct``, ``union``,
``enum``, ``typedef`` o ``var``.
Esempi::
@@ -601,7 +633,25 @@ dai file sorgenti.
Come utilizzare kernel-doc per generare pagine man
--------------------------------------------------
Se volete utilizzare kernel-doc solo per generare delle pagine man, potete
farlo direttamente dai sorgenti del kernel::
Per generare le pagine man di tutti i file che contengono marcatori
kernel-doc, eseguite::
$ tools/docs/kernel-doc -man $(git grep -l '/\*\*' -- :^Documentation :^tools) | scripts/split-man.pl /tmp/man
$ make mandocs
Oppure, chiamando direttamente ``script-build-wrapper``::
$ ./tools/docs/sphinx-build-wrapper mandocs
Il risultato sarà disponibile nella cartella ``/man`` dentro la cartella
di output (predefinita: ``Documentation/output``).
Opzionalmente, è possibile generare un sottoinsieme di pagine man usando
SPHINXDIRS:
$ make SPHINXDIRS=driver-api/media mandocs
.. note::
Quando si usa SPHINXDIRS={subdir}, verranno generate le pagine man solo
per i file che si trovano esplicitamente all'interno di un file
``Documentation/{subdir}/.../*.rst``.

View File

@@ -0,0 +1,60 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-ita.rst
Profilo del manutentore del sottosistema di documentazione
==========================================================
Il "sottosistema" della documentazione è il punto di coordinamento
centrale per la documentazione del kernel e la relativa infrastruttura.
Copre la gerarchia sotto Documentation/ (con l'eccezione di
Documentation/devicetree), diverse utilità sotto scripts/ e, almeno in
parte, LICENSES/.
Vale la pena notare, però, che i confini di questo sottosistema sono più sfumati
del normale. Molti altri manutentori di sottosistemi preferiscono mantenere il
controllo di alcune parti di Documentation/, e molti altri ancora vi applicano
liberamente delle modifiche quando è conveniente. Oltre a ciò, buona parte della
documentazione del kernel si trova nel codice sorgente sotto forma di commenti
kerneldoc; questi sono solitamente (ma non sempre) mantenuti dal manutentore del
sottosistema pertinente.
La lista di discussione per la documentazione è linux-doc@vger.kernel.org.
Le patch dovrebbero essere inviate contro l'albero docs-next quando
possibile.
Aggiunta alla checklist di invio
--------------------------------
Quando si apportano modifiche alla documentazione, dovreste generare
effettivamente la documentazione e assicurarvi che non siano stati
introdotti nuovi errori o avvisi. Generare i documenti in HTML e osservare
il risultato aiuterà a evitare fraintendimenti spiacevoli su come le cose
verranno rappresentate.
Tutta la nuova documentazione (incluse le aggiunte a documenti esistenti)
dovrebbe idealmente giustificare, da qualche parte nel changelog, chi sia
il pubblico a cui è destinata; in questo modo, ci assicuriamo che la
documentazione finisca nel posto giusto. Alcune categorie possibili
sono: sviluppatori del kernel (esperti o principianti), programmatori
dello spazio utente, utenti finali e/o amministratori di sistema, e
distributori.
Date chiave del ciclo
---------------------
Le patch possono essere inviate in qualsiasi momento, ma la risposta sarà
più lenta del solito durante la finestra d'integrazione. L'albero della
documentazione tende a chiudersi tardi, prima dell'apertura della finestra
d'integrazione, poiché il rischio di regressioni dovute a patch sulla
documentazione è basso.
Cadenza di revisione
--------------------
Sono (Jonathan Corbet) l'unico manutentore del sottosistema di documentazione, e
svolgo questo lavoro nel mio tempo libero, quindi la risposta alle patch sarà a
volte lenta. Cerco sempre di inviare una notifica quando una patch viene
integrata (o quando decido che non può esserlo). Non esitate a inviare un
sollecito se non avete ricevuto risposta entro una settimana dall'invio di una
patch.

View File

@@ -1,195 +1,195 @@
.. include:: ../disclaimer-ita.rst
:Original: Documentation/doc-guide/index.rst
=========================================
Includere gli i file di intestazione uAPI
=========================================
=====================================
Includere i file di intestazione uAPI
=====================================
Qualche volta è utile includere dei file di intestazione e degli esempi di codice C
al fine di descrivere l'API per lo spazio utente e per generare dei riferimenti
fra il codice e la documentazione. Aggiungere i riferimenti ai file dell'API
dello spazio utente ha ulteriori vantaggi: Sphinx genererà dei messaggi
dello spazio utente ha un ulteriore vantaggio: Sphinx genererà dei messaggi
d'avviso se un simbolo non viene trovato nella documentazione. Questo permette
di mantenere allineate la documentazione della uAPI (API spazio utente)
con le modifiche del kernel.
Il programma :ref:`parse_headers.py <it_parse_headers>` genera questi riferimenti.
Esso dev'essere invocato attraverso un Makefile, mentre si genera la
documentazione. Per avere un esempio su come utilizzarlo all'interno del kernel
consultate ``Documentation/userspace-api/media/Makefile``.
Il programma :ref:`parse_headers.py <it_parse_headers>` genera questi
riferimenti. Esso dev'essere invocato attraverso un Makefile, mentre si genera
la documentazione. Per avere un esempio su come utilizzarlo all'interno del
kernel consultate ``Documentation/userspace-api/media/Makefile``.
.. _it_parse_headers:
parse_headers.py
^^^^^^^^^^^^^^^^
tools/docs/parse_headers.py
^^^^^^^^^^^^^^^^^^^^^^^^^^^
NOME
****
parse_headers.py - analizza un file C al fine di identificare funzioni,
strutture, enumerati e definizioni, e creare riferimenti per un libro Sphinx.
parse_headers.py - analizza i file C al fine di identificare funzioni,
strutture, enumerati e definizioni, e creare riferimenti per Sphinx
USO
***
SINTASSI
********
parse-headers.py [-h] [-d] [-t] ``FILE_IN`` ``FILE_OUT`` ``FILE_RULES``
SINOSSI
*******
\ **parse_headers.py**\ [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>]
Converte un file d'intestazione o un file sorgente C ``FILE_IN`` in un testo
ReStructured Text incluso mediante il blocco ..parsed-literal con riferimenti
alla documentazione che descrive l'API. Accetta opzionalmente un file
``FILE_RULES`` che descrive quali elementi debbano essere ignorati o il cui
riferimento debba puntare ad un tipo/nome diverso da quello predefinito.
Dove <options> può essere: --debug, --usage o --help.
Il file generato viene scritto in ``FILE_OUT``.
Il programma è capace di identificare ``define``, ``struct``, ``typedef``,
``enum`` e ``symbol`` di un enumerato, creando i riferimenti per ognuno di
loro.
Inoltre, esso è capace di distinguere le ``#define`` utilizzate per
specificare le macro specifiche di Linux usate per definire gli ``ioctl``.
Il file ``FILE_RULES``, opzionale, contiene un insieme di regole come le
seguenti::
ignore ioctl VIDIOC_ENUM_FMT
replace ioctl VIDIOC_DQBUF vidioc_qbuf
replace define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ :c:type:`v4l2_event_motion_det`
ARGOMENTI POSIZIONALI
*********************
``FILE_IN``
File C d'ingresso
``FILE_OUT``
File RST generato
``FILE_RULES``
File delle eccezioni (opzionale)
OPZIONI
*******
\ **--debug**\
Lo script viene messo in modalità verbosa, utile per il debugging.
\ **--usage**\
Mostra un messaggio d'aiuto breve e termina.
\ **--help**\
Mostra un messaggio d'aiuto dettagliato e termina.
``-h``, ``--help``
mostra un messaggio d'aiuto e termina
``-d``, ``--debug``
aumenta il livello di debug. Può essere usato più volte
``-t``, ``--toc``
invece di un blocco letterale, genera nel file RST una tabella
dell'indice (TOC)
DESCRIZIONE
***********
Converte un file d'intestazione o un file sorgente C (C_FILE) in un testo
reStructuredText incluso mediante il blocco ..parsed-literal
con riferimenti alla documentazione che descrive l'API. Opzionalmente,
il programma accetta anche un altro file (EXCEPTIONS_FILE) che
descrive quali elementi debbano essere ignorati o il cui riferimento
deve puntare ad elemento diverso dal predefinito.
Crea, a partire da ``FILE_IN``, una versione arricchita di un file
d'intestazione del kernel con collegamenti incrociati verso ogni tipo di
struttura dati C, formattandola con la notazione reStructuredText, sia
come blocco letterale che come tabella dell'indice.
Il file generato sarà disponibile in (OUT_FILE).
Accetta opzionalmente un file ``FILE_RULES`` che descrive quali elementi
debbano essere ignorati o il cui riferimento debba puntare ad un valore
diverso da quello predefinito, e che può opzionalmente definire lo spazio
dei nomi C da utilizzare.
Il programma è capace di identificare *define*, funzioni, strutture,
tipi di dato, enumerati e valori di enumerati, e di creare i riferimenti
per ognuno di loro. Inoltre, esso è capace di distinguere le #define
utilizzate per specificare i comandi ioctl di Linux.
Ha lo scopo di permettere una documentazione più completa, in cui i file
d'intestazione della uAPI creino collegamenti incrociati verso il codice.
Il file EXCEPTIONS_FILE contiene due tipi di dichiarazioni:
\ **ignore**\ o \ **replace**\ .
Il file generato viene scritto in ``FILE_OUT``.
La sintassi per ignore è:
Il file ``FILE_RULES`` può contenere tre tipi di dichiarazioni:
**ignore**, **replace** e **namespace**.
ignore \ **tipo**\ \ **nome**\
Per impostazione predefinita, vengono create regole per tutti i simboli e
le definizioni, ma è anche possibile fornire un file di eccezioni. Questo
file contiene un insieme di regole che seguono la sintassi descritta di
seguito:
La dichiarazione \ **ignore**\ significa che non verrà generato alcun
riferimento per il simbolo \ **name**\ di tipo \ **tipo**\ .
1. Regole ignore:
ignore *tipo* *simbolo*
La sintassi per replace è:
Rimuove il simbolo dalla generazione dei riferimenti.
replace \ **tipo**\ \ **nome**\ \ **nuovo_valore**\
2. Regole replace:
La dichiarazione \ **replace**\ significa che verrà generato un
riferimento per il simbolo \ **name**\ di tipo \ **tipo**\ , ma, invece
di utilizzare il valore predefinito, verrà utilizzato il valore
\ **nuovo_valore**\ .
replace *tipo* *vecchio_simbolo* *nuovo_riferimento*
Per entrambe le dichiarazioni, il \ **tipo**\ può essere uno dei seguenti:
Sostituisce *vecchio_simbolo* con *nuovo_riferimento*.
*nuovo_riferimento* può essere:
- un semplice nome di simbolo;
- un riferimento Sphinx completo.
\ **ioctl**\
3. Regole namespace
La dichiarazione ignore o replace verrà applicata su definizioni di ioctl
come la seguente:
namespace *spazio_dei_nomi*
#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register)
Imposta lo *spazio_dei_nomi* C da utilizzare durante la generazione dei
riferimenti incrociati. Può essere sovrascritto dalle regole replace.
Nelle regole ignore e replace, *tipo* può essere:
- ioctl:
per le definizioni della forma ``_IO*``, per esempio le definizioni
di ioctl
\ **define**\
- define:
per le altre definizioni
La dichiarazione ignore o replace verrà applicata su una qualsiasi #define
trovata in C_FILE.
- symbol:
per i simboli definiti all'interno di enumerati;
- typedef:
per i typedef;
- enum:
per il nome di un enumerato non anonimo;
\ **typedef**\
La dichiarazione ignore o replace verrà applicata ad una dichiarazione typedef
in C_FILE.
\ **struct**\
La dichiarazione ignore o replace verrà applicata ai nomi di strutture
in C_FILE.
\ **enum**\
La dichiarazione ignore o replace verrà applicata ai nomi di enumerati
in C_FILE.
\ **symbol**\
La dichiarazione ignore o replace verrà applicata ai nomi di valori di
enumerati in C_FILE.
Per le dichiarazioni di tipo replace, il campo \ **new_value**\ utilizzerà
automaticamente i riferimenti :c:type: per \ **typedef**\ , \ **enum**\ e
\ **struct**\. Invece, utilizzerà :ref: per \ **ioctl**\ , \ **define**\ e
\ **symbol**\. Il tipo di riferimento può essere definito esplicitamente
nella dichiarazione stessa.
- struct:
per le strutture.
ESEMPI
******
- Ignora una definizione ``_VIDEODEV2_H`` in ``FILE_IN``::
ignore define _VIDEODEV2_H
ignore define _VIDEODEV2_H
- In una struttura dati come questo enumerato::
enum foo { BAR1, BAR2, PRIVATE };
Non genererà alcun riferimento incrociato per ``PRIVATE``::
ignore symbol PRIVATE
Nello stesso enumerato, invece di creare un riferimento incrociato per
ogni simbolo, si può far si che tutti puntino al tipo C ``enum foo``::
replace symbol BAR1 :c:type:\`foo\`
replace symbol BAR2 :c:type:\`foo\`
Ignora una definizione #define _VIDEODEV2_H nel file C_FILE.
ignore symbol PRIVATE
In un enumerato come il seguente:
enum foo { BAR1, BAR2, PRIVATE };
Non genererà alcun riferimento per \ **PRIVATE**\ .
replace symbol BAR1 :c:type:\`foo\`
replace symbol BAR2 :c:type:\`foo\`
In un enumerato come il seguente:
enum foo { BAR1, BAR2, PRIVATE };
Genererà un riferimento ai valori BAR1 e BAR2 dal simbolo foo nel dominio C.
- Usa lo spazio dei nomi C ``MC`` per tutti i simboli in ``FILE_IN``::
namespace MC
BUGS
****
Riferire ogni malfunzionamento a Mauro Carvalho Chehab <mchehab@s-opensource.com>
Segnalate qualsiasi malfunzionamento a Mauro Carvalho Chehab
<mchehab@kernel.org>
COPYRIGHT
*********
Copyright (c) 2016, 2025 di Mauro Carvalho Chehab <mchehab+huawei@kernel.org>.
Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@s-opensource.com>.
Licenza GPLv2: GNU GPL version 2 <https://gnu.org/licenses/gpl.html>.
Licenza GPLv2: GNU GPL versione 2 <https://gnu.org/licenses/gpl.html>.
Questo è software libero: siete liberi di cambiarlo e ridistribuirlo.
Non c'è alcuna garanzia, nei limiti permessi dalla legge.

View File

@@ -1,8 +1,5 @@
.. include:: ../disclaimer-ita.rst
.. note:: Per leggere la documentazione originale in inglese:
:ref:`Documentation/doc-guide/index.rst <doc_guide>`
.. _it_sphinxdoc:
=============================================
@@ -36,7 +33,7 @@ Installazione Sphinx
====================
I marcatori ReST utilizzati nei file in Documentation/ sono pensati per essere
processati da ``Sphinx`` nella versione 1.7 o superiore.
processati da ``Sphinx`` nella versione 3.4.3 o superiore.
Esiste uno script che verifica i requisiti Sphinx. Per ulteriori dettagli
consultate :ref:`it_sphinx-pre-install`.
@@ -52,24 +49,14 @@ vi raccomandiamo di installare Sphinx dentro ad un ambiente virtuale usando
``virtualenv-3`` o ``virtualenv`` a seconda di come Python 3 è stato
pacchettizzato dalla vostra distribuzione.
.. note::
Riassumendo, se volete installare l'ultima versione di Sphinx, dovete
eseguire::
#) Viene raccomandato l'uso del tema RTD per la documentazione in HTML.
A seconda della versione di Sphinx, potrebbe essere necessaria
l'installazione tramite il comando ``pip install sphinx_rtd_theme``.
$ virtualenv sphinx_latest
$ . sphinx_latest/bin/activate
(sphinx_latest) $ pip install -r Documentation/sphinx/requirements.txt
#) Alcune pagine ReST contengono delle formule matematiche. A causa del
modo in cui Sphinx funziona, queste espressioni sono scritte
utilizzando LaTeX. Per una corretta interpretazione, è necessario aver
installato texlive con i pacchetti amdfonts e amsmath.
Riassumendo, se volete installare la versione 2.4.4 di Sphinx dovete eseguire::
$ virtualenv sphinx_2.4.4
$ . sphinx_2.4.4/bin/activate
(sphinx_2.4.4) $ pip install -r Documentation/sphinx/requirements.txt
Dopo aver eseguito ``. sphinx_2.4.4/bin/activate``, il prompt cambierà per
Dopo aver eseguito ``. sphinx_latest/bin/activate``, il prompt cambierà per
indicare che state usando il nuovo ambiente. Se aprite un nuova sessione,
prima di generare la documentazione, dovrete rieseguire questo comando per
rientrare nell'ambiente virtuale.
@@ -99,6 +86,27 @@ Per alcune distribuzioni Linux potrebbe essere necessario installare
anche una serie di pacchetti ``texlive`` in modo da fornire il supporto
minimo per il funzionamento di ``XeLaTeX``.
Espressioni matematiche in HTML
-------------------------------
Alcune pagine ReST contengono delle formule matematiche. Per come funziona
Sphinx, queste espressioni sono scritte utilizzando la notazione LaTeX. Esistono
due opzioni per far si che Sphinx rappresenti le espressioni matematiche
nell'output HTML. La prima è un'estensione chiamata `imgmath`_ che converte le
espressioni matematiche in immagini e le integra nelle pagine HTML. L'altra è
un'estensione chiamata `mathjax`_ che delega la rappresentazione delle formule
matematiche ai browser web capaci di eseguire JavaScript. La prima era l'unica
opzione per la documentazione del kernel precedente alla versione 6.1 e richiede
diversi pacchetti texlive, fra cui amsfonts e amsmath.
A partire dalla versione 6.1 del kernel, le pagine HTML con espressioni
matematiche possono essere generate senza dover installare alcun pacchetto
texlive. Per maggiori informazioni consultate `Scelta della libreria per le
formule matematiche`_.
.. _imgmath: https://www.sphinx-doc.org/en/master/usage/extensions/math.html#module-sphinx.ext.imgmath
.. _mathjax: https://www.sphinx-doc.org/en/master/usage/extensions/math.html#module-sphinx.ext.mathjax
.. _it_sphinx-pre-install:
Verificare le dipendenze Sphinx
@@ -136,6 +144,30 @@ Questo script ha i seguenti parametri:
Utilizza l'ambiente predefinito dal sistema operativo invece che
l'ambiente virtuale per Python;
Installare la versione minima di Sphinx
---------------------------------------
Quando si modifica il sistema di generazione di Sphinx, è importante
assicurarsi che la versione minima sia ancora supportata. Al giorno d'oggi,
sta diventando sempre più difficile farlo sulle distribuzioni moderne, dato
che non è possibile installarla con Python 3.13 e versioni successive.
Potete verificare la versione minima di Python supportata, così come
definita in Documentation/process/changes.rst, creando un venv con quella
versione e installando i requisiti minimi con::
/usr/bin/python3.9 -m venv sphinx_min
. sphinx_min/bin/activate
pip install -r Documentation/sphinx/min_requirements.txt
Un test più completo può essere eseguito utilizzando:
tools/docs/test_doc_build.py
Questo script crea un venv Python per ogni versione supportata, generando
facoltativamente la documentazione per un intervallo di versioni di
Sphinx.
Generazione della documentazione Sphinx
=======================================
@@ -143,39 +175,82 @@ Generazione della documentazione Sphinx
Per generare la documentazione in formato HTML o PDF si eseguono i rispettivi
comandi ``make htmldocs`` o ``make pdfdocs``. Esistono anche altri formati
in cui è possibile generare la documentazione; per maggiori informazioni
potere eseguire il comando ``make help``.
potete eseguire il comando ``make help``.
La documentazione così generata sarà disponibile nella sottocartella
``Documentation/output``.
Ovviamente, per generare la documentazione, Sphinx (``sphinx-build``)
dev'essere installato. Se disponibile, il tema *Read the Docs* per Sphinx
verrà utilizzato per ottenere una documentazione HTML più gradevole.
Per la documentazione in formato PDF, invece, avrete bisogno di ``XeLaTeX`
e di ``convert(1)`` disponibile in ImageMagick
(https://www.imagemagick.org). \ [#ink]_
Tipicamente, tutti questi pacchetti sono disponibili e pacchettizzati nelle
distribuzioni Linux.
dev'essere installato. Per la documentazione in formato PDF, invece,
avrete bisogno di ``XeLaTeX`` e di ``convert(1)`` disponibile in
ImageMagick (https://www.imagemagick.org).\ [#ink]_ Tutti questi pacchetti
sono ampiamente disponibili e pacchettizzati nelle distribuzioni.
Per poter passare ulteriori opzioni a Sphinx potete utilizzare la variabile
make ``SPHINXOPTS``. Per esempio, se volete che Sphinx sia più verboso durante
la generazione potete usare il seguente comando ``make SPHINXOPTS=-v htmldocs``.
make ``SPHINXOPTS``. Per esempio, se volete che Sphinx sia più prolisso
durante la generazione potete usare il comando
``make SPHINXOPTS=-v htmldocs``.
Potete anche personalizzare l'ouptut html passando un livello aggiuntivo
Potete anche personalizzare l'output html passando un livello aggiuntivo
DOCS_CSS usando la rispettiva variabile d'ambiente ``DOCS_CSS``.
La variable make ``SPHINXDIRS`` è utile quando si vuole generare solo una parte
della documentazione. Per esempio, si possono generare solo di documenti in
``Documentation/doc-guide`` eseguendo ``make SPHINXDIRS=doc-guide htmldocs``. La
sezione dedicata alla documentazione di ``make help`` vi mostrerà quali sotto
cartelle potete specificare.
Il tema di base per generare la documentazione HTML viene è "Alabaster"; questo
tema è distribuito assieme a Sphinx e non necessita di un'installazione
separata. Il tema di Sphinx può essere sostituito usando la variabile make
``DOCS_THEME``.
.. note::
Alcuni potrebbero preferire il tema RTD per l'output in HTML. A seconda
della versione di Sphinx, dev'essere installato separatamente, con il
comando ``pip install sphinx_rtd_theme``.
Esiste un'altra variabile make, ``SPHINXDIRS``, utile quando si vuole
generare, a scopo di test, solo una parte della documentazione. Per
esempio, potete generare i documenti in ``Documentation/doc-guide``
eseguendo ``make SPHINXDIRS=doc-guide htmldocs``. La sezione dedicata alla
documentazione di ``make help`` vi mostrerà l'elenco delle sottocartelle
che potete specificare.
Potete eliminare la documentazione generata tramite il comando
``make cleandocs``.
.. [#ink] Avere installato anche ``inkscape(1)`` dal progetto Inkscape ()
potrebbe aumentare la qualità delle immagini che verranno integrate
nel documento PDF, specialmente per quando si usando rilasci del
kernel uguali o superiori a 5.18
.. [#ink] Avere installato anche ``inkscape(1)`` dal progetto Inkscape
(https://inkscape.org) potrebbe aumentare la qualità delle
immagini integrate nei documenti PDF, specialmente per i rilasci
del kernel dalla versione 5.18 in poi.
Scelta della libreria per le formule matematiche
------------------------------------------------
A partire dalla versione 6.1 del kernel, mathjax funge da libreria di
ripiego per le formule matematiche nell'output HTML.\ [#sph1_8]_
La libreria matematica viene scelta in base ai comandi disponibili, come
mostrato di seguito:
.. table:: Scelta della libreria matematica per l'HTML
======== ================= ================
Libreria Comandi richiesti Formato immagine
======== ================= ================
imgmath latex, dvipng PNG (raster)
mathjax
======== ================= ================
La scelta può essere sovrascritta impostando la variabile d'ambiente
``SPHINX_IMGMATH`` come mostrato di seguito:
.. table:: Effetto dell'impostazione di ``SPHINX_IMGMATH``
====================== ========
Impostazione Libreria
====================== ========
``SPHINX_IMGMATH=yes`` imgmath
``SPHINX_IMGMATH=no`` mathjax
====================== ========
.. [#sph1_8] La libreria di ripiego richiede Sphinx >=1.8.
Scrivere la documentazione
==========================
@@ -289,8 +364,19 @@ incrociato quando questa ha una voce nell'indice. Se trovate degli usi di
``c:func:`` nella documentazione del kernel, sentitevi liberi di rimuoverli.
Tabelle
-------
Il formato reStructuredText offre diverse opzioni per la sintassi delle tabelle.
Lo stile del kernel per le tabelle preferisce la sintassi delle *tabelle
semplici* o delle *tabelle a griglia*. Per maggiori dettagli consultate il
`manuale di riferimento reStructuredText per la sintassi delle tabelle`_.
.. _manuale di riferimento reStructuredText per la sintassi delle tabelle:
https://docutils.sourceforge.io/docs/user/rst/quickref.html#tables
Tabelle a liste
---------------
~~~~~~~~~~~~~~~
Il formato ``list-table`` può essere utile per tutte quelle tabelle che non
possono essere facilmente scritte usando il formato ASCII-art di Sphinx. Però,
@@ -403,6 +489,16 @@ percorso al documento.
Per informazioni riguardo ai riferimenti incrociati ai commenti
kernel-doc per funzioni o tipi, consultate
Documentation/translations/it_IT/doc-guide/kernel-doc.rst.
Riferimenti ai commit
~~~~~~~~~~~~~~~~~~~~~
I riferimenti ai commit di git vengono trasformati automaticamente in
collegamenti ipertestuali quando sono scritti in uno di questi formati::
commit 72bf4f1767f0
commit 72bf4f1767f0 ("net: do not leave an empty skb in write queue")
.. _it_sphinx_kfigure:

View File

@@ -23,50 +23,53 @@ Requisiti minimi correnti
Prima di pensare d'avere trovato un baco, aggiornate i seguenti programmi
**almeno** alla versione indicata! Se non siete certi della versione che state
usando, il comando indicato dovrebbe dirvelo.
usando, il comando indicato dovrebbe dirvelo. Per avere una lista dei programmi
sul vostro sistema, incluse le rispettive versioni, eseguite
./scripts/ver_linux.
Questa lista presume che abbiate già un kernel Linux funzionante. In aggiunta,
non tutti gli strumenti sono necessari ovunque; ovviamente, se non avete una
PC Card, per esempio, probabilmente non dovreste preoccuparvi di pcmciautils.
====================== ================= ========================================
Programma Versione minima Comando per verificare la versione
====================== ================= ========================================
GNU C 8.1 gcc --version
Clang/LLVM (optional) 17.0.1 clang --version
Rust (opzionale) 1.78.0 rustc --version
bindgen (opzionale) 0.65.1 bindgen --version
GNU make 4.0 make --version
bash 4.2 bash --version
binutils 2.30 ld -v
flex 2.5.35 flex --version
bison 2.0 bison --version
pahole 1.16 pahole --version
util-linux 2.10o mount --version
kmod 13 depmod -V
e2fsprogs 1.41.4 e2fsck -V
jfsutils 1.1.3 fsck.jfs -V
xfsprogs 2.6.0 xfs_db -V
squashfs-tools 4.0 mksquashfs -version
btrfs-progs 0.18 btrfsck
pcmciautils 004 pccardctl -V
quota-tools 3.09 quota -V
PPP 2.4.0 pppd --version
nfs-utils 1.0.5 showmount --version
procps 3.2.0 ps --version
udev 081 udevd --version
grub 0.93 grub --version || grub-install --version
mcelog 0.6 mcelog --version
iptables 1.4.2 iptables -V
openssl & libcrypto 1.0.0 openssl version
bc 1.06.95 bc --version
Sphinx\ [#f1]_ 2.4.4 sphinx-build --version
cpio any cpio --version
GNU tar 1.28 tar --version
gtags (opzionale) 6.6.5 gtags --version
mkimage (opzionale) 2017.01 mkimage --version
Python (opzionale) 3.5.x python3 --version
====================== ================= ========================================
====================== =============== ========================================
Programma Versione minima Comando per verificare la versione
====================== =============== ========================================
bash 4.2 bash --version
bc 1.06.95 bc --version
bindgen (opzionale) 0.71.1 bindgen --version
binutils 2.30 ld -v
bison 2.0 bison --version
btrfs-progs 0.18 btrfs --version
Clang/LLVM (opzionale) 17.0.1 clang --version
e2fsprogs 1.41.4 e2fsck -V
flex 2.5.35 flex --version
gdb 7.2 gdb --version
GNU awk (opzionale) 5.1.0 gawk --version
GNU C 8.1 gcc --version
GNU make 4.0 make --version
GNU tar 1.28 tar --version
GRUB 0.93 grub --version || grub-install --version
gtags (opzionale) 6.6.5 gtags --version
iptables 1.4.2 iptables -V
jfsutils 1.1.3 fsck.jfs -V
kmod 13 kmod -V
mcelog 0.6 mcelog --version
mkimage (opzionale) 2017.01 mkimage --version
nfs-utils 1.0.5 showmount --version
openssl & libcrypto 1.0.0 openssl version
pahole 1.26 pahole --version
pcmciautils 004 pccardctl -V
PPP 2.4.0 pppd --version
procps 3.2.0 ps --version
Python 3.9.x python3 --version
quota-tools 3.09 quota -V
Rust (opzionale) 1.85.0 rustc --version
Sphinx\ [#f1]_ 3.4.3 sphinx-build --version
squashfs-tools 4.0 mksquashfs -version
udev 081 udevadm --version
util-linux 2.10o mount --version
xfsprogs 2.6.0 xfs_db -V
====================== =============== ========================================
.. [#f1] Sphinx è necessario solo per produrre la documentazione del Kernel
@@ -144,7 +147,13 @@ pahole
Dalla versione 5.2, quando viene impostato CONFIG_DEBUG_INFO_BTF, il sistema di
compilazione genera BTF (BPF Type Format) a partire da DWARF per vmlinux. Più
tardi anche per i moduli. Questo richiede pahole v1.16 o successivo.
tardi anche per i moduli. Questo richiede pahole v1.22 o successivo.
Dalla versione 7.0, le kfunc annotate con KF_IMPLICIT_ARGS richiedono pahole
v1.26 o successivo. Senza questa versione, tali kfunc avranno prototipi BTF
errati in vmlinux, causando il fallimento del caricamento dei programmi BPF con
l'errore "func_proto incompatible with vmlinux". Molte kfunc in sched_ext sono
interessate da questo problema.
A seconda della distribuzione, lo si può trovare nei pacchetti 'dwarves' o
'pahole'. Oppure lo si può trovare qui: https://fedorapeople.org/~acme/dwarves/.
@@ -155,6 +164,14 @@ Perl
Per compilare il kernel vi servirà perl 5 e i seguenti moduli ``Getopt::Long``,
``Getopt::Std``, ``File::Basename``, e ``File::Find``.
Python
------
Diverse opzioni di configurazione lo richiedono: è necessario per le
configurazioni predefinite di arm/arm64, CONFIG_LTO_CLANG, alcune opzioni
configurabili del DRM, lo strumento kernel-doc e la generazione della
documentazione (Sphinx), e altro ancora.
BC
--
@@ -193,6 +210,12 @@ pacchetto ``u-boot-tools`` oppure può essere compilato dal codice sorgente di
U-Boot. Consultate le istruzioni
https://docs.u-boot.org/en/latest/build/tools.html#building-tools-for-linux
GNU AWK
-------
GNU AWK è necessario se si vuole che la compilazione del kernel generi dati
sugli intervalli di indirizzi per i moduli integrati
(CONFIG_BUILTIN_MODULE_RANGES).
Strumenti di sistema
********************
@@ -405,6 +428,16 @@ Clang/LLVM
- :ref:`Getting LLVM <getting_llvm>`.
Rust
----
- Documentation/rust/quick-start.rst.
bindgen
-------
- Documentation/rust/quick-start.rst.
Make
----
@@ -507,11 +540,6 @@ mcelog
- <https://www.mcelog.org/>
cpio
----
- <https://www.gnu.org/software/cpio/>
Rete
****

View File

@@ -182,7 +182,7 @@ URL は禁止です。
変更を分割する
--------------
**論理的な変更** は、個別のパッチに分けてください。
それぞれの\ **論理的な変更**\ は、個別のパッチに分けてください。
たとえば、単一のドライバに対する変更にバグ修正と性能改善の
両方が含まれるなら、それらは 2 つ以上のパッチに分けてください。
@@ -208,7 +208,7 @@ URL は禁止です。
ことがあります。途中でバグを持ち込めば、彼らに感謝されることは
ないでしょう。
パッチセットをれ以上小さくできないなら、一度に投稿するのは
パッチセットをれ以上小さくできないなら、一度に投稿するのは
15 個程度までにして、レビューと統合を待ってください。
@@ -220,18 +220,17 @@ Documentation/process/coding-style.rst を参照してください。
これを怠ると、単にレビューアの時間を無駄にするだけでなく、
パッチはおそらく読まれもせずに却下されます。
大きな例外が 1 つあります。コードをあるファイルから別の
ファイルへ移動する場合です。このときは、コードを移動する
その同じパッチの中で、移動したコードを一切変更してはいけません。
そうすることで、コードの移動という行為と、あなたの変更と
明確に区別できます。これは実際の差分のレビューを大いに助け、
ツールがコード自体の履歴をより適切に追跡できるようにします。
一つの重要な例外は、コードをあるファイルから別のファイルへ移動する場合です。
その際は、コードを移動するその同じパッチの中で、一切コードを変更しては
いけません。これにより、コードの移動という行為と、コードの変更とが
明確に区別されます。これは実際の差分のレビューを大いに助け、また、ツール
使ったコード変更の履歴の追跡を容易にします。
提出前に、パッチスタイルチェッカー
(``scripts/checkpatch.pl``) でパッチを確認してください。
ただし、スタイルチェッカーは指針として見るべきであり
ただし、スタイルチェッカーは指針にすぎず
人間の判断に取って代わるものではないことに注意してください。
違反があっても、その方がコードの見栄えがよいなら、
違反が指摘されるままのコードの方が見栄えがよいなら、おそらく
そのままにしておくのが最善でしょう。
チェッカーは 3 つのレベルで報告します:
@@ -240,8 +239,7 @@ Documentation/process/coding-style.rst を参照してください。
- WARNING: 慎重なレビューを要するもの
- CHECK: 検討を要するもの
パッチに残した違反については、すべて理由を説明できなければ
なりません。
パッチに違反を残す場合は、そのすべてを正当化できなければなりません。
パッチの宛先を選択する
@@ -256,8 +254,8 @@ Documentation/process/coding-style.rst を参照してください。
サブシステムのメンテナが見つからない場合は、Andrew Morton
(akpm@linux-foundation.org) が最後の手段となるメンテナです。
すべてのパッチは、デフォルトで linux-kernel@vger.kernel.org
使うべきですが、このリスト流量が多いため、目を通さなくなった
すべてのパッチは、デフォルトで linux-kernel@vger.kernel.org にも
送られるべきですが、このリスト流量が多、目を通さなくなった
開発者も少なくありません。とはいえ、無関係なメーリングリストや
無関係な人々にスパムを送らないでください。
@@ -268,103 +266,104 @@ Documentation/process/coding-style.rst を参照してください。
Linux カーネルに採用されるすべての変更の最終的な裁定者は
Linus Torvalds です。彼のメールアドレスは
<torvalds@linux-foundation.org> です。Linus は大量のメールを
受け取っており、現時点では彼に直接届くパッチはごくわずかなので、
通常は彼にメールを送ることを極力避けてください。
受け取っており、現時点では直接彼を経由するパッチはごくわずかなので、
通常は彼にメールを送ることを極力\ **避けて**\ ください。
悪用可能なセキュリティバグを修正するパッチがあるなら
のパッチを security@kernel.org に送ってください。深刻なバグに
悪用可能なセキュリティバグを修正するパッチの場合は
を security@kernel.org に送ってください。深刻なバグに
ついては、ディストリビュータがユーザーにパッチを配布できるよう、
短期間の embargo が検討される場合があります。そのような場合、
のパッチを公開メーリングリストに送るべきではありません
短期間の秘匿措置 (訳註: embargo) が検討される可能性があります。
ですので、その種のパッチを公開メーリングリストに送らないでください
Documentation/process/security-bugs.rst も参照してください。
リリース済みカーネルの深刻なバグを修正するパッチは、次のような行を
パッチの sign-off 欄に入れることで、stable メンテナへ向けてください::
パッチの sign-off 欄に入れることで、stable メンテナに知らせてください
(メールの宛先ではないことに注意。) ::
Cc: stable@vger.kernel.org
これはメールの受信者ではないことに注意してください。また、
この文書に加えて Documentation/process/stable-kernel-rules.rst も
読んでください。
また、この文書に加えて Documentation/process/stable-kernel-rules.rst
も読んでください。
変更がユーザーランドとカーネルのインターフェースに影響する場合は、
MAINTAINERS ファイルに記載されている MAN-PAGES メンテナに
man-pages パッチ、少なくとも変更の通知を送って、情報が
マニュアルページに反映されるようにしてください。ユーザー空間 API の
マニュアルページのパッチ、もしくは少なくとも変更の通知を送って、情報が
そちらにも反映されるようにしてください。ユーザー空間 API の
変更は、linux-api@vger.kernel.org にも Cc してください。
MIME・リンク・圧縮・添付なし、プレーンテキストのみ
----------------------------------------------------
Linus や他のカーネル開発者は、あなたが投稿する変更を読み、
コメントできる必要があります。カーネル開発者が標準的な
メールツールを使ってあなたの変更を「引用」し、コードの特定の
箇所についてコメントできることが重要です。
コメントできる必要があります。カーネル開発者にとって、コードの特定の
箇所について、標準的なメールツールを使ってあなたの変更を「引用」し、
コメントできることが重要です。
このため、すべてのパッチはメール本文中に ``inline`` で投稿すべきです。
このため、すべてのパッチはメール本文中に「インライン」で投稿すべきです。
これを行う最も簡単な方法は ``git send-email`` を使うことであり、
強く推奨されます。``git send-email`` の対話型チュートリアルは
https://git-send-email.io で利用できます。
https://git-send-email.io にあります。
``git send-email`` を使わないことを選ぶ場合:
``git send-email`` を使わない場合:
.. warning::
パッチをコピー&ペーストする場合は、エディタの word-wrap によって
パッチが壊れないよう注意してください。
パッチをコピー&ペーストする際に、エディタによる自動改行で
パッチが壊れないよう注意してください。
圧縮の有無にかかわらず、パッチを MIME 添付ファイルとして添付しては
いけません。多くの一般的なメールアプリケーションは、MIME 添付
ファイルを常にプレーンテキストとして送信するとは限らず、あなたの
コードにコメントできなくなります。MIME 添付ファイルは Linus
処理するのにも少し余分な間がかかるため、MIME 添付された変更が
受け入れられる可能性を下げます。
いけません。よく使われるメールアプリケーションの多くは、MIME 添付
ファイルをプレーンテキストとして送信するとは限らず、あなたのコードに
対するコメントを妨げます。MIME 添付ファイルは Linus (訳補: をはじめ
とする開発者)が処理するのに余分な間がかかるため、MIME 添付すると
その変更が受け入れられる可能性を下げることになります。
例外: メーラがパッチを壊してしまう場合は、誰かから MIME を使って
再送するよう求められることがあります。
例外: パッチがメーラーによって壊されている場合に、MIME による再送
求められることがあります。
パッチを変更せずに送信するようメールクライアント設定するため
ヒントについては、Documentation/process/email-clients.rst を参照してください。
改変なしにパッチを送信するためのメールクライアント設定のヒントは、
Documentation/process/email-clients.rst を参照してください。
レビューコメントに答する
レビューコメントに答する
--------------------------
あなたのパッチには、ほぼ確実に、パッチを改善する方法について
レビューアからコメントが付きます。それは、あなたのメールへの返信という
形で届きます。それらのコメントには必ず答してください。レビューアを
無視することは、こちらも無視されるためのよい方法です。コメントに
答えるには、単にそのメールへ返信すれば構いません。コード変更に
あなたのパッチには、ほぼ確実に、その改善に向けてレビューアから
コメントが付きます。それは、あなたのメールへの返信という
形で届きます。それらのコメントには必ず答してください。レビューアを
無視することは、あなたが無視されることにつながります。コメントに
答えるには、単にそのメールへ返信すればよいです。コード変更に
つながらないレビューコメントや質問であっても、次のレビューアが状況を
よりよく理解できるように、ほぼ確実にコメントまたは changelog エントリ
反映すべきです。
よりよく理解できるよう、多くの場合、コメントまたは changelog エントリ
として残すべきです。
どのような変更を行うのかをレビューアに必ず伝え、時間を割いてくれた
ことに感謝してください。コードレビューは疲れる、時間のかかる作業であり、
レビューアが不機嫌になることもあります。そのような場合であっても
丁寧に返答し、指摘された問題に対応してください。次の版を送るときは
cover letter または個々のパッチに ``patch changelog`` を追加し、前回の
どのような変更を行うのかを忘れずにレビューアに伝えてください。そして
時間を割いてくれることへの感謝を忘れないでください。
コードレビューは疲れる、時間のかかる作業であり
ときにはレビューアが機嫌を損ねることもあります。そのような場合でも
丁寧に応答し、指摘された問題に対応してください。次の版を送る際には、
カバーレターまたは個々のパッチに ``patch changelog`` を追加し、前回の
投稿との差分を説明してください。詳細は原文の該当節
("The canonical patch format") を参照してください。
.. TODO: Convert to file-local cross-reference when the destination is
translated.
あなたのパッチにコメントした人には、パッチの Cc リストに追加して
新しい版知らせてください。
あなたのパッチにコメントしてくれた人たちは、パッチの Cc リストに追加して
新しい版について知らせてください。
メールクライアントとメーリングリストでの作法についての推奨事項は、
Documentation/process/email-clients.rst を参照してください。
メール議論では不要な引用を削った interleaved replies を使う
------------------------------------------------------------
要点に絞ったインライン返信での議論
---------------------------------------
Linux カーネル開発の議論では、top-posting は強く非推奨とされています。
Interleaved replies、または ``inline`` replies を使うと、会話の流れを
ずっと追いやすくなります。詳細は次を参照してください:
Linux カーネル開発の議論では、全文引用 (訳註: top-posting) は強く非推奨す。
インライン返信 (訳註: interleaved reples or "inline" replies) を使うと、
会話の流れをずっと追いやすくなります。詳細は次を参照してください:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
メーリングリストでは、よく次のように引用されます::
これについて、メーリングリストでは、次の引用をしばしば目にします::
A: http://en.wikipedia.org/wiki/Top_post
Q: Where do I find info about this thing called top-posting?
@@ -381,24 +380,102 @@ https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
Q: Should I include quotations after my reply?
落胆しない、そして急がない
--------------------------
落胆しない - いらいらしない
---------------------------
変更を投稿した後は、辛抱強く待ってください。レビューアは忙しい人たちであり、
あなたのパッチすぐに見られるとは限りません。
あなたのパッチすぐに取りかかれるとは限りません。
かつては、パッチが何のコメントもなく虚空へ消えていくこともありましたが、
現在の開発プロセスはそれよりも円滑に機能しています。数週間以内、
通常は 2〜3 週間以内にコメントを受け取るはずです。そうならない場合は、
パッチを正しい場所へ送ったか確認してください。再投稿したりレビューアに
ping したりする前に、少なくとも 1 週間は待ってください。merge window の
ような忙しい時期には、さらに長く待つ方がよい場合もあります
ping したりする前に、少なくとも 1 週間は待ってください。マージ期間
(訳註: merge window) のような忙しい時期には、さらに長く待ちましょう
数週間後に、subject line に "RESEND" を追加して、パッチまたは
パッチシリーズを再送しても構いません::
数週間後に、件名に "RESEND" を追加しパッチまたはパッチシリーズを
再送することは構いません::
[PATCH Vx RESEND] sub/sys: Condensed patch summary
パッチまたはパッチシリーズの修正版を投稿する場合は、"RESEND"
追加しないでください。"RESEND" は、前回の投稿から一切変更していない
パッチまたはパッチシリーズを再送する場合にのみ使います。
ただし、パッチまたはパッチシリーズの修正版を投稿する際には "RESEND"
追加しないでください。
"RESEND" は、前回の投稿から一切変更のないパッチまたはパッチシリーズの
再送だけに当てはまります。
件名に PATCH を含める
---------------------
Linus と linux-kernel メーリングリストには大量のメールが届くため、
件名の先頭に ``[PATCH]`` を付けることが一般的な慣例となっています。
これにより、Linus や他のカーネル開発者は、パッチとその他の議論を
容易に区別できます。
``git send-email`` は、この指定を自動的に行います。
作業への署名 - Developer's Certificate of Origin
--------------------------------------------------
誰が何を行ったのかを追跡しやすくするため、特にパッチが複数階層の
メンテナーを経由して最終的にカーネルへ取り込まれる場合に備えて、
メールでやり取りされるパッチには sign-off の手続きが導入されています。
sign-off は、パッチの説明の末尾に追加する単純な一行です。これは、
そのパッチを自分で作成したか、オープンソースのパッチとして提出する
権利を持っていることを証明します。
.. note:: 【訳註】
``Signed-off-by`` によって同意する対象は、翻訳文ではなく、
以下に示す英語原文の Developer's Certificate of Origin 1.1 です。
DCO は法的な性質を持つ文書であるため、本文は翻訳せず、原文のまま
掲載します。内容を確認する場合は、必ず英語原文を参照してください。
規則は単純で、以下を証明できる場合です::
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
上記を証明できる場合は、次のような行を追加します::
Signed-off-by: Random J Developer <random@developer.example.org>
既知の身元を使用してください。匿名での貢献は認められません。
``git commit -s`` を使用すると、この行を自動的に追加できます。
revert にも ``Signed-off-by:`` を含める必要があります。
``git revert -s`` を使用すると、自動的に追加できます。
末尾に追加のタグを付ける人もいます。現時点では無視されますが、
社内手続きを示したり、sign-off に関する特記事項を記録したりするために
使用できます。
作者の SoB に続く追加の SoB``Signed-off-by:``)は、パッチの開発には
関与せず、その取り扱いや転送を行った人によるものです。SoB の連鎖は、
パッチがメンテナーを経て最終的に Linus へ届いた実際の経路を反映する
必要があります。最初の SoB は、単独の主要作者であることを示します。

View File

@@ -66,15 +66,4 @@ kernel e sobre como ver seu trabalho integrado.
.. toctree::
:maxdepth: 1
Introdução <process/1.Intro>
Guia do Processo de Desenvolvimento <process/development-process>
Index de documentos do Kernel <process/kernel-docs>
Regras de licenciamento <process/license-rules>
Como começar <process/howto>
Requisitos mínimos <process/changes>
Conclave (Continuidade do projeto) <process/conclave>
Manuais dos mantenedores <process/maintainer-handbooks>
Processo do subsistema de rede (netdev) <process/maintainer-netdev>
Processo do subsistema SoC <process/maintainer-soc>
Conformidade de DTS para SoC <process/maintainer-soc-clean-dts>
Processo do subsistema KVM x86 <process/maintainer-kvm-x86>
process/index

View File

@@ -0,0 +1,440 @@
.. SPDX-License-Identifier: GPL-2.0
Escrever o código corretamente
==============================
Embora haja muito o que se dizer sobre um processo de design sólido e orientado
à comunidade, a prova de qualquer projeto de desenvolvimento de kernel está no
código resultante. É o código que será examinado por outros desenvolvedores e
mesclado (ou não) na árvore principal (*mainline*). Portanto, é a qualidade
deste código que determinará o sucesso final do projeto.
Esta seção examinará o processo de codificação. Começaremos analisando uma série
de maneiras pelas quais os desenvolvedores de kernel podem errar. Em seguida, o
foco mudará para como fazer as coisas do jeito certo e as ferramentas que podem
ajudar nessa busca.
Armadilhas
----------
Estilo de Codificação
*********************
O kernel há muito possui um estilo de codificação padrão, descrito em
:ref:`Documentation/process/coding-style.rst <codingstyle>`. Por grande parte
desse tempo, as políticas descritas naquele arquivo eram consideradas, no
máximo, como recomendações. Como resultado, há uma quantidade substancial
de código no kernel que não cumpre as diretrizes de estilo de codificação.
A presença desse código leva a dois riscos independentes para os
desenvolvedores do kernel.
O primeiro deles é acreditar que os padrões de codificação do kernel não importam
e não são exigidos. A verdade é que adicionar novo código ao kernel é muito
difícil se esse código não estiver escrito de acordo com o padrão; muitos
desenvolvedores solicitarão que o código seja reformatado antes mesmo de
revisá-lo. Uma base de código tão grande quanto a do kernel exige certa
uniformidade para tornar possível que os desenvolvedores entendam rapidamente
qualquer parte dela. Portanto, não há mais espaço para códigos com formatações
estranhas.
Ocasionalmente, o estilo de codificação do kernel entrará em conflito com o
estilo exigido por um empregador. Nesses casos, o estilo do kernel terá que
vencer para que o código possa ser mesclado. Colocar código no kernel significa
abrir mão de um certo grau de controle de várias maneiras — incluindo o controle
sobre como o código é formatado.
A outra armadilha é presumir que o código já presente no kernel necessita
urgentemente de correções de estilo de codificação. Os desenvolvedores podem
começar a gerar patches de reformatação como uma forma de ganhar familiaridade
com o processo, ou como um meio de incluir seus nomes nos logs de alterações
(*changelogs*) do kernel ou ambos. No entanto, patches puramente de estilo de
codificação são vistos como ruído pela comunidade de desenvolvimento; eles tendem
a receber uma recepção fria. Portanto, é melhor evitar esse tipo de patch. É
natural corrigir o estilo de um trecho de código ao trabalhar nele por outros
motivos, mas mudanças de estilo de codificação não devem ser feitas apenas por
fazer.
O documento de estilo de codificação também não deve ser lido como uma lei
absoluta que nunca pode ser transgredida. Se houver um bom motivo para ir contra
o estilo (uma linha que se torna muito menos legível se for dividida para caber
no limite de 80 colunas, por exemplo), simplesmente faça isso.
Note que você também pode usar a ferramenta ``clang-format`` para ajudá-lo com
essas regras, para reformatar rapidamente partes do seu código de forma automática
e para revisar arquivos completos a fim de identificar erros de estilo de
codificação, erros de digitação e possíveis melhorias. Ela também é útil para
ordenar ``#includes``, alinhar variáveis/macros, reajustar o fluxo de textos e
outras tarefas semelhantes. Veja o arquivo
:ref:`Documentation/dev-tools/clang-format.rst <clangformat>` para mais detalhes.
Algumas configurações básicas do editor, como indentação e fins de linha,
serão definidas automaticamente se você estiver usando um editor compatível
com o EditorConfig. Consulte o site oficial do EditorConfig para obter mais
informações: https://editorconfig.org/
Camadas de Abstração
********************
Os professores de Ciência da Computação ensinam os alunos a fazerem uso
extensivo de camadas de abstração em nome da flexibilidade e da ocultação de
informações. Certamente o kernel faz uso extensivo de abstração; nenhum
projeto que envolva vários milhões de linhas de código poderia fazer o
contrário e sobreviver. No entanto, a experiência tem mostrado que a
abstração excessiva ou prematura pode ser tão prejudicial quanto a otimização
prematura. A abstração deve ser usada até o nível necessário e não além.
Em um nível simples, considere uma função que possui um argumento que é
sempre passado como zero por todos os chamadores. Alguém poderia manter esse
argumento caso alguém eventualmente precise usar a flexibilidade extra que ele
oferece. A essa altura, no entanto, as chances são grandes de que o código que
implementa esse argumento extra tenha sido quebrado de alguma forma sutil que
nunca foi percebida — porque ele nunca foi usado. Ou, quando surge a
necessidade de flexibilidade extra, ela não ocorre de uma forma que corresponda
à expectativa inicial do programador. Os desenvolvedores do kernel enviam
patches rotineiramente para remover argumentos não utilizados; eles não devem,
em geral, ser adicionados em primeiro lugar.
Camadas de abstração que ocultam o acesso ao hardware — frequentemente para
permitir que a maior parte de um driver seja usada com múltiplos sistemas
operacionais — são especialmente malvistas. Essas camadas obscurecem o código
e podem impor uma penalidade de desempenho; elas não pertencem ao kernel
Linux.
Por outro lado, se você se pegar copiando quantidades significativas de código
de outro subsistema do kernel, é hora de perguntar se faria sentido, de fato,
extrair parte desse código em uma biblioteca separada ou implementar essa
funcionalidade em um nível superior. Não há valor em duplicar o mesmo código
por todo o kernel.
Uso de #ifdef e do pré-processador em geral
*******************************************
O pré-processador C parece apresentar uma forte tentação para alguns
programadores C, que o veem como uma forma de codificar eficientemente uma grande
quantidade de flexibilidade em um arquivo-fonte. No entanto, o pré-processador
não é C, e o uso pesado dele resulta em um código muito mais difícil de ser lido
por outros e mais difícil para o compilador verificar a correção. O uso pesado
do pré-processador é quase sempre um sinal de código que precisa de algum
trabalho de limpeza.
A compilação condicional com #ifdef é, de fato, um recurso poderoso, e é
utilizada dentro do kernel. Mas há pouco desejo de ver um código que seja
salpicado liberalmente com blocos #ifdef. Como regra geral, o uso de #ifdef
deve ser confinado a arquivos de cabeçalho (headers) sempre que possível. O
código compilado condicionalmente pode ser confinado a funções que, se o código
não estiver presente, simplesmente se tornam vazias. O compilador irá então,
silenciosamente, otimizar e remover a chamada para a função vazia. O resultado
é um código muito mais limpo e fácil de acompanhar.
As macros do pré-processador C apresentam uma série de riscos, incluindo a
possível avaliação múltipla de expressões com efeitos colaterais e a falta de
segurança de tipos. Se você se sentir tentado a definir uma macro, considere a
criação de uma função inline em seu lugar. O código resultante será o mesmo,
mas as funções inline são mais fáceis de ler, não avaliam seus argumentos
múltiplas vezes e permitem que o compilador realize a checagem de tipos nos
argumentos e no valor de retorno.
Funções Inline
**************
No entanto, as funções inline apresentam um perigo próprio. Os programadores
podem ficar encantados com a eficiência percebida inerente a evitar uma chamada
de função e encher um arquivo de código-fonte com funções inline. Essas
funções, contudo, podem na verdade reduzir o desempenho. Como seu código é
replicado em cada local de chamada, elas acabam inflando o tamanho do kernel
compilado. Isso, por sua vez, cria pressão nos caches de memória do
processador, o que pode desacelerar a execução drasticamente. As funções
inline, como regra, devem ser bastante pequenas e relativamente raras. O custo
de uma chamada de função, afinal de contas, não é tão alto; a criação de um
grande número de funções inline é um exemplo clássico de otimização prematura.
Em geral, os programadores de kernel ignoram os efeitos de cache por sua própria
conta e risco. O clássico compromisso entre tempo e espaço (tradeoff) ensinado
nas aulas introdutórias de estruturas de dados frequentemente não se aplica ao
hardware contemporâneo. Espaço *é* tempo, no sentido de que um programa maior
será executado mais lentamente do que um que seja mais compacto.
Compiladores mais recentes desempenham um papel cada vez mais ativo em decidir
se uma determinada função deve ou não ser realmente inline. Portanto, a inserção
liberal da palavra-chave "inline" pode não apenas ser excessiva; ela também pode
ser irrelevante.
Mecanismo de Trava
******************
Em maio de 2006, a pilha de rede "Devicescape" foi, com grande alarde, lançada
sob a GPL e disponibilizada para inclusão no kernel mainline. Essa doação foi uma
notícia bem-vinda; o suporte para redes sem fio no Linux era considerado abaixo do
padrão, na melhor das hipóteses, e a pilha da Devicescape oferecia a promessa de
corrigir essa situação. No entanto, esse código só entrou de fato no mainline em
junho de 2007 (2.6.22). O que aconteceu?
Esse código mostrava vários sinais de ter sido desenvolvido a portas fechadas em
ambiente corporativo. Mas um grande problema em particular era que ele não havia
sido projetado para funcionar em sistemas multiprocessados. Antes que essa pilha
de rede (agora chamada de mac80211) pudesse ser integrada, um esquema de locking
(bloqueio) precisou ser adaptado a ela.
Era uma vez uma época em que o código do kernel Linux podia ser desenvolvido sem
pensar nos problemas de concorrência apresentados por sistemas multiprocessados.
Hoje, no entanto, este documento está sendo escrito em um laptop dual-core.
Mesmo em sistemas com um único processador, o trabalho feito para melhorar a
capacidade de resposta aumentará o nível de concorrência dentro do kernel. Os
dias em que o código do kernel podia ser escrito sem pensar em locking ficaram
há muito tempo no passado.
Qualquer recurso (estruturas de dados, registradores de hardware, etc.) que
possa ser acessado concorrentemente por mais de uma linha de execução deve ser
protegido por uma trava (lock). O novo código deve ser escrito com esse
requisito em mente; adaptar o locking após o fato é uma tarefa consideravelmente
mais difícil. Os desenvolvedores do kernel devem dedicar um tempo para
compreender as primitivas de locking disponíveis bem o suficiente para escolher
a ferramenta certa para o trabalho. Códigos que mostrem falta de atenção à
concorrência terão um caminho difícil para entrar no mainline.
Regressions
***********
Um perigo final que vale a pena mencionar é este: pode ser tentador fazer uma
alteração (que pode trazer grandes melhorias) que faça algo quebrar para os
usuários existentes. Esse tipo de alteração é chamado de "regressão", e as
regressões tornaram-se totalmente indesejadas no kernel mainline. Com poucas
exceções, as alterações que causarem regressões serão revertidas se a regressão
não puder ser corrigida em tempo hábil. É muito melhor evitar a regressão em
primeiro lugar.
Muitas vezes argumenta-se que uma regressão pode ser justificada se ela fizer as
coisas funcionarem para mais pessoas do que os problemas que ela cria. Por que
não fazer uma alteração se ela trouxer uma nova funcionalidade para dez sistemas
para cada um que ela quebrar? A melhor resposta para essa pergunta foi expressa
por Linus em julho de 2007:
::
Portanto, nós não corrigimos bugs introduzindo novos problemas. Esse caminho
leva à loucura, e ninguém nunca sabe se você está realmente fazendo algum
progresso real. São dois passos para frente, um passo para trás, ou um passo
para frente e dois passos para trás?
(https://lwn.net/Articles/243460/).
Um tipo de regressão especialmente indesejado é qualquer tipo de alteração na
ABI do espaço do usuário (user-space ABI). Uma vez que uma interface tenha sido
exportada para o espaço do usuário, ela deve receber suporte indefinidamente.
Esse fato torna a criação de interfaces de espaço do usuário particularmente
desafiadora: já que elas não podem ser alteradas de maneiras incompatíveis, elas
devem ser feitas corretamente na primeira vez. Por essa razão, exige-se sempre
muita reflexão, documentação clara e uma ampla revisão para as interfaces do
espaço do usuário.
Ferramentas de verificação de código
------------------------------------
Por enquanto, pelo menos, a escrita de código livre de erros continua sendo um
ideal que poucos de nós conseguem alcançar. O que podemos esperar fazer, no
entanto, é capturar e corrigir o máximo possível desses erros antes que nosso
código entre no kernel mainline. Para esse fim, os desenvolvedores do kernel
reuniram um conjunto impressionante de ferramentas que podem capturar uma ampla
variedade de problemas obscuros de forma automatizada. Qualquer problema
capturado pelo computador é um problema que não afligirá um usuário mais tarde,
portanto, é lógico que as ferramentas automatizadas devem ser usadas sempre que
possível.
O primeiro passo é simplesmente prestar atenção aos avisos (warnings) produzidos
com o compilador. As versões contemporâneas do gcc podem detectar (e alertar
sobre) um grande número de erros potenciais. Com bastante frequência, esses
avisos apontam para problemas reais. O código enviado para revisão deve, como
regra, não produzir nenhum aviso do compilador. Ao silenciar os avisos, tome o
cuidado de entender a real causa e tente evitar "correções" que façam o aviso
desaparecer sem resolver a sua origem.
Note que nem todos os avisos do compilador ficam ativados por padrão. Compile o
kernel com "make KCFLAGS=-W" para obter o conjunto completo.
O kernel fornece várias opções de configuração que ativam recursos de
depuração; a maioria delas é encontrada no submanu "kernel hacking". Várias
dessas opções devem ser ativadas para qualquer kernel usado para fins de
desenvolvimento ou teste. Em particular, você deve ativar:
- FRAME_WARN para obter avisos sobre quadros de pilha (stack frames) maiores
que um determinado valor. A saída gerada pode ser volumosa, mas não é
necessário se preocupar com os avisos de outras partes do kernel.
- DEBUG_OBJECTS adicionará código para rastrear o tempo de vida de vários
objetos criados pelo kernel e alertará quando as ações forem feitas fora de
ordem. Se você estiver adicionando um subsistema que cria (e exporta) seus
próprios objetos complexos, considere adicionar suporte à infraestrutura de
depuração de objetos.
- DEBUG_SLAB pode encontrar uma variedade de erros de alocação e uso de
memória; ele deve ser usado na maioria dos kernels de desenvolvimento.
- DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP e DEBUG_MUTEXES encontrarão uma série de
erros comuns de locking (bloqueio).
Existem várias outras opções de depuração, algumas das quais serão discutidas
abaixo. Algumas delas têm um impacto significativo no desempenho e não devem ser
usadas o tempo todo. Mas um tempo gasto aprendendo as opções disponíveis
provavelmente se pagará muitas vezes em pouco tempo.
Uma das ferramentas de depuração mais pesadas é o verificador de locking, ou
"lockdep". Esta ferramenta rastreará a aquisição e a liberação de cada trava
(spinlock ou mutex) no sistema, a ordem em que as travas são adquiridas umas em
relação às outras, o ambiente de interrupção atual e muito mais. Ela pode,
então, garantir que as travas sejam sempre adquiridas na mesma ordem, que as
mesmas suposições de interrupção se apliquem em todas as situações e assim por
diante. Em outras palavras, o lockdep pode encontrar uma série de cenários nos
quais o sistema poderia, em raras ocasiões, entrar em deadlock. Esse tipo de
problema pode ser doloroso (tanto para desenvolvedores quanto para usuários) em
um sistema implantado; o lockdep permite que eles sejam encontrados de maneira
automatizada e antecipada. Códigos com qualquer tipo de locking não trivial
devem ser executados com o lockdep ativado antes de serem enviados para inclusão.
Como um programador de kernel diligente, você irá, sem dúvida, verificar o
status de retorno de qualquer operação (como uma alocação de memória) que possa
falhar. O fato, porém, é que os caminhos de recuperação de falha resultantes
estão, provavelmente, completamente não testados. Código não testado tende a ser
código quebrado; você poderia estar muito mais confiante em seu código se todos
esses caminhos de tratamento de erros tivessem sido exercitados algumas vezes.
O kernel fornece um framework de injeção de falhas (fault injection) que pode
fazer exatamente isso, especialmente onde alocações de memória estão
envolvidas. Com a injeção de falhas ativada, uma porcentagem configurável das
alocações de memória será forçada a falhar; essas falhas podem ser restritas a
um intervalo específico de código. Executar o código com a injeção de falhas
ativada permite ao programador ver como o código responde quando as coisas vão
mal. Veja Documentation/fault-injection/fault-injection.rst para mais
informações sobre como usar esse recurso.
Outros tipos de erros podem ser encontrados com a ferramenta de análise estática
"sparse". Com o sparse, o programador pode ser alertado sobre confusões entre
endereços do espaço do usuário e do espaço do kernel, mistura de quantidades
big-endian e small-endian, a passagem de valores inteiros onde um conjunto de
sinalizadores de bits (bit flags) é esperado, e assim por diante. O sparse deve
ser instalado separadamente (ele pode ser encontrado em
https://sparse.wiki.kernel.org/index.php/Main_Page se a sua distribuição não o
incluir como pacote); ele pode então ser executado no código adicionando "C=1"
ao seu comando make.
A ferramenta "Coccinelle" (http://coccinelle.lip6.fr/) é capaz de encontrar uma
ampla variedade de potenciais problemas de codificação; ela também pode propor
correções para esses problemas. Uma quantidade considerável de "patches
semânticos" para o kernel foi empacotada sob o diretório scripts/coccinelle;
executar "make coccicheck" passará por esses patches semânticos e relatará
quaisquer problemas encontrados. Veja
:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`
para mais informações.
Outros tipos de erros de portabilidade são encontrados mais facilmente ao
compilar seu código para outras arquiteturas. Se você por acaso não tiver um
sistema S/390 ou uma placa de desenvolvimento Blackfin à mão, ainda assim poderá
realizar a etapa de compilação. Um grande conjunto de compiladores cruzados
(cross-compilers) para sistemas x86 pode ser encontrado em:
https://www.kernel.org/pub/tools/crosstool/
Um tempo gasto instalando e usando esses compiladores ajudará a evitar
constrangimentos mais tarde.
Documentação
-------------
A documentação frequentemente tem sido mais a exceção do que a regra no
desenvolvimento do kernel. Mesmo assim, uma documentação adequada ajudará a
facilitar a integração de novos códigos ao kernel, tornará a vida mais fácil para
outros desenvolvedores e será útil para os seus usuários. Em muitos casos, a
adição de documentação tornou-se essencialmente obrigatória.
A primeira parte da documentação de qualquer patch é o seu log de alterações
(changelog) associado. As entradas do log devem descrever o problema que está
sendo resolvido, a forma da solução, as pessoas que trabalharam no patch,
quaisquer efeitos relevantes no desempenho e qualquer outra coisa que possa ser
necessária para entender o patch. Certifique-se de que o changelog diga o
*porquê* de o patch valer a pena ser aplicado; um número surpreendente de
desenvolvedores falha em fornecer essa informação.
Qualquer código que adicione uma nova interface de espaço do usuário — incluindo
novos arquivos sysfs ou /proc — deve incluir a documentação dessa interface, de
modo a permitir que os desenvolvedores do espaço do usuário saibam com o que
estão trabalhando. Veja Documentation/ABI/README para uma descrição de como essa
documentação deve ser formatada e quais informações precisam ser fornecidas.
O arquivo :ref:`Documentation/admin-guide/kernel-parameters.rst
<kernelparameters>` descreve todos os parâmetros de boot do kernel. Qualquer
patch que adicione novos parâmetros deve adicionar as entradas apropriadas a
este arquivo.
Quaisquer novas opções de configuração devem ser acompanhadas por um texto de
ajuda que explique claramente as opções e quando o usuário pode querer
selecioná-las.
As informações de API interna de muitos subsistemas são documentadas por meio de
comentários com formatação especial; esses comentários podem ser extraídos e
formatados de várias maneiras pelo script "kernel-doc". Se você estiver
trabalhando em um subsistema que possui comentários kerneldoc, você deve
mantê-los e adicioná-los, conforme apropriado, para funções disponíveis
externamente. Mesmo em áreas que não tenham sido documentadas dessa forma, não há
mal nenhum em adicionar comentários kerneldoc para o futuro; de fato, esta pode
ser uma atividade útil para desenvolvedores iniciantes de kernel. O formato
desses comentários, junto com algumas informações sobre como criar modelos de
kerneldoc, pode ser encontrado em :ref:`Documentation/doc-guide/ <doc_guide>`.
Qualquer pessoa que leia uma quantidade significativa de código existente do
kernel notará que, frequentemente, os comentários chamam a atenção por sua
ausência. Mais uma vez, as expectativas para códigos novos são mais altas do que
eram no passado; integrar código sem comentários será mais difícil. Dito isso,
há pouco interesse em códigos comentados de forma prolixa. O código deve, por si
só, ser legível, com os comentários explicando os aspectos mais sutis.
Certas coisas devem sempre ser comentadas. O uso de barreiras de memória
(memory barriers) deve ser acompanhado por uma linha explicando por que a
barreira é necessária. As regras de locking (bloqueio) para estruturas de dados
geralmente precisam ser explicadas em algum lugar. Grandes estruturas de dados
precisam de uma documentação abrangente em geral. Dependências não óbvias entre
trechos distintos de código devem ser apontadas. Qualquer coisa que possa tentar
um "faxineiro de código" (code janitor) a fazer uma "limpeza" incorreta precisa
de um comentário dizendo por que foi feita daquela maneira. E assim por diante.
Alterações de API interna
-------------------------
A interface binária fornecida pelo kernel para o espaço do usuário não pode ser
quebrada, exceto sob as circunstâncias mais graves. Por outro lado, as
interfaces de programação internas do kernel são altamente fluidas e podem ser
alteradas quando surgir a necessidade. Se você se encontrar tendo que criar uma
gambiarra para contornar uma API do kernel, ou simplesmente deixando de usar uma
funcionalidade específica porque ela não atende às suas necessidades, isso pode
ser um sinal de que a API precisa mudar. Como desenvolvedor de kernel, você tem
o poder de fazer tais alterações.
Existem, é claro, algumas pegadinhas. Alterações de API podem ser feitas, mas
precisam ser bem justificadas. Portanto, qualquer patch que faça uma alteração de
API interna deve ser acompanhado por uma descrição do que é a mudança e do porquê
ela é necessária. Esse tipo de alteração também deve ser separado em um patch
independente, em vez de ser enterrado dentro de um patch maior.
A outra pegadinha é que o desenvolvedor que altera uma API interna é geralmente
encarregado da tarefa de corrigir qualquer código dentro da árvore do kernel que
tenha sido quebrado pela mudança. Para uma função amplamente utilizada, esse
dever pode levar a literalmente centenas ou milhares de alterações — muitas das
quais provavelmente entrarão em conflito com o trabalho que está sendo feito por
outros desenvolvedores. Desnecessário dizer que isso pode ser um grande
trabalho, então é melhor ter certeza de que a justificativa é sólida. Note que
a ferramenta Coccinelle pode ajudar com alterações de API de amplo alcance.
Ao fazer uma alteração incompatível de API, deve-se, sempre que possível,
garantir que o código que não foi atualizado seja capturado pelo compilador.
Isso ajudará você a ter certeza de que encontrou todos os usos dessa interface
dentro da árvore (in-tree). Isso também alertará os desenvolvedores de códigos
fora da árvore (out-of-tree) de que há uma mudança à qual eles precisam
responder. Dar suporte a código fora da árvore não é algo com que os
desenvolvedores do kernel precisem se preocupar, mas também não temos que
tornar a vida dos desenvolvedores fora da árvore mais difícil do que precisa ser.

View File

@@ -0,0 +1,376 @@
.. SPDX-License-Identifier: GPL-2.0
Enviando patches
================
Cedo ou tarde, chega o momento em que seu trabalho está pronto para ser
apresentado à comunidade para revisão e, eventualmente, inclusão no kernel
mainline. Sem surpresa, a comunidade de desenvolvimento do kernel evoluiu um
conjunto de convenções e procedimentos que são usados no envio de patches;
segui-los tornará a vida muito mais fácil para todos os envolvidos. Este
documento tentará cobrir essas expectativas em detalhes razoáveis; mais
informações também podem ser encontradas nos arquivos
:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
e :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`.
Quando enviar
-------------
Existe uma tentação constante de evitar o envio de patches antes que eles
estejam completamente "prontos". Para patches simples, isso não é um problema.
No entanto, se o trabalho que está sendo feito for complexo, há muito a se
ganhar obtendo feedback da comunidade antes que o trabalho esteja concluído.
Portanto, você deve considerar o envio de trabalhos em andamento, ou até mesmo
disponibilizar uma árvore git para que os desenvolvedores interessados possam
acompanhar o seu trabalho a qualquer momento.
Ao enviar um código que ainda não é considerado pronto para inclusão, é uma boa
ideia dizer isso no próprio envio. Mencione também qualquer trabalho importante
que ainda precise ser feito e quaisquer problemas conhecidos. Menos pessoas vão
olhar para patches que sabidamente estão "meio cozidos" (half-baked), mas aqueles
que o fizerem virão com a ideia de que podem ajudá-lo a conduzir o trabalho na
direção certa.
Antes de criar patches
----------------------
Há uma série de coisas que devem ser feitas antes de você considerar o envio
de patches para la comunidade de desenvolvimento. Elas incluem:
- Teste o código tanto quanto puder. Faça uso das ferramentas de depuração
do kernel, garanta que o kernel seja compilado com todas as combinações
razoáveis de opções de configuração, use compiladores cruzados (cross-
compilers) para compilar para diferentes arquiteturas, etc. Adicione testes,
provavelmente usando um framework de testes existente como o KUnit, e
inclua-os como um membro separado da sua série (veja a próxima seção para
mais informações sobre séries de patches). Note que isso pode ser
obrigatório ao afetar alguns subsistemas. Por exemplo, funções de biblioteca
(localizadas sob lib/) são amplamente utilizadas em quase todos os lugares e
espera-se que sejam testadas adequadamente.
- Certifique-se de que seu código esteja em conformidade com as diretrizes de
estilo de codificação do kernel.
- Sua alteração tem implicações no desempenho? Se sim, você deve executar
benchmarks mostrando qual é o impacto (ou benefício) da sua mudança; um
resumo dos resultados deve ser incluído junto ao patch.
- Tenha certeza de que você tem o direito de enviar o código. Se este
trabalho foi feito para um empregador, o empregador provavelmente tem direito
sobre o trabalho e deve estar de acordo com a sua liberação sob a GPL.
Como regra geral, dedicar um pouco de reflexão extra antes de enviar o código
quase sempre compensa o esforço em pouco tempo.
Preparação de patches
---------------------
A preparação de patches para envio pode dar uma quantidade surpreendente de
trabalho, mas, mais uma vez, tentar economizar tempo aqui geralmente não é
aconselhável, mesmo a curto prazo.
Os patches devem ser preparados contra uma versão específica do kernel. Como
regra geral, um patch deve ser baseado no mainline atual encontrado na árvore
git do Linus. Ao basear-se no mainline, comece a partir de um ponto de
lançamento bem conhecido — um release estável ou -rc —, em vez de criar uma
bifurcação (branch) a partir do mainline em um ponto arbitrário.
No entanto, pode tornar-se necessário criar versões contra a árvore -mm,
linux-next ou a árvore de um subsistema, para facilitar testes e revisões mais
amplos. Dependendo da área do seu patch e do que está acontecendo em outros
lugares, basear um patch contra essas outras árvores pode exigir uma quantidade
significativa de trabalho para resolver conflitos e lidar com mudanças de API.
Apenas as alterações mais simples devem ser formatadas como um único patch; tudo
o mais deve ser feito como uma série lógica de mudanças. Dividir patches é uma
arte; alguns desenvolvedores passam muito tempo descobrindo como fazer isso da
maneira que a comunidade espera. Existem algumas regras práticas, no entanto,
que podem ajudar consideravelmente:
- A série de patches que você envia quase certamente não será a série de
alterações encontrada no seu sistema de controle de versão de trabalho. Em
vez disso, as mudanças que você fez precisam ser consideradas em sua forma
final e, então, divididas de maneiras que façam sentido. Os desenvolvedores
estão interessados em alterações discretas e autocontidas, não no caminho
que você percorreu para chegar a essas alterações.
- Cada alteração logicamente independente deve ser formatada como um patch separado.
Essas alterações podem ser pequenas ("adicionar um campo a esta estrutura") ou
grandes (adicionar um driver totalmente novo, por exemplo), mas devem ser
conceitualmente pequenas e passíveis de uma descrição de uma única linha. Cada
patch deve fazer uma alteração específica que possa ser revisada por si só e
verificada para garantir que faz o que diz fazer.
- Como uma forma de reafirmar a diretriz acima: não misture diferentes tipos de
alterações no mesmo patch. Se um único patch corrige uma falha crítica de
segurança, reorganiza algumas estruturas e reformatará o código, há uma grande
chance de que ele seja ignorado e a correção importante seja perdida.
- Cada patch deve resultar em um kernel que compile e funcione corretamente; se
sua série de patches for interrompida no meio, o resultado ainda deve ser um
kernel funcional. A aplicação parcial de uma série de patches é um cenário
comum quando a ferramenta "git bisect" é usada para encontrar regressões; se o
resultado for um kernel quebrado, você tornará a vida mais difícil para os
desenvolvedores e usuários que estão engajados no nobre trabalho de rastrear
problemas.
- No entanto, não exagere. Certa vez, um desenvolvedor enviou um conjunto de
edições em um único arquivo como 500 patches separados — um ato que não o
tornou a pessoa mais popular na lista de discussão do kernel. Um único patch
pode ser razoavelmente grande, desde que ainda contenha uma única alteração
*lógica*.
- Pode ser tentador adicionar toda uma nova infraestrutura com uma série de
patches, mas deixar essa infraestrutura sem uso até que o patch final da série
ative tudo. Essa tentação deve ser evitada, se possível; se essa série
adicionar regressões, a bisseção (bisection) apontará o último patch como aquele
que causou o problema, mesmo que o bug real esteja em outro lugar. Sempre que
possível, um patch que adiciona código novo deve tornar esse código ativo
imediatamente.
Trabalhar para criar a série de patches perfeita pode ser um processo
frustrante, que exige bastante tempo e reflexão após o "trabalho real" ter sido
concluído. Quando feito corretamente, no entanto, é um tempo bem gasto.
Formatação de patches e logs de alterações
------------------------------------------
Então agora você tem uma série perfeita de patches para enviar, mas o trabalho
ainda não terminou. Cada patch precisa ser formatado em uma mensagem que comunique
de forma rápida e clara o seu propósito para o resto do mundo. Para esse fim,
cada patch será composto pelo seguinte:
- Uma linha "From" opcional que nomeia o autor do patch. Esta linha só é
necessária se você estiver repassando o patch de outra pessoa via e-mail,
mas nunca é demais adicioná-la em caso de dúvida.
- Uma descrição de uma única linha sobre o que o patch faz. Esta mensagem deve
ser suficiente para que um leitor que a veja sem outro contexto consiga
compreender o escopo do patch; esta é a linha que aparecerá nos logs de
alterações (changelogs) de "forma curta". Esta mensagem geralmente é formatada
com o nome do subsistema relevante primeiro, seguido pelo propósito do patch.
Por exemplo:
::
gpio: fix build on CONFIG_GPIO_SYSFS=n
- Uma linha em branco seguida por uma descrição detalhada do conteúdo do
patch. Esta descrição pode ser tão longa quanto necessário; ela deve dizer
o que o patch faz e por que ele deve ser aplicado ao kernel.
- Uma ou mais linhas de marcadores (tags) com, no mínimo, uma linha
"Signed-off-by:" do autor do patch. Os marcadores serão descritos em mais
detalhes abaixo.
Os itens acima, juntos, formam o log de alterações (changelog) do patch. Escrever
bons changelogs é uma arte crucial, mas frequentemente negligenciada; vale a
pena dedicar mais um momento para discutir esse assunto. Ao escrever um
changelog, você deve ter em mente que várias pessoas diferentes lerão suas
palavras. Elas incluem mantenedores de subsistemas e revisores que precisam
decidir se o patch deve ser incluído, distribuidores e outros mantenedores
tentando decidir se um patch deve ser retroportado (backported) para outros
kernels, caçadores de bugs se perguntando se o patch é responsável por um
problema que estão perseguindo, usuários que querem saber como o kernel mudou e
muito mais. Um bom changelog transmite a informação necessária para todas essas
pessoas da maneira mais direta e concisa possível.
Para esse fim, a linha de resumo deve descrever os efeitos e a motivação da
alteração o melhor possível, dada a restrição de uma única linha. A descrição
detalhada pode então ampliar esses tópicos e fornecer qualquer informação
adicional necessária. Se o patch corrige um bug, cite o commit que introduziu o
bug, se possível (e, por favor, forneça tanto o ID do commit quanto o título ao
citar commits). Se um problema estiver associado a uma saída específica de log
ou do compilador, inclua essa saída para ajudar outras pessoas que buscam uma
solução para o mesmo problema. Se a mudança tem o objetivo de dar suporte a
outras alterações que virão em um patch posterior, informe isso. Se as APIs
internas forem alteradas, detalhe essas mudanças e como outros desenvolvedores
devem reagir. Em geral, quanto mais você puder se colocar no lugar de todos que
lerão seu changelog, melhor será esse changelog (e o kernel como um todo).
Desnecessário dizer que o changelog deve ser o texto usado ao submeter (commit)
a alteração em um sistema de controle de versão. Ele será seguido por:
- O patch em si, no formato de patch unificado ("-u"). O uso da opção "-p" no
diff associará os nomes das funções às alterações, tornando o patch resultante
mais fácil de ser lido por outras pessoas.
As tags já mencionadas brevemente acima são usados para fornecer
informações sobre como o patch surgiu. Eles são descritos em detalhes no
documento :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`;
o que se segue aqui é um breve resumo.
Um marcador é usado para se referir a commits anteriores que introduziram os
problemas corrigidos pelo patch::
Fixes: 1f2e3d4c5b6a ("The first line of the commit specified by the first 12 characters of its SHA-1 ID")
Outro marcador é usado para vincular páginas da web com contextos ou detalhes
adicionais, por exemplo, uma discussão anterior que levou ao patch ou um
documento com uma especificação implementada pelo patch::
Link: https://example.com/somewhere.html optional-other-stuff
De acordo com as orientações do Pinguim-Chefe, um marcador Link
só deve ser adicionado a um commit se ele levar a informações úteis que não
são encontradas no próprio commit.
Se a URL apontar para um relatório de bug público que está sendo corrigido pelo
patch, use o marcador "Closes:" em seu lugar::
Closes: https://example.com/issues/1234 optional-other-stuff
Alguns rastreadores de bugs têm a capacidade de fechar problemas de forma
automática quando um commit com tal marcador é aplicado. Alguns bots que
monitoram listas de discussão também podem rastrear esses marcadores e tomar certas
ações. Rastreadores de bugs privados e URLs inválidas são proibidos.
Outro tipo de marcador é usado para documentar quem esteve envolvido no
desenvolvimento do patch. Cada um deles usa este formato::
tag: Full Name <email address> optional-other-stuff
Os marcadores de uso comum são:
- Signed-off-by: esta é uma certificação do desenvolvedor de que ele ou ela
tem o direito de enviar o patch para inclusão no kernel. É um acordo com o
Developer's Certificate of Origin (Certificado de Origem do Desenvolvedor),
cujo texto completo pode ser encontrado em
:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`.
Códigos sem um signoff adequado não podem ser mesclados (merged) no mainline.
- Co-developed-by: afirma que o patch foi criado em coautoria por vários
desenvolvedores; é usado para dar atribuição aos coautores (além do autor
atribuído pelo marcador From:) quando várias pessoas trabalham em um único
patch. Cada Co-developed-by: deve ser imediatamente seguido por um
Signed-off-by: do coautor associado. Detalhes e exemplos podem ser encontrados
em :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`.
- Acked-by: indica o acordo de outro desenvolvedor (frequentemente um
mantenedor do código relevante) de que o patch é apropriado para inclusão
no kernel.
- Tested-by: afirma que a pessoa nomeada testou o patch e verificou que ele
funciona.
- Reviewed-by: o desenvolvedor nomeado revisou o patch para verificar sua
correção; veja a declaração do revisor em
:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
para mais detalhes.
- Reported-by: nomeia um usuário que relatou o problema que é corrigido por este
patch; este marcador é usado para dar crédito às pessoas (frequentemente sub-
valorizadas) que testam nosso código e nos informam quando as coisas não
funcionam corretamente. Nota: este marcador deve ser seguido por um marcador
Closes: apontando para o relato, a menos que o relato não esteja disponível na
web. O marcador Link: pode ser usado em vez de Closes: se o patch corrigir
apenas uma parte do(s) problema(s) relatado(s).
- A Suggested-by: este marcador indica que a ideia do patch foi sugerida pela
pessoa nomeada e garante o crédito a ela pela ideia. Isso, espera-se, irá
inspirá-la a nos ajudar novamente no futuro.
- Cc: a pessoa nomeada recebeu uma cópia do patch e teve a oportunidade de
comentar sobre ele.
Tenha cuidado ao adicionar os marcadores mencionados acima aos seus patches, pois
todos, exceto Cc:, Reported-by: e Suggested-by:, precisam de permissão explícita
fontes da pessoa nomeada. Para esses três, a permissão implícita é suficiente se
a pessoa contribuiu para o kernel Linux usando esse nome e endereço de e-mail de
acordo com os arquivos do lore ou o histórico de commits — e, no caso de
Reported-by: e Suggested-by:, se fizeram o relato ou a sugestão publicamente.
Nota: o bugzilla.kernel.org é um local público nesse sentido, mas os endereços
de e-mail usados lá são privados; portanto, não os exponha em marcadores, a menos
que a pessoa os tenha usado em contribuições anteriores.
Enviando o patch
-----------------
Antes de enviar seus patches por e-mail, há algumas outras coisas com as quais
você deve se preocupar:
- Você tem certeza de que seu cliente de e-mail não vai corromper os patches?
Patches que sofreram alterações desnecessárias de espaço em branco ou quebra
de linha causadas pelo cliente de e-mail não serão aplicados na outra ponta
e, frequentemente, não serão examinados em detalhes. Se houver qualquer
dúvida, envie o patch para você mesmo e certifique-se de que ele chegue intacto.
O documento :ref:`Documentation/process/email-clients.rst <email_clients>`
possui algumas dicas úteis sobre como fazer clientes de e-mail específicos
funcionarem para o envio de patches.
- Você tem certeza de que seu patch está livre de erros bobos? Você deve sempre
passar os patches pelo scripts/checkpatch.pl e corrigir as reclamações que
ele apresentar. Por favor, tenha em mente que o checkpatch.pl, embora seja a
personificação de uma quantidade razoável de reflexão sobre como os patches do
kernel devem parecer, não é mais inteligente que você. Se corrigir uma
reclamação do checkpatch.pl piorar o código, não o faça.
Os patches devem sempre ser enviados como texto simples (plain text). Por favor,
não os envie como anexos; isso torna muito mais difícil para os revisores citarem
trechos do patch em suas respostas. Em vez disso, coloque o patch diretamente no
corpo da sua mensagem.
Ao enviar patches por e-mail, é importante enviar cópias para qualquer pessoa
que possa estar interessada neles. Ao contrário de alguns outros projetos, o
kernel incentiva as pessoas a pecarem pelo excesso, enviando cópias demais; não
assuma que as pessoas relevantes verão sua publicação nas listas de discussão. Em
particular, as cópias devem ir para:
- O(s) mantenedor(es) do(s) subsistema(s) afetado(s). Como descrito antes, o
arquivo MAINTAINERS é o primeiro lugar para procurar por essas pessoas.
- Outros desenvolvedores que estiveram trabalhando na mesma área — especialmente
aqueles que possam estar trabalhando lá agora. Usar o git para ver quem mais
modificou os arquivos nos quais você está trabalhando pode ser útil.
- Se você estiver respondendo a um relato de bug ou a uma solicitação de recurso
(feature request), envie uma cópia também para o autor original.
- Envie uma cópia para a lista de discussão relevante ou, se nada mais se
aplicar, para a lista linux-kernel.
- Se você estiver corrigindo um bug, pense se a correção deve ir para a próxima
atualização estável (stable update). Se sim, stable@vger.kernel.org deve
receber uma cópia do patch. Adicione também um "Cc: stable@vger.kernel.org"
aos marcadores (tags) dentro do próprio patch; isso fará com que a equipe do
stable receba uma notificação quando sua correção for integrada ao mainline.
Ao selecionar os destinatários para um patch, é bom ter uma ideia de quem você
acha que eventualmente aceitará o patch e fará a mesclagem (merge). Embora seja
possível enviar patches diretamente para Linus Torvalds e fazer com que ele os
mescle, as coisas normalmente não são feitas dessa forma. Linus está ocupado, e
existem mantenedores de subsistemas que vigiam partes específicas do kernel. Em
geral, você desejará que esse mantenedor mescle seus patches. Se não houver um
mantenedor óbvio, Andrew Morton costuma ser o destino de patch de último recurso.
Os patches precisam de boas linhas de assunto (subject lines). O formato canônico
para a linha de um patch é algo como:
::
[PATCH nn/mm] subsys: descrição de uma linha do patch
onde "nn" é o número ordinal do patch, "mm" é o número total de patches na
série, e "subsys" é o nome do subsistema afetado. Claramente, nn/mm pode ser
omitido no caso de um patch único e isolado (standalone).
Se você tiver uma série significativa de patches, é costumeiro enviar uma
descrição introdutória como a parte zero. Essa convenção não é seguida
universalmente, no entanto; se você a utilizar, lembre-se de que as informações
da introdução não entram nos changelogs do kernel. Portanto, certifique-se de
que os patches, em si, possuam informações completas em seus changelogs.
Em geral, a segunda parte e as subsequentes de um patch de múltiplas partes devem
ser enviadas como uma resposta à primeira parte, de modo que todas formem uma
única linha de discussão (thread) na ponta receptora. Ferramentas como o git e o
quilt possuem comandos para enviar por e-mail um conjunto de patches com o
encadeamento correto. Se você tiver uma série longa, contudo, e estiver usando o
git, por favor, evite a opção --chain-reply-to para não criar um aninhamento
excepcionalmente profundo.

View File

@@ -0,0 +1,220 @@
.. SPDX-License-Identifier: GPL-2.0
Acompanhamento
==============
Neste ponto, você seguiu as diretrizes apresentadas até aqui e, com a
adição de suas próprias habilidades de engenharia, enviou uma série perfeita
de patches. Um dos maiores erros que até mesmo desenvolvedores experientes
do kernel podem cometer é concluir que o seu trabalho agora está concluído.
Na verdade, o envio de patches indica uma transição para a próxima etapa
do processo, possivelmente com uma quantidade considerável de trabalho
ainda por fazer.
É raro um patch ser tão bom em seu primeiro envio que não haja margem para
melhorias. O processo de desenvolvimento do kernel reconhece esse fato e,
como resultado, é fortemente orientado para o aprimoramento do código
enviado. Espera-se que você, como autor desse código, trabalhe junto à
comunidade do kernel para garantir que seu código esteja de acordo com os
padrões de qualidade do kernel. A falha em participar desse processo muito
provavelmente impedirá a inclusão de seus patches na árvore principal
(*mainline*).
Trabalhando com revisores
-------------------------
Um patch de qualquer relevância resultará em uma série de comentários de outros
desenvolvedores à medida que eles revisam o código. Trabalhar com revisores
pode ser, para muitos desenvolvedores, a parte mais intimidadora do processo
de desenvolvimento do kernel. No entanto, a vida pode se tornar muito mais
fácil se você mantiver algumas coisas em mente:
* Se você explicou bem o seu patch, os revisores entenderão o seu valor
e o porquê de você ter tido o trabalho de escrevê-lo. Contudo, esse valor
não os impedirá de fazer uma pergunta fundamental: como será manter um
kernel com este código inserido nele daqui a cinco ou dez anos? Muitas das
mudanças que podem lhe pedir para fazer — desde ajustes de estilo de código
até reescritas substanciais — vêm do entendimento de que o Linux ainda estará
por aqui e sob desenvolvimento daqui a uma década.
* A revisão de código é um trabalho árduo e uma ocupação relativamente
ingrata; as pessoas lembram quem escreveu o código do kernel, mas há pouca
fama duradoura para aqueles que o revisaram. Portanto, os revisores podem
ficar ranzinzas, especialmente quando veem os mesmos erros sendo cometidos
repetidamente. Se você receber uma revisão que pareça irritada, insultuosa
ou abertamente ofensiva, resista ao impulso de responder à altura. A revisão
de código diz respeito ao código, não às pessoas, e os revisores de código
não estão atacando você pessoalmente.
* Da mesma forma, os revisores de código não estão tentando promover os
interesses de seus empregadores em detrimento dos seus. Os desenvolvedores
do kernel geralmente esperam continuar trabalhando no kernel daqui a muitos
anos, mas entendem que seu empregador pode mudar. Quase sem exceção, eles
estão verdadeiramente trabalhando em prol da criação do melhor kernel possível;
eles não estão tentando causar desconforto aos concorrentes de seus empregadores.
* Esteja preparado para solicitações aparentemente tolas de mudanças no estilo
de codificação e pedidos para refatorar parte do seu código em seções
compartilhadas do kernel. Uma das funções dos mantenedores é manter as coisas
com a mesma aparência. Às vezes, isso significa que aquele truque inteligente
(*clever hack*) em seu driver para contornar um problema
Note que você não precisa concordar com todas as mudanças sugeridas pelos
revisores. Se você acredita que o revisor entendeu mal o seu código, explique
o que realmente está acontecendo. Se tiver uma objeção técnica a uma mudança
sugerida, descreva-a e justifique a sua solução para o problema. Se as suas
explicações fizerem sentido, o revisor as aceitará. Contudo, caso a sua
explicação não seja persuasiva — especialmente se outros começarem a concordar
com o revisor —, reserve um tempo para repensar as coisas. Pode ser fácil ficar
ceguificado por sua própria solução para um problema, a ponto de não perceber
que algo está fundamentalmente errado ou que, talvez, você não esteja sequer
resolvendo o problema certo.
Andrew Morton sugeriu que todo comentário de revisão que não resulte em uma
alteração de código deveria, em vez disso, resultar em um comentário adicional
no próprio código; isso pode ajudar os futuros revisores a evitar as dúvidas
que surgiram da primeira vez.
Um erro fatal é ignorar os comentários de revisão na esperança de que eles
desapareçam. Eles não vão desaparecer. Se você reenviar o código sem ter
respondido aos comentários que recebeu da vez anterior, é provável que descubra
que os seus patches não vão a lugar nenhum.
Por falar em reenviar código: tenha em mente que os revisores não vão se
lembrar de todos os detalhes do código que você enviou da última vez. Portanto,
é sempre uma boa ideia lembrar os revisores dos problemas levantados
anteriormente e de como você lidou com eles; o registro de alterações
(*changelog*) do patch é um bom lugar para esse tipo de informação. Os revisores
não deveriam ter que vasculhar os arquivos das listas de discussão para se
familiarizarem com o que foi dito na última vez; se você ajudá-los a começar
com o pé direito, eles estarão de melhor humor quando revisitarem o seu código.
E se você tentou fazer tudo certo e as coisas ainda não estão avançando? A
maioria das divergências técnicas pode ser resolvida por meio de discussão,
mas há momentos em que alguém simplesmente precisa tomar uma decisão. Se você
acredita genuinamente que essa decisão está indo contra você de forma errada,
você sempre pode tentar recorrer a uma instância superior. Até o momento em
que este texto foi escrito, essa instância superior costuma ser Andrew Morton.
Andrew goza de um enorme respeito na comunidade de desenvolvimento do kernel;
ele frequentemente consegue destravar uma situação que parece desesperadoramente
bloqueada. Recorrer a Andrew, no entanto, não deve ser feito de ânimo leve e nem
antes que todas as outras alternativas tenham sido esgotadas. E tenha em mente,
é claro, que ele também pode não concordar com você.
O que acontece a seguir
-----------------------
Se um patch for considerado algo bom para ser adicionado ao kernel, e assim
que a maioria dos problemas de revisão tiver sido resolvida, o próximo passo
geralmente é a entrada na árvore de um mantenedor de subsistema. Como isso
funciona varia de um subsistema para o outro; cada mantenedor tem sua própria
maneira de fazer as coisas. Em particular, pode haver mais de uma árvore — uma,
talvez, dedicada a patches planejados para a próxima janela de mesclagem
(*merge window*), e outra para trabalhos de longo prazo.
Para patches que se aplicam a áreas para quais não há uma árvore de subsistema
óbvia (patches de gerenciamento de memória, por exemplo), a árvore padrão
geralmente acaba sendo a *-mm*. Patches que afetam múltiplos subsistemas
também podem acabar passando pela árvore *-mm*.
A inclusão em uma árvore de subsistema pode trazer um nível mais alto de
visibilidade para um patch. Agora, outros desenvolvedores que trabalham com
aquela árvore receberão o patch por padrão. As árvores de subsistemas tipicamente
alimentam a *linux-next* também, tornando seus conteúdos visíveis para a
comunidade de desenvolvimento como um todo. Neste ponto, há uma boa chance de
você receber mais comentários de um novo conjunto de revisores; esses
comentários precisam ser respondidos da mesma forma que na rodada anterior.
O que também pode acontecer neste ponto, dependendo da natureza do seu patch,
é surgirem conflitos com o trabalho que está sendo feito por outros. No pior
dos casos, conflitos pesados de patches podem fazer com que alguns trabalhos
sejam deixados em segundo plano, para que os patches restantes possam ser
ajustados e mesclados. Outras vezes, a resolução de conflitos envolverá trabalhar
junto a outros desenvolvedores e, possivelmente, mover alguns patches entre
árvores para garantir que tudo se aplique de forma limpa. Este trabalho pode ser
árduo, mas console-se com uma vantagem: antes do surgimento da árvore *linux-next*,
esses conflitos frequentemente só apareciam durante a janela de mesclagem e
tinham que ser resolvidos às pressas. Agora eles podem ser resolvidos com calma,
antes que a janela de mesclagem se abra.
Um belo dia, se tudo correr bem, você fará login e verá que o seu patch foi
mesclado ao kernel principal (*mainline*). Parabéns! No entanto, assim que a
comemoração terminar (e você tiver se adicionado ao arquivo MAINTAINERS), vale
a pena lembrar de um pequeno fato importante: o trabalho ainda não acabou. A
mesclagem na árvore principal traz os seus próprios desafios.
Para começar, a visibilidade do seu patch aumentou ainda mais. Pode haver
uma nova rodada de comentários de desenvolvedores que não estavam cientes do
patch antes. Pode ser tentador ignorá-los, já que não há mais nenhuma dúvida
sobre a mesclagem do seu código. No entanto, resista a essa tentação; você
ainda precisa ser receptivo aos desenvolvedores que tiverem dúvidas ou
sugestões.
Mais importante ainda: a inclusão na árvore principal coloca o seu código
nas mãos de um grupo muito maior de testadores. Mesmo que você tenha contribuído
com um driver para um hardware que ainda não está disponível, você se
surpreenderá com a quantidade de pessoas que compilarão seu código em seus
próprios kernels. E, logicamente, onde há testadores, haverá relatórios de
erros (*bug reports*).
O pior tipo de relatório de erro são as regressões (*regressions*). Se o seu
patch causar uma regressão, você descobrirá uma quantidade desconfortável de
olhos voltados para você; as regressões precisam ser corrigidas o mais rápido
possível. Se você não estiver disposto ou for incapaz de corrigir a regressão
(e ninguém mais fizer isso por você), seu patch quase certamente será removido
durante o período de estabilização. Além de anular todo o trabalho que você teve
para colocar seu patch na árvore principal, ter um patch removido como resultado
da falha em corrigir uma regressão pode muito bem tornar mais difícil para você
mesclar trabalhos no futuro.
Depois que todas as regressões tiverem sido tratadas, pode haver outros erros
comuns com os quais lidar. O período de estabilização é a sua melhor oportunidade
para corrigir esses problemas e garantir que a estreia do seu código em um
lançamento do kernel principal seja o mais sólida possível. Portanto, por favor,
responda aos relatórios de erros e corrija os problemas, se for viável. É para
isso que serve o período de estabilização; você pode começar a criar novos
patches fantásticos assim que quaisquer problemas com os antigos tiverem sido
resolvidos.
E não se esqueça de que existem outros marcos que também podem gerar relatórios
de erros: o próximo lançamento estável da árvore principal, o momento em que
distribuidores proeminentes adotarem uma versão do kernel que contenha o seu
patch, etc. Continuar respondendo a esses relatórios é uma questão de orgulho
básico pelo seu trabalho. Se isso não for motivação suficiente, contudo, também
vale a pena considerar que a comunidade de desenvolvimento se lembra dos
desenvolvedores que perdem o interesse em seu próprio código após a mesclagem.
A próxima vez que você enviar um patch, eles o avaliarão sob a suposição de
que você não estará por perto para mantê-lo depois.
Outras coisas que podem acontecer
---------------------------------
Um dia, você poderá abrir o seu cliente de e-mail e ver que alguém lhe enviou
um patch para o seu código. Afinal, essa é uma das vantagens de ter o seu
código disponível publicamente. Se você concordar com o patch, poderá encaminhá-lo
para o mantenedor do subsistema (certifique-se de incluir uma linha ``From:``
adequada para que a atribuição de autoria esteja correta e adicione a sua
própria assinatura — *signoff*) ou enviar uma resposta com um ``Acked-by:``
e deixar que o remetente original o envie para cima.
Se você não concordar com o patch, envie uma resposta educada explicando o
motivo. Se possível, diga ao autor quais alterações precisam ser feitas para
que o patch seja aceitável para você. Existe uma certa resistência em mesclar
patches que sofrem oposição do autor e mantenedor do código, mas isso tem limite.
Se você for visto como alguém que está bloqueando um bom trabalho sem necessidade,
esses patches eventualmente seguirão outro fluxo ao seu redor e entrarão na
árvore principal de qualquer maneira. No kernel do Linux, ninguém tem poder de
veto absoluto sobre nenhum código. Exceto, talvez, o Linus.
Em ocasiões muito raras, você poderá ver algo completamente diferente: outro
desenvolvedor envia uma solução diferente para o seu problema. Nesse ponto,
as chances são de que um dos dois patches não seja mesclado, e o argumento
"o meu chegou primeiro" não é considerado um argumento técnico convincente.
Se o patch de outra pessoa deslocar o seu e entrar na árvore principal, existe
realmente apenas uma maneira de responder: fique satisfeito pelo fato de o seu
problema ter sido resolvido e siga adiante com o seu trabalho. Ter o próprio
trabalho deixado de lado dessa maneira pode ser doloroso e desanimador, mas a
comunidade se lembrará da sua reação muito depois de terem esquecido de quem
foi o patch que realmente foi mesclado.

View File

@@ -0,0 +1,201 @@
.. SPDX-License-Identifier: GPL-2.0
Tópicos avançados
=================
Neste ponto, esperamos que você já tenha uma boa noção de como funciona o
processo de desenvolvimento. No entanto, ainda há mais a aprender! Esta seção
cobrirá uma série de tópicos que podem ser úteis para desenvolvedores que
desejam se tornar parte regular do processo de desenvolvimento do kernel Linux.
Gerenciamento de patches com o git
----------------------------------
O uso de controle de versão distribuído para o kernel começou no início de
2002, quando Linus começou a testar o aplicativo proprietário BitKeeper.
Embora o BitKeeper fosse controverso, a abordagem de gerenciamento de versão
de software que ele incorporava certamente não era. O controle de versão
distribuído permitiu uma aceleração imediata do projeto de desenvolvimento do
kernel. Atualmente, existem várias alternativas gratuitas ao BitKeeper. Para o
bem ou para o mal, o projeto do kernel adotou o git como sua ferramenta de
escolha.
Gerenciar patches com o git pode facilitar muito a vida do desenvolvedor,
especialmente à medida que o volume desses patches cresce. O git também tem suas
pontas soltas e apresenta certos riscos; é uma ferramenta jovem e poderosa que
ainda está sendo refinada por seus desenvolvedores. Este documento não tentará
ensinar o leitor a usar o git; isso seria material suficiente para um documento
longo por si só. Em vez disso, o foco aqui será em como o git se encaixa
especificamente no processo de desenvolvimento do kernel. Os desenvolvedores
que desejam se atualizar com o git encontrarão mais informações em:
https://git-scm.com/
https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
e em vários tutoriais encontrados na web.
A primeira ordem do dia é ler os sites acima e obter uma compreensão sólida de
como o git funciona antes de tentar usá-lo para disponibilizar patches para
outros. Um desenvolvedor que utiliza o git deve ser capaz de obter uma cópia do
repositório principal, explorar o histórico de revisões, comitar alterações na
árvore, usar branches, etc. A compreensão das ferramentas do git para a
reescrita de histórico (como o rebase) também é útil. O git vem com sua própria
terminologia e conceitos; um novo usuário do git deve saber sobre refs, remote
branches, o index, fast-forward merges, pushes e pulls, detached HEADs, etc.
Tudo isso pode ser um pouco intimidante no início, mas os conceitos não são tão
difíceis de entender com um pouco de estudo.
Usar o git para gerar patches para submissão por e-mail pode ser um bom exercício
enquanto você se atualiza.
Quando estiver pronto para começar a disponibilizar árvores git para que outros
possam examinar, você, logicamente, precisará de um servidor a partir do qual um
pull possa ser feito. Configurar um servidor desse tipo com o git-daemon é
relativamente simples se você tiver um sistema acessível à internet. Caso
contrário, sites de hospedagem públicos e gratuitos (o GitHub, por exemplo)
estão começando a surgir na rede. Desenvolvedores estabelecidos podem obter uma
conta no kernel.org, mas estas não são fáceis de conseguir; consulte
https://kernel.org/faq/ para mais informações.
O fluxo de trabalho normal do git envolve o uso de muitas branches. Cada linha
de desenvolvimento pode ser separada em uma "topic branch" distinta e mantida de
forma independente. Branches no git são baratas, não há razão para não fazer um
uso livre delas. E, em qualquer caso, você não deve fazer o seu desenvolvimento
em nenhuma branch a partir da qual pretenda pedir para que outros deem pull.
Branches disponíveis publicamente devem ser criadas com cuidado; mescle patches
de branches de desenvolvimento quando eles estiverem em sua forma final e prontos
para seguir em frente — não antes.
O git fornece algumas ferramentas poderosas que podem permitir que você
reescreva o seu histórico de desenvolvimento. Um patch inconveniente (um que
quebre o bisection, por exemplo, ou que tenha algum outro tipo de bug óbvio)
pode ser corrigido localmente ou feito desaparecer completamente do histórico.
Uma série de patches pode ser reescrita como se tivesse sido escrita no topo da
linha principal de hoje, mesmo que você esteja trabalhando nela há meses. As
alterações podem ser movidas de forma transparente de uma branch para outra. E
assim por diante. O uso criterioso da capacidade do git de revisar o histórico
pode ajudar na criação de conjuntos de patches limpos e com menos problemas.
O uso excessivo dessa capacidade pode levar a outros problemas, no entanto, além
de uma simples obsessão pela criação do histórico de projeto perfeito. Reescrever
o histórico reescreverá as alterações contidas nele, transformando uma árvore do
kernel testada (assim se espera) em uma não testada. Mas, além disso, os
desenvolvedores não podem colaborar facilmente se não tiverem uma visão
compartilhada do histórico do projeto; se você reescrever o histórico que outros
desenvolvedores já deram pull em seus repositórios, tornará a vida deles muito
mais difícil. Portanto, uma regra prática simples se aplica aqui: o histórico
que foi exportado para terceiros deve ser visto geralmente como imutável dali em
diante.
Sendo assim, uma vez que você faz o push de um conjunto de alterações para o seu
servidor disponível publicamente, essas alterações não devem ser reescritas. O
git tentará aplicar essa regra se você tentar dar push em alterações que não
resultem em um fast-forward merge (ou seja, alterações que não compartilham o
mesmo histórico). É possível anular essa verificação, e pode haver momentos em
que seja necessário reescrever uma árvore exportada. Mover changesets entre
árvores para evitar conflitos na linux-next é um exemplo. No entanto, tais ações
devem ser raras. Esta é uma das razões pelas quais o desenvolvimento deve ser
feito em branches privadas (que podem ser reescritas, se necessário) e apenas
movido para branches públicas quando estiver em um estado razoavelmente avançado.
À medida que a linha principal (ou outra árvore na qual um conjunto de
alterações se baseia) avança, é tentador fazer o merge com essa árvore para
permanecer na vanguarda. Para uma branch privada, o rebasing pode ser uma maneira
fácil de acompanhar outra árvore, mas o rebasing não é uma opção uma vez que uma
árvore é exportada para o mundo. Quando isso acontece, um merge completo deve
ser feito. Fazer merges ocasionalmente faz todo o sentido, mas merges excessivamente
frequentes podem poluir o histórico desnecessariamente. A técnica sugerida neste
caso é fazer merges raramente, e geralmente apenas em release points específicos
(como um lançamento -rc da linha principal). Se você estiver inseguro sobre
mudanças específicas, sempre poderá realizar merges de teste em uma branch
privada. A ferramenta "rerere" do git pode ser útil nessas situações; ela se
lembra de como os conflitos de merge foram resolvidos para que você não precise
fazer o mesmo trabalho duas vezes.
Uma das maiores reclamações recorrentes sobre ferramentas como o git é esta: o
movimento em massa de patches de um repositório para outro torna fácil a
inclusão de mudanças desaconselháveis que entram na linha principal abaixo do
radar de revisão. Os desenvolvedores do kernel costumam ficar descontentes quando
veem esse tipo de coisa acontecer; disponibilizar uma árvore git com patches não
revisados ou fora do tópico pode afetar a sua capacidade de ter suas árvores
puxadas no futuro. Citando Linus:
::
Você pode me enviar patches, mas para eu puxar um patch git de você, eu
preciso saber que você sabe o que está fazendo, e preciso ser capaz de
confiar nas coisas *sem* ter que ir lá e verificar cada mudança
individualmente à mão.
(https://lwn.net/Articles/224135/).
Para evitar esse tipo de situação, certifique-se de que todos os patches
dentro de uma determinada branch permaneçam estritamente alinhados ao tópico
associado; uma branch de "correções de drivers" não deveria fazer alterações no
código central de gerenciamento de memória. E, acima de tudo, não use uma árvore
git para burlar o processo de revisão. Publique ocasionalmente um resumo da
árvore na lista de discussão relevante e, quando for o momento certo, solicite
que a árvore seja incluída na linux-next.
Se e quando outros começarem a enviar patches para inclusão em sua árvore, não
se esqueça de revisá-los. Certifique-se também de manter as informações corretas
de autoria; a ferramenta "am" do git faz o melhor que pode a esse respeito, mas
você pode ter que adicionar uma linha "From:" ao patch se ele tiver sido
retransmitido a você por terceiros.
Ao solicitar um pull, certifique-se de fornecer todas as informações
relevantes: onde está a sua árvore, qual branch deve ser puxada e quais
alterações resultarão do pull. O comando git request-pull pode ser útil a esse
respeito; ele formatará a solicitação da maneira que outros desenvolvedores
esperam e também verificará se você se lembrou de dar push nessas alterações
para o servidor público.
Revisão de patches
------------------
Alguns leitores certamente objetarão a inclusão desta seção em "tópicos
avançados" sob o argumento de que mesmo desenvolvedores iniciantes do kernel
deveriam estar revisando patches. É certamente verdade que não há melhor maneira
de aprender a programar no ambiente do kernel do que examinando o código
postado por outros. Além disso, revisores estão sempre em falta; ao examinar o
código, você pode fazer uma contribuição significativa para o processo como um
todo.
Revisar código pode ser uma perspectiva intimidadora, especialmente para um novo
desenvolvedor do kernel que pode se sentir nervoso em questionar — em público —
um código que foi postado por aqueles com mais experiência. No entanto, mesmo o
código escrito pelos desenvolvedores mais experientes pode ser aprimorado. Talvez
o melhor conselho para revisores (todos os revisores) seja este: formule os
comentários de revisão como perguntas em vez de críticas. Perguntar "como o lock
é liberado neste caminho?" sempre funcionará melhor do que afirmar "o bloqueio
aqui está errado."
Outra técnica útil em caso de desacordo é pedir que outros se manifestem. Se uma
discussão chegar a um impasse após algumas trocas de mensagens, peça a opinião
de outros revisores ou mantenedores. Frequentemente, aqueles que concordam com
um revisor permanecem em silêncio, a menos que sejam solicitados. A opinião de
múltiplas pessoas carrega exponencialmente mais peso.
Diferentes desenvolvedores revisarão o código sob diferentes pontos de vista.
Alguns estão preocupados principalmente com o estilo de codificação e se as
linhas de código possuem espaços em branco no final (trailing white space).
Outros se concentrarão principalmente em saber se a alteração implementada pelo
patch como um todo é algo bom para o kernel ou não. Ainda assim, outros buscarão
por bloqueios problemáticos, uso excessivo de pilha (stack usage), possíveis
problemas de segurança, duplicação de código encontrado em outros lugares,
documentação adequada, efeitos adversos no desempenho, alterações na ABI do
espaço do usuário (user-space ABI), etc. Todos os tipos de revisão, se levarem a
um código melhor entrando no kernel, são bem-vindos e valem a pena.
Não há exigência estrita para o uso de tags específicas como ``Reviewed-by``. Na
verdade, revisões em texto simples são mais informativas e incentivadas mesmo
quando uma tag é fornecida, por exemplo: "Analisei os aspectos A, B e C deste
envio e tudo me parece correto." Alguma forma de mensagem de revisão ou resposta
é obviamente necessária, caso contrário, os mantenedores não saberão que o
revisor sequer examinou o patch!
Por último, mas não menos importante, a revisão de patches pode se tornar um
processo negativo, focado em apontar problemas. Por favor, reserve um elogio de
vez em quando, particularmente para os novatos!

View File

@@ -0,0 +1,73 @@
.. SPDX-License-Identifier: GPL-2.0
Para mais informações
=====================
Há inúmeras fontes de informação sobre o desenvolvimento do kernel Linux e
tópicos relacionados. A primeira delas sempre será o diretório Documentation
encontrado na distribuição do código-fonte do kernel. Comece com o arquivo de
nível superior :ref:`process/howto.rst <process_howto>`; leia também
:ref:`process/submitting-patches.rst <submittingpatches>`. Muitas APIs internas
do kernel são documentadas usando o mecanismo kerneldoc; "make htmldocs" ou
"make pdfdocs" podem ser usados para gerar esses documentos em formato HTML ou
PDF (embora a versão do TeX fornecida por algumas distribuições esbarre em
limites internos e falhe em processar os documentos corretamente).
Vários sites discutem o desenvolvimento do kernel em todos os níveis de
detalhes. O autor gostaria de sugerir humildemente o https://lwn.net/ como uma
fonte; informações sobre muitos tópicos específicos do kernel podem ser
encontradas através do índice do kernel do LWN em:
https://lwn.net/Kernel/Index/
Além disso, um recurso valioso para os desenvolvedores do kernel é:
https://kernelnewbies.org/
E, claro, não se deve esquecer o https://kernel.org/, o local definitivo
para informações sobre os lançamentos do kernel.
Há uma série de livros sobre o desenvolvimento do kernel:
Linux Device Drivers, 3rd Edition (Jonathan Corbet, Alessandro
Rubini, and Greg Kroah-Hartman). Online at
https://lwn.net/Kernel/LDD3/.
Linux Kernel Development (Robert Love).
Understanding the Linux Kernel (Daniel Bovet and Marco Cesati).
Todos esses livros, no entanto, sofrem de um defeito comum: eles tendem a estar
um pouco obsoletos quando chegam às prateleiras, e já estão nelas há algum
tempo. Ainda assim, há uma boa quantidade de informações úteis a serem
encontradas ali.
A documentação para o git pode ser encontrada em:
https://www.kernel.org/pub/software/scm/git/docs/
https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
Conclusão
=========
Parabéns a qualquer pessoa que tenha chegado ao fim deste documento longo e
detalhado. Esperamos que ele tenha fornecido uma compreensão útil de como o
kernel Linux é desenvolvido e de como você pode participar desse processo.
No fim das contas, é a participação que importa. Qualquer projeto de software
de código aberto não é nada mais do que a soma do que seus colaboradores
dedicam a ele. O kernel Linux progrediu tão rápido e tão bem porque foi ajudado
por um grupo impressionantemente grande de desenvolvedores, todos trabalhando
para torná-lo melhor. O kernel é um exemplo primordial do que pode ser feito
quando milhares de pessoas trabalham juntas em direção a um objetivo comum.
O kernel, no entanto, sempre pode se beneficiar de uma base maior de
desenvolvedores. Há sempre mais trabalho a fazer. Mas, de forma igualmente
importante, a maioria dos outros participantes do ecossistema Linux pode se
beneficiar ao contribuir para o kernel. Colocar o código na linha principal
(mainline) é a chave para uma maior qualidade de código, menores custos de
manutenção e distribuição, um nível mais alto de influência sobre a direção do
desenvolvimento do kernel e muito mais. É uma situação em que todos os
envolvidos ganham. Abra o seu editor e venha se juntar a nós; você será mais do
que bem-vindo.

View File

@@ -0,0 +1,700 @@
.. SPDX-License-Identifier: GPL-2.0
=======================================
Adicionando uma Nova Chamada de Sistema
=======================================
Este documento descreve o que está envolvido na adição de uma nova chamada de
sistema (system call) ao kernel Linux, indo além dos conselhos normais de
submissão em
:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`.
Alternativas às Chamadas de Sistema
-----------------------------------
A primeira coisa a se considerar ao adicionar uma nova chamada de sistema é se
uma das alternativas poderia ser mais adequada. Embora as chamadas de sistema
sejam os pontos de interação mais tradicionais e óbvios entre o espaço do
usuário (userspace) e o kernel, existem outras possibilidades -- escolha o que
melhor se adapta à sua interface.
- Se as operações envolvidas puderem ser moldadas para se parecerem com um
objeto do tipo arquivo, pode fazer mais sentido criar um novo sistema de
arquivos ou dispositivo. Isso também torna mais fácil encapsular a nova
funcionalidade em um módulo de kernel, em vez de exigir que ela seja
incorporada ao kernel principal.
- Se a nova funcionalidade envolver operações em que o kernel notifica o
espaço do usuário de que algo aconteceu, retornar um novo descritor de
arquivo (file descriptor) para o objeto relevante permite que o espaço
do usuário use ``poll``/``select``/``epoll`` para receber essa
notificação.
- No entanto, as operações que não se mapeiam para operações do tipo
:manpage:`read(2)`/:manpage:`write(2)` precisam ser implementadas como
requisições :manpage:`ioctl(2)`, o que pode levar a uma API um tanto
quanto opaca.
- Se você estiver apenas expondo informações do sistema em tempo de execução,
um novo nó no sysfs (veja ``Documentation/filesystems/sysfs.rst``) ou no
sistema de arquivos ``/proc`` pode ser mais apropriado. No entanto, o acesso
a esses mecanismos exige que o sistema de arquivos relevante esteja montado,
o que pode não ser sempre o caso (por exemplo, em um ambiente com namespaces,
sandboxed ou chrooted). Evite adicionar qualquer API ao debugfs, pois este
não é considerado uma interface de "produção" para o espaço do usuário.
- Se a operação for específica para um arquivo ou descritor de arquivo de um
determinado objeto, então uma opção de comando adicional para :manpage:`fcntl(2)`
pode ser mais adequada. Contudo, o :manpage:`fcntl(2)` é uma chamada de sistema
de multiplexação que oculta muita complexidade, portanto, esta opção é melhor
para quando a nova função for intimamente análoga à funcionalidade existente
do :manpage:`fcntl(2)`, ou se a nova funcionalidade for muito simples (por
exemplo, obter/definir uma flag simples relacionada a um descritor de arquivo).
- Se a operação for específica para uma tarefa (task) ou processo específico,
então uma opção de comando adicional para :manpage:`prctl(2)` pode ser mais
apropriada. Assim como no caso do :manpage:`fcntl(2)`, esta chamada de sistema
é um multiplexador complicado, sendo melhor reservá-la para análogos próximos
de comandos ``prctl()`` existentes ou para obter/definir uma flag simples
relacionada a um processo.
Projetando a API: Planejando a Extensibilidade
----------------------------------------------
Uma nova chamada de sistema faz parte da API do kernel e deve ser suportada
indefinidamente. Sendo assim, é uma excelente ideia discutir explicitamente a
interface na lista de discussão do kernel (LKML), e é crucial planejar extensões
futuras para essa interface.
(A tabela de chamadas de sistema está repleta de exemplos históricos onde isso
não foi feito, juntamente com as respectivas chamadas de sistema de acompanhamento
-- ``eventfd``/``eventfd2``, ``dup2``/``dup3``, ``inotify_init``/``inotify_init1``,
``pipe``/``pipe2``, ``renameat``/``renameat2`` -- portanto, aprenda com a história
do kernel e planeje as extensões desde o início.)
Para chamadas de sistema mais simples que recebem apenas alguns argumentos, a
maneira preferencial de permitir extensibilidade futura é incluir um argumento de
flags na chamada de sistema. Para garantir que os programas do espaço do usuário
possam usar flags de forma segura entre diferentes versões do kernel, verifique
se o valor de flags contém qualquer flag desconhecida e rejeite a chamada de
sistema (com ``EINVAL``) se contiver::
if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3))
return -EINVAL;
(Se nenhum valor de flag for utilizado ainda, verifique se o argumento de flags
é zero.)
Para chamadas de sistema mais sofisticadas que envolvem um número maior de
argumentos, prefere-se encapsular a maioria dos argumentos em uma estrutura
(struct) que é passada por meio de um ponteiro. Esse tipo de estrutura pode
lidar com extensões futuras incluindo um argumento de tamanho (size) na própria
estrutura::
struct xyzzy_params {
u32 size; /* o espaço do usuário define p->size = sizeof(struct xyzzy_params) */
u32 param_1;
u64 param_2;
u64 param_3;
};
Desde que qualquer campo adicionado subsequentemente, digamos ``param_4``, seja
projetado de forma que um valor zero mantenha o comportamento anterior, isso
permitirá lidar com a divergência de versões em ambas as direções:
- Para lidar com um programa de espaço do usuário mais novo chamando um kernel
mais antigo, o código do kernel deve verificar se qualquer memória além do
tamanho da estrutura que ele espera está zerada (efetivamente verificando
se ``param_4 == 0``).
- Para lidar com um programa de espaço do usuário mais antigo chamando um kernel
mais novo, o código do kernel pode preencher com zero (zero-extend) a
instância menor da estrutura (efetivamente definindo ``param_4 = 0``).
Veja :manpage:`perf_event_open(2)` e a função ``perf_copy_attr()`` (em
``kernel/events/core.c``) para um exemplo desta abordagem.
Projetando a API: Outras Considerações
--------------------------------------
Se a sua nova chamada de sistema permitir que o espaço do usuário se refira a
um objeto do kernel, ela deve usar um descritor de arquivo (file descriptor)
como o handle (identificador) para esse objeto -- não invente um novo tipo de
handle de objeto para o espaço do usuário quando o kernel já possui mecanismos
e semânticas bem definidas para o uso de descritores de arquivo.
Se a sua nova chamada de sistema (2) de fato retornar un novo descritor de
arquivo, então o argumento de flags deve incluir um valor que seja equivalente
a definir ``O_CLOEXEC`` no novo FD. Isso torna possível para o espaço do usuário
fechar a janela de tempo entre a chamada ``()`` e a execução de
``fcntl(fd, F_SETFD, FD_CLOEXEC)``, onde um ``fork()`` e ``execve()`` inesperados
em outra thread poderiam vazar um descritor para o programa executado. (Contudo,
resista à tentação de reutilizar o valor real da constante ``O_CLOEXEC``, pois
ela é específica de cada arquitetura e faz parte de um espaço de numeração de
flags ``O_*`` que está bastante cheio.)
Se a sua chamada de sistema retornar um novo descritor de arquivo, você também
deve considerar o que significa usar a família de chamadas de sistema
:manpage:`poll(2)` nesse descritor de arquivo. Tornar um descritor de arquivo
pronto para leitura ou escrita é a maneira normal de o kernel indicar ao espaço
do usuário que um evento ocorreu no objeto correspondente do kernel.
Se a sua nova chamada de sistema (2) envolver um argumento de nome de arquivo
(filename)::
int sys_xyzzy(const char __user *path, ..., unsigned int flags);
você também deve considerar se uma versão xyzzyat(2) seria mais apropriada::
int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags);
Isso permite maior flexibilidade para a forma como o espaço do usuário especifica
o arquivo em questão; em particular, permite que o espaço do usuário solicite a
funcionalidade para um descritor de arquivo já aberto usando a flag
``AT_EMPTY_PATH``, fornecendo efetivamente uma operação fxyzzy(3) de graça::
- xyzzyat(AT_FDCWD, path, ..., 0) é equivalente a (path,...)
- xyzzyat(fd, "", ..., AT_EMPTY_PATH) é equivalente a fxyzzy(fd, ...)
(Para mais detalhes sobre a justificativa das chamadas \*at(), veja a página de
manual :manpage:`openat(2)`; para um exemplo de AT_EMPTY_PATH, veja a página de
manual :manpage:`fstatat(2)`.)
Se a sua nova chamada de sistema (2) envolver um parâmetro que descreve um
deslocamento (offset) dentro de um arquivo, mude o seu tipo para ``loff_t`` para
que offsets de 64 bits possam ser suportados mesmo em arquiteturas de 32 bits.
Se a sua nova chamada de sistema (2) envolver funcionalidades privilegiadas,
ela precisa ser governada pelo bit de capacidade (capability) do Linux apropriado
(verificado com uma chamada a ``capable()``), conforme descrito na página de
manual :manpage:`capabilities(7)`. Escolha um bit de capacidade existente que governe
funcionalidades relacionadas, mas tente evitar combinar muitas funções que tenham
apenas uma vaga relação sob o mesmo bit, pois isso vai contra o propósito das
capabilities de dividir o poder do root. Em particular, evite adicionar novos
usos para a capacidade ``CAP_SYS_ADMIN``, que já é excessivamente generalista.
Se a sua nova chamada de sistema (2) manipular um processo diferente do
processo que a chamou, ela deve ser restrita (usando uma chamada a
``ptrace_may_access()``) para que apenas um processo chamador com as mesmas
permissões do processo alvo, ou com as capacidades necessárias, possa manipular
o processo alvo.
Finalmente, esteja ciente de que algumas arquiteturas não-x86 lidam melhor se os
parâmetros da chamada de sistema que são explicitamente de 64 bits caírem em
argumentos de numeração ímpar (ou seja, parâmetro 1, 3, 5), para permitir o uso
de pares contíguos de registradores de 32 bits. (Esta preocupação não se aplica
se os argumentos fizerem parte de uma estrutura que é passada por meio de um
ponteiro.)
Propondo a API
--------------
Para tornar as novas chamadas de sistema fáceis de revisar, é melhor dividir o
conjunto de patches (patchset) em blocos separados. Estes devem incluir, pelo
menos, os seguintes itens como commits distintos (cada um dos quais é descrito
mais adiante):
- A implementação central da chamada de sistema, juntamente com protótipos,
numeração genérica, alterações no Kconfig e a implementação de stub de realinhamento (fallback stub).
- A fiação (wiring up) da nova chamada de sistema para uma arquitetura em
particular, geralmente x86 (incluindo todas as variantes x86_64, x86_32 e x32).
- Uma demonstração do uso da nova chamada de sistema no espaço do usuário por
meio de um selftest em ``tools/testing/selftests/``.
- Um rascunho da página de manual (man-page) para a nova chamada de sistema,
seja como texto simples na carta de apresentação (cover letter) ou como um
patch para o repositório (separado) de man-pages.
Novas propostas de chamadas de sistema, como qualquer alteração na API do
kernel, devem sempre ser enviadas com cópia (cc'ed) para linux-api@vger.kernel.org.
Implementação Genérica de Chamadas de Sistema
---------------------------------------------
O ponto de entrada principal para a sua nova chamada de sistema (2) será chamado
de ``sys_xyzzy()``, mas você deve adicionar esse ponto de entrada com a macro
``SYSCALL_DEFINEn()`` apropriada, em vez de fazer isso explicitamente. O 'n'
indica o número de argumentos da chamada de sistema, e a macro recebe o nome da
chamada de sistema seguido pelos pares (tipo, nome) para os parâmetros como
argumentos. O uso dessa macro permite que os metadados sobre a nova chamada de
sistema fiquem disponíveis para outras ferramentas.
O novo ponto de entrada também precisa de um protótipo de função correspondente
em ``include/linux/syscalls.h``, marcado como asmlinkage para corresponder à
maneira como as chamadas de sistema são invocadas::
asmlinkage long sys_xyzzy(...);
Algumas arquiteturas (por exemplo, x86) possuem suas próprias tabelas de syscall
específicas da arquitetura, mas várias outras arquiteturas compartilham uma tabela
de syscall genérica. Adicione a sua nova chamada de sistema à lista genérica
adicionando uma entrada na lista em ``include/uapi/asm-generic/unistd.h``::
#define __NR_xyzzy 292
__SYSCALL(__NR_xyzzy, sys_xyzzy)
Atualize também a contagem de __NR_syscalls para refletir a chamada de sistema
adicional, e observe que se múltiplas novas chamadas de sistema forem adicionadas
na mesma janela de mesclagem (merge window), o número da sua nova syscall poderá
ser ajustado para resolver conflitos.
O arquivo ``kernel/sys_ni.c`` fornece uma implementação de stub de fallback para
cada chamada de sistema, retornando ``-ENOSYS``. Adicione a sua nova chamada de
sistema aqui também::
COND_SYSCALL(sys_xyzzy);
A sua nova funcionalidade de kernel, e a chamada de sistema que a controla, deve
normalmente ser opcional, portanto adicione uma opção ``CONFIG`` (tipicamente em
``init/Kconfig``) para ela. Como de costume para novas opções ``CONFIG``:
- Inclua uma descrição da nova funcionalidade e da chamada de sistema controlada
pela opção.
- Faça a opção depender de EXPERT se ela deve ser ocultada dos usuários normais.
- Faça com que quaisquer novos arquivos de código-fonte que implementem a função
sejam dependentes da opção CONFIG no Makefile (por exemplo,
``obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.o``).
- Verifique duas vezes se o kernel ainda compila com a nova opção CONFIG desativada.
Para resumir, você precisa de um commit que inclua:
- Opção ``CONFIG`` para a nova função, normalmente em ``init/Kconfig``
- ``SYSCALL_DEFINEn(, ...)`` para o ponto de entrada
- Protótipo correspondente em ``include/linux/syscalls.h``
- Entrada na tabela genérica em ``include/uapi/asm-generic/unistd.h``
- Stub de fallback em ``kernel/sys_ni.c``
.. _pt_BR_syscall_generic_6_11:
Desde a versão 6.11
~~~~~~~~~~~~~~~~~~~
A partir da versão 6.11 do kernel, a implementação de chamadas de sistema
genéricas para as seguintes arquiteturas não requer mais modificações em
``include/uapi/asm-generic/unistd.h``:
- arc
- arm64
- csky
- hexagon
- loongarch
- nios2
- openrisc
- riscv
Em vez disso, você precisa atualizar ``scripts/syscall.tbl`` e, se aplicável,
ajustar ``arch/*/kernel/Makefile.syscalls``.
Como o ``scripts/syscall.tbl`` serve como uma tabela de syscall comum para
múltiplas arquiteturas, uma nova entrada é necessária nesta tabela::
468 common sys_xyzzy
Note que adicionar uma entrada ao ``scripts/syscall.tbl`` com a ABI "common"
também afeta todas as arquiteturas que compartilham essa tabela. Para alterações
mais limitadas ou específicas de uma arquitetura, considere usar uma ABI
específica da arquitetura ou definir uma nova.
Se uma nova ABI, digamos ``xyz``, for introduzida, as atualizações
correspondentes também devem ser feitas em ``arch/*/kernel/Makefile.syscalls``::
syscall_abis_{32,64} += xyz (...)
Para resumir, você precisa de um commit que inclua:
- Opção ``CONFIG`` para a nova função, normalmente em ``init/Kconfig``
- ``SYSCALL_DEFINEn(, ...)`` para o ponto de entrada
- Protótipo correspondente em ``include/linux/syscalls.h``
- Nova entrada em ``scripts/syscall.tbl``
- (Se necessário) Atualizações de Makefile em ``arch/*/kernel/Makefile.syscalls``
- Stub de fallback em ``kernel/sys_ni.c``
Implementação de Chamadas de Sistema em x86
-------------------------------------------
Para interligar (wire up) a sua nova chamada de sistema nas plataformas x86, você
precisa atualizar as tabelas mestras de syscall. Assumindo que a sua nova chamada
de sistema não seja especial de alguma forma (veja abaixo), isso envolve uma
entrada "common" (para x86_64 e x32) em
``arch/x86/entry/syscalls/syscall_64.tbl``::
333 common sys_xyzzy
e uma entrada "i386" em ``arch/x86/entry/syscalls/syscall_32.tbl``::
380 i386 sys_xyzzy
Novamente, esses números estão sujeitos a alterações caso ocorram conflitos na
janela de mesclagem (merge window) relevante.
Chamadas de Sistema de Compatibilidade (Genéricas)
--------------------------------------------------
Para a maioria das chamadas de sistema, a mesma implementação de 64 bits pode
ser invocada mesmo quando o programa do espaço do usuário é, ele próprio, de 32
bits; mesmo se os parâmetros da chamada de sistema incluírem um ponteiro
explícito, isso é tratado de forma transparente.
No entanto, existem algumas situações em que uma camada de compatibilidade
(compatibility layer) é necessária para lidar com as diferenças de tamanho entre
32 bits e 64 bits.
A primeira é se o kernel de 64 bits também suportar programas de espaço do
usuário de 32 bits e, portanto, precisar analisar áreas de memória
(``__user``) que poderiam conter valores de 32 bits ou 64 bits. Em particular,
isso é necessário sempre que um argumento de chamada de sistema for:
- um ponteiro para um ponteiro
- um ponteiro para uma struct que contém um ponteiro (por exemplo,
``struct iovec __user *``)
- um ponteiro para um tipo integral de tamanho variável (``time_t``,
``off_t``, ``long``, ...)
- um ponteiro para uma struct que contém um tipo integral de tamanho variável.
A segunda situação que requer uma camada de compatibilidade é se um dos
argumentos da chamada de sistema tiver um tipo que é explicitamente de 64 bits,
mesmo em uma arquitetura de 32 bits, por exemplo, ``loff_t`` ou ``__u64``. Neste
caso, um valor que chega ao kernel de 64 bits vindo de uma aplicação de 32 bits
será dividido em dois valores de 32 bits, que precisarão ser remontados na
camada de compatibilidade.
(Note que um argumento de chamada de sistema que seja um ponteiro para um tipo
explícito de 64 bits **não** precisa de uma camada de compatibilidade; por
exemplo, os argumentos do :manpage:`splice(2)` do tipo ``loff_t __user *`` não
disparam a necessidade de uma chamada de sistema ``compat_``.)
A versão de compatibilidade da chamada de sistema é chamada de
``compat_sys_xyzzy()`` e é adicionada com a macro ``COMPAT_SYSCALL_DEFINEn()``,
de forma análoga à macro SYSCALL_DEFINEn. Esta versão da implementação roda como
parte de um kernel de 64 bits, mas espera receber valores de parâmetros de 32
bits e faz o que for necessário para lidar com eles. (Tipicamente, a versão
``compat_sys_`` converte os valores para versões de 64 bits e chama a versão
``sys_``, ou ambas chamam uma função interna comum de implementação).
O ponto de entrada compat também precisa de um protótipo de função
correspondente em ``include/linux/compat.h``, marcado como asmlinkage para
corresponder à maneira como as chamadas de sistema são invocadas::
asmlinkage long compat_sys_xyzzy(...);
Se a chamada de sistema envolver uma estrutura cujo layout seja diferente em
sistemas de 32 bits e 64 bits, digamos ``struct xyzzy_args``, então o arquivo de
cabeçalho ``include/linux/compat.h`` também deve incluir uma versão compat da
estrutura (``struct compat_xyzzy_args``), onde cada campo de tamanho variável
tenha o tipo ``compat_`` correspondente ao tipo na ``struct xyzzy_args``. A
rotina ``compat_sys_xyzzy()`` pode então usar essa estrutura ``compat_`` para
analisar os argumentos vindos de uma invocação de 32 bits.
Por exemplo, se existirem os campos::
struct xyzzy_args {
const char __user *ptr;
__kernel_long_t varying_val;
u64 fixed_val;
/* ... */
};
na struct xyzzy_args, então a struct compat_xyzzy_args teria::
struct compat_xyzzy_args {
compat_uptr_t ptr;
compat_long_t varying_val;
u64 fixed_val;
/* ... */
};
A lista genérica de chamadas de sistema também precisa de ajustes para permitir
a versão compat; a entrada em ``include/uapi/asm-generic/unistd.h`` deve usar
``__SC_COMP`` em vez de ``__SYSCALL``::
#define __NR_xyzzy 292
__SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy)
Para resumir, você precisa de:
- uma macro ``COMPAT_SYSCALL_DEFINEn(, ...)`` para o ponto de entrada compat
- protótipo correspondente em ``include/linux/compat.h``
- (se necessário) struct de mapeamento de 32 bits em ``include/linux/compat.h``
- instância de ``__SC_COMP``, e não de ``__SYSCALL``, em
``include/uapi/asm-generic/unistd.h``
Desde a versão 6.11
~~~~~~~~~~~~~~~~~~~
Isso se aplica a todas as arquiteturas listadas em
:ref:`Desde a versão 6.11<pt_BR_syscall_generic_6_11>` sob "Implementação Genérica de
Chamadas de Sistema", exceto arm64. Veja
:ref:`Chamadas de Sistema de Compatibilidade (arm64)<pt_BR_compat_arm64>` para mais
informações.
Você precisa estender a entrada em ``scripts/syscall.tbl`` com uma coluna extra
para indicar que um programa de espaço do usuário de 32 bits rodando em um
kernel de 64 bits deve atingir o ponto de entrada compat::
468 common sys_xyzzy compat_sys_xyzzy
Para resumir, você precisa de:
- ``COMPAT_SYSCALL_DEFINEn(, ...)`` para o ponto de entrada compat
- Protótipo correspondente em ``include/linux/compat.h``
- Modificação da entrada em ``scripts/syscall.tbl`` para incluir uma coluna
"compat" extra
- (Se necessário) Struct de mapeamento de 32 bits em ``include/linux/compat.h``
.. _pt_BR_compat_arm64:
Chamadas de Sistema de Compatibilidade (arm64)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
No arm64, existe uma tabela de syscall dedicada para chamadas de sistema de
compatibilidade voltadas para o espaço do usuário de 32 bits (AArch32):
``arch/arm64/tools/syscall_32.tbl``. Você precisa adicionar uma linha adicional
a esta tabela especificando o ponto de entrada compat::
468 common sys_xyzzy compat_sys_xyzzy
Chamadas de Sistema de Compatibilidade (x86)
--------------------------------------------
Para interligar a arquitetura x86 de uma chamada de sistema com uma versão de
compatibilidade, as entradas nas tabelas de syscall precisam ser ajustadas.
Primeiro, a entrada em ``arch/x86/entry/syscalls/syscall_32.tbl`` ganha uma
coluna extra para indicar que um programa de espaço do usuário de 32 bits rodando
em um kernel de 64 bits deve atingir o ponto de entrada compat::
380 i386 sys_xyzzy __ia32_compat_sys_xyzzy
Segundo, você precisa definir o que deve acontecer para a versão da ABI x32 da
nova chamada de sistema. Há uma escolha aqui: o layout dos argumentos deve
corresponder à versão de 64 bits ou à versão de 32 bits.
Se houver um ponteiro para um ponteiro envolvido, a decisão é fácil: x32 é
ILP32 (inteiro, long e ponteiro possuem 32 bits), portanto o layout deve
corresponder à versão de 32 bits, e a entrada em
``arch/x86/entry/syscalls/syscall_64.tbl`` é dividida para que os programas x32
atinjam o wrapper de compatibilidade::
333 64 sys_xyzzy
...
555 x32 __x32_compat_sys_xyzzy
Se não houver ponteiros envolvidos, então é preferível reutilizar a chamada de
sistema de 64 bits para a ABI x32 (e, consequentemente, a entrada em
``arch/x86/entry/syscalls/syscall_64.tbl`` permanece inalterada).
Em qualquer um dos casos, você deve verificar se os tipos envolvidos no layout
dos seus argumentos de fato se mapeiam exatamente do x32 (-mx32) para os seus
equivalentes de 32 bits (-m32) ou 64 bits (-m64).
Chamadas de Sistema com Retorno para Outro Local
------------------------------------------------
Para a maioria das chamadas de sistema (syscalls), assim que a execução é
concluída, o programa do usuário continua exatamente de onde parou -- na
próxima instrução, com a pilha idêntica e a maior parte dos registradores no
mesmo estado de antes da chamada, além do mesmo espaço de memória virtual.
No entanto, algumas poucas chamadas de sistema agem de forma diferente. Elas
podem retornar para um local distinto (``rt_sigreturn``), alterar o espaço de
memória (``fork``/``vfork``/``clone``) ou até mesmo modificar a arquitetura
(``execve``/``execveat``) do programa.
Para permitir isso, a implementação da chamada de sistema no kernel pode
precisar salvar e restaurar registradores adicionais na pilha do kernel,
garantindo controle total de onde e como a execução continuará após a syscall.
Isso é específico de cada arquitetura (arch-specific), mas tipicamente envolve
a definição de pontos de entrada em assembly que salvam/restauram esses
registradores adicionais e invocam o ponto de entrada real da chamada de
sistema.
Para x86_64, isso é implementado como um ponto de entrada ``stub_xyzzy`` em
``arch/x86/entry/entry_64.S``, e a entrada correspondente na tabela de syscalls
(``arch/x86/entry/syscalls/syscall_64.tbl``) é ajustada para refletir::
333 common stub_xyzzy
O equivalente para programas de 32 bits executados em um kernel de 64 bits é
normalmente chamado de ``stub32_xyzzy`` e implementado em
``arch/x86/entry/entry_64_compat.S``, com o respectivo ajuste na tabela de
syscalls em ``arch/x86/entry/syscalls/syscall_32.tbl``::
380 i386 sys_xyzzy stub32_xyzzy
Se a chamada de sistema precisar de uma camada de compatibilidade (como na
seção anterior), a versão ``stub32_`` precisará chamar a versão
``compat_sys_`` da chamada de sistema em vez da versão nativa de 64 bits. Além
disso, se a implementação da ABI x32 não for compartilhada com a versão
x86_64, sua tabela de syscalls também precisará invocar um stub que direcione
para a versão ``compat_sys_``.
Por questões de integridade, também é recomendado configurar um mapeamento para
que o User-Mode Linux (UML) continue funcionando -- sua tabela de syscalls fará
referência a ``stub_xyzzy``, mas o build do UML não inclui a implementação de
``arch/x86/entry/entry_64.S`` (já que o UML simula registradores, etc.). Corrigir
isso é tão simples quanto adicionar um #define em
``arch/x86/um/sys_call_table_64.c``::
#define stub_xyzzy sys_xyzzy
Outros Detalhes
---------------
A maior parte do kernel trata as chamadas de sistema de maneira genérica, mas
há exceções ocasionais que podem precisar de atualização para a sua chamada
de sistema específica.
O subsistema de auditoria (audit) é um desses casos especiais; ele inclui
funções (específicas de cada arquitetura) que classificam alguns tipos
especiais de chamada de sistema -- especificamente operações de abertura de
arquivo (``open``/``openat``), execução de programa (``execve``/``exeveat``) ou
multiplexador de socket (``socketcall``). Se a sua nova chamada de sistema for
análoga a uma dessas, o sistema de auditoria deverá ser atualizado.
De forma mais geral, se existir uma chamada de sistema atual que seja análoga
à sua nova chamada de sistema, vale a pena fazer um grep em todo o kernel pela
chamada existente para verificar se não há outros casos especiais.
Testes
------
Uma nova chamada de sistema deve, obviamente, ser testada; também é útil
fornecer aos revisores uma demonstração de como os programas do espaço do
usuário (user space) usarão a chamada de sistema. Uma boa maneira de combinar
esses objetivos é incluir um programa simples de autoteste em um novo diretório
sob ``tools/testing/selftests/``.
Para uma nova chamada de sistema, obviamente não haverá uma função de wrapper
na libc e, portanto, o teste precisará invocá-la usando ``syscall()``; além
disso, se a chamada de sistema envolver uma nova estrutura visível para o
espaço do usuário, o cabeçalho correspondente precisará ser instalado para
compilar o teste.
Certifique-se de que o autoteste seja executado com sucesso em todas as
arquiteturas suportadas. Por exemplo, verifique se ele funciona quando compitado
como um programa ABI x86_64 (-m64), x86_32 (-m32) e x32 (-mx32).
Para testes mais extensos e minuciosos de novas funcionalidades, você também
deve considerar a adição de testes ao Linux Test Project ou ao projeto
xfstests para alterações relacionadas
Página de Manual (Man Page)
---------------------------
Todas as novas chamadas de sistema devem vir acompanhadas de uma página de
manual completa, idealmente usando a marcação groff, mas texto simples também
é aceitável. Se o groff for utilizado, é útil incluir uma versão ASCII pré-
renderizada da página de manual no e-mail de apresentação (cover letter) do
conjunto de patches (patchset), para a conveniência dos revisores.
A página de manual deve ser enviada com cópia (cc) para
linux-man@vger.kernel.org. Para mais detalhes, consulte
https://www.kernel.org/doc/man-pages/patches.html
Não invoque Chamadas de Sistema dentro do Kernel
------------------------------------------------
As chamadas de sistema são, como mencionado acima, pontos de interação entre o
espaço do usuário (userspace) e o kernel. Portanto, funções de chamada de
sistema como ``sys_xyzzy()`` ou ``compat_sys_xyzzy()`` só devem ser chamadas a
partir do espaço do usuário por meio da tabela de syscalls, e não de outros
lugares do kernel. Se a funcionalidade da syscall for útil para ser utilizada
dentro do kernel, precisar ser compartilhada entre uma syscall antiga e uma
nova, ou precisar ser compartilhada entre uma syscall e sua variante de
compatibilidade, ela deve ser implementada por meio de uma função auxiliadora
("helper", como ``ksys_xyzzy()``). Essa função do kernel poderá então ser
chamada dentro do stub da syscall (``sys_xyzzy()``), do stub da syscall de
compatibilidade (``compat_sys_xyzzy()``) e/ou de outro código do kernel.
Pelo menos em x86 de 64 bits, será um requisito rígido a partir da versão v4.17
em diante não chamar funções de chamadas de sistema no kernel. Essa arquitetura
utiliza uma convenção de chamada diferente para chamadas de sistema na qual a
``struct pt_regs`` é decodificada dinamicamente em um wrapper de syscall, que
então repassa o processamento para a função real da syscall. Isso significa que
apenas os parâmetros realmente necessários para uma syscall específica são
passados durante a entrada da syscall, em vez de preencher seis registradores da
CPU com conteúdos aleatórios do espaço do usuário o tempo todo (o que poderia
causar problemas sérios no decorrer da cadeia de chamadas).
Além disso, as regras sobre como os dados podem ser acessados diferem entre os
dados do kernel e os dados do usuário. Essa é outra razão pela qual chamar
``sys_xyzzy()`` geralmente é uma má ideia.
Exceções a essa regra são permitidas apenas em substituições (overrides)
específicas de cada arquitetura, wrappers de compatibilidade específicos de cada
arquitetura ou outros códigos dentro do diretório arch/.
Referências e Fontes
--------------------
- Artigo da LWN por Michael Kerrisk sobre o uso do argumento flags em chamadas
de sistema:
https://lwn.net/Articles/585415/
- Artigo da LWN por Michael Kerrisk sobre como lidar com flags desconhecidas
em uma chamada de sistema: https://lwn.net/Articles/588444/
- Artigo da LWN por Jake Edge descrevendo restrições em argumentos de chamadas
de sistema de 64 bits: https://lwn.net/Articles/311630/
- Par de artigos da LWN por David Drysdale que descrevem detalhadamente os
caminhos de implementação de chamadas de sistema para a v3.14:
- https://lwn.net/Articles/604287/
- https://lwn.net/Articles/604515/
- Os requisitos específicos de arquitetura para chamadas de sistema são
discutidos na página de manual :manpage:`syscall(2)`:
http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES
- E-mails compilados de Linus Torvalds discutindo os problemas com ``ioctl()``:
https://yarchive.net/comp/linux/ioctl.html
- "How to not invent kernel interfaces", Arnd Bergmann,
https://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf
- Artigo da LWN por Michael Kerrisk sobre evitar novos usos de CAP_SYS_ADMIN:
https://lwn.net/Articles/486306/
- Recomendação de Andrew Morton para que todas as informações relacionadas a
uma nova chamada de sistema venham na mesma thread de e-mail:
https://lore.kernel.org/r/20140724144747.3041b208832bbdf9fbce5d96@linux-foundation.org
- Recomendação de Michael Kerrisk para que uma nova chamada de sistema venha
acompanhada de uma página de manual:
https://lore.kernel.org/r/CAKgNAkgMA39AfoSoA5Pe1r9N+ZzfYQNvNPvcRN7tOvRb8+v06Q@mail.gmail.com
- Sugestão de Thomas Gleixner para que a vinculação (wire-up) do x86 esteja em
um commit separado:
https://lore.kernel.org/r/alpine.DEB.2.11.1411191249560.3909@nanos
- Sugestão de Greg Kroah-Hartman de que é bom que novas chamadas de sistema
venham acompanhadas de uma página de manual e um autoteste:
https://lore.kernel.org/r/20140320025530.GA25469@kroah.com
- Discussão de Michael Kerrisk sobre uma nova chamada de sistema versus a
extensão de :manpage:`prctl(2)`:
https://lore.kernel.org/r/CAHO5Pa3F2MjfTtfNxa8LbnkeeU8=YJ+9tDqxZpw7Gz59E-4AUg@mail.gmail.com
- Sugestão de Ingo Molnar de que as chamadas de sistema que envolvem múltiplos
argumentos devem encapsular esses argumentos em uma struct, a qual inclua um
campo de tamanho (size) para fins de extensibilidade futura:
https://lore.kernel.org/r/20150730083831.GA22182@gmail.com
- Excentricidades de numeração decorrentes do uso (e reuso) de flags do espaço
de numeração O_*:
- commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness
check")
- commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc
conflict")
- commit bb458c644a59 ("Safer ABI for O_TMPFILE")
- Discussão de Matthew Wilcox sobre restrições em argumentos de 64 bits:
https://lore.kernel.org/r/20081212152929.GM26095@parisc-linux.org
- Recomendação de Greg Kroah-Hartman de que flags desconhecidas devem ser
fiscalizadas/policiadas:
https://lore.kernel.org/r/20140717193330.GB4703@kroah.com
- Recomendação de Linus Torvalds de que as chamadas de sistema x32 devem
preferir a compatibilidade com as versões de 64 bits em vez das versões de
32 bits:
https://lore.kernel.org/r/CA+55aFxfmwfB7jbbrXxa=K7VBYPfAvmu3XOkGrLbB1UFjX1+Ew@mail.gmail.com
- Série de patches revisando a infraestrutura da tabela de chamadas de sistema
para utilizar scripts/syscall.tbl em múltiplas arquiteturas:
https://lore.kernel.org/lkml/20240704143611.2979589-1-arnd@kernel.org

View File

@@ -0,0 +1,447 @@
.. SPDX-License-Identifier: GPL-2.0
Aplicando Patches ao Kernel Linux
+++++++++++++++++++++++++++++++++
Autor Original:
Jesper Juhl, Agosto de 2005
.. note::
Este documento está obsoleto. Na maioria dos casos, em vez de usar ``patch``
manualmente, você quase certamente desejará considerar o uso do Git.
Uma pergunta feita com frequência na Linux Kernel Mailing List é como aplicar
an patch ao kernel ou, mais especificamente, a qual kernel base um patch para
uma das muitas árvores/branches deve ser aplicado. Esperamos que este documento
explique isso a você.
Além de explicar como aplicar e reverter patches, uma breve descrição das
diferentes árvores do kernel (e exemplos de como aplicar seus patches
específicos) também é fornecida.
O que é um Patch?
=================
Um patch é um pequeno documento de texto que contém uma diferença (delta) de
alterações entre duas versões diferentes de uma árvore de código-fonte. Os
patches são criados com o programa ``diff``.
Para aplicar um patch corretamente, você precisa saber de qual base ele foi
gerado e em qual nova versão o patch transformará a árvore de código-fonte.
Ambas as informações devem estar presentes nos metadados do arquivo de patch
ou ser possíveis de deduzir a partir do nome do arquivo.
Como eu aplico ou reverto um patch?
===================================
Você aplica um patch com o programa ``patch``. O programa patch lê um arquivo
de diff (ou patch) e faz as alterações descritas nele na árvore de
código-fonte.
Os patches para o kernel Linux são gerados relativamente ao diretório pai que
contém o diretório do código-fonte do kernel.
Isso significa que os caminhos para os arquivos dentro do arquivo de patch
contêm o nome dos diretórios do código-fonte do kernel contra os quais ele foi
gerado (ou alguns outros nomes de diretório como "a/" e "b/").
Como é improvável que isso corresponda ao nome do diretório do código-fonte do
kernel na sua máquina local (mas frequentemente é uma informação útil para ver
contra qual versão um patch sem identificação foi gerado), você deve entrar no
seu diretório de código-fonte do kernel e, em seguida, remover o primeiro
elemento do caminho dos nomes de arquivos no arquivo de patch ao aplicá-lo (o
argumento ``-p1`` para o ``patch`` faz isso).
Para reverter um patch aplicado anteriormente, use o argumento -R para o patch.
Portanto, se você aplicou um patch desta forma::
patch -p1 < ../patch-x.y.z
Você pode revertê-lo (desfazê-lo) assim::
patch -R -p1 < ../patch-x.y.z
Como eu passo um arquivo de patch/diff para o ``patch``?
========================================================
Isso (como de costume no Linux e em outros sistemas operacionais do tipo UNIX)
pode ser feito de várias maneiras diferentes.
Em todos os exemplos abaixo, eu passo o arquivo (em formato não compactado) para
o patch via stdin usando a seguinte sintaxe::
patch -p1 < path/to/patch-x.y.z
Se você quer apenas ser capaz de seguir os exemplos abaixo e não deseja
conhecer mais do que uma maneira de usar o patch, então você pode parar a
leitura desta seção aqui.
O patch também pode receber o nome do arquivo a ser usado através do argumento
-i, desta forma::
patch -p1 -i path/to/patch-x.y.z
Se o seu arquivo de patch estiver compactado com gzip ou xz e você não quiser
descompactá-lo antes de aplicá-lo, você pode passá-lo para o patch desta outra
forma::
xzcat path/to/patch-x.y.z.xz | patch -p1
bzcat path/to/patch-x.y.z.gz | patch -p1
Se você deseja descompactar o arquivo de patch manualmente primeiro antes de
aplicá-lo (o que presumo que você tenha feito nos exemplos abaixo), basta
executar gunzip ou xz no arquivo -- desta forma::
gunzip patch-x.y.z.gz
xz -d patch-x.y.z.xz
O que deixará você com um arquivo patch-x.y.z em texto puro que você pode
passar para o patch via stdin ou pelo argumento ``-i``, conforme sua preferência.
Alguns outros argumentos úteis para o patch são ``-s``, que faz com que o patch
seja silencioso (exceto por erros), o que é bom para evitar que erros sumam da
tela rolando rápido demais; e ``--dry-run``, que faz com que o patch apenas
imprima uma lista do que aconteceria, mas sem realizar nenhuma alteração de
fato. Por fim, ``--verbose`` diz ao patch para imprimir mais informações sobre o
trabalho que está sendo realizado.
Erros comuns ao aplicar patches
===============================
Quando o patch aplica um arquivo de patch, ele tenta verificar a integridade do
arquivo de diferentes maneiras.
Verificar se o arquivo parece um arquivo de patch válido e checar se o código ao
redor dos trechos sendo modificados corresponde ao contexto fornecido no patch
são apenas duas das verificações básicas de integridade que o patch faz.
Se o patch encontrar algo que não pareça totalmente correto, ele tem duas
opções. Ele pode se recusar a aplicar as alterações e abortar, ou pode tentar
encontrar uma maneira de fazer o patch ser aplicado com algumas pequenas
alterações.
Um exemplo de algo que não está "totalmente correto" e que o patch tentará
corrigir é se todo o contexto coincidir, as linhas sendo alteradas coincidirem,
mas os números das linhas forem diferentes. Isso pode acontecer, por exemplo, se
o patch fizer uma alteração no meio do arquivo, mas, por algum motivo, algumas
linhas tiverem sido adicionadas ou removidas perto do início do arquivo. Nesse
caso, tudo parece correto, apenas mudou um pouco para cima ou para baixo, e o
patch geralmente ajustará os números das linhas e aplicará o patch.
Sempre que o patch aplicar um patch que ele teve de modificar um pouco para
fazer caber, ele avisará você dizendo que o patch foi aplicado com **fuzz**.
Você deve ser cauteloso com tais alterações porque, embora o patch
provavelmente tenha acertado, ele nem /sempre/ acerta, e o resultado às vezes
será incorreto.
Quando o patch encontra uma alteração que não consegue corrigir com fuzz, ele a
rejeita imediatamente e deixa um arquivo com a extensão ``.rej`` (um arquivo de
rejeição). Você pode ler esse arquivo para ver exatamente qual alteração não
pôde ser aplicada, para que possa corrigi-la manualmente, se desejar.
Se você não tem nenhum patch de terceiros aplicado ao seu código-fonte do
kernel, mas apenas patches do kernel.org, e você aplica os patches na ordem
correta, e não fez nenhuma modificação por conta própria nos arquivos de
origem, então você nunca deveria ver uma mensagem de fuzz ou de rejeição (reject)
do patch. Se você ainda assim vir tais mensagens, então há um alto risco de que
sua árvore de código-fonte local ou o arquivo de patch estejam corrompidos de
alguma forma. Nesse caso, você provavelmente deveria tentar baixar o patch
novamente e, se as coisas ainda não estiverem certas, aconselha-se começar com
uma árvore limpa baixada na íntegra do kernel.org.
Vamos examinar um pouco mais algumas das mensagens que o patch pode produzir.
Se o patch parar e apresentar um prompt ``File to patch:``, então o patch não
conseguiu encontrar um arquivo para ser modificado. O mais provável é que você
tenha esquecido de especificar -p1 ou esteja no diretório errado. Com menos
frequência, você encontrará patches que precisam ser aplicados com ``-p0`` em
vez de ``-p1`` (a leitura do arquivo de patch deve revelar se este é o caso -- se
for, isso é um erro da pessoa que criou o patch, mas não é fatal).
Se você receber ``Hunk #2 succeeded at 1887 with fuzz 2 (offset 7 lines).`` ou
uma mensagem semelhante a essa, significa que o patch teve que ajustar o local
da alteração (neste exemplo, ele precisou se mover 7 linhas de onde esperava
fazer a alteração para fazê-la caber).
O arquivo resultante pode ou não estar correto, dependendo do motivo pelo qual o
arquivo estava diferente do esperado.
Isso geralmente acontece se você tentar aplicar un patch que foi gerado contra uma
versão de kernel diferente daquela que você está tentando modificar.
Se você receber uma mensagem como ``Hunk #3 FAILED at 2387.``, significa que o
patch não pôde ser aplicado corretamente e o programa patch não foi capaz de
encontrar um caminho usando o fuzz. Isso gerará um arquivo ``.rej`` com a
alteração que fez o patch falhar e também um arquivo ``.orig`` mostrando o
conteúdo original que não pôde ser alterado.
Se você receber ``Reversed (or previously applied) patch detected! Assume -R? [n]``
então o patch detectou que a alteração contida no patch parece já ter sido feita.
Se você realmente aplicou este patch anteriormente e apenas o reaplicou por erro,
basta dizer [n]ão (n) e abortar este patch. Se você aplicou este patch
anteriormente e realmente pretendia revertê-lo, mas esqueceu de especificar -R,
você pode dizer [**y**]es (sim) aqui para fazer o patch revertê-lo para você.
Isso também pode acontecer se o criador do patch inverteu os diretórios de
origem e destino ao criar o patch e, nesse caso, reverter o patch irá, na
verdade, aplicá-lo.
Uma mensagem semelhante a ``patch: **** unexpected end of file in patch`` ou
``patch unexpectedly ends in middle of line`` significa que o patch não conseguiu
fazer sentido do arquivo que você passou para ele. Ou o seu download está
quebrado, ou você tentou passar para o patch um arquivo de patch compactado sem
descompactá-lo primeiro, ou o arquivo de patch que você está usando foi alterado
por um cliente de e-mail ou agente de transferência de e-mail em algum lugar pelo
caminho, por exemplo, dividindo uma linha longa em duas linhas. Frequentemente,
esses avisos podem ser corrigidos facilmente juntando (concatenando) as duas
linhas que foram divididas.
Como já mencionei acima, esses erros nunca deveriam acontecer se você aplicar um
patch do kernel.org na versão correta de uma árvore de código-fonte não
modificada. Portanto, se você obtiver esses erros com patches do kernel.org,
você provavelmente deve assumir que o seu arquivo de patch ou a sua árvore está
quebrada, e eu o aconselharia a recomeçar com um download limpo de uma árvore
completa do kernel e do patch que deseja aplicar.
Existem alternativas ao ``patch``?
==================================
Sim, existem alternativas.
Você pode usar o programa ``interdiff`` (http://cyberelk.net/tim/patchutils/) para
gerar um patch que represente as diferenças entre dois patches e, em seguida,
aplicar o resultado.
Isso permitirá que você passe de algo como 5.7.2 para 5.7.3 em um único
passo. A flag -z do interdiff permite até mesmo passar patches em formato
compactado com gzip ou bzip2 diretamente, sem o uso de zcat, bzcat ou
descompactação manual.
Aqui está como você passaria de 5.7.2 para 5.7.3 em um único passo::
interdiff -z ../patch-5.7.2.gz ../patch-5.7.3.gz | patch -p1
Embora o interdiff possa economizar um ou dois passos, geralmente recomenda-se
realizar os passos adicionais, já que o interdiff pode errar em alguns casos.
Outra alternativa é o ``ketchup``, que é um script em python para download e
aplicação automática de patches (https://www.selenic.com/ketchup/).
Outras ferramentas úteis são o diffstat, que mostra um resumo das alterações
feitas por um patch; o lsdiff, que exibe uma lista curta dos arquivos afetados
em um arquivo de patch, junto com (opcionalmente) os números das linhas de
início de cada patch; e o grepdiff, que exibe uma lista dos arquivos modificados
por um patch onde o patch contém uma determinada expressão regular.
Onde posso baixar os patches?
=============================
Os patches estão disponíveis em https://kernel.org/
Os patches mais recentes estão vinculados na página principal, mas eles também
possuem locais específicos.
Os patches 5.x.y (-stable) e 5.x residem em
https://www.kernel.org/pub/linux/kernel/v5.x/
Os patches incrementais 5.x.y residem em
https://www.kernel.org/pub/linux/kernel/v5.x/incr/
Os patches -rc não são armazenados no servidor web, mas são gerados sob
demanda a partir de tags do git, tais como
https://git.kernel.org/torvalds/p/v5.1-rc1/v5.0
Os patches estáveis -rc residem em
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/
Os kernels 5.x
==============
Estes são os lançamentos estáveis base publicados por Linus. O lançamento com o
número mais alto é o mais recente.
Se regressões ou outras falhas graves forem encontradas, um patch de correção
-stable será lançado (veja abaixo) sobre esta base. Assim que um novo kernel
base 5.x é lançado, um patch é disponibilizado contendo o delta entre o kernel
5.x anterior e o novo.
Para aplicar um patch mudando da versão 5.6 para a 5.7, você faria o seguinte
(note que tais patches **NÃO** se aplicam sobre kernels 5.x.y, mas sim sobre o
kernel base 5.x -- se você precisar mudar de 5.x.y para 5.x+1, você deve
primeiro reverter o patch do 5.x.y).
Aqui estão alguns exemplos::
# mudando de 5.6 para 5.7
$ cd ~/linux-5.6 # muda para o dir do fonte do kernel
$ patch -p1 < ../patch-5.7 # aplica o patch do 5.7
$ cd ..
$ mv linux-5.6 linux-5.7 # renomeia o dir do fonte
# mudando de 5.6.1 para 5.7
$ cd ~/linux-5.6.1 # muda para o dir do fonte do kernel
$ patch -p1 -R < ../patch-5.6.1 # reverte o patch do 5.6.1
# o dir do fonte agora é o 5.6
$ patch -p1 < ../patch-5.7 # aplica o novo patch do 5.7
$ cd ..
$ mv linux-5.6.1 linux-5.7 # renomeia o dir do fonte
Os kernels 5.x.y
================
Kernels com versões de 3 dígitos são kernels -stable (estáveis). Eles contêm
correções críticas relativamente pequenas para problemas de segurança ou
regressões significativas descobertas em um determinado kernel 5.x.
Esta é a ramificação recomendada para usuários que desejam o kernel estável mais
recente e não estão interessados em ajudar a testar versões de desenvolvimento
ou experimentais.
Se nenhum kernel 5.x.y estiver disponível, então o kernel 5.x com o número mais
alto será o atual kernel estável.
A equipe -stable fornece patches normais, bem como incrementais. Abaixo está
como aplicar esses patches.
Patches normais
~~~~~~~~~~~~~~~
Estes patches não são incrementais, o que significa que, por exemplo, o patch
5.7.3 não se aplica sobre o código-fonte do kernel 5.7.2, mas sim sobre o
código-fonte do kernel base 5.7.
Portanto, para aplicar o patch 5.7.3 ao seu código-fonte existente do kernel
5.7.2, você deve primeiro remover o patch 5.7.2 (de modo que reste apenas o
código-fonte do kernel base 5.7) e então aplicar o novo patch 5.7.3.
Aqui está um pequeno exemplo::
$ cd ~/linux-5.7.2 # muda para o dir do fonte do kernel
$ patch -p1 -R < ../patch-5.7.2 # reverte o patch do 5.7.2
$ patch -p1 < ../patch-5.7.3 # aplica o novo patch do 5.7.3
$ cd ..
$ mv linux-5.7.2 linux-5.7.3 # renomeia o dir do fonte do kernel
Patches incrementais
~~~~~~~~~~~~~~~~~~~~
Os patches incrementais são diferentes: em vez de serem aplicados sobre o kernel
base 5.x, eles são aplicados sobre o kernel estável anterior (5.x.y-1).
Aqui está o exemplo para aplicar estes::
$ cd ~/linux-5.7.2 # muda para o dir do fonte do kernel
$ patch -p1 < ../patch-5.7.2-3 # aplica o novo patch do 5.7.3
$ cd ..
$ mv linux-5.7.2 linux-5.7.3 # renomeia o dir do fonte do kernel
Os kernels -rc
==============
Estes são os kernels candidatos a lançamento (release-candidate). São kernels
de desenvolvimento publicados por Linus sempre que ele considera que a árvore
atual do git (a ferramenta de gerenciamento de código-fonte do kernel) está em
um estado razoavelmente íntegro e adequado para testes.
Estes kernels não são estáveis e você deve esperar quebras ocasionais se pretender
executá-los. Esta é, no entanto, a mais estável das principais ramificações de
desenvolvimento e é também o que eventualmente se tornará o próximo kernel
estável, por isso é importante que seja testado pelo maior número possível de
pessoas.
Esta é uma boa ramificação para pessoas que querem ajudar a testar kernels de
desenvolvimento, mas não querem executar algumas das coisas realmente
experimentais (essas pessoas devem ver as seções sobre os kernels -next e -mm
abaixo).
Os patches -rc não são incrementais; eles se aplicam a um kernel base 5.x, assim
como os patches 5.x.y descritos acima. A versão do kernel antes do sufixo -rcN
indica a versão do kernel na qual este kernel -rc eventualmente se tornará.
Portanto, 5.8-rc5 significa que este é o quinto candidato a lançamento para o
kernel 5.8 e o patch deve ser aplicado sobre o código-fonte do kernel 5.7.
Aqui estão 3 exemplos de como aplicar esses patches::
# primeiro, um exemplo de mudança do 5.7 para o 5.8-rc3
$ cd ~/linux-5.7 # muda para o dir do fonte do 5.7
$ patch -p1 < ../patch-5.8-rc3 # aplica o patch do 5.8-rc3
$ cd ..
$ mv linux-5.7 linux-5.8-rc3 # renomeia o dir do fonte
# agora vamos mudar do 5.8-rc3 para o 5.8-rc5
$ cd ~/linux-5.8-rc3 # muda para o dir do 5.8-rc3
$ patch -p1 -R < ../patch-5.8-rc3 # reverte o patch do 5.8-rc3
$ patch -p1 < ../patch-5.8-rc5 # aplica o novo patch do 5.8-rc5
$ cd ..
$ mv linux-5.8-rc3 linux-5.8-rc5 # renomeia o dir do fonte
# por fim, vamos tentar mudar do 5.7.3 para o 5.8-rc5
$ cd ~/linux-5.7.3 # muda para o dir do fonte do kernel
$ patch -p1 -R < ../patch-5.7.3 # reverte o patch do 5.7.3
$ patch -p1 < ../patch-5.8-rc5 # aplica o novo patch do 5.8-rc5
$ cd ..
$ mv linux-5.7.3 linux-5.8-rc5 # renomeia o dir do fonte do kernel
Os patches -mm e a árvore linux-next
====================================
Os patches -mm são patches experimentais publicados por Andrew Morton.
No passado, a árvore -mm também era usada para testar patches de subsistemas,
mas essa função agora é realizada por meio da árvore
`linux-next` (https://www.kernel.org/doc/man-pages/linux-next.html).
Os mantenedores de subsistemas enviam seus patches primeiro para a linux-next e,
durante a janela de mesclagem (merge window), enviam-nos diretamente para Linus.
Os patches -mm servem como uma espécie de campo de testes para novos recursos e
outros patches experimentais que não são mesclados por meio de uma árvore de
subsistema. Assim que tais patches provam seu valor na -mm por um tempo, Andrew
os envia para Linus para inclusão na linha principal (mainline).
A árvore linux-next é atualizada diariamente e inclui os patches -mm. Ambas
estão em constante fluxo e contêm muitos recursos experimentais, uma grande
quantidade de patches de depuração (debugging) não apropriados para a linha
principal etc., sendo as mais experimentais das ramificações descritas neste
documento.
Estes patches não são apropriados para uso em sistemas que devem ser estáveis e
são mais arriscados de executar do que qualquer uma das outras ramificações
(certifique-se de ter backups atualizados -- isso vale para qualquer kernel
experimental, mas ainda mais para patches -mm ou ao usar um kernel da árvore
linux-next).
O teste dos patches -mm e da linux-next é imensamente apreciado, pois todo o
objetivo deles é eliminar regressões, travamentos (crashes), bugs de corrupção
de dados, quebras de compilação (e qualquer outro bug em geral) antes que as
alterações sejam mescladas na árvore principal do Linus, que é mais estável.
Mas os testadores da -mm e da linux-next devem estar cientes de que quebras são
mais comuns do que em qualquer outra árvore.
Isso conclui esta lista de explicações sobre as várias árvores do kernel.
Espero que agora você tenha clareza sobre como aplicar os vários patches e
ajudar a testar o kernel.
Agradecimentos a Randy Dunlap, Rolf Eike Beer, Linus Torvalds, Bodo Eggert,
Johannes Stezenbach, Grant Coady, Pavel Machek e outros que posso ter esquecido
por suas revisões e contribuições para este documento.

View File

@@ -0,0 +1,598 @@
.. SPDX-License-Identifier: GPL-2.0
====================================
Backporting e resolução de conflitos
====================================
:Autor: Vegard Nossum <vegard.nossum@oracle.com>
.. contents::
:local:
:depth: 3
:backlinks: none
Introdução
==========
Alguns desenvolvedores podem nunca precisar lidar de fato com backporting de
patches, mesclagem de ramificações (branches) ou resolução de conflitos em seu
trabalho diário, portanto, quando um conflito de mesclagem aparece, pode ser
assustador. Felizmente, resolver conflitos é uma habilidade como qualquer outra,
e existem muitas técnicas úteis que você pode usar para tornar o processo mais
suave e aumentar sua confiança no resultado.
Este documento tem como objetivo ser um guia abrangente e passo a passo para
backporting e resolução de conflitos.
Aplicando o patch a uma árvore
==============================
Às vezes, o patch que você está fazendo backport já existe como um commit do
git, caso em que você apenas faz o cherry-pick dele diretamente usando
``git cherry-pick``. No entanto, se o patch vier de um e-mail, como costuma
acontecer no caso do kernel Linux, você precisará aplicá-lo a uma árvore usando
``git am``.
Se você já usou o ``git am``, provavelmente já sabe que ele é bastante exigente
sobre o patch ser aplicado perfeitamente à sua árvore de código-fonte. Na
verdade, você provavelmente já teve pesadelos com arquivos ``.rej`` e tentando
editar o patch para fazê-lo ser aplicado.
Recomenda-se fortemente, em vez disso, encontrar uma versão base apropriada onde
o patch se aplique de forma limpa e *então* fazer o cherry-pick dele para a sua
árvore de destino, pois isso fará com que o git exiba marcadores de conflito e
permitirá que você resolva os conflitos com a ajuda do git e de quaisquer outras
ferramentas de resolução de conflitos que preferir usar. Por exemplo, se você
quiser aplicar um patch que acabou de chegar na LKML a um kernel estável mais
antigo, você pode aplicá-lo ao kernel principal (mainline) mais recente e, em
seguida, fazer o cherry-pick dele para a sua ramificação estável mais antiga.
Geralmente é melhor usar exatamente a mesma base a partir da qual o patch foi
gerado, mas isso não importa tanto, desde que ele se aplique de forma limpa e
não esteja muito longe da base original. O único problema ao aplicar o patch na
base "errada" é que isso pode trazer mais alterações não relacionadas no
contexto do diff ao fazer o cherry-pick dele para a ramificação mais antiga.
Um bom motivo para preferir o ``git cherry-pick`` em vez do ``git am`` é que o
git conhece o histórico preciso de um commit existente, de modo que ele saberá
quando o código foi movido de lugar e teve seus números de linha alterados; isso,
por sua vez, torna menos provável que o patch seja aplicado no lugar errado (o
que pode resultar em erros silenciosos ou conflitos confusos).
Se você estiver usando o `b4`_. e estiver aplicando o patch diretamente de um
e-mail, você pode usar o ``b4 am`` com as opções ``-g``/``--guess-base`` e
``-3``/``--prep-3way`` para fazer parte disso automaticamente (veja a
`apresentação do b4`_ para mais informações). No entanto, o restante deste
artigo assumirá que você está fazendo um ``git cherry-pick`` simples.
.. _b4: https://people.kernel.org/monsieuricon/introducing-b4-and-patch-attestation
.. _apresentação do b4: https://youtu.be/mF10hgVIx9o?t=2996
Assim que tiver o patch no git, você pode prosseguir e fazer o cherry-pick dele
em sua árvore de código-fonte. Não se esqueça de fazer o cherry-pick com ``-x``
se quiser um registro por escrito de onde o patch veio!
Note que, se você estiver enviando um patch para a ramificação estável (stable),
o formato é ligeiramente diferente; a primeira linha após a linha de assunto
precisa ser::
commit <upstream commit> upstream
ou::
[ Upstream commit <upstream commit> ]
Resolvendo conflitos
====================
Ih, rapaz; o cherry-pick falhou com uma mensagem vagamente ameaçadora::
CONFLICT (content): Merge conflict
O que fazer agora?
Em geral, os conflitos aparecem quando o contexto do patch (ou seja, as linhas
que estão sendo alteradas e/ou as linhas que cercam as alterações) não
corresponde ao que está na árvore à qual você está tentando aplicar o patch.
No caso de backports, o que provavelmente aconteceu foi que a ramificação
(branch) a partir da qual você está fazendo o backport contém patches que não
estão na ramificação para a qual você está fazendo o backport. No entanto, o
inverso também é possível. Em qualquer caso, o resultado é um conflito que
precisa ser resolvido.
Se a sua tentativa de cherry-pick falhar com um conflito, o git edita os
arquivos automaticamente para incluir os chamados marcadores de conflito,
mostrando onde está o conflito e como as duas ramificações divergiram. Resolver
o conflito normalmente significa editar o resultado final de forma que ele leve
em consideração esses outros commits.
A resolução do conflito pode ser feita manualmente em um editor de texto comum
ou usando uma ferramenta dedicada de resolução de conflitos.
Muitas pessoas preferem usar seu editor de texto comum e editar o conflito
diretamente, pois pode ser mais fácil entender o que você está fazendo e
controlar o resultado final. Definitivamente, existem prós e contras em cada
método, e às vezes há valor em usar ambos.
Não abordaremos o uso de ferramentas de mesclagem (merge tools) dedicadas aqui,
além de fornecer algumas indicações de várias ferramentas que você poderia usar:
- `Modo Emacs Ediff <https://www.emacswiki.org/emacs/EdiffMode>`__
- `vimdiff/gvimdiff <https://linux.die.net/man/1/vimdiff>`__
- `KDiff3 <http://kdiff3.sourceforge.net/>`__
- `TortoiseMerge <https://tortoisesvn.net/TortoiseMerge.html>`__
- `Meld <https://meldmerge.org/help/>`__
- `P4Merge <https://www.perforce.com/products/helix-core-apps/merge-diff-tool-p4merge>`__
- `Beyond Compare <https://www.scootersoftware.com/>`__
- `IntelliJ <https://www.jetbrains.com/help/idea/resolve-conflicts.html>`__
- `VSCode <https://code.visualstudio.com/docs/editor/versioncontrol>`__
Para configurar o git para funcionar com elas, veja ``git mergetool --help`` ou
a `documentação oficial do git-mergetool`_.
.. _documentação oficial do git-mergetool: https://git-scm.com/docs/git-mergetool
Patches pré-requisitos
----------------------
A maioria dos conflitos acontece porque a ramificação para a qual você está
fazendo o backport não possui alguns patches em comparação com a ramificação a
partir da qual você está fazendo o backport. No caso mais geral (como a
mesclagem de duas ramificações independentes), o desenvolvimento poderia ter
ocorrido em qualquer uma das ramificações, ou as ramificações simplesmente
divergiram -- talvez a sua ramificação mais antiga tenha recebido alguns outros
backports que, por si só, precisaram de resoluções de conflitos, causando uma
divergência.
É importante sempre identificar o commit ou os commits que causaram o conflito,
pois, caso contrário, você não poderá ter confiança na correção da sua
resolução. Como um bônus adicional, especialmente se o patch for em uma área com
a qual você não está muito familiarizado, os registros de alterações (changelogs)
desses commits frequentemente lhe darão o contexto para entender o código e os
problemas ou armadilhas potenciais com a sua resolução de conflito.
git log
~~~~~~~
Um bom primeiro passo é olhar o ``git log`` para o arquivo que possui o
conflito -- isso geralmente é suficiente quando não há muitos patches no
arquivo, mas pode ficar confuso se o arquivo for grande e frequentemente
modificado por patches. Você deve executar o ``git log`` no intervalo de commits
entre a sua ramificação atualmente ativa (``HEAD``) e o pai do patch que você está
escolhendo (``<commit>``), ou seja::
git log HEAD..<commit>^ -- <path>
Melhor ainda, se você quiser restringir essa saída a uma única função (porque é
onde o conflito aparece), você pode usar a seguinte sintaxe::
git log -L:'\<function\>':<path> HEAD..<commit>^
.. note::
O ``\<`` e o ``\>`` ao redor do nome da função garantem que as
correspondências fiquem ancoradas em um limite de palavra. Isso é
importante, pois essa parte é na verdade uma regex e o git segue apenas a
primeira correspondência; portanto, se você usar
``-L:thread_stack:kernel/fork.c``, ele poderá fornecer apenas resultados
para a função ``try_release_thread_stack_to_cache``, embora existam muitas
outras funções naquele arquivo contendo a string ``thread_stack`` em seus
nomes.
Outra opção útil para o ``git log`` é a ``-G``, que permite filtrar por certas
strings que aparecem nos diffs dos commits que você está listando::
git log -G'regex' HEAD..<commit>^ -- <path>
Esta também pode ser uma maneira prática de encontrar rapidamente quando algo
(por exemplo, uma chamada de função ou uma variável) foi alterado, adicionado
ou removido. A string de busca é uma expressão regular, o que significa que você
pode potencialmente buscar por coisas mais específicas, como atribuições a um
membro específico de uma struct::
git log -G'\->index\>.*='
git blame
~~~~~~~~~
Outra maneira de encontrar commits pré-requisitos (embora apenas o mais recente
para um determinado conflito) é executar o ``git blame``. Neste caso, você
precisa executá-lo no commit pai do patch para o qual está fazendo o
cherry-pick e no arquivo onde o conflito apareceu, ou seja::
git blame <commit>^ -- <path>
Este comando também aceita o argumento ``-L`` (para restringir a saída a uma
única função), mas, neste caso, você especifica o nome do arquivo no final do
comando, como de costume::
git blame -L:'\<function\>' <commit>^ -- <path>
Navegue até o local onde o conflito ocorreu. A primeira coluna da saída do
blame é o ID do commit do patch que adicionou uma determinada linha de código.
Pode ser uma boa ideia dar um ``git show`` nesses commits e ver se eles se
parecem com a possível origem do conflito. Às vezes, haverá mais de um desses
commits, seja porque múltiplos commits alteraram linhas diferentes da mesma área
de conflito *ou* porque múltiplos patches subsequentes alteraram a mesma linha
(ou linhas) várias vezes. Neste último caso, você pode ter que executar o
``git blame`` novamente e especificar a versão mais antiga do arquivo para
analisar, a fim de cavar mais fundo no histórico do arquivo.
Patches pré-requisitos vs. incidentais
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tendo encontrado o patch que causou o conflito, você precisa determinar se ele
é um pré-requisito para o patch que você está fazendo o backport ou se é apenas
incidental e pode ser pulado. Um patch incidental seria aquele que toca no mesmo
código que o patch para o qual você está fazendo o backport, mas não altera a
semântica do código de nenhuma forma relevante. Por exemplo, um patch de limpeza
de espaços em branco é completamente incidental -- da mesma forma, um patch que
simplesmente renomeia uma função ou uma variável também seria incidental. Por
outro lado, se a função que está sendo alterada sequer existe na sua ramificação
atual, então isso não seria nada incidental e você precisa considerar com
cuidado se o patch que adiciona a função deve ser aplicado via cherry-pick
primeiro.
Se você descobrir que há um patch pré-requisito necessário, então você precisa
parar e fazer o cherry-pick dele em vez disso. Se você já resolveu alguns
conflitos em um arquivo diferente e não quer fazer isso de novo, você pode
criar uma cópia temporária daquele arquivo.
Para abortar o cherry-pick atual, vá em frente e execute
``git cherry-pick --abort`` e, em seguida, reinicie o processo de cherry-pick
com o ID do commit do patch pré-requisito.
Entendendo os marcadores de conflito
------------------------------------
Diffs combinados
~~~~~~~~~~~~~~~~
Digamos que você tenha decidido não fazer o cherry-pick (ou o revert) de patches
adicionais e quer apenas resolver o conflito. O Git terá inserido marcadores de
conflito no seu arquivo. Por padrão, isso se parecerá com algo como::
<<<<<<< HEAD
this is what's in your current tree before cherry-picking
=======
this is what the patch wants it to be after cherry-picking
>>>>>>> <commit>... title
Isso é o que você veria se abrisse o arquivo no seu editor. No entanto, se você
executasse o ``git diff`` sem nenhum argumento, a saída seria algo assim::
$ git diff
[...]
++<<<<<<<< HEAD
+this is what's in your current tree before cherry-picking
++========
+ this is what the patch wants it to be after cherry-picking
++>>>>>>>> <commit>... title
Quando você está resolvendo um conflito, o comportamento do ``git diff`` difere
do seu comportamento normal. Note as duas colunas de marcadores de diff em vez
da coluna única usual; este é o chamado "`diff combinado`_", aqui mostrando o
diff de 3 vias (ou diff-de-diffs) entre:
#. a ramificação atual (antes do cherry-pick) e o diretório de trabalho atual, e
#. a ramificação atual (antes do cherry-pick) e o arquivo como ele fica após o
patch original ter sido aplicado.
.. _diff combinado: https://git-scm.com/docs/diff-format#_combined_diff_format
Diffs melhores
~~~~~~~~~~~~~~
Diffs combinados de 3 vias incluem todas as outras alterações que aconteceram
no arquivo entre a sua ramificação atual e a ramificação a partir da qual você
está fazendo o cherry-pick. Embora isso seja útil para detectar outras
alterações que você precisa levar em consideração, também torna a saída do
``git diff`` um tanto intimidadora e difícil de ler. Em vez disso, você pode
preferir executar ``git diff HEAD`` (ou ``git diff --ours``), que mostra apenas
o diff entre a ramificação atual antes do cherry-pick e o diretório de trabalho
atual. Ele se parece com isso::
$ git diff HEAD
[...]
+<<<<<<<< HEAD
this is what's in your current tree before cherry-picking
+========
+this is what the patch wants it to be after cherry-picking
+>>>>>>>> <commit>... title
Como você pode ver, isso é lido exatamente como qualquer outro diff e deixa claro
quais linhas estão na ramificação atual e quais linhas estão sendo adicionadas
porque fazem parte do conflito de mesclagem ou do patch que está sendo aplicado
via cherry-pick.
Estilos de mesclagem e diff3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
O estilo padrão de marcador de conflito mostrado acima é conhecido como o estilo
``merge``. Também está disponível um outro estilo, conhecido como o estilo
``diff3``, que se parece com isso::
<<<<<<< HEAD
this is what is in your current tree before cherry-picking
||||||| parent of <commit> (title)
this is what the patch expected to find there
=======
this is what the patch wants it to be after being applied
>>>>>>> <commit> (title)
Como você pode ver, isso tem 3 partes em vez de 2, e inclui o que o git
esperava encontrar lá, mas não encontrou. É *altamente recomendável* usar este
estilo de conflito, pois deixa muito mais claro o que o patch realmente alterou;
ou seja, ele permite que você compare as versões de antes e depois do arquivo
para o commit do qual está fazendo o cherry-pick. Isso permite que você tome
melhores decisões sobre como resolver o conflito.
Para alterar os estilos de marcadores de conflito, você pode usar o seguinte
comando::
git config merge.conflictStyle diff3
Existe uma terceira opção, ``zdiff3``, introduzida no `Git 2.35`_, que possui as
mesmas 3 seções do ``diff3``, mas onde as linhas comuns foram cortadas, tornando
a área de conflito menor em alguns casos.
.. _Git 2.35: https://github.blog/2022-01-24-highlights-from-git-2-35/
Iterando em resoluções de conflito
----------------------------------
O primeiro passo em qualquer processo de resolução de conflito é entender o
patch para o qual você está fazendo o backport. Para o kernel Linux, isso é
especialmente importante, pois uma alteração incorreta pode levar ao travamento
de todo o sistema -- ou pior, a uma vulnerabilidade de segurança não detectada.
Entender o patch pode ser fácil ou difícil, dependendo do próprio patch, do
registro de alterações (changelog) e da sua familiaridade com o código que está
sendo alterado. No entanto, uma boa pergunta para cada alteração (ou cada bloco/
hunk do patch) seria: "Por que este hunk está no patch?" As respostas a essas
perguntas orientarão a sua resolução de conflito.
Processo de resolução
~~~~~~~~~~~~~~~~~~~~~
Às vezes, a coisa mais fácil a fazer é apenas remover tudo, exceto a primeira
parteda do conflito, deixando o arquivo essencialmente inalterado, e aplicar
as alterações manualmente. Talvez o patch esteja alterando um argumento de
chamada de função de ``0`` para ``1``, enquanto uma alteração conflitante
adicionou um parâmetro totalmente novo (e insignificante) ao final da lista de
parâmetros; nesse caso, é bastante fácil alterar o argumento de ``0`` para ``1``
manualmente e deixar o restante dos argumentos como estão. Esta técnica de
aplicar alterações manualmente é mais útil se o conflito tiver trazido muito
contexto não relacionado com o qual você não precisa realmente se preocupar.
Para conflitos particularmente difíceis com muitos marcadores de conflito, você
pode usar ``git add`` ou ``git add -i`` para indexar (stage) seletivamente as
suas resoluções para tirá-las do caminho; isso também permite que você use
``git diff HEAD`` para ver sempre o que ainda resta a ser resolvido ou
``git diff --cached`` para ver como está o seu patch até o momento.
Lidando com arquivos renomeados
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Uma das coisas mais irritantes que podem acontecer ao fazer o backport de um
patch é descobrir que um dos arquivos modificados foi renomeado, pois isso
geralmente significa que o git sequer colocará marcadores de conflito, mas
apenas lavará as mãos e dirá (parafraseando): "Caminho não mesclado! Faça você o
trabalho..."
Geralmente existem algumas maneiras de lidar com isso. Se o patch para o
arquivo renomeado for pequeno, como uma alteração de uma única linha, a coisa
mais fácil é prosseguir, aplicar a alteração manualmente e dar o caso por
encerrado. Por outro lado, se a alteração for grande ou complicada, você
definitivamente não vai querer fazê-la manualmente.
Como uma primeira tentativa, você pode tentar algo assim, que reduzirá o limite
(threshold) de detecção de renomeação para 30% (por padrão, o git usa 50%, o que
significa que dois arquivos precisam ter pelo menos 50% em comum para que ele
considere um par de adição/remoção como uma renomeação potencial)::
git cherry-pick -strategy=recursive -Xrename-threshold=30
Às vezes, a coisa certa a fazer será fazer o backport também do patch que
realizou a renomeação, mas esse definitivamente não é o caso mais comum. Em vez
disso, o que você pode fazer é renomear temporariamente o arquivo na
ramificação para a qual está fazendo o backport (usando ``git mv`` e commitando
o resultado), reiniciar a tentativa de cherry-pick do patch, renomear o arquivo
de volta (``git mv`` e commitando novamente) e, finalmente, esmagar (squash) o
resultado usando ``git rebase -i`` (veja o `tutorial de rebase`_) para que ele
apareça como um único commit quando você terminar.
.. _tutorial de rebase: [https://medium.com/@slamflipstrom/a-beginners-guide-to-squashing-commits-with-git-rebase-8185cf6e62ec](https://medium.com/@slamflipstrom/a-beginners-guide-to-squashing-commits-with-git-rebase-8185cf6e62ec)
Pegadinhas
----------
Argumentos de função
~~~~~~~~~~~~~~~~~~~~
Preste atenção às alterações em argumentos de função! É fácil deixar passar
detalhes e pensar que duas linhas são iguais quando, na verdade, elas diferem em
algum pequeno detalhe, como qual variável foi passada como argumento
(especialmente se as duas variáveis forem de apenas um caractere e parecerem
iguais, como i e j).
Tratamento de erros
~~~~~~~~~~~~~~~~~~~
Se você fizer o cherry-pick de um patch que inclua uma instrução ``goto``
(geralmente para tratamento de erros), é absolutamente imperativo verificar em
dobro se o rótulo (label) de destino ainda está correto na ramificação para a
qual você está fazendo o backport. O mesmo vale para instruções ``return``,
``break`` e ``continue`` adicionadas.
O tratamento de erros geralmente fica localizado no final da função, portanto,
pode não fazer parte do conflito, mesmo que possa ter sido alterado por outros
patches.
Uma boa maneira de garantir que você revise os caminhos de erro é sempre usar
``git diff -W`` e ``git show -W`` (também conhecido como ``--function-context``)
ao inspecionar suas alterações. Para código em C, isso mostrará toda a função
que está sendo alterada em um patch. Uma das coisas que frequentemente dão
errado durante backports é que algo mais na função mudou em qualquer uma das
ramificações a partir da qual ou para a qual você está fazendo o backport. Ao
incluir a função inteira no diff, você obtém mais contexto e pode identificar
mais facilmente problemas que de outra forma poderiam passar despercebidos.
Código refatorado
~~~~~~~~~~~~~~~~~
Algo que acontece com bastante frequência é o código ser refatorado ao "isolar"
uma sequência ou padrão de código comum em uma função auxiliar. Ao fazer o
backport de patches para uma área onde tal refatoração ocorreu, você efetivamente
precisa fazer o inverso ao realizar o backport: um patch para um único local pode
precisar ser aplicado a múltiplos locais na versão que recebeu o backport. (Um
indicativo para este cenário é que uma função foi renomeada -- mas nem sempre é o
caso.)
Para evitar backports incompletos, vale a pena tentar descobrir se o patch
corrige um bug que aparece em mais de um lugar. Uma maneira de fazer isso seria
usar o ``git grep``. (Isso, na verdade, é uma boa ideia de se fazer em geral, não
apenas para backports.) Se você descobrir que o mesmo tipo de correção se
aplicaria a outros lugares, também vale a pena ver se esses lugares existem no
upstream -- se não existirem, é provável que o patch precise ser ajustado. O
``git log`` é seu amigo para descobrir o que aconteceu com essas áreas, já que o
``git blame`` não mostrará código que foi removido.
Se você encontrar outras instâncias do mesmo padrão na árvore do upstream e não
tiver certeza se isso também é um bug, pode valer a pena perguntar ao autor do
patch. Não é incomum encontrar novos bugs durante o processo de backport!
Verificando o resultado
=======================
colordiff
---------
Tendo commitado um novo patch sem conflitos, você pode agora comparar o seu
patch com o patch original. É altamente recomendável que você use uma
ferramenta como o `colordiff`_ que possa mostrar dois arquivos lado a lado e
colori-los de acordo com as alterações entre eles::
colordiff -yw -W 200 <(git diff -W <upstream commit>^-) <(git diff -W HEAD^-) | less -SR
.. _colordiff: https://www.colordiff.org/
Aqui, ``-y`` significa fazer uma comparação lado a lado; ``-w`` ignora
espaços em branco e ``-W 200`` define a largura da saída (caso contrário, ele
usará 130 por padrão, o que costuma ser um pouco pouco).
A sintaxe ``rev^-`` é um atalho prático para ``rev^..rev``, essencialmente
fornecendo apenas o diff para aquele único commit; veja também a
`documentação oficial do git rev-parse`_.
.. _documentação oficial do git rev-parse: https://git-scm.com/docs/git-rev-parse#_other_rev_parent_shorthand_notations
Novamente, note a inclusão de ``-W`` para o ``git diff``; isso garante que você
verá a função completa para qualquer função que tenha mudado.
Uma coisa incrivelmente importante que o colordiff faz é destacar as linhas que
são diferentes. Por exemplo, se um ``goto`` de tratamento de erros teve seus
rótulos alterados entre o patch original e o que sofreu o backport, o colordiff
irá mostrá-los lado a lado, mas destacados em uma cor diferente. Assim, é fácil
ver que as duas instruções ``goto`` estão saltando para rótulos diferentes. Da
mesma forma, linhas que não foram modificadas por nenhum dos patches, mas que
diferem no contexto, também serão destacadas e, portanto, se destacarão durante
uma inspeção manual.
Claro, esta é apenas uma inspeção visual; o teste real é compilar e executar o
kernel (ou programa) com o patch aplicado.
Testes de compilação (Build testing)
------------------------------------
Não abordaremos os testes em tempo de execução aqui, mas pode ser uma boa ideia
compilar apenas os arquivos tocados pelo patch como uma verificação rápida de
sanidade. Para o kernel Linux, você pode compilar arquivos únicos assim,
assumindo que você tenha o ``.config`` e o ambiente de compilação configurados
corretamente::
make caminho/para/o/arquivo.o
Note que isso não descobrirá erros de ligação (linker errors), então você ainda
deve fazer uma compilação completa após verificar que o arquivo único compila.
Ao compilar o arquivo único primeiro, você pode evitar ter que esperar por uma
compilação completa *caso* haja erros de compilador em qualquer um dos arquivos
que você alterou.
Testes em tempo de execução
---------------------------
Mesmo um teste de compilação ou de boot bem-sucedido não é necessariamente o
suficiente para descartar uma dependência ausente em algum lugar. Embora as
chances sejam pequenas, pode haver alterações de código onde duas modificações
independentes no mesmo arquivo resultem em nenhum conflito, nenhum erro em tempo
de compilação e erros em tempo de execução apenas em casos excepcionais.
Um exemplo concreto disso foi um par de patches para o código de entrada de
chamada de sistema (system call entry code), onde o primeiro patch salvava/
restaurava um registrador e um patch posterior fazia uso do mesmo registrador
em algum lugar no meio dessa sequência. Como não havia sobreposição entre as
alterações, era possível fazer o cherry-pick do segundo patch, não ter conflitos
e acreditar que tudo estava bem, quando na verdade o código estava agora
sobrescrevendo (scribbling over) um registrador não salvo.
Embora a vasta maioria dos erros seja capturada durante a compilação ou ao
exercitar o código superficialmente, a única maneira de *realmente* verificar um
backport é revisar o patch final com o mesmo nível de escrutínio que você daria
(ou deveria dar) a qualquer outro patch. Ter testes unitários e testes de
regressão ou outros tipos de testes automáticos pode ajudar a aumentar a
confiança na correção de um backport.
Enviando backports para a árvore estável (stable)
=================================================
À medida que os mantenedores da árvore estável tentam aplicar correções da linha
principal (mainline) em seus kernels estáveis via cherry-pick, eles podem enviar
e-mails solicitando backports quando encontram conflitos; veja, por exemplo,
<https://lore.kernel.org/stable/2023101528-jawed-shelving-071a@gregkh/>.
Esses e-mails normalmente incluem os passos exatos que você precisa seguir para
fazer o cherry-pick do patch para a árvore correta e enviá-lo.
Uma coisa a se certificar é que o seu registro de alterações (changelog) esteja
em conformidade com o formato esperado::
<original patch title>
[ Upstream commit <mainline rev> ]
<rest of the original changelog>
[ <summary of the conflicts and their resolutions> ]
Signed-off-by: <your name and email>
A linha "Upstream commit" às vezes é ligeiramente diferente dependendo da versão
estável. Versões mais antigas usavam este formato::
commit <mainline rev> upstream.
O mais comum é indicar a versão do kernel à qual o patch se aplica na linha de
assunto do e-mail (usando, por exemplo,
``git send-email --subject-prefix='PATCH 6.1.y'``), mas você também pode
colocá-la na área do Signed-off-by: ou abaixo da linha ``---``.
Os mantenedores da árvore estável esperam envios separados para cada versão
estável ativa, e cada envio também deve ser testado separadamente.
Algumas palavras finais de conselho
===================================
1) Aborde o processo de backport com humildade.
2) Entenda o patch para o qual você está fazendo o backport; isso significa ler
tanto o registro de alterações (changelog) quanto o código.
3) Seja honesto sobre a sua confiança no resultado ao enviar o patch.
4) Peça aprovações explícitas (acks) aos mantenedores relevantes.
Exemplos
========
O texto acima mostra, de forma geral, o processo idealizado de backport de um
patch. Para um exemplo mais concreto, veja este tutorial em vídeo onde dois
patches são portados da linha principal (mainline) para a estável (stable):
`Backporting Linux Kernel Patches`_.
.. _Backporting Linux Kernel Patches: https://youtu.be/sBR7R1V2FeA

View File

@@ -0,0 +1,256 @@
.. SPDX-License-Identifier: GPL-2.0
============================================
(Como evitar) Deixar as ioctls malfeitas
============================================
De: https://blog.ffwll.ch/2013/11/botching-up-ioctls.html
Por: Daniel Vetter, Copyright © 2013 Intel Corporation
Uma percepção clara que os hackers de gráficos do kernel tiveram nos últimos
anos é que tentar criar uma interface unificada para gerenciar as unidades de
execução e a memória em GPUs completamente diferentes é um esforço inútil.
Portanto, hoje em dia, cada driver tem seu próprio conjunto de ioctls para
alocar memória e enviar trabalho para a GPU. O que é bom, já que não há mais a
insanidade na forma de interfaces falsamente genéricas, mas que na verdade só
são usadas uma vez. No entanto, a desvantagem clara é que há muito mais
potencial para estragar as coisas.
Para evitar repetir todos os mesmos erros novamente, escrevi algumas das lições
aprendidas enquanto fazia um trabalho malfeito para o driver drm/i915. A maioria
delas aborda apenas tecnicalidades e não os problemas macro (big-picture), como
deveria ser exatamente a aparência da ioctl de envio de comando. Aprender essas
lições é provavelmente algo que cada driver de GPU tem que fazer por conta
própria.
Pré-requisitos
--------------
Primeiro, os pré-requisitos. Sem estes você já falhou, porque precisará
adicionar uma camada de compatibilidade de 32 bits (compat layer):
* Use apenas inteiros de tamanho fixo. Para evitar conflitos com typedefs no
espaço de usuário (userspace), o kernel possui tipos especiais como __u32 e
__s64. Use-os.
* Alinhe tudo ao tamanho natural e use preenchimento (padding) explícito.
Plataformas de 32 bits não alinham necessariamente valores de 64 bits a
limites (boundaries) de 64 bits, mas plataformas de 64 bits o fazem. Portanto,
sempre precisamos de padding para o tamanho natural para acertar isso.
* Preencha a struct inteira para um múltiplo de 64 bits se a estrutura contiver
tipos de 64 bits -- caso contrário, o tamanho da estrutura diferirá entre
32 bits e 64 bits. Ter um tamanho de estrutura diferente prejudica ao passar
matrizes (arrays) de estruturas para o kernel, ou se o kernel verificar o
tamanho da estrutura, o que o core do drm, por exemplo, faz.
* Ponteiros são __u64, convertidos de/para um uintptr_t no lado do espaço de
usuário e de/para um void __user * no kernel. Tente de verdade não atrasar
essa conversão ou, pior ainda, manipular o __u64 bruto pelo seu código, pois
isso diminui a verificação que ferramentas como o sparse podem fornecer. A
macro u64_to_user_ptr pode ser usada no kernel para evitar avisos sobre
inteiros e ponteiros de tamanhos diferentes.
Conceitos básicos
-----------------
Evitadas as alegrias de escrever uma camada de compatibilidade (compat layer),
podemos dar uma olhada nos deslizes básicos. Negligenciar estes pontos tornará a
compatibilidade retroativa e futura uma verdadeira dor de cabeça. E, como errar
na primeira tentativa é garantido, você certamente terá uma segunda iteração ou,
pelo menos, uma extensão para qualquer interface fornecida.
* Tenha uma maneira clara para o espaço de usuário descobrir se a sua nova
ioctl ou extensão de ioctl é suportada em um determinado kernel. Se você não
puder confiar que os kernels antigos rejeitarão as novas flags/modos ou
ioctls (já que fazer isso foi deixado de lado no passado), então você
precisará de uma flag de recurso (feature flag) do driver ou de um número de
revisão em algum lugar.
* Tenha um plano para estender as ioctls com novas flags ou novos campos no
final da estrutura. O core do drm verifica o tamanho passado para cada
chamada de ioctl e preenche com zero (zero-extends) quaisquer divergências
entre o kernel e o espaço de usuário. Isso ajuda, mas não é uma solução
completa, já que um espaço de usuário mais novo em um kernel mais antigo não
notará que os campos recém-adicionados no final estão sendo ignorados.
Portanto, isso ainda exige novas flags de recurso do driver.
* Verifique todos os campos e flags não utilizados, além de todo o preenchimento
(padding), para garantir que estejam em 0, e rejeite a ioctl se esse não for
o caso. Caso contrário, seu excelente plano para extensões futuras irá por
água abaixo, pois alguém enviará uma struct de ioctl com lixo de pilha
(stack garbage) aleatório nas partes ainda não utilizadas. O que, então,
consolida na ABI que esses campos nunca poderão ser usados para nada além de
lixo. Esta também é a razão pela qual você deve preencher explicitamente todas
as estruturas, mesmo que nunca as use em uma matriz (array) -- o padding que
o compilador possa inserir poderia conter lixo.
* Tenha casos de teste simples para tudo o que foi mencionado acima.
Diversão com caminhos de erro (Error Paths)
-------------------------------------------
Hoje em dia, não temos mais nenhuma desculpa para que os drivers drm sejam pequenos
exploits de root disfarçados. Isso significa que precisamos tanto de uma
validação completa de entrada quanto de caminhos sólidos de tratamento de erros
-- as GPUs eventualmente vão parar de funcionar (die) nos casos mais bizarros
de qualquer maneira:
* A ioctl deve verificar se há estouros de matriz (array overflows). Ela também
precisa verificar estouros superiores/inferiores (over/underflows) e problemas
de limitação (clamping) de valores inteiros em geral. O exemplo usual são os
valores de posicionamento de sprite alimentados diretamente no hardware, onde
o hardware possui apenas 12 bits ou algo assim. Funciona perfeitamente até que
algum servidor de exibição bizarro não se preocupe em fazer o clamping por si
mesmo e o cursor dê a volta (wrap around) na tela.
* Tenha casos de teste simples para cada caso de falha de validação de entrada
na sua ioctl. Verifique se o código de erro corresponde às suas expectativas.
E, finalmente, certifique-se de testar apenas um único caminho de erro em
cada subteste, enviando dados que, de outra forma, seriam perfeitamente
válidos. Sem isso, uma verificação anterior já poderia rejeitar a ioctl e
ofuscar (shadow) o caminho de código que você realmente deseja testar,
ocultando bugs e regressões.
* Torne todas as suas ioctls reiniciáveis (restartable). Primeiro, o X (X11)
realmente ama sinais (signals) e, segundo, isso permitirá que você teste 90%
de todos os caminhos de tratamento de erro apenas interrompendo sua suíte de
testes principal constantemente com sinais. Graças ao amor do X por sinais,
você obterá uma excelente cobertura de base de todos os seus caminhos de erro
praticamente de graça para drivers de gráficos. Além disso, seja consistente
na forma como você lida com a reinicialização de ioctls -- por exemplo, o drm
possui um pequeno helper drmIoctl em sua biblioteca de espaço de usuário. O
driver i915 estragou isso com a ioctl set_tiling; agora estamos presos para
sempre com algumas semânticas arcanas tanto no kernel quanto no espaço de
usuário.
* Se você não puder tornar um determinado caminho de código reiniciável, torne
uma tarefa travada pelo menos finalizável (killable). As GPUs simplesmente
morrem, e seus usuários não vão gostar mais de você se você travar a máquina
inteira deles (por meio de um processo do X impossível de matar). Se a
recuperação de estado ainda for muito complicada, tenha um timeout ou uma
rede de segurança de verificação de travamento (hangcheck) como um esforço de
última hora (last-ditch) caso o hardware enlouqueça (gone bananas).
* Tenha casos de teste para os cenários mais complexos (corner cases) no seu
código de recuperação de erros -- é fácil demais criar um deadlock entre seu
código de hangcheck e os processos que estão aguardando (waiters).
Tempo, Espera e a Perda de Prazos
---------------------------------
As GPUs fazem quase tudo de forma assíncrona, portanto, temos a necessidade de
cronometrar operações e aguardar pelas que estão pendentes. Esse é um negócio
realmente complicado; no momento, nenhuma das ioctls suportadas pelo drm/i915
acerta isso completamente, o que significa que ainda há toneladas de lições para
aprender aqui.
* Use CLOCK_MONOTONIC como seu tempo de referência, sempre. É o que o alsa, o
drm e o v4l usam por padrão hoje em dia. Mas informe ao espaço de usuário
quais carimbos de data/hora (timestamps) são derivados de domínios de relógio
diferentes, como o relógio principal do seu sistema (fornecido pelo kernel)
ou algum contador de hardware independente em outro lugar. Os relógios vão
divergir se você olhar de perto o suficiente, mas se as ferramentas de
medição de desempenho tiverem essa informação, elas poderão ao menos compensar.
Se o seu espaço de usuário puder obter os valores brutos de alguns relógios
(por exemplo, por meio de instruções de amostragem de contador de desempenho
no fluxo de comandos), considere expor esses também.
* Use __s64 para segundos mais __u64 para nanossegundos para especificar o
tempo. Não é a especificação de tempo mais conveniente, mas é praticamente o
padrão.
* Verifique se os valores de tempo de entrada estão normalizados e rejeite-os
caso contrário. Note que a struct nativa do kernel, ktime, possui um inteiro
sinalizado tanto para segundos quanto para nanossegundos, portanto, cuidado
aqui.
* Para timeouts, use tempos absolutos. Se você for um bom sujeito e tiver
tornado a sua ioctl reiniciável, os timeouts relativos tendem a ser muito
imprecisos (coarse) e podem estender indefinidamente o seu tempo de espera
devido ao arredondamento a cada reinicialização. Especialmente se o seu relógio
de referência for algo realmente lento, como o contador de quadros da tela
(display frame counter). Vestindo o chapéu de advogado de especificações, isso
não é um bug, já que os timeouts sempre podem ser estendidos -- mas os usuários
com certeza vão odiar você se as belas animações deles começarem a gaguejar
(stutter) devido a isso.
* Considere descartar quaisquer ioctls de espera síncrona com timeouts e apenas
entregue um evento assíncrono em um descritor de arquivo passível de poll
(pollable file descriptor). Isso se encaixa muito melhor no loop principal de
aplicações orientadas a eventos.
* Tenha casos de teste para cenários complexos (corner-cases), especialmente se
os valores de retorno para eventos já concluídos, esperas bem-sucedidas e
esperas que estouraram o tempo (timed-out) são todos sãos e adequados às suas
necessidades.
Evitando o vazamento de recursos (Leaking Resources, Not)
---------------------------------------------------------
Um driver drm completo essencialmente implementa um pequeno SO, mas especializado
para as plataformas de GPU fornecidas. Isso significa que um driver precisa
expor toneladas de handles (identificadores) para diferentes objetos e outros
recursos para o espaço de usuário. Fazer isso corretamente traz seu próprio
pequeno conjunto de armadilhas:
* Sempre vincule o tempo de vida (lifetime) de seus recursos criados
dinamicamente ao tempo de vida de um descritor de arquivo (file descriptor -
fd). Considere usar um mapeamento 1:1 se o seu recurso precisar ser
compartilhado entre processos -- a passagem de fds sobre unix domain sockets
também simplifica o gerenciamento do tempo de vida para o espaço de usuário.
* Sempre tenha suporte a O_CLOEXEC.
* Certifique-se de que você tem isolamento suficiente entre os diferentes
clientes. Por padrão, escolha um namespace privado por fd, o que força
qualquer compartilhamento a ser feito de forma explícita. Só adote um
namespace mais global por dispositivo se os objetos forem verdadeiramente
únicos do dispositivo. Um contraexemplo nas interfaces de modeset do drm é
que os objetos de modeset por dispositivo, como conectores, compartilham um
namespace com objetos de framebuffer, que na maioria das vezes não são
compartilhados de forma alguma. Um namespace separado, privado por padrão,
para os framebuffers teria sido mais adequado.
* Pense sobre os requisitos de unicidade para os handles do espaço de usuário.
Por exemplo, para a maioria dos drivers drm, é um bug do espaço de usuário
enviar o mesmo objeto duas vezes na mesma ioctl de envio de comando. Mas,
se os objetos forem compartilháveis, o espaço de usuário precisa saber se
já viu um objeto importado de outro processo ou não. Eu ainda não tentei isso
sozinho devido à falta de uma nova classe de objetos, mas considere usar
números de inode em seus descritores de arquivo compartilhados como
identificadores únicos -- é assim que arquivos reais também são diferenciados.
Infelizmente, isso requer um sistema de arquivos virtual completo no kernel.
Por último, mas não menos importante
------------------------------------
Nem todo problema precisa de uma nova ioctl:
* Pense bem se você realmente quer uma interface privada do driver. Claro que
é muito mais rápido aprovar uma interface privada do driver do que se envolver
em discussões longas por uma solução mais genérica. E, ocasionalmente, criar
uma interface privada para liderar um novo conceito é o que se exige. Mas,
no final, assim que a interface genérica surgir, você acabará mantendo duas
interfaces. Indefinidamente.
* Considere outras interfaces além de ioctls. Um atributo sysfs é muito melhor
para configurações por dispositivo ou para objetos filhos com tempos de vida
razoavelmente estáticos (como conectores de saída no drm com todos os seus
atributos de sobreposição de detecção). Ou talvez apenas a sua suíte de
testes precise dessa interface e, nesse caso, o debugfs, com seu aviso de
isenção de responsabilidade por não ter uma ABI estável, seria melhor.
Finalmente, o objetivo principal é acertar na primeira tentativa, pois se o seu
driver se provar popular e suas plataformas de hardware forem duradouras, você
ficará preso a uma determinada ioctl essencialmente para sempre. Você pode
tentar depreciar ioctls horríveis em iterações mais novas do seu hardware, mas
geralmente leva anos para conseguir isso. E depois mais anos até que o último
usuário capaz de reclamar sobre regressões desapareça também.

View File

@@ -0,0 +1,257 @@
.. SPDX-License-Identifier: GPL-2.0
Interpretação do Código de Conduta do Kernel Linux
==================================================
O :ref:`pt_BR_code_of_conduct` é um documento geral que tem como objetivo
fornecer um conjunto de regras para quase todas as comunidades de código
aberto. Toda comunidade de código aberto é única e o kernel Linux não é
exceção. Por causa disso, este documento descreve como nós, na comunidade
do kernel Linux, o interpretaremos. Nós também não esperamos que esta
interpretação seja estática ao longo do tempo, e a ajustaremos conforme
necessário.
O esforço de desenvolvimento do kernel Linux é um processo muito pessoal
em comparação com as formas "tradicionais" de desenvolvimento de software.
Suas contribuições e as ideias por trás delas serão cuidadosamente
revisadas, frequentemente resultando em críticas e apontamentos. A
revisão quase sempre exigirá melhorias antes que o material possa ser
incluído no kernel. Saiba que isso acontece porque todos os envolvidos
querem ver a melhor solução possível para o sucesso geral do Linux. Este
processo de desenvolvimento provou criar o kernel de sistema operacional
mais robusto de todos os tempos, e nós não queremos fazer nada que cause
a diminuição da qualidade do envio e do resultado final.
Mantenedores
------------
O Código de Conduta usa o termo "mantenedores" várias vezes. Na
comunidade do kernel, um "mantenedor" é qualquer pessoa responsável por
um subsistema, driver ou arquivo, e que esteja listada no arquivo
MAINTAINERS na árvore de código-fonte do kernel.
Responsabilidades
-----------------
O Código de Conduta menciona direitos e responsabilidades para os
mantenedores, e isso precisa de alguns esclarecimentos adicionais.
Em primeiro lugar e acima de tudo, é uma expectativa razoável que os
mantenedores liderem pelo exemplo.
Dito isto, nossa comunidade é vasta e ampla, e não há um novo requisito
para que os mantenedores lidem unilateralmente com o comportamento de
outras pessoas nas partes da comunidade onde atuam. Essa responsabilidade
é de todos nós e, em última análise, o Código de Conduta documenta os
caminhos finais de escalonamento em caso de preocupações não resolvidas
em relação a questões de conduta.
Os mantenedores devem estar dispostos a ajudar quando ocorrerem problemas
e trabalhar com outras pessoas na comunidade quando necessário. Não tenha
medo de entrar em contato com o Conselho Consultivo Técnico (TAB) ou
outros mantenedores se não tiver certeza de como lidar com as situações
que surgirem. Isso não será considerado um relato de violação, a menos
que você queira que seja. Se não tiver certeza sobre como abordar o TAB
ou quaisquer outros mantenedores, entre em contato com nossa mediadora
de conflitos, Joanna Lee <jlee@linuxfoundation.org>.
No final, "sejam gentis uns com os outros" é realmente o objetivo final
para todos. Sabemos que todos são humanos e que todos falhamos às vezes,
mas o objetivo principal para todos nós deve ser trabalhar em direção a
resoluções amigáveis dos problemas. A aplicação do código de conduta será
apenas uma opção de último recurso.
Nosso objetivo de criar um sistema operacional robusto e tecnicamente
avançado e a complexidade técnica envolvida exigem naturalmente
conhecimento técnico e tomada de decisões.
O conhecimento técnico exigido varia dependendo da área de contribuição.
Ele é determinado principalmente pelo contexto e pela complexidade técnica
e apenas secundariamente pelas expectativas de contribuidores e
mantenedores.
Tanto as expectativas de conhecimento técnico quanto a tomada de decisões
estão sujeitas a discussão, mas no final das contas há uma necessidade
básica de sermos capazes de tomar decisões para progredir. Esta
prerrogativa está nas mãos dos mantenedores e da liderança do projeto e
espera-se que seja usada de boa fé.
Como consequência, definir expectativas de conhecimento técnico, tomar
decisões e rejeitar contribuições inadequadas não são vistos como uma
violação do Código de Conduta.
Embora os mantenedores sejam em geral receptivos aos novatos, sua
capacidade de ajudar os contribuidores a superar os obstáculos de entrada
é limitada, portanto, eles devem definir prioridades. Isso, também, não
deve ser visto como uma violação do Código de Conduta. A comunidade do
kernel está ciente disso e fornece programas de nível de entrada de
várias formas, como o kernelnewbies.org.
Escopo
------
A comunidade do kernel Linux interage primariamente em um conjunto de listas
de e-mail públicas distribuídas por vários servidores diferentes controlados
por várias empresas ou indivíduos diferentes. Todas essas listas estão
definidas no arquivo MAINTAINERS na árvore de código-fonte do kernel.
Quaisquer e-mails enviados para essas listas de e-mail são considerados
cobertos pelo Código de Conduta.
Desenvolvedores que usam o bugzilla do kernel.org e outras ferramentas de
rastreamento de bugs ou bugzilla de subsistemas devem seguir as diretrizes
do Código de Conduta. A comunidade do kernel Linux não possui um endereço
de e-mail de projeto "oficial" ou endereço "oficial" de mídia social.
Qualquer atividade realizada usando uma conta de e-mail do kernel.org deve
seguir o Código de Conduta conforme publicado para o kernel.org, assim como
qualquer indivíduo usando uma conta de e-mail corporativa deve seguir as
regras específicas daquela corporação.
O Código de Conduta não proíbe que se continue a incluir nomes, endereços de
e-mail e comentários associados em mensagens de listas de discussão,
mensagens de log de alterações (changelog) do kernel ou comentários no
código.
A interação em outros fóruns é coberta pelas regras que se aplicam a tais
fóruns e, em geral, não é coberta pelo Código de Conduta. Exceções podem
ser consideradas para circunstâncias extremas.
As contribuições enviadas para o kernel devem usar linguagem apropriada.
O conteúdo já existente que precede o Código de Conduta não será tratado
agora como uma violação. No entanto, a linguagem inapropriada pode ser vista
como um bug; tais bugs serão corrigidos mais rapidamente se quaisquer partes
interessadas enviarem patches com esse propósito. Expressões que atualmente
fazem parte da API de usuário/kernel, ou que refletem a terminologia usada
em padrões ou especificações publicadas, não são consideradas bugs.
Aplicação
---------
O endereço listado no Código de Conduta vai para o Comitê do Código de
Conduta. Os membros exatos que recebem esses e-mails a qualquer momento
estão listados em https://kernel.org/code-of-conduct.html. Os membros não
podem acessar relatos feitos antes de se juntarem ou após terem deixado o
comitê.
O Comitê do Código de Conduta consiste em membros voluntários da comunidade
nomeados pelo TAB, bem como um mediador profissional agindo como um terceiro
neutro. Os processos que o comitê do Código de Conduta usará para lidar com
os relatos variam e dependerão das circunstâncias individuais; no entanto,
este arquivo serve como documentação para o processo geral utilizado.
Qualquer membro do comitê, incluindo o mediador, pode ser contatado
diretamente se o relator não desejar incluir todo o comitê em uma
reclamação ou preocupação.
O Comitê do Código de Conduta revisa os casos de acordo com os processos
(veja acima) e consulta o TAB conforme a necessidade e a conveniência,
por exemplo, para solicitar e receber informações sobre a comunidade do
kernel.
Quaisquer decisões a respeito de recomendações de aplicação (enforcement)
serão levadas ao TAB para implementação junto aos mantenedores relevantes,
se necessário. Uma vez que o TAB aprove uma ou mais das medidas descritas
no escopo do banimento pelo voto de dois terços dos membros, o Comitê do
Código de Conduta aplicará as medidas aprovadas pelo TAB. Quaisquer membros
do Comitê do Código de Conduta que sirvam no TAB não votarão nas medidas.
Em intervalos trimestrais, o Comitê do Código de Conduta e o TAB fornecerão
um relatório resumindo os relatos anonimizados que o comitê do Código de
Conduta recebeu e o status deles, bem como os detalhes de quaisquer
decisões aprovadas pelo TAB, incluindo dados completos e identificáveis da
votação.
Como a maneira pela qual interpretamos e aplicamos o Código de Conduta
evoluirá com o tempo, este documento será atualizado quando necessário para
refletir quaisquer mudanças.
Aplicação para Violações de Comportamento Inaceitável do Código de Conduta
----------------------------------------------------------------------------
O comitê do Código de Conduta trabalha para garantir que nossa comunidade
continue a ser inclusiva e promova discussões e pontos de vista diversos, e
trabalha para melhorar essas características ao longo do tempo. A maioria
dos relatos que o Comitê do Código de Conduta recebe decorre da
compreensão incorreta sobre o processo de desenvolvimento e os papéis,
responsabilidades e o direito dos mantenedores de tomar decisões sobre a
aceitação de código. Estes são resolvidos através do esclarecimento do
processo de desenvolvimento e do escopo do Código de Conduta.
Comportamentos inaceitáveis podem interromper a colaboração respeitosa por um
curto período de tempo e impactar negativamente a saúde da comunidade a longo
prazo. Comportamentos inaceitáveis frequentemente são resolvidos quando os
indivíduos reconhecem seu comportamento e se retratam por ele no ambiente em
que a violação ocorreu.
O Comitê do Código de Conduta recebe relatos sobre comportamentos
inaceitáveis quando eles não são resolvidos através de discussões na
comunidade. O comitê do Código de Conduta toma medidas para restaurar a
colaboração produtiva e respeitosa quando um comportamento inaceitável
impactou negativamente esse relacionamento.
O Comitê do Código de Conduta tem a obrigação de manter os relatos e as
informações dos relatores em sigilo. Os relatos podem vir de partes lesadas
e membros da comunidade que são observadores de comportamentos
inaceitáveis. O Comitê do Código de Conduta tem a responsabilidade de
investigar e resolver esses relatos, trabalhando com todas as partes
envolvidas.
O Comitê do Código de Conduta trabalha com o indivíduo para promover uma
mudança em sua compreensão sobre a importância de reparar os danos causados
por seu comportamento à parte lesada e o impacto negativo a longo prazo na
comunidade.
O objetivo é alcançar uma resolução que seja aceitável para todas as partes.
Se trabalhar com o indivíduo não trouxer o resultado desejado, o Comitê do
Código de Conduta avaliará outras medidas, como buscar um pedido de
desculpas público para reparar o dano.
Buscar retratação pública pela violação
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
O Comitê do Código de Conduta chama a atenção publicamente para o comportamento
no ambiente em que a violação ocorreu, buscando uma retratação pública
pela violação.
Uma retratação pública pela violação é o primeiro passo para reconstruir a
confiança. A confiança é essencial para o sucesso contínuo e a saúde da
comunidade, que opera com base na confiança e no respeito.
Medidas corretivas se não houver uma retratação pública pela violação
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
O Comitê do Código de Conduta determina o próximo curso de ação para restaurar
a colaboração saudável, recomendando medida(s) corretiva(s) ao TAB para
aprovação.
- Banir o infrator de participar do processo de desenvolvimento do kernel por
um período de até um ciclo completo de desenvolvimento do kernel. O Comitê
do Código de Conduta pode exigir uma retratação pública como condição
para suspender o banimento.
O escopo do banimento por um período de tempo pode incluir:
a. negar contribuições de patch e pull requests
b. pausar a colaboração com o infrator ignorando suas contribuições e/ou
bloqueando sua(s) conta(s) de e-mail
c. restringir sua capacidade de se comunicar pelas plataformas kernel.org,
como listas de discussão e sites de mídia social
Uma vez que o TAB aprove uma ou mais das medidas descritas no escopo do
banimento por dois terços dos membros votando a favor das medidas, o Comitê do
Código de Conduta aplicará a(s) medida(s) aprovada(s) pelo TAB em colaboração
com a comunidade, mantenedores, submantenedores e administradores do
kernel.org. Quaisquer membros do Comitê do Código de Conduta atuando no TAB
não votarão nas medidas.
O Comitê do Código de Conduta está ciente do impacto negativo que buscar uma
retratação pública e instituir um banimento pode ter sobre os indivíduos.
Também está ciente dos danos a longo prazo para a comunidade que podem resultar
da falta de ação quando tais violações públicas graves ocorrem.
A eficácia da(s) medida(s) corretiva(s) aprovada(s) pelo TAB depende da
confiança e cooperação da comunidade, mantenedores, submantenedores e
administradores do kernel.org na sua aplicação.
O Comitê do Código de Conduta espera sinceramente que comportamentos
inaceitáveis que exijam a busca de retratações públicas continuem a ser
ocorrências extremamente raras no futuro.

View File

@@ -0,0 +1,88 @@
.. SPDX-License-Identifier: GPL-2.0
.. _pt_BR_code_of_conduct:
Código de Conduta de Compromisso do Colaborador
+++++++++++++++++++++++++++++++++++++++++++++++
Nosso Compromisso
=================
No interesse de promover um ambiente aberto e acolhedor, nós, como colaboradores
e mantenedores, nos comprometemos a tornar a participação em nosso projeto e em
nossa comunidade uma experiência livre de assédio para todos, independentemente
da idade, tamanho corporal, deficiência, etnia, características sexuais,
identidade e expressão de gênero, nível de experiência, educação, status
socioeconômico, nacionalidade, aparência pessoal, raça, religião ou identidade
e orientação sexual.
Nossos Padrões
==============
Exemplos de comportamentos que contribuem para a criação de um ambiente positivo
incluem:
* Utilizar linguagem acolhedora e inclusiva
* Respeitar pontos de vista e experiências divergentes
* Aceitar críticas construtivas de forma cortês
* Focar no que é melhor para a comunidade
* Demonstrar empatia para com outros membros da comunidade
Exemplos de comportamentos inaceitáveis por parte dos participantes incluem:
* O uso de linguagem ou imagens de teor sexual, bem como atenção ou avanços
sexuais indesejados
* Provocações (*trolling*), comentários insultuosos/depreciativos e ataques
pessoais ou políticos
* Assédio público ou privado
* Publicar informações privadas de terceiros, como endereço físico ou eletrônico,
sem permissão explícita
* Qualquer outra conduta que possa ser razoavelmente considerada inadequada em um
ambiente profissional
Nossas Responsabilidades
========================
Os mantenedores são responsáveis por esclarecer os padrões de comportamento
aceitável e devem tomar medidas corretivas apropriadas e justas em resposta a
quaisquer casos de comportamento inaceitável.
Os mantenedores têm o direito e a responsabilidade de remover, editar ou rejeitar
comentários, commits, código, edições em wiki, issues e outras contribuições que
não estejam alinhadas a este Código de Conduta, ou de banir temporária ou
permanentemente qualquer colaborador por outros comportamentos que considerem
inadequados, ameaçadores, ofensivos ou prejudiciais.
Escopo
======
Este Código de Conduta se aplica tanto dentro dos espaços do projeto quanto em
espaços públicos quando um indivíduo estiver representando o projeto ou sua
comunidade. Exemplos de representação do projeto ou comunidade incluem o uso de um
endereço de e-mail oficial do projeto, publicações por meio de uma conta oficial
em redes sociais ou atuar como um representante nomeado em um evento online ou
presencial. A representação de um projeto pode ser detalhada e esclarecida de forma
adicional pelos mantenedores do projeto.
Aplicação
=========
Casos de comportamento abusivo, de assédio ou inaceitável sob qualquer outro aspecto
podem ser relatados entrando em contato com o Comitê do Código de Conduta pelo e-mail
<conduct@kernel.org>. Todas as reclamações serão revisadas e investigadas, resultando
em uma resposta considerada necessária e adequada às circunstâncias. O Comitê do
Código de Conduta é obrigado a manter a confidencialidade em relação ao denunciante
de um incidente. Detalhes adicionais sobre políticas de aplicação específicas podem
ser publicados separadamente.
Atribuição
==========
Este Código de Conduta foi adaptado do Contributor Covenant, versão 1.4,
disponível em https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
Interpretação
=============
Consulte o documento :ref:`code_of_conduct_interpretation` para entender como a
comunidade do kernel Linux interpretará este documento.

View File

@@ -0,0 +1,111 @@
.. SPDX-License-Identifier: GPL-2.0
=======================================================
Modelos de Maturidade para Contribuição no Kernel Linux
=======================================================
Contexto
========
Como parte do Linux Kernel Maintainers Summit de 2021, houve uma
`discussão <https://lwn.net/Articles/870581/>`_ sobre os desafios na
contratação de mantenedores do kernel, bem como a sucessão de mantenedores.
Algumas das conclusões daquela discussão incluíram que as empresas que fazem
parte da comunidade do Kernel Linux precisam permitir que os engenheiros atuem
como mantenedores como parte de seu trabalho, para que possam crescer e se
tornar líderes respeitados e, eventualmente, mantenedores do kernel. Para
apoiar um fluxo forte de talentos, os desenvolvedores devem ser autorizados e
incentivados a assumir contribuições no upstream, como revisar os patches de
outras pessoas, refatorar a infraestrutura do kernel e escrever documentação.
Para tanto, o Conselho Técnico Consultivo (Technical Advisory Board - TAB) da
Linux Foundation propõe este Modelo de Maturidade para Contribuição no Kernel
Linux. Essas expectativas comuns para o engajamento da comunidade upstream visam
aumentar a influência de desenvolvedores individuais, aumentar a colaboração
de organizações e melhorar a saúde geral do ecossistema do Kernel Linux.
O TAB insta as organizações a avaliarem continuamente seu modelo de maturidade
em Open Source e a se comprometerem com melhorias para se alinharem a este
modelo. Para ser eficaz, essa avaliação deve incorporar o feedback de toda a
organização, incluindo a gerência e os desenvolvedores de todos os níveis de
senioridade. No espírito do Open Source, incentivamos as organizações a
publicarem suas avaliações e planos para melhorar seu engajamento com a
comunidade upstream.
Nível 0
=======
* Engenheiros de Software não têm permissão para contribuir com patches para o
kernel Linux.
Nível 1
=======
* Engenheiros de Software têm permissão para contribuir com patches para o
kernel Linux, seja como parte de suas responsabilidades de trabalho ou em seu
próprio tempo.
Nível 2
=======
* Espera-se que os Engenheiros de Software contribuam para o Kernel Linux como
parte de suas responsabilidades de trabalho.
* Os Engenheiros de Software receberão apoio para participar de conferências
relacionadas ao Linux como parte de seu trabalho.
* As contribuições de código no upstream de um Engenheiro de Software serão
consideradas em promoções e avaliações de desempenho.
Nível 3
=======
* Espera-se que os Engenheiros de Software revisem patches (incluindo patches
escritos por engenheiros de outras empresas) como parte de suas
responsabilidades de trabalho.
* A contribuição com apresentações ou artigos para conferências acadêmicas ou
relacionadas ao Linux (como as organizadas pela Linux Foundation, Usenix,
ACM, etc.) é considerada parte do trabalho do engenheiro.
* As contribuições comunitárias de um Engenheiro de Software serão consideradas
em promoções e avaliações de desempenho.
* As organizações relatarão regularmente as métricas de suas contribuições em
open source e acompanharão essas métricas ao longo do tempo. Essas métricas
podem ser publicadas apenas internamente na organização ou, a critério da
organização, algumas ou todas podem ser publicadas externamente. As métricas
fortemente sugeridas incluem:
* O número de contribuições ao kernel no upstream por equipe ou organização
(por exemplo, todas as pessoas que se reportam a um gerente, diretor ou
vice-presidente).
* A porcentagem de desenvolvedores de kernel que fizeram contribuições no
upstream em relação ao total de desenvolvedores de kernel na organização.
* O intervalo de tempo entre os kernels usados nos servidores e/ou produtos
da organização e a data de publicação do kernel upstream no qual o kernel
interno se baseia.
* O número de commits fora da árvore (out-of-tree) presentes nos kernels
internos.
Nível 4
=======
* Os Engenheiros de Software são incentivados a dedicar uma parte do seu tempo
de trabalho focados no Trabalho no Upstream, o qual é definido como a revisão
de patches, atuação em comitês de programa, melhoria da infraestrutura central
do projeto -- como escrita ou manutenção de testes, redução de dívida técnica
no upstream, escrita de documentação, etc.
* Os Engenheiros de Software recebem apoio para ajudar a organizar conferências
relacionadas ao Linux.
* As organizações considerarão o feedback dos membros da comunidade em
avaliações de desempenho oficiais.
Nível 5
=======
* O desenvolvimento de kernel no upstream é considerado um cargo formal, com
pelo menos um terço do tempo do engenheiro dedicado à realização de Trabalho
no Upstream.
* As organizações buscarão ativamente o feedback dos membros da comunidade como
um fator nas avaliações de desempenho oficiais.
* As organizações relatarão internamente e de forma regular a proporção entre o
Trabalho no Upstream e o trabalho focado em atingir diretamente os objetivos
de negócios.

View File

@@ -0,0 +1,125 @@
.. SPDX-License-Identifier: GPL-2.0
====
CVEs
====
Os números Common Vulnerabilities and Exposure (CVE®) foram desenvolvidos
como uma forma inequívoca de identificar, definir e catalogar vulnerabilidades
de segurança divulgadas publicamente. Com o tempo, sua utilidade diminuiu em
relação ao projeto do kernel, e os números CVE foram frequentemente atribuídos
de formas inadequadas e por motivos inadequados. Por causa disso, a comunidade
de desenvolvimento do kernel tendeu a evitá-los. No entanto, a combinação da
pressão contínua para atribuir CVEs e outras formas de identificadores de
segurança, e abusos contínuos por indivíduos e empresas de fora da comunidade
do kernel, deixou claro que a comunidade do kernel deve controlar
essas atribuições.
A equipe de desenvolvedores do kernel Linux tem a capacidade de atribuir CVEs
para possíveis problemas de segurança do kernel Linux. Essa atribuição é
independente do processo normal de relato de bugs de segurança do kernel
Linux, descrito em :ref:`securitybugs`.
Uma lista de todos os CVEs atribuídos ao kernel Linux pode ser encontrada nos
arquivos da lista de discussão linux-cve, como visto em
https://lore.kernel.org/linux-cve-announce/. Para receber notificações sobre
os CVEs atribuídos, por favor, `inscreva-se
<https://subspace.kernel.org/subscribing.html>`_ nessa lista de discussão.
Processo
========
Como parte do processo normal de lançamento estável, alterações do kernel que
são potencialmente problemas de segurança são identificadas pelos
desenvolvedores responsáveis pelas atribuições de números CVE e recebem
automaticamente números CVE. Essas atribuições são publicadas na lista de
discussão linux-cve-announce como anúncios frequentes.
Observe que, devido à camada em que o kernel Linux se encontra em um sistema,
quase qualquer bug pode ser explorável para comprometer a segurança do kernel,
mas a possibilidade de exploração muitas vezes não é evidente quando o bug é
corrigido. Por causa disso, a equipe de atribuição de CVEs é excessivamente
cautelosa e atribui números CVE a qualquer correção de bug que identificar.
Isso explica o número aparentemente grande de CVEs emitidos pela equipe do
kernel Linux.
Se a equipe de atribuição de CVEs deixar passar uma correção específica que
qualquer usuário considere que deveria receber um CVE, por favor envie um
e-mail para <cve@kernel.org> e a equipe trabalhará com você nisso. Observe
que nenhum possível problema de segurança deve ser enviado para esse alias;
ele é SOMENTE para atribuição de CVEs a correções que já estejam em árvores de
kernel lançadas. Se você acredita ter encontrado um problema de segurança
ainda
não corrigido, por favor siga o processo normal de relato de bugs de segurança do kernel
Linux, descrito em :ref:`securitybugs`.
Nenhum CVE será atribuído automaticamente para problemas de segurança ainda
não corrigidos no kernel Linux; a atribuição só acontecerá automaticamente
depois que uma correção estiver disponível e aplicada a uma árvore de kernel
estável, e ela será rastreada dessa forma pelo ID do commit git da correção
original. Se alguém desejar que um CVE seja atribuído antes que um problema
seja resolvido com um commit, por favor entre em contato com a equipe de
atribuição de CVEs do kernel em <cve@kernel.org> para obter um identificador
atribuído a partir de seu lote de identificadores reservados.
Nenhum CVE será atribuído para qualquer problema encontrado em uma versão do
kernel que atualmente não esteja sendo mantida ativamente pela equipe de kernel
Stable/LTS. Uma lista dos ramos de kernel atualmente suportados pode ser
encontrada em https://kernel.org/releases.html
Contestações de CVEs atribuídos
===============================
A autoridade para contestar ou modificar um CVE atribuído a uma alteração
específica do kernel pertence exclusivamente aos mantenedores do subsistema
relevante afetado. Esse princípio garante um alto grau de precisão e
responsabilização no relato de vulnerabilidades. Somente esses indivíduos, com
profundo conhecimento técnico e conhecimento íntimo do subsistema, podem
avaliar de forma eficaz a validade e o escopo de uma vulnerabilidade relatada e
determinar sua designação CVE apropriada. Qualquer tentativa de modificar ou
contestar um CVE fora dessa autoridade designada pode levar a confusão, relato
impreciso e, em última análise, sistemas comprometidos.
CVEs inválidos
==============
Se um problema de segurança for encontrado em um kernel Linux que é suportado
apenas por uma distribuição Linux devido às alterações feitas por essa
distribuição, ou porque a distribuição oferece suporte a uma versão do kernel
que não é mais uma das versões suportadas pelo kernel.org, então um CVE não
pode ser atribuído pela equipe de CVEs do kernel Linux e deve ser solicitado à
própria distribuição Linux.
Qualquer CVE atribuído ao kernel Linux para uma versão de kernel
ativamente suportada, por qualquer grupo que não seja a equipe de atribuição de
CVEs do kernel, não deve ser tratado como um CVE válido. Por favor, notifique
a equipe de atribuição de CVEs do kernel em <cve@kernel.org> para que ela
possa trabalhar para invalidar essas entradas por meio do processo de remediação
da CNA.
Aplicabilidade de CVEs específicos
==================================
Como o kernel Linux pode ser usado de múltiplas maneiras, com diversas
formas de acesso por usuários externos, ou sem nenhum acesso, a
aplicabilidade de qualquer CVE específico cabe ao usuário do Linux determinar;
isso não cabe à equipe de atribuição de CVEs. Por favor, não entre em contato
conosco para tentar determinar a aplicabilidade de qualquer CVE específico.
Além disso, como a árvore de códigos-fonte é muito grande, e cada sistema usa
apenas um pequeno subconjunto dessa árvore, o usuário do Linux deve estar
ciente de que grandes quantidades de CVEs atribuídos não são relevantes para
seus sistemas.
Em resumo, não conhecemos o seu caso de uso e não sabemos quais partes do
kernel você usa, portanto não há como determinarmos se um CVE específico é
relevante para o seu sistema.
Como sempre, o melhor é adotar todas as alterações de kernel lançadas, pois
elas são testadas em conjunto como um todo unificado por muitos membros da
comunidade, e não como alterações individuais selecionadas. Observe também que,
para muitos bugs, a solução do problema geral não é encontrada em uma única
alteração, mas pela soma de muitas correções umas sobre as outras. Idealmente,
CVEs serão atribuídos a todas as correções de todos os problemas, mas às vezes
podemos deixar de perceber algumas correções; portanto, presuma que algumas alterações
sem um CVE atribuído podem ser relevantes para adotar.

View File

@@ -0,0 +1,422 @@
.. SPDX-License-Identifier: GPL-2.0
========================================================================
Interfaces, recursos de linguagem, atributos e convenções obsoletos
========================================================================
Em um mundo perfeito, seria possível converter todas as instâncias de alguma
API obsoleta para a nova API e remover completamente a API antiga em um único
ciclo de desenvolvimento. No entanto, devido ao tamanho do kernel, à hierarquia
de manutenção e ao cronograma, nem sempre é viável realizar esse tipo de
conversão de uma só vez. Isso significa que novas instâncias podem acabar
entrando no kernel enquanto as antigas estão sendo removidas, apenas aumentando
o volume de trabalho para remover a API. A fim de instruir os desenvolvedores
sobre o que se tornou obsoleto e o porquê, esta lista foi criada para servir de
referência quando o uso de elementos obsoletos for proposto para inclusão no
kernel.
__deprecated
------------
Embora este atributo marque visualmente uma interface como obsoleta, ele `não
gera mais avisos durante as compilações
<https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_ porque
um dos objetivos permanentes do kernel é compilar sem avisos (*warnings*), e
ninguém estava de fato agindo para remover essas interfaces obsoletas. Embora o
uso de `__deprecated` seja útil para sinalizar uma API antiga em um arquivo de
cabeçalho (*header file*), não é a solução completa. Tais interfaces devem ser
totalmente removidas do kernel ou adicionadas a este arquivo para desestimular
outros desenvolvedores de usá-las no futuro.
BBUG() e BUG_ON()
-----------------
Em vez disso, use WARN() e WARN_ON() e trate a condição de erro "impossível"
da forma mais amigável possível. Embora a família de APIs BUG() tenha sido
originalmente projetada para agir como uma asserção de "situação impossível" e
eliminar uma thread do kernel de forma "segura", ela se mostrou arriscada
demais. (Por exemplo: "Em que ordem os bloqueios precisam ser liberados? Os
diversos estados foram restaurados?") Muito frequentemente, o uso de BUG() vai
desestabilizar o sistema ou travá-lo por completo, o que torna impossível
depurar ou até mesmo obter relatórios de travamento (*crash reports*) viáveis.
Linus tem opiniões `muito fortes
<https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_
`sobre isso
<https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_.
Note que a família WARN() só deve ser usada para situações que "espera-se que
sejam inacessíveis". Se você quiser alertar sobre situações que são
"acessíveis, mas indesejáveis", use a família de funções pr_warn(). Os
administradores do sistema podem ter configurado o sysctl *panic_on_warn* para
garantir que seus sistemas não continuem executando diante de condições
"inacessíveis". (Para exemplos, veja commits como `este aqui
<https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_.)
Aritmética explícita em argumentos do alocador
----------------------------------------------
Cálculos dinâmicos de tamanho (especialmente multiplicação) não devem ser
realizados em argumentos de funções de alocação de memória (ou similares)
devido ao risco de estouro de capacidade (*overflow*). Isso poderia fazer com
que os valores dessem a volta (*wrap around*), resultando em uma alocação menor
do que o esperado pelo chamador. O uso dessas alocações pode levar a estouros
lineares na memória heap e a outros comportamentos incorretos. (Uma exceção a
isso são valores literais onde o compilador pode emitir um aviso se houver
risco de estouro. No entanto, a maneira preferível nesses casos é refatorar o
código conforme sugerido abaixo para evitar a aritmética explícita.)
Por exemplo, não use ``count * size`` como argumento, como em::
foo = kmalloc(count * size, GFP_KERNEL);
Em vez disso, a forma de dois fatores do alocador deve ser utilizada::
foo = kmalloc_array(count, size, GFP_KERNEL);
Especificamente, kmalloc() pode ser substituído por kmalloc_array(), e
kzalloc() pode ser substituído por kcalloc().
Se nenhuma forma de dois fatores estiver disponível, os auxiliares de
saturação em estouro (*saturate-on-overflow*) devem ser usados::
bar = dma_alloc_coherent(dev, array_size(count, size), &dma, GFP_KERNEL);
Outro caso comum a ser evitado é calcular o tamanho de uma estrutura com uma
matriz final de outras estruturas, como em::
header = kzalloc(sizeof(*header) + count * sizeof(*header->item),
GFP_KERNEL);
Em vez disso, use o auxiliar::
header = kzalloc(struct_size(header, item, count), GFP_KERNEL);
.. note:: Se você estiver usando struct_size() em uma estrutura que contém uma
matriz de comprimento zero ou de um único elemento como membro final,
refatore o uso dessa matriz e mude para um `membro de matriz flexível
<#zero-length-and-one-element-arrays>`_ em seu lugar.
Para outros cálculos, faça a composição usando os auxiliares size_mul(),
size_add() e size_sub(). Por exemplo, no caso de::
foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL);
Em vez disso, use os auxiliares::
foo = krealloc(size_add(current_size,
size_mul(chunk_size,
size_sub(count, 3))), GFP_KERNEL);
Para mais detalhes, veja também array3_size() e flex_array_size(), bem como as
funções relacionadas das famílias check_mul_overflow(), check_add_overflow(),
check_sub_overflow() e check_shl_overflow().\
simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull()
----------------------------------------------------------------------
As funções simple_strtol(), simple_strtoll(), simple_strtoul() e
simple_strtoull() ignoram explicitamente estouros de capacidade (*overflows*),
o que pode levar a resultados inesperados nos chamadores. As respectivas
funções kstrtol(), kstrtoll(), kstrtoul() e kstrtoull() tendem a ser as
substitutas corretas, embora se deva notar que estas exigem que a string seja
terminada em NUL ou em nova linha (*newline*).
strcpy()
--------
A função strcpy() não realiza verificação de limites no buffer de destino.
Isso pode resultar em estouros lineares além do final do buffer, levando a todo
tipo de comportamentos incorretos. Embora ``CONFIG_FORTIFY_SOURCE=y`` e várias
opções do compilador ajudem a reduzir o risco de usar esta função, não há uma
boa razão para adicionar novos usos dela. A substituta segura é strscpy(),
embora se deva ter cuidado nos casos em que o valor de retorno de strcpy() era
utilizado, já que strscpy() não retorna um ponteiro para o destino, mas sim a
quantidade de bytes não-NUL copiados (ou um código de erro errno negativo quando
ocorre truncamento).
strncpy()
---------
A função strncpy() foi removida do kernel. Todos os chamadores antigos foram
migrados para alternativas mais seguras.
A função strncpy() não garantia a terminação em NUL do buffer de destino,
levando a estouros de leitura linear e outros comportamentos incorretos. Ela
também preenchia incondicionalmente o destino com NUL, o que representava uma
penalidade de desempenho desnecessária para chamadores que usavam apenas
strings terminadas em NUL. Devido aos seus diversos comportamentos, ela era uma
API ambígua para determinar qual era a real intenção do autor ao realizar a
cópia.
As substitutas para strncpy() são:
- strscpy() quando o destino deve ser terminado em NUL.
- strscpy_pad() quando o destino deve ser terminado em NUL e preenchido com
zeros (por exemplo, estruturas que cruzam fronteiras de privilégio).
- memtostr() para destinos terminados em NUL a partir de origens de largura
fixa não terminadas em NUL (com o atributo ``__nonstring`` na origem).
- memtostr_pad() para o mesmo caso anterior, mas com preenchimento de zeros.
- strtomem() para destinos de largura fixa não terminados em NUL, com o
atributo ``__nonstring`` no destino.
- strtomem_pad() para destinos não terminados em NUL que também precisam de
preenchimento com zeros.
- memcpy_and_pad() para cópias limitadas a partir de origens potencialmente não
terminadas, onde o tamanho do destino é um valor definido em tempo de
execução (*runtime*).
strlcpy()
---------
A função strlcpy() lê primeiro todo o buffer de origem (já que o valor de
retorno deve corresponder ao de strlen()). Essa leitura pode exceder o limite
de tamanho do destino. Isso é ineficiente e pode levar a estouros de leitura
linear se a string de origem não for terminada em NUL. A substituta segura é
strscpy(), embora se deva ter cuidado nos casos em que o valor de retorno de
strlcpy() é utilizado, já que strscpy() retornará valores negativos de errno
quando houver truncamento.
Especificador de formato %p
----------------------------
Tradicionalmente, o uso de "%p" em strings de formatação causava falhas de
exposição de endereços reais no dmesg, proc, sysfs, etc. Em vez de deixar esses
endereços expostos a explorações, todos os usos de "%p" no kernel agora são
exibidos como um valor hash, tornando-os inúteis para fins de endereçamento.
Novos usos de "%p" não devem ser adicionados ao kernel. Para endereços de texto,
usar "%pS" costuma ser melhor, pois exibe o nome do símbolo, que é muito mais
útil. Para quase todo o restante, simplesmente não adicione "%p" de forma
alguma.
Parafraseando as diretrizes atuais do Linus `guidance
<https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_:
- Se o valor hash de "%p" é inútil, pergunte a si mesmo se o ponteiro em si é
importante. Talvez ele deva ser removido por completo?
- Se você realmente acredita que o valor real do ponteiro é importante, por que
algum estado do sistema ou nível de privilégio do usuário seria considerado
"especial"? Se você acha que pode justificar isso (em comentários e no log de
commit) de forma sólida o suficiente para resistir ao escrutínio do Linus,
talvez possa usar "%px", certificando-se de aplicar permissões adequadas.
Se você estiver depurando algo em que a geração de hash de "%p" esteja causando
problemas, é possível inicializar o sistema temporariamente com a opção de
depuração "`no_hash_pointers
<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_".
Matrizes de Tamanho Variável (VLAs)
-----------------------------------
O uso de VLAs (Variable Length Arrays) na pilha de execução gera um código de
máquina muito pior do que matrizes de tamanho estático na pilha. Embora esses
problemas significativos de `desempenho
<https://git.kernel.org/linus/02361bc77888>`_ sejam motivo suficiente para
eliminar as VLAs, elas também representam um risco de segurança. O crescimento
dinâmico de uma matriz na pilha pode exceder a memória restante no segmento da
pilha. Isso pode levar a um travamento, à possível sobrescrita de dados
sensíveis no final da pilha (quando compilado sem ``CONFIG_THREAD_INFO_IN_TASK=y``)
ou à sobrescrita de posições de memória adjacentes à pilha (quando compilado sem
``CONFIG_VMAP_STACK=y``).
Passagem direta implícita no switch case (fall-through)
-------------------------------------------------------
A linguagem C permite que o fluxo de execução de um bloco switch passe
diretamente para o próximo caso (fall-through) quando uma instrução "break"
está ausente ao final de um caso. No entanto, isso introduz ambiguidade no
código, pois nem sempre fica claro se o "break" ausente é intencional ou um bug.
Por exemplo, não é óbvio apenas olhando para o código se o ``STATE_ONE`` foi
intencionalmente projetado para passar diretamente para o ``STATE_TWO``::
switch (value) {
case STATE_ONE:
do_something();
case STATE_TWO:
do_other();
break;
default:
WARN("unknown state");
}
Como há uma longa lista de falhas `causadas pela ausência de instruções "break"
<https://cwe.mitre.org/data/definitions/484.html>`_, não permitimos mais a
passagem direta implícita. Para identificar os casos de passagem direta
intencionais, adotamos a macro pseudo-palavra-chave "fallthrough", que se
expande para a extensão do gcc `__attribute__((__fallthrough__))
<https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_. (Quando a
sintaxe ``[[fallthrough]]`` do C17/C18 for suportada de forma mais ampla por
compiladores C, analisadores estáticos e IDEs, poderemos mudar para o uso dessa
sintaxe para a pseudo-palavra-chave da macro.)
Todos os blocos de switch/case devem terminar com um dos seguintes elementos:
* break;
* fallthrough;
* continue;
* goto <rótulo>;
* return [expressão];
Matrizes de comprimento zero e de um único elemento
----------------------------------------------------
Há uma necessidade frequente no kernel de fornecer uma maneira de declarar uma
estrutura com um conjunto de elementos finais de tamanho dinâmico. O código do
kernel deve sempre usar `"membros de matriz flexível"
<https://en.wikipedia.org/wiki/Flexible_array_member>`_ para esses casos. O
estilo antigo de matrizes de um único elemento ou de comprimento zero não deve
mais ser utilizado.
No código C mais antigo, elementos finais de tamanho dinâmico eram declarados
especificando uma matriz de um elemento ao final de uma estrutura::
struct something {
size_t count;
struct foo items[1];
};
Isso levava a cálculos de tamanho frágeis via sizeof() (que exigiam a subtração
do tamanho do elemento final único para obter o tamanho correto do "cabeçalho").
Uma `extensão GNU C <https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ foi
introduzida para permitir matrizes de comprimento zero, a fim de evitar esses
problemas de cálculo de tamanho::
struct something {
size_t count;
struct foo items[0];
};
No entanto, isso trouxe outros problemas e não resolveu algumas limitações de
ambos os estilos, como a incapacidade de detectar quando tal matriz é usada
acidentalmente *fora* do final de uma estrutura (o que poderia ocorrer
diretamente, ou quando tal estrutura estava contida em unions, estruturas de
estruturas, etc.).
O padrão C99 introduziu os "membros de matriz flexível", nos quais a declaração
da matriz simplesmente não possui um tamanho numérico::
struct something {
size_t count;
struct foo items[];
};
Esta é a maneira como o kernel espera que elementos finais de tamanho dinâmico
sejam declarados. Isso permite que o compilador gere erros quando a matriz
flexível não for o último elemento da estrutura, o que ajuda a evitar que bugs
de `comportamento indefinido
<https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_ sejam
introduzidos inadvertidamente na base de código. Também permite que o
compilador analise corretamente os tamanhos das matrizes (via sizeof(),
``CONFIG_FORTIFY_SOURCE`` e ``CONFIG_UBSAN_BOUNDS``). Por exemplo, não existe um
mecanismo que nos alerte de que a seguinte aplicação do operador sizeof() a uma
matriz de comprimento zero sempre resulta em zero::
struct something {
size_t count;
struct foo items[0];
};
struct something *instance;
instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
instance->count = count;
size = sizeof(instance->items) * instance->count;
memcpy(instance->items, source, size);
Na última linha do código acima, ``size`` acaba sendo ``zero``, quando se
poderia pensar que ele representaria o tamanho total em bytes da memória
dinâmica recentemente alocada para a matriz final ``items``. Aqui estão alguns
exemplos deste problema: `link 1
<https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_,
`link 2
<https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_.
Em vez disso, `membros de matriz flexível têm tipo incompleto e, portanto, o
operador sizeof() não pode ser aplicado
<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, de modo que qualquer
uso incorreto de tais operadores será imediatamente percebido em tempo de
compilação.
Em relação às matrizes de um único elemento, é preciso estar muito ciente de que
`tais matrizes ocupam pelo menos o mesmo espaço que um único objeto daquele tipo
<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ e, portanto, contribuem
para o tamanho da estrutura que as contém. Isso é propício a erros sempre que se
deseja calcular o tamanho total da memória dinâmica a ser alocada para uma
estrutura que contém uma matriz desse tipo como membro::
struct something {
size_t count;
struct foo items[1];
};
struct something *instance;
instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL);
instance->count = count;
size = sizeof(instance->items) * instance->count;
memcpy(instance->items, source, size);
No exemplo acima, foi necessário lembrar de calcular ``count - 1`` ao usar o
auxiliar struct_size(); caso contrário, teríamos alocado memória --de forma não
intencional-- para um objeto ``items`` a mais. A maneira mais limpa e menos
sujeita a erros de implementar isso é através do uso de um `membro de matriz
flexível`, em conjunto com os auxiliares struct_size() e flex_array_size()::
struct something {
size_t count;
struct foo items[];
};
struct something *instance;
instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
instance->count = count;
memcpy(instance->items, source, flex_array_size(instance, items, instance->count));
Existem dois casos especiais de substituição nos quais o auxiliar
DECLARE_FLEX_ARRAY() precisa ser utilizado. (Note que ele é nomeado
__DECLARE_FLEX_ARRAY() para uso em cabeçalhos de UAPI.) Esses casos ocorrem
quando a matriz flexível está sozinha em uma estrutura ou faz parte de uma
union. Isso não é permitido pela especificação C99, mas sem justificativa
técnica (como pode ser visto tanto pelo uso existente de tais matrizes nesses
locais quanto pela solução alternativa que DECLARE_FLEX_ARRAY() adota). Por
exemplo, para converter isto::
struct something {
...
union {
struct type1 one[0];
struct type2 two[0];
};
};
O auxiliar deve ser utilizado::
struct something {
...
union {
DECLARE_FLEX_ARRAY(struct type1, one);
DECLARE_FLEX_ARRAY(struct type2, two);
};
};
Atribuições diretas de kmalloc para objetos struct
--------------------------------------------------
Realizar atribuições diretas (*open-coded*) de alocações da família kmalloc()
impede que o kernel (e o compilador) consigam examinar o tipo da variável que
está recebendo a atribuição, o que limita qualquer introspecção relacionada que
possa ajudar com alinhamento, estouros de capacidade (*wrap-around*) ou
proteções adicionais (*hardening*). A família de macros kmalloc_obj() fornece
essa introspecção, que pode ser usada para os padrões de código comuns de
alocações de objetos únicos, de matrizes ou de objetos flexíveis. Por exemplo,
estas atribuições diretas::
ptr = kmalloc(sizeof(*ptr), gfp);
ptr = kzalloc(sizeof(*ptr), gfp);
ptr = kmalloc_array(count, sizeof(*ptr), gfp);
ptr = kcalloc(count, sizeof(*ptr), gfp);
ptr = kmalloc(struct_size(ptr, flex_member, count), gfp);
ptr = kmalloc(sizeof(struct foo), gfp);
tornam-se, respectivamente::
ptr = kmalloc_obj(*ptr [, gfp] );
ptr = kzalloc_obj(*ptr [, gfp] );
ptr = kmalloc_objs(*ptr, count [, gfp] );
ptr = kzalloc_objs(*ptr, count [, gfp] );
ptr = kmalloc_flex(*ptr, flex_member, count [, gfp] );
__auto_type ptr = kmalloc_obj(struct foo [, gfp] );
O argumento gfp é opcional, sendo o valor padrão GFP_KERNEL. Se
``ptr->flex_member`` estiver anotado com __counted_by(), a alocação falhará
automaticamente caso ``count`` seja maior do que o valor máximo representável
que pode ser armazenado no membro contador associado a ``flex_member``.

View File

@@ -20,3 +20,8 @@ conhecimento profundo de programação de kernel para ser compreendida.
1.Intro
2.Process
3.Early-stage
4.Coding
5.Posting
6.Followthrough
7.AdvancedTopics
8.Conclusion

View File

@@ -0,0 +1,368 @@
.. SPDX-License-Identifier: GPL-2.0
Informações sobre clientes de email para Linux
==============================================
Git
---
Hoje em dia a maioria dos desenvolvedores usa ``git send-email`` em vez de
clientes de email comuns. A página de manual desse comando é bem útil. No lado
de quem recebe, os mantenedores usam ``git am`` para aplicar os patches.
Se você é novo no ``git``, envie seu primeiro patch para si mesmo. Salve-o
como texto bruto, incluindo todos os cabeçalhos. Execute ``git am raw_email.txt``
e então revise o changelog com ``git log``. Quando isso funcionar, envie o
patch para a(s) lista(s) de discussão apropriada(s).
Preferências Gerais
-------------------
Os patches para o kernel Linux são enviados por email, preferencialmente como
texto inline no corpo da mensagem. Alguns mantenedores aceitam anexos, mas,
nesse caso, os anexos devem ter o content-type ``text/plain``. Contudo, anexos
são, em geral, desaconselhados porque dificultam citar trechos do patch durante
o processo de revisão.
Também é altamente recomendável que você use plain text no corpo do email, tanto
para patches quanto para outras mensagens. https://useplaintext.email pode ser
útil para obter informações sobre como configurar seu cliente de email preferido,
além de listar clientes de email recomendados caso você ainda não tenha preferência.
Clientes de email usados para patches do kernel Linux devem enviar o texto do
patch sem alterações. Por exemplo, eles não devem modificar ou apagar tabs ou
espaços, mesmo no início ou no fim das linhas.
Não envie patches com ``format=flowed``. Isso pode causar quebras de linha
inesperadas e indesejadas.
Não deixe seu cliente de email fazer quebra automática de linha para você.
Isso também pode corromper seu patch.
Clientes de email não devem modificar a codificação do conjunto de caracteres do
texto. Patches enviados por email devem usar apenas codificação ASCII ou UTF-8.
Se você configurar seu cliente de email para enviar mensagens com codificação
UTF-8, você evita alguns possíveis problemas de charset.
Clientes de email devem gerar e manter "References:" ou "In-Reply-To:"
cabeçalhos para que o encadeamento de mensagens não seja quebrado.
Copiar e colar (ou recortar e colar) geralmente não funciona para patches
porque tabs são convertidos em espaços. Usar xclipboard, xclip e/ou xcutsel
pode funcionar, mas é melhor testar isso você mesmo ou simplesmente evitar
copiar e colar.
Não use assinaturas PGP/GPG em emails que contenham patches. Isso quebra muitos
scripts que leem e aplicam os patches.
(Isso deve ser corrigível.)
É uma boa ideia enviar um patch para si mesmo, salvar a mensagem recebida e
aplicá-la com sucesso com o comando 'patch' antes de enviar patches para as
listas de discussão do Linux.
Algumas dicas de clientes de email (MUA)
----------------------------------------
Aqui estão algumas dicas específicas de configuração de MUA para editar e enviar
patches para o kernel Linux. Estas dicas não pretendem ser resumos completos da
configuração dos pacotes de software.
Legenda:
- TUI = Interface de Usuário Baseada em Texto
- GUI = Interface Gráfica de Usuário
Alpine (TUI)
************
Opções de configuração:
Na seção :menuselection:`Preferências de Envio`:
- :menuselection:`Não Envie Texto com Quebra de Linha Automática` deve estar ``habilitado``
- :menuselection:`Remover Espaços em Branco Antes de Enviar` deve estar ``desabilitado``
Ao compor a mensagem, o cursor deve ser posicionado onde o patch deverá aparecer,
e então pressionar `CTRL-R` permite especificar o arquivo de patch a ser
inserido na mensagem.
Claws Mail (GUI)
****************
Funciona. Algumas pessoas usam isso com sucesso para patches.
Para inserir um patch, use :menuselection:`Mensagem-->Inserir Arquivo`(`CTRL-I`)
ou um editor externo.
Se o patch inserido precisar ser editado na janela de composição do
Claws, a opção "Quebra automática" em
:menuselection:`Configuração-->Preferências-->Escrever-->Quebra de linha`
deve estar desabilitada.
Evolution (GUI)
***************
Algumas pessoas usam isso com sucesso para patches.
Ao compor o e-mail, selecione: Preformatado
em :menuselection:`Formatar-->Estilo de Parágrafo-->Preformatado` (`CTRL-7`)
ou na barra de ferramentas
Depois use:
:menuselection:`Inserir-->Arquivo de Texto...` (`ALT-N x`)
para inserir o patch.
Você também pode usar ``diff -Nru old.c new.c | xclip``, selecionar
:menuselection:`Preformatado`, depois colar com o botão do meio.
Kmail (GUI)
***********
Algumas pessoas usam o KMail com sucesso para patches.
A configuração padrão de não compor em HTML é apropriada; não a habilite.
Ao compor um email, em opções, desmarque “quebra de linha automática”. A única
desvantagem é que qualquer texto que você digitar no email não será quebrado
automaticamente, então você terá que quebrar manualmente o texto antes do patch.
A maneira mais fácil é compor o email com quebra de linha automática habilitado,
depois salvá-lo como rascunho. Depois de abri-lo novamente dos rascunhos, ele
estará com quebras de linha rígidas e você poderá desmarcar “quebra de linha
automática” sem perder a quebra existente.
No final do seu email, coloque o delimitador de patch comumente usado antes de
inserir o patch: três hífens (``---``).
Então, no menu :menuselection:`Mensagem`, selecione :menuselection:`inserir arquivo`
e escolha o seu patch. Como benefício adicional, você pode personalizar a barra
de ferramentas de criação de mensagens e colocar o ícone :menuselection:`inserir arquivo` lá.
Deixe a janela do compositor larga o suficiente para que nenhuma linha seja
quebrada. A partir do KMail 1.13.5 (KDE 4.5.4), o KMail aplica quebra de linha
ao enviar o email se as linhas quebrarem na janela do compositor. Ter a quebra de
linha desativada no menu Opções não é suficiente. Por isso se o seu patch tiver
linhas muito longas, você deve deixar a janela do seu compositor bem larga antes
de enviar o email. Veja: https://bugs.kde.org/show_bug.cgi?id=174034
Você pode assinar anexos com GPG com segurança, mas texto em linha é preferido
para patches, então não os assine com GPG. Assinar patches que foram inseridos
como texto em linha torna mais difícil extraí-los de sua codificação 7 bits.
Se você absolutamente precisar enviar patches como anexos em vez de inseri-los
como texto, clique com o botão direito no anexo e selecione
:menuselection:`propriedades`, e destaque :menuselection:`Sugerir exibição automática`
para fazer o anexo ser exibido como texto inserido e ficar mais fácil de
visualizar.
Ao salvar patches enviados como texto inserido, selecione o email que contém o
patch no painel da lista de mensagens, clique com o botão direito e selecione
:menuselection:`salvar como`. Você pode usar o email inteiro sem alterações como
patch se ele tiver sido composto corretamente. Emails são salvos como leitura e
escrita apenas para o usuário, então você terá que alterar as permissões para
torná-los legíveis por grupo e por todos se copiá-los para outro lugar.
Lotus Notes (GUI)
*****************
Fuja dele.
IBM Verse (Web GUI)
*******************
Veja Lotus Notes.
Mutt (TUI)
**********
Muitos desenvolvedores Linux usam ``mutt``, então deve funcionar muito bem.
O mutt não vem com editor, então qualquer editor que você use deve ser usado de
forma que não haja quebras de linha automáticas. A maioria dos editores tem uma
opção :menuselection:`Inserir Arquivo` que insere o conteúdo de um arquivo sem
alterações.
Para usar ``vim`` com o mutt::
set editor="vi"
Se estiver usando xclip, digite o comando::
:set paste
antes do botão do meio ou shift-insert ou use::
:r filename
se você quiser incluir o patch inline.
(a)ttach funciona bem sem ``set paste``.
Você também pode gerar patches com ``git format-patch`` e depois usar o Mutt
para enviá-los::
$ mutt -H 0001-some-bug-fix.patch
Opções de configuração:
Deve funcionar com as configurações padrão. No entanto, é uma boa ideia definir
o ``send_charset`` como::
set send_charset="us-ascii:utf-8"
O Mutt é altamente personalizável. Aqui está uma configuração mínima para
começar a usar o Mutt para enviar patches pelo Gmail::
# .muttrc
# ================ IMAP ====================
set imap_user = 'seuusuario@gmail.com'
set imap_pass = 'suasenha'
set spoolfile = imaps://imap.gmail.com/INBOX
set folder = imaps://imap.gmail.com/
set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
# ================ SMTP ====================
set smtp_url = "smtp://usuario@smtp.gmail.com:587/"
set smtp_pass = $imap_pass
set ssl_force_tls = yes # Exige conexão criptografada
# ================ Composição ====================
set editor = `echo \$EDITOR`
set edit_headers = yes # Exibe os cabeçalhos ao editar
set charset = UTF-8 # valor de $LANG; também usado como
# fallback para send_charset
# Remetente, endereço de e-mail e linha de assinatura devem
# corresponder
unset use_domain # porque joe@localhost é constrangedor
set realname = "SEU NOME"
set from = "usuario@gmail.com"
set use_from = yes
A documentação do Mutt tem muito mais informações:
https://gitlab.com/muttmua/mutt/-/wikis/UseCases/Gmail
http://www.mutt.org/doc/manual/
Pine (TUI)
**********
O Pine já teve alguns problemas de truncamento de espaços em branco no passado,
mas isso deve estar todo corrigido agora.
Use o alpine (sucessor do pine) se possível.
Opções de configuração:
- ``quell-flowed-text`` é necessário para versões recentes
- a opção ``no-strip-whitespace-before-send`` é necessária
Sylpheed (GUI)
**************
- Funciona bem para inserir texto inline (ou usando anexos).
- Permite o uso de um editor externo.
- É lento em pastas grandes.
- Não fará autenticação TLS SMTP sobre uma conexão não-SSL.
- Tem uma barra de régua útil na janela de composição.
- Adicionar endereços ao catálogo de endereços não reconhece corretamente o nome
de exibição.
Thunderbird (GUI)
*****************
O Thunderbird é um clone do Outlook que gosta de bagunçar o texto, mas há formas
de convencê-lo a se comportar.
Depois de fazer as modificações, incluindo a instalação das extensões, você
precisa reiniciar o Thunderbird.
- Permitir o uso de um editor externo:
A forma mais fácil de trabalhar com patches no Thunderbird é usar extensões
que abrem seu editor externo favorito.
Aqui estão alguns exemplos de extensões capazes de fazer isso.
- "Editor Externo Reativado"
https://github.com/Frederick888/external-editor-revived
https://addons.thunderbird.net/en-GB/thunderbird/addon/external-editor-revived/
É necessário instalar um "host de mensagens nativas".
Leia a wiki, que pode ser encontrada aqui:
https://github.com/Frederick888/external-editor-revived/wiki
- "Editor Externo"
https://github.com/exteditor/exteditor
Para isso, baixe e instale a extensão, depois abra a janela de
:menuselection:`compor`, adicione um botão para ela usando
:menuselection:`Visualizar-->Barras de Ferramentas-->Personalizar...`
e então basta clicar no novo botão quando quiser usar o editor externo.
Observe que o "Editor Externo" exige que seu editor não faça fork, ou seja,
o editor não deve retornar antes de fechar. Pode ser necessário passar flags
adicionais ou alterar as configurações do seu editor. Principalmente se você
estiver usando o gvim, deve passar a opção -f para o gvim colocando
``/usr/bin/gvim --nofork"`` (se o binário estiver em ``/usr/bin``) no campo
de editor de texto nas configurações de :menuselection:`editor externo`. Se
estiver usando outro editor, consulte seu manual para descobrir como fazer isso.
Para colocar juízo no editor interno, faça o seguinte:
- Edite as configurações do Thunderbird para que ele não use ``format=flowed``!
Vá até a janela principal e encontre o botão do menu suspenso principal.
:menuselection:`Menu Principal-->Preferências-->Geral-->Editor de Configurações...`
para abrir o editor de registro do Thunderbird.
- Defina ``mailnews.send_plaintext_flowed`` como ``false``
- Altere ``mailnews.wraplength`` de ``72`` para ``0`` **ou** instale a
extensão "Toggle Line Wrap"
https://github.com/jan-kiszka/togglelinewrap
https://addons.thunderbird.net/thunderbird/addon/toggle-line-wrap
para controlar esse registro dinamicamente.
- Não escreva mensagens em HTML! Vá até a janela principal
:menuselection:`Menu Principal-->Configurações da Conta-->suaconta@servidor.algo-->Composição e Endereçamento`!
Lá você pode desabilitar a opção "Compor mensagens em formato HTML".
- Abra mensagens apenas como texto simples! Vá até a janela principal
:menuselection:`Menu Principal-->Visualizar-->Corpo da Mensagem Como-->Texto Simples`!
TkRat (GUI)
***********
Funciona. Use "Inserir arquivo..." ou um editor externo.
Gmail (Web GUI)
***************
Não funciona para enviar patches.
O cliente web do Gmail converte tabulações em espaços automaticamente.
Ao mesmo tempo, ele quebra linhas a cada 78 caracteres com quebras de linha no
estilo CRLF, embora o problema de tab para espaço possa ser resolvido com um
editor externo.
Outro problema é que o Gmail codifica em base64 qualquer mensagem que tenha um
caractere não-ASCII. Isso inclui coisas como nomes europeus.
HacKerMaiL (TUI)
****************
HacKerMaiL (hkml) é uma ferramenta simples de gerenciamento de e-mails baseada
em public-inbox que não exige inscrição em listas de discussão. É desenvolvida
e mantida pelo mantenedor do DAMON e visa oferecer suporte a fluxos de trabalho
de desenvolvimento simples para o DAMON e para subsistemas gerais do kernel.
Consulte o README (https://github.com/sjp38/hackermail/blob/master/README.md)
para mais detalhes.

View File

@@ -0,0 +1,102 @@
.. SPDX-License-Identifier: GPL-2.0
.. raw:: latex
\renewcommand\thesection*
\renewcommand\thesubsection*
===============================================
Trabalhando com a comunidade de desenvolvimento
===============================================
Então você quer ser um desenvolvedor do kernel Linux? Bem-vindo! Embora haja
muito a aprender sobre o kernel em um sentido técnico, também é importante
aprender como nossa comunidade funciona. A leitura desses documentos tornará
muito mais fácil para você ter suas alterações integradas com um mínimo de
problemas.
Uma introdução sobre como funciona o desenvolvimento do kernel
--------------------------------------------------------------
Leia estes documentos primeiro: entender este material facilitará
sua entrada na comunidade do kernel.
.. toctree::
:maxdepth: 1
Como começar <howto>
Guia do Processo de Desenvolvimento <development-process>
Lista de verificação para submissão de patches do kernel Linux <submit-checklist>
Ferramentas e guias técnicos para desenvolvedores do kernel
-----------------------------------------------------------
Esta é uma coleção de material com o qual os desenvolvedores do kernel
devem estar familiarizados.
.. toctree::
:maxdepth: 1
Requisitos mínimos <changes>
Informações sobre clientes de email para Linux <email-clients>
Como aplicar patches <applying-patches>
Backporting e resolução de conflitos <backporting>
Adicionando uma nova chamada de Sistema <adding-syscalls>
Como não Deixar as ioctls malfeitas <botching-up-ioctls>
Guias de políticas e declarações de desenvolvedores
---------------------------------------------------
Estas são as regras pelas quais tentamos viver na comunidade do kernel
(e além).
.. toctree::
:maxdepth: 1
Regras de licenciamento <license-rules>
Código de Conduta de Compromisso do Colaborador <code-of-conduct>
Interpretação do Código de Conduta do Kernel Linux <code-of-conduct-interpretation>
Modelos de Maturidade para Contribuição no Kernel Linux <contribution-maturity-model.rst>
Declaração sobre Drivers do Kernel <kernel-driver-statement>
Estilo de gerenciamento do kernel Linux <management-style>
Conclave (Continuidade do projeto) <conclave>
Lidando com bugs
----------------
Bugs são uma realidade; é importante lidarmos com eles de forma correta.
Os documentos abaixo detalham políticas e conselhos em relação ao
gerenciamento de bugs e vulnerabilidades.
.. toctree::
:maxdepth: 1
Falhas de segurança <security-bugs>
CVEs <cve>
Informações para mantenedores
-----------------------------
Como encontrar as pessoas que aceitarão seus patches e manuais úteis para os
mantenedores de subsistemas.
.. toctree::
:maxdepth: 1
Manuais dos mantenedores <maintainer-handbooks>
Processo do subsistema de rede (netdev) <maintainer-netdev>
Processo do subsistema SoC <maintainer-soc>
Conformidade de DTS para SoC <maintainer-soc-clean-dts>
Processo do subsistema KVM x86 <maintainer-kvm-x86>
Outros materiais
----------------
Aqui estão alguns outros guias para a comunidade que são de interesse para
a maioria dos desenvolvedores:
.. toctree::
:maxdepth: 1
Index de documentos do Kernel <kernel-docs>
Interfaces, recursos de linguagem, atributos e convenções obsoletos <deprecated>

View File

@@ -0,0 +1,205 @@
.. SPDX-License-Identifier: GPL-2.0
Declaração sobre Drivers do Kernel
----------------------------------
Posicionamento sobre os Módulos do Kernel Linux
===============================================
Nós, os desenvolvedores do kernel Linux abaixo assinados, consideramos
qualquer módulo ou driver de código fechado para o kernel Linux
prejudicial e indesejável. Repetidamente, constatamos que eles são
nocivos aos usuários do Linux, às empresas e ao ecossistema Linux como
um todo. Tais módulos negam a abertura, a estabilidade, a flexibilidade
e a manutenibilidade do modelo de desenvolvimento do Linux e privam
seus usuários do conhecimento da comunidade Linux. Fornecedores que
oferecem módulos de kernel de código fechado forçam seus clientes a
abrir mão de vantagens fundamentais do Linux ou a escolher novos
fornecedores. Portanto, para aproveitar plenamente a economia de custos
e os benefícios de suporte compartilhado que o código aberto tem a
oferecer, incentivamos fortemente para que os fornecedores adotem uma
política de dar suporte a seus clientes no Linux com código de kernel
de código aberto.
Falamos apenas por nós mesmos, e não por qualquer empresa para a qual
possamos trabalhar hoje, tenhamos trabalhado no passado ou venhamos a
trabalhar no futuro.
- Dave Airlie
- Nick Andrew
- Jens Axboe
- Ralf Baechle
- Felipe Balbi
- Ohad Ben-Cohen
- Muli Ben-Yehuda
- Jiri Benc
- Arnd Bergmann
- Thomas Bogendoerfer
- Vitaly Bordug
- James Bottomley
- Josh Boyer
- Neil Brown
- Mark Brown
- David Brownell
- Michael Buesch
- Franck Bui-Huu
- Adrian Bunk
- François Cami
- Ralph Campbell
- Luiz Fernando N. Capitulino
- Mauro Carvalho Chehab
- Denis Cheng
- Jonathan Corbet
- Glauber Costa
- Alan Cox
- Magnus Damm
- Ahmed S. Darwish
- Robert P. J. Day
- Hans de Goede
- Arnaldo Carvalho de Melo
- Helge Deller
- Jean Delvare
- Mathieu Desnoyers
- Sven-Thorsten Dietrich
- Alexey Dobriyan
- Daniel Drake
- Alex Dubov
- Randy Dunlap
- Michael Ellerman
- Pekka Enberg
- Jan Engelhardt
- Mark Fasheh
- J. Bruce Fields
- Larry Finger
- Jeremy Fitzhardinge
- Mike Frysinger
- Kumar Gala
- Robin Getz
- Liam Girdwood
- Jan-Benedict Glaw
- Thomas Gleixner
- Brice Goglin
- Cyrill Gorcunov
- Andy Gospodarek
- Thomas Graf
- Krzysztof Halasa
- Harvey Harrison
- Stephen Hemminger
- Michael Hennerich
- Tejun Heo
- Benjamin Herrenschmidt
- Kristian Høgsberg
- Henrique de Moraes Holschuh
- Marcel Holtmann
- Mike Isely
- Takashi Iwai
- Olof Johansson
- Dave Jones
- Jesper Juhl
- Matthias Kaehlcke
- Kenji Kaneshige
- Jan Kara
- Jeremy Kerr
- Russell King
- Olaf Kirch
- Roel Kluin
- Hans-Jürgen Koch
- Auke Kok
- Peter Korsgaard
- Jiri Kosina
- Aaro Koskinen
- Mariusz Kozlowski
- Greg Kroah-Hartman
- Michael Krufky
- Aneesh Kumar
- Clemens Ladisch
- Christoph Lameter
- Gunnar Larisch
- Anders Larsen
- Grant Likely
- John W. Linville
- Yinghai Lu
- Tony Luck
- Pavel Machek
- Matt Mackall
- Paul Mackerras
- Roland McGrath
- Patrick McHardy
- Kyle McMartin
- Paul Menage
- Thierry Merle
- Eric Miao
- Akinobu Mita
- Ingo Molnar
- James Morris
- Andrew Morton
- Paul Mundt
- Oleg Nesterov
- Luca Olivetti
- S.Çağlar Onur
- Pierre Ossman
- Keith Owens
- Venkatesh Pallipadi
- Nick Piggin
- Nicolas Pitre
- Evgeniy Polyakov
- Richard Purdie
- Mike Rapoport
- Sam Ravnborg
- Gerrit Renker
- Stefan Richter
- David Rientjes
- Luis R. Rodriguez
- Stefan Roese
- Francois Romieu
- Rami Rosen
- Stephen Rothwell
- Maciej W. Rozycki
- Mark Salyzyn
- Yoshinori Sato
- Deepak Saxena
- Holger Schurig
- Amit Shah
- Yoshihiro Shimoda
- Sergei Shtylyov
- Kay Sievers
- Sebastian Siewior
- Rik Snel
- Jes Sorensen
- Alexey Starikovskiy
- Alan Stern
- Timur Tabi
- Hirokazu Takata
- Eliezer Tamir
- Eugene Teo
- Doug Thompson
- FUJITA Tomonori
- Dmitry Torokhov
- Marcelo Tosatti
- Steven Toth
- Theodore Tso
- Matthias Urlichs
- Geert Uytterhoeven
- Arjan van de Ven
- Ivo van Doorn
- Rik van Riel
- Wim Van Sebroeck
- Hans Verkuil
- Horst H. von Brand
- Dmitri Vorobiev
- Anton Vorontsov
- Daniel Walker
- Johannes Weiner
- Harald Welte
- Matthew Wilcox
- Dan J. Williams
- Darrick J. Wong
- David Woodhouse
- Chris Wright
- Bryan Wu
- Rafael J. Wysocki
- Herbert Xu
- Vlad Yasevich
- Peter Zijlstra
- Bartlomiej Zolnierkiewicz

View File

@@ -22,11 +22,11 @@ netdev
------
A **netdev** é a lista de discussão para todos os assuntos do Linux relacionados
a rede. Isso inclui qualquer item encontrado em ``net/`` (ex: código principal
como IPv6) e em ``drivers/net`` (ex: drivers específicos de hardware) na árvore
como IPv6) e em ``drivers/net`` (ex: drivers específicos de hardware) na árvore
de diretórios do Linux.
Note que alguns subsistemas (ex: drivers de rede sem fio/wireless), que possuem
um alto volume de tráfego, possuem suas próprias listas de discussão e árvores
um alto volume de tráfego, possuem suas próprias listas de discussão e árvores
específicas.
Como muitas outras listas de discussão do Linux, a lista netdev é hospedada no
@@ -34,7 +34,7 @@ Como muitas outras listas de discussão do Linux, a lista netdev é hospedada no
https://lore.kernel.org/netdev/.
À exceção dos subsistemas mencionados anteriormente, todo o desenvolvimento de
rede do Linux (ex: RFCs, revisões, comentários, etc.) ocorre na **netdev**.
rede do Linux (ex: RFCs, revisões, comentários, etc.) ocorre na **netdev**.
Ciclo de Desenvolvimento
------------------------
@@ -506,8 +506,14 @@ netdevsim
O ``netdevsim`` é um driver de teste que pode ser usado para exercitar APIs de
configuração de driver sem a necessidade de hardware compatível. Mock-ups e
testes baseados no ``netdevsim`` são fortemente encorajados ao adicionar novas
APIs, mas o ``netdevsim`` em si **não** é considerado um caso de uso/usuário.
testes baseados no ``netdevsim`` são encorajados ao adicionar novas APIs com
lógica complexa na pilha. Os testes devem ser escritos de forma que possam ser
executados tanto contra o ``netdevsim`` quanto contra um dispositivo real
(veja ``tools/testing/selftests/drivers/net/README.rst``). Testes exclusivos
para o ``netdevsim`` devem se concentrar em testar casos extremos e caminhos de
falha no núcleo que são difíceis de exercitar com um driver real.
``netdevsim`` em si **não** é considerado um caso de uso/usuário.
Você também deve implementar as novas APIs em um driver real.
Não damos garantias de que o ``netdevsim`` mudará no futuro de uma forma que
@@ -577,8 +583,11 @@ independentemente do nível de experiência. Para orientações gerais e dicas
É seguro assumir que os mantenedores da netdev conhecem a comunidade e o nível
de experiência dos revisores. Os revisores não devem se preocupar com o fato de
seus comentários impedirem ou desviarem o fluxo de patches. Revisores menos
experientes são fortemente incentivados a fazer uma revisão mais aprofundada das
seus comentários impedirem ou desviarem o fluxo de patches. Uma tag Reviewed-by
é entendida como "Eu revisei este código da melhor maneira possível" em vez de
"Posso atestar que este código está correto".
Revisores são fortemente incentivados a fazer uma revisão mais aprofundada das
submissões e não focar exclusivamente em questões triviais ou subjetivas, como
formatação de código, tags, etc.

View File

@@ -0,0 +1,265 @@
.. SPDX-License-Identifier: GPL-2.0
Estilo de gerenciamento do kernel Linux
=======================================
Este é um documento curto descrevendo o estilo de gerenciamento preferido (ou
inventado, dependendo de quem você perguntar) para o kernel do Linux. Ele se
destina a espelhar o documento :ref:`process/coding-style.rst <codingstyle>` em
algum grau, e foi escrito principalmente para evitar responder [#f1]_ as mesmas
(ou semelhantes) perguntas repetidamente.
Estilo de gerenciamento é muito pessoal e muito mais difícil de quantificar do
que simples regras de estilo de codificação, então este documento pode ou não ter
qualquer coisa a ver com a realidade. Começou como uma brincadeira, mas isso não
significa que não possa ser verdade. Você terá que decidir por si mesmo.
A propósito, quando falamos sobre "gerente do kernel", trata-se de pessoas líderes
técnicas, e não das pessoas que fazem gerenciamento tradicional dentro das empresas.
Se você assina pedidos de compra ou tem alguma ideia sobre o orçamento do seu grupo,
você quase certamente não é um gerente do kernel. Essas sugestões podem ou não se
aplicar a você.
Primeiro, eu sugeriria comprar "Os Sete Hábitos das Pessoas Altamente Eficazes"
e NÃO lê-lo. Queime-o, é um ótimo gesto simbólico.
.. [#f1] Este documento faz isso não respondendo tanto à pergunta, mas torna
dolorosamente óbvio para o questionador que não temos ideia de qual é a resposta.
De qualquer maneira, aqui vai:
.. _decisoes:
1) Decisões
-----------
Todo mundo pensa que os gerentes tomam decisões, e que a tomada de decisões é
importante. Quanto maior e mais dolorosa a decisão, maior deve ser o gerente para
tomá-la. Isso é muito profundo e óbvio, mas na verdade não é verdade.
O nome do jogo é **evitar** ter que tomar uma decisão. Em particular, se alguém
lhe disser "escolha (a) ou (b), realmente precisamos que você decida sobre isso",
você está em apuros como gerente. As pessoas que você gerencia devem conhecer os
detalhes melhor do que você, então se elas vierem até você para uma decisão técnica,
você está ferrado. Você claramente não é competente para tomar essa decisão por elas.
(Consequência: Se as pessoas que você gerencia não conhecem os detalhes melhor
do que você, você também está ferrado, embora por um motivo totalmente diferente.
Isso significa que você está no trabalho errado, e que **elas** deveriam estar
gerenciando sua genialidade em vez disso).
Então o nome do jogo é **evitar** decisões, pelo menos as grandes e dolorosas.
Tomar decisões pequenas e sem consequências é bom, e faz você parecer que sabe
o que está fazendo, então o que um gerente do kernel precisa fazer é transformar
as grandes e dolorosas em pequenas coisas com as quais ninguém realmente se importa.
Ajuda a perceber que a diferença fundamental entre uma grande decisão e uma pequena
é se você pode consertar sua decisão depois. Qualquer decisão pode ser pequena
garantindo sempre que, se você estiver errado (e você **vai** estar errado), você
sempre pode desfazer o dano mais tarde voltando atrás. De repente, você demonstra
o dobro de capacidade como gerente por tomar **duas** decisões inconsequentes
- a errada **e** a certa.
E as pessoas verão isso como verdadeira liderança (*cof cof* besteira *cof cof*).
Portanto a chave para evitar grandes decisões torna-se apenas evitar fazer coisas
que não podem ser desfeitas. Não se deixe encurralar em um canto do qual você não
possa escapar. Um rato encurralado pode ser perigoso - um gerente encurralado é
apenas lamentável.
Como ninguém seria estúpido o suficiente para realmente deixar um gerente do kernel
ter uma enorme responsabilidade fiscal **de qualquer maneira**, é geralmente
bastante fácil voltar atrás. Como você não vai ser capaz de desperdiçar enormes
quantidades de dinheiro que você pode não ser capaz de reembolsar, a única coisa que
você pode voltar atrás é uma decisão técnica, e lá o retrocesso é muito fácil:
apenas diga a todos que você era um imbecil incompetente, peça desculpas e desfaça
todo o trabalho inútil em que você fez as pessoas trabalharem no último ano.
De repente, a decisão que você tomou há um ano não era uma grande decisão afinal,
já que poderia ser facilmente desfeita.
Acontece que algumas pessoas têm problemas com essa abordagem, por dois motivos:
- admitir que você foi um idiota é mais difícil do que parece. Todos nós gostamos
de manter as aparências, e sair em público para dizer que você estava errado
às vezes é muito difícil mesmo.
- ter alguém falando que o que você trabalhou no último ano não valeu a pena
depois de tudo pode ser difícil para os pobres engenheiros humildes também,
e enquanto o **trabalho** real foi fácil de desfazer apenas excluindo-o, você
pode ter perdido irrevogavelmente a confiança desse engenheiro. E lembre-se:
"irrevogável" era o que tentamos evitar em primeiro lugar, e sua decisão acabou
sendo uma grande decisão afinal.
Felizmente, ambas essas razões podem ser mitigadas efetivamente apenas admitindo
de antemão que você não tem a menor ideia, e dizendo às pessoas antes do fato
que sua decisão é puramente preliminar, e pode ser a coisa errada. Você deve
sempre reservar o direito de mudar de ideia, e fazer com que as pessoas estejam
muito **cientes** disso. E é muito mais fácil admitir que você é estúpido quando
você ainda não fez a coisa realmente estúpida.
Então, quando realmente se revela estúpido, as pessoas apenas reviram os olhos
e dizem "Ops, não de novo".
Essa admissão preventiva de incompetência também pode fazer com que as pessoas
que realmente fazem o trabalho também pensem duas vezes sobre se vale a pena ou
não. Afinal, se **elas** não têm certeza se é uma boa ideia, você com certeza não
deve encorajá-las prometendo que o que elas trabalham será incluído. Faça com que
elas pelo menos pensem duas vezes antes de embarcar em um grande empreendimento.
Lembre-se: eles devem saber mais sobre os detalhes do que você, e geralmente já
pensam que têm a resposta para tudo. A melhor coisa que você pode fazer como
gerente é não incutir confiança, mas sim uma dose saudável de pensamento crítico
sobre o que eles fazem.
A propósito, um outro jeito de evitar uma decisão é simplesmente choramingar "não
podemos fazer os dois?" e parecer patético. Confie em mim, funciona. Se não estiver
claro qual abordagem é melhor, eles eventualmente descobrirão. A resposta pode
acabar sendo que ambas as equipes ficam tão frustradas com a situação que apenas
desistem.
Isso pode soar como uma falha, mas geralmente é um sinal de que havia algo errado
com ambos os projetos, e a razão pela qual as pessoas envolvidas não conseguiram
decidir foi que ambas estavam erradas. Você acaba saindo por cima, e evitou mais
uma decisão que poderia ter estragado.
2) Pessoas
----------
A maioria das pessoas é idiota, e ser um gerente significa que você terá que lidar
com isso, e talvez mais importante, que **elas** terão que lidar com **você**.
Aconteceu que enquanto é fácil desfazer erros técnicos, não é tão fácil desfazer
distúrbios de personalidade. Você só tem que conviver com os deles - e com os seus.
Entretanto, para se preparar como gerente do kernel, é melhor lembrar de não queimar
nenhuma ponte, bombardear nenhum vilarejo inocente ou alienar muitos desenvolvedores
do kernel. Acontece que alienar pessoas é bastante fácil, e reverter esse afastamento
é difícil. Assim, "alienar" cai imediatamente sob o título de "não reversível",
e se torna um não-não de acordo com :ref:`decisoes`.
Existem apenas algumas regras simples aqui:
(1) não chame as pessoas de imbecis (pelo menos não em público)
(2) aprenda a pedir desculpas quando você esquecer a regra (1)
O problema com #1 é que é muito fácil de fazer, já que você pode dizer "você é
um imbecil" de milhões de maneiras diferentes [#f2]_, às vezes sem nem perceber,
e quase sempre com uma convicção ardente de que você está certo.
E quanto mais convencido você estiver de que está certo (e vamos encarar, você
pode chamar praticamente qualquer pessoa de imbecil, e muitas vezes você **vai**
estar certo), mais difícil acaba sendo se desculpar depois.
Para resolver esse problema, você realmente só tem duas opções:
- fique muito bom em pedir desculpas
- espalhe o "amor" de forma tão uniforme que ninguém realmente acabe se sentindo
injustamente alvo. Torne-o inventivo o suficiente, e eles podem até se divertir.
A opção de ser infalivelmente educado realmente não existe. Ninguém confiará em
alguém que está claramente escondendo seu verdadeiro caráter.
.. [#f2] Paul Simon cantou "Fifty Ways to Leave Your Lover", porque francamente,
"A Million Ways to Tell a Developer They're a D*ckhead" não soa tão bem. Mas
tenho certeza de que ele pensou sobre isso.
3) Pessoas II - o tipo bom
--------------------------
Embora no final das contas a maioria das pessoas seja idiota, a consequência disso
é tristemente que você também é, e que enquanto todos nós podemos nos deleitar na
segura convicção de que somos melhores do que a pessoa média (vamos encarar, ninguém
nunca acredita que é mediano ou abaixo da média), também devemos admitir que não
somos a faca mais afiada por aí, e haverá outras pessoas que são menos idiotas
do que você.
Algumas pessoas reagem mal a pessoas inteligentes. Outras se aproveitam delas.
Tenha certeza de que você, como mantenedor do kernel, está no segundo grupo.
Puxe o saco delas, porque são as pessoas que tornarão seu trabalho mais fácil.
Em particular, elas serão capazes de tomar suas decisões por você, que é tudo
sobre o jogo.
Então quando você encontrar alguém mais inteligente do que você, apenas siga o
fluxo. Suas responsabilidades de gerenciamento tornam-se em grande parte dizer
"Parece uma boa ideia - pode ir fundo", ou "Isso parece bom, mas e quanto a xxx?".
A segunda versão, em particular, é uma ótima maneira de aprender algo novo sobre
"xxx" ou parecer **extra** gerencial ao apontar algo que a pessoa mais inteligente
não havia pensado. Em qualquer caso, você vence.
Uma coisa a se observar é perceber que a grandeza em uma área não se traduz
necessariamente em outras áreas. Então você pode instigar as pessoas em direções
específicas, mas vamos encarar, elas podem ser boas no que fazem e péssimas em
tudo o mais. A boa notícia é que as pessoas tendem a naturalmente voltar para o
que são boas, então não é como se você estivesse fazendo algo irreversível quando
você **as** instiga em alguma direção, apenas não pressione demais.
4) Colocando a culpa
--------------------
As coisas vão dar errado, e as pessoas querem alguém para culpar. Pronto, a culpa
é sua.
Não é realmente tão difícil aceitar a culpa, especialmente se as pessoas perceberem
que não foi **toda** a sua culpa. O que nos leva à melhor maneira de assumir a
culpa: faça isso por outra pessoa. Você se sentirá bem por assumir a culpa, eles
se sentirão bem por não serem culpados, e a pessoa que perdeu toda a coleção de
pornografia de 36 GB por causa da sua incompetência vai admitir relutantemente que
pelo menos você não tentou se esquivar disso.
Então faça o desenvolvedor que realmente estragou (se você conseguir encontrá-lo)
saber **em particular** que ele estragou. Não apenas para que ele possa evitar isso
no futuro, mas para que ele saiba que lhe deve uma. E, talvez ainda mais importante,
ele provavelmente é a pessoa que pode consertar. Porque, vamos encarar, com certeza
não é você.
Levar a culpa também é o motivo pelo qual você se torna gerente em primeiro lugar.
É parte do que faz as pessoas confiarem em você, e permite a você a glória potencial,
porque você é quem pode dizer "Eu estraguei". E se você seguiu as regras anteriores,
você será muito bom em dizer isso agora.
5) Coisas para evitar
---------------------
Tem uma coisa que as pessoas odeiam ainda mais do que ser chamado de "idiota", e
isso é ser chamado de "idiota" com uma voz moralista. O primeiro você pode se
desculpar, o segundo você realmente não terá a chance. Eles provavelmente não
estarão mais ouvindo, mesmo que você faça um bom trabalho de outra forma.
Todos nós pensamos que somos melhores do que qualquer outra pessoa, o que significa
que quando alguém posa de superior, isso realmente nos irrita. Você pode ser moral
e intelectualmente superior a todos ao seu redor, mas não tente tornar isso muito
óbvio, a menos que você realmente **pretenda** irritar alguém [#f3]_.
Semelhantemente, não seja muito educado ou sutil sobre as coisas. A educação
facilmente acaba indo longe demais e escondendo o problema, e como dizem, "Na
internet, ninguém pode ouvir você sendo sutil". Use um grande objeto contundente
para martelar o ponto, porque você realmente não pode depender das pessoas
entenderem o seu ponto de outra forma.
Um pouco de humor pode ajudar a amortecer tanto a franqueza quanto a moralização.
Ir além do limite a ponto de ser ridículo pode transmitir um ponto sem tornar
doloroso para o destinatário, que apenas pensa que você está sendo bobo. Isso pode
ajudar a superar o bloqueio mental pessoal que todos nós temos sobre críticas.
.. [#f3] Dica: grupos de discussão na internet que não estão diretamente relacionados
ao seu trabalho são ótimas maneiras de descarregar suas frustrações nos outros.
Escreva posts insultuosos com sarcasmo apenas para entrar em uma boa discussão
de vez em quando, e você se sentirá aliviado. Só não faça sujeira muito perto
de casa (ou seja, não crie problemas onde isso possa afetar sua vida pessoal).
6) Por que eu?
--------------
Já que a sua maior responsabilidade parece ser assumir a culpa pelos erros de outras
pessoas, e tornar dolorosamente óbvio para todos os outros que você é incompetente,
a pergunta óbvia se torna: por que fazer isso em primeiro lugar?
Primeiramente, embora você possa ou não receber adolescentes gritando (meninas ou
meninos, não vamos ser preconceituosos ou sexistas aqui) batendo na porta do seu
camarim, você **vai** receber uma imensa sensação de realização pessoal por estar
"no comando". Não importa o fato de que você realmente está liderando tentando
acompanhar todos os outros e correndo atrás deles o mais rápido que puder. Todos
ainda vão pensar que você é a pessoa no comando.
É um ótimo trabalho se você conseguir aguentar.

View File

@@ -0,0 +1,368 @@
.. SPDX-License-Identifier: GPL-2.0
Falhas de segurança
===================
Os desenvolvedores do kernel Linux levam a segurança muito a sério. Como tal,
gostaríamos de saber quando uma falha de segurança é encontrada para que ela
possa ser corrigida e divulgada o mais rápido possível.
Preparando seu relatório
------------------------
Como em qualquer relatório de bug, um relatório de falha de segurança exige
muito trabalho de análise por parte dos desenvolvedores, portanto, quanto mais
informações você puder compartilhar sobre o problema, melhor. Por favor, revise
o procedimento descrito em Documentation/admin-guide/reporting-issues.rst se
você não tiver certeza sobre quais informações são úteis. As seguintes
informações são absolutamente necessárias em **qualquer** relatório de falha de
segurança:
* **versão do kernel afetada**: sem indicação de versão, seu relatório não
será processado. Uma parte significativa dos relatórios é de bugs que já
foram corrigidos, portanto, é extremamente importante que as
vulnerabilidades sejam verificadas em versões recentes (árvore de
desenvolvimento ou a versão estável mais recente), pelo menos verificando
se o código não mudou desde a versão onde foi detectado.
* **descrição do problema**: uma descrição detalhada do problema, com rastros
mostrando sua manifestação, e por que você considera o comportamento
observado como um problema no Kernel, é necessária.
* **reproduzir**: os desenvolvedores precisarão ser capazes de reproduzir o
problema para considerar uma correção como eficaz. Isso inclui tanto uma
maneira de acionar o problema quanto uma maneira de confirmar que ele
ocorre. Será necessário um reprodutor com dependências de baixa
complexidade (código-fonte, script de shell, sequência de instruções,
imagem de sistema de arquivos, etc). Executáveis apenas binários não são
aceitos. Exploits funcionais são extremamente úteis e não serão divulgados
sem o consentimento do relator, a menos que já sejam públicos. Por
definição, se um problema não pode ser reproduzido, ele não é explorável,
portanto, não é um bug de segurança.
* **condições**: se o bug depender de certas opções de configuração, sysctls,
permissões, temporização, modificações de código, etc., estas devem ser
indicadas.
Além disso, as seguintes informações são altamente desejáveis:
* **localização suspeita do bug**: os nomes dos arquivos e funções onde
se suspeita que o bug esteja presente são muito importantes, pelo menos
para ajudar a encaminhar o relatório aos mantenedores apropriados. Quando
não for possível (por exemplo, "o sistema trava toda vez que executo este
comando"), a equipe de segurança ajudará a identificar a origem do bug.
* **uma proposta de correção**: os relatores de bugs que analisaram a causa
de uma falha no código-fonte quase sempre têm uma ideia precisa de como
corrigi-lo, porque passaram muito tempo estudando o problema e suas
implicações. Propor uma correção testada poupará muito tempo dos
mantenedores, mesmo que a correção acabe não sendo a correta, pois ajuda a
entender o bug. Ao propor uma correção testada, por favor, formate-a
sempre de uma maneira que possa ser mesclada imediatamente (consulte
Documentation/process/submitting-patches.rst). Isso evitará algumas trocas
de mensagens caso ela seja aceita, e você receberá o crédito por
encontrar e corrigir o problema. Observe que, neste caso, apenas uma tag
``Signed-off-by:`` é necessária, sem ``Reported-by:`` quando o relator e
o autor forem a mesma pessoa.
* **mitigações**: com muita frequência, durante a análise de um bug,
surgem algumas maneiras de mitigar o problema. É útil compartilhá-las,
pois podem ser úteis para manter os usuários finais protegidos durante o
tempo que levam para aplicar a correção.
O que se qualifica como um bug de segurança
-------------------------------------------
É importante que a maioria dos bugs seja tratada publicamente, de modo a
envolver o maior público possível e encontrar a melhor solução. Por natureza,
bugs que são tratados em discussões fechadas entre um pequeno conjunto de
participantes têm menos probabilidade de produzir a melhor correção possível
(por exemplo, risco de perder casos de uso válidos, capacidades de testes
limitadas).
Acontece que a maioria dos bugs relatados por meio da equipe de segurança são
apenas bugs comuns que foram qualificados incorretamente como bugs de segurança
devido à falta de conhecimento do modelo de ameaças do kernel Linux, conforme
descrito em Documentation/process/threat-model.rst, e deveriam ter sido
enviados através dos canais normais descritos em
Documentation/admin-guide/reporting-issues.rst
A lista de segurança existe para bugs urgentes que concedem a um atacante uma
capacidade que ele não deveria ter em um sistema de produção corretamente
configurado, e que podem ser facilmente explorados, representando uma ameaça
iminente para muitos usuários. Antes de relatar, considere se o problema
realmente ultrapassa um limite de confiança em tal sistema.
**Se você recorreu a assistência de IA para identificar um bug, você deve
tratá-lo como público**. Embora você possa ter motivos válidos para acreditar
que não seja, a experiência da equipe de segurança mostra que os bugs
descobertos desta forma surgem sistematicamente e de forma simultânea entre
múltiplos pesquisadores, frequentemente no mesmo dia. Neste caso, não
compartilhe publicamente um reprodutor, pois isso poderia causar danos não
intencionais; apenas mencione que um está disponível e os mantenedores poderão
solicitá-lo privadamente se precisarem.
Se você não tiver certeza se um problema se qualifica, opte por relatar de
forma privada: a equipe de segurança prefere triar um relatório limítrofe
a perder uma vulnerabilidade real. Relatar bugs comuns na lista de segurança,
no entanto, não faz com que eles andem mais rápido e consome a capacidade de
triagem de que outros relatórios precisam.
Identificando contatos
----------------------
A maneira mais eficaz de relatar um bug de segurança é enviá-lo diretamente
aos mantenedores do subsistema afetado e Cc: para a equipe de segurança do
kernel Linux. Não o envie para uma lista pública nesta fase, a menos que você
tenha bons motivos para considerar o problema como público ou trivial de ser
descoberto (por exemplo, resultado de uma ferramenta automatizada de varredura
de vulnerabilidades amplamente disponível que possa ser repetida por qualquer
pessoa, ou o uso de ferramentas baseadas em IA).
Se você estiver enviando um relatório de problemas que afetam várias partes no
kernel, mesmo que sejam problemas bastante semelhantes, envie mensagens
individuais (pense que os mantenedores não trabalharão todos nos problemas ao
mesmo tempo). A única exceção é quando um problema diz respeito a partes
intimamente relacionadas, mantidas pelo exato mesmo subconjunto de
mantenedores, e espera-se que essas partes sejam todas corrigidas de uma só vez
pelo mesmo commit; então pode ser aceitável relatá-las de uma vez.
Uma dificuldade para a maioria dos relatores de primeira viagem é descobrir a
lista certa de destinatários para enviar um relatório. No kernel Linux, todos
os mantenedores oficiais são confiáveis, portanto as consequências de incluir
acidentalmente o mantenedor errado são apenas um pequeno ruído para essa
pessoa, ou seja, nada dramático. Sendo assim, um método adequado para descobrir
a lista de mantenedores (o qual os oficiais de segurança do kernel usam) é
contar com o script get_maintainer.pl, ajustado para relatar apenas
mantenedores. Este script, quando recebe um nome de arquivo, procurará por seu
caminho no arquivo MAINTAINERS para deduzir uma lista hierárquica de
mantenedores relevantes. Chamá-lo pela primeira vez com o nível mais refinado
de filtragem retornará, na maioria das vezes, uma lista curta de mantenedores
deste arquivo específico::
$ ./scripts/get_maintainer.pl --no-l --no-r --pattern-depth 1 \
drivers/example.c
Developer One <dev1@example.com> (maintainer:example driver)
Developer Two <dev2@example.org> (maintainer:example driver)
Estes dois mantenedores devem então receber a mensagem. Se o comando não
retornar nada, isso significa que o arquivo afetado faz parte de um subsistema
mais amplo, portanto devemos ser menos específicos::
$ ./scripts/get_maintainer.pl --no-l --no-r drivers/example.c
Developer One <dev1@example.com> (maintainer:example subsystem)
Developer Two <dev2@example.org> (maintainer:example subsystem)
Developer Three <dev3@example.com> (maintainer:example subsystem [GENERAL])
Developer Four <dev4@example.org> (maintainer:example subsystem [GENERAL])
Aqui, escolher os primeiros, mais específicos, é suficiente. Quando a lista for
longa, é possível produzir uma lista de endereços de e-mail delimitada por
vírgulas em uma única linha adequada para o uso no campo TO: de um cliente de
e-mail como este::
$ ./scripts/get_maintainer.pl --no-tree --no-l --no-r --no-n --m \
--no-git-fallback --no-substatus --no-rolestats --no-multiline \
--pattern-depth 1 drivers/example.c
dev1@example.com, dev2@example.org
ou este para a lista mais ampla::
$ ./scripts/get_maintainer.pl --no-tree --no-l --no-r --no-n --m \
--no-git-fallback --no-substatus --no-rolestats --no-multiline \
drivers/example.c
dev1@example.com, dev2@example.org, dev3@example.com, dev4@example.org
Se a esta altura você ainda estiver enfrentando dificuldades para identificar
os mantenedores corretos, e apenas neste caso, é possível enviar seu
relatório apenas para a equipe de segurança do kernel Linux. Sua mensagem
será triada e você receberá instruções sobre quem contatar, se necessário.
Sua mensagem poderá igualmente ser encaminhada como está para os mantenedores
relevantes.
Uso responsável de IA para encontrar bugs
-----------------------------------------
Uma fração significativa dos relatórios de bugs enviados à equipe de segurança
é, na verdade, o resultado de revisões de código assistidas por ferramentas de
IA. Embora isso possa ser um meio eficiente de encontrar bugs em áreas
raramente exploradas, causa uma sobrecarga nos mantenedores, que às vezes são
forçados a ignorar tais relatórios devido à sua má qualidade ou precisão. Sendo
assim, os relatores devem ter um cuidado especial com vários pontos que tendem
a tornar esses relatórios desnecessariamente difíceis de lidar:
* **Comprimento**: Os relatórios gerados por IA tendem a ser excessivamente
longos, contendo várias seções e detalhes em excesso. Isso dificulta a
identificação de informações importantes, como arquivos afetados, versões e
impacto. Por favor, certifique-se de que um resumo claro do problema e
todos os detalhes críticos sejam apresentados primeiro. Não exija que os
engenheiros de triagem analisem várias páginas de texto. Configure suas
ferramentas para produzir relatórios concisos e em estilo humano.
* **Formatação**: A maioria dos relatórios gerados por IA está repleta de
tags Markdown. Essas decorações complicam a busca por informações
importantes e não sobrevivem aos processos de citação envolvidos no
encaminhamento ou nas respostas. Por favor, sempre converta seu relatório
para texto simples sem quaisquer decorações de formatação antes de
enviá-lo.
* **Avaliação de Impacto**: Muitos relatórios gerados por IA carecem de uma
compreensão do modelo de ameaças do kernel (consulte
Documentation/process/threat-model.rst) e fazem de tudo para inventar
consequências teóricas. Isso adiciona ruído e complica a triagem. Por
favor, limite-se a fatos verificáveis (por exemplo, "este bug permite que
qualquer usuário obtenha CAP_NET_ADMIN") sem enumerar implicações
especulativas. Faça com que sua ferramenta leia esta documentação como
parte do processo de avaliação.
* **Reproduzidor**: As ferramentas baseadas em IA são frequentemente capazes
de gerar reproduzidores. Por favor, certifique-se sempre de que sua
ferramenta forneça um e teste-o exaustivamente. Se o reproduzidor não
funcionar, ou se a ferramenta não puder produzir um, a validade do
relatório deve ser seriamente questionada. Observe que, como o relatório
será postado em uma lista pública, o reproduzidor só deve ser compartilhado
mediante solicitação dos mantenedores.
* **Propor uma Correção:** muitas ferramentas de IA são na verdade melhores
em escrever código do que em avaliá-lo. Por favor, peça à sua ferramenta
para propor uma correção e teste-a antes de relatar o problema.
Se a correção não puder ser testada porque depende de hardware raro ou de
protocolos de rede quase extintos, é provável que o problema não seja um
bug de segurança. Em qualquer caso, se uma correção for proposta, ela deve
aderir a Documentation/process/submitting-patches.rst e incluir uma tag
'Fixes:' designando o commit que introduziu o bug.
A falha em considerar estes pontos expõe seu relatório ao risco de ser
ignorado.
Use o bom senso ao avaliar o relatório. Se o arquivo afetado não tiver sido
alterado por mais de um ano e for mantido por um único indivíduo, é provável
que o uso tenha diminuído e os usuários expostos sejam virtualmente
inexistentes (por exemplo, drivers para hardware muito antigo, sistemas de
arquivos obsoletos). Nesses casos, não há necessidade de consumir o tempo de
um mantenedor com um relatório sem importância. Se o problema for claramente
trivial e publicamente detectável, você deve relatá-lo diretamente às listas
de discussão públicas.
Enviando o relatório
--------------------
Os relatórios devem ser enviados exclusivamente por e-mail. Por favor, use um
endereço de e-mail funcional, de preferência o mesmo que você deseja que
apareça nas tags ``Reported-by``, se houver. Se não tiver certeza, envie o seu
relatório para você mesmo primeiro.
A equipe de segurança e os mantenedores quase sempre exigem informações
adicionais além das fornecidas inicialmente em um relatório e dependem de uma
colaboração ativa e eficiente com o relator para realizar testes adicionais
(por exemplo, verificar versões, opções de configuração, mitigações ou
patches). Antes de entrar em contato com a equipe de segurança, o relator deve
certificar-se de que está disponível para explicar suas descobertas, participar
de discussões e executar testes adicionais. Relatórios nos quais o relator não
responde prontamente ou não consegue discutir suas descobertas de forma eficaz
podem ser abandonados se a comunicação não melhorar rapidamente.
O relatório deve ser enviado aos mantenedores. Se houver dois ou menos
destinatários em sua mensagem, você também deve sempre colocar em Cc: a equipe
de segurança do kernel Linux, que garantirá que a mensagem seja entregue às
pessoas corretas e poderá auxiliar pequenas equipes de mantenedores com
processos com os quais eles possam não estar familiarizados. Para equipes
maiores, coloque em Cc: a equipe de segurança do kernel Linux em seus primeiros
relatórios ou ao buscar ajuda específica, como ao reenviar uma mensagem que não
obteve resposta dentro de uma semana. Assim que você se sentir confortável com
o processo após alguns relatórios, não será mais necessário colocar a lista de
segurança em Cc: ao enviar para equipes grandes. A equipe de segurança do
kernel Linux pode ser contatada por e-mail em security@kernel.org. Esta é uma
lista privada de oficiais de segurança que ajudarão a verificar o relatório de
bug e auxiliarão os desenvolvedores que trabalham em uma correção. É possível
que a equipe de segurança traga ajuda extra de mantenedores da área para
entender e corrigir a vulnerabilidade de segurança.
Por favor, envie e-mails em **texto simples** sem anexos, sempre que possível.
É muito mais difícil ter uma discussão com citações de contexto sobre um
problema complexo se todos os detalhes estiverem ocultos em anexos. Pense nisso
como uma :doc:`regular path submission </../../../process/submitting-patches>`
(mesmo que você ainda não tenha um patch): descreva o problema e o impacto,
liste as etapas de reprodução e siga com uma proposta de correção, tudo em
texto simples. Relatórios formatados em Markdown, HTML e RST são
particularmente malvistos, pois são bastante difíceis de ler por humanos e
incentivam o uso de visualizadores dedicados, às vezes online, o que por
definição não é aceitável para um relatório de segurança confidencial. Note
que alguns clientes de e-mail tendem a corromper a formatação de texto simples
por padrão; por favor, consulte Documentation/process/email-clients.rst para
mais informações.
Divulgação e informações sob embargo
------------------------------------
A lista de segurança não é um canal de divulgação. Para isso, veja Coordenação
abaixo.
Assim que uma correção robusta for desenvolvida, o processo de lançamento é
iniciado. Correções para bugs publicamente conhecidos são lançadas
imediatamente.
Embora nossa preferência seja lançar correções para bugs publicamente não
divulgados assim que estiverem disponíveis, isso pode ser adiado a pedido do
relator ou de uma parte afetada por até 7 dias corridos a partir do início do
processo de lançamento, com uma extensão excepcional para 14 dias corridos se
for acordado que a criticidade do bug exige mais tempo. O único motivo válido
para adiar a publicação de uma correção é acomodar a logística de QA e as
implantações em larga escala que exigem coordenação de lançamento.
Embora as informações sob embargo possam ser compartilhadas com indivíduos de
confiança para o desenvolvimento de uma correção, tais informações não serão
publicadas juntamente com a correção ou em qualquer outro canal de divulgação
sem a permissão do relator. Isso inclui, mas não se limita ao relatório de bug
original e discussões de acompanhamento (se houver), exploits, informações de
CVE ou a identidade do relator.
Em outras palavras, nosso único interesse é fazer com que os bugs sejam
corrigidos. Todas as outras informações enviadas à lista de segurança e
quaisquer discussões de acompanhamento do relatório são tratadas de forma
confidencial, mesmo após o término do embargo, perpetuamente.
Coordenação com outros grupos
-----------------------------
Embora a equipe de segurança do kernel se concentre exclusivamente em corrigir
bugs, outros grupos se concentram em corrigir problemas em distribuições e em
coordenar a divulgação entre fornecedores de sistemas operacionais. A
coordenação é geralmente tratada pela lista de discussão "linux-distros" e a
divulgação pela lista pública "oss-security", ambas intimamente relacionadas
e apresentadas na wiki da linux-distros:
https://oss-security.openwall.org/wiki/mailing-lists/distros
Por favor, note que as respectivas políticas e regras são diferentes, já que as
3 listas buscam objetivos distintos. A coordenação entre a equipe de segurança
do kernel e outras equipes é difícil porque para a equipe de segurança do
kernel os embargos ocasionais (sujeitos a um número máximo de dias permitido)
começam a partir da disponibilidade de uma correção, enquanto para a
"linux-distros" eles começam a partir da postagem inicial na lista,
independentemente da disponibilidade de uma correção.
Como tal, a equipe de segurança do kernel recomenda fortemente que, como
relator de um potencial problema de segurança, você NÃO contate a lista de
discussão "linux-distros" ATÉ que uma correção seja aceita pelos mantenedores
do código afetado e você tenha lido a página wiki das distribuições acima e
compreendido totalmente os requisitos que o contato com a "linux-distros"
imporá a você e à comunidade do kernel. Isso também significa que, em geral,
não faz sentido colocar ambas as listas em Cc: ao mesmo tempo, exceto talvez
para coordenação se e enquanto uma correção aceita ainda não tiver sido
mesclada. Em outras palavras, até que uma correção seja aceita, não coloque
em Cc: "linux-distros", e após ela ser mesclada, não coloque em Cc: a equipe
de segurança do kernel.
Atribuição de CVE
-----------------
A equipe de segurança não atribui CVEs, nem os exigimos para relatórios ou
correções, pois isso pode complicar desnecessariamente o processo e adiar o
tratamento do bug. Se um relator desejar que um identificador CVE seja
atribuído para um problema confirmado, ele pode entrar em contato com a
:doc:`kernel CVE assignment team<../../../process/cve>` para obter um.
Acordo de não divulgação
------------------------
A equipe de segurança do kernel Linux não é um órgão formal e, portanto, é
incapaz de celebrar quaisquer acordos de não divulgação.

View File

@@ -0,0 +1,145 @@
.. SPDX-License-Identifier: GPL-2.0
==============================================================
Lista de verificação para submissão de patches do kernel Linux
==============================================================
Aqui estão algumas coisas básicas que os desenvolvedores devem fazer se
quiserem ver suas submissões de patches de kernel aceitas mais rapidamente.
Estas diretrizes vão além da documentação fornecida em
:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
e em outros locais sobre o envio de patches para o kernel Linux.
Revise seu código
=================
1) Se você usar um recurso, faça o #include do arquivo que define/declara
esse recurso. Não dependa de outros arquivos de cabeçalho que incluam
os que você usa de forma indireta.
2) Verifique o estilo geral do seu patch conforme detalhado em
:ref:`Documentation//process/coding-style.rst <codingstyle>`.
3) Todas as barreiras de memória {por exemplo, ``barrier()``, ``rmb()``,
``wmb()``} precisam de um comentário no código-fonte que explique a
lógica do que estão fazendo e o porquê.
Revise as alterações do Kconfig
===============================
1) Quaisquer novas ou modificadas opções de ``CONFIG`` não bagunçam o
menu de configuração e têm 'desativado' (off) como padrão, a menos que
atendam aos critérios de exceção documentados em
``Documentation/kbuild/kconfig-language.rst``, atributos de menu: valor
padrão.
2) Todas as novas opções de ``Kconfig`` possuem texto de ajuda.
3) Foram cuidadosamente revisadas com relação às combinações relevantes de
``Kconfig``. Isso é muito difícil de acertar apenas com testes --- exige
capacidade de raciocínio.
pays off here.
Forneça documentação
====================
1) Inclua :ref:`kernel-doc <kernel_doc>` para documentar as APIs globais
do kernel. (Não é obrigatório para funções estáticas, mas também é
aceitável nelas.)
2) Todas as novas entradas em ``/proc`` devem ser documentadas sob
``Documentation/``.
3) Todos os novos parâmetros de inicialização (boot) do kernel devem ser
documentados em ``Documentation/admin-guide/kernel-parameters.rst``.
4) Todos os novos parâmetros de módulo devem ser documentados com
``MODULE_PARM_DESC()``.
5) Todas as novas interfaces com o espaço de usuário (userspace) devem ser
documentadas em ``Documentation/ABI/``. Consulte
``Documentation/admin-guide/abi.rst`` (ou ``Documentation/ABI/README``)
para obter mais informações. Patches que alteram interfaces de espaço
de usuário devem incluir em cópia (CC) linux-api@vger.kernel.org.
6) Se quaisquer ioctls forem adicionados pelo patch, atualize também
``Documentation/userspace-api/ioctl/ioctl-number.rst``.
Verifique seu código com ferramentas
====================================
1) Verifique se há violações triviais com o verificador de estilo de patch
antes do envio (``scripts/checkpatch.pl``). Você deve ser capaz de
justificar todas as violações que permanecerem no seu patch.
2) Faça uma verificação limpa com o sparse.
3) Use ``make checkstack`` e corrija quaisquer problemas encontrados por ele.
Observe que o ``checkstack`` não aponta problemas explicitamente, mas
qualquer função individual que utilize mais de 512 bytes na pilha é uma
candidata a alteração.
Compile seu código
==================
1) Compila de forma limpa:
a) com as opções de ``CONFIG`` aplicáveis ou modificadas definidas como
``=y``, ``=m`` e ``=n``. Sem avisos/erros do ``gcc``, sem avisos/erros do
vinculador (linker).
b) Passa em ``allnoconfig``, ``allmodconfig``
c) Compila com sucesso ao usar ``O=builddir``
d) Quaisquer alterações em Documentation/ compilam com sucesso sem novos
avisos/erros. Use ``make htmldocs`` ou ``make pdfdocs`` para verificar
a compilação e corrigir quaisquer problemas.
2) Compila em múltiplas arquiteturas de CPU usando ferramentas locais de
compilação cruzada (cross-compile) ou alguma outra fazenda de compilação
(build farm).
Observe que testar em arquiteturas de diferentes tamanhos de palavra
(32 e 64 bits) e diferentes endianness (big- e little-endian) é eficaz
para capturar vários problemas de portabilidade decorrentes de falsas
suposições sobre o intervalo de quantidade representável, alinhamento
de dados ou endianness, entre outros.
3) O novo código adicionado foi compilado com ``gcc -W`` (use
``make KCFLAGS=-W``). Isso gerará muito ruído, mas é bom para encontrar
bugs como "warning: comparison between signed and unsigned".
4) Se o seu código-fonte modificado depender ou usar quaisquer APIs ou
recursos do kernel relacionados aos seguintes símbolos do ``Kconfig``,
teste múltiplas compilações com os símbolos relacionados do ``Kconfig``
desativados e/ou definidos como ``=m`` (se essa opção estiver disponível)
[não todos ao mesmo tempo, apenas combinações variadas/aleatórias deles]:
``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``,
``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
``CONFIG_NET``, ``CONFIG_INET=n`` (mas este último com ``CONFIG_NET=y``).
Teste seu código
================
1) Foi testado com ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
``CONFIG_SLUB_DEBUG``, ``CONFIG_DEBUG_PAGEALLOC``,
``CONFIG_DEBUG_MUTEXES``, ``CONFIG_DEBUG_SPINLOCK``,
``CONFIG_DEBUG_ATOMIC_SLEEP``, ``CONFIG_PROVE_RCU`` e
``CONFIG_DEBUG_OBJECTS_RCU_HEAD`` todos habilitados simultaneamente.
2) Foi testado em tempo de compilação e de execução com e sem ``CONFIG_SMP``
e ``CONFIG_PREEMPT``.
3) Todos os caminhos de código foram executados com todos os recursos de
lockdep ativados.
4) Foi verificado com a injeção de falhas de pelo menos slab e alocação de
páginas. Consulte ``Documentation/fault-injection/``.
Se o novo código for substancial, a adição de injeção de falhas específica
do subsistema pode ser apropriada.
5) Testado com a tag mais recente do linux-next para garantir que ele ainda
funcione com todos os outros patches enfileirados e com várias alterações
na VM, VFS e outros subsistemas.

View File

@@ -148,7 +148,7 @@ psi接口提供的均值即可。
Cgroup2接口
===========
对于CONFIG_CGROUP=y及挂载了cgroup2文件系统的系统能够获取cgroups内任务的psi。
对于CONFIG_CGROUPS=y及挂载了cgroup2文件系统的系统能够获取cgroups内任务的psi。
此场景下cgroupfs挂载点的子目录包含cpu.pressure、memory.pressure、io.pressure文件
内容格式与/proc/pressure/下的文件相同。

View File

@@ -1,7 +1,13 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: :doc:`../../../admin-guide/index`
:Translator: Alex Shi <alex.shi@linux.alibaba.com>
:Original: Documentation/admin-guide/index.rst
:翻译:
时奎亮 Alex Shi <alex.shi@linux.alibaba.com>
朱岩 Yan Zhu <zhuyan2015@qq.com>
Linux 内核用户和管理员指南
@@ -11,7 +17,11 @@ Linux 内核用户和管理员指南
整体的顺序或组织 - 这些材料不是一个单一的,连贯的文件!幸运的话,情况会随着
时间的推移而迅速改善。
这个初始部分包含总体信息包括描述内核的README 关于内核参数的文档等。
内核管理通用指南
----------------
本节包含总体信息,包括描述内核整体的 README 文件、内核参数文档等。
.. toctree::
:maxdepth: 1
@@ -20,17 +30,54 @@ Linux 内核用户和管理员指南
Todolist:
* kernel-parameters
* devices
* sysctl/index
* features
本节介绍CPU漏洞及其缓解措施。
内核管理接口的重要组成部分是 /proc 和 sysfs 虚拟文件系统;这些文档描述了如何
与之交互。
.. toctree::
:maxdepth: 1
cputopology
Todolist:
* sysfs-rules
* sysctl/index
* abi
安全相关文档:
.. toctree::
:maxdepth: 1
Todolist:
* hw-vuln/index
* LSM/index
* perf-security
下面的一组文档针对的是试图跟踪问题和bug的用户。
内核启动
--------
.. toctree::
:maxdepth: 1
bootconfig
Todolist:
* kernel-parameters
* efi-stub
* initrd
追踪和识别问题
--------------
以下是一组面向试图追踪特定问题和 bug 的用户的文档。
.. toctree::
:maxdepth: 1
@@ -39,94 +86,149 @@ Todolist:
reporting-regressions
bug-hunting
bug-bisect
tainted-kernels
init
clearing-warn-once
lockup-watchdogs
sysrq
Todolist:
* quickly-build-trimmed-linux
* verify-bugs-and-bisect-regressions
* tainted-kernels
* ramoops
* dynamic-debug-howto
* kdump/index
* perf/index
* pstore-blk
* kernel-per-CPU-kthreads
* RAS/index
这是应用程序开发人员感兴趣的章节的开始。可以在这里找到涵盖内核ABI各个
方面的文档。
Todolist:
* sysfs-rules
本手册的其余部分包括各种指南,介绍如何根据您的喜好配置内核的特定行为。
核心内核子系统
--------------
这些文档描述了核心内核管理接口,这些接口几乎在任何系统上都值得关注。
.. toctree::
:maxdepth: 1
bootconfig
clearing-warn-once
cpu-load
cputopology
lockup-watchdogs
numastat
unicode
sysrq
mm/index
module-signing
numastat
Todolist:
* cgroup-v2
* cgroup-v1/index
* namespaces/index
* pm/index
* syscall-user-dispatch
对非原生二进制格式的支持。请注意,其中一些文档相当 **古老**
.. toctree::
:maxdepth: 1
Todolist:
* binfmt-misc
* java
* mono
块设备和文件系统管理
--------------------
.. toctree::
:maxdepth: 1
Todolist:
* bcache
* binderfs
* blockdev/index
* cifs/index
* device-mapper/index
* ext4
* filesystem-monitoring
* nfs/index
* iostats
* jfs
* md
* ufs
* xfs
专用设备指南
------------
如何在 Linux 系统中配置硬件。
.. toctree::
:maxdepth: 1
Todolist:
* acpi/index
* aoe/index
* auxdisplay/index
* bcache
* binderfs
* binfmt-misc
* blockdev/index
* braille-console
* btmrvl
* cgroup-v1/index
* cgroup-v2
* cifs/index
* dell_rbu
* device-mapper/index
* edid
* efi-stub
* ext4
* nfs/index
* gpio/index
* highuid
* hw_random
* initrd
* iostats
* java
* jfs
* kernel-per-CPU-kthreads
* laptops/index
* lcd-panel-cgram
* ldm
* LSM/index
* md
* media/index
* module-signing
* mono
* namespaces/index
* nvme-multipath
* parport
* perf-security
* pm/index
* pnp
* rapidio
* ras
* rtc
* serial-console
* svga
* thermal/index
* thunderbolt
* ufs
* vga-softcursor
* video-output
* xfs
工作负载分析
------------
这是一个章节的开始,其中包含对从事 Linux 内核安全关键性分析的应用程序开发人员
和系统集成商感兴趣的信息。这里可以找到支持分析内核与应用程序交互以及关键内核
子系统预期的文档。
.. toctree::
:maxdepth: 1
Todolist:
* workload-tracing
其他内容
--------
一些难以分类且通常已过时的文档。
.. toctree::
:maxdepth: 1
Todolist:
* highuid
* ldm
* unicode
.. only:: subproject and html
Indices
=======
索引
====
* :ref:`genindex`

View File

@@ -0,0 +1,250 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/admin-guide/module-signing.rst
:翻译:
朱岩 Yan Zhu <zhuyan2015@qq.com>
================
内核模块签名机制
================
.. 目录
..
.. - 概述
.. - 配置模块签名
.. - 生成签名密钥
.. - 内核中的公钥
.. - 模块手动签名
.. - 已签名模块和剥离
.. - 加载已签名模块
.. - 无效签名和未签名模块
.. - 管理/保护私钥
概述
====
内核模块签名机制在安装过程中对模块进行加密签名,然后在加载模块时检查签名。这
通过禁止加载未签名的模块或使用无效密钥签名的模块来提高内核安全性。模块签名通
过使恶意模块更难加载到内核中来增加安全性。模块签名检查在内核中完成,因此不需
要受信任的用户空间位。
此机制使用 X.509 ITU-T 标准证书对涉及的公钥进行编码。签名本身不以任何工业标准
类型编码。内置机制目前仅支持 RSA、NIST P-384 ECDSA 和 NIST FIPS-204 ML-DSA
公钥签名标准(尽管它是可插拔的并允许使用其他标准)。对于 RSA 和 ECDSA可以使
用的可能的哈希算法是大小为 256、384 和 512 的 SHA-2 和 SHA-3算法由签名中的
数据选择ML-DSA 会自行进行哈希运算,但允许与 SHA512 哈希算法结合用于签名属
性。
配置模块签名
============
通过进入内核配置的 :menuselection:`Enable Loadable Module Support` 菜单并打
开以下选项来启用模块签名机制::
CONFIG_MODULE_SIG "Module signature verification"
这有多个可用选项:
(1) :menuselection:`Require modules to be validly signed`
(``CONFIG_MODULE_SIG_FORCE``)
这指定了内核应如何处理其密钥未知或未签名的模块。
如果关闭(即"宽松模式"),则允许使用不可用密钥和未签名的模块,但内核将被
标记为受污染,并且相关模块将被标记为受污染,显示字符'E'。
如果打开(即"限制模式"),只有具有有效签名且可由内核拥有的公钥验证的模块
才会被加载。所有其他模块将生成错误。
无论此处的设置如何,如果模块的签名块无法解析,它将被直接拒绝。
(2) :menuselection:`Automatically sign all modules`
(``CONFIG_MODULE_SIG_ALL``)
如果打开此选项,则在构建的 modules_install 阶段期间将自动签名模块。
如果关闭,则必须使用以下命令手动签名模块::
scripts/sign-file
(3) :menuselection:`Which hash algorithm should modules be signed with?`
这提供了安装阶段将用于签名模块的哈希算法选择:
=============================== ==========================================
``CONFIG_MODULE_SIG_SHA256`` :menuselection:`Sign modules with SHA-256`
``CONFIG_MODULE_SIG_SHA384`` :menuselection:`Sign modules with SHA-384`
``CONFIG_MODULE_SIG_SHA512`` :menuselection:`Sign modules with SHA-512`
``CONFIG_MODULE_SIG_SHA3_256`` :menuselection:`Sign modules with SHA3-256`
``CONFIG_MODULE_SIG_SHA3_384`` :menuselection:`Sign modules with SHA3-384`
``CONFIG_MODULE_SIG_SHA3_512`` :menuselection:`Sign modules with SHA3-512`
=============================== ==========================================
此处选择的算法也将被构建到内核中(而不是作为模块),以便使用该算法签名的
模块可以在不导致循环依赖的情况下检查其签名。
(4) :menuselection:`File name or PKCS#11 URI of module signing key`
(``CONFIG_MODULE_SIG_KEY``)
将此选项设置为除默认值 ``certs/signing_key.pem`` 之外的其他值将禁用签名
密钥的自动生成,并允许使用您选择的密钥对内核模块进行签名。提供的字符串应
标识包含私钥及其对应的 PEM 格式 X.509 证书的文件,或者在 OpenSSL
ENGINE_pkcs11 功能正常的系统上,使用 RFC7512 定义的 PKCS#11 URI。在后一
种情况下PKCS#11 URI 应引用证书和私钥。
如果包含私钥的 PEM 文件已加密,或者 PKCS#11 令牌需要 PIN可以通过
``KBUILD_SIGN_PIN`` 变量在构建时提供。
(5) :menuselection:`Additional X.509 keys for default system keyring`
(``CONFIG_SYSTEM_TRUSTED_KEYS``)
此选项可设置为包含附加证书的 PEM 编码文件的文件名,这些证书将默认包含在
系统密钥环中。
请注意,启用模块签名会为内核构建过程添加对执行签名工具的 OpenSSL 开发包的依赖。
生成签名密钥
============
生成和检查签名需要加密密钥对。私钥用于生成签名,相应的公钥用于检查签名。私钥
仅在构建期间需要,之后可以删除或安全存储。公钥被构建到内核中,以便在加载模块
时可以使用它来检查签名。
在正常情况下,当 ``CONFIG_MODULE_SIG_KEY`` 保持默认值时,如果文件中不存在密
钥对,内核构建将使用 openssl 自动生成新的密钥对::
certs/signing_key.pem
在构建 vmlinux 期间(公钥需要构建到 vmlinux 中)使用参数::
certs/x509.genkey
文件(如果尚不存在也会生成)。
可以在 RSA``MODULE_SIG_KEY_TYPE_RSA``)、
ECDSA``MODULE_SIG_KEY_TYPE_ECDSA``)和
ML-DSA``MODULE_SIG_KEY_TYPE_MLDSA_*``)之间选择生成 RSA 4k、NIST P-384
密钥对或 ML-DSA 44、65 或 87 密钥对。
强烈建议您提供自己的 x509.genkey 文件。
最值得注意的是,在 x509.genkey 文件中req_distinguished_name 部分应从默认值
更改::
[ req_distinguished_name ]
#O = Unspecified company
CN = Build time autogenerated kernel key
#emailAddress = unspecified.user@unspecified.company
生成的 RSA 密钥大小也可以通过以下方式设置::
[ req ]
default_bits = 4096
也可以使用位于 Linux 内核源代码树根节点中的 x509.genkey 密钥生成配置文件和
openssl 命令手动生成公钥/私钥文件。以下是生成公钥/私钥文件的示例::
openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
-config x509.genkey -outform PEM -out kernel_key.pem \
-keyout kernel_key.pem
然后可以将生成的 kernel_key.pem 文件的完整路径名指定在
``CONFIG_MODULE_SIG_KEY`` 选项中,并且将使用其中的证书和密钥而不是自动生成的
密钥对。
内核中的公钥
============
内核包含一个可由 root 查看的公钥环。它们在名为 ".builtin_trusted_keys" 的密
钥环中,可以通过以下方式查看::
[root@deneb ~]# cat /proc/keys
...
223c7853 I------ 1 perm 1f030000 0 0 keyring .builtin_trusted_keys: 1
302d2d52 I------ 1 perm 1f010000 0 0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
除了专门为模块签名生成的公钥外,还可以在 ``CONFIG_SYSTEM_TRUSTED_KEYS`` 配置
选项引用的 PEM 编码文件中提供其他受信任的证书。
此外,架构代码可以从硬件存储中获取公钥并将其添加(例如从 UEFI 密钥数据库)。
最后,可以通过以下方式添加其他公钥::
keyctl padd asymmetric "" [.builtin_trusted_keys-ID] <[key-file]
例如::
keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509
但是,请注意,内核只允许将由已驻留在 ``.builtin_trusted_keys`` 中的密钥有效
签名的密钥添加到 ``.builtin_trusted_keys``
模块手动签名
============
要手动对模块进行签名,请使用 Linux 内核源代码树中可用的 scripts/sign-file 工
具。该脚本需要 4 个参数:
1. 哈希算法例如sha256
2. 私钥文件名或 PKCS#11 URI
3. 公钥文件名
4. 要签名的内核模块
以下是签名内核模块的示例::
scripts/sign-file sha512 kernel-signkey.priv \
kernel-signkey.x509 module.ko
使用的哈希算法不必与配置的算法匹配,但如果不同,应确保哈希算法要么内置在内核
中,要么可以在不需要自身的情况下加载。
如果私钥需要密码或 PIN可以在 $KBUILD_SIGN_PIN 环境变量中提供。
已签名模块和剥离
================
已签名模块在末尾简单地附加了数字签名。模块文件末尾的字符串
``~Module signature appended~.`` 确认签名存在,但不能确认签名有效!
已签名模块是脆弱的因为签名在定义的ELF容器之外。因此一旦计算并附加签名
不得剥离它们。请注意,整个模块都是签名的有效载荷,包括签名时存在的任何和所有
调试信息。
加载已签名模块
==============
模块通过 insmod、modprobe、 ``init_module()````finit_module()`` 加载,
与未签名模块完全一样,因为在用户空间中不进行任何处理。
所有签名检查都在内核内完成。
无效签名和未签名模块
====================
如果启用了 ``CONFIG_MODULE_SIG_FORCE`` 或在内核启动命令提供了
module.sig_enforce=1内核将仅加载具有有效签名且具有公钥的模块。否则它还将
加载未签名的模块。任何具有不匹配签名的模块将不被允许加载。
任何具有不可解析签名的模块将被拒绝。
管理/保护私钥
==============
由于私钥用于签名模块,病毒和恶意软件可以使用私钥签名模块并危害操作系统。私钥
必须被销毁或移动到安全位置,而不是保存在内核源代码树的根节点中。
如果使用相同的私钥为多个内核配置签名模块,必须确保模块版本信息足以防止将模块
加载到不同的内核中。要么设置 ``CONFIG_MODVERSIONS=y``,要么通过更改
``EXTRAVERSION````CONFIG_LOCALVERSION`` 确保每个配置具有不同的内核发布字
符串。

View File

@@ -79,7 +79,7 @@ KASAN只支持SLUB。
CONFIG_KASAN=y
同时在 ``CONFIG_KASAN_GENERIC`` (启用通用KASAN模式) ``CONFIG_KASAN_SW_TAGS``
(启用基于件标签的KASAN模式),和 ``CONFIG_KASAN_HW_TAGS`` (启用基于硬件标签
(启用基于件标签的KASAN模式),和 ``CONFIG_KASAN_HW_TAGS`` (启用基于硬件标签
的KASAN模式)之间进行选择。
对于软件模式,还可以在 ``CONFIG_KASAN_OUTLINE````CONFIG_KASAN_INLINE``

View File

@@ -13,20 +13,20 @@ Linux 内核中文文档翻译规范
过去几年在广大社区爱好者的友好合作下Linux 内核中文文档迎来了蓬勃的发
展。在翻译的早期,一切都是混乱的,社区对译稿只有一个准确翻译的要求,以鼓
励更多的开发者参与进来,这是从 0 到 1 的必然过程,所以早期的中文文档目录
更加具有多样性,不过好在文档不多,维护上并没有过大的压力。
呈现出较强的多样性,不过好在文档不多,维护上并没有过大的压力。
然而,世事变幻,不觉有年,现在内核中文文档在前进的道路上越走越远,很多潜
在的问题逐渐浮出水面,而且随着中文文档数量的增加,翻译更多的文档与提高中
文文档可维护性之间的矛盾愈发尖锐。由于文档翻译的特殊性,很多开发者并不会
一直更新文档,如果中文文档落后英文文档太多,文档更新的工作量会远大于重新
翻译。而且邮件列表中陆续有新的面孔出现,他们那股热情,就像燃烧的火焰,能
瞬间点燃整个空间,可是他们的补丁往往具有个性,这给审阅带来了很大的困难,
瞬间点燃整个空间,可是他们的补丁往往具有个性,这给审阅带来了很大的困难,
reviewer 们只能耐心地指导他们如何与社区更好地合作,但是这项工作具有重复
性,长此以往,会渐渐浇灭 reviewer 审阅的热情。
虽然内核文档中已经有了类似的贡献指南,但是缺乏专门针对于中文翻译的,尤其
虽然内核文档中已经有了类似的贡献指南,但是缺乏专门面向中文翻译的,尤其
是对于新手来说,浏览大量的文档反而更加迷惑,该文档就是为了缓解这一问题而
编写,目的是为提供给新手一个快速翻译指南。
编写,旨在为新手提供一份快速翻译指南。
详细的贡献指南Documentation/translations/zh_CN/process/index.rst。
@@ -145,8 +145,8 @@ Git 和邮箱配置
sudo dnf install git-email
vim ~/.gitconfig
这里是我的一个配置文件示范,请根据您的邮箱域名服务商提供的手册替换
的字段。
这里是我的一个配置文件示范,请根据您的邮箱域名服务商提供的手册替换对
的字段。
::
[user]
@@ -190,7 +190,7 @@ Git 和邮箱配置
译文格式要求
------------
- 每行长度最多不超过 40 个字符
- 每行长度不超过 40 个字符
- 每行长度请保持一致
- 标题的下划线长度请按照一个英文一个字符、一个中文两个字符与标题对齐
- 其它的修饰符请与英文文档保持一致
@@ -211,7 +211,7 @@ Git 和邮箱配置
--------
中文文档有每行 40 字符限制,因为一个中文字符等于 2 个英文字符。但是社区并
没有那么严格,一个诀窍是将您翻译的内容与英文原文的每行长度对齐即可,这样,
没有那么严格,一个诀窍是将您翻译的内容与英文原文的每行长度对齐,这样,
您也不必总是检查有没有超限。
如果您的英文阅读能力有限,可以考虑使用辅助翻译工具,例如 deepseek。但是您
@@ -257,7 +257,9 @@ Git 和邮箱配置
Update the translation through commit b080e52110ea
("docs: update self-protection __ro_after_init status")
# 请执行 git log --oneline <您翻译的英文文档路径>,并替换上述内容
# 请执行 git log --no-merges --oneline <您翻译的英文文档路径>
# 并替换上述内容。注意:应引用实际修改文件内容的 commit
# 而非 merge commit
Signed-off-by: Yanteng Si <si.yanteng@linux.dev>
# 如果您前面的步骤正确执行,该行会自动显示,否则请检查 gitconfig 文件
@@ -267,13 +269,22 @@ Git 和邮箱配置
**请注意** 以上四行,缺少任何一行,您都将会在第一轮审阅后返工,如果您需要一个
更加明确的示例,请对 zh_CN 目录执行 git log。
导出补丁和制作封面
------------------
导出补丁
--------
这个时候,可以导出补丁,做发送邮件列表最后的准备了。命令行执行::
这个时候,可以导出补丁,做发送邮件列表最后的准备了。对于单个补丁,
命令行执行::
git format-patch -1
然后命令行会输出类似下面的内容::
0001-docs-zh_CN-add-xxxxxxxx.patch
如果您有多个补丁,命令行执行::
git format-patch -N
# N 要替换为补丁数量,一般 N 大于等于 1
# N 要替换为补丁数量,一般 N 大于 1
然后命令行会输出类似下面的内容::
@@ -288,13 +299,12 @@ Git 和邮箱配置
./scripts/checkpatch.pl *.patch
参考脚本输出,解决掉所有的 error 和 warning通常情况下,只有下面这个
参考脚本输出,解决掉所有的 error 和 warning通常情况下,只有下面这个
warning 不需要解决::
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
一个简单的解决方法是一次只检查一个补丁,然后打上该补丁,直接对译文进行修改,
然后执行以下命令为补丁追加更改::
对于单个补丁,解决方案很简单,只需要打上该补丁,直接对译文进行修改,为补丁追加后续更改::
git checkout docs-next
git checkout -b test-trans-new
@@ -302,15 +312,21 @@ warning 不需要解决::
./scripts/checkpatch.pl 0001-xxxxx.patch
# 直接修改您的翻译
git add .
git am --amend
git commit --amend
# 保存退出
git am 0002-xxxxx.patch
……
重新导出再次检测,重复这个过程,直到处理完所有的补丁。
随后,重新导出补丁再次检测,重复这个过程,直到处理完所有 warning 和
error。
最后,如果检测时没有 warning 和 error 需要被处理或者您只有一个补丁,请跳
过下面这个步骤,否则请重新导出补丁制作封面::
如果您有多个补丁,请按补丁集中补丁顺序对每个补丁重复上述流程,一次只处理
一个,不要一次 git am 多个补丁。全部处理完毕后再重新导出并再次测试。
为补丁集制作封面
----------------
对于单个补丁,请跳过本节。
如果您有多个补丁,则需要为补丁集制作一份封面,即 0 号补丁::
git format-patch -N --cover-letter --thread=shallow
# N 要替换为补丁数量,一般 N 大于 1
@@ -327,18 +343,14 @@ warning 不需要解决::
vim 0000-cover-letter.patch
...
Subject: [PATCH 0/N] *** SUBJECT HERE *** #修改该字段,概括您的补丁集都做了哪些事情
Subject: [PATCH 0/N] *** SUBJECT HERE *** # 修改该字段,概括您的补丁集都做了哪些事情
*** BLURB HERE *** #修改该字段,详细描述您的补丁集做了哪些事情
*** BLURB HERE *** # 修改该字段,详细描述您的补丁集做了哪些事情
Yanteng Si (1):
docs/zh_CN: add xxxxx
...
如果您只有一个补丁,则可以不制作封面,即 0 号补丁,只需要执行::
git format-patch -1
把补丁提交到邮件列表
====================
@@ -361,13 +373,13 @@ warning 不需要解决::
git send-email *.patch --to <maintainer email addr> --cc <others addr>
# 一个 to 对应一个地址,一个 cc 对应一个地址,有几个就写几个
执行该命令时,请确保网络通,邮件发送成功一般会返回 250。
执行该命令时,请确保网络通,邮件发送成功一般会返回 250。
您可以先发送给自己,尝试发出的 patch 是否可以用 'git am' 工具正常打上。
如果检查正常, 您就可以放心的发送到社区评审了。
如果该步骤被中断,您可以检查一下,继续用上条命令发送失败的补丁,一定不要再
次发送已经发送成功的补丁。
如果该步骤被中断,您可以检查一下,然后用上条命令继续发送失败的补丁,一定不
要再次发送已经发送成功的补丁。
积极参与审阅过程并迭代补丁
==========================
@@ -380,7 +392,7 @@ reviewer 的评论,做到每条都有回复,每个回复都落实到位。
- 请先将您的邮箱客户端信件回复修改为 **纯文本** 格式,并去除所有签名,尤其是
企业邮箱。
- 然后点击回复按钮,并要回复的邮件带入
- 然后点击回复按钮,并引用要回复的邮件,
- 在第一条评论行尾换行,输入您的回复
- 在第二条评论行尾换行,输入您的回复
- 直到处理完最后一条评论,换行空两行输入问候语和署名
@@ -390,28 +402,67 @@ reviewer 的评论,做到每条都有回复,每个回复都落实到位。
迭代补丁
--------
建议您每回复一条评论,就修改一处翻译然后重新生成补丁,相信您现在已经具
备了灵活使用 git am --amend 的能力。
建议您每回复一条评论,就修改一处翻译然后重新生成补丁,相信您现在
已经具备了灵活使用 git am 与 git commit --amend 的能力。
每次迭代一个补丁,不要一次多个::
对于单个补丁,每回复完评论后修改、追加::
git am <您要修改的补丁>
git am 0001-xxxxx.patch
# 直接对文件进行您的修改
git add .
git commit --amend
当您将所有的评论落实到位后,导出第二版补丁,并修改封面::
当您将所有的评论落实到位后,导出第二版补丁::
git format-patch -1 -v 2
命令行会输出 v2-0001-xxxxx.patch。打开该文件在 --- 分割线下方追加
changelog。注意分割线以下的内容不会进入 git 提交历史,仅作为邮件中的
说明供 reviewer 检查::
Subject: [PATCH v2] docs/zh_CN: add xxxxxx translation
Translate .../xxx.rst into Chinese.
Signed-off-by: Yanteng Si <si.yanteng@linux.dev>
---
v1->v2:
- 修正第二节的错别字Reviewer-A 提出的意见
- 根据 Reviewer-B 的建议调整段落顺序
Documentation/translations/zh_CN/xxx.rst | 100 ++++++
1 file changed, 100 insertions(+)
后续迭代 v3、v4 …… 时,新的 changelog 放在最上面,旧的保留在下方,按
从新到旧的顺序叠加。例如 v3 补丁的 --- 下方::
---
v2->v3:
- ...本次相较 v2 的改动...
v1->v2:
- ...上一次相较 v1 的改动...
然后发送::
git send-email v2-0001-*.patch --to <maintainer email addr> --cc <others addr>
如果您有多个补丁,迭代时请按以下原则:每次只迭代一个补丁,不要一次多个,
每个补丁独立重复上述流程。所有评论落实到位后,导出 v2 时附带封面::
git format-patch -N -v 2 --cover-letter --thread=shallow
打开 0 号补丁,在 BLURB HERE 处编写相较于上个版本,您做了哪些改动。
打开 0 号补丁,在 BLURB HERE 处写明整组补丁相较 v1 的总体改动,格式
同上面的单个补丁 changelog 示例。如果某个补丁需要单独说明,可在该
补丁文件的 --- 分割线下方追加单个补丁的 changelog。最后执行::
然后执行::
git send-email v2* --to <maintainer email addr> --cc <others addr>
git send-email v2-*.patch --to <maintainer email addr> --cc <others addr>
这样,新的一版补丁就又发送到邮件列表等待审阅,之后就是重复这个过程。
此外,如果审阅者或维护者在邮件回复中给出了 Reviewed-by tag请在下
一版补丁的 commit 信息中加入该 tag放在 Signed-off-by 行的下方,以
便维护者合入时保留您的审阅记录。
审阅周期
--------
@@ -425,10 +476,10 @@ reviewer 的评论,做到每条都有回复,每个回复都落实到位。
紧急处理
--------
如果您发送到邮件列表之后发现发错了补丁集,尤其是在多个版本迭代的过程中;
如果您发送到邮件列表之后发现发错了补丁集,尤其是在多个版本迭代的过程中;
自己发现了一些不妥的翻译;发送错了邮件列表……
git email 默认会抄送给您一份,所以您可以切换为审阅者的角色审查自己的补丁,
git send-email 默认会抄送给您一份,所以您可以切换为审阅者的角色审查自己的补丁,
并留下评论,描述有何不妥,将在下个版本怎么改,并付诸行动,重新提交,但是
注意频率,每天提交的次数不要超过两次。
@@ -437,7 +488,7 @@ git email 默认会抄送给您一份,所以您可以切换为审阅者的角
对于首次参与 Linux 内核中文文档翻译的新手,建议您在 linux 目录中运行以下命令:
::
tools/docs/checktransupdate.py -l zh_CN``
tools/docs/checktransupdate.py -l zh_CN
该命令会列出需要翻译或更新的英文文档,结果同时保存在 checktransupdate.log 中。
@@ -446,9 +497,9 @@ git email 默认会抄送给您一份,所以您可以切换为审阅者的角
进阶
----
希望您不只是单纯翻译内核文档,在熟悉了一起与社区作之后,您可以审阅其他
希望您不只是单纯翻译内核文档,在熟悉了与社区作之后,您可以审阅其他
开发者的翻译,或者提出具有建设性的主张。与此同时,与文档对应的代码更加有趣,
而且需要完善的地方还有很多,勇敢地去探索,然后提交的想法吧。
而且需要完善的地方还有很多,勇敢地去探索,然后提交的想法吧。
常见的问题
==========
@@ -467,7 +518,7 @@ Maintainer 回复补丁不能正常 apply
------------------
大部分情况下,是由于您发送了非纯文本格式的信件,请尽量避免使用 webmail推荐
使用邮件客户端,比如 thunderbird记得在设置的回信配置改为纯文本发送。
使用邮件客户端,比如 thunderbird记得在设置的回信配置改为纯文本发送。
如果超过了 24 小时,您依旧没有在<https://lore.kernel.org/linux-doc/>发现您的
邮件,请联系您的网络管理员帮忙解决。
如果超过了 24 小时,您依旧没有在 https://lore.kernel.org/linux-doc/ 上找到您
邮件,请联系您的网络管理员帮忙解决。

View File

@@ -23,6 +23,7 @@
``arm64`` Maintained 仅小端序。
``loongarch`` Maintained \-
``riscv`` Maintained 仅 ``riscv64``,且仅限 LLVM/Clang。
``s390`` Maintained 必须禁用 ``CONFIG_EXPOLINE``
``um`` Maintained \-
``x86`` Maintained 仅 ``x86_64``
============= ================ ==============================================

View File

@@ -13,6 +13,14 @@
本文档包含了在内核中使用Rust支持时需要了解的有用信息。
``no_std``
----------
内核中的 Rust 支持只能链接 `core <https://doc.rust-lang.org/core/>`_
而不能链接 `std <https://doc.rust-lang.org/std/>`_。供内核使用的 crate
必须使用 ``#![no_std]`` 属性选择这种行为。
.. _rust_code_documentation_zh_cn:
代码文档
@@ -20,10 +28,18 @@
Rust内核代码使用其内置的文档生成器 ``rustdoc`` 进行记录。
生成的HTML文档包括集成搜索、链接项如类型、函数、常量、源代码等。它们可以在以下地址阅读
TODO当在主线中时链接与其他文档一起生成
生成的 HTML 文档包括集成搜索、链接项(如类型、函数、常量)、源代码等。
它们可以在以下地址阅读
http://kernel.org/
https://rust.docs.kernel.org
对于 linux-next请参阅
https://rust.docs.kernel.org/next/
每个主要版本也有对应的标签,例如:
https://rust.docs.kernel.org/6.10/
这些文档也可以很容易地在本地生成和阅读。这相当快(与编译代码本身的顺序相同),而且不需要特
殊的工具或环境。这有一个额外的好处,那就是它们将根据所使用的特定内核配置进行定制。要生成它
@@ -62,6 +78,58 @@ Rust内核代码使用其内置的文档生成器 ``rustdoc`` 进行记录。
模块例如驱动程序不应该直接使用C语言的绑定。相反子系统应该根据需要提供尽可能安
全的抽象。
.. code-block::
rust/bindings/
(rust/helpers/)
include/ -----+ <-+
| |
drivers/ rust/kernel/ +----------+ <-+ |
fs/ | bindgen | |
.../ +-------------------+ +----------+ --+ |
| Abstractions | | |
+---------+ | +------+ +------+ | +----------+ | |
| my_foo | -----> | | foo | | bar | | -------> | Bindings | <-+ |
| driver | Safe | | sub- | | sub- | | Unsafe | | |
+---------+ | |system| |system| | | bindings | <-----+
| | +------+ +------+ | | crate | |
| | kernel crate | +----------+ |
| +-------------------+ |
| |
+------------------# FORBIDDEN #--------------------------------+
主要思想是将所有与内核 C API 的直接交互封装到经过仔细审查和文档化的抽象
中。这样,只要满足以下条件,这些抽象的用户就不能引入未定义行为
undefined behaviorUB
#. 抽象是正确的("可靠")。
#. 任何 ``unsafe`` 块都遵守调用块内操作所需的安全契约。类似地,任何
``unsafe impl`` 都遵守实现该特性所需的安全契约。
绑定
~~~~
通过从 ``include/`` 中将 C 头文件包含到
``rust/bindings/bindings_helper.h`` ``bindgen`` 工具将为所包含的子系统
自动生成绑定。构建后,请查看 ``rust/bindings/`` 目录中的
``*_generated.rs`` 输出文件。
对于 ``bindgen`` 不会自动生成的 C 头文件部分,例如 C ``inline`` 函数或
非平凡宏,可以在 ``rust/helpers/`` 中添加一个小型包装函数,使其也可供
Rust 端使用。
抽象
~~~~
抽象是绑定和内核内用户之间的层。它们位于 ``rust/kernel/`` 中,其作用是
将对绑定的不安全访问封装到尽可能安全并暴露给用户的 API 中。抽象的用户
包括用 Rust 编写的驱动程序或文件系统等。
除了安全方面,这些抽象还应该易于使用,也就是说,把 C 接口转换为符合
Rust 惯例的代码。基本示例包括将 C 的资源获取和释放转换为 Rust 的初始化
和清理模式,或者将 C 整数错误码转换为 Rust 的 ``Result``
有条件的编译
------------
@@ -74,3 +142,11 @@ Rust代码可以访问基于内核配置的条件性编译:
#[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`)
#[cfg(CONFIG_X="m")] // Enabled as a module (`m`)
#[cfg(not(CONFIG_X))] // Disabled
对于 Rust 的 ``cfg`` 不支持的其他条件,例如带有数值比较的表达式,可以
定义一个新的 Kconfig 符号:
.. code-block:: kconfig
config RUSTC_HAS_SPAN_FILE
def_bool RUSTC_VERSION >= 108800

View File

@@ -59,7 +59,7 @@ Fedora Linux 提供较新的 Rust 版本,因此通常开箱即用,例如::
Gentoo Linux
************
Gentoo Linux(尤其是 testing 分支)提供较新的 Rust 版本,因此通常开箱即用,
Gentoo Linux 提供较新的 Rust 版本,因此通常开箱即用,
例如::
USE='rust-src rustfmt clippy' emerge dev-lang/rust dev-util/bindgen
@@ -70,7 +70,7 @@ Gentoo Linux尤其是 testing 分支)提供较新的 Rust 版本,因此
Nix
***
Nixunstable 频道)提供较新的 Rust 版本,因此通常开箱即用,例如::
Nix 提供较新的 Rust 版本,因此通常开箱即用,例如::
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
@@ -85,16 +85,14 @@ openSUSE
openSUSE Slowroll 和 openSUSE Tumbleweed 提供较新的 Rust 版本,因此通常开箱
即用,例如::
zypper install rust rust1.79-src rust-bindgen clang
zypper install rust rust-src rust-bindgen clang
Ubuntu
******
25.04
~~~~~
最新的 Ubuntu 版本提供较新的 Rust 版本,因此通常开箱即用,例如::
Ubuntu 25.10 和 26.04 LTS 提供较新的 Rust 版本,因此通常开箱即用,
例如::
apt install rustc rust-src bindgen rustfmt rust-clippy
@@ -111,32 +109,32 @@ Ubuntu
虽然 Ubuntu 24.04 LTS 及更早版本仍然提供较新的 Rust 版本,但它们需要一些额外的配
置,使用带版本号的软件包,例如::
apt install rustc-1.80 rust-1.80-src bindgen-0.65 rustfmt-1.80 \
rust-1.80-clippy
ln -s /usr/lib/rust-1.80/bin/rustfmt /usr/bin/rustfmt-1.80
ln -s /usr/lib/rust-1.80/bin/clippy-driver /usr/bin/clippy-driver-1.80
apt install rustc-1.85 rust-1.85-src bindgen-0.71 rustfmt-1.85 \
rust-1.85-clippy
ln -s /usr/lib/rust-1.85/bin/rustfmt /usr/bin/rustfmt-1.85
ln -s /usr/lib/rust-1.85/bin/clippy-driver /usr/bin/clippy-driver-1.85
这些软件包都不会将其工具设置为默认值;因此应该显式指定它们,例如::
make LLVM=1 RUSTC=rustc-1.80 RUSTDOC=rustdoc-1.80 RUSTFMT=rustfmt-1.80 \
CLIPPY_DRIVER=clippy-driver-1.80 BINDGEN=bindgen-0.65
make LLVM=1 RUSTC=rustc-1.85 RUSTDOC=rustdoc-1.85 RUSTFMT=rustfmt-1.85 \
CLIPPY_DRIVER=clippy-driver-1.85 BINDGEN=bindgen-0.71
或者,修改 ``PATH`` 变量将 Rust 1.80 的二进制文件放在前面,并将 ``bindgen``
或者,修改 ``PATH`` 变量将 Rust 1.85 的二进制文件放在前面,并将 ``bindgen``
置为默认值,例如::
PATH=/usr/lib/rust-1.80/bin:$PATH
PATH=/usr/lib/rust-1.85/bin:$PATH
update-alternatives --install /usr/bin/bindgen bindgen \
/usr/bin/bindgen-0.65 100
update-alternatives --set bindgen /usr/bin/bindgen-0.65
/usr/bin/bindgen-0.71 100
update-alternatives --set bindgen /usr/bin/bindgen-0.71
使用带版本号的软件包时需要设置 ``RUST_LIB_SRC``,例如::
使用带版本号的软件包时可能需要设置 ``RUST_LIB_SRC``,例如::
RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.80 --version | cut -d' ' -f2)/library
RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.85 --version | cut -d' ' -f2)/library
为方便起见,可以将 ``RUST_LIB_SRC`` 导出到全局环境中。
此外, ``bindgen-0.65`` 在较新的版本24.04 LTS 和 24.10)中可用,但在更早的版
20.04 LTS 和 22.04 LTS中可能不可用因此可能需要手动构建 ``bindgen``
此外, ``bindgen-0.71`` 在较新的版本24.04 LTS中可用但在更早的版
20.04 LTS 和 22.04 LTS中可能不可用因此可能需要手动构建 ``bindgen``
(请参见下文)。
@@ -325,11 +323,3 @@ Rust支持CONFIG_RUST需要在 ``General setup`` 菜单中启用。在其
要想深入了解,请看 ``samples/rust/`` 下的样例源代码、 ``rust/`` 下的Rust支持代码和
``Kernel hacking`` 下的 ``Rust hacking`` 菜单。
如果使用的是GDB/Binutils而Rust符号没有被demangled原因是工具链还不支持Rust的新v0
mangling方案。有几个办法可以解决
- 安装一个较新的版本GDB >= 10.2, Binutils >= 2.36)。
- 一些版本的GDB例如vanilla GDB 10.1)能够使用嵌入在调试信息(``CONFIG_DEBUG_INFO``)
中的pre-demangled的名字。

View File

@@ -128,10 +128,13 @@ Rust 测试中常用的断言宏是来自 Rust 标准库( ``core`` )中的 `
这些测试通过 ``kunit_tests`` 过程宏引入,该宏将测试套件的名称作为参数。
每个测试套件都应该由 ``rust/kernel/Kconfig.test`` 中的 Kconfig 选项保护。
例如,假设想要测试前面文档测试示例中的函数 ``f``,我们可以在定义该函数的同一文件中编写:
.. code-block:: rust
#[cfg(CONFIG_RUST_MYMOD_KUNIT_TEST)]
#[kunit_tests(rust_kernel_mymod)]
mod tests {
use super::*;
@@ -158,6 +161,7 @@ Rust 测试中常用的断言宏是来自 Rust 标准库( ``core`` )中的 `
.. code-block:: rust
#[cfg(CONFIG_RUST_MYMOD_KUNIT_TEST)]
#[kunit_tests(rust_kernel_mymod)]
mod tests {
use super::*;

View File

@@ -119,7 +119,7 @@ EAS覆盖了CFS的任务唤醒平衡代码。在唤醒平衡时它使用平
如果唤醒的任务被迁移find_energy_efficient_cpu()使用compute_energy()来估算
系统将消耗多少能量。compute_energy()检查各CPU当前的利用率情况并尝试调整来
“模拟”任务迁移。EM框架提供了API em_pd_energy()计算每个性能域在给定的利用率条件
“模拟”任务迁移。EM框架提供了API em_cpu_energy()计算每个性能域在给定的利用率条件
下的预期能量消耗。
下面详细介绍一个优化能量消耗的任务放置决策的例子。

View File

@@ -97,7 +97,7 @@ ARCH_OPTIONAL_KERNEL_RWX时的默认设置。
--------------------
对于64位系统一种消除许多系统调用最简单的方法是构建时不启用
CONFIG_CONPAT。然而这种情况通常不可行。
CONFIG_COMPAT。然而这种情况通常不可行。
“seccomp”系统为用户空间提供了一种可选功能提供了一种减少可供
运行中进程使用内核入口点数量的方法。这限制了可以访问内核代码

View File

@@ -14,21 +14,21 @@
中文版校譯者: 李陽 Li Yang <leoyang.li@nxp.com>
胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
Linux 內核驅動接口
Linux 內核驅動介面
==================
寫作本文檔的目的是爲了解釋爲什麼Linux既沒有二進制內核接口,也沒有穩定
的內核接口。這裏所說的內核接口,是指內核裏的接口,而不是內核和用戶空間
接口。內核到用戶空間的接口,是提供給應用程序使用的系統調用,系統調用
寫作本文檔的目的是爲了解釋爲什麼Linux既沒有二進制內核介面,也沒有穩定
的內核介面。這裏所說的內核介面,是指內核裏的介面,而不是內核和用戶空間
介面。內核到用戶空間的介面,是提供給應用程序使用的系統調用,系統調用
在歷史上幾乎沒有過變化將來也不會有變化。我有一些老應用程序是在0.9版本
或者更早版本的內核上編譯的在使用2.6版本內核的Linux發佈上依然用得很好
。用戶和應用程序作者可以將這個接口看成是穩定的。
。用戶和應用程序作者可以將這個介面看成是穩定的。
執行綱要
--------
你也許以爲自己想要穩定的內核接口,但是你不清楚你要的實際上不是它。你需
你也許以爲自己想要穩定的內核介面,但是你不清楚你要的實際上不是它。你需
要的其實是穩定的驅動程序,而你只有將驅動程序放到公版內核的源代碼樹裏,
纔有可能達到這個目的。而且這樣做還有很多其它好處,正是因爲這些好處使得
Linux能成爲強壯穩定成熟的操作系統這也是你最開始選擇Linux的原因。
@@ -37,8 +37,8 @@ Linux能成爲強壯穩定成熟的操作系統這也是你最開始選
入門
-----
只有那些寫驅動程序的“怪人”纔會擔心內核接口的改變,對廣大用戶來說,既
看不到內核接口,也不需要去關心它。
只有那些寫驅動程序的“怪人”纔會擔心內核介面的改變,對廣大用戶來說,既
看不到內核介面,也不需要去關心它。
首先我不打算討論關於任何非GPL許可的內核驅動的法律問題這些非GPL許可
的驅動程序包括不公開源代碼,隱藏源代碼,二進制或者是用源代碼包裝,或者
@@ -46,14 +46,14 @@ Linux能成爲強壯穩定成熟的操作系統這也是你最開始選
詢律師,我只是一個程序員,所以我只打算探討技術問題(不是小看法律問題,
法律問題很實際,並且需要一直關注)。
既然只談技術問題,我們就有了下面兩個主題:二進制內核接口和穩定的內核源
代碼接口。這兩個問題是互相關聯的,讓我們先解決掉二進制接口的問題。
既然只談技術問題,我們就有了下面兩個主題:二進制內核介面和穩定的內核源
代碼介面。這兩個問題是互相關聯的,讓我們先解決掉二進制介面的問題。
二進制內核接口
二進制內核介面
--------------
假如我們有一個穩定的內核源代碼接口,那麼自然而然的,我們就擁有了穩定的
二進制接口是這樣的嗎錯。讓我們看看關於Linux內核的幾點事實
假如我們有一個穩定的內核源代碼介面,那麼自然而然的,我們就擁有了穩定的
二進制介面是這樣的嗎錯。讓我們看看關於Linux內核的幾點事實
- 取決於所用的C編譯器的版本不同的內核數據結構裏的結構體的對齊方
式會有差別代碼中不同函數的表現形式也不一樣函數是不是被inline
@@ -84,18 +84,18 @@ Linux能成爲強壯穩定成熟的操作系統這也是你最開始選
深刻的教訓...
穩定的內核源代碼接口
穩定的內核源代碼介面
--------------------
如果有人不將他的內核驅動程序,放入公版內核的源代碼樹,而又想讓驅動程序
一直保持在最新的內核中可用,那麼這個話題將會變得沒完沒了。
內核開發是持續而且快節奏的,從來都不會慢下來。內核開發人員在當前接口
內核開發是持續而且快節奏的,從來都不會慢下來。內核開發人員在當前介面
找到bug或者找到更好的實現方式。一旦發現這些他們就很快會去修改當前的
接口。修改接口意味着,函數名可能會改變,結構體可能被擴充或者刪減,函數
的參數也可能發生改變。一旦接口被修改,內核中使用這些接口的地方需要同時
介面。修改介面意味着,函數名可能會改變,結構體可能被擴充或者刪減,函數
的參數也可能發生改變。一旦介面被修改,內核中使用這些介面的地方需要同時
修正,這樣才能保證所有的東西繼續工作。
舉一個例子內核的USB驅動程序接口在USB子系統的整個生命週期中至少經歷
舉一個例子內核的USB驅動程序介面在USB子系統的整個生命週期中至少經歷
了三次重寫。這些重寫解決以下問題:
- 把數據流從同步模式改成非同步模式,這個改動減少了一些驅動程序的
@@ -105,22 +105,22 @@ Linux能成爲強壯穩定成熟的操作系統這也是你最開始選
需要提供更多的參數給USB核心以修正了很多已經被記錄在案的死鎖。
這和一些封閉源代碼的操作系統形成鮮明的對比,在那些操作系統上,不得不額
外的維護舊的USB接口。這導致了一個可能性,新的開發者依然會不小心使用舊的
接口,以不恰當的方式編寫代碼,進而影響到操作系統的穩定性。
外的維護舊的USB介面。這導致了一個可能性,新的開發者依然會不小心使用舊的
介面,以不恰當的方式編寫代碼,進而影響到操作系統的穩定性。
在上面的例子中,所有的開發者都同意這些重要的改動,在這樣的情況下修改代
價很低。如果Linux保持一個穩定的內核源代碼接口,那麼就得創建一個新的接口
;舊的,有問題的接口必須一直維護給Linux USB開發者帶來額外的工作。既然
價很低。如果Linux保持一個穩定的內核源代碼介面,那麼就得創建一個新的介面
;舊的,有問題的介面必須一直維護給Linux USB開發者帶來額外的工作。既然
所有的Linux USB驅動的作者都是利用自己的時間工作那麼要求他們去做毫無意
義的免費額外工作,是不可能的。
安全問題對Linux來說十分重要。一個安全問題被發現就會在短時間內得到修
正。在很多情況下這將導致Linux內核中的一些接口被重寫,以從根本上避免安
全問題。一旦接口被重寫,所有使用這些接口的驅動程序,必須同時得到修正,
正。在很多情況下這將導致Linux內核中的一些介面被重寫,以從根本上避免安
全問題。一旦介面被重寫,所有使用這些介面的驅動程序,必須同時得到修正,
以確定安全問題已經得到修復並且不可能在未來還有同樣的安全問題。如果內核
內部接口不允許改變,那麼就不可能修復這樣的安全問題,也不可能確認這樣的
內部介面不允許改變,那麼就不可能修復這樣的安全問題,也不可能確認這樣的
安全問題以後不會發生。
開發者一直在清理內核接口。如果一個接口沒有人在使用了,它就會被刪除。這
樣可以確保內核儘可能的小,而且所有潛在的接口都會得到儘可能完整的測試
(沒有人使用的接口是不可能得到良好的測試的)。
開發者一直在清理內核介面。如果一個介面沒有人在使用了,它就會被刪除。這
樣可以確保內核儘可能的小,而且所有潛在的介面都會得到儘可能完整的測試
(沒有人使用的介面是不可能得到良好的測試的)。
要做什麼
@@ -128,11 +128,11 @@ Linux能成爲強壯穩定成熟的操作系統這也是你最開始選
如果你寫了一個Linux內核驅動但是它還不在Linux源代碼樹裏作爲一個開發
者,你應該怎麼做?爲每個發佈的每個版本提供一個二進制驅動,那簡直是一個
噩夢,要跟上永遠處於變化之中的內核接口,也是一件辛苦活。
噩夢,要跟上永遠處於變化之中的內核介面,也是一件辛苦活。
很簡單讓你的驅動進入內核源代碼樹要記得我們在談論的是以GPL許可發行
的驅動如果你的代碼不符合GPL那麼祝你好運你只能自己解決這個問題了
你這個吸血鬼<把Andrew和Linus對吸血鬼的定義鏈接到這裏>)。當你的代碼加入
公版內核源代碼樹之後,如果一個內核接口改變,你的驅動會直接被修改接口
公版內核源代碼樹之後,如果一個內核介面改變,你的驅動會直接被修改介面
那個人修改。保證你的驅動永遠都可以編譯通過,並且一直工作,你幾乎不需要
做什麼事情。
@@ -142,7 +142,7 @@ Linux能成爲強壯穩定成熟的操作系統這也是你最開始選
- 其他人會給驅動添加新特性。
- 其他人會找到驅動中的bug並修復。
- 其他人會在驅動中找到性能優化的機會。
- 當外部的接口的改變需要修改驅動程序的時候,其他人會修改驅動程序
- 當外部的介面的改變需要修改驅動程序的時候,其他人會修改驅動程序
- 不需要聯繫任何發行商這個驅動會自動的隨着所有的Linux發佈一起發
布。

View File

@@ -7738,6 +7738,7 @@ F: include/linux/dmi.h
DOCUMENTATION
M: Jonathan Corbet <corbet@lwn.net>
R: Shuah Khan <skhan@linuxfoundation.org>
R: Randy Dunlap <rdunlap@infradead.org>
L: linux-doc@vger.kernel.org
S: Maintained
P: Documentation/doc-guide/maintainer-profile.rst
@@ -27569,10 +27570,10 @@ F: kernel/trace/trace_osnoise.c
F: kernel/trace/trace_sched_wakeup.c
TRADITIONAL CHINESE DOCUMENTATION
M: Hu Haowen <2023002089@link.tyut.edu.cn>
M: Chen-Yu Yeh <chenyou910331@gmail.com>
M: Weijie Yuan <wy@wyuan.org>
M: Dongliang Mu <dzm91@hust.edu.cn>
S: Maintained
W: https://github.com/srcres258/linux-doc
T: git https://github.com/srcres258/linux-doc.git doc-zh-tw
F: Documentation/translations/zh_TW/
TRIGGER SOURCE

18
README
View File

@@ -30,15 +30,15 @@ Who Are You?
Find your role below:
* New Kernel Developer - Getting started with kernel development
* Academic Researcher - Studying kernel internals and architecture
* Security Expert - Hardening and vulnerability analysis
* Backport/Maintenance Engineer - Maintaining stable kernels
* System Administrator - Configuring and troubleshooting
* Maintainer - Leading subsystems and reviewing patches
* Hardware Vendor - Writing drivers for new hardware
* Distribution Maintainer - Packaging kernels for distros
* AI Coding Assistant - LLMs and AI-powered development tools
* New Kernel Developer: Getting started with kernel development
* Academic Researcher: Studying kernel internals and architecture
* Security Expert: Hardening and vulnerability analysis
* Backport/Maintenance Engineer: Maintaining stable kernels
* System Administrator: Configuring and troubleshooting
* Maintainer: Leading subsystems and reviewing patches
* Hardware Vendor: Writing drivers for new hardware
* Distribution Maintainer: Packaging kernels for distros
* AI Coding Assistant: LLMs and AI-powered development tools
For Specific Users

View File

@@ -3124,11 +3124,12 @@ sub process {
}
}
# Assisted-by uses AGENT_NAME:MODEL_VERSION format, not email
# Assisted-by uses a free-form value (e.g. "LLM"), not an
# email address, so skip the email format checks below.
if ($sign_off =~ /^Assisted-by:/i) {
if ($email !~ /^\S+:\S+/) {
if ($email =~ /^\s*$/) {
WARN("BAD_SIGN_OFF",
"Assisted-by expects 'AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]' format\n" . $herecurr);
"Assisted-by requires a value\n" . $herecurr);
}
next;
}

View File

@@ -143,7 +143,7 @@ while (<IN>) {
# Check if exists, evaluating wildcards
next if (grep -e, glob("$ref $fulref"));
# Accept relative Documentation patches for tools/
# Accept relative Documentation paths for tools/
if ($f =~ m/tools/) {
my $path = $f;
$path =~ s,(.*)/.*,$1,;

View File

@@ -99,9 +99,9 @@ class SphinxBuilder:
def get_path(self, path, use_cwd=False, abs_path=False):
"""
Ancillary routine to handle patches the right way, as shell does.
Ancillary routine to handle paths the right way, as shell does.
It first expands "~" and "~user". Then, if patch is not absolute,
It first expands "~" and "~user". Then, if path is not absolute,
join self.srctree. Finally, if requested, convert to abspath.
"""
@@ -219,6 +219,15 @@ class SphinxBuilder:
self.kernelrelease = os.environ.get("KERNELRELEASE", "unknown")
self.pdflatex = os.environ.get("PDFLATEX", "xelatex")
#
# Add localversion* to kernelversion if present
#
for file in glob(os.environ["srctree"] + "/localversion*"):
if not file.endswith(".orig"):
with open(file, 'r', encoding='utf-8') as f:
text = f.read()
self.kernelversion += text
#
# Kernel main Makefile defines a PYTHON3 variable whose default is
# "python3". When set to a different value, it allows running a

View File

@@ -65,8 +65,7 @@ class AbiRegex(AbiParser):
(re.compile(r"\[[^\]]+\]"), "\\\\w\xf7"),
(re.compile(r"XX+"), "\\\\w\xf7"),
(re.compile(r"([^A-Z])[XYZ]([^A-Z])"), "\\1\\\\w\xf7\\2"),
(re.compile(r"([^A-Z])[XYZ]$"), "\\1\\\\w\xf7"),
(re.compile(r"(?<![A-Z])[XYZ](?![A-Z])"), "\\\\w\xf7"),
(re.compile(r"_[AB]_"), "_\\\\w\xf7_"),
# Recover [0-9] type of patterns
@@ -155,7 +154,7 @@ class AbiRegex(AbiParser):
if self.search_string:
if what.find(self.search_string) >= 0:
print(f"What: {what}")
except re.PatternError:
except re.error:
self.log.warning("Ignoring '%s' as it produced an invalid regex:\n"
" '%s'", what, new)
@@ -194,7 +193,7 @@ class AbiRegex(AbiParser):
try:
self.re_string = re.compile(self.search_string)
except re.PatternError as e:
except re.error as e:
msg = f"{self.search_string} is not a valid regular expression"
raise ValueError(msg) from e
@@ -223,9 +222,9 @@ class AbiRegex(AbiParser):
for r, s in self.re_whats:
try:
new = r.sub(s, new)
except re.PatternError as e:
except re.error as e:
# Help debugging troubles with new regexes
raise re.PatternError(f"{e}\nwhile re.sub('{r.pattern}', {s}, str)") from e
raise re.error(f"{e}\nwhile re.sub('{r.pattern}', {s}, str)") from e
v["regex"].append(new)

View File

@@ -624,7 +624,7 @@ class ManFormat(OutputFormat):
``manual``
Defaults to ``Kernel API Manual``.
The above controls the output of teh corresponding fields on troff
The above controls the output of the corresponding fields on troff
title headers, which will be filled like this::
.TH "{name}" {section} "{date}" "{modulename}" "{manual}"

View File

@@ -11,6 +11,7 @@ and extract embedded documentation comments from it.
import sys
import re
import difflib
from pprint import pformat
from kdoc.c_lex import CTokenizer, tokenizer_set_log
@@ -558,6 +559,51 @@ class KernelDoc:
self.push_parameter(ln, decl_type, param, dtype,
arg, declaration_name)
def get_suggestions_hint(self, decl_name, possible_names):
# For decl name 'flags' or 'flgas', suggests 'substruct.flags'
submember_exact = []
submember_substrings = []
submember_suggestions = []
for possible_name in possible_names:
parts = possible_name.strip().split('.')
if len(parts) < 2:
continue
final_part = parts[-1]
if decl_name == final_part:
submember_exact.append(possible_name)
elif decl_name in final_part:
submember_substrings.append(possible_name)
elif difflib.get_close_matches(decl_name, [final_part]):
submember_suggestions.append(possible_name)
# For decl name 'flgas', suggests 'flags'
full_suggestions = difflib.get_close_matches(decl_name, possible_names)
# For decl name 'member', suggests 'longer_member'
full_substrings = [name for name in possible_names if decl_name in name]
ordered_lists = [
submember_exact,
submember_substrings,
submember_suggestions,
full_suggestions,
full_substrings,
]
# Deduplicate but maintain order from most to least likely:
unique_suggestions = {}
for suggestion_list in ordered_lists:
for suggestion in suggestion_list:
unique_suggestions[suggestion] = None
suggestions = list(unique_suggestions.keys())
if not suggestions:
return ""
joined_suggestions = "', '".join(suggestions)
return f"(did you mean one of: '{joined_suggestions}')"
def check_sections(self, ln, decl_name, decl_type):
"""
Check for errors inside sections, emitting warnings if not found
@@ -566,12 +612,13 @@ class KernelDoc:
for section in self.entry.sections:
if section not in self.entry.parameterlist and \
not known_sections.search(section):
hint = self.get_suggestions_hint(section, self.entry.parameterlist)
if decl_type == 'function':
dname = f"{decl_type} parameter"
else:
dname = f"{decl_type} member"
self.emit_msg(ln,
f"Excess {dname} '{section}' description in '{decl_name}'")
f"Excess {dname} '{section}' description in '{decl_name}' {hint}".strip())
#
# Check that documented parameter names (from doc comments, including
@@ -591,12 +638,13 @@ class KernelDoc:
if param_name in self.entry.parameterlist:
continue
hint = self.get_suggestions_hint(param_name, self.entry.parameterlist)
if decl_type == 'function':
dname = f"{decl_type} parameter"
else:
dname = f"{decl_type} member"
self.emit_msg(ln,
f"Excess {dname} '{param_name}' description in '{decl_name}'")
f"Excess {dname} '{param_name}' description in '{decl_name}' {hint}".strip())
def check_return_section(self, ln, declaration_name, return_type):
"""
@@ -791,7 +839,7 @@ class KernelDoc:
if self.entry.identifier != declaration_name:
self.emit_msg(ln, f"expecting prototype for {decl_type} {self.entry.identifier}. "
f"Prototype was for {decl_type} {declaration_name} instead\n")
f"Prototype was for {decl_type} {declaration_name} instead")
return
#
# Go through the list of members applying all of our transformations.
@@ -1108,7 +1156,7 @@ class KernelDoc:
if self.entry.identifier != declaration_name:
self.emit_msg(ln,
f"expecting prototype for typedef {self.entry.identifier}. Prototype was for typedef {declaration_name} instead\n")
f"expecting prototype for typedef {self.entry.identifier}. Prototype was for typedef {declaration_name} instead")
return
self.create_parameter_list(ln, 'function', args, ',', declaration_name)
@@ -1128,7 +1176,7 @@ class KernelDoc:
if self.entry.identifier != declaration_name:
self.emit_msg(ln,
f"expecting prototype for typedef {self.entry.identifier}. Prototype was for typedef {declaration_name} instead\n")
f"expecting prototype for typedef {self.entry.identifier}. Prototype was for typedef {declaration_name} instead")
return
self.output_declaration('typedef', declaration_name,

View File

@@ -90,6 +90,7 @@ class CTransforms:
(CMatch("__(?:re)?alloc_size"), ""),
(CMatch("__diagnose_as"), ""),
(CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"),
(CMatch("DEFINE_IDTENTRY_IRQ"), r"static void \1(struct pt_regs *regs, u32 vector)"),
(CMatch("__cond_acquires"), ""),
(CMatch("__cond_releases"), ""),
(CMatch("__acquires"), ""),