mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 11:47:47 +00:00
Merge branch 'docs-next' of git://git.lwn.net/linux.git
# Conflicts: # scripts/checkpatch.pl
This commit is contained in:
commit
6b432139e5
@ -47,7 +47,7 @@ should not change the relative position of each field within the struct.
|
||||
1) Common and basic accounting fields::
|
||||
|
||||
/* The version number of this struct. This field is always set to
|
||||
* TAKSTATS_VERSION, which is defined in <linux/taskstats.h>.
|
||||
* TASKSTATS_VERSION, which is defined in <linux/taskstats.h>.
|
||||
* Each time the struct is changed, the value should be incremented.
|
||||
*/
|
||||
__u16 version;
|
||||
|
@ -356,5 +356,5 @@ instructions at 'Documentation/admin-guide/reporting-issues.rst'.
|
||||
|
||||
Hints on understanding kernel bug reports are in
|
||||
'Documentation/admin-guide/bug-hunting.rst'. More on debugging the kernel
|
||||
with gdb is in 'Documentation/dev-tools/gdb-kernel-debugging.rst' and
|
||||
'Documentation/dev-tools/kgdb.rst'.
|
||||
with gdb is in 'Documentation/process/debugging/gdb-kernel-debugging.rst' and
|
||||
'Documentation/process/debugging/kgdb.rst'.
|
||||
|
@ -121,14 +121,14 @@ compression algorithm to use external pre-trained dictionary, pass full
|
||||
path to the `dict` along with other parameters::
|
||||
|
||||
#pass path to pre-trained zstd dictionary
|
||||
echo "algo=zstd dict=/etc/dictioary" > /sys/block/zram0/algorithm_params
|
||||
echo "algo=zstd dict=/etc/dictionary" > /sys/block/zram0/algorithm_params
|
||||
|
||||
#same, but using algorithm priority
|
||||
echo "priority=1 dict=/etc/dictioary" > \
|
||||
echo "priority=1 dict=/etc/dictionary" > \
|
||||
/sys/block/zram0/algorithm_params
|
||||
|
||||
#pass path to pre-trained zstd dictionary and compression level
|
||||
echo "algo=zstd level=8 dict=/etc/dictioary" > \
|
||||
echo "algo=zstd level=8 dict=/etc/dictionary" > \
|
||||
/sys/block/zram0/algorithm_params
|
||||
|
||||
Parameters are algorithm specific: not all algorithms support pre-trained
|
||||
|
@ -21,8 +21,8 @@ override the baud rate to 115200, etc.
|
||||
By default, the braille device will just show the last kernel message (console
|
||||
mode). To review previous messages, press the Insert key to switch to the VT
|
||||
review mode. In review mode, the arrow keys permit to browse in the VT content,
|
||||
:kbd:`PAGE-UP`/:kbd:`PAGE-DOWN` keys go at the top/bottom of the screen, and
|
||||
the :kbd:`HOME` key goes back
|
||||
`PAGE-UP`/`PAGE-DOWN` keys go at the top/bottom of the screen, and
|
||||
the `HOME` key goes back
|
||||
to the cursor, hence providing very basic screen reviewing facility.
|
||||
|
||||
Sound feedback can be obtained by adding the ``braille_console.sound=1`` kernel
|
||||
|
@ -7,6 +7,9 @@ added to the kernel over time. There is, as yet, little overall order or
|
||||
organization here — this material was not written to be a single, coherent
|
||||
document! With luck things will improve quickly over time.
|
||||
|
||||
General guides to kernel administration
|
||||
---------------------------------------
|
||||
|
||||
This initial section contains overall information, including the README
|
||||
file describing the kernel as a whole, documentation on kernel parameters,
|
||||
etc.
|
||||
@ -15,19 +18,44 @@ etc.
|
||||
:maxdepth: 1
|
||||
|
||||
README
|
||||
kernel-parameters
|
||||
devices
|
||||
sysctl/index
|
||||
|
||||
abi
|
||||
features
|
||||
|
||||
This section describes CPU vulnerabilities and their mitigations.
|
||||
A big part of the kernel's administrative interface is the /proc and sysfs
|
||||
virtual filesystems; these documents describe how to interact with tem
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
sysfs-rules
|
||||
sysctl/index
|
||||
cputopology
|
||||
abi
|
||||
|
||||
Security-related documentation:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
hw-vuln/index
|
||||
LSM/index
|
||||
perf-security
|
||||
|
||||
Booting the kernel
|
||||
------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
bootconfig
|
||||
kernel-parameters
|
||||
efi-stub
|
||||
initrd
|
||||
|
||||
|
||||
Tracking down and identifying problems
|
||||
--------------------------------------
|
||||
|
||||
Here is a set of documents aimed at users who are trying to track down
|
||||
problems and bugs in particular.
|
||||
@ -48,15 +76,97 @@ problems and bugs in particular.
|
||||
kdump/index
|
||||
perf/index
|
||||
pstore-blk
|
||||
clearing-warn-once
|
||||
kernel-per-CPU-kthreads
|
||||
lockup-watchdogs
|
||||
RAS/index
|
||||
sysrq
|
||||
|
||||
This is the beginning of a section with information of interest to
|
||||
application developers. Documents covering various aspects of the kernel
|
||||
ABI will be found here.
|
||||
|
||||
Core-kernel subsystems
|
||||
----------------------
|
||||
|
||||
These documents describe core-kernel administration interfaces that are
|
||||
likely to be of interest on almost any system.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
sysfs-rules
|
||||
cgroup-v2
|
||||
cgroup-v1/index
|
||||
cpu-load
|
||||
mm/index
|
||||
module-signing
|
||||
namespaces/index
|
||||
numastat
|
||||
pm/index
|
||||
syscall-user-dispatch
|
||||
|
||||
Support for non-native binary formats. Note that some of these
|
||||
documents are ... old ...
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
binfmt-misc
|
||||
java
|
||||
mono
|
||||
|
||||
|
||||
Block-layer and filesystem administration
|
||||
-----------------------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
bcache
|
||||
binderfs
|
||||
blockdev/index
|
||||
cifs/index
|
||||
device-mapper/index
|
||||
ext4
|
||||
filesystem-monitoring
|
||||
nfs/index
|
||||
iostats
|
||||
jfs
|
||||
md
|
||||
ufs
|
||||
xfs
|
||||
|
||||
Device-specific guides
|
||||
----------------------
|
||||
|
||||
How to configure your hardware within your Linux system.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
acpi/index
|
||||
aoe/index
|
||||
auxdisplay/index
|
||||
braille-console
|
||||
btmrvl
|
||||
dell_rbu
|
||||
edid
|
||||
gpio/index
|
||||
hw_random
|
||||
laptops/index
|
||||
lcd-panel-cgram
|
||||
media/index
|
||||
nvme-multipath
|
||||
parport
|
||||
pnp
|
||||
rapidio
|
||||
rtc
|
||||
serial-console
|
||||
svga
|
||||
thermal/index
|
||||
thunderbolt
|
||||
vga-softcursor
|
||||
video-output
|
||||
|
||||
Workload analysis
|
||||
-----------------
|
||||
|
||||
This is the beginning of a section with information of interest to
|
||||
application developers and system integrators doing analysis of the
|
||||
@ -69,73 +179,17 @@ subsystems expectations will be found here.
|
||||
|
||||
workload-tracing
|
||||
|
||||
The rest of this manual consists of various unordered guides on how to
|
||||
configure specific aspects of kernel behavior to your liking.
|
||||
Everything else
|
||||
---------------
|
||||
|
||||
A few hard-to-categorize and generally obsolete documents.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
acpi/index
|
||||
aoe/index
|
||||
auxdisplay/index
|
||||
bcache
|
||||
binderfs
|
||||
binfmt-misc
|
||||
blockdev/index
|
||||
bootconfig
|
||||
braille-console
|
||||
btmrvl
|
||||
cgroup-v1/index
|
||||
cgroup-v2
|
||||
cifs/index
|
||||
clearing-warn-once
|
||||
cpu-load
|
||||
cputopology
|
||||
dell_rbu
|
||||
device-mapper/index
|
||||
edid
|
||||
efi-stub
|
||||
ext4
|
||||
filesystem-monitoring
|
||||
nfs/index
|
||||
gpio/index
|
||||
highuid
|
||||
hw_random
|
||||
initrd
|
||||
iostats
|
||||
java
|
||||
jfs
|
||||
kernel-per-CPU-kthreads
|
||||
laptops/index
|
||||
lcd-panel-cgram
|
||||
ldm
|
||||
lockup-watchdogs
|
||||
LSM/index
|
||||
md
|
||||
media/index
|
||||
mm/index
|
||||
module-signing
|
||||
mono
|
||||
namespaces/index
|
||||
numastat
|
||||
parport
|
||||
perf-security
|
||||
pm/index
|
||||
pnp
|
||||
rapidio
|
||||
RAS/index
|
||||
rtc
|
||||
serial-console
|
||||
svga
|
||||
syscall-user-dispatch
|
||||
sysrq
|
||||
thermal/index
|
||||
thunderbolt
|
||||
ufs
|
||||
unicode
|
||||
vga-softcursor
|
||||
video-output
|
||||
xfs
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
|
@ -7481,7 +7481,7 @@
|
||||
vt.cur_default= [VT] Default cursor shape.
|
||||
Format: 0xCCBBAA, where AA, BB, and CC are the same as
|
||||
the parameters of the <Esc>[?A;B;Cc escape sequence;
|
||||
see VGA-softcursor.txt. Default: 2 = underline.
|
||||
see vga-softcursor.rst. Default: 2 = underline.
|
||||
|
||||
vt.default_blu= [VT]
|
||||
Format: <blue0>,<blue1>,<blue2>,...,<blue15>
|
||||
|
72
Documentation/admin-guide/nvme-multipath.rst
Normal file
72
Documentation/admin-guide/nvme-multipath.rst
Normal file
@ -0,0 +1,72 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
====================
|
||||
Linux NVMe multipath
|
||||
====================
|
||||
|
||||
This document describes NVMe multipath and its path selection policies supported
|
||||
by the Linux NVMe host driver.
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The NVMe multipath feature in Linux integrates namespaces with the same
|
||||
identifier into a single block device. Using multipath enhances the reliability
|
||||
and stability of I/O access while improving bandwidth performance. When a user
|
||||
sends I/O to this merged block device, the multipath mechanism selects one of
|
||||
the underlying block devices (paths) according to the configured policy.
|
||||
Different policies result in different path selections.
|
||||
|
||||
|
||||
Policies
|
||||
========
|
||||
|
||||
All policies follow the ANA (Asymmetric Namespace Access) mechanism, meaning
|
||||
that when an optimized path is available, it will be chosen over a non-optimized
|
||||
one. Current the NVMe multipath policies include numa(default), round-robin and
|
||||
queue-depth.
|
||||
|
||||
To set the desired policy (e.g., round-robin), use one of the following methods:
|
||||
1. echo -n "round-robin" > /sys/module/nvme_core/parameters/iopolicy
|
||||
2. or add the "nvme_core.iopolicy=round-robin" to cmdline.
|
||||
|
||||
|
||||
NUMA
|
||||
----
|
||||
|
||||
The NUMA policy selects the path closest to the NUMA node of the current CPU for
|
||||
I/O distribution. This policy maintains the nearest paths to each NUMA node
|
||||
based on network interface connections.
|
||||
|
||||
When to use the NUMA policy:
|
||||
1. Multi-core Systems: Optimizes memory access in multi-core and
|
||||
multi-processor systems, especially under NUMA architecture.
|
||||
2. High Affinity Workloads: Binds I/O processing to the CPU to reduce
|
||||
communication and data transfer delays across nodes.
|
||||
|
||||
|
||||
Round-Robin
|
||||
-----------
|
||||
|
||||
The round-robin policy distributes I/O requests evenly across all paths to
|
||||
enhance throughput and resource utilization. Each I/O operation is sent to the
|
||||
next path in sequence.
|
||||
|
||||
When to use the round-robin policy:
|
||||
1. Balanced Workloads: Effective for balanced and predictable workloads with
|
||||
similar I/O size and type.
|
||||
2. Homogeneous Path Performance: Utilizes all paths efficiently when
|
||||
performance characteristics (e.g., latency, bandwidth) are similar.
|
||||
|
||||
|
||||
Queue-Depth
|
||||
-----------
|
||||
|
||||
The queue-depth policy manages I/O requests based on the current queue depth
|
||||
of each path, selecting the path with the least number of in-flight I/Os.
|
||||
|
||||
When to use the queue-depth policy:
|
||||
1. High load with small I/Os: Effectively balances load across paths when
|
||||
the load is high, and I/O operations consist of small, relatively
|
||||
fixed-sized requests.
|
@ -733,7 +733,7 @@ can easily happen that your self-built kernel will lack modules for tasks you
|
||||
did not perform before utilizing this make target. That's because those tasks
|
||||
require kernel modules that are normally autoloaded when you perform that task
|
||||
for the first time; if you didn't perform that task at least once before using
|
||||
localmodonfig, the latter will thus assume these modules are superfluous and
|
||||
localmodconfig, the latter will thus assume these modules are superfluous and
|
||||
disable them.
|
||||
|
||||
You can try to avoid this by performing typical tasks that often will autoload
|
||||
|
@ -41,7 +41,7 @@ pre-allocation or re-sizing of any kernel data structures.
|
||||
dentry-negative
|
||||
----------------------------
|
||||
|
||||
Policy for negative dentries. Set to 1 to to always delete the dentry when a
|
||||
Policy for negative dentries. Set to 1 to always delete the dentry when a
|
||||
file is removed, and 0 to disable it. By default, this behavior is disabled.
|
||||
|
||||
dentry-state
|
||||
|
@ -49,26 +49,26 @@ How do I use the magic SysRq key?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
On x86
|
||||
You press the key combo :kbd:`ALT-SysRq-<command key>`.
|
||||
You press the key combo `ALT-SysRq-<command key>`.
|
||||
|
||||
.. note::
|
||||
Some
|
||||
keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is
|
||||
also known as the 'Print Screen' key. Also some keyboards cannot
|
||||
handle so many keys being pressed at the same time, so you might
|
||||
have better luck with press :kbd:`Alt`, press :kbd:`SysRq`,
|
||||
release :kbd:`SysRq`, press :kbd:`<command key>`, release everything.
|
||||
have better luck with press `Alt`, press `SysRq`,
|
||||
release `SysRq`, press `<command key>`, release everything.
|
||||
|
||||
On SPARC
|
||||
You press :kbd:`ALT-STOP-<command key>`, I believe.
|
||||
You press `ALT-STOP-<command key>`, I believe.
|
||||
|
||||
On the serial console (PC style standard serial ports only)
|
||||
You send a ``BREAK``, then within 5 seconds a command key. Sending
|
||||
``BREAK`` twice is interpreted as a normal BREAK.
|
||||
|
||||
On PowerPC
|
||||
Press :kbd:`ALT - Print Screen` (or :kbd:`F13`) - :kbd:`<command key>`.
|
||||
:kbd:`Print Screen` (or :kbd:`F13`) - :kbd:`<command key>` may suffice.
|
||||
Press `ALT - Print Screen` (or `F13`) - `<command key>`.
|
||||
`Print Screen` (or `F13`) - `<command key>` may suffice.
|
||||
|
||||
On other
|
||||
If you know of the key combos for other architectures, please
|
||||
@ -88,7 +88,7 @@ On all
|
||||
|
||||
echo _reisub > /proc/sysrq-trigger
|
||||
|
||||
The :kbd:`<command key>` is case sensitive.
|
||||
The `<command key>` is case sensitive.
|
||||
|
||||
What are the 'command' keys?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -225,9 +225,9 @@ Sometimes SysRq seems to get 'stuck' after using it, what can I do?
|
||||
|
||||
When this happens, try tapping shift, alt and control on both sides of the
|
||||
keyboard, and hitting an invalid sysrq sequence again. (i.e., something like
|
||||
:kbd:`alt-sysrq-z`).
|
||||
`alt-sysrq-z`).
|
||||
|
||||
Switching to another virtual console (:kbd:`ALT+Fn`) and then back again
|
||||
Switching to another virtual console (`ALT+Fn`) and then back again
|
||||
should also help.
|
||||
|
||||
I hit SysRq, but nothing seems to happen, what's wrong?
|
||||
@ -290,7 +290,7 @@ exception the header line from the sysrq command is passed to all console
|
||||
consumers as if the current loglevel was maximum. If only the header
|
||||
is emitted it is almost certain that the kernel loglevel is too low.
|
||||
Should you require the output on the console channel then you will need
|
||||
to temporarily up the console loglevel using :kbd:`alt-sysrq-8` or::
|
||||
to temporarily up the console loglevel using `alt-sysrq-8` or::
|
||||
|
||||
echo 8 > /proc/sysrq-trigger
|
||||
|
||||
|
@ -1431,7 +1431,7 @@ can easily happen that your self-built kernels will lack modules for tasks you
|
||||
did not perform at least once before utilizing this make target. That happens
|
||||
when a task requires kernel modules which are only autoloaded when you execute
|
||||
it for the first time. So when you never performed that task since starting your
|
||||
kernel the modules will not have been loaded -- and from localmodonfig's point
|
||||
kernel the modules will not have been loaded -- and from localmodconfig's point
|
||||
of view look superfluous, which thus disables them to reduce the amount of code
|
||||
to be compiled.
|
||||
|
||||
|
@ -77,7 +77,7 @@ Protocol 2.14 BURNT BY INCORRECT COMMIT
|
||||
Protocol 2.15 (Kernel 5.5) Added the kernel_info and kernel_info.setup_type_max.
|
||||
============= ============================================================
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
The protocol version number should be changed only if the setup header
|
||||
is changed. There is no need to update the version number if boot_params
|
||||
or kernel_info are changed. Additionally, it is recommended to use
|
||||
@ -95,27 +95,27 @@ Memory Layout
|
||||
The traditional memory map for the kernel loader, used for Image or
|
||||
zImage kernels, typically looks like::
|
||||
|
||||
| |
|
||||
0A0000 +------------------------+
|
||||
| Reserved for BIOS | Do not use. Reserved for BIOS EBDA.
|
||||
09A000 +------------------------+
|
||||
| Command line |
|
||||
| Stack/heap | For use by the kernel real-mode code.
|
||||
098000 +------------------------+
|
||||
| Kernel setup | The kernel real-mode code.
|
||||
090200 +------------------------+
|
||||
| Kernel boot sector | The kernel legacy boot sector.
|
||||
090000 +------------------------+
|
||||
| Protected-mode kernel | The bulk of the kernel image.
|
||||
010000 +------------------------+
|
||||
| Boot loader | <- Boot sector entry point 0000:7C00
|
||||
001000 +------------------------+
|
||||
| Reserved for MBR/BIOS |
|
||||
000800 +------------------------+
|
||||
| Typically used by MBR |
|
||||
000600 +------------------------+
|
||||
| BIOS use only |
|
||||
000000 +------------------------+
|
||||
| |
|
||||
0A0000 +------------------------+
|
||||
| Reserved for BIOS | Do not use. Reserved for BIOS EBDA.
|
||||
09A000 +------------------------+
|
||||
| Command line |
|
||||
| Stack/heap | For use by the kernel real-mode code.
|
||||
098000 +------------------------+
|
||||
| Kernel setup | The kernel real-mode code.
|
||||
090200 +------------------------+
|
||||
| Kernel boot sector | The kernel legacy boot sector.
|
||||
090000 +------------------------+
|
||||
| Protected-mode kernel | The bulk of the kernel image.
|
||||
010000 +------------------------+
|
||||
| Boot loader | <- Boot sector entry point 0000:7C00
|
||||
001000 +------------------------+
|
||||
| Reserved for MBR/BIOS |
|
||||
000800 +------------------------+
|
||||
| Typically used by MBR |
|
||||
000600 +------------------------+
|
||||
| BIOS use only |
|
||||
000000 +------------------------+
|
||||
|
||||
When using bzImage, the protected-mode kernel was relocated to
|
||||
0x100000 ("high memory"), and the kernel real-mode block (boot sector,
|
||||
@ -142,28 +142,28 @@ above the 0x9A000 point; too many BIOSes will break above that point.
|
||||
For a modern bzImage kernel with boot protocol version >= 2.02, a
|
||||
memory layout like the following is suggested::
|
||||
|
||||
~ ~
|
||||
| Protected-mode kernel |
|
||||
100000 +------------------------+
|
||||
| I/O memory hole |
|
||||
0A0000 +------------------------+
|
||||
| Reserved for BIOS | Leave as much as possible unused
|
||||
~ ~
|
||||
| Command line | (Can also be below the X+10000 mark)
|
||||
X+10000 +------------------------+
|
||||
| Stack/heap | For use by the kernel real-mode code.
|
||||
X+08000 +------------------------+
|
||||
| Kernel setup | The kernel real-mode code.
|
||||
| Kernel boot sector | The kernel legacy boot sector.
|
||||
X +------------------------+
|
||||
| Boot loader | <- Boot sector entry point 0000:7C00
|
||||
001000 +------------------------+
|
||||
| Reserved for MBR/BIOS |
|
||||
000800 +------------------------+
|
||||
| Typically used by MBR |
|
||||
000600 +------------------------+
|
||||
| BIOS use only |
|
||||
000000 +------------------------+
|
||||
~ ~
|
||||
| Protected-mode kernel |
|
||||
100000 +------------------------+
|
||||
| I/O memory hole |
|
||||
0A0000 +------------------------+
|
||||
| Reserved for BIOS | Leave as much as possible unused
|
||||
~ ~
|
||||
| Command line | (Can also be below the X+10000 mark)
|
||||
X+10000 +------------------------+
|
||||
| Stack/heap | For use by the kernel real-mode code.
|
||||
X+08000 +------------------------+
|
||||
| Kernel setup | The kernel real-mode code.
|
||||
| Kernel boot sector | The kernel legacy boot sector.
|
||||
X +------------------------+
|
||||
| Boot loader | <- Boot sector entry point 0000:7C00
|
||||
001000 +------------------------+
|
||||
| Reserved for MBR/BIOS |
|
||||
000800 +------------------------+
|
||||
| Typically used by MBR |
|
||||
000600 +------------------------+
|
||||
| BIOS use only |
|
||||
000000 +------------------------+
|
||||
|
||||
... where the address X is as low as the design of the boot loader permits.
|
||||
|
||||
@ -229,22 +229,22 @@ Offset/Size Proto Name Meaning
|
||||
=========== ======== ===================== ============================================
|
||||
|
||||
.. note::
|
||||
(1) For backwards compatibility, if the setup_sects field contains 0, the
|
||||
real value is 4.
|
||||
(1) For backwards compatibility, if the setup_sects field contains 0,
|
||||
the real value is 4.
|
||||
|
||||
(2) For boot protocol prior to 2.04, the upper two bytes of the syssize
|
||||
field are unusable, which means the size of a bzImage kernel
|
||||
cannot be determined.
|
||||
(2) For boot protocol prior to 2.04, the upper two bytes of the syssize
|
||||
field are unusable, which means the size of a bzImage kernel
|
||||
cannot be determined.
|
||||
|
||||
(3) Ignored, but safe to set, for boot protocols 2.02-2.09.
|
||||
(3) Ignored, but safe to set, for boot protocols 2.02-2.09.
|
||||
|
||||
If the "HdrS" (0x53726448) magic number is not found at offset 0x202,
|
||||
the boot protocol version is "old". Loading an old kernel, the
|
||||
following parameters should be assumed::
|
||||
|
||||
Image type = zImage
|
||||
initrd not supported
|
||||
Real-mode kernel must be located at 0x90000.
|
||||
Image type = zImage
|
||||
initrd not supported
|
||||
Real-mode kernel must be located at 0x90000.
|
||||
|
||||
Otherwise, the "version" field contains the protocol version,
|
||||
e.g. protocol version 2.01 will contain 0x0201 in this field. When
|
||||
@ -265,7 +265,7 @@ All general purpose boot loaders should write the fields marked
|
||||
nonstandard address should fill in the fields marked (reloc); other
|
||||
boot loaders can ignore those fields.
|
||||
|
||||
The byte order of all fields is littleendian (this is x86, after all.)
|
||||
The byte order of all fields is little endian (this is x86, after all.)
|
||||
|
||||
============ ===========
|
||||
Field name: setup_sects
|
||||
@ -365,7 +365,7 @@ Offset/size: 0x206/2
|
||||
Protocol: 2.00+
|
||||
============ =======
|
||||
|
||||
Contains the boot protocol version, in (major << 8)+minor format,
|
||||
Contains the boot protocol version, in (major << 8) + minor format,
|
||||
e.g. 0x0204 for version 2.04, and 0x0a11 for a hypothetical version
|
||||
10.17.
|
||||
|
||||
@ -397,17 +397,17 @@ Protocol: 2.00+
|
||||
If set to a nonzero value, contains a pointer to a NUL-terminated
|
||||
human-readable kernel version number string, less 0x200. This can
|
||||
be used to display the kernel version to the user. This value
|
||||
should be less than (0x200*setup_sects).
|
||||
should be less than (0x200 * setup_sects).
|
||||
|
||||
For example, if this value is set to 0x1c00, the kernel version
|
||||
number string can be found at offset 0x1e00 in the kernel file.
|
||||
This is a valid value if and only if the "setup_sects" field
|
||||
contains the value 15 or higher, as::
|
||||
|
||||
0x1c00 < 15*0x200 (= 0x1e00) but
|
||||
0x1c00 >= 14*0x200 (= 0x1c00)
|
||||
0x1c00 < 15 * 0x200 (= 0x1e00) but
|
||||
0x1c00 >= 14 * 0x200 (= 0x1c00)
|
||||
|
||||
0x1c00 >> 9 = 14, So the minimum value for setup_secs is 15.
|
||||
0x1c00 >> 9 = 14, So the minimum value for setup_secs is 15.
|
||||
|
||||
============ ==================
|
||||
Field name: type_of_loader
|
||||
@ -427,9 +427,9 @@ Protocol: 2.00+
|
||||
|
||||
For example, for T = 0x15, V = 0x234, write::
|
||||
|
||||
type_of_loader <- 0xE4
|
||||
ext_loader_type <- 0x05
|
||||
ext_loader_ver <- 0x23
|
||||
type_of_loader <- 0xE4
|
||||
ext_loader_type <- 0x05
|
||||
ext_loader_ver <- 0x23
|
||||
|
||||
Assigned boot loader ids (hexadecimal):
|
||||
|
||||
@ -686,7 +686,7 @@ Protocol: 2.10+
|
||||
If a boot loader makes use of this field, it should update the
|
||||
kernel_alignment field with the alignment unit desired; typically::
|
||||
|
||||
kernel_alignment = 1 << min_alignment
|
||||
kernel_alignment = 1 << min_alignment;
|
||||
|
||||
There may be a considerable performance cost with an excessively
|
||||
misaligned kernel. Therefore, a loader should typically try each
|
||||
@ -754,7 +754,7 @@ Protocol: 2.07+
|
||||
0x00000000 The default x86/PC environment
|
||||
0x00000001 lguest
|
||||
0x00000002 Xen
|
||||
0x00000003 Moorestown MID
|
||||
0x00000003 Intel MID (Moorestown, CloverTrail, Merrifield, Moorefield)
|
||||
0x00000004 CE4100 TV Platform
|
||||
========== ==============================
|
||||
|
||||
@ -808,12 +808,12 @@ Protocol: 2.09+
|
||||
parameters passing mechanism. The definition of struct setup_data is
|
||||
as follow::
|
||||
|
||||
struct setup_data {
|
||||
u64 next;
|
||||
u32 type;
|
||||
u32 len;
|
||||
u8 data[0];
|
||||
};
|
||||
struct setup_data {
|
||||
__u64 next;
|
||||
__u32 type;
|
||||
__u32 len;
|
||||
__u8 data[];
|
||||
}
|
||||
|
||||
Where, the next is a 64-bit physical pointer to the next node of
|
||||
linked list, the next field of the last node is 0; the type is used
|
||||
@ -834,12 +834,12 @@ Protocol: 2.09+
|
||||
Thus setup_indirect struct and SETUP_INDIRECT type were introduced in
|
||||
protocol 2.15::
|
||||
|
||||
struct setup_indirect {
|
||||
__u32 type;
|
||||
__u32 reserved; /* Reserved, must be set to zero. */
|
||||
__u64 len;
|
||||
__u64 addr;
|
||||
};
|
||||
struct setup_indirect {
|
||||
__u32 type;
|
||||
__u32 reserved; /* Reserved, must be set to zero. */
|
||||
__u64 len;
|
||||
__u64 addr;
|
||||
};
|
||||
|
||||
The type member is a SETUP_INDIRECT | SETUP_* type. However, it cannot be
|
||||
SETUP_INDIRECT itself since making the setup_indirect a tree structure
|
||||
@ -849,17 +849,17 @@ Protocol: 2.09+
|
||||
Let's give an example how to point to SETUP_E820_EXT data using setup_indirect.
|
||||
In this case setup_data and setup_indirect will look like this::
|
||||
|
||||
struct setup_data {
|
||||
__u64 next = 0 or <addr_of_next_setup_data_struct>;
|
||||
__u32 type = SETUP_INDIRECT;
|
||||
__u32 len = sizeof(setup_indirect);
|
||||
__u8 data[sizeof(setup_indirect)] = struct setup_indirect {
|
||||
__u32 type = SETUP_INDIRECT | SETUP_E820_EXT;
|
||||
__u32 reserved = 0;
|
||||
__u64 len = <len_of_SETUP_E820_EXT_data>;
|
||||
__u64 addr = <addr_of_SETUP_E820_EXT_data>;
|
||||
}
|
||||
}
|
||||
struct setup_data {
|
||||
.next = 0, /* or <addr_of_next_setup_data_struct> */
|
||||
.type = SETUP_INDIRECT,
|
||||
.len = sizeof(setup_indirect),
|
||||
.data[sizeof(setup_indirect)] = (struct setup_indirect) {
|
||||
.type = SETUP_INDIRECT | SETUP_E820_EXT,
|
||||
.reserved = 0,
|
||||
.len = <len_of_SETUP_E820_EXT_data>,
|
||||
.addr = <addr_of_SETUP_E820_EXT_data>,
|
||||
},
|
||||
}
|
||||
|
||||
.. note::
|
||||
SETUP_INDIRECT | SETUP_NONE objects cannot be properly distinguished
|
||||
@ -896,19 +896,19 @@ Offset/size: 0x260/4
|
||||
|
||||
The kernel runtime start address is determined by the following algorithm::
|
||||
|
||||
if (relocatable_kernel) {
|
||||
if (load_address < pref_address)
|
||||
load_address = pref_address;
|
||||
runtime_start = align_up(load_address, kernel_alignment);
|
||||
} else {
|
||||
runtime_start = pref_address;
|
||||
}
|
||||
if (relocatable_kernel) {
|
||||
if (load_address < pref_address)
|
||||
load_address = pref_address;
|
||||
runtime_start = align_up(load_address, kernel_alignment);
|
||||
} else {
|
||||
runtime_start = pref_address;
|
||||
}
|
||||
|
||||
Hence the necessary memory window location and size can be estimated by
|
||||
a boot loader as::
|
||||
|
||||
memory_window_start = runtime_start;
|
||||
memory_window_size = init_size;
|
||||
memory_window_start = runtime_start;
|
||||
memory_window_size = init_size;
|
||||
|
||||
============ ===============
|
||||
Field name: handover_offset
|
||||
@ -938,12 +938,12 @@ The kernel_info
|
||||
===============
|
||||
|
||||
The relationships between the headers are analogous to the various data
|
||||
sections:
|
||||
sections::
|
||||
|
||||
setup_header = .data
|
||||
boot_params/setup_data = .bss
|
||||
|
||||
What is missing from the above list? That's right:
|
||||
What is missing from the above list? That's right::
|
||||
|
||||
kernel_info = .rodata
|
||||
|
||||
@ -975,22 +975,22 @@ after kernel_info_var_len_data label. Each chunk of variable size data has to
|
||||
be prefixed with header/magic and its size, e.g.::
|
||||
|
||||
kernel_info:
|
||||
.ascii "LToP" /* Header, Linux top (structure). */
|
||||
.long kernel_info_var_len_data - kernel_info
|
||||
.long kernel_info_end - kernel_info
|
||||
.long 0x01234567 /* Some fixed size data for the bootloaders. */
|
||||
.ascii "LToP" /* Header, Linux top (structure). */
|
||||
.long kernel_info_var_len_data - kernel_info
|
||||
.long kernel_info_end - kernel_info
|
||||
.long 0x01234567 /* Some fixed size data for the bootloaders. */
|
||||
kernel_info_var_len_data:
|
||||
example_struct: /* Some variable size data for the bootloaders. */
|
||||
.ascii "0123" /* Header/Magic. */
|
||||
.long example_struct_end - example_struct
|
||||
.ascii "Struct"
|
||||
.long 0x89012345
|
||||
example_struct: /* Some variable size data for the bootloaders. */
|
||||
.ascii "0123" /* Header/Magic. */
|
||||
.long example_struct_end - example_struct
|
||||
.ascii "Struct"
|
||||
.long 0x89012345
|
||||
example_struct_end:
|
||||
example_strings: /* Some variable size data for the bootloaders. */
|
||||
.ascii "ABCD" /* Header/Magic. */
|
||||
.long example_strings_end - example_strings
|
||||
.asciz "String_0"
|
||||
.asciz "String_1"
|
||||
example_strings: /* Some variable size data for the bootloaders. */
|
||||
.ascii "ABCD" /* Header/Magic. */
|
||||
.long example_strings_end - example_strings
|
||||
.asciz "String_0"
|
||||
.asciz "String_1"
|
||||
example_strings_end:
|
||||
kernel_info_end:
|
||||
|
||||
@ -1139,67 +1139,63 @@ mode segment.
|
||||
|
||||
Such a boot loader should enter the following fields in the header::
|
||||
|
||||
unsigned long base_ptr; /* base address for real-mode segment */
|
||||
unsigned long base_ptr; /* base address for real-mode segment */
|
||||
|
||||
if ( setup_sects == 0 ) {
|
||||
setup_sects = 4;
|
||||
}
|
||||
if (setup_sects == 0)
|
||||
setup_sects = 4;
|
||||
|
||||
if ( protocol >= 0x0200 ) {
|
||||
type_of_loader = <type code>;
|
||||
if ( loading_initrd ) {
|
||||
ramdisk_image = <initrd_address>;
|
||||
ramdisk_size = <initrd_size>;
|
||||
}
|
||||
if (protocol >= 0x0200) {
|
||||
type_of_loader = <type code>;
|
||||
if (loading_initrd) {
|
||||
ramdisk_image = <initrd_address>;
|
||||
ramdisk_size = <initrd_size>;
|
||||
}
|
||||
|
||||
if ( protocol >= 0x0202 && loadflags & 0x01 )
|
||||
heap_end = 0xe000;
|
||||
else
|
||||
heap_end = 0x9800;
|
||||
if (protocol >= 0x0202 && loadflags & 0x01)
|
||||
heap_end = 0xe000;
|
||||
else
|
||||
heap_end = 0x9800;
|
||||
|
||||
if ( protocol >= 0x0201 ) {
|
||||
heap_end_ptr = heap_end - 0x200;
|
||||
loadflags |= 0x80; /* CAN_USE_HEAP */
|
||||
}
|
||||
if (protocol >= 0x0201) {
|
||||
heap_end_ptr = heap_end - 0x200;
|
||||
loadflags |= 0x80; /* CAN_USE_HEAP */
|
||||
}
|
||||
|
||||
if ( protocol >= 0x0202 ) {
|
||||
cmd_line_ptr = base_ptr + heap_end;
|
||||
strcpy(cmd_line_ptr, cmdline);
|
||||
} else {
|
||||
cmd_line_magic = 0xA33F;
|
||||
cmd_line_offset = heap_end;
|
||||
setup_move_size = heap_end + strlen(cmdline)+1;
|
||||
strcpy(base_ptr+cmd_line_offset, cmdline);
|
||||
}
|
||||
} else {
|
||||
/* Very old kernel */
|
||||
if (protocol >= 0x0202) {
|
||||
cmd_line_ptr = base_ptr + heap_end;
|
||||
strcpy(cmd_line_ptr, cmdline);
|
||||
} else {
|
||||
cmd_line_magic = 0xA33F;
|
||||
cmd_line_offset = heap_end;
|
||||
setup_move_size = heap_end + strlen(cmdline) + 1;
|
||||
strcpy(base_ptr + cmd_line_offset, cmdline);
|
||||
}
|
||||
} else {
|
||||
/* Very old kernel */
|
||||
|
||||
heap_end = 0x9800;
|
||||
heap_end = 0x9800;
|
||||
|
||||
cmd_line_magic = 0xA33F;
|
||||
cmd_line_offset = heap_end;
|
||||
cmd_line_magic = 0xA33F;
|
||||
cmd_line_offset = heap_end;
|
||||
|
||||
/* A very old kernel MUST have its real-mode code
|
||||
loaded at 0x90000 */
|
||||
/* A very old kernel MUST have its real-mode code loaded at 0x90000 */
|
||||
if (base_ptr != 0x90000) {
|
||||
/* Copy the real-mode kernel */
|
||||
memcpy(0x90000, base_ptr, (setup_sects + 1) * 512);
|
||||
base_ptr = 0x90000; /* Relocated */
|
||||
}
|
||||
|
||||
if ( base_ptr != 0x90000 ) {
|
||||
/* Copy the real-mode kernel */
|
||||
memcpy(0x90000, base_ptr, (setup_sects+1)*512);
|
||||
base_ptr = 0x90000; /* Relocated */
|
||||
}
|
||||
strcpy(0x90000 + cmd_line_offset, cmdline);
|
||||
|
||||
strcpy(0x90000+cmd_line_offset, cmdline);
|
||||
|
||||
/* It is recommended to clear memory up to the 32K mark */
|
||||
memset(0x90000 + (setup_sects+1)*512, 0,
|
||||
(64-(setup_sects+1))*512);
|
||||
}
|
||||
/* It is recommended to clear memory up to the 32K mark */
|
||||
memset(0x90000 + (setup_sects + 1) * 512, 0, (64 - (setup_sects + 1)) * 512);
|
||||
}
|
||||
|
||||
|
||||
Loading The Rest of The Kernel
|
||||
==============================
|
||||
|
||||
The 32-bit (non-real-mode) kernel starts at offset (setup_sects+1)*512
|
||||
The 32-bit (non-real-mode) kernel starts at offset (setup_sects + 1) * 512
|
||||
in the kernel file (again, if setup_sects == 0 the real value is 4.)
|
||||
It should be loaded at address 0x10000 for Image/zImage kernels and
|
||||
0x100000 for bzImage kernels.
|
||||
@ -1207,13 +1203,14 @@ It should be loaded at address 0x10000 for Image/zImage kernels and
|
||||
The kernel is a bzImage kernel if the protocol >= 2.00 and the 0x01
|
||||
bit (LOAD_HIGH) in the loadflags field is set::
|
||||
|
||||
is_bzImage = (protocol >= 0x0200) && (loadflags & 0x01);
|
||||
load_address = is_bzImage ? 0x100000 : 0x10000;
|
||||
is_bzImage = (protocol >= 0x0200) && (loadflags & 0x01);
|
||||
load_address = is_bzImage ? 0x100000 : 0x10000;
|
||||
|
||||
Note that Image/zImage kernels can be up to 512K in size, and thus use
|
||||
the entire 0x10000-0x90000 range of memory. This means it is pretty
|
||||
much a requirement for these kernels to load the real-mode part at
|
||||
0x90000. bzImage kernels allow much more flexibility.
|
||||
.. note::
|
||||
Image/zImage kernels can be up to 512K in size, and thus use the entire
|
||||
0x10000-0x90000 range of memory. This means it is pretty much a
|
||||
requirement for these kernels to load the real-mode part at 0x90000.
|
||||
bzImage kernels allow much more flexibility.
|
||||
|
||||
Special Command Line Options
|
||||
============================
|
||||
@ -1282,19 +1279,20 @@ es = ss.
|
||||
|
||||
In our example from above, we would do::
|
||||
|
||||
/* Note: in the case of the "old" kernel protocol, base_ptr must
|
||||
be == 0x90000 at this point; see the previous sample code */
|
||||
/*
|
||||
* Note: in the case of the "old" kernel protocol, base_ptr must
|
||||
* be == 0x90000 at this point; see the previous sample code.
|
||||
*/
|
||||
seg = base_ptr >> 4;
|
||||
|
||||
seg = base_ptr >> 4;
|
||||
cli(); /* Enter with interrupts disabled! */
|
||||
|
||||
cli(); /* Enter with interrupts disabled! */
|
||||
/* Set up the real-mode kernel stack */
|
||||
_SS = seg;
|
||||
_SP = heap_end;
|
||||
|
||||
/* Set up the real-mode kernel stack */
|
||||
_SS = seg;
|
||||
_SP = heap_end;
|
||||
|
||||
_DS = _ES = _FS = _GS = seg;
|
||||
jmp_far(seg+0x20, 0); /* Run the kernel */
|
||||
_DS = _ES = _FS = _GS = seg;
|
||||
jmp_far(seg + 0x20, 0); /* Run the kernel */
|
||||
|
||||
If your boot sector accesses a floppy drive, it is recommended to
|
||||
switch off the floppy motor before running the kernel, since the
|
||||
@ -1349,7 +1347,7 @@ from offset 0x01f1 of kernel image on should be loaded into struct
|
||||
boot_params and examined. The end of setup header can be calculated as
|
||||
follow::
|
||||
|
||||
0x0202 + byte value at offset 0x0201
|
||||
0x0202 + byte value at offset 0x0201
|
||||
|
||||
In addition to read/modify/write the setup header of the struct
|
||||
boot_params as that of 16-bit boot protocol, the boot loader should
|
||||
@ -1385,7 +1383,7 @@ Then, the setup header at offset 0x01f1 of kernel image on should be
|
||||
loaded into struct boot_params and examined. The end of setup header
|
||||
can be calculated as follows::
|
||||
|
||||
0x0202 + byte value at offset 0x0201
|
||||
0x0202 + byte value at offset 0x0201
|
||||
|
||||
In addition to read/modify/write the setup header of the struct
|
||||
boot_params as that of 16-bit boot protocol, the boot loader should
|
||||
@ -1427,7 +1425,7 @@ execution context provided by the EFI firmware.
|
||||
|
||||
The function prototype for the handover entry point looks like this::
|
||||
|
||||
efi_stub_entry(void *handle, efi_system_table_t *table, struct boot_params *bp)
|
||||
void efi_stub_entry(void *handle, efi_system_table_t *table, struct boot_params *bp);
|
||||
|
||||
'handle' is the EFI image handle passed to the boot loader by the EFI
|
||||
firmware, 'table' is the EFI system table - these are the first two
|
||||
@ -1442,12 +1440,13 @@ The boot loader *must* fill out the following fields in bp::
|
||||
|
||||
All other fields should be zero.
|
||||
|
||||
NOTE: The EFI Handover Protocol is deprecated in favour of the ordinary PE/COFF
|
||||
entry point, combined with the LINUX_EFI_INITRD_MEDIA_GUID based initrd
|
||||
loading protocol (refer to [0] for an example of the bootloader side of
|
||||
this), which removes the need for any knowledge on the part of the EFI
|
||||
bootloader regarding the internal representation of boot_params or any
|
||||
requirements/limitations regarding the placement of the command line
|
||||
and ramdisk in memory, or the placement of the kernel image itself.
|
||||
.. note::
|
||||
The EFI Handover Protocol is deprecated in favour of the ordinary PE/COFF
|
||||
entry point, combined with the LINUX_EFI_INITRD_MEDIA_GUID based initrd
|
||||
loading protocol (refer to [0] for an example of the bootloader side of
|
||||
this), which removes the need for any knowledge on the part of the EFI
|
||||
bootloader regarding the internal representation of boot_params or any
|
||||
requirements/limitations regarding the placement of the command line
|
||||
and ramdisk in memory, or the placement of the kernel image itself.
|
||||
|
||||
[0] https://github.com/u-boot/u-boot/commit/ec80b4735a593961fe701cc3a5d717d4739b0fd0
|
||||
|
@ -53,6 +53,7 @@ Library functionality that is used throughout the kernel.
|
||||
floating-point
|
||||
union_find
|
||||
min_heap
|
||||
parser
|
||||
|
||||
Low level entry and exit
|
||||
========================
|
||||
|
@ -3,7 +3,7 @@ Adding reference counters (krefs) to kernel objects
|
||||
===================================================
|
||||
|
||||
:Author: Corey Minyard <minyard@acm.org>
|
||||
:Author: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
:Author: Thomas Hellström <thomas.hellstrom@linux.intel.com>
|
||||
|
||||
A lot of this was lifted from Greg Kroah-Hartman's 2004 OLS paper and
|
||||
presentation on krefs, which can be found at:
|
||||
@ -321,3 +321,8 @@ rcu grace period after release_entry_rcu was called. That can be accomplished
|
||||
by using kfree_rcu(entry, rhead) as done above, or by calling synchronize_rcu()
|
||||
before using kfree, but note that synchronize_rcu() may sleep for a
|
||||
substantial amount of time.
|
||||
|
||||
Functions and structures
|
||||
========================
|
||||
|
||||
.. kernel-doc:: include/linux/kref.h
|
||||
|
17
Documentation/core-api/parser.rst
Normal file
17
Documentation/core-api/parser.rst
Normal file
@ -0,0 +1,17 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
==============
|
||||
Generic parser
|
||||
==============
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The generic parser is a simple parser for parsing mount options,
|
||||
filesystem options, driver options, subsystem options, etc.
|
||||
|
||||
Parser API
|
||||
==========
|
||||
|
||||
.. kernel-doc:: lib/parser.c
|
||||
:export:
|
@ -41,9 +41,9 @@ entries.
|
||||
In addition to the macros EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL(), that allow
|
||||
exporting of kernel symbols to the kernel symbol table, variants of these are
|
||||
available to export symbols into a certain namespace: EXPORT_SYMBOL_NS() and
|
||||
EXPORT_SYMBOL_NS_GPL(). They take one additional argument: the namespace.
|
||||
Please note that due to macro expansion that argument needs to be a
|
||||
preprocessor symbol. E.g. to export the symbol ``usb_stor_suspend`` into the
|
||||
EXPORT_SYMBOL_NS_GPL(). They take one additional argument: the namespace as a
|
||||
string constant. Note that this string must not contain whitespaces.
|
||||
E.g. to export the symbol ``usb_stor_suspend`` into the
|
||||
namespace ``USB_STORAGE``, use::
|
||||
|
||||
EXPORT_SYMBOL_NS(usb_stor_suspend, "USB_STORAGE");
|
||||
@ -78,11 +78,10 @@ as this argument has preference over a default symbol namespace.
|
||||
A second option to define the default namespace is directly in the compilation
|
||||
unit as preprocessor statement. The above example would then read::
|
||||
|
||||
#undef DEFAULT_SYMBOL_NAMESPACE
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "USB_COMMON"
|
||||
|
||||
within the corresponding compilation unit before any EXPORT_SYMBOL macro is
|
||||
used.
|
||||
within the corresponding compilation unit before the #include for
|
||||
<linux/export.h>. Typically it's placed before the first #include statement.
|
||||
|
||||
3. How to use Symbols exported in Namespaces
|
||||
============================================
|
||||
|
@ -10,6 +10,9 @@ whole; patches welcome!
|
||||
A brief overview of testing-specific tools can be found in
|
||||
Documentation/dev-tools/testing-overview.rst
|
||||
|
||||
Tools that are specific to debugging can be found in
|
||||
Documentation/process/debugging/index.rst
|
||||
|
||||
.. toctree::
|
||||
:caption: Table of contents
|
||||
:maxdepth: 2
|
||||
@ -27,8 +30,6 @@ Documentation/dev-tools/testing-overview.rst
|
||||
kmemleak
|
||||
kcsan
|
||||
kfence
|
||||
gdb-kernel-debugging
|
||||
kgdb
|
||||
kselftest
|
||||
kunit/index
|
||||
ktap
|
||||
|
@ -104,7 +104,7 @@ iomap calls these functions:
|
||||
|
||||
For the pagecache, races can happen if writeback doesn't take
|
||||
``i_rwsem`` or ``invalidate_lock`` and updates mapping information.
|
||||
Races can also happen if the filesytem allows concurrent writes.
|
||||
Races can also happen if the filesystem allows concurrent writes.
|
||||
For such files, the mapping *must* be revalidated after the folio
|
||||
lock has been taken so that iomap can manage the folio correctly.
|
||||
|
||||
|
@ -156,7 +156,7 @@ A directory is made opaque by setting the xattr "trusted.overlay.opaque"
|
||||
to "y". Where the upper filesystem contains an opaque directory, any
|
||||
directory in the lower filesystem with the same name is ignored.
|
||||
|
||||
An opaque directory should not conntain any whiteouts, because they do not
|
||||
An opaque directory should not contain any whiteouts, because they do not
|
||||
serve any purpose. A merge directory containing regular files with the xattr
|
||||
"trusted.overlay.whiteout", should be additionally marked by setting the xattr
|
||||
"trusted.overlay.opaque" to "x" on the merge directory itself.
|
||||
@ -266,7 +266,7 @@ Non-directories
|
||||
Objects that are not directories (files, symlinks, device-special
|
||||
files etc.) are presented either from the upper or lower filesystem as
|
||||
appropriate. When a file in the lower filesystem is accessed in a way
|
||||
the requires write-access, such as opening for write access, changing
|
||||
that requires write-access, such as opening for write access, changing
|
||||
some metadata etc., the file is first copied from the lower filesystem
|
||||
to the upper filesystem (copy_up). Note that creating a hard-link
|
||||
also requires copy_up, though of course creation of a symlink does
|
||||
@ -549,8 +549,8 @@ Nesting overlayfs mounts
|
||||
|
||||
It is possible to use a lower directory that is stored on an overlayfs
|
||||
mount. For regular files this does not need any special care. However, files
|
||||
that have overlayfs attributes, such as whiteouts or "overlay.*" xattrs will be
|
||||
interpreted by the underlying overlayfs mount and stripped out. In order to
|
||||
that have overlayfs attributes, such as whiteouts or "overlay.*" xattrs, will
|
||||
be interpreted by the underlying overlayfs mount and stripped out. In order to
|
||||
allow the second overlayfs mount to see the attributes they must be escaped.
|
||||
|
||||
Overlayfs specific xattrs are escaped by using a special prefix of
|
||||
|
@ -313,7 +313,7 @@ done.
|
||||
|
||||
**mandatory**
|
||||
|
||||
block truncatation on error exit from ->write_begin, and ->direct_IO
|
||||
block truncation on error exit from ->write_begin, and ->direct_IO
|
||||
moved from generic methods (block_write_begin, cont_write_begin,
|
||||
nobh_write_begin, blockdev_direct_IO*) to callers. Take a look at
|
||||
ext2_write_failed and callers for an example.
|
||||
|
@ -261,6 +261,10 @@ The tags in common use are:
|
||||
can be used instead of Closes: if the patch fixes a part of the issue(s)
|
||||
being reported.
|
||||
|
||||
- A Suggested-by: tag indicates that the patch idea is suggested by the person
|
||||
named and ensures credit to the person for the idea. This will, hopefully,
|
||||
inspire them to help us again in the future.
|
||||
|
||||
- Cc: the named person received a copy of the patch and had the
|
||||
opportunity to comment on it.
|
||||
|
||||
|
@ -207,17 +207,29 @@ resources, that can cause performance disruptions or even OOM kills.
|
||||
device coredump
|
||||
---------------
|
||||
|
||||
Prerequisite: ``#include <linux/devcoredump.h>``
|
||||
Prerequisite: ``CONFIG_DEV_COREDUMP`` & ``#include <linux/devcoredump.h>``
|
||||
|
||||
Provides the infrastructure for a driver to provide arbitrary data to userland.
|
||||
It is most often used in conjunction with udev or similar userland application
|
||||
to listen for kernel uevents, which indicate that the dump is ready. Udev has
|
||||
rules to copy that file somewhere for long-term storage and analysis, as by
|
||||
default, the data for the dump is automatically cleaned up after 5 minutes.
|
||||
That data is analyzed with driver-specific tools or GDB.
|
||||
default, the data for the dump is automatically cleaned up after a default
|
||||
5 minutes. That data is analyzed with driver-specific tools or GDB.
|
||||
|
||||
A device coredump can be created with a vmalloc area, with read/free
|
||||
methods, or as a scatter/gather list.
|
||||
|
||||
You can find an example implementation at:
|
||||
`drivers/media/platform/qcom/venus/core.c
|
||||
<https://elixir.bootlin.com/linux/v6.11.6/source/drivers/media/platform/qcom/venus/core.c#L30>`__
|
||||
<https://elixir.bootlin.com/linux/v6.11.6/source/drivers/media/platform/qcom/venus/core.c#L30>`__,
|
||||
in the Bluetooth HCI layer, in several wireless drivers, and in several
|
||||
DRM drivers.
|
||||
|
||||
devcoredump interfaces
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: include/linux/devcoredump.h
|
||||
|
||||
.. kernel-doc:: drivers/base/devcoredump.c
|
||||
|
||||
**Copyright** ©2024 : Collabora
|
||||
|
@ -11,6 +11,8 @@ general guides
|
||||
:maxdepth: 1
|
||||
|
||||
driver_development_debugging_guide
|
||||
gdb-kernel-debugging
|
||||
kgdb
|
||||
userspace_debugging_guide
|
||||
|
||||
.. only:: subproject and html
|
||||
|
@ -255,10 +255,10 @@ scenarios.
|
||||
.. note::
|
||||
|
||||
Kgdboc does not support interrupting the target via the gdb remote
|
||||
protocol. You must manually send a :kbd:`SysRq-G` unless you have a proxy
|
||||
protocol. You must manually send a `SysRq-G` unless you have a proxy
|
||||
that splits console output to a terminal program. A console proxy has a
|
||||
separate TCP port for the debugger and a separate TCP port for the
|
||||
"human" console. The proxy can take care of sending the :kbd:`SysRq-G`
|
||||
"human" console. The proxy can take care of sending the `SysRq-G`
|
||||
for you.
|
||||
|
||||
When using kgdboc with no debugger proxy, you can end up connecting the
|
||||
@ -267,9 +267,9 @@ have loaded kgdboc, a message should print on the console stating it is
|
||||
waiting for the debugger. In this case you disconnect your terminal
|
||||
program and then connect the debugger in its place. If you want to
|
||||
interrupt the target system and forcibly enter a debug session you have
|
||||
to issue a :kbd:`Sysrq` sequence and then type the letter :kbd:`g`. Then you
|
||||
to issue a `Sysrq` sequence and then type the letter `g`. Then you
|
||||
disconnect the terminal session and connect gdb. Your options if you
|
||||
don't like this are to hack gdb to send the :kbd:`SysRq-G` for you as well as
|
||||
don't like this are to hack gdb to send the `SysRq-G` for you as well as
|
||||
on the initial connect, or to use a debugger proxy that allows an
|
||||
unmodified gdb to do the debugging.
|
||||
|
||||
@ -401,7 +401,7 @@ This is a quick example of how to use kdb.
|
||||
|
||||
2. Enter the kernel debugger manually or by waiting for an oops or
|
||||
fault. There are several ways you can enter the kernel debugger
|
||||
manually; all involve using the :kbd:`SysRq-G`, which means you must have
|
||||
manually; all involve using the `SysRq-G`, which means you must have
|
||||
enabled ``CONFIG_MAGIC_SYSRQ=y`` in your kernel config.
|
||||
|
||||
- When logged in as root or with a super user session you can run::
|
||||
@ -410,16 +410,16 @@ This is a quick example of how to use kdb.
|
||||
|
||||
- Example using minicom 2.2
|
||||
|
||||
Press: :kbd:`CTRL-A` :kbd:`f` :kbd:`g`
|
||||
Press: `CTRL-A` `f` `g`
|
||||
|
||||
- When you have telneted to a terminal server that supports sending
|
||||
a remote break
|
||||
|
||||
Press: :kbd:`CTRL-]`
|
||||
Press: `CTRL-]`
|
||||
|
||||
Type in: ``send break``
|
||||
|
||||
Press: :kbd:`Enter` :kbd:`g`
|
||||
Press: `Enter` `g`
|
||||
|
||||
3. From the kdb prompt you can run the ``help`` command to see a complete
|
||||
list of the commands that are available.
|
||||
@ -460,7 +460,7 @@ This is a quick example of how to use kdb with a keyboard.
|
||||
|
||||
2. Enter the kernel debugger manually or by waiting for an oops or
|
||||
fault. There are several ways you can enter the kernel debugger
|
||||
manually; all involve using the :kbd:`SysRq-G`, which means you must have
|
||||
manually; all involve using the `SysRq-G`, which means you must have
|
||||
enabled ``CONFIG_MAGIC_SYSRQ=y`` in your kernel config.
|
||||
|
||||
- When logged in as root or with a super user session you can run::
|
||||
@ -469,27 +469,27 @@ This is a quick example of how to use kdb with a keyboard.
|
||||
|
||||
- Example using a laptop keyboard:
|
||||
|
||||
Press and hold down: :kbd:`Alt`
|
||||
Press and hold down: `Alt`
|
||||
|
||||
Press and hold down: :kbd:`Fn`
|
||||
Press and hold down: `Fn`
|
||||
|
||||
Press and release the key with the label: :kbd:`SysRq`
|
||||
Press and release the key with the label: `SysRq`
|
||||
|
||||
Release: :kbd:`Fn`
|
||||
Release: `Fn`
|
||||
|
||||
Press and release: :kbd:`g`
|
||||
Press and release: `g`
|
||||
|
||||
Release: :kbd:`Alt`
|
||||
Release: `Alt`
|
||||
|
||||
- Example using a PS/2 101-key keyboard
|
||||
|
||||
Press and hold down: :kbd:`Alt`
|
||||
Press and hold down: `Alt`
|
||||
|
||||
Press and release the key with the label: :kbd:`SysRq`
|
||||
Press and release the key with the label: `SysRq`
|
||||
|
||||
Press and release: :kbd:`g`
|
||||
Press and release: `g`
|
||||
|
||||
Release: :kbd:`Alt`
|
||||
Release: `Alt`
|
||||
|
||||
3. Now type in a kdb command such as ``help``, ``dmesg``, ``bt`` or ``go`` to
|
||||
continue kernel execution.
|
||||
@ -531,7 +531,7 @@ Connecting with gdb to a serial port
|
||||
|
||||
In order to connect to gdb via kgdboc, the kernel must first be
|
||||
stopped. There are several ways to stop the kernel which include
|
||||
using kgdbwait as a boot argument, via a :kbd:`SysRq-G`, or running the
|
||||
using kgdbwait as a boot argument, via a `SysRq-G`, or running the
|
||||
kernel until it takes an exception where it waits for the debugger to
|
||||
attach.
|
||||
|
||||
@ -541,16 +541,16 @@ Connecting with gdb to a serial port
|
||||
|
||||
- Example using minicom 2.2
|
||||
|
||||
Press: :kbd:`CTRL-A` :kbd:`f` :kbd:`g`
|
||||
Press: `CTRL-A` `f` `g`
|
||||
|
||||
- When you have telneted to a terminal server that supports sending
|
||||
a remote break
|
||||
|
||||
Press: :kbd:`CTRL-]`
|
||||
Press: `CTRL-]`
|
||||
|
||||
Type in: ``send break``
|
||||
|
||||
Press: :kbd:`Enter` :kbd:`g`
|
||||
Press: `Enter` `g`
|
||||
|
||||
3. Connect from gdb
|
||||
|
||||
@ -578,7 +578,7 @@ Connecting with gdb to a serial port
|
||||
set debug remote 1
|
||||
|
||||
Remember if you continue in gdb, and need to "break in" again, you need
|
||||
to issue an other :kbd:`SysRq-G`. It is easy to create a simple entry point by
|
||||
to issue an other `SysRq-G`. It is easy to create a simple entry point by
|
||||
putting a breakpoint at ``sys_sync`` and then you can run ``sync`` from a
|
||||
shell or script to break into the debugger.
|
||||
|
||||
@ -612,7 +612,7 @@ or delete because kgdb will interpret that as part of the debug stream.
|
||||
|
||||
.. note::
|
||||
|
||||
Now you must kill gdb. Typically you press :kbd:`CTRL-Z` and issue
|
||||
Now you must kill gdb. Typically you press `CTRL-Z` and issue
|
||||
the command::
|
||||
|
||||
kill -9 %
|
@ -86,7 +86,7 @@ In the :menuselection:`Sending Preferences` section:
|
||||
- :menuselection:`Strip Whitespace Before Sending` must be ``disabled``
|
||||
|
||||
When composing the message, the cursor should be placed where the patch
|
||||
should appear, and then pressing :kbd:`CTRL-R` let you specify the patch file
|
||||
should appear, and then pressing `CTRL-R` let you specify the patch file
|
||||
to insert into the message.
|
||||
|
||||
Claws Mail (GUI)
|
||||
@ -94,7 +94,7 @@ Claws Mail (GUI)
|
||||
|
||||
Works. Some people use this successfully for patches.
|
||||
|
||||
To insert a patch use :menuselection:`Message-->Insert File` (:kbd:`CTRL-I`)
|
||||
To insert a patch use :menuselection:`Message-->Insert File` (`CTRL-I`)
|
||||
or an external editor.
|
||||
|
||||
If the inserted patch has to be edited in the Claws composition window
|
||||
@ -108,11 +108,11 @@ Evolution (GUI)
|
||||
Some people use this successfully for patches.
|
||||
|
||||
When composing mail select: Preformat
|
||||
from :menuselection:`Format-->Paragraph Style-->Preformatted` (:kbd:`CTRL-7`)
|
||||
from :menuselection:`Format-->Paragraph Style-->Preformatted` (`CTRL-7`)
|
||||
or the toolbar
|
||||
|
||||
Then use:
|
||||
:menuselection:`Insert-->Text File...` (:kbd:`ALT-N x`)
|
||||
:menuselection:`Insert-->Text File...` (`ALT-N x`)
|
||||
to insert the patch.
|
||||
|
||||
You can also ``diff -Nru old.c new.c | xclip``, select
|
||||
|
@ -270,7 +270,7 @@ Ordering of commit tags
|
||||
To have a uniform view of the commit tags, the tip maintainers use the
|
||||
following tag ordering scheme:
|
||||
|
||||
- Fixes: 12char-SHA1 ("sub/sys: Original subject line")
|
||||
- Fixes: 12+char-SHA1 ("sub/sys: Original subject line")
|
||||
|
||||
A Fixes tag should be added even for changes which do not need to be
|
||||
backported to stable kernels, i.e. when addressing a recently introduced
|
||||
|
@ -143,10 +143,10 @@ also track such tags and take certain actions. Private bug trackers and
|
||||
invalid URLs are forbidden.
|
||||
|
||||
If your patch fixes a bug in a specific commit, e.g. you found an issue using
|
||||
``git bisect``, please use the 'Fixes:' tag with the first 12 characters of
|
||||
the SHA-1 ID, and the one line summary. Do not split the tag across multiple
|
||||
lines, tags are exempt from the "wrap at 75 columns" rule in order to simplify
|
||||
parsing scripts. For example::
|
||||
``git bisect``, please use the 'Fixes:' tag with at least the first 12
|
||||
characters of the SHA-1 ID, and the one line summary. Do not split the tag
|
||||
across multiple lines, tags are exempt from the "wrap at 75 columns" rule in
|
||||
order to simplify parsing scripts. For example::
|
||||
|
||||
Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
|
||||
|
||||
@ -610,6 +610,9 @@ that, if you have your patches stored in a ``git`` repository, proper patch
|
||||
formatting can be had with ``git format-patch``. The tools cannot create
|
||||
the necessary text, though, so read the instructions below anyway.
|
||||
|
||||
Subject Line
|
||||
^^^^^^^^^^^^
|
||||
|
||||
The canonical patch subject line is::
|
||||
|
||||
Subject: [PATCH 001/123] subsystem: summary phrase
|
||||
@ -683,6 +686,9 @@ Here are some good example Subjects::
|
||||
Subject: [PATCH v2] sub/sys: Condensed patch summary
|
||||
Subject: [PATCH v2 M/N] sub/sys: Condensed patch summary
|
||||
|
||||
From Line
|
||||
^^^^^^^^^
|
||||
|
||||
The ``from`` line must be the very first line in the message body,
|
||||
and has the form:
|
||||
|
||||
@ -693,6 +699,9 @@ patch in the permanent changelog. If the ``from`` line is missing,
|
||||
then the ``From:`` line from the email header will be used to determine
|
||||
the patch author in the changelog.
|
||||
|
||||
Explanation Body
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
The explanation body will be committed to the permanent source
|
||||
changelog, so should make sense to a competent reader who has long since
|
||||
forgotten the immediate details of the discussion that might have led to
|
||||
@ -708,6 +717,31 @@ _all_ of the compile failures; just enough that it is likely that
|
||||
someone searching for the patch can find it. As in the ``summary
|
||||
phrase``, it is important to be both succinct as well as descriptive.
|
||||
|
||||
.. _backtraces:
|
||||
|
||||
Backtraces in commit messages
|
||||
"""""""""""""""""""""""""""""
|
||||
|
||||
Backtraces help document the call chain leading to a problem. However,
|
||||
not all backtraces are helpful. For example, early boot call chains are
|
||||
unique and obvious. Copying the full dmesg output verbatim, however,
|
||||
adds distracting information like timestamps, module lists, register and
|
||||
stack dumps.
|
||||
|
||||
Therefore, the most useful backtraces should distill the relevant
|
||||
information from the dump, which makes it easier to focus on the real
|
||||
issue. Here is an example of a well-trimmed backtrace::
|
||||
|
||||
unchecked MSR access error: WRMSR to 0xd51 (tried to write 0x0000000000000064)
|
||||
at rIP: 0xffffffffae059994 (native_write_msr+0x4/0x20)
|
||||
Call Trace:
|
||||
mba_wrmsr
|
||||
update_domains
|
||||
rdtgroup_mkdir
|
||||
|
||||
Commentary
|
||||
^^^^^^^^^^
|
||||
|
||||
The ``---`` marker line serves the essential purpose of marking for
|
||||
patch handling tools where the changelog message ends.
|
||||
|
||||
@ -746,28 +780,6 @@ patch::
|
||||
See more details on the proper patch format in the following
|
||||
references.
|
||||
|
||||
.. _backtraces:
|
||||
|
||||
Backtraces in commit messages
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Backtraces help document the call chain leading to a problem. However,
|
||||
not all backtraces are helpful. For example, early boot call chains are
|
||||
unique and obvious. Copying the full dmesg output verbatim, however,
|
||||
adds distracting information like timestamps, module lists, register and
|
||||
stack dumps.
|
||||
|
||||
Therefore, the most useful backtraces should distill the relevant
|
||||
information from the dump, which makes it easier to focus on the real
|
||||
issue. Here is an example of a well-trimmed backtrace::
|
||||
|
||||
unchecked MSR access error: WRMSR to 0xd51 (tried to write 0x0000000000000064)
|
||||
at rIP: 0xffffffffae059994 (native_write_msr+0x4/0x20)
|
||||
Call Trace:
|
||||
mba_wrmsr
|
||||
update_domains
|
||||
rdtgroup_mkdir
|
||||
|
||||
.. _explicit_in_reply_to:
|
||||
|
||||
Explicit In-Reply-To headers
|
||||
|
@ -591,12 +591,13 @@ Deadline Task Scheduling
|
||||
|
||||
The system wide settings are configured under the /proc virtual file system.
|
||||
|
||||
For now the -rt knobs are used for -deadline admission control and the
|
||||
-deadline runtime is accounted against the -rt runtime. We realize that this
|
||||
isn't entirely desirable; however, it is better to have a small interface for
|
||||
now, and be able to change it easily later. The ideal situation (see 5.) is to
|
||||
run -rt tasks from a -deadline server; in which case the -rt bandwidth is a
|
||||
direct subset of dl_bw.
|
||||
For now the -rt knobs are used for -deadline admission control and with
|
||||
CONFIG_RT_GROUP_SCHED the -deadline runtime is accounted against the (root)
|
||||
-rt runtime. With !CONFIG_RT_GROUP_SCHED the knob only serves for the -dl
|
||||
admission control. We realize that this isn't entirely desirable; however, it
|
||||
is better to have a small interface for now, and be able to change it easily
|
||||
later. The ideal situation (see 5.) is to run -rt tasks from a -deadline
|
||||
server; in which case the -rt bandwidth is a direct subset of dl_bw.
|
||||
|
||||
This means that, for a root_domain comprising M CPUs, -deadline tasks
|
||||
can be created while the sum of their bandwidths stays below:
|
||||
|
@ -16,12 +16,12 @@ programs - the BPF scheduler.
|
||||
* The system integrity is maintained no matter what the BPF scheduler does.
|
||||
The default scheduling behavior is restored anytime an error is detected,
|
||||
a runnable task stalls, or on invoking the SysRq key sequence
|
||||
:kbd:`SysRq-S`.
|
||||
`SysRq-S`.
|
||||
|
||||
* When the BPF scheduler triggers an error, debug information is dumped to
|
||||
aid debugging. The debug dump is passed to and printed out by the
|
||||
scheduler binary. The debug dump can also be accessed through the
|
||||
`sched_ext_dump` tracepoint. The SysRq key sequence :kbd:`SysRq-D`
|
||||
`sched_ext_dump` tracepoint. The SysRq key sequence `SysRq-D`
|
||||
triggers a debug dump. This doesn't terminate the BPF scheduler and can
|
||||
only be read through the tracepoint.
|
||||
|
||||
@ -59,7 +59,7 @@ set in ``ops->flags``, only tasks with the ``SCHED_EXT`` policy are scheduled
|
||||
by sched_ext, while tasks with ``SCHED_NORMAL``, ``SCHED_BATCH`` and
|
||||
``SCHED_IDLE`` policies are scheduled by CFS.
|
||||
|
||||
Terminating the sched_ext scheduler program, triggering :kbd:`SysRq-S`, or
|
||||
Terminating the sched_ext scheduler program, triggering `SysRq-S`, or
|
||||
detection of any internal error including stalled runnable tasks aborts the
|
||||
BPF scheduler and reverts all tasks back to CFS.
|
||||
|
||||
|
@ -92,10 +92,10 @@ The system wide settings are configured under the /proc virtual file system:
|
||||
/proc/sys/kernel/sched_rt_runtime_us:
|
||||
A global limit on how much time real-time scheduling may use. This is always
|
||||
less or equal to the period_us, as it denotes the time allocated from the
|
||||
period_us for the real-time tasks. Even without CONFIG_RT_GROUP_SCHED enabled,
|
||||
this will limit time reserved to real-time processes. With
|
||||
CONFIG_RT_GROUP_SCHED=y it signifies the total bandwidth available to all
|
||||
real-time groups.
|
||||
period_us for the real-time tasks. Without CONFIG_RT_GROUP_SCHED enabled,
|
||||
this only serves for admission control of deadline tasks. With
|
||||
CONFIG_RT_GROUP_SCHED=y it also signifies the total bandwidth available to
|
||||
all real-time groups.
|
||||
|
||||
* Time is specified in us because the interface is s32. This gives an
|
||||
operating range from 1us to about 35 minutes.
|
||||
|
@ -8,14 +8,14 @@ checking* and *theorem proving*) with a more practical approach for complex
|
||||
systems.
|
||||
|
||||
Instead of relying on a fine-grained model of a system (e.g., a
|
||||
re-implementation a instruction level), RV works by analyzing the trace of the
|
||||
re-implementation at instruction level), RV works by analyzing the trace of the
|
||||
system's actual execution, comparing it against a formal specification of
|
||||
the system behavior.
|
||||
|
||||
The main advantage is that RV can give precise information on the runtime
|
||||
behavior of the monitored system, without the pitfalls of developing models
|
||||
that require a re-implementation of the entire system in a modeling language.
|
||||
Moreover, given an efficient monitoring method, it is possible execute an
|
||||
Moreover, given an efficient monitoring method, it is possible to execute an
|
||||
*online* verification of a system, enabling the *reaction* for unexpected
|
||||
events, avoiding, for example, the propagation of a failure on safety-critical
|
||||
systems.
|
||||
|
@ -95,7 +95,7 @@ Nella sezione :menuselection:`Sending Preferences`:
|
||||
- :menuselection:`Strip Whitespace Before Sending` deve essere ``disabled``
|
||||
|
||||
Quando state scrivendo un messaggio, il cursore dev'essere posizionato
|
||||
dove volete che la patch inizi, poi premendo :kbd:`CTRL-R` vi verrà chiesto
|
||||
dove volete che la patch inizi, poi premendo `CTRL-R` vi verrà chiesto
|
||||
di selezionare il file patch da inserire nel messaggio.
|
||||
|
||||
Claws Mail (GUI)
|
||||
@ -104,7 +104,7 @@ Claws Mail (GUI)
|
||||
Funziona. Alcune persone riescono ad usarlo con successo per inviare le patch.
|
||||
|
||||
Per inserire una patch usate :menuselection:`Messaggio-->Inserisci file`
|
||||
(:kbd:`CTRL-I`) oppure un editor esterno.
|
||||
(`CTRL-I`) oppure un editor esterno.
|
||||
|
||||
Se la patch che avete inserito dev'essere modificata usando la finestra di
|
||||
scrittura di Claws, allora assicuratevi che l'"auto-interruzione" sia
|
||||
@ -117,10 +117,10 @@ Alcune persone riescono ad usarlo con successo per inviare le patch.
|
||||
|
||||
Quando state scrivendo una lettera selezionate: Preformattato
|
||||
da :menuselection:`Formato-->Stile del paragrafo-->Preformattato`
|
||||
(:kbd:`CTRL-7`) o dalla barra degli strumenti
|
||||
(`CTRL-7`) o dalla barra degli strumenti
|
||||
|
||||
Poi per inserire la patch usate:
|
||||
:menuselection:`Inserisci--> File di testo...` (:kbd:`ALT-N x`)
|
||||
:menuselection:`Inserisci--> File di testo...` (`ALT-N x`)
|
||||
|
||||
Potete anche eseguire ``diff -Nru old.c new.c | xclip``, selezionare
|
||||
:menuselection:`Preformattato`, e poi usare il tasto centrale del mouse.
|
||||
|
@ -1,11 +1,241 @@
|
||||
.. include:: ../disclaimer-sp.rst
|
||||
|
||||
:Original: Documentation/process/3.Early-stage.rst
|
||||
:Translator: Carlos Bilbao <carlos.bilbao.osdev@gmail.com> and Avadhut Naik <avadhut.naik@amd.com>
|
||||
|
||||
.. _sp_development_early_stage:
|
||||
|
||||
Planificación en etapa inicial
|
||||
==============================
|
||||
|
||||
.. warning::
|
||||
TODO aún no traducido
|
||||
Cuando uno se sienta a planear un proyecto de desarrollo del kernel Linux,
|
||||
puede ser tentador lanzarse directamente a escribir código. Sin embargo,
|
||||
como ocurre con cualquier proyecto significativo, gran parte del trabajo
|
||||
que conduce al éxito es mejor realizarlo antes de escribir la primera línea
|
||||
de código. Dedicar tiempo a la planificación y comunicación temprana puede
|
||||
ahorrar mucho más tiempo en adelante.
|
||||
|
||||
Especificar el problema
|
||||
-----------------------
|
||||
|
||||
Como en cualquier proyecto de ingeniería, una mejora exitosa del kernel
|
||||
comienza con una descripción clara del problema a resolver. En algunos
|
||||
casos, este paso es sencillo: cuando se necesita un driver para un hardware
|
||||
específico, por ejemplo. En otros, sin embargo, es tentador confundir el
|
||||
problema real con la solución propuesta, lo que puede generar dificultades.
|
||||
|
||||
Consideremos un ejemplo: hace algunos años, los desarrolladores que
|
||||
trabajaban con audio en Linux buscaban una forma de ejecutar aplicaciones
|
||||
sin interrupciones u otros artefactos causados por la latencia excesiva en
|
||||
el sistema. La solución a la que llegaron fue un módulo del kernel
|
||||
destinado a integrarse en el marco del Módulo de Seguridad de Linux (LSM,
|
||||
por sus siglas en inglés); este módulo podía configurarse para dar acceso a
|
||||
aplicaciones específicas al planificador en tiempo real. Este módulo fue
|
||||
implementado y enviado a la lista de correo del kernel de Linux, donde
|
||||
inmediatamente encontró problemas.
|
||||
|
||||
Para los desarrolladores de audio, este módulo de seguridad era suficiente
|
||||
para resolver su problema inmediato. Sin embargo, para la comunidad más
|
||||
amplia del kernel, se veía como un uso indebido del marco LSM (que no está
|
||||
diseñado para otorgar privilegios a procesos que de otro modo no los
|
||||
tendrían) y como un riesgo para la estabilidad del sistema. Sus soluciones
|
||||
preferidas implicaban el acceso a la programación en tiempo real a través
|
||||
del mecanismo de rlimit a corto plazo, y trabajo continuo para reducir la
|
||||
latencia a largo plazo.
|
||||
|
||||
La comunidad de audio, sin embargo, no podía ver más allá de la solución
|
||||
particular que habían implementado; no estaban dispuestos a aceptar
|
||||
alternativas. El desacuerdo resultante dejó a esos desarrolladores
|
||||
desilusionados con todo el proceso de desarrollo del kernel; uno de ellos
|
||||
volvió a una lista de audio y publicó esto (traducido):
|
||||
|
||||
"Hay un buen número de desarrolladores muy competentes del kernel de Linux, pero tienden a ser opacados por una multitud de arrogantes necios. Intentar comunicar los requisitos de los usuarios a estas personas es una pérdida de tiempo. Son demasiado 'inteligentes' como para escuchar a simples mortales".
|
||||
|
||||
Siendo el texto original:
|
||||
|
||||
There are a number of very good Linux kernel developers, but they
|
||||
tend to get outshouted by a large crowd of arrogant fools. Trying
|
||||
to communicate user requirements to these people is a waste of
|
||||
time. They are much too "intelligent" to listen to lesser mortals.
|
||||
|
||||
(https://lwn.net/Articles/131776/).
|
||||
|
||||
La realidad de la situación era diferente; los desarrolladores del kernel
|
||||
estaban mucho más preocupados por la estabilidad del sistema, el
|
||||
mantenimiento a largo plazo y encontrar la solución correcta al problema
|
||||
que por un módulo específico. La moraleja de la historia es centrarse en el
|
||||
problema, no en una solución específica, y discutirlo con la comunidad de
|
||||
desarrollo antes de invertir en la creación de un cuerpo de código.
|
||||
|
||||
Por lo tanto, al contemplar un proyecto de desarrollo del kernel, se deben
|
||||
obtener respuestas a un conjunto corto de preguntas:
|
||||
|
||||
- ¿Cuál es exactamente el problema que necesita ser resuelto?
|
||||
|
||||
- ¿Quiénes son los usuarios afectados por este problema? ¿Qué casos de uso
|
||||
debería abordar la solución?
|
||||
|
||||
- ¿En qué aspectos el kernel actual no logra abordar ese problema?
|
||||
|
||||
Solo entonces tiene sentido comenzar a considerar posibles soluciones.
|
||||
|
||||
Discusión temprana
|
||||
------------------
|
||||
|
||||
Al planificar un proyecto de desarrollo del kernel, tiene mucho sentido
|
||||
realizar discusiones con la comunidad antes de lanzarse a la
|
||||
implementación. La comunicación temprana puede ahorrar tiempo y problemas
|
||||
de varias maneras:
|
||||
|
||||
- Es posible que el problema ya esté siendo abordado por el kernel de
|
||||
maneras que no haya comprendido. El kernel de Linux es grande y tiene
|
||||
una serie de características y capacidades que no son inmediatamente
|
||||
obvias. No todas las capacidades del kernel están documentadas tan bien
|
||||
como uno quisiera, y es fácil pasar cosas por alto. El autor de este
|
||||
texto ha visto la publicación de un driver completo que duplicaba uno
|
||||
existente del que el nuevo autor no tenía conocimiento. El código que
|
||||
reinventa ruedas existentes no solo es desperdicio; tampoco será aceptado
|
||||
en el kernel principal.
|
||||
|
||||
- Puede haber elementos de la solución propuesta que no serán aceptables
|
||||
para su inclusión en el kernel principal. Es mejor descubrir problemas
|
||||
como este antes de escribir el código.
|
||||
|
||||
- Es completamente posible que otros desarrolladores ya hayan pensado en el
|
||||
problema; pueden tener ideas para una mejor solución y estar dispuestos a
|
||||
ayudar en la creación de esa solución.
|
||||
|
||||
Años de experiencia con la comunidad de desarrollo del kernel han enseñado
|
||||
una lección clara: el código del kernel que se diseña y desarrolla a
|
||||
puertas cerradas invariablemente tiene problemas que solo se revelan cuando
|
||||
el código se libera a la comunidad. A veces, estos problemas son graves,
|
||||
requiriendo meses o años de esfuerzo antes de que el código pueda cumplir
|
||||
con los estándares de la comunidad del kernel. Algunos ejemplos incluyen:
|
||||
|
||||
- La pila de red Devicescape fue diseñada e implementada para sistemas de
|
||||
un solo procesador. No pudo fusionarse en la rama principal hasta que se
|
||||
hizo adecuada para sistemas multiprocesador. Adaptar el bloqueo y otros
|
||||
aspectos en el código es una tarea difícil; como resultado, la fusión de
|
||||
este código (ahora llamado mac80211) se retrasó más de un año.
|
||||
|
||||
- El sistema de archivos Reiser4 incluía una serie de capacidades que, en
|
||||
opinión de los desarrolladores principales del kernel, deberían haberse
|
||||
implementado en la capa de sistemas de archivos virtuales. También
|
||||
incluía funciones que no podían implementarse fácilmente sin exponer el
|
||||
sistema a bloqueos causados por los usuarios. La revelación tardía de
|
||||
estos problemas, y la negativa a abordar algunos de ellos, ha mantenido a
|
||||
Reiser4 fuera del kernel principal.
|
||||
|
||||
- El módulo de seguridad AppArmor hacía uso de estructuras de datos
|
||||
internas del sistema de archivos virtual de maneras que se consideraban
|
||||
inseguras y poco fiables. Esta preocupación (entre otras) mantuvo a
|
||||
AppArmor fuera de la rama principal durante años.
|
||||
|
||||
En cada uno de estos casos, se podría haber evitado mucho dolor y trabajo
|
||||
adicional con algunas discusiones tempranas con los desarrolladores del
|
||||
kernel.
|
||||
|
||||
¿Con quién hablar?
|
||||
-------------------
|
||||
|
||||
Cuando los desarrolladores deciden hacer públicas sus ideas, la siguiente
|
||||
pregunta será: ¿dónde empezar? La respuesta es encontrar la lista de correo
|
||||
adecuada y el maintainer correcto. Para las listas de correo, la mejor
|
||||
opción es buscar en el archivo MAINTAINERS un lugar relevante para
|
||||
publicar. Si existe una lista de subsistema adecuada, es preferible
|
||||
publicarla allí en lugar de en linux-kernel; es más probable que llegues a
|
||||
desarrolladores con experiencia en el subsistema relevante y el ambiente
|
||||
puede ser más propicio.
|
||||
|
||||
Encontrar a los maintainers puede ser un poco más difícil. Nuevamente, el
|
||||
archivo MAINTAINERS es el lugar para empezar. Sin embargo, ese archivo
|
||||
tiende a no estar siempre actualizado, y no todos los subsistemas están
|
||||
representados allí. La persona listada en el archivo MAINTAINERS puede, de
|
||||
hecho, no ser la persona que está actuando en ese rol actualmente. Por lo
|
||||
tanto, cuando haya dudas sobre a quién contactar, un truco útil es usar git
|
||||
(y "git log" en particular) para ver quién está activo actualmente en el
|
||||
subsistema de interés. Mira quién está escribiendo parches y quién, si
|
||||
alguien, está adjuntando líneas de Signed-off-by a esos parches. Esas son
|
||||
las personas que estarán mejor posicionadas para ayudar con un nuevo
|
||||
proyecto de desarrollo.
|
||||
|
||||
La tarea de encontrar al maintainer correcto es lo suficientemente
|
||||
desafiante como para que los desarrolladores del kernel hayan añadido un
|
||||
script para facilitar el proceso:
|
||||
|
||||
::
|
||||
|
||||
.../scripts/get_maintainer.pl
|
||||
|
||||
Este script devolverá los maintainers actuales de un archivo o directorio
|
||||
dado cuando se le pase la opción "-f". Si se le pasa un parche en la línea
|
||||
de comandos, listará a los maintainers que probablemente deberían recibir
|
||||
copias del parche. Esta es la manera preferida (a diferencia de la opción
|
||||
"-f") de obtener la lista de personas a las que hay que enviar las copias
|
||||
de sus parches. Hay varias opciones que regulan cuán agresivamente
|
||||
get_maintainer.pl buscará maintainers; por favor, ten cuidado al usar las
|
||||
opciones más agresivas, ya que podrías terminar incluyendo desarrolladores
|
||||
que no tienen ningún interés real en el código que estás modificando.
|
||||
|
||||
Si todo lo demás falla, hablar con Andrew Morton puede ser una forma
|
||||
efectiva de encontrar a un maintainer para un código específico.
|
||||
|
||||
¿Cuándo publicar?
|
||||
------------------
|
||||
|
||||
Si es posible, publicar sus planes en las primeras etapas solo puede ser
|
||||
útil. Describa el problema que se está resolviendo y cualquier plan que se
|
||||
haya hecho sobre cómo se llevará a cabo la implementación. Cualquier
|
||||
información que puedas proporcionar puede ayudar a la comunidad de
|
||||
desarrollo a ofrecer comentarios útiles sobre el proyecto.
|
||||
|
||||
Una cosa desalentadora que puede suceder en esta etapa no es una reacción
|
||||
hostil, sino, en cambio, poca o ninguna reacción en absoluto. La triste
|
||||
realidad es que (1) los desarrolladores del kernel tienden a estar
|
||||
ocupados, (2) no hay escasez de personas con grandes planes y poco código
|
||||
(o incluso perspectivas de código) para respaldarlos, y (3) nadie está
|
||||
obligado a revisar o comentar las ideas publicadas por otros. Además, los
|
||||
diseños de alto nivel a menudo esconden problemas que solo se revelan
|
||||
cuando alguien realmente intenta implementar esos diseños; por esa razón,
|
||||
los desarrolladores del kernel prefieren ver el código.
|
||||
|
||||
Si una publicación de solicitud de comentarios genera pocos comentarios, no
|
||||
asuma que significa que no hay interés en el proyecto. Desafortunadamente,
|
||||
tampoco puedes asumir que no hay problemas con tu idea. Lo mejor que puede
|
||||
hacer en esta situación es seguir adelante, manteniendo informada a
|
||||
comunidad a medida que avanza.
|
||||
|
||||
Obtener respaldo oficial
|
||||
------------------------
|
||||
|
||||
Si su trabajo se está realizando en un entorno corporativo — como ocurre
|
||||
con la mayoría del trabajo en el kernel de Linux — es obvio que debe tener
|
||||
permiso de los jefes debidamente autorizados antes de poder publicar los
|
||||
planes o el código de su empresa en una lista de correo pública. La
|
||||
publicación de código que no ha sido autorizado para su liberación bajo una
|
||||
licencia compatible con la GPL puede ser especialmente problemática; cuanto
|
||||
antes la gerencia y el personal legal de una empresa lleguen a un acuerdo
|
||||
sobre la publicación de un proyecto de desarrollo del kernel, mejor será
|
||||
para todos los involucrados.
|
||||
|
||||
Algunos lectores pueden estar pensando en este momento que su trabajo en el
|
||||
kernel está destinado a respaldar un producto que aún no ha sido reconocido
|
||||
oficialmente. Revelar los planes de su empleador en una lista de correo
|
||||
pública puede no ser una opción viable. En casos como este, vale la pena
|
||||
considerar si realmente es necesario mantener el secreto; a menudo no hay
|
||||
una necesidad real de mantener los planes de desarrollo en secreto.
|
||||
|
||||
Dicho esto, también hay casos en los que una empresa legítimamente no puede
|
||||
revelar sus planes al inicio del proceso de desarrollo. Las empresas con
|
||||
desarrolladores experimentados en el kernel pueden optar por proceder de
|
||||
manera abierta, bajo el supuesto de que podrán evitar problemas graves de
|
||||
integración más adelante. Para las empresas sin ese tipo de experiencia
|
||||
interna, la mejor opción suele ser contratar a un desarrollador externo
|
||||
para que revise los planes bajo un acuerdo de confidencialidad (NDA). La
|
||||
Linux Foundation opera un programa de NDA diseñado para ayudar en este tipo
|
||||
de situaciones; se puede encontrar más información en:
|
||||
|
||||
https://www.linuxfoundation.org/nda/
|
||||
|
||||
Este tipo de revisión suele ser suficiente para evitar problemas graves más
|
||||
adelante sin necesidad de revelar públicamente el proyecto.
|
||||
|
@ -1,11 +1,470 @@
|
||||
.. include:: ../disclaimer-sp.rst
|
||||
|
||||
:Original: Documentation/process/4.Coding.rst
|
||||
:Translator: Carlos Bilbao <carlos.bilbao.osdev@gmail.com> and Avadhut Naik <avadhut.naik@amd.com>
|
||||
|
||||
.. _sp_development_coding:
|
||||
|
||||
Conseguir el código correcto
|
||||
============================
|
||||
|
||||
.. warning::
|
||||
TODO aún no traducido
|
||||
Si bien hay mucho que decir a favor de un proceso de diseño sólido y
|
||||
orientado a la comunidad, la prueba de cualquier proyecto de desarrollo del
|
||||
kernel está en el código resultante. Es el código lo que será examinado por
|
||||
otros desarrolladores y lo que será incluido (o no) en el árbol principal.
|
||||
Por lo tanto, es la calidad de este código lo que determinará el éxito
|
||||
final del proyecto.
|
||||
|
||||
Esta sección examinará el proceso de programación. Comenzaremos observando
|
||||
algunas de las maneras en que los desarrolladores del kernel pueden cometer
|
||||
errores. Luego, el enfoque se dirigirá hacia hacer las cosas bien y las
|
||||
herramientas que pueden ayudar en dicha búsqueda.
|
||||
|
||||
Problemas
|
||||
---------
|
||||
|
||||
Estilo de programación
|
||||
**********************
|
||||
|
||||
El kernel ha tenido durante mucho tiempo un estilo de programación
|
||||
estándar, descrito en la documentación del kernel en
|
||||
`Documentation/process/coding-style.rst`. Durante gran parte de ese tiempo,
|
||||
las políticas descritas en ese archivo se tomaban como, en el mejor de los
|
||||
casos, orientativas. Como resultado, hay una cantidad considerable de
|
||||
código en el kernel que no cumple con las pautas de estilo de programación.
|
||||
La presencia de ese código lleva a dos peligros independientes para los
|
||||
desarrolladores del kernel.
|
||||
|
||||
El primero de estos es creer que los estándares de programación del kernel
|
||||
no importan y no se aplican. La realidad es que agregar nuevo código al
|
||||
kernel es muy difícil si ese código no está escrito de acuerdo con el
|
||||
estándar; muchos desarrolladores solicitarán que el código sea reformateado
|
||||
antes de revisarlo. Una base de código tan grande como el kernel requiere
|
||||
cierta uniformidad para que los desarrolladores puedan comprender
|
||||
rápidamente cualquier parte de él. Así que ya no hay lugar para el código
|
||||
con formato extraño.
|
||||
|
||||
Ocasionalmente, el estilo de programación del kernel entrará en conflicto
|
||||
con el estilo obligatorio de un empleador. En tales casos, el estilo del
|
||||
kernel tendrá que prevalecer antes de que el código pueda ser fusionado.
|
||||
Incluir código en el kernel significa renunciar a cierto grado de control
|
||||
de varias maneras, incluida la forma en que se formatea el código.
|
||||
|
||||
La otra trampa es asumir que el código que ya está en el kernel necesita
|
||||
urgentemente correcciones de estilo de programación. Los desarrolladores
|
||||
pueden comenzar a generar parches de reformateo como una forma de
|
||||
familiarizarse con el proceso o como una forma de incluir su nombre en los
|
||||
registros de cambios del kernel, o ambos. Pero las correcciones puramente
|
||||
de estilo de programación son vistas como ruido por la comunidad de
|
||||
desarrollo; tienden a recibir una recepción adversa. Por lo tanto, este
|
||||
tipo de parche es mejor evitarlo. Es natural corregir el estilo de una
|
||||
parte del código mientras se trabaja en él por otras razones, pero los
|
||||
cambios de estilo de programación no deben hacerse por sí mismos.
|
||||
|
||||
El documento de estilo de programación tampoco debe leerse como una ley
|
||||
absoluta que nunca puede transgredirse. Si hay una buena razón para ir en
|
||||
contra del estilo (una línea que se vuelve mucho menos legible si se divide
|
||||
para ajustarse al límite de 80 columnas, por ejemplo), perfecto.
|
||||
|
||||
Tenga en cuenta que también puedes usar la herramienta `clang-format` para
|
||||
ayudarle con estas reglas, para reformatear rápidamente partes de su código
|
||||
automáticamente y para revisar archivos completos a fin de detectar errores
|
||||
de estilo de programación, errores tipográficos y posibles mejoras. También
|
||||
es útil para ordenar `#includes`, alinear variables/macros, reformatear
|
||||
texto y otras tareas similares. Consulte el archivo
|
||||
`Documentation/dev-tools/clang-format.rst` para más detalles.
|
||||
|
||||
Algunas configuraciones básicas del editor, como la indentación y los
|
||||
finales de línea, se configurarán automáticamente si utilizas un editor
|
||||
compatible con EditorConfig. Consulte el sitio web oficial de EditorConfig
|
||||
para obtener más información: https://editorconfig.org/
|
||||
|
||||
Capas de abstracción
|
||||
********************
|
||||
|
||||
Los profesores de ciencias de la computación enseñan a los estudiantes a
|
||||
hacer un uso extensivo de capas de abstracción en nombre de la
|
||||
flexibilidad y el ocultamiento de la información. Sin duda, el kernel hace
|
||||
un uso extensivo de la abstracción; ningún proyecto que involucre varios
|
||||
millones de líneas de código podría sobrevivir de otra manera. Pero la
|
||||
experiencia ha demostrado que una abstracción excesiva o prematura puede
|
||||
ser tan perjudicial como la optimización prematura. La abstracción debe
|
||||
usarse en la medida necesaria y ya.
|
||||
|
||||
A un nivel simple, considere una función que tiene un argumento que siempre
|
||||
se pasa como cero por todos los que la invocan. Uno podría mantener ese
|
||||
argumento por si alguien eventualmente necesita usar la flexibilidad
|
||||
adicional que proporciona. Sin embargo, para entonces, es probable que el
|
||||
código que implementa este argumento adicional se haya roto de alguna
|
||||
manera sutil que nunca se notó, porque nunca se ha utilizado. O, cuando
|
||||
surge la necesidad de flexibilidad adicional, no lo hace de una manera que
|
||||
coincida con la expectativa temprana del programador. Los desarrolladores
|
||||
del kernel rutinariamente enviarán parches para eliminar argumentos no
|
||||
utilizados; en general, no deberían añadirse en primer lugar.
|
||||
|
||||
Las capas de abstracción que ocultan el acceso al hardware, a menudo para
|
||||
permitir que la mayor parte de un controlador se utilice con varios
|
||||
sistemas operativos, son especialmente mal vistas. Dichas capas oscurecen
|
||||
el código y pueden imponer una penalización en el rendimiento; no
|
||||
pertenecen al kernel de Linux.
|
||||
|
||||
Por otro lado, si se encuentra copiando cantidades significativas de código
|
||||
de otro subsistema del kernel, es hora de preguntar si, de hecho, tendría
|
||||
sentido extraer parte de ese código en una biblioteca separada o
|
||||
implementar esa funcionalidad a un nivel superior. No tiene sentido
|
||||
replicar el mismo código en todo el kernel.
|
||||
|
||||
Uso de #ifdef y del preprocesador en general
|
||||
********************************************
|
||||
|
||||
El preprocesador de C tiene una tentación poderosa para algunos
|
||||
programadores de C, quienes lo ven como una forma de programar
|
||||
eficientemente una gran cantidad de flexibilidad en un archivo fuente. Pero
|
||||
el preprocesador no es C, y el uso intensivo de él da como resultado un
|
||||
código mucho más difícil de leer para otros y más difícil de verificar por
|
||||
el compilador para su corrección. El uso intensivo del preprocesador es
|
||||
asi siempre un signo de un código que necesita algo de limpieza.
|
||||
|
||||
La compilación condicional con `#ifdef` es, de hecho, una característica
|
||||
poderosa, y se usa dentro del kernel. Pero hay poco deseo de ver código que
|
||||
sté salpicado liberalmente con bloques `#ifdef`. Como regla general, el uso
|
||||
de `#ifdef` debe limitarse a los archivos de encabezado siempre que sea
|
||||
posible. El código condicionalmente compilado puede confinarse a funciones
|
||||
que, si el código no va a estar presente, simplemente se convierten en
|
||||
vacías. El compilador luego optimizará silenciosamente la llamada a la
|
||||
función vacía. El resultado es un código mucho más limpio y fácil de
|
||||
seguir.
|
||||
|
||||
Las macros del preprocesador de C presentan varios peligros, incluida la
|
||||
posible evaluación múltiple de expresiones con efectos secundarios y la
|
||||
falta de seguridad de tipos. Si te sientes tentado a definir una macro,
|
||||
considera crear una función en línea en su lugar. El código resultante será
|
||||
el mismo, pero las funciones en línea son más fáciles de leer, no evalúan
|
||||
sus argumentos varias veces y permiten que el compilador realice
|
||||
comprobaciones de tipo en los argumentos y el valor de retorno.
|
||||
|
||||
Funciones en línea
|
||||
******************
|
||||
|
||||
Las funciones en línea presentan su propio peligro, sin embargo. Los
|
||||
programadores pueden enamorarse de la eficiencia percibida al evitar una
|
||||
llamada a función y llenar un archivo fuente con funciones en línea. Esas
|
||||
funciones, sin embargo, pueden en realidad reducir el rendimiento. Dado que
|
||||
su código se replica en cada sitio de llamada, terminan hinchando el tamaño
|
||||
del kernel compilado. Eso, a su vez, crea presión en las cachés de memoria
|
||||
del procesador, lo que puede ralentizar la ejecución de manera drástica
|
||||
Las funciones en línea, como regla, deben ser bastante pequeñas y
|
||||
relativamente raras. El costo de una llamada a función, después de todo, no
|
||||
es tan alto; la creación de un gran número de funciones en línea es un
|
||||
ejemplo clásico de optimización prematura.
|
||||
|
||||
En general, los programadores del kernel ignoran los efectos de caché bajo
|
||||
su propio riesgo. El clásico intercambio de tiempo/espacio que se enseña en
|
||||
las clases de estructuras de datos iniciales a menudo no se aplica al
|
||||
hardware contemporáneo. El espacio *es* tiempo, en el sentido de que un
|
||||
programa más grande se ejecutará más lentamente que uno más compacto.
|
||||
|
||||
Los compiladores más recientes toman un papel cada vez más activo al
|
||||
decidir si una función dada debe realmente ser en línea o no. Por lo tanto,
|
||||
la colocación liberal de palabras clave "inline" puede no solo ser
|
||||
excesiva; también podría ser irrelevante.
|
||||
|
||||
Bloqueo
|
||||
*******
|
||||
|
||||
En mayo de 2006, la pila de red "Devicescape" fue, con gran fanfarria,
|
||||
lanzada bajo la licencia GPL y puesta a disposición para su inclusión en el
|
||||
kernel principal. Esta donación fue una noticia bienvenida; el soporte para
|
||||
redes inalámbricas en Linux se consideraba, en el mejor de los casos,
|
||||
deficiente, y la pila de Devicescape ofrecía la promesa de solucionar esa
|
||||
situación. Sin embargo, este código no fue incluido en el kernel principal
|
||||
hasta junio de 2007 (versión 2.6.22). ¿Qué sucedió?
|
||||
|
||||
Este código mostró varios signos de haber sido desarrollado a puertas
|
||||
cerradas en una empresa. Pero un problema importante en particular fue que
|
||||
no estaba diseñado para funcionar en sistemas multiprocesador. Antes de que
|
||||
esta pila de red (ahora llamada mac80211) pudiera fusionarse, se tuvo que
|
||||
implementar un esquema de bloqueo en ella.
|
||||
|
||||
Hubo un tiempo en que se podía desarrollar código para el kernel de Linux
|
||||
sin pensar en los problemas de concurrencia que presentan los sistemas
|
||||
multiprocesador. Ahora, sin embargo, este documento se está escribiendo en
|
||||
una computadora portátil con dos núcleos. Incluso en sistemas de un solo
|
||||
procesador, el trabajo que se está realizando para mejorar la capacidad de
|
||||
respuesta aumentará el nivel de concurrencia dentro del kernel. Los días en
|
||||
que se podía escribir código para el kernel sin pensar en el bloqueo han
|
||||
quedado atrás.
|
||||
|
||||
Cualquier recurso (estructuras de datos, registros de hardware, etc.) que
|
||||
pueda ser accedido concurrentemente por más de un hilo debe estar protegido
|
||||
por un bloqueo. El nuevo código debe escribirse teniendo en cuenta este
|
||||
requisito; implementar el bloqueo después de que el código ya ha sido
|
||||
desarrollado es una tarea mucho más difícil. Los desarrolladores del kernel
|
||||
deben tomarse el tiempo para comprender bien los primitivos de bloqueo
|
||||
disponibles para elegir la herramienta adecuada para el trabajo. El código
|
||||
que muestre una falta de atención a la concurrencia tendrá un camino
|
||||
difícil para ser incluido en el kernel principal.
|
||||
|
||||
Regresiones
|
||||
***********
|
||||
|
||||
Un último peligro que vale la pena mencionar es el siguiente: puede ser
|
||||
tentador realizar un cambio (que puede traer grandes mejoras) que cause un
|
||||
problema para los usuarios existentes. Este tipo de cambio se llama una
|
||||
"regresión", y las regresiones se han vuelto muy mal recibidas en el kernel
|
||||
principal. Con pocas excepciones, los cambios que causan regresiones serán
|
||||
revertidos si la regresión no se puede solucionar de manera oportuna. Es
|
||||
mucho mejor evitar la regresión desde el principio.
|
||||
|
||||
A menudo se argumenta que una regresión puede justificarse si hace que las
|
||||
cosas funcionen para más personas de las que crea problemas. ¿Por qué no
|
||||
hacer un cambio si trae nueva funcionalidad a diez sistemas por cada uno
|
||||
que rompe? La mejor respuesta a esta pregunta fue expresada por Linus en
|
||||
julio de 2007 (traducido):
|
||||
|
||||
::
|
||||
|
||||
Entonces, no arreglamos errores introduciendo nuevos problemas. Eso
|
||||
lleva a la locura, y nadie sabe si realmente se avanza. ¿Es dos pasos
|
||||
adelante, uno atrás, o un paso adelante y dos atrás?
|
||||
|
||||
(https://lwn.net/Articles/243460/).
|
||||
|
||||
Un tipo de regresión especialmente mal recibido es cualquier tipo de cambio
|
||||
en la ABI del espacio de usuario. Una vez que se ha exportado una interfaz
|
||||
al espacio de usuario, debe ser soportada indefinidamente. Este hecho hace
|
||||
que la creación de interfaces para el espacio de usuario sea
|
||||
particularmente desafiante: dado que no pueden cambiarse de manera
|
||||
incompatible, deben hacerse bien desde el principio. Por esta razón,
|
||||
siempre se requiere una gran cantidad de reflexión, documentación clara y
|
||||
una amplia revisión para las interfaces del espacio de usuario.
|
||||
|
||||
Herramientas de verificación de código
|
||||
**************************************
|
||||
|
||||
Por ahora, al menos, escribir código libre de errores sigue siendo un ideal
|
||||
que pocos de nosotros podemos alcanzar. Sin embargo, lo que podemos esperar
|
||||
hacer es detectar y corregir tantos de esos errores como sea posible antes
|
||||
de que nuestro código se integre en el kernel principal. Con ese fin, los
|
||||
desarrolladores del kernel han reunido una impresionante variedad de
|
||||
herramientas que pueden detectar una amplia variedad de problemas oscuros
|
||||
de manera automatizada. Cualquier problema detectado por el ordenador es
|
||||
un problema que no afectará a un usuario más adelante, por lo que es lógico
|
||||
que las herramientas automatizadas se utilicen siempre que sea posible.
|
||||
|
||||
El primer paso es simplemente prestar atención a las advertencias
|
||||
producidas por el compilador. Las versiones contemporáneas de gcc pueden
|
||||
detectar (y advertir sobre) una gran cantidad de errores potenciales. Con
|
||||
bastante frecuencia, estas advertencias apuntan a problemas reales. El
|
||||
código enviado para revisión no debería, por regla general, producir
|
||||
ninguna advertencia del compilador. Al silenciar las advertencias, tenga
|
||||
cuidado de comprender la causa real e intente evitar "correcciones" que
|
||||
hagan desaparecer la advertencia sin abordar su causa.
|
||||
|
||||
Tenga en cuenta que no todas las advertencias del compilador están
|
||||
habilitadas de forma predeterminada. Compile el kernel con
|
||||
"make KCFLAGS=-W" para obtener el conjunto completo.
|
||||
|
||||
El kernel proporciona varias opciones de configuración que activan
|
||||
funciones de depuración; la mayoría de estas se encuentran en el submenú
|
||||
"kernel hacking". Varias de estas opciones deben estar activadas para
|
||||
cualquier kernel utilizado para desarrollo o pruebas. En particular,
|
||||
debería activar:
|
||||
|
||||
- FRAME_WARN para obtener advertencias sobre marcos de pila más grandes
|
||||
que una cantidad determinada. La salida generada puede ser extensa, pero
|
||||
no es necesario preocuparse por las advertencias de otras partes del
|
||||
kernel.
|
||||
|
||||
- DEBUG_OBJECTS agregará código para rastrear la vida útil de varios
|
||||
objetos creados por el kernel y advertir cuando se realicen cosas fuera
|
||||
de orden. Si está agregando un subsistema que crea (y exporta) objetos
|
||||
complejos propios, considere agregar soporte para la infraestructura de
|
||||
depuración de objetos.
|
||||
|
||||
- DEBUG_SLAB puede encontrar una variedad de errores en la asignación y
|
||||
uso de memoria; debe usarse en la mayoría de los kernels de desarrollo.
|
||||
|
||||
- DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP y DEBUG_MUTEXES encontrarán una serie
|
||||
de errores comunes de bloqueo.
|
||||
|
||||
Hay bastantes otras opciones de depuración, algunas de las cuales se
|
||||
discutirán más adelante. Algunas de ellas tienen un impacto significativo
|
||||
en el rendimiento y no deben usarse todo el tiempo. Pero dedicar tiempo a
|
||||
aprender las opciones disponibles probablemente será recompensado muchas
|
||||
veces en poco tiempo.
|
||||
|
||||
Una de las herramientas de depuración más pesadas es el verificador de
|
||||
bloqueos, o "lockdep". Esta herramienta rastreará la adquisición y
|
||||
liberación de cada bloqueo (spinlock o mutex) en el sistema, el orden en
|
||||
que se adquieren los bloqueos en relación entre sí, el entorno actual de
|
||||
interrupción, y más. Luego, puede asegurarse de que los bloqueos siempre se
|
||||
adquieran en el mismo orden, que las mismas suposiciones de interrupción se
|
||||
apliquen en todas las situaciones, y así sucesivamente. En otras palabras,
|
||||
lockdep puede encontrar varios escenarios en los que el sistema podría, en
|
||||
raras ocasiones, bloquearse. Este tipo de problema puede ser doloroso
|
||||
(tanto para desarrolladores como para usuarios) en un sistema desplegado;
|
||||
lockdep permite encontrarlos de manera automatizada con anticipación. El
|
||||
código con cualquier tipo de bloqueo no trivial debe ejecutarse con lockdep
|
||||
habilitado antes de ser enviado para su inclusión.
|
||||
|
||||
Como programador diligente del kernel, sin duda alguna, verificará el
|
||||
estado de retorno de cualquier operación (como una asignación de memoria)
|
||||
que pueda fallar. Sin embargo, el hecho es que las rutas de recuperación de
|
||||
fallos resultantes probablemente no hayan sido probadas en absoluto. El
|
||||
código no probado tiende a ser código roto; podría tener mucha más
|
||||
confianza en su código si todas esas rutas de manejo de errores se hubieran
|
||||
ejercitado algunas veces.
|
||||
|
||||
El kernel proporciona un marco de inyección de fallos que puede hacer
|
||||
precisamente eso, especialmente donde están involucradas las asignaciones
|
||||
de memoria. Con la inyección de fallos habilitada, un porcentaje
|
||||
configurable de las asignaciones de memoria fallarán; estas fallas pueden
|
||||
restringirse a un rango específico de código. Ejecutar con la inyección de
|
||||
fallos habilitada permite al programador ver cómo responde el código cuando
|
||||
las cosas van mal. Consulte
|
||||
Documentation/fault-injection/fault-injection.rst para obtener más
|
||||
información sobre cómo utilizar esta funcionalidad.
|
||||
|
||||
Otros tipos de errores se pueden encontrar con la herramienta de análisis
|
||||
estático "sparse". Con sparse, el programador puede recibir advertencias
|
||||
sobre confusiones entre direcciones del espacio de usuario y del kernel,
|
||||
mezcla de cantidades big-endian y little-endian, el paso de valores enteros
|
||||
donde se espera un conjunto de banderas de bits, y así sucesivamente.
|
||||
Sparse debe instalarse por separado (puede encontrarse en
|
||||
https://sparse.wiki.kernel.org/index.php/Main_Page si su distribución no lo
|
||||
empaqueta); luego, puede ejecutarse en el código agregando "C=1" a su
|
||||
comando make.
|
||||
|
||||
La herramienta "Coccinelle" (http://coccinelle.lip6.fr/) puede encontrar
|
||||
una amplia variedad de posibles problemas de codificación; también puede
|
||||
proponer correcciones para esos problemas. Bastantes "parches semánticos"
|
||||
para el kernel se han empaquetado en el directorio scripts/coccinelle;
|
||||
ejecutar "make coccicheck" ejecutará esos parches semánticos e informará
|
||||
sobre cualquier problema encontrado. Consulte:
|
||||
ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>` para
|
||||
obtener más información.
|
||||
|
||||
Otros tipos de errores de portabilidad se encuentran mejor compilando su
|
||||
código para otras arquitecturas. Si no tiene un sistema S/390 o una placa
|
||||
de desarrollo Blackfin a mano, aún puede realizar el paso de compilación.
|
||||
Un gran conjunto de compiladores cruzados para sistemas x86 se puede
|
||||
encontrar en
|
||||
|
||||
https://www.kernel.org/pub/tools/crosstool/
|
||||
|
||||
Muchos sistemas de compilación disponibles comercialmente también se pueden
|
||||
utilizar para compilar código de kernel para una amplia gama de
|
||||
arquitecturas.
|
||||
|
||||
Los desarrolladores del kernel son afortunados: tienen acceso a una
|
||||
variedad de herramientas de verificación de código de la que los
|
||||
desarrolladores de la mayoría de los otros sistemas pueden estar celosos.
|
||||
Pero todas esas herramientas no servirán de nada si no las usa. El
|
||||
resultado final de ignorar estas herramientas es simple: alguien más puede
|
||||
notificarle de un problema en su código a través de un "oportuno"
|
||||
comentario en la lista de correo o, peor aún, el código problemático podría
|
||||
ser eliminado. Es mucho más fácil usar estas herramientas en primer lugar.
|
||||
|
||||
Documentación
|
||||
*************
|
||||
|
||||
La documentación a menudo ha sido más la excepción que la regla en el
|
||||
desarrollo del kernel. Aun así, una documentación adecuada ayudará a
|
||||
facilitar la integración de nuevo código en el kernel, hará la vida más
|
||||
fácil a otros desarrolladores, y será útil para sus usuarios. En muchos
|
||||
casos, la inclusión de documentación se ha vuelto esencialmente
|
||||
obligatoria.
|
||||
|
||||
La primera pieza de documentación para cualquier parche es su changelog
|
||||
asociado. Las entradas de registro deben describir el problema que se está
|
||||
esolviendo, la forma de la solución, las personas que trabajaron en el
|
||||
parche, cualquier efecto relevante en el rendimiento, y cualquier otra cosa
|
||||
que pueda ser necesaria para entender el parche. Asegúrese de que el
|
||||
changelog diga *por qué* el parche vale la pena ser aplicado; un
|
||||
sorprendente número de desarrolladores no proporciona esa información.
|
||||
|
||||
Cualquier código que agregue una nueva interfaz para el espacio de usuario,
|
||||
incluidos los nuevos archivos de sysfs o /proc, debe incluir documentación
|
||||
de esa interfaz que permita a los desarrolladores del espacio de usuario
|
||||
saber con qué están trabajando. Consulte `Documentation/ABI/README` para
|
||||
una descripción de cómo debe formatearse esta documentación y qué
|
||||
información debe proporcionarse.
|
||||
|
||||
El archivo
|
||||
:ref:`Documentation/admin-guide/kernel-parameters.rst <kernelparameters>`
|
||||
describe todos los parámetros de arranque del kernel. Cualquier parche que
|
||||
agregue nuevos parámetros debe agregar las entradas correspondientes a este
|
||||
archivo.
|
||||
|
||||
Cualquier nueva opción de configuración debe ir acompañada de un texto de
|
||||
ayuda que explique claramente las opciones y cuándo el usuario podría
|
||||
querer seleccionarlas.
|
||||
|
||||
La información de la API interna para muchos subsistemas está documentada
|
||||
mediante comentarios especialmente formateados; estos comentarios pueden
|
||||
extraerse y formatearse de diversas maneras mediante el script
|
||||
"kernel-doc". Si está trabajando dentro de un subsistema que tiene
|
||||
comentarios de kerneldoc, debe mantenerlos y agregarlos según corresponda
|
||||
para las funciones disponibles externamente. Incluso en áreas que no han
|
||||
sido tan documentadas, no hay ningún inconveniente en agregar comentarios
|
||||
de kerneldoc para el futuro; de hecho, esta puede ser una actividad útil
|
||||
para desarrolladores de kernel principiantes. El formato de estos
|
||||
comentarios, junto con alguna información sobre cómo crear plantillas de
|
||||
kerneldoc, se puede encontrar en
|
||||
:ref:`Documentation/doc-guide/ <doc_guide>`.
|
||||
|
||||
Cualquiera que lea una cantidad significativa de código existente del
|
||||
kernel notará que, a menudo, los comentarios son notables por su ausencia.
|
||||
Una vez más, las expectativas para el nuevo código son más altas que en el
|
||||
pasado; integrar código sin comentarios será más difícil. Dicho esto, hay
|
||||
poco deseo de tener código excesivamente comentado. El código en sí debe
|
||||
ser legible, con comentarios que expliquen los aspectos más sutiles.
|
||||
|
||||
Ciertas cosas siempre deben comentarse. El uso de barreras de memoria debe
|
||||
ir acompañado de una línea que explique por qué la barrera es necesaria.
|
||||
Las reglas de bloqueo para las estructuras de datos generalmente necesitan
|
||||
explicarse en algún lugar. Las estructuras de datos importantes en general
|
||||
necesitan documentación completa. Las dependencias no obvias entre
|
||||
fragmentos de código separados deben señalarse. Cualquier cosa que pueda
|
||||
tentar a un maintainer de código a hacer una "limpieza" incorrecta necesita
|
||||
un comentario que explique por qué se hace de esa manera. Y así
|
||||
sucesivamente.
|
||||
|
||||
Cambios en la API interna
|
||||
*************************
|
||||
|
||||
La interfaz binaria proporcionada por el kernel al espacio de usuario no se
|
||||
puede romper, excepto en las circunstancias más graves. Las interfaces de
|
||||
programación internas del kernel, en cambio, son altamente fluidas y pueden
|
||||
cambiarse cuando surge la necesidad. Si usted se encuentra teniendo que
|
||||
hacer un rodeo alrededor de una API del kernel, o simplemente no utilizando
|
||||
una funcionalidad específica porque no cumple con sus necesidades, eso
|
||||
puede ser una señal de que la API necesita cambiar. Como desarrollador del
|
||||
kernel, usted está autorizado a hacer esos cambios.
|
||||
|
||||
Hay, por supuesto, algunas condiciones. Los cambios en la API se pueden
|
||||
hacer, pero necesitan estar bien justificados. Entonces, cualquier parche
|
||||
que realice un cambio en la API interna debe ir acompañado de una
|
||||
descripción de cuál es el cambio y por qué es necesario. Este tipo de
|
||||
cambio también debe desglosarse en un parche separado, en lugar de estar
|
||||
enterrado dentro de un parche más grande.
|
||||
|
||||
La otra condición es que un desarrollador que cambia una API interna
|
||||
generalmente está encargado de la tarea de corregir cualquier código dentro
|
||||
del árbol del kernel que se vea afectado por el cambio. Para una función
|
||||
ampliamente utilizada, este deber puede llevar a literalmente cientos o
|
||||
miles de cambios, muchos de los cuales probablemente entren en conflicto
|
||||
con el trabajo que otros desarrolladores están realizando. No hace falta
|
||||
decir que esto puede ser un trabajo grande, por lo que es mejor asegurarse
|
||||
de que la justificación sea sólida. Tenga en cuenta que la herramienta
|
||||
Coccinelle puede ayudar con los cambios de API a gran escala.
|
||||
|
||||
Cuando se realice un cambio incompatible en la API, siempre que sea
|
||||
posible, se debe asegurar que el código que no ha sido actualizado sea
|
||||
detectado por el compilador. Esto le ayudará a estar seguro de que ha
|
||||
encontrado todos los usos en el árbol de esa interfaz. También alertará a
|
||||
los desarrolladores de código fuera del árbol de que hay un cambio al que
|
||||
necesitan responder. Apoyar el código fuera del árbol no es algo de lo que
|
||||
los desarrolladores del kernel deban preocuparse, pero tampoco tenemos que
|
||||
dificultarles la vida más de lo necesario.
|
||||
|
@ -1,11 +1,391 @@
|
||||
.. include:: ../disclaimer-sp.rst
|
||||
|
||||
:Original: Documentation/process/5.Posting.rst
|
||||
:Translator: Carlos Bilbao <carlos.bilbao.osdev@gmail.com> and Avadhut Naik <avadhut.naik@amd.com>
|
||||
|
||||
.. _sp_development_posting:
|
||||
|
||||
Publicar parches
|
||||
================
|
||||
Publicación de parches
|
||||
======================
|
||||
|
||||
.. warning::
|
||||
TODO aún no traducido
|
||||
Tarde o temprano, llega el momento en que su trabajo esté listo para ser
|
||||
presentado a la comunidad para su revisión y, eventualmente, su inclusión
|
||||
en el kernel mainline. Como era de esperar, la comunidad de desarrollo del
|
||||
kernel ha desarrollado un conjunto de convenciones y procedimientos que se
|
||||
utilizan en la publicación de parches; seguirlos hará la vida mucho más
|
||||
fácil para todos los involucrados. Este documento intentará cubrir estas
|
||||
expectativas con un detalle razonable; también se puede encontrar más
|
||||
información en los archivos.
|
||||
:ref:`Documentation/translations/sp_SP/process/submitting-patches.rst <sp_submittingpatches>`
|
||||
and :ref:`Documentation/translations/sp_SP/process/submit-checklist.rst <sp_submitchecklist>`
|
||||
|
||||
Cuando publicar
|
||||
---------------
|
||||
|
||||
Hay una tentación constante de evitar publicar parches antes de que
|
||||
estén completamente “listos”. Para parches simples, eso no es un
|
||||
problema. Sin embargo, si el trabajo que se está realizando es complejo,
|
||||
hay mucho que ganar al obtener comentarios de la comunidad antes de que
|
||||
se complete el trabajo. Por lo tanto, se debería considerar publicar
|
||||
trabajo en progreso, o incluso poner a disposición un árbol de git para
|
||||
que los desarrolladores interesados puedan ponerse al día con su trabajo
|
||||
en cualquier momento.
|
||||
|
||||
Al publicar código que aún no se considera listo para su inclusión, es
|
||||
una buena idea decirlo en la propia publicación. Además, mencione
|
||||
cualquier trabajo importante que aún falte por hacer y cualquier problema
|
||||
conocido. Menos personas mirarán los parches que se sabe que están a
|
||||
medias, pero aquellos que lo hagan vendrán con la idea de que pueden
|
||||
ayudarlo a llevar el trabajo en la dirección correcta.
|
||||
|
||||
Antes de crear parches
|
||||
----------------------
|
||||
|
||||
Se deben hacer varias cosas antes de considerar enviar parches a la
|
||||
comunidad de desarrollo. Estas incluyen:
|
||||
|
||||
- Pruebe el código en la medida de lo posible. Utilice las herramientas
|
||||
de depuración del kernel, asegúrese de que el kernel se compilará con
|
||||
todas las combinaciones razonables de opciones de configuración, use
|
||||
compiladores cruzados para compilar para diferentes arquitecturas, etc.
|
||||
|
||||
- Asegúrese de que su código cumpla con las directrices de estilo de
|
||||
codificación del kernel.
|
||||
|
||||
- ¿Su cambio tiene implicaciones de rendimiento? Si es así, debe ejecutar
|
||||
puntos de referencia que muestren cuál es el impacto (o beneficio) de
|
||||
su cambio; se debe incluir un resumen de los resultados con el parche.
|
||||
|
||||
- Asegúrese de que tiene derecho a publicar el código. Si este trabajo
|
||||
se realizó para un empleador, es probable que el empleador tenga
|
||||
derecho al trabajo y debe estar de acuerdo con su lanzamiento bajo la
|
||||
GPL.
|
||||
|
||||
Como regla general, pensar un poco más antes de publicar el código casi
|
||||
siempre compensa el esfuerzo en poco tiempo.
|
||||
|
||||
Preparación del parche
|
||||
----------------------
|
||||
|
||||
La preparación de parches para su publicación puede ser una cantidad
|
||||
sorprendente de trabajo, pero, una vez más, intentar ahorrar tiempo aquí
|
||||
generalmente no es recomendable, ni siquiera a corto plazo.
|
||||
|
||||
Los parches deben prepararse contra una versión específica del kernel.
|
||||
Como regla general, un parche debe basarse en el mainline actual que se
|
||||
encuentra en el árbol git de Linus. Al basarse en el mainline, comience
|
||||
con un punto de lanzamiento bien conocido, una versión estable o -rc, en
|
||||
lugar de bifurcarse fuera del mainline en un punto arbitrario.
|
||||
|
||||
Puede ser necesario hacer revisiones contra -mm, linux-next o un árbol de
|
||||
subsistemas para facilitar pruebas y revisiones más amplias. Dependiendo
|
||||
del área de su parche y de lo que esté sucediendo en otros lugares, basar
|
||||
un parche en estos otros árboles puede requerir una cantidad significativa
|
||||
de trabajo para resolver conflictos y lidiar con los cambios de API.
|
||||
|
||||
Solo los cambios más simples deben formatearse como un solo parche; todo
|
||||
lo demás debe hacerse como una serie lógica de cambios. Dividir parches
|
||||
es un poco un arte; algunos desarrolladores pasan mucho tiempo averiguando
|
||||
cómo hacerlo de la manera que la comunidad espera. Sin embargo, hay
|
||||
algunas reglas generales que pueden ayudar considerablemente:
|
||||
|
||||
- La serie de parches que publique casi seguramente no será la serie de
|
||||
cambios que se encuentran en su sistema de control de revisiones. En su
|
||||
lugar, los cambios que ha realizado deben considerarse en su forma
|
||||
final y luego dividirse de manera que tengan sentido. A los
|
||||
desarrolladores les interesan los cambios discretos y autónomos, no el
|
||||
camino que tomó para llegar a esos cambios.
|
||||
|
||||
- Cada cambio lógicamente independiente debe formatearse como un parche
|
||||
separado. Estos cambios pueden ser pequeños (“agregar un campo a esta
|
||||
estructura”) o grandes (agregar un nuevo controlador significativo,
|
||||
por ejemplo), pero deben ser conceptualmente pequeños y susceptibles
|
||||
de una descripción de una línea. Cada parche debe hacer un cambio
|
||||
especifico que pueda ser revisado por sí mismo y verificado para hacer
|
||||
lo que dice que hace.
|
||||
|
||||
- Para reafirmar la pauta anterior: no mezcle diferentes tipos de cambios
|
||||
en el mismo parche. Si un solo parche corrige un error de seguridad
|
||||
crítico, reorganiza algunas estructuras y reformatea el código, es muy
|
||||
probable que se pase por alto y se pierda la solución importante.
|
||||
|
||||
- Cada parche debe producir un kernel que se compile y funcione
|
||||
correctamente; si su serie de parches se interrumpe en el medio, el
|
||||
resultado debería seguir siendo un kernel funcional. La aplicación
|
||||
parcial de una serie de parches es un escenario común cuando se
|
||||
utiliza la herramienta “git bisect” para encontrar regresiones; si
|
||||
el resultado es un kernel roto, hará la vida más difícil para los
|
||||
desarrolladores y usuarios que participan en el noble trabajo de
|
||||
rastrear problemas.
|
||||
|
||||
- Sin embargo, no lo exagere. Un desarrollador una vez publicó un conjunto
|
||||
de ediciones en un solo archivo como 500 parches separados – un acto
|
||||
que no lo convirtió en la persona más popular en la lista de correo del
|
||||
kernel. Un solo parche puede ser razonablemente grande si todavía
|
||||
contiene un solo cambio *lógico*.
|
||||
|
||||
- Puede ser tentador agregar una infraestructura completamente nueva con
|
||||
una serie de parches, pero dejar esa infraestructura sin usar hasta el
|
||||
parche final de la serie lo habilite todo. Esta tentación debe evitarse
|
||||
si es posible; si esa serie agrega regresiones, bisection señalará el
|
||||
ultimo parche como el que causó el problema, aunque el error real esté
|
||||
en otra parte. Siempre que sea posible, un parche que agregue código
|
||||
nuevo debe hacer que ese código se active de inmediato.
|
||||
|
||||
Trabajar para crear la serie de parches perfecta puede ser un proceso
|
||||
frustrante que lleva mucho tiempo y reflexión después de que el “trabajo
|
||||
real” se ha hecho. Sin embargo, cuando se hace correctamente, es un tiempo
|
||||
bien empleado.
|
||||
|
||||
Formato de parches y registros de cambios
|
||||
-----------------------------------------
|
||||
|
||||
Así que ahora tiene una serie perfecta de parches para publicar, pero el
|
||||
trabajo aún no se ha hecho. Cada parche necesita ser formateado en un
|
||||
mensaje que comunique rápida y claramente su propósito al resto del
|
||||
mundo. A tal fin, cada parche se compondrá de lo siguiente:
|
||||
|
||||
- Una línea opcional “From” que nombra al autor del parche. Esta línea
|
||||
solo es necesaria si pasa el parche de otra persona por correo
|
||||
electrónico, pero nunca está de más agregarla en caso de duda.
|
||||
|
||||
- Una descripción de una línea de lo que hace el parche. Este mensaje
|
||||
debería ser suficiente para que un lector que lo vea sin otro contexto
|
||||
pueda entender el alcance del parche; la línea aparecerá en los
|
||||
registros de cambios de “forma corta”. Este mensaje generalmente se
|
||||
formatea con el nombre del subsistema relevante primero, seguido del
|
||||
propósito del parche. Por ejemplo:
|
||||
|
||||
::
|
||||
|
||||
gpio: fix build on CONFIG_GPIO_SYSFS=n
|
||||
|
||||
- Una línea en blanco seguida de una descripción detallada del contenido
|
||||
del parche. Esta descripción puede ser tan larga como sea necesario;
|
||||
debería decir qué hace el parche y por qué debe aplicarse al kernel.
|
||||
|
||||
- Una o más líneas de etiquetas, con, como mínimo, una línea
|
||||
Signed-off-by: del autor del parche. Las etiquetas se describirán con
|
||||
más detalle a continuación.
|
||||
|
||||
Los elementos de arriba, juntos, forman el registro de cambios para el
|
||||
parche. Escribir buenos registros de cambios es un arte crucial, pero a
|
||||
menudo descuidado; vale la pena pasar otro momento discutiendo este tema.
|
||||
Al escribir un registro de cambios, debe recordar que muchas personas
|
||||
diferentes leerán sus palabras. Estos incluyen a los maintainers y
|
||||
revisores de subsistemas que necesitan decidir si el parche debe
|
||||
incluirse, a los distribuidores y otros maintainers que intentan
|
||||
determinar si un parche debe ser “backported” a otros kernels, a los
|
||||
cazadores de errores que se preguntan si el parche es responsable de un
|
||||
problema que están persiguiendo, a los usuarios que quieren saber cómo
|
||||
ha cambiado el kernel, y más. Un buen registro de cambios transmite la
|
||||
información necesaria a todas estas personas de la forma más directa y
|
||||
concisa posible.
|
||||
|
||||
Con ese fin, la línea de resumen debe describir los efectos y la
|
||||
motivación del cambio, así como lo mejor posible dada la restricción de
|
||||
una línea. La descripción detallada puede ampliar esos temas y
|
||||
proporcionar cualquier información adicional necesaria. Si el parche
|
||||
corrige un error, cita el commit que introdujo el error si es posible (y
|
||||
por favor, proporcione tanto el ID del commit como el título al citar
|
||||
commits). Si un problema está asociado con un registro específico o la
|
||||
salida del compilador, incluya esa salida para ayudar a otros usuarios a
|
||||
buscar una solución al mismo problema. Si el cambio está destinado a
|
||||
apoyar otros cambios que llegarán en un parche posterior, dígalo. Si se
|
||||
cambian las API internas, detalle esos cambios y cómo deben responder
|
||||
otros desarrolladores. En general, cuanto más pueda ponerse en los zapatos
|
||||
de todos los que leerán su registro de cambios, mejor será ese registro de
|
||||
cambios (y el kernel en su conjunto).
|
||||
|
||||
No hace falta decir que el registro de cambios debe ser el texto utilizado
|
||||
al realizar el commit en un sistema de control de revisiones. Será seguido
|
||||
por:
|
||||
|
||||
- El parche, en el formato unificado de parche (“-u”). Usar la opción
|
||||
“-p” en diff asociará los nombres de las funciones con los cambios, lo
|
||||
que hará que el parche resultante sea más fácil de leer para otros.
|
||||
|
||||
Debe evitar incluir cambios en archivos irrelevantes (los generados por
|
||||
el proceso de compilación, por ejemplo, o los archivos de respaldo del
|
||||
editor) en el parche. El archivo “dontdiff” en el directorio de
|
||||
Documentation puede ayudar en este sentido; páselo a diff con la
|
||||
opción “-X”.
|
||||
|
||||
Las etiquetas ya mencionadas brevemente anteriormente proporcionan
|
||||
información sobre cómo surgió el parche. Se describen en detalle en el
|
||||
documento
|
||||
:ref:`Documentation/translations/sp_SP/process/submitting-patches.rst <sp_submittingpatches>`;
|
||||
lo que sigue aquí es un breve resumen.
|
||||
|
||||
Una etiqueta se usa para referirse a commits anteriores que introdujeron
|
||||
problemas corregidos por el parche::
|
||||
|
||||
Fixes: 1f2e3d4c5b6a ("La primera línea del commit especificada por los primeros 12 caracteres de su ID SHA-1.")
|
||||
|
||||
Otra etiqueta se utiliza para vincular páginas web con información
|
||||
adicional o detalles, por ejemplo, una discusión previa que condujo al
|
||||
parche o un documento con una especificación implementada por el parche::
|
||||
|
||||
Link: https://example.com/somewhere.html otras cosas opcionales
|
||||
|
||||
Muchos maintainers, al aplicar un parche, también agregan esta etiqueta
|
||||
para vincular a la última publicación de revisión pública del parche; a
|
||||
menudo, eso se hace automáticamente mediante herramientas como b4 o git
|
||||
hook como el que se describe en
|
||||
'Documentation/maintainer/configure-git.rst'.
|
||||
|
||||
Si la URL apunta a un informe de error público que está siendo corregido
|
||||
por el parche, use la etiqueta “Closes:” (Cierra) en su lugar::
|
||||
|
||||
Closes: https://example.com/issues/1234 otras cosas opcionales
|
||||
|
||||
Algunos rastreadores de errores tienen la capacidad de cerrar problemas
|
||||
automáticamente cuando se aplica un commit con tal etiqueta. Algunos bots
|
||||
que monitorean listas de correo también pueden rastrear dichas etiquetas
|
||||
y realizar ciertas acciones. Los rastreadores de errores privados y las
|
||||
URL no válidas están prohibidos.
|
||||
|
||||
Otro tipo de etiqueta se utiliza para documentar quién estuvo involucrado
|
||||
en el desarrollo del parche. Cada uno de estos utiliza este formato::
|
||||
|
||||
tag: Full Name <email address> otras cosas opcionales
|
||||
|
||||
Las etiquetas de uso común son:
|
||||
|
||||
- Signed-off-by: esta es una certificación del desarrollador de que él
|
||||
o ella tiene el derecho de enviar el parche para su inclusión en el
|
||||
kernel. Es un acuerdo con el Certificado de Origen del Desarrollador,
|
||||
que se encuentra en
|
||||
:ref:`Documentation/translations/sp_SP/process/submitting-patches.rst <sp_submittingpatches>`.
|
||||
El código sin la firma adecuada no se puede fusionar en el mainline.
|
||||
|
||||
- Co-developed-by: indica que el parche fue co-creado por varios
|
||||
desarrolladores; se utiliza para atribuir a los coautores (además del
|
||||
autor atribuido por la etiqueta From:) cuando varias personas trabajan
|
||||
en un solo parche. Cada Co-developed-by: debe ir seguido inmediatamente
|
||||
por un Signedoff-by: del coautor asociado. Los detalles y ejemplos se
|
||||
pueden encontrar en
|
||||
:ref:`Documentation/translations/sp_SP/process/submitting-patches.rst <sp_submittingpatches>`.
|
||||
|
||||
- Acked-by: indica un acuerdo por parte de otro desarrollador (a menudo
|
||||
un maintainer del código relevante) de que el parche es apropiado para
|
||||
su inclusión en el kernel.
|
||||
|
||||
- Tested-by: indica que la persona nombrada ha probado el parche y ha
|
||||
encontrado que funciona.
|
||||
|
||||
- Reviewed-by: el desarrollador nombrado ha revisado el parche para
|
||||
verificar que sea correcto; consulte la declaración del revisor en
|
||||
:ref:`Documentation/translations/sp_SP/process/submitting-patches.rst <sp_submittingpatches>`
|
||||
para obtener más detalles.
|
||||
|
||||
- Reported-by: nombra a un usuario que informó un problema que se
|
||||
soluciona con este parche; esta etiqueta se utiliza para dar crédito
|
||||
a las personas (a menudo infravalorada) que prueban nuestro código y
|
||||
nos hacen saber cuándo las cosas no funcionan correctamente. Tenga en
|
||||
cuenta que esta etiqueta debe ir seguida de una etiqueta Closes: que
|
||||
apunte al informe, a menos que el informe no esté disponible en la
|
||||
web. La etiqueta Link: se puede usar en lugar de Closes: si el parche
|
||||
corrige una parte de los problemas reportados.
|
||||
|
||||
- Cc: la persona nombrada recibió una copia del parche y tuvo la
|
||||
oportunidad de comentar sobre él.
|
||||
|
||||
Tenga cuidado al agregar etiquetas a sus parches, ya que solo Cc: es
|
||||
apropiado para la adición sin el permiso explícito de la persona nombrada;
|
||||
usar Reported-by: está casi bien en su mayoría, pero pida permiso si el
|
||||
error fue reportado en privado.
|
||||
|
||||
Envió del parche
|
||||
----------------
|
||||
|
||||
Antes de enviar sus parches por correo, hay un par de cosas más de las
|
||||
que debe ocuparse:
|
||||
|
||||
- ¿Está seguro de que su correo no corromperá los parches? Los parches
|
||||
con cambios gratuitos de espacio en blanco o ajuste de línea
|
||||
realizados por el cliente de correo no se aplicarán en el otro
|
||||
extremo, y a menudo, no se examinarán en detalle. Si tiene alguna
|
||||
duda, envíese el parche por correo y convénzase de que parece
|
||||
intacto.
|
||||
|
||||
:ref:`Documentation/translations/sp_SP/process/email-clients.rst <sp_email_clients>`
|
||||
tiene algunos consejos útiles sobre cómo hacer que clientes de correo
|
||||
específicos funcionen para enviar parches.
|
||||
|
||||
- ¿Está seguro de que su parche está libre de errores tontos? Siempre
|
||||
debe ejecutar parches a través de scripts/checkpatch.pl y abordar las
|
||||
quejas que surjan. Por favor, tenga en cuenta que checkpatch.pl, aunque
|
||||
es la encarnación de una buena cantidad de pensamiento sobre cómo
|
||||
deberían ser los parches del kernel, no es más inteligente que usted.
|
||||
Si corregir una queja de checkpatch.pl empeoraría el código, no lo
|
||||
haga.
|
||||
|
||||
Los parches siempre deben enviarse como texto sin formato. Por favor, no
|
||||
los envíe como archivos adjuntos; eso hace que sea mucho más difícil para
|
||||
los revisores citar secciones del parche en sus respuestas. En su lugar,
|
||||
simplemente coloca el parche directamente en su mensaje.
|
||||
|
||||
Al enviar parches por correo, es importante enviar copias a cualquier
|
||||
persona que pueda estar interesada en ellos. A diferencia de otros
|
||||
proyectos, el kernel anima a la gente a equivocarse por el lado de enviar
|
||||
demasiadas copias; no asuma que las personas relevantes verán su
|
||||
publicación en las listas de correo. En particular, las copias deben
|
||||
ir a:
|
||||
|
||||
- El (los) maintainer(s) del (de los) subsistema(s) afectado(s). Como se
|
||||
describió anteriormente, el archivo MAINTAINERS es el primer lugar para
|
||||
buscar a estas personas.
|
||||
|
||||
- Otros desarrolladores que han estado trabajando en la misma
|
||||
área – especialmente aquellos que podrían estar trabajando allí ahora.
|
||||
Usar git para ver quién más ha modificado los archivos en los que está
|
||||
trabajando puede ser útil.
|
||||
|
||||
- Si está respondiendo a un informe de error o a una solicitud de
|
||||
función, copie también al autor.
|
||||
|
||||
- Envié una copia a la lista de correo relevante o, si no se aplica nada
|
||||
más, a la lista de linux-kernel.
|
||||
|
||||
- Si está corrigiendo un error, piense si la corrección debe incluirse en
|
||||
la próxima actualización estable. Si es así, stable@vger.kernel.org
|
||||
debería obtener una copia del parche. También agregue un
|
||||
"Cc: stable@vger.kernel.org" a las etiquetas dentro del parche; eso
|
||||
hará que el equipo estable reciba una notificación cuando su solución
|
||||
incluya en el mainline.
|
||||
|
||||
Al seleccionar destinatarios para un parche, es bueno saber quién cree que
|
||||
eventualmente aceptará el parche y lo fusionará. Aunque es posible enviar
|
||||
parches directamente a Linus Torvalds y hacer que los fusione, las cosas
|
||||
normalmente no se hacen de esa manera. Linus está ocupado y hay
|
||||
maintainers de subsistemas que vigilan partes específicas del kernel.
|
||||
Generalmente, querrá que ese maintainer fusione sus parches. Andrew Morton
|
||||
es a menudo el objetivo del parche de último recurso si no hay un
|
||||
maintainer obvio.
|
||||
|
||||
Los parches necesitan buenas líneas de asunto. El formato canónico de una
|
||||
línea de parche es algo así como:
|
||||
|
||||
::
|
||||
|
||||
[PATCH nn/mm] subsys: descripción en una línea del parche
|
||||
|
||||
donde “nn” es el número ordinal del parche, “”mm” es el número total de
|
||||
parches en la serie, y “subsys” es el nombre del subsistema afectado.
|
||||
Claramente, nn/mm se puede omitir para un parche único e independiente.
|
||||
|
||||
Si tiene una serie significativa de parches, es costumbre enviar una
|
||||
descripción introductoria como parte cero. Sin embargo, esta convención no
|
||||
se sigue universalmente; si la utiliza, recuerde que la información en la
|
||||
introducción no se incluye en los registros de cambios del kernel. Por lo
|
||||
tanto, asegúrese de que los parches, en sí mismos, tengan información
|
||||
completa del registro de cambios.
|
||||
|
||||
En general, la segunda y las siguientes partes de un parche de varias
|
||||
partes deben enviarse como una respuesta a la primera parte para que todas
|
||||
se hilen juntas en el extremo receptor. Herramientas como git y quilt
|
||||
tienen comandos para enviar por correo un conjunto de parches con el
|
||||
subproceso adecuado. Sin embargo, si tiene una serie larga y está usando
|
||||
git, por favor evite la opción –chain-reply-to para evitar crear un
|
||||
anidamiento excepcionalmente profundo.
|
||||
|
@ -1,11 +1,230 @@
|
||||
.. include:: ../disclaimer-sp.rst
|
||||
|
||||
:Original: Documentation/process/6.Followthrough.rst
|
||||
:Translator: Carlos Bilbao <carlos.bilbao.osdev@gmail.com> and Avadhut Naik <avadhut.naik@amd.com>
|
||||
|
||||
.. _sp_development_followthrough:
|
||||
|
||||
Seguimiento
|
||||
===========
|
||||
|
||||
.. warning::
|
||||
TODO aún no traducido
|
||||
Llegados a este punto, ha seguido las directrices dadas hasta ahora, lo que
|
||||
sumado a sus propias habilidades de ingeniería, ha resultado en una serie
|
||||
de parches perfectos. Uno de los mayores errores que incluso los
|
||||
desarrolladores de kernel experimentados pueden cometer es concluir que su
|
||||
trabajo ya está hecho. En verdad, publicar parches indica una transición a
|
||||
la siguiente etapa del proceso, con, posiblemente, bastante trabajo aún por
|
||||
hacer.
|
||||
|
||||
Es raro un parche que sea tan bueno en su primera publicación que no haya
|
||||
espacio para la mejora. El proceso de desarrollo del kernel reconoce este
|
||||
hecho y, como resultado, está muy orientado hacia la mejora del código
|
||||
publicado. Y usted, como autor de ese código, se espera que trabaje con la
|
||||
comunidad del kernel para asegurarse de que su código esté a la altura de
|
||||
los estándares de calidad del kernel. No participar en este proceso es muy
|
||||
probable que impida la inclusión de sus parches en la línea principal.
|
||||
|
||||
Trabajando con revisores
|
||||
------------------------
|
||||
|
||||
Un parche de cualquier importancia resultará en una serie de comentarios de
|
||||
otros desarrolladores a medida que revisan el código. Trabajar con los
|
||||
revisores puede ser, para muchos desarrolladores, la parte más intimidante
|
||||
del proceso de desarrollo del kernel. Sin embargo, la vida puede ser mucho
|
||||
más fácil si tiene en cuenta algunas cosas:
|
||||
|
||||
- Si ha explicado bien su parche, los revisores entenderán su valor y por
|
||||
qué se tomó la molestia de escribirlo. Pero ese valor no les impedirá
|
||||
hacer una pregunta fundamental: ¿cómo será mantener un kernel con este
|
||||
código en él cinco o diez años después? Muchos de los cambios que se le
|
||||
pueden pedir que haga, desde ajustes de estilo de codificación hasta
|
||||
reescrituras sustanciales, provienen de la comprensión de que Linux
|
||||
seguirá existiendo y en desarrollo dentro de una década.
|
||||
|
||||
- La revisión de código es un trabajo arduo y es una ocupación
|
||||
relativamente ingrata; la gente recuerda quién escribió el código del
|
||||
kernel, pero hay poca fama duradera para aquellos que lo revisaron. Así
|
||||
que los revisores pueden ponerse de mal humor, especialmente cuando ven
|
||||
los mismos errores repetirse una y otra vez. Si recibe una revisión que
|
||||
parece enojada, insultante o abiertamente ofensiva, resista el impulso de
|
||||
responder de la misma manera. La revisión de código se trata del código,
|
||||
no de las personas, y los revisores de código no lo están atacando
|
||||
personalmente.
|
||||
|
||||
- De manera similar, los revisores de código no están tratando de promover
|
||||
las agendas de sus empleadores a expensas de la suya. Los desarrolladores
|
||||
del kernel a menudo esperan estar trabajando en el kernel dentro de
|
||||
varios años, pero entienden que su empleador podría cambiar.
|
||||
Verdaderamente, casi sin excepción, están trabajando hacia la creación
|
||||
del mejor kernel posible; no están tratando de causar incomodidad a los
|
||||
competidores de sus empleadores.
|
||||
|
||||
- Esté preparado para solicitudes aparentemente ridículas de cambios en el
|
||||
estilo de codificación y solicitudes para factorizar parte de su código
|
||||
en partes compartidas del kernel. Una de las tareas que realizan los
|
||||
maintainers es mantener las cosas con una apariencia uniforme. A veces, esto significa que el truco ingenioso en su driver para sortear un problema necesita convertirse en una característica generalizada del kernel lista para la próxima vez.
|
||||
|
||||
En resumen, cuando los revisores le envían comentarios, necesita prestar
|
||||
atención a las observaciones técnicas que están haciendo. No permita que su
|
||||
forma de expresarse o su propio orgullo le impidan hacerlo. Cuando reciba
|
||||
comentarios de revisión sobre un parche, tómese el tiempo para entender lo
|
||||
que el revisor está tratando de decir. Si es posible, arregle las cosas que
|
||||
el revisor le está pidiendo que corrija. Y responda al revisor:
|
||||
agradézcales y describa cómo responderá a sus preguntas.
|
||||
|
||||
Tenga en cuenta que no tiene que estar de acuerdo con cada cambio sugerido
|
||||
por los revisores. Si cree que el revisor ha malinterpretado su código,
|
||||
explique lo que realmente está sucediendo. Si tiene una objeción técnica a
|
||||
un cambio sugerido, descríbalo y justifique su solución al problema. Si sus
|
||||
explicaciones tienen sentido, el revisor las aceptará. Sin embargo, si su
|
||||
explicación no resulta persuasiva, especialmente si otros comienzan a estar
|
||||
de acuerdo con el revisor, tómese un tiempo para reflexionar nuevamente
|
||||
sobre las cosas. Puede ser fácil quedar cegado por su propia solución a un
|
||||
problema hasta el punto de no darse cuenta de que algo está
|
||||
fundamentalmente mal o, quizás, ni siquiera está resolviendo el problema
|
||||
correcto.
|
||||
|
||||
Andrew Morton ha sugerido que cada comentario de revisión que no resulte en
|
||||
un cambio de código debería resultar en un comentario adicional en el
|
||||
código; eso puede ayudar a los revisores futuros a evitar las preguntas que
|
||||
surgieron la primera vez.
|
||||
|
||||
Un error fatal es ignorar los comentarios de revisión con la esperanza de
|
||||
que desaparezcan. No desaparecerán. Si vuelve a publicar código sin haber
|
||||
respondido a los comentarios que recibió la vez anterior, es probable que
|
||||
descubra que sus parches no van a ninguna parte.
|
||||
|
||||
Hablando de volver a publicar código: tenga en cuenta que los revisores no
|
||||
recordarán todos los detalles del código que publicó la vez anterior. Así
|
||||
que siempre es una buena idea recordarles sobre problemas planteados
|
||||
anteriormente y cómo los manejó; el registro de cambios del parche es un
|
||||
buen lugar para este tipo de información. Los revisores no deberían tener
|
||||
que buscar en los archivos de la lista para familiarizarse con lo que se
|
||||
dijo la última vez; si les ayuda a tener un buen comienzo, estarán de mejor
|
||||
humor cuando revisiten su código.
|
||||
|
||||
¿Qué sucede si ha intentado hacer todo bien y las cosas aún no van a
|
||||
ninguna parte? La mayoría de los desacuerdos técnicos pueden resolverse
|
||||
mediante discusión, pero hay momentos en los que alguien simplemente tiene
|
||||
que tomar una decisión. Si realmente cree que esta decisión está en su
|
||||
contra de manera incorrecta, siempre puede intentar apelar a una autoridad
|
||||
superior. En el momento de escribir esto, esa autoridad superior tiende a
|
||||
ser Andrew Morton. Andrew tiene un gran respeto en la comunidad de
|
||||
desarrollo del kernel; a menudo puede desbloquear una situación que parece
|
||||
estar irremediablemente bloqueada. Sin embargo, apelar a Andrew no debe
|
||||
hacerse a la ligera, y no antes de que se hayan explorado todas las demás
|
||||
alternativas. Y tenga en cuenta, por supuesto, que él puede no estar de
|
||||
acuerdo con usted tampoco.
|
||||
|
||||
¿Qué pasa después?
|
||||
--------------------
|
||||
|
||||
Si un parche se considera algo bueno para agregar al kernel, y una vez que
|
||||
se hayan resuelto la mayoría de los problemas de revisión, el siguiente
|
||||
paso suele ser la entrada en el árbol del mantenedor de un subsistema. Cómo
|
||||
funciona eso varía de un subsistema a otro; cada mantenedor tiene su propia
|
||||
forma de hacer las cosas. En particular, puede haber más de un árbol, uno,
|
||||
quizás, dedicado a los parches planificados para la próxima ventana de
|
||||
fusión y otro para trabajos a más largo plazo.
|
||||
|
||||
Para los parches que se aplican a áreas para las que no hay un árbol de
|
||||
subsistema obvio (parches de gestión de memoria, por ejemplo), el árbol
|
||||
predeterminado suele ser -mm. Los parches que afectan a múltiples
|
||||
subsistemas también pueden terminar pasando por el árbol -mm.
|
||||
|
||||
La inclusión en un árbol de subsistema puede dar mayor visibilidad a un
|
||||
parche. Ahora, otros desarrolladores que trabajan con ese árbol recibirán
|
||||
el parche por defecto. Los árboles de subsistemas típicamente alimentan
|
||||
linux-next también, haciendo que su contenido sea visible para la comunidad
|
||||
de desarrollo en su conjunto. En este punto, hay una buena probabilidad de
|
||||
que reciba más comentarios de un nuevo conjunto de revisores; estos
|
||||
comentarios necesitan ser respondidos como en la ronda anterior.
|
||||
|
||||
Lo que también puede suceder en este punto, dependiendo de la naturaleza de
|
||||
su parche, es que aparezcan conflictos con el trabajo que están realizando
|
||||
otros. En el peor de los casos, conflictos pesados de parches pueden
|
||||
resultar en que algunos trabajos se pongan en espera para que los parches
|
||||
restantes puedan ser ajustados y fusionados. Otras veces, la resolución de
|
||||
conflictos involucrará trabajar con otros desarrolladores y, posiblemente,
|
||||
mover algunos parches entre árboles para asegurarse de que todo se aplique
|
||||
sin problemas. Este trabajo puede ser un dolor, pero cuente sus
|
||||
bendiciones: antes de la llegada del árbol linux-next, estos conflictos a
|
||||
menudo solo surgían durante la ventana de fusión y tenían que ser abordados
|
||||
de prisa. Ahora pueden resolverse con calma, antes de que se abra la
|
||||
ventana de fusión (merge window).
|
||||
|
||||
Algún día, si todo va bien, iniciará sesión y verá que su parche ha sido
|
||||
incluido en el kernel principal. ¡Felicidades! Una vez que la celebración
|
||||
termine (y se hayas agregado al archivo MAINTAINERS), vale la pena
|
||||
recordar un pequeño hecho importante: el trabajo aún no está hecho. La
|
||||
inclusión trae sus propios desafíos.
|
||||
|
||||
Para empezar, la visibilidad de su parche ha aumentado una vez más. Puede
|
||||
haber una nueva ronda de comentarios de desarrolladores que no estaban al
|
||||
tanto del parche antes. Puede ser tentador ignorarlos, ya que ya no hay
|
||||
cuestión de que su código sea fusionado. Sin embargo, resista esa
|
||||
tentación; aún necesita ser receptivo a los desarrolladores que tienen
|
||||
preguntas o sugerencias.
|
||||
|
||||
Más importante aún, la inclusión en la línea principal pone su código en
|
||||
manos de un grupo mucho más grande de probadores. Incluso si ha contribuido
|
||||
un driver para hardware que aún no está disponible, se sorprenderá de
|
||||
cuántas personas construirán su código en sus kernels. Y, por supuesto,
|
||||
donde hay probadores, habrá informes de errores.
|
||||
|
||||
El peor tipo de informes de errores son las regresiones. Si su parche causa
|
||||
una regresión, encontrará un número incómodo de ojos sobre usted; las
|
||||
regresiones pueden dar lugar a mucho malestar en la comunidad y pueden
|
||||
hacer que algunos desarrolladores comiencen a preguntarse si su parche
|
||||
realmente debería haber sido fusionado en primer lugar. Así que esté atento
|
||||
a los comentarios sobre problemas y, si es posible, corrija los errores de
|
||||
inmediato.
|
||||
|
||||
Después de haber abordado cualquier regresión, puede haber otros errores
|
||||
ordinarios que resolver. El período de estabilización es su mejor
|
||||
oportunidad para corregir estos errores y garantizar que el debut de su
|
||||
código en una versión del kernel principal sea lo más sólido posible. Así
|
||||
que, por favor, responda a los informes de errores y solucione los
|
||||
problemas si es posible. Para eso es el período de estabilización; puede
|
||||
comenzar a crear parches nuevos y geniales una vez que se hayan resuelto
|
||||
los problemas de los antiguos.
|
||||
|
||||
Y no olvide que hay otros hitos que también pueden generar informes de
|
||||
errores: la próxima versión estable del kernel principal, cuando
|
||||
distribuidores prominentes adopten una versión del kernel que contenga su
|
||||
parche, etc. Continuar respondiendo a estos informes es una cuestión de
|
||||
orgullo básico en su trabajo. Sin embargo, si eso no es suficiente
|
||||
motivación, también vale la pena considerar que la comunidad de desarrollo
|
||||
recuerda a los desarrolladores que pierden interés en su código después de
|
||||
que se fusiona. La próxima vez que publique un parche, lo evaluarán con la
|
||||
suposición de que no estará disponible para mantenerlo después.
|
||||
|
||||
Otras cosas que pueden suceder
|
||||
-------------------------------
|
||||
|
||||
Un día, puede que abra su cliente de correo y vea que alguien le ha enviado
|
||||
un parche para su código. Esa es una de las ventajas de tener su código
|
||||
disponible públicamente, después de todo. Si está de acuerdo con el parche, puede reenviarlo al maintainer del subsistema (asegúrese de incluir una
|
||||
línea From: adecuada para que la atribución sea correcta, y añada su propia
|
||||
firma), o enviar una respuesta Acked-by: y dejar que el autor original lo
|
||||
envíe hacia arriba.
|
||||
|
||||
Si no está de acuerdo con el parche, envíe una respuesta educada explicando
|
||||
por qué. Si es posible, dígale al autor qué cambios deben hacerse para que
|
||||
considere el parche aceptable. Existe una cierta resistencia a incluir
|
||||
parches que son rechazados por el autor y el maintainer del código, pero
|
||||
esto tiene un límite. Si se interpreta que bloque buen trabajo, esos
|
||||
parches eventualmente lo eludirán y se incorporarán al kernel de todos
|
||||
modos. En el kernel de Linux, nadie tiene poder de veto absoluto sobre
|
||||
ningún código. Excepto quizás Linus.
|
||||
|
||||
En muy raras ocasiones, puede encontrar algo completamente diferente: otro
|
||||
desarrollador publica una solución distinta a su problema. En ese punto, es
|
||||
probable que uno de los dos parches no se incluya, y "el mío fue el
|
||||
primero" no se considera un argumento técnico convincente. Si el parche de
|
||||
otra persona desplaza al suyo y se incorpora al kernel, realmente solo hay
|
||||
una manera de responder: alegrarse de que su problema se haya resuelto y
|
||||
continuar con su trabajo. Que su trabajo sea desplazado de esta manera
|
||||
puede ser doloroso y desalentador, pero la comunidad recordará su reacción
|
||||
mucho después de que hayan olvidado de quién era el parche que realmente se
|
||||
incluyó.
|
||||
|
@ -1,11 +1,214 @@
|
||||
.. include:: ../disclaimer-sp.rst
|
||||
|
||||
:Original: Documentation/process/7.AdvancedTopics.rst
|
||||
:Translator: Carlos Bilbao <carlos.bilbao.osdev@gmail.com> and Avadhut Naik <avadhut.naik@amd.com>
|
||||
|
||||
.. _sp_development_advancedtopics:
|
||||
|
||||
Temas avanzados
|
||||
===============
|
||||
|
||||
.. warning::
|
||||
TODO aún no traducido
|
||||
Llegados a este punto, con suerte, tiene una idea de cómo funciona el
|
||||
proceso de desarrollo. Sin embargo, ¡todavía hay más que aprender! Esta
|
||||
sección cubrirá varios temas que pueden ser útiles para los desarrolladores
|
||||
que desean convertirse en una parte regular del proceso de desarrollo del
|
||||
kernel Linux.
|
||||
|
||||
Gestionar parches con git
|
||||
-------------------------
|
||||
|
||||
El uso del control de versiones distribuido para el kernel comenzó a
|
||||
principios de 2002 cuando Linus comenzó a jugar con la aplicación
|
||||
propietaria BitKeeper. Aunque BitKeeper fue controvertido, el enfoque de
|
||||
la gestión de versiones de software que incorporó ciertamente no lo fue.
|
||||
El control de versiones distribuido permitió una aceleración inmediata
|
||||
del proyecto de desarrollo del kernel. En los tiempos actuales, existen
|
||||
varias alternativas gratuitas a BitKeeper. Para bien o para mal, el
|
||||
proyecto del kernel ha optado por git como su herramienta preferida.
|
||||
|
||||
Administrar parches con git puede hacer la vida mucho más fácil para el
|
||||
desarrollador, especialmente a medida que crece el volumen de esos
|
||||
parches. Git también tiene sus asperezas y representa ciertos peligros;
|
||||
es una herramienta joven y poderosa que aún está siendo civilizada por
|
||||
sus desarrolladores. Este documento no intentará enseñar al lector cómo
|
||||
usar git; eso sería material suficiente para un documento extenso por
|
||||
derecho propio. En su lugar, el enfoque aquí será cómo git encaja en el
|
||||
proceso de desarrollo del kernel en particular. Los desarrolladores que
|
||||
deseen ponerse al día con git encontrarán más información en:
|
||||
|
||||
https://git-scm.com/
|
||||
|
||||
https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
|
||||
|
||||
y en varios tutoriales que se encuentran en la web.
|
||||
|
||||
El primer orden del negocio es leer los sitios mencionados anteriormente
|
||||
y comprender cómo funciona git antes de intentar usarlo para poner
|
||||
parches a disposición de otros. Un desarrollador que usa git debe ser
|
||||
capaz de obtener una copia del repositorio mainline, explorar el historial
|
||||
de revisiones, hacer commits en el árbol, usar ramas, etcétera. También es
|
||||
útil entender las herramientas de git para rescribir la historia (como
|
||||
rebase). Git viene con su propia terminología y conceptos; un nuevo
|
||||
usuario de git debe conocer las referencias, las ramas remotas, el índice,
|
||||
las fusiones fast-forward, los pushes y pulls, las cabezas separadas,
|
||||
etcétera. Todo puede ser un poco intimidante al principio, pero los
|
||||
conceptos no son tan difíciles de entender con un poco de estudio.
|
||||
|
||||
Usar git para generar parches para enviarlos por correo electrónico puede
|
||||
ser un buen ejercicio mientras te pones al día.
|
||||
|
||||
Cuando esté listo para comenzar a publicar árboles de git para que otros
|
||||
los vean, necesitará por supuesto, un servidor del que se pueda extraer.
|
||||
Configurar un servidor de este tipo con git-daemon es relativamente
|
||||
sencillo si tiene un sistema accesible a Internet. De lo contrario, los
|
||||
sitios de alojamiento público y gratuitos (GitHub, por ejemplo) están
|
||||
comenzando a aparecer en la red. Los desarrolladores establecidos pueden
|
||||
obtener una cuenta en kernel.org, pero no son fáciles de conseguir; ver
|
||||
https://kernel.org/faq/ para más información.
|
||||
|
||||
El flujo de trabajo normal de git implica el uso de muchas ramas. Cada
|
||||
línea de desarrollo puede separarse en una “rama temática” separada y
|
||||
mantenerse de forma independiente. Las ramas en git son baratas, no hay
|
||||
razón para no hacer uso gratuito de ellas. Y, en cualquier caso, no debe
|
||||
desarrollarse en ninguna rama de la que tenga la intención de pedir a
|
||||
otros que hagan un pull. Las ramas disponibles públicamente deben crearse
|
||||
con cuidado; fusione los parches de las ramas de desarrollo cuando estén
|
||||
en forma completa y listos para usar – no antes.
|
||||
|
||||
Git proporciona herramientas poderosas que permiten reescribir su historia
|
||||
de desarrollo. Un parche inconveniente (uno que rompe la bisección, por
|
||||
ejemplo, o que tiene algún otro tipo de error obvio) se puede corregir en
|
||||
su lugar o hacer que desaparezca de la historia por completo. Una serie de
|
||||
parches se puede reescribir como si se hubiera escrito sobre el mainline
|
||||
de hoy, aunque haya estado trabajando en ella durante meses. Los cambios
|
||||
se pueden transferir de manera transparente de una rama a otra. Y así
|
||||
sucesivamente. El uso juicioso de la capacidad de git para revisar el
|
||||
historial puede ayudar en la creación de conjuntos de parches limpios con
|
||||
menos problemas.
|
||||
|
||||
El uso excesivo de esta capacidad puede llevar a otros problemas más allá
|
||||
de una simple obsesión por crear la historia perfecta del proyecto.
|
||||
Reescribir la historia rescribirá los cambios contenidos en esa historia,
|
||||
convirtiendo un árbol del kernel probado (con suerte) en uno no probado.
|
||||
Pero más allá de eso, los desarrolladores no pueden colaborar fácilmente
|
||||
si no tienen una vista compartida del historial del proyecto; si reescribe
|
||||
la historia que otros desarrolladores han introducido en sus repositorios,
|
||||
les hará la vida mucho más difícil a esos desarrolladores. Por lo tanto,
|
||||
aquí se aplica una regla simple general: la historia que se ha exportado
|
||||
a otros generalmente debe considerarse inmutable a partir de entonces.
|
||||
|
||||
Por lo tanto, una vez que envié un conjunto de cambios a su servidor
|
||||
disponible públicamente, esos cambios no deben reescribirse. Git
|
||||
intentará hacer cumplir esta regla si intenta enviar cambios que no
|
||||
resulten en un “fast-forward merge” (es decir, cambios que no comparten
|
||||
el mismo historial). Es posible anular esta comprobación, y puede haber
|
||||
ocasiones en las que sea necesario reescribir un árbol exportado. Mover
|
||||
conjuntos de cambios entre árboles para evitar conflictos en linux-next
|
||||
es un ejemplo. Pero tales acciones deberían ser raras. Esta es una de las
|
||||
razones por las que el desarrollo debe hacerse en ramas privadas (que se
|
||||
pueden reescribir si es necesario) y solo trasladarse a ramas públicas
|
||||
cuando esté en un estado razonablemente avanzado.
|
||||
|
||||
A medida que el mainline (u otro árbol en el que se basa un conjunto de
|
||||
cambios) avanza, es tentador fusionarse con ese árbol para permanecer a
|
||||
la vanguardia. Para una rama privada, la rebase puede ser una manera fácil
|
||||
de mantenerse al día con otro árbol, pero la rebase no es una opción una
|
||||
vez que el árbol se exporta al mundo. Una vez que eso sucede, se debe
|
||||
realizar una fusión completa. Fusionar ocasionalmente tiene sentido, pero
|
||||
las fusiones demasiado frecuentes pueden desordenar el historial
|
||||
innecesariamente. La técnica sugerida en este caso es fusionar con poca
|
||||
frecuencia y, por lo general, solo en puntos de lanzamiento específicos
|
||||
(como una versión -rc del mainline). Si está nervioso por cambios
|
||||
específicos, siempre puede realizar fusiones de prueba en una rama
|
||||
privada. La herramienta git “rerere” puede ser útil en tales situaciones;
|
||||
recuerda cómo se resolvieron los conflictos de fusión para que no tenga
|
||||
que hacer el mismo trabajo dos veces.
|
||||
|
||||
Una de las mayores quejas recurrentes sobre herramientas como git es la
|
||||
siguiente: el movimiento masivo de parches de un repositorio a otro hace
|
||||
que sea fácil deslizar cambios más aconsejados que pasan al mainline
|
||||
debajo del radar de revisión. Los desarrolladores del kernel tienden a
|
||||
descontentarse cuando ven que suceden ese tipo de cosas; poner un árbol
|
||||
de git con parches no revisados o fuera de tema puede afectar su capacidad
|
||||
para hacer que los árboles sean integrados en el futuro. Citando a Linus:
|
||||
|
||||
::
|
||||
|
||||
Puede enviarme parches, pero para que yo acepte un parche de git de
|
||||
su parte, necesito saber que usted sabe lo que está haciendo, y
|
||||
necesito poder confiar en las cosas *sin* tener que revisar
|
||||
manualmente cada cambio individual.
|
||||
|
||||
(https://lwn.net/Articles/224135/).
|
||||
|
||||
Para evitar este tipo de situación, asegúrese de que todos los parches
|
||||
dentro de una rama determinada se adhieran estrictamente al tema asociado;
|
||||
una rama de “correcciones de drivers” no debería hacer cambios en el
|
||||
código central de gestión de memoria. Y, lo más importante, no utilice un
|
||||
árbol git para eludir el proceso de revisión. Publique un resumen
|
||||
ocasional del árbol en la lista relevante y, cuando sea el momento
|
||||
adecuado, solicite que el árbol se incluya en linux-next.
|
||||
|
||||
Si y cuando otros comiencen a enviar parches para su inclusión en su
|
||||
árbol, no olvide revisarlos. Además, asegúrese de mantener la información
|
||||
de autoría correcta; la herramienta git “am” hace lo mejor que puede es
|
||||
este sentido, pero es posible que tenga que agregar una línea “From:” al
|
||||
parche si ha sido reenviado a través de un tercero.
|
||||
|
||||
Al solicitar un pull, proporcione toda la información relevante: dónde
|
||||
está su árbol, qué rama se debe pull, y que cambios resultarán del pull.
|
||||
El comando git request-pull puede ser útil en este sentido; formateará la
|
||||
solicitud como otros desarrolladores esperan, y también comprobará para
|
||||
asegurarse de que ha recordado enviar esos cambios al servidor público.
|
||||
|
||||
Revisión de parches
|
||||
-------------------
|
||||
|
||||
Algunos lectores seguramente se opondrán a incluir esta sección con
|
||||
“temas avanzados” porque incluso los desarrolladores principiantes del
|
||||
kernel deberían revisar los parches. Es cierto que no hay mejor manera de
|
||||
aprender a programar en el entorno del kernel que mirando el código
|
||||
publicado por otros. Además, los revisores siempre escasean; al revisar
|
||||
código, puede contribuir significativamente al proceso en su conjunto.
|
||||
|
||||
Revisar el código puede ser una perspectiva intimidante, especialmente
|
||||
para un nuevo desarrollador de kernel que puede sentirse nervioso al
|
||||
cuestionar el código – en público – publicado por aquellos con más
|
||||
experiencia. Sin embargo, incluso el código escrito por los desarrolladores
|
||||
más experimentados se puede mejorar. Quizás el mejor consejo para los
|
||||
revisores (todos los revisores) es este: expresar los comentarios de
|
||||
revisión como preguntas en lugar de críticas. Preguntar “¿cómo se libera
|
||||
el bloqueo en este camino?” siempre funcionará mejor que decir “el
|
||||
bloqueo aquí es incorrecto”.
|
||||
|
||||
Otra técnica que es útil en caso de desacuerdo es pedir a otros que
|
||||
intervengan. Si una discusión llega a un punto muerto después de algunos
|
||||
intercambios, solicite las opiniones de otros revisores o maintainers. A
|
||||
menudo, aquellos que están de acuerdo con un revisor permanecen en
|
||||
silencio a menos que se les invite a participar. La opinión de varias
|
||||
personas tiene exponencialmente más peso.
|
||||
|
||||
Diferentes desarrolladores revisarán el código desde diferentes puntos de
|
||||
vista. Algunos se preocupan principalmente por el estilo de codificación
|
||||
y si las líneas de código tienen espacios en blanco al final. Otros se
|
||||
enfocarán principalmente en si el cambio implementado por el parche en su
|
||||
totalidad es beneficioso para el kernel o no. Sin embargo, otros
|
||||
comprobarán si hay bloqueos problemáticos, uso excesivo de la pila,
|
||||
posibles problemas de seguridad, duplicación de código encontrado en
|
||||
otras partes, documentación adecuada, efectos adversos en el rendimiento,
|
||||
cambios en la ABI del espacio de usuario, etcétera. Todos los tipos de
|
||||
revisión, si conducen a un mejor código en el kernel, son bienvenidos y
|
||||
valen la pena.
|
||||
|
||||
No hay ningún requisito estricto para usar etiquetas específicas como
|
||||
``Reviewed-by``. De hecho, las revisiones en Inglés sencillo son más
|
||||
informativas y alentadas incluso cuando se proporciona una etiqueta, por
|
||||
ejemplo, “Revisé los aspectos A, B y C de esta propuesta y me parece
|
||||
bien”.
|
||||
¡Alguna forma de mensaje de revisión o respuesta es obviamente necesaria,
|
||||
de lo contrario, los maintainers no sabrán que el revisor ha revisado el
|
||||
parche en absoluto!
|
||||
|
||||
Por último, pero no menos importante, la revisión de parches puede
|
||||
convertirse en un proceso negativo, centrado en señalar problemas. ¡Por
|
||||
favor, dé un cumplido de vez en cuando, especialmente a los principiantes!
|
||||
|
@ -1,11 +1,82 @@
|
||||
.. include:: ../disclaimer-sp.rst
|
||||
|
||||
:Original: Documentation/process/8.Conclusion.rst
|
||||
:Translator: Carlos Bilbao <carlos.bilbao.osdev@gmail.com> and Avadhut Naik <avadhut.naik@amd.com>
|
||||
|
||||
.. _sp_development_conclusion:
|
||||
|
||||
Para más información
|
||||
====================
|
||||
|
||||
.. warning::
|
||||
TODO aún no traducido
|
||||
Hay numerosas fuentes de información sobre el desarrollo del kernel de
|
||||
Linux y temas relacionados. La primera de ellas será el directorio de
|
||||
Documentación (Documentation) que se encuentra en la distribución del
|
||||
código fuente del kernel. Comience con el nivel superior
|
||||
:ref:`Documentation/translations/sp_SP/process/howto.rst <sp_process_howto>`;
|
||||
también lea
|
||||
:ref:`Documentation/translations/sp_SP/process/submitting-patches.rst <sp_submittingpatches>`.
|
||||
Muchas API internas del kernel están documentadas utilizando el mecanismo
|
||||
de kerneldoc; “make htmldocs” o “make pdfdocs” se pueden usar para
|
||||
generar esos documentos en formato HTML o PDF (aunque la versión de TeX
|
||||
incluida en algunas distribuciones tiene límites internos y no procesa
|
||||
los documentos correctamente).
|
||||
|
||||
Varios sitios web discuten el desarrollo del kernel en todos los niveles
|
||||
de detalle. A su autor le gustaría sugerir humildemente https://lwn.net/
|
||||
como fuente. La información sobre muchos temas específicos del kernel se
|
||||
puede encontrar a través del índice del kernel de LWN en:
|
||||
|
||||
https://lwn.net/Kernel/Index/
|
||||
|
||||
Más allá de eso, un recurso valioso para los desarrolladores del kernel
|
||||
es:
|
||||
|
||||
https://kernelnewbies.org/
|
||||
|
||||
Y, por supuesto, no se debe olvidar https://kernel.org/, la ubicación
|
||||
definitiva para información de lanzamiento del kernel.
|
||||
|
||||
Hay varios libros sobre el desarrollo del kernel:
|
||||
|
||||
Linux Device Drivers, 3rd Edition (Jonathan Corbet, Alessandro
|
||||
Rubini, and Greg Kroah-Hartman). En linea en
|
||||
https://lwn.net/Kernel/LDD3/.
|
||||
|
||||
Linux Kernel Development (Robert Love).
|
||||
|
||||
Understanding the Linux Kernel (Daniel Bovet and Marco Cesati).
|
||||
|
||||
Todos estos libros padecen un defecto común: suelen estar algo obsoletos
|
||||
cuando llegan a las estanterías, y ya llevan un tiempo en las estanterías.
|
||||
Aun así, hay bastante buena información que se puede encontrar allí.
|
||||
|
||||
La documentación de git se puede encontrar en:
|
||||
|
||||
https://www.kernel.org/pub/software/scm/git/docs/
|
||||
|
||||
https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
|
||||
|
||||
Conclusión
|
||||
==========
|
||||
|
||||
Felicitaciones a todos los que han logrado leer este extenso documento.
|
||||
Con suerte, ha proporcionado una comprensión útil de cómo se desarrolla
|
||||
el kernel Linux y cómo puede participar en ese proceso.
|
||||
|
||||
Al final, lo que importa es la participación. Cualquier proyecto de
|
||||
software de código abierto no es más que la suma de lo que sus
|
||||
colaboradores aportan. El kernel Linux ha progresado tan rápido y tan como
|
||||
lo ha hecho porque ha sido ayudado por un grupo impresionantemente grande
|
||||
de desarrolladores, todos los cuales están trabajando para mejorarlo. El
|
||||
kernel es un excelente ejemplo de lo que se puede lograr cuando miles de
|
||||
personas trabajan juntas hacia un objetivo común.
|
||||
|
||||
Sin embargo, el kernel siempre puede beneficiarse de una base de
|
||||
desarrolladores más grande. Siempre hay más trabajo por hacer. Pero, lo
|
||||
que es igual de importante, la mayoría de los demás participantes en el
|
||||
ecosistema Linux pueden beneficiarse contribuyendo al kernel. Introducir
|
||||
código en el mainline es la clave para una mayor calidad del código,
|
||||
menores costes de mantenimiento y distribución, un mayor nivel de
|
||||
influencia sobre la dirección del desarrollo del kernel y más. Es una
|
||||
situación en la que todos los involucrados ganan. Encienda su editor y
|
||||
únase a nosotros; será más que bienvenido.
|
||||
|
@ -1,7 +1,7 @@
|
||||
.. include:: ../disclaimer-sp.rst
|
||||
|
||||
:Original: Documentation/process/development-process.rst
|
||||
:Translator: Avadhut Naik <avadhut.naik@amd.com>
|
||||
:Translator: Carlos Bilbao <carlos.bilbao.osdev@gmail.com> and Avadhut Naik <avadhut.naik@amd.com>
|
||||
|
||||
.. _sp_development_process_main:
|
||||
|
||||
@ -9,14 +9,13 @@ Guía del proceso de desarrollo del kernel
|
||||
=========================================
|
||||
|
||||
El propósito de este documento es ayudar a los desarrolladores (y sus
|
||||
gerentes) a trabajar con la comunidad de desarrollo con un mínimo de
|
||||
jefes) a trabajar con la comunidad de desarrollo con el mínimo de
|
||||
frustración. Es un intento de documentar cómo funciona esta comunidad
|
||||
de una manera accesible para aquellos que no están familiarizados
|
||||
íntimamente con el desarrollo del kernel de Linux (o, de hecho, el
|
||||
desarrollo de software libre en general). Si bien hay algo de material
|
||||
técnico aquí, este es en gran medida una discusión orientada al proceso
|
||||
que no requiere un conocimiento profundo de la programación del kernel
|
||||
para entenderla.
|
||||
de una manera accesible, para aquellos que no están familiarizados
|
||||
íntimamente con el desarrollo del kernel Linux (o, de hecho, el desarrollo
|
||||
de software libre en general). Si bien hay algo de material técnico aquí,
|
||||
esto es en gran medida una discusión orientada al proceso que no requiere
|
||||
un conocimiento profundo de la programación del kernel para entenderla.
|
||||
|
||||
.. toctree::
|
||||
:caption: Contenido
|
||||
@ -25,3 +24,9 @@ para entenderla.
|
||||
|
||||
1.Intro
|
||||
2.Process
|
||||
3.Early-stage
|
||||
4.Coding
|
||||
5.Posting
|
||||
6.Followthrough
|
||||
7.AdvancedTopics
|
||||
8.Conclusion
|
||||
|
@ -96,7 +96,7 @@ En la sección :menuselection:`Sending Preferences`:
|
||||
- :menuselection:`Strip Whitespace Before Sending` debe estar ``disabled``
|
||||
|
||||
Al redactar el mensaje, el cursor debe colocarse donde el parche debería
|
||||
aparecer, y luego presionando :kbd:`CTRL-R` se le permite especificar e
|
||||
aparecer, y luego presionando `CTRL-R` se le permite especificar e
|
||||
archivo de parche a insertar en el mensaje.
|
||||
|
||||
Claws Mail (GUI)
|
||||
@ -104,7 +104,7 @@ Claws Mail (GUI)
|
||||
|
||||
Funciona. Algunos usan esto con éxito para los parches.
|
||||
|
||||
Para insertar un parche haga :menuselection:`Message-->Insert File` (:kbd:`CTRL-I`)
|
||||
Para insertar un parche haga :menuselection:`Message-->Insert File` (`CTRL-I`)
|
||||
o use un editor externo.
|
||||
|
||||
Si el parche insertado debe editarse en la ventana de composición de Claws
|
||||
@ -118,11 +118,11 @@ Evolution (GUI)
|
||||
Algunos usan esto con éxito para sus parches.
|
||||
|
||||
Cuando escriba un correo seleccione: Preformat
|
||||
desde :menuselection:`Format-->Paragraph Style-->Preformatted` (:kbd:`CTRL-7`)
|
||||
desde :menuselection:`Format-->Paragraph Style-->Preformatted` (`CTRL-7`)
|
||||
o en la barra de herramientas
|
||||
|
||||
Luego haga:
|
||||
:menuselection:`Insert-->Text File...` (:kbd:`ALT-N x`)
|
||||
:menuselection:`Insert-->Text File...` (`ALT-N x`)
|
||||
para insertar el parche.
|
||||
|
||||
También puede hacer ``diff -Nru old.c new.c | xclip``, seleccione
|
||||
|
@ -10,6 +10,7 @@
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
development-process
|
||||
submitting-patches
|
||||
kernel-docs
|
||||
coding-style
|
||||
@ -28,5 +29,4 @@
|
||||
management-style
|
||||
submit-checklist
|
||||
howto
|
||||
development-process
|
||||
maintainer-kvm-x86
|
||||
|
@ -60,24 +60,24 @@ CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 必须是以 16 进制数写入。
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
在 x86 架构上
|
||||
你可以按下键盘组合键 :kbd:`ALT-SysRq-<command key>`。
|
||||
你可以按下键盘组合键 `ALT-SysRq-<command key>`。
|
||||
|
||||
.. note::
|
||||
一些键盘可能没有标识 'SySRq' 键。'SySRq' 键也被当做 'Print Screen'键。
|
||||
同时有些键盘无法处理同时按下这么多键,因此你可以先按下键盘 :kbd:`Alt` 键,
|
||||
然后按下键盘 :kbd:`SysRq` 键,再释放键盘 :kbd:`SysRq` 键,之后按下键盘上命令键
|
||||
:kbd:`<command key>`,最后释放所有键。
|
||||
同时有些键盘无法处理同时按下这么多键,因此你可以先按下键盘 `Alt` 键,
|
||||
然后按下键盘 `SysRq` 键,再释放键盘 `SysRq` 键,之后按下键盘上命令键
|
||||
`<command key>`,最后释放所有键。
|
||||
|
||||
在 SPARC 架构上
|
||||
你可以按下键盘组合键 :kbd:`ALT-STOP-<command key>` 。
|
||||
你可以按下键盘组合键 `ALT-STOP-<command key>` 。
|
||||
|
||||
在串行控制台(只针对 PC 类型的标准串口)
|
||||
你可以发一个 ``BREAK`` ,然后在 5 秒内发送一个命令键,
|
||||
发送 ``BREAK`` 两次将被翻译为一个正常的 BREAK 操作。
|
||||
|
||||
在 PowerPC 架构上
|
||||
按下键盘组合键 :kbd:`ALT - Print Screen` (或者 :kbd:`F13`) - :kbd:`<命令键>` 。
|
||||
:kbd:`Print Screen` (或者 :kbd:`F13`) - :kbd:`<命令键>` 或许也能实现。
|
||||
按下键盘组合键 `ALT - Print Screen` (或者 `F13`) - `<命令键>` 。
|
||||
`Print Screen` (或者 `F13`) - `<命令键>` 或许也能实现。
|
||||
|
||||
在其他架构上
|
||||
如果你知道其他架构的组合键,请告诉我,我可以把它们添加到这部分。
|
||||
@ -87,7 +87,7 @@ CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 必须是以 16 进制数写入。
|
||||
|
||||
echo t > /proc/sysrq-trigger
|
||||
|
||||
这个命令键 :kbd:`<command key>` 是区分大小写的。
|
||||
这个命令键 `<command key>` 是区分大小写的。
|
||||
|
||||
什么是命令键?
|
||||
~~~~~~~~~~~~~~
|
||||
@ -203,8 +203,8 @@ syslogd/klogd 进程是运行的,它们仍将被记录。)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
这也会发生在我这,我发现轻敲键盘两侧的 shift、alt 和 control 键,然后再次敲击
|
||||
一个无效的 SysRq 键序列可以解决问题。(比如,像键盘组合键 :kbd:`alt-sysrq-z` )
|
||||
切换到另一个虚拟控制台(键盘操作 :kbd:`ALT+Fn` ),然后再切回来应该也有帮助。
|
||||
一个无效的 SysRq 键序列可以解决问题。(比如,像键盘组合键 `alt-sysrq-z` )
|
||||
切换到另一个虚拟控制台(键盘操作 `ALT+Fn` ),然后再切回来应该也有帮助。
|
||||
|
||||
我敲击了 SysRq 键,但像是什么都没发生,发生了什么错误?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -259,7 +259,7 @@ SysRq 键的输出和所有其他控制台输出一样,受制于控制台日
|
||||
文件的消费访问到。作为一个特例,来自 sysrq 命令的标题行将被传递给所有控制台
|
||||
使用者,就好像当前日志级别是最大的一样。如果只发出标题头,则几乎可以肯定内核日志
|
||||
级别太低。如果你需要控制台上的输出,那么你将需要临时提高控制台日志级别,通过使用
|
||||
键盘组合键 :kbd:`alt-sysrq-8` 或者::
|
||||
键盘组合键 `alt-sysrq-8` 或者::
|
||||
|
||||
echo 8 > /proc/sysrq-trigger
|
||||
|
||||
|
@ -85,7 +85,7 @@ Alpine (TUI)
|
||||
- :menuselection:`Do Not Send Flowed Text` 必须开启
|
||||
- :menuselection:`Strip Whitespace Before Sending` 必须关闭
|
||||
|
||||
当写邮件时,光标应该放在补丁会出现的地方,然后按下 :kbd:`CTRL-R` 组合键,使指
|
||||
当写邮件时,光标应该放在补丁会出现的地方,然后按下 `CTRL-R` 组合键,使指
|
||||
定的补丁文件嵌入到邮件中。
|
||||
|
||||
Claws Mail (GUI)
|
||||
@ -93,7 +93,7 @@ Claws Mail (GUI)
|
||||
|
||||
可以用,有人用它成功地发过补丁。
|
||||
|
||||
用 :menuselection:`Message-->Insert File` (:kbd:`CTRL-I`) 或外置编辑器插入补丁。
|
||||
用 :menuselection:`Message-->Insert File` (`CTRL-I`) 或外置编辑器插入补丁。
|
||||
|
||||
若要在Claws编辑窗口重修改插入的补丁,需关闭
|
||||
:menuselection:`Configuration-->Preferences-->Compose-->Wrapping`
|
||||
@ -105,11 +105,11 @@ Evolution (GUI)
|
||||
一些开发者成功的使用它发送补丁。
|
||||
|
||||
撰写邮件时:
|
||||
从 :menuselection:`格式-->段落样式-->预格式化` (:kbd:`CTRL-7`)
|
||||
从 :menuselection:`格式-->段落样式-->预格式化` (`CTRL-7`)
|
||||
或工具栏选择 :menuselection:`预格式化` ;
|
||||
|
||||
然后使用:
|
||||
:menuselection:`插入-->文本文件...` (:kbd:`ALT-N x`) 插入补丁文件。
|
||||
:menuselection:`插入-->文本文件...` (`ALT-N x`) 插入补丁文件。
|
||||
|
||||
你还可以 ``diff -Nru old.c new.c | xclip`` ,选择 :menuselection:`预格式化` ,
|
||||
然后使用鼠标中键进行粘帖。
|
||||
|
97
Documentation/translations/zh_CN/security/IMA-templates.rst
Normal file
97
Documentation/translations/zh_CN/security/IMA-templates.rst
Normal file
@ -0,0 +1,97 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/security/IMA-templates.rst
|
||||
|
||||
:翻译:
|
||||
赵硕 Shuo Zhao <zhaoshuo@cqsoftware.com.cn>
|
||||
|
||||
===============
|
||||
IMA模板管理机制
|
||||
===============
|
||||
|
||||
|
||||
介绍
|
||||
====
|
||||
|
||||
原始的 ``ima`` 模板是固定长度的,包含文件数据的哈希值和路径名。文件数据
|
||||
哈希值限制为20字节(md5/sha1)。路径名是一个以空字符终止的字符串,长度限
|
||||
制为255个字符内。
|
||||
为了克服这些限制并添加额外的文件元数据,通过定义额外的模板来扩展当前版本
|
||||
的IMA这是有必要的。例如,可能报告的信息包括索引节点的 UID/GID或索引节点
|
||||
及访问它进程的LSM标签。
|
||||
|
||||
然而,引入这个功能的主要问题是,每次定义一个新模板时,生成和显示度量列表
|
||||
的函数都需要包含处理新格式的代码,因此,这些函数的规模随着时间的推移会
|
||||
显著增长。
|
||||
|
||||
提出的解决方案通过将模板管理与其余IMA代码分离来解决这个问题。该解决方案
|
||||
的核心是定义两个新的数据结构:一个是模板描述符,用于确定度量列表中应包含
|
||||
哪些信息;另一个是模板字段,用于生成和显示给定类型的数据。
|
||||
|
||||
使用这些结构管理模板非常简单。为了支持一种新的数据类型,开发人员定义字段
|
||||
标识符,并实现两个函数,分别为init()和show(),用于生成和显示度量条目。
|
||||
定义一个新的模板描述符需要通过 ``ima_template_fmt`` 内核命令行参数指定
|
||||
模板格式(一个由 ``|`` 字符分隔的字段标识符字符串)。在启动时,IMA通过将格
|
||||
式转换从支持的模板字段集合中选取模板字段数组,来初始化所选的模板描述符。
|
||||
|
||||
在初始化步骤之后,IMA将调用 ``ima_alloc_init_template()`` (这是为新模板
|
||||
管理机制所打补丁中定义的新函数),通过使用在内核配置选择的模板描述符或者新引
|
||||
入的 ``ima_template`` 和 ``ima_template_fmt`` 内核命令行参数,生成一个新
|
||||
的度量条目。在这一阶段,新架构的优势得以清晰展示:后一个函数将不会包含处理给
|
||||
定模板的特定代码,而是简单地调用与所选模板描述符关联的模板字段的 ``init()``
|
||||
方法,并将结果(指向已分配数据的指针和数据长度)存储在度量条目结构中。
|
||||
|
||||
相同的机制也用于显示度量条目。函数 ``ima[_ascii]_measurements_show()`` 会为
|
||||
每个条目检索用于生成该条目的模板描述符,并为模板字段结构数组中的每一项调用show()
|
||||
方法。
|
||||
|
||||
|
||||
|
||||
支持的模板字段和描述符
|
||||
======================
|
||||
|
||||
下面是支持的模板字段列表 ``('<identifier>': description)`` ,可以通过将其标识符
|
||||
添加到格式字符串中用于定义新的模板描述符(后续将添加对更多数据类型的支持):
|
||||
|
||||
- 'd':事件的摘要(即测量文件的摘要),通过SHA1或MD5哈希算法计算;
|
||||
- 'n':事件的名称(即文件名),大小至多255字节;
|
||||
- 'd-ng':事件的摘要,通过任意哈希算法计算(字段格式:<hash algo>:digest);
|
||||
- 'd-ngv2':与d-ng相同,但以"ima"或"verity"摘要类型为前缀
|
||||
(字段格式:<digest type>:<hash algo>:digest);
|
||||
- 'd-modsig':不含附加modsig的事件摘要;
|
||||
- 'n-ng':事件的名称,没有大小限制;
|
||||
- 'sig':文件签名,基于文件的/文件系统验证的摘要[1],或EVM便携式签名,
|
||||
如果'security.ima'包含文件哈希;
|
||||
- 'modsig':附加的文件签名;
|
||||
- 'buf':用于生成哈希的缓冲区数据,没有大小限制;
|
||||
- 'evmsig':EVM便携式签名;
|
||||
- 'iuid':索引节点的UID;
|
||||
- 'igid':索引节点的GID;
|
||||
- 'imode':索引节点的模式;
|
||||
- 'xattrnames':xattr名称的列表(由``|``分隔),仅当xattr存在时;
|
||||
- 'xattrlengths':xattr长度的列表(u32),仅当xattr存在时;
|
||||
- 'xattrvalues':xattr值的列表;
|
||||
|
||||
|
||||
下面是已定义的模板描述符列表:
|
||||
|
||||
- "ima":其格式是 ``d|n`` ;
|
||||
- "ima-ng"(默认):其格式是 ``d-ng|n-ng`` ;
|
||||
- "ima-ngv2":其格式是 ``d-ngv2|n-ng`` ;
|
||||
- "ima-sig":其格式是 ``d-ng|n-ng|sig`` ;
|
||||
- "ima-sigv2":其格式是 ``d-ngv2|n-ng|sig`` ;
|
||||
- "ima-buf":其格式是 ``d-ng|n-ng|buf`` ;
|
||||
- "ima-modsig":其格式是 ``d-ng|n-ng|sig|d-modsig|modsig`` ;
|
||||
- "evm-sig":其格式是 ``d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode`` ;
|
||||
|
||||
|
||||
|
||||
使用
|
||||
====
|
||||
|
||||
要指定用于生成度量条目的模板描述符,目前支持以下方法:
|
||||
|
||||
- 从内核配置所支持模板描述符中选择一个模板描述符( ``ima-ng`` 是默认选择);
|
||||
- 通过 ``ima_template=`` 参数从内核命令行指定模板描述符名称;
|
||||
- 通过内核命令行参数 ``ima_template_fmt=`` 注册一个具有自定义格式的新模板描述符。
|
103
Documentation/translations/zh_CN/security/digsig.rst
Normal file
103
Documentation/translations/zh_CN/security/digsig.rst
Normal file
@ -0,0 +1,103 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/security/digsig.rst
|
||||
|
||||
:翻译:
|
||||
赵硕 Shuo Zhao <zhaoshuo@cqsoftware.com.cn>
|
||||
|
||||
===============
|
||||
数字签名验证API
|
||||
===============
|
||||
|
||||
:作者: Dmitry Kasatkin
|
||||
:日期: 2011.06.10
|
||||
|
||||
|
||||
.. 内容
|
||||
|
||||
1.介绍
|
||||
2.API
|
||||
3.用户空间工具
|
||||
|
||||
|
||||
介绍
|
||||
====
|
||||
|
||||
数字签名验证API提供了一种验证数字签名的方法。
|
||||
目前,数字签名被IMA/EVM完整性保护子系统使用。
|
||||
|
||||
数字签名验证是通过精简的GnuPG多精度整数(MPI)库的内核移植来实现的。
|
||||
该内核版本提供了内存分配错误处理,已根据内核编码风格进行重构,并修复
|
||||
了checkpatch.pl报告的错误和警告。
|
||||
|
||||
公钥和签名由头部和MPIs组成::
|
||||
|
||||
struct pubkey_hdr {
|
||||
uint8_t version; /* 密钥格式版本 */
|
||||
time_t timestamp; /* 密钥时间戳,目前为0 */
|
||||
uint8_t algo;
|
||||
uint8_t nmpi;
|
||||
char mpi[0];
|
||||
} __packed;
|
||||
|
||||
struct signature_hdr {
|
||||
uint8_t version; /* 签名格式版本 */
|
||||
time_t timestamp; /* 签名时间戳 */
|
||||
uint8_t algo;
|
||||
uint8_t hash;
|
||||
uint8_t keyid[8];
|
||||
uint8_t nmpi;
|
||||
char mpi[0];
|
||||
} __packed;
|
||||
|
||||
keyid等同对整个密钥的内容进行SHA1哈希运算后的第12到19字节。
|
||||
签名头部用于生成签名的输入。这种方法确保了密钥或签名头部无法更改。
|
||||
它保护时间戳不被更改,并可以用于回滚保护。
|
||||
|
||||
API
|
||||
===
|
||||
|
||||
目前API仅包含一个函数::
|
||||
|
||||
digsig_verify() - 使用公钥进行数字签名验证
|
||||
|
||||
/**
|
||||
* digsig_verify() - 使用公钥进行数字签名验证
|
||||
* @keyring: 查找密钥的密钥环
|
||||
* @sig: 数字签名
|
||||
* @sigen: 签名的长度
|
||||
* @data: 数据
|
||||
* @datalen: 数据的长度
|
||||
* @return: 成功时返回0,失败时返回 -EINVAL
|
||||
*
|
||||
* 验证数据相对于数字签名的完整性。
|
||||
* 目前仅支持RSA算法。
|
||||
* 通常将内容的哈希值作为此函数的数据。
|
||||
*
|
||||
*/
|
||||
int digsig_verify(struct key *keyring, const char *sig, int siglen,
|
||||
const char *data, int datalen);
|
||||
|
||||
用户空间工具
|
||||
============
|
||||
|
||||
签名和密钥管理实用工具evm-utils提供了生成签名、加载密钥到内核密钥环中的功能。
|
||||
密钥可以是PEM格式,或转换为内核格式。
|
||||
当把密钥添加到内核密钥环时,keyid定义该密钥的名称:下面的示例中为5D2B05FC633EE3E8。
|
||||
|
||||
以下是keyctl实用工具的示例输出::
|
||||
|
||||
$ keyctl show
|
||||
Session Keyring
|
||||
-3 --alswrv 0 0 keyring: _ses
|
||||
603976250 --alswrv 0 -1 \_ keyring: _uid.0
|
||||
817777377 --alswrv 0 0 \_ user: kmk
|
||||
891974900 --alswrv 0 0 \_ encrypted: evm-key
|
||||
170323636 --alswrv 0 0 \_ keyring: _module
|
||||
548221616 --alswrv 0 0 \_ keyring: _ima
|
||||
128198054 --alswrv 0 0 \_ keyring: _evm
|
||||
|
||||
$ keyctl list 128198054
|
||||
1 key in keyring:
|
||||
620789745: --alswrv 0 0 user: 5D2B05FC633EE3E8
|
34
Documentation/translations/zh_CN/security/index.rst
Normal file
34
Documentation/translations/zh_CN/security/index.rst
Normal file
@ -0,0 +1,34 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/security/index.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
赵岳辉 Yuehui Zhao <zhaoyuehui@cqsoftware.com.cn>
|
||||
|
||||
========
|
||||
安全文档
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
lsm
|
||||
siphash
|
||||
digsig
|
||||
landlock
|
||||
|
||||
TODOLIST:
|
||||
* credentials
|
||||
* snp-tdx-threat-model
|
||||
* IMA-templates
|
||||
* keys/index
|
||||
* lsm-development
|
||||
* sak
|
||||
* SCTP
|
||||
* self-protection
|
||||
* tpm/index
|
||||
* secrets/index
|
||||
* ipe
|
123
Documentation/translations/zh_CN/security/landlock.rst
Normal file
123
Documentation/translations/zh_CN/security/landlock.rst
Normal file
@ -0,0 +1,123 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. Copyright ? 2017-2020 Micka?l Salaün <mic@digikod.net>
|
||||
.. Copyright ? 2019-2020 ANSSI
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/security/landlock.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
毛玉贤 Yuxian Mao <maoyuxian@cqsoftware.com.cn>
|
||||
|
||||
======================
|
||||
Landlock LSM: 内核文档
|
||||
======================
|
||||
|
||||
:作者: Mickaël Salaün
|
||||
:日期: 2022年12月
|
||||
|
||||
Landlock的目标是创建有范围的访问控制(即沙箱机制)。为了增强整个
|
||||
系统的安全性,此功能应适用于任何进程,包括非特权进程。因为这些进
|
||||
程可能被攻击或植入后门(即不可信任的),所以从内核和其他进程的角
|
||||
度来看,Landlock的功能必须安全可用。因此,Landlock 的接口设计应当
|
||||
尽量减少可能的攻击点。
|
||||
|
||||
Landlock 旨在为非特权进程使用,同时遵循由其他访问控制机制(例如 DAC、LSM)
|
||||
强制执行的系统安全策略。Landlock 规则不应与系统上强制执行的其他访问
|
||||
控制相冲突,而只能添加额外的限制。
|
||||
|
||||
任何用户都可以在其进程上强制执行Landlock规则集。这些规则集会以一种
|
||||
确保只能添加更多约束的方式与继承的规则集合并和评估。
|
||||
|
||||
|
||||
用户空间文档如下:
|
||||
Documentation/userspace-api/landlock.rst.
|
||||
|
||||
安全访问控制机制指导原则
|
||||
========================
|
||||
|
||||
* Landlock规则应侧重于对内核对象的访问控制,而非系统调用过滤(即
|
||||
系统调用参数),后者是seccomp-bpf要侧重的。
|
||||
* 为了避免多种侧信道攻击(例如安全策略泄露、基于CPU的攻击),Landlock
|
||||
规则不应与用户空间进行程序化通信。
|
||||
* 内核访问检查不应降低未沙盒化进程的访问请求速度。
|
||||
* 与 Landlock 操作相关的计算(例如强制执行规则集)应仅影响请求这些
|
||||
操作的进程。
|
||||
* 由沙盒化进程直接从内核中获得的资源(例如文件描述符)在被任何进程
|
||||
使用时,都应保留其获取时的作用域访问权限。
|
||||
Cf. `文件描述符访问权限`_.
|
||||
|
||||
设计选择
|
||||
========
|
||||
|
||||
inode访问权限
|
||||
-------------
|
||||
|
||||
所有访问权限都与inode以及通过inode所访问到的内容相关。读取目录的
|
||||
内容并不意味着有权读取该目录中列出的 inode 所对应文件的内容。实际
|
||||
上,文件名是相对于其父目录而言的 ,一个 inode 可以通过多个文件名
|
||||
(通过硬链接)来引用。删除文件链接这一操作仅直接影响对应目录,而
|
||||
对被移除链接的inode并无影响。这就是“LANDLOCK_ACCESS_FS_REMOVE_FILE”
|
||||
(文件系统移除文件访问权限)或“LANDLOCK_ACCESS_FS_REFER” (文件系
|
||||
统引用访问权限)不能与文件绑定,而只能与目录绑定的原因。
|
||||
|
||||
文件描述符访问权限
|
||||
------------------
|
||||
|
||||
在打开文件时,会检查访问权限并将其与文件描述符绑定。其基本原则是,
|
||||
当在相同的 Landlock 域下执行时,等效的操作序列会产生相同的结果。
|
||||
以LANDLOCK_ACCESS_FS_TRUNCATE权限为例,如果相关的文件层次结构没有
|
||||
授予该访问权限,那么可能允许打开一个文件进行写操作,但不允许使用
|
||||
ftruncate调用截断由此产生的文件描述符。
|
||||
以下操作序列具有相同的语义,因此会产生相同的结果:
|
||||
|
||||
* ``truncate(path);``
|
||||
* ``int fd = open(path, O_WRONLY); ftruncate(fd); close(fd);``
|
||||
|
||||
与文件访问模式类似(例如O_RDWR),即使文件描述符在进程之间传递
|
||||
(例如通过Unix域套接字),文件描述符中的Landlock访问权限也会被保留。
|
||||
这些访问权限即使在接收进程未被 Landlock 沙盒化的情况下也会被强制执行。
|
||||
事实上,这是为了保持整个系统访问控制的一致性,避免通过文件描述符传递
|
||||
而无意中绕过安全限制(即“混淆代理攻击”)。
|
||||
|
||||
测试
|
||||
====
|
||||
|
||||
用户空间的向后兼容性测试、ptrace 限制测试和文件系统支持测试可以在这里
|
||||
找到:tools/testing/selftests/landlock/
|
||||
|
||||
内核结构
|
||||
========
|
||||
|
||||
对象
|
||||
----
|
||||
|
||||
该API在以下内核代码中:
|
||||
|
||||
security/landlock/object.h
|
||||
|
||||
文件系统
|
||||
--------
|
||||
|
||||
该API在以下内核代码中:
|
||||
|
||||
security/landlock/fs.h
|
||||
|
||||
规则集和域
|
||||
----------
|
||||
|
||||
域是与一组主体(即任务凭证)关联的只读规则集。每次在任务上执行规则集时,
|
||||
都会复制当前域,并在新域中导入规则集作为新的规则层。 事实上,一旦进入
|
||||
一个域,每条规则都与一个层级绑定。要授予对对象的访问权限,每一层中至少
|
||||
有一条规则必须允许对该对象执行请求操作。然后,任务只能过渡到一个新的域,
|
||||
该新域是当前域的约束和任务提供的规则集的约束的交集。任务自行沙盒化时,
|
||||
主体的定义是隐式的,这使得推理变得更加简单,并有助于避免陷阱。
|
||||
|
||||
该API在以下内核代码中:
|
||||
|
||||
security/landlock/ruleset.h
|
||||
|
||||
.. Links
|
||||
.. _tools/testing/selftests/landlock/:
|
||||
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/landlock/
|
95
Documentation/translations/zh_CN/security/lsm.rst
Normal file
95
Documentation/translations/zh_CN/security/lsm.rst
Normal file
@ -0,0 +1,95 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/security/lsm.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
赵岳辉 Yuehui Zhao <zhaoyuehui@cqsoftware.com.cn>
|
||||
|
||||
================================
|
||||
Linux安全模块:Linux通用安全钩子
|
||||
================================
|
||||
|
||||
:作者: Stephen Smalley
|
||||
:作者: Timothy Fraser
|
||||
:作者: Chris Vance
|
||||
|
||||
.. note::
|
||||
|
||||
本文中描述的api已经过时了。
|
||||
|
||||
介绍
|
||||
====
|
||||
|
||||
在2001年3月,美国国家安全局(NSA)在2.5 Linux内核峰会上做了一个关于安全
|
||||
增强Linux(SELinux)的报告。SELinux是Linux内核中一种实现灵活且细粒度的非
|
||||
自主访问控制,最初作为自己特定的内核补丁实现。其他一些安全项目(例如RSBAC、
|
||||
Medusa)也为Linux内核开发了灵活的访问控制架构,并且多个项目为Linux开发了
|
||||
特定的访问控制模型(例如LIDS、DTE、SubDomain)。每个项目都开发并维护了自
|
||||
己的内核补丁,以支持其安全需求。
|
||||
|
||||
针对美国国家安全局的报告,Linus Torvalds发表了一系列言论,描述了一个他愿
|
||||
意考虑纳入主流Linux内核的安全框架。他描述了一个通用的框架,该框架将提供
|
||||
一组安全钩子来控制对内核对象的操作,同时在内核数据结构中提供一组不透明的
|
||||
安全域来维护安全属性。这个框架可以被可加载的内核模块用来实现任何所需的安
|
||||
全模型。Linus还提出了将Linux权能代码迁移到这样一个模块中的可能性。
|
||||
|
||||
Linux安全模块(LSM)项目是由WireX发起开发的这样一个框架。LSM是几个安全
|
||||
项目共同开发的成果,包括immununix、SELinux、SGI和Janus,以及包括
|
||||
Greg Kroah-Hartman和James Morris在内的几个人,来开发一个实现这一框架的
|
||||
Linux内核补丁。这项工作在2003年12月被纳入主流内核。此技术报告概述了该框
|
||||
架和权能安全模块的内容。
|
||||
|
||||
LSM框架
|
||||
=======
|
||||
|
||||
LSM框架提供了一个通用的内核框架来支持安全模块。特别地,LSM框架主要关注
|
||||
支持访问控制模块,尽管未来的开发可能会解决其他安全需求,比如沙箱。就其
|
||||
本身而言,框架不提供任何额外的安全;它仅提供了支持安全模块的基础架构。
|
||||
LSM框架是可选的,要求开启 `CONFIG_SECURITY` 配置。权能逻辑作为一个安全
|
||||
模块被实现。该权能模块将在 `LSM权能模块`_ 一节中进一步讨论。
|
||||
|
||||
LSM框架在内核数据结构中包含安全域,并在内核代码的关键点调用钩子函数来
|
||||
管理这些安全域并执行访问控制。它还增加了注册安全模块的函数。接口
|
||||
/sys/kernel/security/lsm记录了一个以逗号分隔的安全模块列表,这些模块在
|
||||
系统中是激活的。
|
||||
|
||||
LSM安全域只是 ``void*`` 指针。数据被称为blob,这些数据可以由框架或使用
|
||||
它的各个安全模块进行管理。多个安全模块共同使用的安全blob通常由框架管理。
|
||||
对于进程和程序执行的安全信息,安全域包含在 :c:type:
|
||||
`struct task_struct <task_struct>` 和 :c:type: `struct cred <cred>` 中。
|
||||
对于文件系统的安全信息,安全域包含在 :c:type:
|
||||
`struct super_block <super_block>` 中。对于管道、文件和套接字的安全信息,
|
||||
安全域包含在 :c:type: `struct inode <inode>` 和 :c:type: `struct file <file>`
|
||||
中。对于System V IPC的安全信息,安全域被添加到 :c:type:
|
||||
`struct kern_ipc_perm <kern_ipc_perm>` 和 :c:type: `struct msg_msg <msg_msg>`
|
||||
中;另外,:c:type: `struct msg_msg <msg_msg>` 、struct msg_queue和
|
||||
struct shmid_kernel的定义被移动到头文件中( ``include/linux/msg.h`` 和
|
||||
``include/linux/shm.h`` 视情况而定),以允许安全模块使用这些定义。
|
||||
|
||||
对于数据包和网络设备的安全信息,安全域被添加到 :c:type:
|
||||
`struct sk_buff <sk_buff>` 和 :c:type: `struct scm_cookie <scm_cookie>` 中。
|
||||
与其他安全模块数据不同,这里使用的数据是一个32位整数。安全模块需要将这些值
|
||||
进行映射或关联到真正的安全属性。
|
||||
|
||||
LSM钩子被维护在链表中。每个钩子函数都维护一个链表,这些钩子按照CONFIG_LSM中
|
||||
指定的顺序被调用。每个钩子的详细文档都包含在 `security/security.c` 源文件中。
|
||||
|
||||
LSM框架提供了一种近似通用的安全模块堆栈。它定义了security_add_hooks(),每个安
|
||||
全模块向它传递一个 :c:type: `struct security_hooks_list <security_hooks_list>`
|
||||
,该结构会被添加到链表中。LSM框架没有提供移除已注册钩子的机制。SELinux安全
|
||||
模块已经实现了一种移除自身的方法,然而该特性已被弃用。
|
||||
|
||||
这些钩子可以分为两大类:用于管理安全域的钩子和用于执行访问控制的钩子。
|
||||
第一类钩子的示例包括security_inode_alloc()和security_inode_free(),这些
|
||||
钩子用于为inode对象分配和释放安全结构。第二类钩子的示例是
|
||||
security_inode_permission()钩子,该钩子在访问inode时检查权限。
|
||||
|
||||
LSM权能模块
|
||||
===========
|
||||
|
||||
POSIX.1e 权能逻辑作为一个安全模块维护,存储在文件 ``security/commoncap.c``
|
||||
中。权能模块使用 :c:type: `lsm_info` 描述中的order域来标识它为第一个注册
|
||||
的安全模块。与其他模块不同,权能安全模块不使用通用的安全blob。其原因是历史
|
||||
性的,主要基于开销、复杂性和性能的考虑。
|
195
Documentation/translations/zh_CN/security/siphash.rst
Normal file
195
Documentation/translations/zh_CN/security/siphash.rst
Normal file
@ -0,0 +1,195 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
:Original: Documentation/security/siphash.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
张巍 zhangwei <zhangwei@cqsoftware.com.cn>
|
||||
|
||||
=====================================
|
||||
SipHash - 一种短输入伪随机函数(PRF)
|
||||
=====================================
|
||||
|
||||
:作者: Jason A.Donenfeld <jason@zx2c4.com>
|
||||
|
||||
SipHash是一种加密安全的伪随机函数,即一种用于生成伪随机密钥的哈
|
||||
希函数,因为其在处理短输入时表现出色,因此得名。其由密码学家
|
||||
Daniel J. Bernstein和Jean-Philippe Aumasson设计。目的主要是替
|
||||
代其他哈希函数,例如:jhash,md5_transform,sha1_transform等。
|
||||
|
||||
SipHash采用一个完全由随机数生成的密钥,以及一个输入缓冲区或者
|
||||
多个输入整数,它输出一个与随机数难以区分的整数,你可以将它作
|
||||
为安全序列、安全cookies的一部分,或者对其进行掩码处理,以便在
|
||||
哈希表中使用。
|
||||
|
||||
生成密钥
|
||||
========
|
||||
|
||||
密钥应来源于加密安全的随机数生成,要么使用get random bytes
|
||||
要么使用get random once::
|
||||
|
||||
siphash_key_t key;
|
||||
get_random_bytes(&key, sizeof(key));
|
||||
|
||||
如果你的密钥来源不是这两个,那么你的做法是错的。
|
||||
|
||||
使用函数
|
||||
========
|
||||
|
||||
这个函数有两个变种,一种是接受整数列表,另一种是接受缓冲区::
|
||||
|
||||
u64 siphash(const void *data, size_t len, const siphash_key_t *key);
|
||||
|
||||
和::
|
||||
|
||||
u64 siphash_1u64(u64, const siphash_key_t *key);
|
||||
u64 siphash_2u64(u64, u64, const siphash_key_t *key);
|
||||
u64 siphash_3u64(u64, u64, u64, const siphash_key_t *key);
|
||||
u64 siphash_4u64(u64, u64, u64, u64, const siphash_key_t *key);
|
||||
u64 siphash_1u32(u32, const siphash_key_t *key);
|
||||
u64 siphash_2u32(u32, u32, const siphash_key_t *key);
|
||||
u64 siphash_3u32(u32, u32, u32, const siphash_key_t *key);
|
||||
u64 siphash_4u32(u32, u32, u32, u32, const siphash_key_t *key);
|
||||
|
||||
如果向一个通用的hsiphash函数传递一个恒定长度的常量,他将
|
||||
在编译的时候将常量折叠,并自动选择一个优化后的函数。
|
||||
|
||||
哈希表键函数的用法::
|
||||
|
||||
struct some_hashtable {
|
||||
DECLARE_HASHTABLE(hashtable, 8);
|
||||
siphash_key_t key;
|
||||
};
|
||||
|
||||
void init_hashtable(struct some_hashtable *table)
|
||||
{
|
||||
get_random_bytes(&table->key, sizeof(table->key));
|
||||
}
|
||||
|
||||
static inline hlist_head *some_hashtable_bucket(struct some_hashtable *table, struct interesting_input *input)
|
||||
{
|
||||
return &table->hashtable[siphash(input, sizeof(*input), &table->key) & (HASH_SIZE(table->hashtable) - 1)];
|
||||
}
|
||||
|
||||
然后,你可以像往常一样对返回的哈希存储桶进行迭代。
|
||||
|
||||
安全性
|
||||
======
|
||||
|
||||
SipHash有着非常高的安全性,因为其有128位的密钥。只要密钥是保密的,
|
||||
即使攻击者看到多个输出,也无法猜测出函数的正确输出,因为2^128次
|
||||
方个输出是非常庞大的。
|
||||
|
||||
Linux实现了SipHash的“2-4”变体
|
||||
|
||||
Struct-passing陷阱
|
||||
==================
|
||||
|
||||
通常情况下,XuY函数的输出长度不够大,因此你可能需要传递一个预填充
|
||||
的结构体给SipHash,在这样做时,务必确保结构体没有填充空隙,最简单
|
||||
的方法就是将结构体的成员按照大小降序的方式排序,并且使用offsetofend()
|
||||
函数代替sizeof()来获取结构体大小,出于性能的考虑,如果可以的话,最
|
||||
好将结构体按右边界对齐,示例如下::
|
||||
|
||||
const struct {
|
||||
struct in6_addr saddr;
|
||||
u32 counter;
|
||||
u16 dport;
|
||||
} __aligned(SIPHASH_ALIGNMENT) combined = {
|
||||
.saddr = *(struct in6_addr *)saddr,
|
||||
.counter = counter,
|
||||
.dport = dport
|
||||
};
|
||||
u64 h = siphash(&combined, offsetofend(typeof(combined), dport), &secret);
|
||||
|
||||
资源
|
||||
====
|
||||
|
||||
如果你有兴趣了解更多信息,请阅读SipHash论文:
|
||||
https://131002.net/siphash/siphash.pdf
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
===========================================
|
||||
HalfSipHash 是 SipHash 的一个较不安全的变种
|
||||
===========================================
|
||||
|
||||
:作者: Jason A.Donenfeld <jason@zx2c4.com>
|
||||
|
||||
如果你认为SipHash的速度不够快,无法满足你的需求,那么你可以
|
||||
使用HalfSipHash,这是一种令人担忧但是有用的选择。HalfSipHash
|
||||
将SipHash的轮数从“2-4”降低到“1-3”,更令人担心的是,它使用一
|
||||
个容易被穷举攻击的64位密钥(输出为32位),而不是SipHash的128位
|
||||
密钥,不过,这对于要求高性能“jhash”用户来说这是比较好的选择。
|
||||
|
||||
HalfSipHash是通过 "hsiphash" 系列函数提供的。
|
||||
|
||||
.. warning::
|
||||
绝对不要在作为哈希表键函数之外使用hsiphash函数,只有在你
|
||||
能完全能确定输出永远不会从内核传输出去的情况下才能使用,
|
||||
作为缓解哈希表泛洪拒绝服务攻击的一种手段,它仅在某些情况
|
||||
下比jhash好用。
|
||||
|
||||
在64位的内核中,hsiphash函数实际上实现的是SipHash-1-3,这是一
|
||||
种减少轮数的SipHash变形,而不是HalfSipHash-1-3。这是因为在64位
|
||||
代码中SipHash-1-3的性能与HalfSipHash-1-3相当,甚至可能更快,请
|
||||
注意,这并不意味这在64位的内核中,hsihpash函数与siphash函数相
|
||||
同,也不意味着他们是安全的;hsihash函数仍然使用一种不太安全的
|
||||
减少轮数的算法,并将输出截断为32位。
|
||||
|
||||
生成哈希密钥
|
||||
============
|
||||
|
||||
密钥应始终来源于加密安全的随机数生成,要么使用get random bytes
|
||||
要么使用get random once::
|
||||
|
||||
hsiphash_key_t key;
|
||||
get_random_bytes(&key, sizeof(key));
|
||||
|
||||
如果你的钥匙来源不是这两个,那么你的做法是错的。
|
||||
|
||||
使用哈希函数
|
||||
============
|
||||
|
||||
这个函数有两种变体,一个是接受整数列表,另一种是接受缓冲区::
|
||||
|
||||
u32 hsiphash(const void *data, size_t len, const hsiphash_key_t *key);
|
||||
|
||||
和::
|
||||
|
||||
u32 hsiphash_1u32(u32, const hsiphash_key_t *key);
|
||||
u32 hsiphash_2u32(u32, u32, const hsiphash_key_t *key);
|
||||
u32 hsiphash_3u32(u32, u32, u32, const hsiphash_key_t *key);
|
||||
u32 hsiphash_4u32(u32, u32, u32, u32, const hsiphash_key_t *key);
|
||||
|
||||
如果向一个通用的hsiphash函数传递一个恒定长度的常量,他将在编译
|
||||
的时候将常量折叠,并自动选择一个优化后的函数。
|
||||
|
||||
哈希表键函数的用法
|
||||
==================
|
||||
|
||||
::
|
||||
|
||||
struct some_hashtable {
|
||||
DECLARE_HASHTABLE(hashtable, 8);
|
||||
hsiphash_key_t key;
|
||||
};
|
||||
|
||||
void init_hashtable(struct some_hashtable *table)
|
||||
{
|
||||
get_random_bytes(&table->key, sizeof(table->key));
|
||||
}
|
||||
|
||||
static inline hlist_head *some_hashtable_bucket(struct some_hashtable *table, struct interesting_input *input)
|
||||
{
|
||||
return &table->hashtable[hsiphash(input, sizeof(*input), &table->key) & (HASH_SIZE(table->hashtable) - 1)];
|
||||
}
|
||||
|
||||
然后,你可以像往常一样对返回的哈希存储桶进行迭代。
|
||||
|
||||
性能
|
||||
====
|
||||
|
||||
hsiphash()大约比jhash()慢三倍,这是因为有许多替换,不过这些都不是问题,
|
||||
因为哈希表查找不是瓶颈。而且,这些牺牲是为了hsiphash()的安全性和DoS抗
|
||||
性,这是值得的。
|
@ -88,6 +88,7 @@ TODOList:
|
||||
cpu-freq/index
|
||||
iio/index
|
||||
virt/index
|
||||
security/index
|
||||
PCI/index
|
||||
peci/index
|
||||
|
||||
@ -102,7 +103,6 @@ TODOList:
|
||||
* watchdog/index
|
||||
* hwmon/index
|
||||
* accel/index
|
||||
* security/index
|
||||
* crypto/index
|
||||
* bpf/index
|
||||
* usb/index
|
||||
|
@ -60,24 +60,24 @@ CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 必須是以 16 進制數寫入。
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
在 x86 架構上
|
||||
你可以按下鍵盤組合鍵 :kbd:`ALT-SysRq-<command key>`。
|
||||
你可以按下鍵盤組合鍵 `ALT-SysRq-<command key>`。
|
||||
|
||||
.. note::
|
||||
一些鍵盤可能沒有標識 'SySRq' 鍵。'SySRq' 鍵也被當做 'Print Screen'鍵。
|
||||
同時有些鍵盤無法處理同時按下這麼多鍵,因此你可以先按下鍵盤 :kbd:`Alt` 鍵,
|
||||
然後按下鍵盤 :kbd:`SysRq` 鍵,再釋放鍵盤 :kbd:`SysRq` 鍵,之後按下鍵盤上命令鍵
|
||||
:kbd:`<command key>`,最後釋放所有鍵。
|
||||
同時有些鍵盤無法處理同時按下這麼多鍵,因此你可以先按下鍵盤 `Alt` 鍵,
|
||||
然後按下鍵盤 `SysRq` 鍵,再釋放鍵盤 `SysRq` 鍵,之後按下鍵盤上命令鍵
|
||||
`<command key>`,最後釋放所有鍵。
|
||||
|
||||
在 SPARC 架構上
|
||||
你可以按下鍵盤組合鍵 :kbd:`ALT-STOP-<command key>` 。
|
||||
你可以按下鍵盤組合鍵 `ALT-STOP-<command key>` 。
|
||||
|
||||
在串行控制檯(只針對 PC 類型的標準串口)
|
||||
你可以發一個 ``BREAK`` ,然後在 5 秒內發送一個命令鍵,
|
||||
發送 ``BREAK`` 兩次將被翻譯爲一個正常的 BREAK 操作。
|
||||
|
||||
在 PowerPC 架構上
|
||||
按下鍵盤組合鍵 :kbd:`ALT - Print Screen` (或者 :kbd:`F13`) - :kbd:`<命令鍵>` 。
|
||||
:kbd:`Print Screen` (或者 :kbd:`F13`) - :kbd:`<命令鍵>` 或許也能實現。
|
||||
按下鍵盤組合鍵 `ALT - Print Screen` (或者 `F13`) - `<命令鍵>` 。
|
||||
`Print Screen` (或者 `F13`) - `<命令鍵>` 或許也能實現。
|
||||
|
||||
在其他架構上
|
||||
如果你知道其他架構的組合鍵,請告訴我,我可以把它們添加到這部分。
|
||||
@ -87,7 +87,7 @@ CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 必須是以 16 進制數寫入。
|
||||
|
||||
echo t > /proc/sysrq-trigger
|
||||
|
||||
這個命令鍵 :kbd:`<command key>` 是區分大小寫的。
|
||||
這個命令鍵 `<command key>` 是區分大小寫的。
|
||||
|
||||
什麼是命令鍵?
|
||||
~~~~~~~~~~~~~~
|
||||
@ -203,8 +203,8 @@ syslogd/klogd 進程是運行的,它們仍將被記錄。)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
這也會發生在我這,我發現輕敲鍵盤兩側的 shift、alt 和 control 鍵,然後再次敲擊
|
||||
一個無效的 SysRq 鍵序列可以解決問題。(比如,像鍵盤組合鍵 :kbd:`alt-sysrq-z` )
|
||||
切換到另一個虛擬控制檯(鍵盤操作 :kbd:`ALT+Fn` ),然後再切回來應該也有幫助。
|
||||
一個無效的 SysRq 鍵序列可以解決問題。(比如,像鍵盤組合鍵 `alt-sysrq-z` )
|
||||
切換到另一個虛擬控制檯(鍵盤操作 `ALT+Fn` ),然後再切回來應該也有幫助。
|
||||
|
||||
我敲擊了 SysRq 鍵,但像是什麼都沒發生,發生了什麼錯誤?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -259,7 +259,7 @@ SysRq 鍵的輸出和所有其他控制檯輸出一樣,受制於控制檯日
|
||||
文件的消費訪問到。作爲一個特例,來自 sysrq 命令的標題行將被傳遞給所有控制檯
|
||||
使用者,就好像當前日誌級別是最大的一樣。如果只發出標題頭,則幾乎可以肯定內核日誌
|
||||
級別太低。如果你需要控制檯上的輸出,那麼你將需要臨時提高控制檯日誌級別,通過使用
|
||||
鍵盤組合鍵 :kbd:`alt-sysrq-8` 或者::
|
||||
鍵盤組合鍵 `alt-sysrq-8` 或者::
|
||||
|
||||
echo 8 > /proc/sysrq-trigger
|
||||
|
||||
|
@ -86,7 +86,7 @@ Alpine (TUI)
|
||||
- :menuselection:`Do Not Send Flowed Text` 必須開啓
|
||||
- :menuselection:`Strip Whitespace Before Sending` 必須關閉
|
||||
|
||||
當寫郵件時,光標應該放在補丁會出現的地方,然後按下 :kbd:`CTRL-R` 組合鍵,使指
|
||||
當寫郵件時,光標應該放在補丁會出現的地方,然後按下 `CTRL-R` 組合鍵,使指
|
||||
定的補丁文件嵌入到郵件中。
|
||||
|
||||
Claws Mail (GUI)
|
||||
@ -94,7 +94,7 @@ Claws Mail (GUI)
|
||||
|
||||
可以用,有人用它成功地發過補丁。
|
||||
|
||||
用 :menuselection:`Message-->Insert File` (:kbd:`CTRL-I`) 或外置編輯器插入補丁。
|
||||
用 :menuselection:`Message-->Insert File` (`CTRL-I`) 或外置編輯器插入補丁。
|
||||
|
||||
若要在Claws編輯窗口重修改插入的補丁,需關閉
|
||||
:menuselection:`Configuration-->Preferences-->Compose-->Wrapping`
|
||||
@ -106,11 +106,11 @@ Evolution (GUI)
|
||||
一些開發者成功的使用它發送補丁。
|
||||
|
||||
撰寫郵件時:
|
||||
從 :menuselection:`格式-->段落樣式-->預格式化` (:kbd:`CTRL-7`)
|
||||
從 :menuselection:`格式-->段落樣式-->預格式化` (`CTRL-7`)
|
||||
或工具欄選擇 :menuselection:`預格式化` ;
|
||||
|
||||
然後使用:
|
||||
:menuselection:`插入-->文本文件...` (:kbd:`ALT-N x`) 插入補丁文件。
|
||||
:menuselection:`插入-->文本文件...` (`ALT-N x`) 插入補丁文件。
|
||||
|
||||
你還可以 ``diff -Nru old.c new.c | xclip`` ,選擇 :menuselection:`預格式化` ,
|
||||
然後使用鼠標中鍵進行粘帖。
|
||||
|
@ -5577,7 +5577,7 @@ KVM_XEN_ATTR_TYPE_SHARED_INFO_HVA
|
||||
in guest physical address space. This attribute should be used in
|
||||
preference to KVM_XEN_ATTR_TYPE_SHARED_INFO as it avoids
|
||||
unnecessary invalidation of an internal cache when the page is
|
||||
re-mapped in guest physcial address space.
|
||||
re-mapped in guest physical address space.
|
||||
|
||||
Setting the hva to zero will disable the shared_info page.
|
||||
|
||||
|
@ -12844,7 +12844,7 @@ L: kgdb-bugreport@lists.sourceforge.net
|
||||
S: Maintained
|
||||
W: http://kgdb.wiki.kernel.org/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb.git
|
||||
F: Documentation/dev-tools/kgdb.rst
|
||||
F: Documentation/process/debugging/kgdb.rst
|
||||
F: drivers/misc/kgdbts.c
|
||||
F: drivers/tty/serial/kgdboc.c
|
||||
F: include/linux/kdb.h
|
||||
|
@ -46,18 +46,18 @@ static inline void kref_get(struct kref *kref)
|
||||
}
|
||||
|
||||
/**
|
||||
* kref_put - decrement refcount for object.
|
||||
* @kref: object.
|
||||
* @release: pointer to the function that will clean up the object when the
|
||||
* kref_put - Decrement refcount for object
|
||||
* @kref: Object
|
||||
* @release: Pointer to the function that will clean up the object when the
|
||||
* last reference to the object is released.
|
||||
* This pointer is required, and it is not acceptable to pass kfree
|
||||
* in as this function.
|
||||
*
|
||||
* Decrement the refcount, and if 0, call release().
|
||||
* Return 1 if the object was removed, otherwise return 0. Beware, if this
|
||||
* function returns 0, you still can not count on the kref from remaining in
|
||||
* memory. Only use the return value if you want to see if the kref is now
|
||||
* gone, not present.
|
||||
* Decrement the refcount, and if 0, call @release. The caller may not
|
||||
* pass NULL or kfree() as the release function.
|
||||
*
|
||||
* Return: 1 if this call removed the object, otherwise return 0. Beware,
|
||||
* if this function returns 0, another caller may have removed the object
|
||||
* by the time this function returns. The return value is only certain
|
||||
* if you want to see if the object is definitely released.
|
||||
*/
|
||||
static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
|
||||
{
|
||||
@ -68,17 +68,37 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* kref_put_mutex - Decrement refcount for object
|
||||
* @kref: Object
|
||||
* @release: Pointer to the function that will clean up the object when the
|
||||
* last reference to the object is released.
|
||||
* @mutex: Mutex which protects the release function.
|
||||
*
|
||||
* This variant of kref_lock() calls the @release function with the @mutex
|
||||
* held. The @release function will release the mutex.
|
||||
*/
|
||||
static inline int kref_put_mutex(struct kref *kref,
|
||||
void (*release)(struct kref *kref),
|
||||
struct mutex *lock)
|
||||
struct mutex *mutex)
|
||||
{
|
||||
if (refcount_dec_and_mutex_lock(&kref->refcount, lock)) {
|
||||
if (refcount_dec_and_mutex_lock(&kref->refcount, mutex)) {
|
||||
release(kref);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* kref_put_lock - Decrement refcount for object
|
||||
* @kref: Object
|
||||
* @release: Pointer to the function that will clean up the object when the
|
||||
* last reference to the object is released.
|
||||
* @lock: Spinlock which protects the release function.
|
||||
*
|
||||
* This variant of kref_lock() calls the @release function with the @lock
|
||||
* held. The @release function will release the lock.
|
||||
*/
|
||||
static inline int kref_put_lock(struct kref *kref,
|
||||
void (*release)(struct kref *kref),
|
||||
spinlock_t *lock)
|
||||
@ -94,8 +114,6 @@ static inline int kref_put_lock(struct kref *kref,
|
||||
* kref_get_unless_zero - Increment refcount for object unless it is zero.
|
||||
* @kref: object.
|
||||
*
|
||||
* Return non-zero if the increment succeeded. Otherwise return 0.
|
||||
*
|
||||
* This function is intended to simplify locking around refcounting for
|
||||
* objects that can be looked up from a lookup structure, and which are
|
||||
* removed from that lookup structure in the object destructor.
|
||||
@ -105,6 +123,8 @@ static inline int kref_put_lock(struct kref *kref,
|
||||
* With a lookup followed by a kref_get_unless_zero *with return value check*
|
||||
* locking in the kref_put path can be deferred to the actual removal from
|
||||
* the lookup structure and RCU lookups become trivial.
|
||||
*
|
||||
* Return: non-zero if the increment succeeded. Otherwise return 0.
|
||||
*/
|
||||
static inline int __must_check kref_get_unless_zero(struct kref *kref)
|
||||
{
|
||||
|
@ -320,7 +320,7 @@ struct serial_struct;
|
||||
*
|
||||
* @poll_init: ``int ()(struct tty_driver *driver, int line, char *options)``
|
||||
*
|
||||
* kgdboc support (Documentation/dev-tools/kgdb.rst). This routine is
|
||||
* kgdboc support (Documentation/process/debugging/kgdb.rst). This routine is
|
||||
* called to initialize the HW for later use by calling @poll_get_char or
|
||||
* @poll_put_char.
|
||||
*
|
||||
|
@ -433,7 +433,7 @@ config GDB_SCRIPTS
|
||||
build directory. If you load vmlinux into gdb, the helper
|
||||
scripts will be automatically imported by gdb as well, and
|
||||
additional functions are available to analyze a Linux kernel
|
||||
instance. See Documentation/dev-tools/gdb-kernel-debugging.rst
|
||||
instance. See Documentation/process/debugging/gdb-kernel-debugging.rst
|
||||
for further details.
|
||||
|
||||
endif # DEBUG_INFO
|
||||
|
@ -19,7 +19,7 @@ menuconfig KGDB
|
||||
CONFIG_FRAME_POINTER to aid in producing more reliable stack
|
||||
backtraces in the external debugger. Documentation of
|
||||
kernel debugger is available at http://kgdb.sourceforge.net
|
||||
as well as in Documentation/dev-tools/kgdb.rst. If
|
||||
as well as in Documentation/process/debugging/kgdb.rst. If
|
||||
unsure, say N.
|
||||
|
||||
if KGDB
|
||||
|
@ -275,8 +275,9 @@ EXPORT_SYMBOL(match_hex);
|
||||
*
|
||||
* Description: Parse the string @str to check if matches wildcard
|
||||
* pattern @pattern. The pattern may contain two types of wildcards:
|
||||
* '*' - matches zero or more characters
|
||||
* '?' - matches one character
|
||||
*
|
||||
* * '*' - matches zero or more characters
|
||||
* * '?' - matches one character
|
||||
*
|
||||
* Return: If the @str matches the @pattern, return true, else return false.
|
||||
*/
|
||||
|
@ -3220,7 +3220,7 @@ sub process {
|
||||
my $tag_case = not ($tag eq "Fixes:");
|
||||
my $tag_space = not ($line =~ /^fixes:? [0-9a-f]{5,40} ($balanced_parens)/i);
|
||||
|
||||
my $id_length = not ($orig_commit =~ /^[0-9a-f]{12}$/i);
|
||||
my $id_length = not ($orig_commit =~ /^[0-9a-f]{12,40}$/i);
|
||||
my $id_case = not ($orig_commit !~ /[A-F]/);
|
||||
|
||||
my $id = "0123456789ab";
|
||||
|
@ -2085,7 +2085,7 @@ sub process_name($$) {
|
||||
# Look for foo() or static void foo() - description; or misspelt
|
||||
# identifier
|
||||
elsif (/^$decl_start$fn_type?(\w+)\s*$parenthesis?\s*$decl_end?$/ ||
|
||||
/^$decl_start$fn_type?(\w+.*)$parenthesis?\s*$decl_end$/) {
|
||||
/^$decl_start$fn_type?(\w+[^-:]*)$parenthesis?\s*$decl_end$/) {
|
||||
$identifier = $1;
|
||||
$decl_type = 'function';
|
||||
$identifier =~ s/^define\s+//;
|
||||
|
Loading…
x
Reference in New Issue
Block a user