Merge branch 'docs-next' of git://git.lwn.net/linux.git

# Conflicts:
#	scripts/checkpatch.pl
This commit is contained in:
Stephen Rothwell 2025-01-13 11:00:58 +11:00
commit 6b432139e5
62 changed files with 2864 additions and 450 deletions

View File

@ -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;

View File

@ -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'.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View 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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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,13 +808,13 @@ 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
to identify the contents of data; the len is the length of data
@ -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

View File

@ -53,6 +53,7 @@ Library functionality that is used throughout the kernel.
floating-point
union_find
min_heap
parser
Low level entry and exit
========================

View File

@ -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

View 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:

View File

@ -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
============================================

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -11,6 +11,8 @@ general guides
:maxdepth: 1
driver_development_debugging_guide
gdb-kernel-debugging
kgdb
userspace_debugging_guide
.. only:: subproject and html

View File

@ -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 %

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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ó.

View File

@ -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!

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:`预格式化`
然后使用鼠标中键进行粘帖。

View 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=`` 注册一个具有自定义格式的新模板描述符。

View 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

View 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

View 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/

View 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内核峰会上做了一个关于安全
增强LinuxSELinux的报告。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。其原因是历史
性的,主要基于开销、复杂性和性能的考虑。

View 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设计。目的主要是替
代其他哈希函数例如jhashmd5_transformsha1_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抗
性,这是值得的。

View File

@ -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

View File

@ -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

View File

@ -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:`預格式化`
然後使用鼠標中鍵進行粘帖。

View File

@ -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.

View File

@ -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

View File

@ -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)
{

View File

@ -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.
*

View File

@ -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

View File

@ -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

View File

@ -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.
*/

View File

@ -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";

View File

@ -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+//;