* Re: [PATCH v3 1/2] dt-bindings: iio: dac: Add AD5529R
From: Jonathan Cameron @ 2026-06-14 19:44 UTC (permalink / raw)
To: Janani Sunil
Cc: Rodrigo Alencar, Janani Sunil, Lars-Peter Clausen,
Michael Hennerich, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Philipp Zabel,
Jonathan Corbet, Shuah Khan, linux-iio, devicetree, linux-kernel,
linux-doc, Mark Brown
In-Reply-To: <603473ac-30e6-45e5-8a3b-c9902715cc9e@gmail.com>
On Tue, 9 Jun 2026 16:47:23 +0200
Janani Sunil <jan.sun97@gmail.com> wrote:
> On 5/26/26 15:11, Rodrigo Alencar wrote:
> > On 26/05/19 05:42PM, Janani Sunil wrote:
> >> Devicetree bindings for AD5529R 16 channel 12/16 bit high voltage,
> >> buffered voltage output digital-to-analog converter (DAC) with an
> >> integrated precision reference.
> > ...
> > Probably others may comment on that, but...
> >
> > This parent node may support device addressing for multi-device support through
> > those ID pins. I suppose that each device may have its own power supplies or
> > other resources like the toggle pins or reset and enable.
> >
> > That way I suppose that an example would look like...
> >
> >> +
> >> +patternProperties:
> >> + "^channel@([0-9]|1[0-5])$":
> >> + type: object
> >> + description: Child nodes for individual channel configuration
> >> +
> >> + properties:
> >> + reg:
> >> + description: Channel number.
> >> + minimum: 0
> >> + maximum: 15
> >> +
> >> + adi,output-range-microvolt:
> >> + description: |
> >> + Output voltage range for this channel as [min, max] in microvolts.
> >> + If not specified, defaults to 0V to 5V range.
> >> + oneOf:
> >> + - items:
> >> + - const: 0
> >> + - enum: [5000000, 10000000, 20000000, 40000000]
> >> + - items:
> >> + - const: -5000000
> >> + - const: 5000000
> >> + - items:
> >> + - const: -10000000
> >> + - const: 10000000
> >> + - items:
> >> + - const: -15000000
> >> + - const: 15000000
> >> + - items:
> >> + - const: -20000000
> >> + - const: 20000000
> >> +
> >> + required:
> >> + - reg
> >> +
> >> + additionalProperties: false
> >> +
> >> +required:
> >> + - compatible
> >> + - reg
> >> + - vdd-supply
> >> + - avdd-supply
> >> + - hvdd-supply
> >> +
> >> +dependencies:
> >> + spi-cpha: [ spi-cpol ]
> >> + spi-cpol: [ spi-cpha ]
> >> +
> >> +allOf:
> >> + - $ref: /schemas/spi/spi-peripheral-props.yaml#
> >> +
> >> +unevaluatedProperties: false
> >> +
> >> +examples:
> >> + - |
> >> + #include <dt-bindings/gpio/gpio.h>
> >> +
> >> + spi {
> >> + #address-cells = <1>;
> >> + #size-cells = <0>;
> >> +
> >> + dac@0 {
> >> + compatible = "adi,ad5529r-16";
> >> + reg = <0>;
> >> + spi-max-frequency = <25000000>;
> >> +
> >> + vdd-supply = <&vdd_regulator>;
> >> + avdd-supply = <&avdd_regulator>;
> >> + hvdd-supply = <&hvdd_regulator>;
> >> + hvss-supply = <&hvss_regulator>;
> >> +
> >> + reset-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>;
> >> +
> >> + #address-cells = <1>;
> >> + #size-cells = <0>;
> >> +
> >> + channel@0 {
> >> + reg = <0>;
> >> + adi,output-range-microvolt = <0 5000000>;
> >> + };
> >> +
> >> + channel@1 {
> >> + reg = <1>;
> >> + adi,output-range-microvolt = <(-10000000) 10000000>;
> >> + };
> >> +
> >> + channel@2 {
> >> + reg = <2>;
> >> + adi,output-range-microvolt = <0 40000000>;
> >> + };
> >> + };
> >> + };
> > ...
> >
> > spi {
> > #address-cells = <1>;
> > #size-cells = <0>;
> >
> > multi-dac@0 {
> > compatible = "adi,ad5529r-16";
> > reg = <0>;
> > spi-max-frequency = <25000000>;
> >
> > #address-cells = <1>;
> > #size-cells = <0>;
> >
> > dac@0 {
> > reg = <0>;
> > vdd-supply = <&vdd_regulator>;
> > avdd-supply = <&avdd_regulator>;
> > hvdd-supply = <&hvdd_regulator>;
> > hvss-supply = <&hvss_regulator>;
> >
> > reset-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>;
> >
> > #address-cells = <1>;
> > #size-cells = <0>;
> >
> > channel@0 {
> > reg = <0>;
> > adi,output-range-microvolt = <0 5000000>;
> > };
> >
> > channel@1 {
> > reg = <1>;
> > adi,output-range-microvolt = <(-10000000) 10000000>;
> > };
> >
> > channel@2 {
> > reg = <2>;
> > adi,output-range-microvolt = <0 40000000>;
> > };
> > }
> >
> > dac@1 {
> > reg = <1>;
> > vdd-supply = <&vdd_regulator>;
> > avdd-supply = <&avdd_regulator>;
> > hvdd-supply = <&hvdd_regulator>;
> > hvss-supply = <&hvss_regulator>;
> >
> > reset-gpios = <&gpio0 88 GPIO_ACTIVE_LOW>;
> >
> > #address-cells = <1>;
> > #size-cells = <0>;
> >
> > channel@0 {
> > reg = <0>;
> > adi,output-range-microvolt = <0 5000000>;
> > };
> >
> > channel@1 {
> > reg = <1>;
> > adi,output-range-microvolt = <(-10000000) 10000000>;
> > };
> > }
> > };
> > };
> >
> > then you might need something like:
> >
> > patternProperties:
> > "^dac@[0-3]$":
> >
> > and put most of the things under this node pattern.
> >
> > So the main driver that you're putting together might need to handle up to four instances.
> > Even if your current driver cannot handle this, the dt-bindings might need cover that.
> >
> > Need to double check if each dac node needs a separate compatible, so you would maybe populate
> > a platform data to be shared with the child nodes, which would be a separate driver.
> > (not sure if it would make sense to mix and match ad5529r-16 and ad5529r-12).
>
> Hi Rodrigo,
>
> Thank you for looking at this.
>
> For now, I would prefer to keep the binding scoped to a single AD5529R device instance. The current
> hardware/use case we have only needs one device node and the driver is written around that model as well.
> While the device addressing pins could allow multi-device topology, we do not have an actual platform using
> that configuration at the moment, so I would prefer not to introduce an extra parent/child binding structure
> speculatively without a validating use case.
Interesting feature - kind of similar to address control on a typical i2c bus device, or
looking at it another way a kind of distributed SPI mux.
Challenge of a binding is we need to anticipate the future. So I think we do need something
like Rodrigo is suggesting even if we only (for now) support a single instance in the driver.
That would leave the path open to supporting the addressing at a later date.
An alternative might be to look at it like a chained device setup. In those we pretend there
is just one device with a lot of channels etc. The snag is that here things are more loosely
coupled whereas for those devices it tends to be you have to read / write the same register
in all devices in the chain as one big SPI message.
+CC Mark Brown as he may know of some precedence for this feature. For his reference..
- Each of these device has 2 ID pins. The SPI transfers have to contain the 2 bit
value that matches that or they are ignored. Thus a single bus + 1 chip select can
be used to talk to 4 devices. Question is what that looks like in device tree + I guess
longer term how to support it cleanly in SPI.
Jonathan
>
> Best Regards,
> Janani Sunil
>
>
^ permalink raw reply
* Re: [PATCH v16 04/14] lib: kstrtox: add initial value to _parse_integer_limit()
From: Jonathan Cameron @ 2026-06-14 20:00 UTC (permalink / raw)
To: Rodrigo Alencar
Cc: rodrigo.alencar, linux-kernel, linux-iio, devicetree, linux-doc,
linux, David Lechner, Andy Shevchenko, Lars-Peter Clausen,
Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Corbet, Andrew Morton, Petr Mladek, Steven Rostedt,
Andy Shevchenko, Rasmus Villemoes, Sergey Senozhatsky, Shuah Khan
In-Reply-To: <rvx36i2ydmwhbbkdgbvh26uqchyoptzuu7tleuyarqn2skzkxz@owzwp62mzkdo>
On Thu, 4 Jun 2026 11:09:33 +0100
Rodrigo Alencar <455.rodrigo.alencar@gmail.com> wrote:
> On 26/06/04 10:58AM, Rodrigo Alencar via B4 Relay wrote:
> > From: Rodrigo Alencar <rodrigo.alencar@analog.com>
> >
> > Add init parameter to _parse_integer_limit() that defines an initial
> > value for the accumulated result when parsing an 64-bit integer. The
> > new function prototype is adjusted so that the _parse_integer() macros
> > stay consistent allowing for one more argument, which defaults to 0.
>
> ...
>
> > noinline
> > unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p,
> > - size_t max_chars)
> > + size_t max_chars, unsigned long long init)
> > {
> > unsigned long long res;
> > unsigned int rv;
> >
> > - res = 0;
> > + res = init;
>
> This might generate conflict, as the code around have changed in linux-next.
> It is an easy fix though.
>
Thanks for the heads up. Hopefully that will all fall out when I rebase testing
on rc1 once that is out.
Jonathan
> > rv = 0;
> > while (max_chars--) {
> > unsigned int c = *s;
>
^ permalink raw reply
* Re: [PATCH v16 00/14] ADF41513/ADF41510 PLL frequency synthesizers
From: Jonathan Cameron @ 2026-06-14 20:56 UTC (permalink / raw)
To: Rodrigo Alencar via B4 Relay
Cc: rodrigo.alencar, linux-kernel, linux-iio, devicetree, linux-doc,
linux, David Lechner, Andy Shevchenko, Lars-Peter Clausen,
Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Corbet, Andrew Morton, Petr Mladek, Steven Rostedt,
Andy Shevchenko, Rasmus Villemoes, Sergey Senozhatsky, Shuah Khan,
Krzysztof Kozlowski, Randy Dunlap
In-Reply-To: <20260604-adf41513-iio-driver-v16-0-1a7d09143bc2@analog.com>
On Thu, 04 Jun 2026 10:58:54 +0100
Rodrigo Alencar via B4 Relay <devnull+rodrigo.alencar.analog.com@kernel.org> wrote:
> This patch series adds support for the Analog Devices ADF41513 and ADF41510
> ultralow noise PLL frequency synthesizers. These devices are designed for
> implementing local oscillators (LOs) in high-frequency applications.
> The ADF41513 covers frequencies from 1 GHz to 26.5 GHz, while the ADF41510
> operates from 1 GHz to 10 GHz.
>
> Key features supported by this driver:
> - Integer-N and fractional-N operation modes
> - High maximum PFD frequency (250 MHz integer-N, 125 MHz fractional-N)
> - 25-bit fixed modulus or 49-bit variable modulus fractional modes
> - Digital lock detect functionality
> - Phase resync capability for consistent output phase
> - Load Enable vs Reference signal syncronization
>
> The series includes:
> 1. PLL driver implementation
> 2. Device tree bindings documentation
> 3. IIO ABI documentation
> 4. Parsing utils for 64-bit decimal values
>
> Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
Applied to the testing branch of iio.git
Thanks for your persistence with this. On a particular plus I think this
is the largest series I've yet seen that Sashiko gave a clean bill of health
to (so not even any false positives!)
Jonathan
> ---
> Changes in v16:
> - Incorporate Andy's series: https://lore.kernel.org/all/20260602203706.103449-1-andriy.shevchenko@linux.intel.com
> - Drop iio_val_s64_to_s32s() and iio_val_s64_from_s32s().
> - Add/change comments and minor changes.
> - Link to v15: https://lore.kernel.org/r/20260531-adf41513-iio-driver-v15-0-da09adf1c0dd@analog.com
>
> Changes in v15:
> - Set bleed value when chaging mode.
> - Link to v14: https://lore.kernel.org/r/20260524-adf41513-iio-driver-v14-0-06824d9c15f4@analog.com
>
> Changes in v14:
> - Review include headers.
> - Use named fields in spi device table.
> - Address relevant sashiko's feedback.
> - Minor tweaks to iio core changes.
> - Link to v13: https://lore.kernel.org/r/20260517-adf41513-iio-driver-v13-0-bb6e134a360f@analog.com
>
> Changes in v13:
> - Introduce _parse_integer_limit_init()
> - Better support for 0 and larger scales in kstrtodec64()
> - Increase test scope for kstrtodec64()
> - Fix LSB_P1 check at startup when going for fixed modulus mode.
> - Clear phase adjust when setting phase (It turns out sashiko was correct).
> - Make sure Load Enable is not selected when powering up.
> - Address some minor comments.
> - Link to v12: https://lore.kernel.org/r/20260510-adf41513-iio-driver-v12-0-34af2ed2779f@analog.com
>
> Changes in v12:
> - Contraint charge pump current.
> - Fix division-by-zero issues.
> - Address PM and sysfs powerdown conflicts.
> - Program proper phase resync value in clk divider mode.
> - Link to v11: https://lore.kernel.org/r/20260506-adf41513-iio-driver-v11-0-2b7e99cfe8f2@analog.com
>
> Changes in v11:
> - Cleanup ext info attribute read/write callbacks.
> - Adjust attribute names in the documentation.
> - Turn s64 compose macros into static inline functions.
> - Link to v10: https://lore.kernel.org/r/20260415-adf41513-iio-driver-v10-0-df61046d5457@analog.com
>
> Changes in v10:
> - Drop simple_strntoull() changes
> - Create kstrtodec64() and kstrtoudec64() helpers.
> - Add IIO value format for 64-bit decimal values.
> - PLL driver code implements new decimal format for frequency attr.
> - Link to v9: https://lore.kernel.org/r/20260320-adf41513-iio-driver-v9-0-132f0d076374@analog.com
>
> Changes in v9:
> - Expose simple_strntoull() in a safer prototype instead of new kstrntoull()
> - Link to v8: https://lore.kernel.org/r/20260303-adf41513-iio-driver-v8-0-8dd2417cc465@analog.com
>
> Changes in v8:
> - Add new function kstrntoull() to lib/kstrtox.c and tests to lib/test-kstrtox.c.
> - Drop custom iio u64 parser, replacing it for kstrntoull().
> - Dedicated MAINTAINERS entry for drivers/iio/test/iio-test-fixpoint-parse.c.
> - Link to v7: https://lore.kernel.org/r/20260216-adf41513-iio-driver-v7-0-b0ed387ab559@analog.com
>
> Changes in v7:
> - Addressed minor suggestions.
> - frequency_resolution ABI for AD4350 removed in favor of generic one.
> - Link to v6: https://lore.kernel.org/r/20260130-adf41513-iio-driver-v6-0-cf46239026bc@analog.com
>
> Changes in v6:
> - Drop usage of simple_strtoull().
> - Implement better overflow checks with iio_safe_strntou64().
> - Link to v5: https://lore.kernel.org/r/20260123-adf41513-iio-driver-v5-0-2dce812a2dda@analog.com
>
> Changes in v5:
> - Drop local parsing of 64-bit plus fractional parts
> - Add iio_str_to_fixpoint64() to iio core with parsing tests
> - Add DT property dependency for adi,charge-pump-resistor-ohms
> - Add local definition for ADF41513_HZ_PER_GHZ and drop units.h patch
> - Link to v4: https://lore.kernel.org/r/20260116-adf41513-iio-driver-v4-0-dbb7d6782217@analog.com
>
> Changes in v4:
> - Proper usage of units.h macros
> - Simplifications to DT property parsing
> - Adjustments to return value handling
> - Drop of simple DT property node example
> - Link to v3: https://lore.kernel.org/r/20260108-adf41513-iio-driver-v3-0-23d1371aef48@analog.com
>
> Changes in v3:
> - Use FIELD_MODIFY macro in driver implementation
> - Drop refin_frequency iio attribute
> - Drop muxout-select property from dt-bindings (and rename logic-level property)
> - Use -mhz suffix in power-up frequency property
> - Address documentation issues
> - Link to v2: https://lore.kernel.org/r/20251219-adf41513-iio-driver-v2-0-be29a83d5793@analog.com
>
> Changes in v2:
> - separate driver implementation from extra features and improve commit messages
> - use macros from units.h
> - explanation of custom parse function: adf41513_parse_uhz
> - reorganize driver data structures
> - drop clock framework support for now
> - reorganize documentation
> - Link to v1: https://lore.kernel.org/r/20251110-adf41513-iio-driver-v1-0-2df8be0fdc6e@analog.com
>
> ---
> Andy Shevchenko (2):
> lib: kstrtox: Make _parse_integer() take variadic arguments
> lib: vsprintf: use _parse_integer() instead of _parse_integer_limit()
>
> Rodrigo Alencar (12):
> dt-bindings: iio: frequency: add adf41513
> lib: kstrtox: add initial value to _parse_integer_limit()
> lib: kstrtox: add kstrtoudec64() and kstrtodec64()
> lib: test-kstrtox: tests for kstrtodec64() and kstrtoudec64()
> lib: math: div64: add div64_s64_rem()
> iio: core: add decimal value formatting into 64-bit value
> iio: test: iio-test-format: add test case for decimal format
> iio: frequency: adf41513: driver implementation
> iio: frequency: adf41513: handle LE synchronization feature
> iio: frequency: adf41513: features on frequency change
> docs: iio: add documentation for adf41513 driver
> Documentation: ABI: testing: add common ABI file for iio/frequency
>
> Documentation/ABI/testing/sysfs-bus-iio-frequency | 11 +
> .../ABI/testing/sysfs-bus-iio-frequency-adf4350 | 10 -
> .../bindings/iio/frequency/adi,adf41513.yaml | 227 ++++
> Documentation/iio/adf41513.rst | 199 ++++
> Documentation/iio/index.rst | 1 +
> MAINTAINERS | 9 +
> drivers/iio/frequency/Kconfig | 10 +
> drivers/iio/frequency/Makefile | 1 +
> drivers/iio/frequency/adf41513.c | 1246 ++++++++++++++++++++
> drivers/iio/industrialio-core.c | 49 +-
> drivers/iio/test/iio-test-format.c | 97 +-
> include/linux/iio/types.h | 20 +
> include/linux/kstrtox.h | 3 +
> include/linux/math64.h | 18 +
> lib/kstrtox.c | 114 +-
> lib/kstrtox.h | 17 +-
> lib/math/div64.c | 15 +
> lib/test-kstrtox.c | 182 +++
> lib/vsprintf.c | 2 +-
> 19 files changed, 2178 insertions(+), 53 deletions(-)
> ---
> base-commit: ae696dfa47c30016cd429b9db5e70b259b8f509e
> change-id: 20251110-adf41513-iio-driver-aaca8a7f808e
>
> Best regards,
^ permalink raw reply
* Re: [PATCH] docs: kbuild: remove ISDN references in Makefile examples
From: Ethan Nelson-Moore @ 2026-06-14 21:54 UTC (permalink / raw)
To: Julian Braha
Cc: Shuah Khan, Chen Pei, Randy Dunlap, Jonathan Corbet, linux-kbuild,
linux-doc, Nathan Chancellor, Nicolas Schier, Andrew Jones
In-Reply-To: <b677c9e4-edd7-42ab-ac0d-d721e7aaf2e3@gmail.com>
Hi, Julian,
On Sun, Jun 14, 2026 at 8:00 AM Julian Braha <julianbraha@gmail.com> wrote:
> Hi Ethan, are you using the kconfig-sym-check[1] that was recently
> merged? This dead symbol check should not have the false positives on
> documentation.
No, I'm not - I had heard about the Kconfirm project, but not about
this similar tool. Thanks for letting me know,
> Though maybe your check also catches dead symbols in C, Rust, Makefiles?
Yes, it does; it has orthogonal functionality to kconfig-sym-check,
which only operates within Kconfig files.
My script checks for CONFIG_* symbols that are referenced in code or
documentation, but that are not defined in any Kconfig file. The
decision to include documentation is intentional and has revealed
several instances of outdated documentation.
It also filters out symbols that are defined in a Makefile or
hardcoded with #define, and also attempts to filter out structs and
enums (and typedefs thereof) named CONFIG_*, though I need to improve
this further.
I will post it publicly once I have done so.
Ethan
^ permalink raw reply
* Re: [PATCH RFC v4 1/6] dt-bindings: iio: add Open Sensor Fusion device
From: Kim Jinseob @ 2026-06-14 23:04 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Conor Dooley, linux-iio, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Corbet, Shuah Khan, devicetree, linux-kernel, linux-doc
In-Reply-To: <20260614185551.10ca9e0f@jic23-huawei>
2026년 6월 15일 (월) 오전 2:55, Jonathan Cameron <jic23@kernel.org>님이 작성:
>
> On Wed, 10 Jun 2026 18:33:54 +0900
> Kim Jinseob <kimjinseob88@gmail.com> wrote:
> When a device needs power, the regulator is required, not optional from a binding
> point of view. If it is always one people can use a fixed regulator to represent it.
>
> Now from a driver point of view, the regulator framework in linux provides stub regulators
> for missing ones - on assumption they are always on. So we can just request the
> regulators in the driver. Keep it simple for now and use a
> devm_regulator_get_enable() in probe so we have power on for all the time
> the driver is loaded. Can do fancy stuff later when you have a board where the
> power is controlled.
Understood, thanks.
I will make vcc-supply a required property in the binding and use
devm_regulator_get_enable() in probe in the next revision, keeping the
power handling simple for now.
Jinseob
^ permalink raw reply
* Re: [PATCH RFC v4 2/6] Documentation: iio: add Open Sensor Fusion driver overview
From: Kim Jinseob @ 2026-06-14 23:10 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-iio, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
Shuah Khan, devicetree, linux-kernel, linux-doc
In-Reply-To: <20260614185914.6c14d376@jic23-huawei>
> Same issue on needing this series to be against a suitable
> tree, not on top of your previous version.
Understood, thanks.
I will regenerate the next revision as a full standalone series against a
clean upstream base, not on top of the previous version.
I will also check the final diffstat before sending so files from earlier
versions are not removed, and fold the MAINTAINERS cleanup into the correct
patch.
Thanks,
Jinseob
^ permalink raw reply
* [PATCH] docs: pt_BR: update minimal software requirement for pahole in changes.rst
From: Amanda Corrêa @ 2026-06-14 23:43 UTC (permalink / raw)
To: Daniel Pereira, Jonathan Corbet
Cc: Shuah Khan, linux-doc, linux-kernel, Amanda Corrêa
Update the Brazilian Portuguese translation of changes.rst to align with
the latest English version.
Key changes include:
- Updated minimum version for pahole (1.26)
- Added note about kfuncs annotated with KF_IMPLICIT_ARGS
requiring pahole v1.26 or later
- Changed "optional" to "opcional" in the software requirements
table
Signed-off-by: Amanda Corrêa <amandacorreasilvax@gmail.com>
---
.../translations/pt_BR/process/changes.rst | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/Documentation/translations/pt_BR/process/changes.rst b/Documentation/translations/pt_BR/process/changes.rst
index a105581dc..49b7f7450 100644
--- a/Documentation/translations/pt_BR/process/changes.rst
+++ b/Documentation/translations/pt_BR/process/changes.rst
@@ -32,16 +32,16 @@ PC Card por exemplo, provavelmente não precisará se preocupar com o pcmciautil
Programa Versão mínima Comando para verificar a versão
====================== =============== ========================================
GNU C 8.1 gcc --version
-Clang/LLVM (optional) 15.0.0 clang --version
-Rust (optional) 1.85.0 rustc --version
-bindgen (optional) 0.71.1 bindgen --version
+Clang/LLVM (opcional) 15.0.0 clang --version
+Rust (opcional) 1.85.0 rustc --version
+bindgen (opcional) 0.71.1 bindgen --version
GNU make 4.0 make --version
bash 4.2 bash --version
binutils 2.30 ld -v
flex 2.5.35 flex --version
gdb 7.2 gdb --version
bison 2.0 bison --version
-pahole 1.22 pahole --version
+pahole 1.26 pahole --version
util-linux 2.10o mount --version
kmod 13 kmod -V
e2fsprogs 1.41.4 e2fsck -V
@@ -149,6 +149,11 @@ Desde o Linux 5.2, se CONFIG_DEBUG_INFO_BTF estiver selecionado, o sistema de
compilação gera BTF (BPF Type Format) a partir do DWARF no vmlinux, e um pouco
depois para os módulos do kernel também. Isso requer o pahole v1.22 ou superior.
+Desde o Linux 7.0, kfuncs anotados com KF_IMPLICIT_ARGS exigem o pahole v1.26
+ou posterior. Sem ele, tais kfuncs terão protótipos BTF incorretos em vmlinux,
+fazendo com que os programas BPF falhem ao carregar com um erro "func_proto
+incompatible with vmlinux". Muitos kfuncs sched_ext são afetados.
+
Ele pode ser encontrado nos pacotes ``dwarves`` ou ``pahole`` das
distribuições, ou em https://fedorapeople.org/~acme/dwarves/.
@@ -189,7 +194,7 @@ Tar
O GNU tar é necessário caso você deseje habilitar o acesso aos cabeçalhos do
kernel via sysfs (CONFIG_IKHEADERS).
-gtags / GNU GLOBAL (optional)
+gtags / GNU GLOBAL (opcional)
-----------------------------
A compilação do kernel requer o GNU GLOBAL versão 6.6.5 ou superior para gerar
--
2.43.0
^ permalink raw reply related
* [PATCH 0/2] docs: pt_BR: Translate coding and posting guidelines
From: Daniel Pereira @ 2026-06-14 23:50 UTC (permalink / raw)
To: Jonathan Corbet; +Cc: linux-doc, Daniel Pereira
This patch series translates chapters 4 and 5 of the kernel development
process documentation ("4.Coding.rst" and "5.Posting.rst") into
Brazilian Portuguese (pt_BR).
The goal is to expand the available documentation for Portuguese-speaking
developers, making it easier to understand core coding standards and
patch submission guidelines.
Daniel Pereira (2):
docs: pt_BR: Translate 4.coding.rst into Portuguese
docs: pt_BR: Translate patch posting documentation
.../translations/pt_BR/process/4.Coding.rst | 440 ++++++++++++++++++
.../translations/pt_BR/process/5.Posting.rst | 376 +++++++++++++++
.../pt_BR/process/development-process.rst | 2 +
3 files changed, 818 insertions(+)
create mode 100644 Documentation/translations/pt_BR/process/4.Coding.rst
create mode 100644 Documentation/translations/pt_BR/process/5.Posting.rst
--
2.47.3
^ permalink raw reply
* [PATCH 1/2] docs: pt_BR: Translate 4.coding.rst into Portuguese
From: Daniel Pereira @ 2026-06-14 23:50 UTC (permalink / raw)
To: Jonathan Corbet; +Cc: linux-doc, Daniel Pereira
In-Reply-To: <20260614235044.42810-1-danielmaraboo@gmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 27392 bytes --]
Translate the chapter regarding coding standards and patch formatting
rules ("4.Coding.rst") into Brazilian Portuguese.
This translation helps Portuguese-speaking developers better understand
the core guidelines required for kernel code contributions.
Signed-off-by: Daniel Pereira <danielmaraboo@gmail.com>
---
.../translations/pt_BR/process/4.Coding.rst | 440 ++++++++++++++++++
.../pt_BR/process/development-process.rst | 2 +
2 files changed, 442 insertions(+)
create mode 100644 Documentation/translations/pt_BR/process/4.Coding.rst
diff --git a/Documentation/translations/pt_BR/process/4.Coding.rst b/Documentation/translations/pt_BR/process/4.Coding.rst
new file mode 100644
index 000000000..ca4c74774
--- /dev/null
+++ b/Documentation/translations/pt_BR/process/4.Coding.rst
@@ -0,0 +1,440 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Escrever o código corretamente
+==============================
+
+Embora haja muito o que se dizer sobre um processo de design sólido e orientado
+à comunidade, a prova de qualquer projeto de desenvolvimento de kernel está no
+código resultante. É o código que será examinado por outros desenvolvedores e
+mesclado (ou não) na árvore principal (*mainline*). Portanto, é a qualidade
+deste código que determinará o sucesso final do projeto.
+
+Esta seção examinará o processo de codificação. Começaremos analisando uma série
+de maneiras pelas quais os desenvolvedores de kernel podem errar. Em seguida, o
+foco mudará para como fazer as coisas do jeito certo e as ferramentas que podem
+ajudar nessa busca.
+
+
+Armadilhas
+----------
+
+Estilo de Codificação
+*********************
+
+O kernel há muito possui um estilo de codificação padrão, descrito em
+:ref:`Documentation/process/coding-style.rst <codingstyle>`. Por grande parte
+desse tempo, as políticas descritas naquele arquivo eram consideradas, no
+máximo, como recomendações. Como resultado, há uma quantidade substancial
+de código no kernel que não cumpre as diretrizes de estilo de codificação.
+A presença desse código leva a dois riscos independentes para os
+desenvolvedores do kernel.
+
+O primeiro deles é acreditar que os padrões de codificação do kernel não importam
+e não são exigidos. A verdade é que adicionar novo código ao kernel é muito
+difícil se esse código não estiver escrito de acordo com o padrão; muitos
+desenvolvedores solicitarão que o código seja reformatado antes mesmo de
+revisá-lo. Uma base de código tão grande quanto a do kernel exige certa
+uniformidade para tornar possível que os desenvolvedores entendam rapidamente
+qualquer parte dela. Portanto, não há mais espaço para códigos com formatações
+estranhas.
+
+Ocasionalmente, o estilo de codificação do kernel entrará em conflito com o
+estilo exigido por um empregador. Nesses casos, o estilo do kernel terá que
+vencer para que o código possa ser mesclado. Colocar código no kernel significa
+abrir mão de um certo grau de controle de várias maneiras — incluindo o controle
+sobre como o código é formatado.
+
+A outra armadilha é presumir que o código já presente no kernel necessita
+urgentemente de correções de estilo de codificação. Os desenvolvedores podem
+começar a gerar patches de reformatação como uma forma de ganhar familiaridade
+com o processo, ou como um meio de incluir seus nomes nos logs de alterações
+(*changelogs*) do kernel ou ambos. No entanto, patches puramente de estilo de
+codificação são vistos como ruído pela comunidade de desenvolvimento; eles tendem
+a receber uma recepção fria. Portanto, é melhor evitar esse tipo de patch. É
+natural corrigir o estilo de um trecho de código ao trabalhar nele por outros
+motivos, mas mudanças de estilo de codificação não devem ser feitas apenas por
+fazer.
+
+O documento de estilo de codificação também não deve ser lido como uma lei
+absoluta que nunca pode ser transgredida. Se houver um bom motivo para ir contra
+o estilo (uma linha que se torna muito menos legível se for dividida para caber
+no limite de 80 colunas, por exemplo), simplesmente faça isso.
+
+Note que você também pode usar a ferramenta ``clang-format`` para ajudá-lo com
+essas regras, para reformatar rapidamente partes do seu código de forma automática
+e para revisar arquivos completos a fim de identificar erros de estilo de
+codificação, erros de digitação e possíveis melhorias. Ela também é útil para
+ordenar ``#includes``, alinhar variáveis/macros, reajustar o fluxo de textos e
+outras tarefas semelhantes. Veja o arquivo
+:ref:`Documentation/dev-tools/clang-format.rst <clangformat>` para mais detalhes.
+
+Algumas configurações básicas do editor, como indentação e fins de linha,
+serão definidas automaticamente se você estiver usando um editor compatível
+com o EditorConfig. Consulte o site oficial do EditorConfig para obter mais
+informações: https://editorconfig.org/
+
+Camadas de Abstração
+********************
+
+Os professores de Ciência da Computação ensinam os alunos a fazerem uso
+extensivo de camadas de abstração em nome da flexibilidade e da ocultação de
+informações. Certamente o kernel faz uso extensivo de abstração; nenhum
+projeto que envolva vários milhões de linhas de código poderia fazer o
+contrário e sobreviver. No entanto, a experiência tem mostrado que a
+abstração excessiva ou prematura pode ser tão prejudicial quanto a otimização
+prematura. A abstração deve ser usada até o nível necessário e não além.
+
+Em um nível simples, considere uma função que possui um argumento que é
+sempre passado como zero por todos os chamadores. Alguém poderia manter esse
+argumento caso alguém eventualmente precise usar a flexibilidade extra que ele
+oferece. A essa altura, no entanto, as chances são grandes de que o código que
+implementa esse argumento extra tenha sido quebrado de alguma forma sutil que
+nunca foi percebida — porque ele nunca foi usado. Ou, quando surge a
+necessidade de flexibilidade extra, ela não ocorre de uma forma que corresponda
+à expectativa inicial do programador. Os desenvolvedores do kernel enviam
+patches rotineiramente para remover argumentos não utilizados; eles não devem,
+em geral, ser adicionados em primeiro lugar.
+
+Camadas de abstração que ocultam o acesso ao hardware — frequentemente para
+permitir que a maior parte de um driver seja usada com múltiplos sistemas
+operacionais — são especialmente malvistas. Essas camadas obscurecem o código
+e podem impor uma penalidade de desempenho; elas não pertencem ao kernel
+Linux.
+
+Por outro lado, se você se pegar copiando quantidades significativas de código
+de outro subsistema do kernel, é hora de perguntar se faria sentido, de fato,
+extrair parte desse código em uma biblioteca separada ou implementar essa
+funcionalidade em um nível superior. Não há valor em duplicar o mesmo código
+por todo o kernel.
+
+
+Uso de #ifdef e do pré-processador em geral
+*******************************************
+
+O pré-processador C parece apresentar uma forte tentação para alguns
+programadores C, que o veem como uma forma de codificar eficientemente uma grande
+quantidade de flexibilidade em um arquivo-fonte. No entanto, o pré-processador
+não é C, e o uso pesado dele resulta em um código muito mais difícil de ser lido
+por outros e mais difícil para o compilador verificar a correção. O uso pesado
+do pré-processador é quase sempre um sinal de código que precisa de algum
+trabalho de limpeza.
+
+A compilação condicional com #ifdef é, de fato, um recurso poderoso, e é
+utilizada dentro do kernel. Mas há pouco desejo de ver um código que seja
+salpicado liberalmente com blocos #ifdef. Como regra geral, o uso de #ifdef
+deve ser confinado a arquivos de cabeçalho (headers) sempre que possível. O
+código compilado condicionalmente pode ser confinado a funções que, se o código
+não estiver presente, simplesmente se tornam vazias. O compilador irá então,
+silenciosamente, otimizar e remover a chamada para a função vazia. O resultado
+é um código muito mais limpo e fácil de acompanhar.
+
+As macros do pré-processador C apresentam uma série de riscos, incluindo a
+possível avaliação múltipla de expressões com efeitos colaterais e a falta de
+segurança de tipos. Se você se sentir tentado a definir uma macro, considere a
+criação de uma função inline em seu lugar. O código resultante será o mesmo,
+mas as funções inline são mais fáceis de ler, não avaliam seus argumentos
+múltiplas vezes e permitem que o compilador realize a checagem de tipos nos
+argumentos e no valor de retorno.
+
+
+Funções Inline
+**************
+
+No entanto, as funções inline apresentam um perigo próprio. Os programadores
+podem ficar encantados com a eficiência percebida inerente a evitar uma chamada
+de função e encher um arquivo de código-fonte com funções inline. Essas
+funções, contudo, podem na verdade reduzir o desempenho. Como seu código é
+replicado em cada local de chamada, elas acabam inflando o tamanho do kernel
+compilado. Isso, por sua vez, cria pressão nos caches de memória do
+processador, o que pode desacelerar a execução drasticamente. As funções
+inline, como regra, devem ser bastante pequenas e relativamente raras. O custo
+de uma chamada de função, afinal de contas, não é tão alto; a criação de um
+grande número de funções inline é um exemplo clássico de otimização prematura.
+
+Em geral, os programadores de kernel ignoram os efeitos de cache por sua própria
+conta e risco. O clássico compromisso entre tempo e espaço (tradeoff) ensinado
+nas aulas introdutórias de estruturas de dados frequentemente não se aplica ao
+hardware contemporâneo. Espaço *é* tempo, no sentido de que um programa maior
+será executado mais lentamente do que um que seja mais compacto.
+
+Compiladores mais recentes desempenham um papel cada vez mais ativo em decidir
+se uma determinada função deve ou não ser realmente inline. Portanto, a inserção
+liberal da palavra-chave "inline" pode não apenas ser excessiva; ela também pode
+ser irrelevante.
+
+
+Mecanismo de Trava
+******************
+
+Em maio de 2006, a pilha de rede "Devicescape" foi, com grande alarde, lançada
+sob a GPL e disponibilizada para inclusão no kernel mainline. Essa doação foi uma
+notícia bem-vinda; o suporte para redes sem fio no Linux era considerado abaixo do
+padrão, na melhor das hipóteses, e a pilha da Devicescape oferecia a promessa de
+corrigir essa situação. No entanto, esse código só entrou de fato no mainline em
+junho de 2007 (2.6.22). O que aconteceu?
+
+Esse código mostrava vários sinais de ter sido desenvolvido a portas fechadas em
+ambiente corporativo. Mas um grande problema em particular era que ele não havia
+sido projetado para funcionar em sistemas multiprocessados. Antes que essa pilha
+de rede (agora chamada de mac80211) pudesse ser integrada, um esquema de locking
+(bloqueio) precisou ser adaptado a ela.
+
+Era uma vez uma época em que o código do kernel Linux podia ser desenvolvido sem
+pensar nos problemas de concorrência apresentados por sistemas multiprocessados.
+Hoje, no entanto, este documento está sendo escrito em um laptop dual-core.
+Mesmo em sistemas com um único processador, o trabalho feito para melhorar a
+capacidade de resposta aumentará o nível de concorrência dentro do kernel. Os
+dias em que o código do kernel podia ser escrito sem pensar em locking ficaram
+há muito tempo no passado.
+
+Qualquer recurso (estruturas de dados, registradores de hardware, etc.) que
+possa ser acessado concorrentemente por mais de uma linha de execução deve ser
+protegido por uma trava (lock). O novo código deve ser escrito com esse
+requisito em mente; adaptar o locking após o fato é uma tarefa consideravelmente
+mais difícil. Os desenvolvedores do kernel devem dedicar um tempo para
+compreender as primitivas de locking disponíveis bem o suficiente para escolher
+a ferramenta certa para o trabalho. Códigos que mostrem falta de atenção à
+concorrência terão um caminho difícil para entrar no mainline.
+
+
+Regressions
+***********
+
+Um perigo final que vale a pena mencionar é este: pode ser tentador fazer uma
+alteração (que pode trazer grandes melhorias) que faça algo quebrar para os
+usuários existentes. Esse tipo de alteração é chamado de "regressão", e as
+regressões tornaram-se totalmente indesejadas no kernel mainline. Com poucas
+exceções, as alterações que causarem regressões serão revertidas se a regressão
+não puder ser corrigida em tempo hábil. É muito melhor evitar a regressão em
+primeiro lugar.
+
+Muitas vezes argumenta-se que uma regressão pode ser justificada se ela fizer as
+coisas funcionarem para mais pessoas do que os problemas que ela cria. Por que
+não fazer uma alteração se ela trouxer uma nova funcionalidade para dez sistemas
+para cada um que ela quebrar? A melhor resposta para essa pergunta foi expressa
+por Linus em julho de 2007:
+
+::
+
+ Portanto, nós não corrigimos bugs introduzindo novos problemas. Esse caminho
+ leva à loucura, e ninguém nunca sabe se você está realmente fazendo algum
+ progresso real. São dois passos para frente, um passo para trás, ou um passo
+ para frente e dois passos para trás?
+
+(https://lwn.net/Articles/243460/).
+
+Um tipo de regressão especialmente indesejado é qualquer tipo de alteração na
+ABI do espaço do usuário (user-space ABI). Uma vez que uma interface tenha sido
+exportada para o espaço do usuário, ela deve receber suporte indefinidamente.
+Esse fato torna a criação de interfaces de espaço do usuário particularmente
+desafiadora: já que elas não podem ser alteradas de maneiras incompatíveis, elas
+devem ser feitas corretamente na primeira vez. Por essa razão, exige-se sempre
+muita reflexão, documentação clara e uma ampla revisão para as interfaces do
+espaço do usuário.
+
+
+Ferramentas de verificação de código
+------------------------------------
+
+Por enquanto, pelo menos, a escrita de código livre de erros continua sendo um
+ideal que poucos de nós conseguem alcançar. O que podemos esperar fazer, no
+entanto, é capturar e corrigir o máximo possível desses erros antes que nosso
+código entre no kernel mainline. Para esse fim, os desenvolvedores do kernel
+reuniram um conjunto impressionante de ferramentas que podem capturar uma ampla
+variedade de problemas obscuros de forma automatizada. Qualquer problema
+capturado pelo computador é um problema que não afligirá um usuário mais tarde,
+portanto, é lógico que as ferramentas automatizadas devem ser usadas sempre que
+possível.
+
+O primeiro passo é simplesmente prestar atenção aos avisos (warnings) produzidos
+com o compilador. As versões contemporâneas do gcc podem detectar (e alertar
+sobre) um grande número de erros potenciais. Com bastante frequência, esses
+avisos apontam para problemas reais. O código enviado para revisão deve, como
+regra, não produzir nenhum aviso do compilador. Ao silenciar os avisos, tome o
+cuidado de entender a real causa e tente evitar "correções" que façam o aviso
+desaparecer sem resolver a sua origem.
+
+Note que nem todos os avisos do compilador ficam ativados por padrão. Compile o
+kernel com "make KCFLAGS=-W" para obter o conjunto completo.
+
+O kernel fornece várias opções de configuração que ativam recursos de
+depuração; a maioria delas é encontrada no submanu "kernel hacking". Várias
+dessas opções devem ser ativadas para qualquer kernel usado para fins de
+desenvolvimento ou teste. Em particular, você deve ativar:
+
+ - FRAME_WARN para obter avisos sobre quadros de pilha (stack frames) maiores
+ que um determinado valor. A saída gerada pode ser volumosa, mas não é
+ necessário se preocupar com os avisos de outras partes do kernel.
+
+ - DEBUG_OBJECTS adicionará código para rastrear o tempo de vida de vários
+ objetos criados pelo kernel e alertará quando as ações forem feitas fora de
+ ordem. Se você estiver adicionando um subsistema que cria (e exporta) seus
+ próprios objetos complexos, considere adicionar suporte à infraestrutura de
+ depuração de objetos.
+
+ - DEBUG_SLAB pode encontrar uma variedade de erros de alocação e uso de
+ memória; ele deve ser usado na maioria dos kernels de desenvolvimento.
+
+ - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP e DEBUG_MUTEXES encontrarão uma série de
+ erros comuns de locking (bloqueio).
+
+Existem várias outras opções de depuração, algumas das quais serão discutidas
+abaixo. Algumas delas têm um impacto significativo no desempenho e não devem ser
+usadas o tempo todo. Mas um tempo gasto aprendendo as opções disponíveis
+provavelmente se pagará muitas vezes em pouco tempo.
+
+Uma das ferramentas de depuração mais pesadas é o verificador de locking, ou
+"lockdep". Esta ferramenta rastreará a aquisição e a liberação de cada trava
+(spinlock ou mutex) no sistema, a ordem em que as travas são adquiridas umas em
+relação às outras, o ambiente de interrupção atual e muito mais. Ela pode,
+então, garantir que as travas sejam sempre adquiridas na mesma ordem, que as
+mesmas suposições de interrupção se apliquem em todas as situações e assim por
+diante. Em outras palavras, o lockdep pode encontrar uma série de cenários nos
+quais o sistema poderia, em raras ocasiões, entrar em deadlock. Esse tipo de
+problema pode ser doloroso (tanto para desenvolvedores quanto para usuários) em
+um sistema implantado; o lockdep permite que eles sejam encontrados de maneira
+automatizada e antecipada. Códigos com qualquer tipo de locking não trivial
+devem ser executados com o lockdep ativado antes de serem enviados para inclusão.
+
+Como um programador de kernel diligente, você irá, sem dúvida, verificar o
+status de retorno de qualquer operação (como uma alocação de memória) que possa
+falhar. O fato, porém, é que os caminhos de recuperação de falha resultantes
+estão, provavelmente, completamente não testados. Código não testado tende a ser
+código quebrado; você poderia estar muito mais confiante em seu código se todos
+esses caminhos de tratamento de erros tivessem sido exercitados algumas vezes.
+
+O kernel fornece um framework de injeção de falhas (fault injection) que pode
+fazer exatamente isso, especialmente onde alocações de memória estão
+envolvidas. Com a injeção de falhas ativada, uma porcentagem configurável das
+alocações de memória será forçada a falhar; essas falhas podem ser restritas a
+um intervalo específico de código. Executar o código com a injeção de falhas
+ativada permite ao programador ver como o código responde quando as coisas vão
+mal. Veja Documentation/fault-injection/fault-injection.rst para mais
+informações sobre como usar esse recurso.
+
+Outros tipos de erros podem ser encontrados com a ferramenta de análise estática
+"sparse". Com o sparse, o programador pode ser alertado sobre confusões entre
+endereços do espaço do usuário e do espaço do kernel, mistura de quantidades
+big-endian e small-endian, a passagem de valores inteiros onde um conjunto de
+sinalizadores de bits (bit flags) é esperado, e assim por diante. O sparse deve
+ser instalado separadamente (ele pode ser encontrado em
+https://sparse.wiki.kernel.org/index.php/Main_Page se a sua distribuição não o
+incluir como pacote); ele pode então ser executado no código adicionando "C=1"
+ao seu comando make.
+
+A ferramenta "Coccinelle" (http://coccinelle.lip6.fr/) é capaz de encontrar uma
+ampla variedade de potenciais problemas de codificação; ela também pode propor
+correções para esses problemas. Uma quantidade considerável de "patches
+semânticos" para o kernel foi empacotada sob o diretório scripts/coccinelle;
+executar "make coccicheck" passará por esses patches semânticos e relatará
+quaisquer problemas encontrados. Veja
+:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`
+para mais informações.
+
+Outros tipos de erros de portabilidade são encontrados mais facilmente ao
+compilar seu código para outras arquiteturas. Se você por acaso não tiver um
+sistema S/390 ou uma placa de desenvolvimento Blackfin à mão, ainda assim poderá
+realizar a etapa de compilação. Um grande conjunto de compiladores cruzados
+(cross-compilers) para sistemas x86 pode ser encontrado em:
+
+ https://www.kernel.org/pub/tools/crosstool/
+
+Um tempo gasto instalando e usando esses compiladores ajudará a evitar
+constrangimentos mais tarde.
+
+
+Documentação
+-------------
+
+A documentação frequentemente tem sido mais a exceção do que a regra no
+desenvolvimento do kernel. Mesmo assim, uma documentação adequada ajudará a
+facilitar a integração de novos códigos ao kernel, tornará a vida mais fácil para
+outros desenvolvedores e será útil para os seus usuários. Em muitos casos, a
+adição de documentação tornou-se essencialmente obrigatória.
+
+A primeira parte da documentação de qualquer patch é o seu log de alterações
+(changelog) associado. As entradas do log devem descrever o problema que está
+sendo resolvido, a forma da solução, as pessoas que trabalharam no patch,
+quaisquer efeitos relevantes no desempenho e qualquer outra coisa que possa ser
+necessária para entender o patch. Certifique-se de que o changelog diga o
+*porquê* de o patch valer a pena ser aplicado; um número surpreendente de
+desenvolvedores falha em fornecer essa informação.
+
+Qualquer código que adicione uma nova interface de espaço do usuário — incluindo
+novos arquivos sysfs ou /proc — deve incluir a documentação dessa interface, de
+modo a permitir que os desenvolvedores do espaço do usuário saibam com o que
+estão trabalhando. Veja Documentation/ABI/README para uma descrição de como essa
+documentação deve ser formatada e quais informações precisam ser fornecidas.
+
+O arquivo :ref:`Documentation/admin-guide/kernel-parameters.rst
+<kernelparameters>` descreve todos os parâmetros de boot do kernel. Qualquer
+patch que adicione novos parâmetros deve adicionar as entradas apropriadas a
+este arquivo.
+
+Quaisquer novas opções de configuração devem ser acompanhadas por um texto de
+ajuda que explique claramente as opções e quando o usuário pode querer
+selecioná-las.
+
+As informações de API interna de muitos subsistemas são documentadas por meio de
+comentários com formatação especial; esses comentários podem ser extraídos e
+formatados de várias maneiras pelo script "kernel-doc". Se você estiver
+trabalhando em um subsistema que possui comentários kerneldoc, você deve
+mantê-los e adicioná-los, conforme apropriado, para funções disponíveis
+externamente. Mesmo em áreas que não tenham sido documentadas dessa forma, não há
+mal nenhum em adicionar comentários kerneldoc para o futuro; de fato, esta pode
+ser uma atividade útil para desenvolvedores iniciantes de kernel. O formato
+desses comentários, junto com algumas informações sobre como criar modelos de
+kerneldoc, pode ser encontrado em :ref:`Documentation/doc-guide/ <doc_guide>`.
+
+Qualquer pessoa que leia uma quantidade significativa de código existente do
+kernel notará que, frequentemente, os comentários chamam a atenção por sua
+ausência. Mais uma vez, as expectativas para códigos novos são mais altas do que
+eram no passado; integrar código sem comentários será mais difícil. Dito isso,
+há pouco interesse em códigos comentados de forma prolixa. O código deve, por si
+só, ser legível, com os comentários explicando os aspectos mais sutis.
+
+Certas coisas devem sempre ser comentadas. O uso de barreiras de memória
+(memory barriers) deve ser acompanhado por uma linha explicando por que a
+barreira é necessária. As regras de locking (bloqueio) para estruturas de dados
+geralmente precisam ser explicadas em algum lugar. Grandes estruturas de dados
+precisam de uma documentação abrangente em geral. Dependências não óbvias entre
+trechos distintos de código devem ser apontadas. Qualquer coisa que possa tentar
+um "faxineiro de código" (code janitor) a fazer uma "limpeza" incorreta precisa
+de um comentário dizendo por que foi feita daquela maneira. E assim por diante.
+
+
+Alterações de API interna
+-------------------------
+
+A interface binária fornecida pelo kernel para o espaço do usuário não pode ser
+quebrada, exceto sob as circunstâncias mais graves. Por outro lado, as
+interfaces de programação internas do kernel são altamente fluidas e podem ser
+alteradas quando surgir a necessidade. Se você se encontrar tendo que criar uma
+gambiarra para contornar uma API do kernel, ou simplesmente deixando de usar uma
+funcionalidade específica porque ela não atende às suas necessidades, isso pode
+ser um sinal de que a API precisa mudar. Como desenvolvedor de kernel, você tem
+o poder de fazer tais alterações.
+
+Existem, é claro, algumas pegadinhas. Alterações de API podem ser feitas, mas
+precisam ser bem justificadas. Portanto, qualquer patch que faça uma alteração de
+API interna deve ser acompanhado por uma descrição do que é a mudança e do porquê
+ela é necessária. Esse tipo de alteração também deve ser separado em um patch
+independente, em vez de ser enterrado dentro de um patch maior.
+
+A outra pegadinha é que o desenvolvedor que altera uma API interna é geralmente
+encarregado da tarefa de corrigir qualquer código dentro da árvore do kernel que
+tenha sido quebrado pela mudança. Para uma função amplamente utilizada, esse
+dever pode levar a literalmente centenas ou milhares de alterações — muitas das
+quais provavelmente entrarão em conflito com o trabalho que está sendo feito por
+outros desenvolvedores. Desnecessário dizer que isso pode ser um grande
+trabalho, então é melhor ter certeza de que a justificativa é sólida. Note que
+a ferramenta Coccinelle pode ajudar com alterações de API de amplo alcance.
+
+Ao fazer uma alteração incompatível de API, deve-se, sempre que possível,
+garantir que o código que não foi atualizado seja capturado pelo compilador.
+Isso ajudará você a ter certeza de que encontrou todos os usos dessa interface
+dentro da árvore (in-tree). Isso também alertará os desenvolvedores de códigos
+fora da árvore (out-of-tree) de que há uma mudança à qual eles precisam
+responder. Dar suporte a código fora da árvore não é algo com que os
+desenvolvedores do kernel precisem se preocupar, mas também não temos que
+tornar a vida dos desenvolvedores fora da árvore mais difícil do que precisa ser.
diff --git a/Documentation/translations/pt_BR/process/development-process.rst b/Documentation/translations/pt_BR/process/development-process.rst
index 599c34c85..71f151f36 100644
--- a/Documentation/translations/pt_BR/process/development-process.rst
+++ b/Documentation/translations/pt_BR/process/development-process.rst
@@ -20,3 +20,5 @@ conhecimento profundo de programação de kernel para ser compreendida.
1.Intro
2.Process
3.Early-stage
+ 4.Coding
+
--
2.47.3
^ permalink raw reply related
* [PATCH 2/2] docs: pt_BR: Translate patch posting documentation
From: Daniel Pereira @ 2026-06-14 23:50 UTC (permalink / raw)
To: Jonathan Corbet; +Cc: linux-doc, Daniel Pereira
In-Reply-To: <20260614235044.42810-1-danielmaraboo@gmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 22365 bytes --]
Translate the chapter regarding the process of formatting and sending
patches ("5.Posting.rst") into Brazilian Portuguese.
Also, update the main index in "development-process.rst" to include
the newly translated document into the documentation tree.
Signed-off-by: Daniel Pereira <danielmaraboo@gmail.com>
---
.../translations/pt_BR/process/5.Posting.rst | 376 ++++++++++++++++++
.../pt_BR/process/development-process.rst | 2 +-
2 files changed, 377 insertions(+), 1 deletion(-)
create mode 100644 Documentation/translations/pt_BR/process/5.Posting.rst
diff --git a/Documentation/translations/pt_BR/process/5.Posting.rst b/Documentation/translations/pt_BR/process/5.Posting.rst
new file mode 100644
index 000000000..820a56b66
--- /dev/null
+++ b/Documentation/translations/pt_BR/process/5.Posting.rst
@@ -0,0 +1,376 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Enviando patches
+================
+
+Cedo ou tarde, chega o momento em que seu trabalho está pronto para ser
+apresentado à comunidade para revisão e, eventualmente, inclusão no kernel
+mainline. Sem surpresa, a comunidade de desenvolvimento do kernel evoluiu um
+conjunto de convenções e procedimentos que são usados no envio de patches;
+segui-los tornará a vida muito mais fácil para todos os envolvidos. Este
+documento tentará cobrir essas expectativas em detalhes razoáveis; mais
+informações também podem ser encontradas nos arquivos
+:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+e :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`.
+
+
+Quando enviar
+-------------
+
+Existe uma tentação constante de evitar o envio de patches antes que eles
+estejam completamente "prontos". Para patches simples, isso não é um problema.
+No entanto, se o trabalho que está sendo feito for complexo, há muito a se
+ganhar obtendo feedback da comunidade antes que o trabalho esteja concluído.
+Portanto, você deve considerar o envio de trabalhos em andamento, ou até mesmo
+disponibilizar uma árvore git para que os desenvolvedores interessados possam
+acompanhar o seu trabalho a qualquer momento.
+
+Ao enviar um código que ainda não é considerado pronto para inclusão, é uma boa
+ideia dizer isso no próprio envio. Mencione também qualquer trabalho importante
+que ainda precise ser feito e quaisquer problemas conhecidos. Menos pessoas vão
+olhar para patches que sabidamente estão "meio cozidos" (half-baked), mas aqueles
+que o fizerem virão com a ideia de que podem ajudá-lo a conduzir o trabalho na
+direção certa.
+
+
+Antes de criar patches
+----------------------
+
+Há uma série de coisas que devem ser feitas antes de você considerar o envio
+de patches para la comunidade de desenvolvimento. Elas incluem:
+
+ - Teste o código tanto quanto puder. Faça uso das ferramentas de depuração
+ do kernel, garanta que o kernel seja compilado com todas as combinações
+ razoáveis de opções de configuração, use compiladores cruzados (cross-
+ compilers) para compilar para diferentes arquiteturas, etc. Adicione testes,
+ provavelmente usando um framework de testes existente como o KUnit, e
+ inclua-os como um membro separado da sua série (veja a próxima seção para
+ mais informações sobre séries de patches). Note que isso pode ser
+ obrigatório ao afetar alguns subsistemas. Por exemplo, funções de biblioteca
+ (localizadas sob lib/) são amplamente utilizadas em quase todos os lugares e
+ espera-se que sejam testadas adequadamente.
+
+ - Certifique-se de que seu código esteja em conformidade com as diretrizes de
+ estilo de codificação do kernel.
+
+ - Sua alteração tem implicações no desempenho? Se sim, você deve executar
+ benchmarks mostrando qual é o impacto (ou benefício) da sua mudança; um
+ resumo dos resultados deve ser incluído junto ao patch.
+
+ - Tenha certeza de que você tem o direito de enviar o código. Se este
+ trabalho foi feito para um empregador, o empregador provavelmente tem direito
+ sobre o trabalho e deve estar de acordo com a sua liberação sob a GPL.
+
+Como regra geral, dedicar um pouco de reflexão extra antes de enviar o código
+quase sempre compensa o esforço em pouco tempo.
+
+
+Preparação de patches
+---------------------
+
+A preparação de patches para envio pode dar uma quantidade surpreendente de
+trabalho, mas, mais uma vez, tentar economizar tempo aqui geralmente não é
+aconselhável, mesmo a curto prazo.
+
+Os patches devem ser preparados contra uma versão específica do kernel. Como
+regra geral, um patch deve ser baseado no mainline atual encontrado na árvore
+git do Linus. Ao basear-se no mainline, comece a partir de um ponto de
+lançamento bem conhecido — um release estável ou -rc —, em vez de criar uma
+bifurcação (branch) a partir do mainline em um ponto arbitrário.
+
+No entanto, pode tornar-se necessário criar versões contra a árvore -mm,
+linux-next ou a árvore de um subsistema, para facilitar testes e revisões mais
+amplos. Dependendo da área do seu patch e do que está acontecendo em outros
+lugares, basear um patch contra essas outras árvores pode exigir uma quantidade
+significativa de trabalho para resolver conflitos e lidar com mudanças de API.
+
+Apenas as alterações mais simples devem ser formatadas como um único patch; tudo
+o mais deve ser feito como uma série lógica de mudanças. Dividir patches é uma
+arte; alguns desenvolvedores passam muito tempo descobrindo como fazer isso da
+maneira que a comunidade espera. Existem algumas regras práticas, no entanto,
+que podem ajudar consideravelmente:
+
+ - A série de patches que você envia quase certamente não será a série de
+ alterações encontrada no seu sistema de controle de versão de trabalho. Em
+ vez disso, as mudanças que você fez precisam ser consideradas em sua forma
+ final e, então, divididas de maneiras que façam sentido. Os desenvolvedores
+ estão interessados em alterações discretas e autocontidas, não no caminho
+ que você percorreu para chegar a essas alterações.
+
+ - Cada alteração logicamente independente deve ser formatada como um patch separado.
+ Essas alterações podem ser pequenas ("adicionar um campo a esta estrutura") ou
+ grandes (adicionar um driver totalmente novo, por exemplo), mas devem ser
+ conceitualmente pequenas e passíveis de uma descrição de uma única linha. Cada
+ patch deve fazer uma alteração específica que possa ser revisada por si só e
+ verificada para garantir que faz o que diz fazer.
+
+ - Como uma forma de reafirmar a diretriz acima: não misture diferentes tipos de
+ alterações no mesmo patch. Se um único patch corrige uma falha crítica de
+ segurança, reorganiza algumas estruturas e reformatará o código, há uma grande
+ chance de que ele seja ignorado e a correção importante seja perdida.
+
+ - Cada patch deve resultar em um kernel que compile e funcione corretamente; se
+ sua série de patches for interrompida no meio, o resultado ainda deve ser um
+ kernel funcional. A aplicação parcial de uma série de patches é um cenário
+ comum quando a ferramenta "git bisect" é usada para encontrar regressões; se o
+ resultado for um kernel quebrado, você tornará a vida mais difícil para os
+ desenvolvedores e usuários que estão engajados no nobre trabalho de rastrear
+ problemas.
+
+ - No entanto, não exagere. Certa vez, um desenvolvedor enviou um conjunto de
+ edições em um único arquivo como 500 patches separados — um ato que não o
+ tornou a pessoa mais popular na lista de discussão do kernel. Um único patch
+ pode ser razoavelmente grande, desde que ainda contenha uma única alteração
+ *lógica*.
+
+ - Pode ser tentador adicionar toda uma nova infraestrutura com uma série de
+ patches, mas deixar essa infraestrutura sem uso até que o patch final da série
+ ative tudo. Essa tentação deve ser evitada, se possível; se essa série
+ adicionar regressões, a bisseção (bisection) apontará o último patch como aquele
+ que causou o problema, mesmo que o bug real esteja em outro lugar. Sempre que
+ possível, um patch que adiciona código novo deve tornar esse código ativo
+ imediatamente.
+
+Trabalhar para criar a série de patches perfeita pode ser um processo
+frustrante, que exige bastante tempo e reflexão após o "trabalho real" ter sido
+concluído. Quando feito corretamente, no entanto, é um tempo bem gasto.
+
+
+Formatação de patches e logs de alterações
+------------------------------------------
+
+Então agora você tem uma série perfeita de patches para enviar, mas o trabalho
+ainda não terminou. Cada patch precisa ser formatado em uma mensagem que comunique
+de forma rápida e clara o seu propósito para o resto do mundo. Para esse fim,
+cada patch será composto pelo seguinte:
+
+ - Uma linha "From" opcional que nomeia o autor do patch. Esta linha só é
+ necessária se você estiver repassando o patch de outra pessoa via e-mail,
+ mas nunca é demais adicioná-la em caso de dúvida.
+
+ - Uma descrição de uma única linha sobre o que o patch faz. Esta mensagem deve
+ ser suficiente para que um leitor que a veja sem outro contexto consiga
+ compreender o escopo do patch; esta é a linha que aparecerá nos logs de
+ alterações (changelogs) de "forma curta". Esta mensagem geralmente é formatada
+ com o nome do subsistema relevante primeiro, seguido pelo propósito do patch.
+ Por exemplo:
+
+ ::
+
+ gpio: fix build on CONFIG_GPIO_SYSFS=n
+
+ - Uma linha em branco seguida por uma descrição detalhada do conteúdo do
+ patch. Esta descrição pode ser tão longa quanto necessário; ela deve dizer
+ o que o patch faz e por que ele deve ser aplicado ao kernel.
+
+ - Uma ou mais linhas de marcadores (tags) com, no mínimo, uma linha
+ "Signed-off-by:" do autor do patch. Os marcadores serão descritos em mais
+ detalhes abaixo.
+
+Os itens acima, juntos, formam o log de alterações (changelog) do patch. Escrever
+bons changelogs é uma arte crucial, mas frequentemente negligenciada; vale a
+pena dedicar mais um momento para discutir esse assunto. Ao escrever um
+changelog, você deve ter em mente que várias pessoas diferentes lerão suas
+palavras. Elas incluem mantenedores de subsistemas e revisores que precisam
+decidir se o patch deve ser incluído, distribuidores e outros mantenedores
+tentando decidir se um patch deve ser retroportado (backported) para outros
+kernels, caçadores de bugs se perguntando se o patch é responsável por um
+problema que estão perseguindo, usuários que querem saber como o kernel mudou e
+muito mais. Um bom changelog transmite a informação necessária para todas essas
+pessoas da maneira mais direta e concisa possível.
+
+Para esse fim, a linha de resumo deve descrever os efeitos e a motivação da
+alteração o melhor possível, dada a restrição de uma única linha. A descrição
+detalhada pode então ampliar esses tópicos e fornecer qualquer informação
+adicional necessária. Se o patch corrige um bug, cite o commit que introduziu o
+bug, se possível (e, por favor, forneça tanto o ID do commit quanto o título ao
+citar commits). Se um problema estiver associado a uma saída específica de log
+ou do compilador, inclua essa saída para ajudar outras pessoas que buscam uma
+solução para o mesmo problema. Se a mudança tem o objetivo de dar suporte a
+outras alterações que virão em um patch posterior, informe isso. Se as APIs
+internas forem alteradas, detalhe essas mudanças e como outros desenvolvedores
+devem reagir. Em geral, quanto mais você puder se colocar no lugar de todos que
+lerão seu changelog, melhor será esse changelog (e o kernel como um todo).
+
+Desnecessário dizer que o changelog deve ser o texto usado ao submeter (commit)
+a alteração em um sistema de controle de versão. Ele será seguido por:
+
+ - O patch em si, no formato de patch unificado ("-u"). O uso da opção "-p" no
+ diff associará os nomes das funções às alterações, tornando o patch resultante
+ mais fácil de ser lido por outras pessoas.
+
+As tags já mencionadas brevemente acima são usados para fornecer
+informações sobre como o patch surgiu. Eles são descritos em detalhes no
+documento :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`;
+o que se segue aqui é um breve resumo.
+
+Um marcador é usado para se referir a commits anteriores que introduziram os
+problemas corrigidos pelo patch::
+
+ Fixes: 1f2e3d4c5b6a ("The first line of the commit specified by the first 12 characters of its SHA-1 ID")
+
+Outro marcador é usado para vincular páginas da web com contextos ou detalhes
+adicionais, por exemplo, uma discussão anterior que levou ao patch ou um
+documento com uma especificação implementada pelo patch::
+
+ Link: https://example.com/somewhere.html optional-other-stuff
+
+De acordo com as orientações do Pinguim-Chefe, um marcador Link
+só deve ser adicionado a um commit se ele levar a informações úteis que não
+são encontradas no próprio commit.
+
+Se a URL apontar para um relatório de bug público que está sendo corrigido pelo
+patch, use o marcador "Closes:" em seu lugar::
+
+ Closes: https://example.com/issues/1234 optional-other-stuff
+
+Alguns rastreadores de bugs têm a capacidade de fechar problemas de forma
+automática quando um commit com tal marcador é aplicado. Alguns bots que
+monitoram listas de discussão também podem rastrear esses marcadores e tomar certas
+ações. Rastreadores de bugs privados e URLs inválidas são proibidos.
+
+Outro tipo de marcador é usado para documentar quem esteve envolvido no
+desenvolvimento do patch. Cada um deles usa este formato::
+
+ tag: Full Name <email address> optional-other-stuff
+
+Os marcadores de uso comum são:
+
+ - Signed-off-by: esta é uma certificação do desenvolvedor de que ele ou ela
+ tem o direito de enviar o patch para inclusão no kernel. É um acordo com o
+ Developer's Certificate of Origin (Certificado de Origem do Desenvolvedor),
+ cujo texto completo pode ser encontrado em
+ :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`.
+ Códigos sem um signoff adequado não podem ser mesclados (merged) no mainline.
+
+ - Co-developed-by: afirma que o patch foi criado em coautoria por vários
+ desenvolvedores; é usado para dar atribuição aos coautores (além do autor
+ atribuído pelo marcador From:) quando várias pessoas trabalham em um único
+ patch. Cada Co-developed-by: deve ser imediatamente seguido por um
+ Signed-off-by: do coautor associado. Detalhes e exemplos podem ser encontrados
+ em :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`.
+
+ - Acked-by: indica o acordo de outro desenvolvedor (frequentemente um
+ mantenedor do código relevante) de que o patch é apropriado para inclusão
+ no kernel.
+
+ - Tested-by: afirma que a pessoa nomeada testou o patch e verificou que ele
+ funciona.
+
+ - Reviewed-by: o desenvolvedor nomeado revisou o patch para verificar sua
+ correção; veja a declaração do revisor em
+ :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+ para mais detalhes.
+
+ - Reported-by: nomeia um usuário que relatou o problema que é corrigido por este
+ patch; este marcador é usado para dar crédito às pessoas (frequentemente sub-
+ valorizadas) que testam nosso código e nos informam quando as coisas não
+ funcionam corretamente. Nota: este marcador deve ser seguido por um marcador
+ Closes: apontando para o relato, a menos que o relato não esteja disponível na
+ web. O marcador Link: pode ser usado em vez de Closes: se o patch corrigir
+ apenas uma parte do(s) problema(s) relatado(s).
+
+ - A Suggested-by: este marcador indica que a ideia do patch foi sugerida pela
+ pessoa nomeada e garante o crédito a ela pela ideia. Isso, espera-se, irá
+ inspirá-la a nos ajudar novamente no futuro.
+
+ - Cc: a pessoa nomeada recebeu uma cópia do patch e teve a oportunidade de
+ comentar sobre ele.
+
+Tenha cuidado ao adicionar os marcadores mencionados acima aos seus patches, pois
+todos, exceto Cc:, Reported-by: e Suggested-by:, precisam de permissão explícita
+fontes da pessoa nomeada. Para esses três, a permissão implícita é suficiente se
+a pessoa contribuiu para o kernel Linux usando esse nome e endereço de e-mail de
+acordo com os arquivos do lore ou o histórico de commits — e, no caso de
+Reported-by: e Suggested-by:, se fizeram o relato ou a sugestão publicamente.
+Nota: o bugzilla.kernel.org é um local público nesse sentido, mas os endereços
+de e-mail usados lá são privados; portanto, não os exponha em marcadores, a menos
+que a pessoa os tenha usado em contribuições anteriores.
+
+
+Enviando o patch
+-----------------
+
+Antes de enviar seus patches por e-mail, há algumas outras coisas com as quais
+você deve se preocupar:
+
+ - Você tem certeza de que seu cliente de e-mail não vai corromper os patches?
+ Patches que sofreram alterações desnecessárias de espaço em branco ou quebra
+ de linha causadas pelo cliente de e-mail não serão aplicados na outra ponta
+ e, frequentemente, não serão examinados em detalhes. Se houver qualquer
+ dúvida, envie o patch para você mesmo e certifique-se de que ele chegue intacto.
+
+ O documento :ref:`Documentation/process/email-clients.rst <email_clients>`
+ possui algumas dicas úteis sobre como fazer clientes de e-mail específicos
+ funcionarem para o envio de patches.
+
+ - Você tem certeza de que seu patch está livre de erros bobos? Você deve sempre
+ passar os patches pelo scripts/checkpatch.pl e corrigir as reclamações que
+ ele apresentar. Por favor, tenha em mente que o checkpatch.pl, embora seja a
+ personificação de uma quantidade razoável de reflexão sobre como os patches do
+ kernel devem parecer, não é mais inteligente que você. Se corrigir uma
+ reclamação do checkpatch.pl piorar o código, não o faça.
+
+Os patches devem sempre ser enviados como texto simples (plain text). Por favor,
+não os envie como anexos; isso torna muito mais difícil para os revisores citarem
+trechos do patch em suas respostas. Em vez disso, coloque o patch diretamente no
+corpo da sua mensagem.
+
+Ao enviar patches por e-mail, é importante enviar cópias para qualquer pessoa
+que possa estar interessada neles. Ao contrário de alguns outros projetos, o
+kernel incentiva as pessoas a pecarem pelo excesso, enviando cópias demais; não
+assuma que as pessoas relevantes verão sua publicação nas listas de discussão. Em
+particular, as cópias devem ir para:
+
+- O(s) mantenedor(es) do(s) subsistema(s) afetado(s). Como descrito antes, o
+ arquivo MAINTAINERS é o primeiro lugar para procurar por essas pessoas.
+
+ - Outros desenvolvedores que estiveram trabalhando na mesma área — especialmente
+ aqueles que possam estar trabalhando lá agora. Usar o git para ver quem mais
+ modificou os arquivos nos quais você está trabalhando pode ser útil.
+
+ - Se você estiver respondendo a um relato de bug ou a uma solicitação de recurso
+ (feature request), envie uma cópia também para o autor original.
+
+ - Envie uma cópia para a lista de discussão relevante ou, se nada mais se
+ aplicar, para a lista linux-kernel.
+
+ - Se você estiver corrigindo um bug, pense se a correção deve ir para a próxima
+ atualização estável (stable update). Se sim, stable@vger.kernel.org deve
+ receber uma cópia do patch. Adicione também um "Cc: stable@vger.kernel.org"
+ aos marcadores (tags) dentro do próprio patch; isso fará com que a equipe do
+ stable receba uma notificação quando sua correção for integrada ao mainline.
+
+Ao selecionar os destinatários para um patch, é bom ter uma ideia de quem você
+acha que eventualmente aceitará o patch e fará a mesclagem (merge). Embora seja
+possível enviar patches diretamente para Linus Torvalds e fazer com que ele os
+mescle, as coisas normalmente não são feitas dessa forma. Linus está ocupado, e
+existem mantenedores de subsistemas que vigiam partes específicas do kernel. Em
+geral, você desejará que esse mantenedor mescle seus patches. Se não houver um
+mantenedor óbvio, Andrew Morton costuma ser o destino de patch de último recurso.
+
+Os patches precisam de boas linhas de assunto (subject lines). O formato canônico
+para a linha de um patch é algo como:
+
+::
+
+
+ [PATCH nn/mm] subsys: descrição de uma linha do patch
+
+onde "nn" é o número ordinal do patch, "mm" é o número total de patches na
+série, e "subsys" é o nome do subsistema afetado. Claramente, nn/mm pode ser
+omitido no caso de um patch único e isolado (standalone).
+
+Se você tiver uma série significativa de patches, é costumeiro enviar uma
+descrição introdutória como a parte zero. Essa convenção não é seguida
+universalmente, no entanto; se você a utilizar, lembre-se de que as informações
+da introdução não entram nos changelogs do kernel. Portanto, certifique-se de
+que os patches, em si, possuam informações completas em seus changelogs.
+
+Em geral, a segunda parte e as subsequentes de um patch de múltiplas partes devem
+ser enviadas como uma resposta à primeira parte, de modo que todas formem uma
+única linha de discussão (thread) na ponta receptora. Ferramentas como o git e o
+quilt possuem comandos para enviar por e-mail um conjunto de patches com o
+encadeamento correto. Se você tiver uma série longa, contudo, e estiver usando o
+git, por favor, evite a opção --chain-reply-to para não criar um aninhamento
+excepcionalmente profundo.
diff --git a/Documentation/translations/pt_BR/process/development-process.rst b/Documentation/translations/pt_BR/process/development-process.rst
index 71f151f36..e9f04df62 100644
--- a/Documentation/translations/pt_BR/process/development-process.rst
+++ b/Documentation/translations/pt_BR/process/development-process.rst
@@ -21,4 +21,4 @@ conhecimento profundo de programação de kernel para ser compreendida.
2.Process
3.Early-stage
4.Coding
-
+ 5.Posting
--
2.47.3
^ permalink raw reply related
* Re: [PATCH] docs: pt_BR: update minimal software requirement for pahole in changes.rst
From: Daniel Pereira @ 2026-06-15 0:55 UTC (permalink / raw)
To: Amanda Corrêa; +Cc: Jonathan Corbet, Shuah Khan, linux-doc, linux-kernel
In-Reply-To: <20260614234320.8199-1-amandacorreasilvax@gmail.com>
Em dom., 14 de jun. de 2026 às 20:44, Amanda Corrêa
<amandacorreasilvax@gmail.com> escreveu:
>
> Update the Brazilian Portuguese translation of changes.rst to align with
> the latest English version.
>
> Key changes include:
> - Updated minimum version for pahole (1.26)
> - Added note about kfuncs annotated with KF_IMPLICIT_ARGS
> requiring pahole v1.26 or later
> - Changed "optional" to "opcional" in the software requirements
> table
>
> Signed-off-by: Amanda Corrêa <amandacorreasilvax@gmail.com>
Hi Amanda,
The grammar for Brazilian Portuguese is okay.
Thanks,
Acked-by: Daniel Pereira <danielmaraboo@gmail.com>
^ permalink raw reply
* [PATCH v4 0/7] tracing/probes: Add more typecast features
From: Masami Hiramatsu (Google) @ 2026-06-15 1:13 UTC (permalink / raw)
To: Steven Rostedt, Mathieu Desnoyers
Cc: Jonathan Corbet, Shuah Khan, Masami Hiramatsu, linux-kernel,
linux-trace-kernel, linux-doc, linux-kselftest
Hi,
Here is the 4th version of series to introduce more typecast features
to probe events. The previous version is here:
https://lore.kernel.org/all/178144880282.159464.16882854283219530040.stgit@devnote2/
In this version, I fixed some issues found by Sashiko reviews.
Steve introduced BTF typecast feature for eprobe[1].
This series extends it and add more options:
1. Expanding BTF typecast to kprobe and fprobe.
(currently only function entry/exit)
2. Introduce container_of like typecast. This adds a "assigned
member" option to the typecast.
(STRUCT,MEMBER)VAR->ANOTHER_MEMBER
This casts VAR to STRUCT type but the VAR is as the address
of STRUCT.MEMBER. In C, it is:
container_of(VAR, STRUCT, MEMBER)->ANOTHER_MEMBER
3. Support nested typecast, e.g.
(STRUCT)((STRUCT2)VAR->MEMBER2)->MEMBER
the nest level must be smaller than 3.
4. Add $current variable to point "current" task_struct.
This is useful with typecast, e.g.
(task_struct)$current->pid
5. per-cpu dereference support.
Intrdouce this_cpu_read(VAR) and this_cpu_ptr(VAR) to
access per-cpu data on the current CPU (accessing other CPU
data is not stable, because it can be changed.)
You can access the member of per-cpu data structure using
typecast like:
(STRUCT)this_cpu_ptr(VAR)->MEMBER
And added a test script to test part of them.
[1] https://lore.kernel.org/all/20260601130746.2139d926@gandalf.local.home/
---
Masami Hiramatsu (Google) (7):
tracing/events: Fix to check the simple_tsk_fn creation
tracing/probes: Support typecast for various probe events
tracing/probes: Support nested typecast
tracing/probes: Support field specifier option for typecast
tracing/probes: Add $current variable support
tracing/probes: Add this_cpu_read() and this_cpu_ptr() dereference method to fetcharg
tracing/probes: Add a new testcase for BTF typecasts
Documentation/trace/eprobetrace.rst | 9
Documentation/trace/fprobetrace.rst | 10
Documentation/trace/kprobetrace.rst | 11 +
kernel/trace/trace.c | 8
kernel/trace/trace_probe.c | 413 +++++++++++++++-----
kernel/trace/trace_probe.h | 19 +
kernel/trace/trace_probe_tmpl.h | 33 +-
samples/trace_events/trace-events-sample.c | 44 ++
samples/trace_events/trace-events-sample.h | 34 ++
.../ftrace/test.d/dynevent/btf_probe_event.tc | 51 ++
.../ftrace/test.d/dynevent/fprobe_syntax_errors.tc | 9
.../ftrace/test.d/kprobe/kprobe_syntax_errors.tc | 9
.../ftrace/test.d/kprobe/uprobe_syntax_errors.tc | 5
13 files changed, 540 insertions(+), 115 deletions(-)
create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/btf_probe_event.tc
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
^ permalink raw reply
* [PATCH v4 1/7] tracing/events: Fix to check the simple_tsk_fn creation
From: Masami Hiramatsu (Google) @ 2026-06-15 1:14 UTC (permalink / raw)
To: Steven Rostedt, Mathieu Desnoyers
Cc: Jonathan Corbet, Shuah Khan, Masami Hiramatsu, linux-kernel,
linux-trace-kernel, linux-doc, linux-kselftest
In-Reply-To: <178148603548.185520.3389196102475741865.stgit@devnote2>
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Sashiko pointed that this sample code does not correctly handle the
failure of thread creation because kthread_run() can return -errno.
Check the simple_tsk_fn is correctly initialized (created) or not.
Link: https://sashiko.dev/#/patchset/178092865666.163648.10457567771536160909.stgit%40devnote2
Fixes: 9cfe06f8cd5c ("tracing/events: add trace-events-sample")
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v4:
- Fix to remove decrementing counter in error path, since foo_bar_reg() always returns 0.
- Add a newline to error message.
Changes in v3:
- Recover the usage counter.
---
samples/trace_events/trace-events-sample.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/samples/trace_events/trace-events-sample.c b/samples/trace_events/trace-events-sample.c
index ecc7db237f2e..0b7a6efdb247 100644
--- a/samples/trace_events/trace-events-sample.c
+++ b/samples/trace_events/trace-events-sample.c
@@ -107,6 +107,10 @@ int foo_bar_reg(void)
* for consistency sake, we still take the thread_mutex.
*/
simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn");
+ if (IS_ERR_OR_NULL(simple_tsk_fn)) {
+ pr_err("Failed to create simple_thread_fn\n");
+ simple_tsk_fn = NULL;
+ }
out:
mutex_unlock(&thread_mutex);
return 0;
^ permalink raw reply related
* [PATCH v4 2/7] tracing/probes: Support typecast for various probe events
From: Masami Hiramatsu (Google) @ 2026-06-15 1:14 UTC (permalink / raw)
To: Steven Rostedt, Mathieu Desnoyers
Cc: Jonathan Corbet, Shuah Khan, Masami Hiramatsu, linux-kernel,
linux-trace-kernel, linux-doc, linux-kselftest
In-Reply-To: <178148603548.185520.3389196102475741865.stgit@devnote2>
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Support BTF typecast feature on other probe events, but only if it is
kernel function entry or return, and must use function parameter name
or $retval. This means you can do:
(STRUCT)PARAM->MEMBER
but you can not do (this should be enabled by nesting support)
(STRUCT)%reg->MEMBER
To support other probe events, we just need to use last_struct type
when we find a function parameter in parse_btf_arg().
This also update <tracefs>/README file to show struct typecast.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v3:
- Clarify the limitation.
Changes in v2:
- Fix to re-enable typecast on eprobe.
---
Documentation/trace/fprobetrace.rst | 3 +++
Documentation/trace/kprobetrace.rst | 4 ++++
kernel/trace/trace.c | 2 +-
kernel/trace/trace_probe.c | 14 +++++++++-----
kernel/trace/trace_probe.h | 5 +++++
5 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/Documentation/trace/fprobetrace.rst b/Documentation/trace/fprobetrace.rst
index b4c2ca3d02c1..7435ded2d66d 100644
--- a/Documentation/trace/fprobetrace.rst
+++ b/Documentation/trace/fprobetrace.rst
@@ -57,6 +57,9 @@ Synopsis of fprobe-events
(u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
(x8/x16/x32/x64), "char", "string", "ustring", "symbol", "symstr"
and bitfield are supported.
+ (STRUCT)FIELD->MEMBER[->MEMBER] : If BTF is supported, typecast FIELD to
+ a pointer to STRUCT and then derference the pointer defined by
+ ->MEMBER.
(\*1) This is available only when BTF is enabled.
(\*2) only for the probe on function entry (offs == 0). Note, this argument access
diff --git a/Documentation/trace/kprobetrace.rst b/Documentation/trace/kprobetrace.rst
index 3b6791c17e9b..f73614997d52 100644
--- a/Documentation/trace/kprobetrace.rst
+++ b/Documentation/trace/kprobetrace.rst
@@ -61,6 +61,10 @@ Synopsis of kprobe_events
(x8/x16/x32/x64), VFS layer common type(%pd/%pD), "char",
"string", "ustring", "symbol", "symstr" and bitfield are
supported.
+ (STRUCT)FIELD->MEMBER[->MEMBER] : If BTF is supported, typecast FIELD to
+ a pointer to STRUCT and then derference the pointer defined by
+ ->MEMBER. Note that this is available only when the probe is
+ on function entry.
(\*1) only for the probe on function entry (offs == 0). Note, this argument access
is best effort, because depending on the argument type, it may be passed on
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 6eb4d3097a4d..aa93e7b01146 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4325,7 +4325,7 @@ static const char readme_msg[] =
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
"\t $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
#ifdef CONFIG_PROBE_EVENTS_BTF_ARGS
- "\t <argname>[->field[->field|.field...]],\n"
+ "\t [(structname)]<argname>[->field[->field|.field...]],\n"
#endif
#else
"\t $stack<index>, $stack, $retval, $comm,\n"
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index fd1caa1f9723..9158f1f22a62 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -759,7 +759,10 @@ static int parse_btf_arg(char *varname,
return -ENOENT;
found:
- type = btf_type_skip_modifiers(ctx->btf, tid, &tid);
+ if (ctx->struct_btf)
+ type = ctx->last_struct;
+ else
+ type = btf_type_skip_modifiers(ctx->btf, tid, &tid);
found_type:
if (!type) {
trace_probe_log_err(ctx->offset, BAD_BTF_TID);
@@ -836,10 +839,11 @@ static int handle_typecast(char *arg, struct fetch_insn **pcode,
char *tmp;
int ret;
- /* Currently this only works for eprobes */
- if (!(ctx->flags & TPARG_FL_TEVENT)) {
- trace_probe_log_err(ctx->offset, TYPECAST_NOT_EVENT);
- return -EINVAL;
+ if (!(tparg_is_event_probe(ctx->flags) ||
+ tparg_is_function_entry(ctx->flags) ||
+ tparg_is_function_return(ctx->flags))) {
+ trace_probe_log_err(ctx->offset, NOSUP_BTFARG);
+ return -EOPNOTSUPP;
}
tmp = strchr(arg, ')');
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 15758cc11fc6..883938a74aee 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -414,6 +414,11 @@ static inline bool tparg_is_function_return(unsigned int flags)
return (flags & TPARG_FL_LOC_MASK) == (TPARG_FL_KERNEL | TPARG_FL_RETURN);
}
+static inline bool tparg_is_event_probe(unsigned int flags)
+{
+ return !!(flags & TPARG_FL_TEVENT);
+}
+
struct traceprobe_parse_context {
struct trace_event_call *event;
/* BTF related parameters */
^ permalink raw reply related
* [PATCH v4 3/7] tracing/probes: Support nested typecast
From: Masami Hiramatsu (Google) @ 2026-06-15 1:14 UTC (permalink / raw)
To: Steven Rostedt, Mathieu Desnoyers
Cc: Jonathan Corbet, Shuah Khan, Masami Hiramatsu, linux-kernel,
linux-trace-kernel, linux-doc, linux-kselftest
In-Reply-To: <178148603548.185520.3389196102475741865.stgit@devnote2>
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
When we hit an open parenthesis right after typecast closing
parenthesis, it means we have nested typecast. This allows us to
typecast a generic data member in a structure to a pointer to
another structure.
For example, to cast a DATA_MEMBER of VAR structure to STRUCT pointer
and get MEMBER value.
(STRUCT)(VAR->DATA_MEMBER)->MEMBER
Also, we can nest typecast.
(STRUCT1)((STRUCT2)$ARG->FIELD2)->FIELD1
Currently the max nest level is limited to 3.
This also allows user to use typecasting for registers or stacks on
kprobe events. e.g.
(STRUCT)(%ax)->MEMBER
(STRUCT)($stack0)->MEMBER
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v4:
- Use orig_offset for reporting NO_PTR_STRCT error.
Changes in v2:
- Fix to skip "->" after closing parenthetsis.
---
Documentation/trace/eprobetrace.rst | 2 +
Documentation/trace/fprobetrace.rst | 2 +
Documentation/trace/kprobetrace.rst | 2 +
kernel/trace/trace.c | 1
kernel/trace/trace_probe.c | 78 +++++++++++++++++++++++++++++++----
kernel/trace/trace_probe.h | 7 +++
6 files changed, 83 insertions(+), 9 deletions(-)
diff --git a/Documentation/trace/eprobetrace.rst b/Documentation/trace/eprobetrace.rst
index fe3602540569..cd0b4aa7f896 100644
--- a/Documentation/trace/eprobetrace.rst
+++ b/Documentation/trace/eprobetrace.rst
@@ -50,6 +50,8 @@ Synopsis of eprobe_events
a pointer to STRUCT and then derference the pointer defined by
->MEMBER. Note that when this is used, the FIELD name does not
need to be prefixed with a '$'.
+ (STRUCT)(FETCHARG)->MEMBER[->MEMBER] : typecast can nest, so the above can
+ also be used with another FETCHARG instead of FIELD.
Types
-----
diff --git a/Documentation/trace/fprobetrace.rst b/Documentation/trace/fprobetrace.rst
index 7435ded2d66d..6b8bb27bb62d 100644
--- a/Documentation/trace/fprobetrace.rst
+++ b/Documentation/trace/fprobetrace.rst
@@ -60,6 +60,8 @@ Synopsis of fprobe-events
(STRUCT)FIELD->MEMBER[->MEMBER] : If BTF is supported, typecast FIELD to
a pointer to STRUCT and then derference the pointer defined by
->MEMBER.
+ (STRUCT)(FETCHARG)->MEMBER[->MEMBER] : typecast can nest, so the above can
+ also be used with another FETCHARG instead of FIELD.
(\*1) This is available only when BTF is enabled.
(\*2) only for the probe on function entry (offs == 0). Note, this argument access
diff --git a/Documentation/trace/kprobetrace.rst b/Documentation/trace/kprobetrace.rst
index f73614997d52..c4382765d5b2 100644
--- a/Documentation/trace/kprobetrace.rst
+++ b/Documentation/trace/kprobetrace.rst
@@ -65,6 +65,8 @@ Synopsis of kprobe_events
a pointer to STRUCT and then derference the pointer defined by
->MEMBER. Note that this is available only when the probe is
on function entry.
+ (STRUCT)(FETCHARG)->MEMBER[->MEMBER] : typecast can nest, so the above can
+ also be used with another FETCHARG instead of FIELD.
(\*1) only for the probe on function entry (offs == 0). Note, this argument access
is best effort, because depending on the argument type, it may be passed on
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index aa93e7b01146..4f70318918c2 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4326,6 +4326,7 @@ static const char readme_msg[] =
"\t $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
#ifdef CONFIG_PROBE_EVENTS_BTF_ARGS
"\t [(structname)]<argname>[->field[->field|.field...]],\n"
+ "\t [(structname)](fetcharg)->field[->field|.field...],\n"
#endif
#else
"\t $stack<index>, $stack, $retval, $comm,\n"
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index 9158f1f22a62..adcb5a19e72d 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -832,10 +832,35 @@ static int query_btf_struct(const char *sname, struct traceprobe_parse_context *
return 0;
}
+/* Find the matching closing parenthesis for a given opening parenthesis. */
+static char *find_matched_close_paren(char *s)
+{
+ char *p = s;
+ int count = 0;
+
+ while (*p) {
+ if (*p == '(')
+ count++;
+ else if (*p == ')') {
+ if (--count == 0)
+ return p;
+ }
+ p++;
+ }
+ return NULL;
+}
+
+static int
+parse_probe_arg(char *arg, const struct fetch_type *type,
+ struct fetch_insn **pcode, struct fetch_insn *end,
+ struct traceprobe_parse_context *ctx);
+
static int handle_typecast(char *arg, struct fetch_insn **pcode,
struct fetch_insn *end,
struct traceprobe_parse_context *ctx)
{
+ int orig_offset = ctx->offset;
+ bool nested = false;
char *tmp;
int ret;
@@ -852,19 +877,56 @@ static int handle_typecast(char *arg, struct fetch_insn **pcode,
DEREF_OPEN_BRACE);
return -EINVAL;
}
- *tmp = '\0';
- ret = query_btf_struct(arg + 1, ctx);
- *tmp = ')';
+ *tmp++ = '\0';
+
+ /* Handle the nested structure like (STRUCT)(VAR->FIELD)->... */
+ if (*tmp == '(') {
+ char *close = find_matched_close_paren(tmp);
+
+ ctx->offset += tmp - arg;
+ if (!close) {
+ trace_probe_log_err(ctx->offset, DEREF_OPEN_BRACE);
+ return -EINVAL;
+ }
+ /* We expect a field access for typecast */
+ if (close[1] != '-' || close[2] != '>') {
+ trace_probe_log_err(ctx->offset + close - tmp + 1,
+ TYPECAST_REQ_FIELD);
+ return -EINVAL;
+ }
+ ctx->nested_level++;
+ if (ctx->nested_level > TRACEPROBE_MAX_NESTED_LEVEL) {
+ trace_probe_log_err(ctx->offset, TOO_MANY_NESTED);
+ return -E2BIG;
+ }
+ *close = '\0';
+
+ ctx->offset += 1; /* for the '(' */
+ /* We need to parse the nested one */
+ ret = parse_probe_arg(tmp + 1, find_fetch_type(NULL, ctx->flags),
+ pcode, end, ctx);
+ if (ret < 0)
+ return ret;
+ ctx->nested_level--;
+ clear_struct_btf(ctx);
+
+ tmp = close + 3;/* Skip "->" after closing parenthesis */
+ nested = true;
+ }
+
+ ret = query_btf_struct(arg + 1, ctx);
if (ret < 0) {
- trace_probe_log_err(ctx->offset + 1, NO_PTR_STRCT);
+ trace_probe_log_err(orig_offset + 1, NO_PTR_STRCT);
return -EINVAL;
}
- tmp++;
-
- ctx->offset += tmp - arg;
- ret = parse_btf_arg(tmp, pcode, end, ctx);
+ ctx->offset = orig_offset + tmp - arg;
+ /* If it is nested, tmp points to the field name. */
+ if (nested)
+ ret = parse_btf_field(tmp, ctx->last_struct, pcode, end, ctx);
+ else
+ ret = parse_btf_arg(tmp, pcode, end, ctx);
return ret;
}
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 883938a74aee..982d32a5df8b 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -435,8 +435,11 @@ struct traceprobe_parse_context {
struct trace_probe *tp;
unsigned int flags;
int offset;
+ int nested_level;
};
+#define TRACEPROBE_MAX_NESTED_LEVEL 3
+
extern int traceprobe_parse_probe_arg(struct trace_probe *tp, int i,
const char *argv,
struct traceprobe_parse_context *ctx);
@@ -571,7 +574,9 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
C(TOO_MANY_ARGS, "Too many arguments are specified"), \
C(TOO_MANY_EARGS, "Too many entry arguments specified"), \
C(EVENT_TOO_BIG, "Event too big (too many fields?)"), \
- C(TYPECAST_NOT_EVENT, "Typecasts are only for eprobe fields"),
+ C(TYPECAST_NOT_EVENT, "Typecasts are only for eprobe fields"), \
+ C(TYPECAST_REQ_FIELD, "Typecast requires a field access"), \
+ C(TOO_MANY_NESTED, "Too many nested typecasts/dereferences"),
#undef C
#define C(a, b) TP_ERR_##a
^ permalink raw reply related
* [PATCH v4 4/7] tracing/probes: Support field specifier option for typecast
From: Masami Hiramatsu (Google) @ 2026-06-15 1:14 UTC (permalink / raw)
To: Steven Rostedt, Mathieu Desnoyers
Cc: Jonathan Corbet, Shuah Khan, Masami Hiramatsu, linux-kernel,
linux-trace-kernel, linux-doc, linux-kselftest
In-Reply-To: <178148603548.185520.3389196102475741865.stgit@devnote2>
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Add a field specifier option for the typecast. This works like
container_of() macro.
(STRUCT[,FIELD[.FIELD2...]])VAR
This is equivalent to :
container_of(VAR, struct STRUCT, FIELD[.FIELD2...])
For example:
echo "f tick_nohz_handler next_tick=(tick_sched,sched_timer)timer->next_tick" >> dynamic_events
This will trace tick_nohz_handler() with its tick_sched::next_tick which
is converted from @timer by contianer_of(tick, struct tick_sched, sched_timer).
So, if you enabkle both fprobes:tick_nohz_handler__entry and
timer:hrtimer_expire_entry events, we will see something like:
<idle>-0 [002] d.h1. 3778.087272: hrtimer_expire_entry: hrtimer=00000000d63db328 f
unction=tick_nohz_handler now=3777450051040
<idle>-0 [002] d.h1. 3778.087281: tick_nohz_handler__entry: (tick_nohz_handler+0x4
/0x140) next_tick=3777450000000
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v3:
- Fix error caret position.
Changes in v2:
- Use byteoffset for typecast field offset instead of bitoffset. This fixes negative modulo calculation.
- Check whether a field is specified after typecast.
- Reject if typecast field option has arrow operator.
---
Documentation/trace/eprobetrace.rst | 5 +
Documentation/trace/fprobetrace.rst | 8 +-
Documentation/trace/kprobetrace.rst | 8 +-
kernel/trace/trace.c | 4 -
kernel/trace/trace_probe.c | 179 ++++++++++++++++++++++++-----------
kernel/trace/trace_probe.h | 5 +
6 files changed, 142 insertions(+), 67 deletions(-)
diff --git a/Documentation/trace/eprobetrace.rst b/Documentation/trace/eprobetrace.rst
index cd0b4aa7f896..680e0af43d5d 100644
--- a/Documentation/trace/eprobetrace.rst
+++ b/Documentation/trace/eprobetrace.rst
@@ -49,7 +49,10 @@ Synopsis of eprobe_events
(STRUCT)FIELD->MEMBER[->MEMBER] : If BTF is supported, typecast FIELD to
a pointer to STRUCT and then derference the pointer defined by
->MEMBER. Note that when this is used, the FIELD name does not
- need to be prefixed with a '$'.
+ need to be prefixed with a '$'. ASGN can be specified optionally.
+ If ASGN is specified, FIELD will be cast to the same offset
+ position as the ASGN member, rather than to the beginning of
+ the STRUCT.
(STRUCT)(FETCHARG)->MEMBER[->MEMBER] : typecast can nest, so the above can
also be used with another FETCHARG instead of FIELD.
diff --git a/Documentation/trace/fprobetrace.rst b/Documentation/trace/fprobetrace.rst
index 6b8bb27bb62d..290a9e6f7491 100644
--- a/Documentation/trace/fprobetrace.rst
+++ b/Documentation/trace/fprobetrace.rst
@@ -57,10 +57,12 @@ Synopsis of fprobe-events
(u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
(x8/x16/x32/x64), "char", "string", "ustring", "symbol", "symstr"
and bitfield are supported.
- (STRUCT)FIELD->MEMBER[->MEMBER] : If BTF is supported, typecast FIELD to
+ (STRUCT[,ASGN])FIELD->MEMBER[->MEMBER] : If BTF is supported, typecast FIELD to
a pointer to STRUCT and then derference the pointer defined by
- ->MEMBER.
- (STRUCT)(FETCHARG)->MEMBER[->MEMBER] : typecast can nest, so the above can
+ ->MEMBER. ASGN can be specified optionally. If ASGN is specified,
+ FIELD will be cast to the same offset position as the ASGN member,
+ rather than to the beginning of the STRUCT.
+ (STRUCT[,ASGN])(FETCHARG)->MEMBER[->MEMBER] : typecast can nest, so the above can
also be used with another FETCHARG instead of FIELD.
(\*1) This is available only when BTF is enabled.
diff --git a/Documentation/trace/kprobetrace.rst b/Documentation/trace/kprobetrace.rst
index c4382765d5b2..a62707e6a9f2 100644
--- a/Documentation/trace/kprobetrace.rst
+++ b/Documentation/trace/kprobetrace.rst
@@ -61,11 +61,13 @@ Synopsis of kprobe_events
(x8/x16/x32/x64), VFS layer common type(%pd/%pD), "char",
"string", "ustring", "symbol", "symstr" and bitfield are
supported.
- (STRUCT)FIELD->MEMBER[->MEMBER] : If BTF is supported, typecast FIELD to
+ (STRUCT[,ASGN])FIELD->MEMBER[->MEMBER] : If BTF is supported, typecast FIELD to
a pointer to STRUCT and then derference the pointer defined by
->MEMBER. Note that this is available only when the probe is
- on function entry.
- (STRUCT)(FETCHARG)->MEMBER[->MEMBER] : typecast can nest, so the above can
+ on function entry. ASGN can be specified optionally. If ASGN
+ is specified, FIELD will be cast to the same offset position
+ as the ASGN member, rather than to the beginning of the STRUCT.
+ (STRUCT[,ASGN])(FETCHARG)->MEMBER[->MEMBER] : typecast can nest, so the above can
also be used with another FETCHARG instead of FIELD.
(\*1) only for the probe on function entry (offs == 0). Note, this argument access
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 4f70318918c2..0e36af853199 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4325,8 +4325,8 @@ static const char readme_msg[] =
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
"\t $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
#ifdef CONFIG_PROBE_EVENTS_BTF_ARGS
- "\t [(structname)]<argname>[->field[->field|.field...]],\n"
- "\t [(structname)](fetcharg)->field[->field|.field...],\n"
+ "\t [(structname[,field])]<argname>[->field[->field|.field...]],\n"
+ "\t [(structname[,field])](fetcharg)->field[->field|.field...],\n"
#endif
#else
"\t $stack<index>, $stack, $retval, $comm,\n"
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index adcb5a19e72d..3ead93de2d93 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -574,6 +574,65 @@ static int split_next_field(char *varname, char **next_field,
return ret;
}
+/* Inner loop for solving dot operator ('.'). Return bit-offset of the given field */
+static int get_bitoffset_of_field(char **pfieldname, const struct btf_type **ptype,
+ struct traceprobe_parse_context *ctx)
+{
+ const struct btf_type *type = *ptype;
+ const struct btf_member *field;
+ struct btf *btf = ctx_btf(ctx);
+ char *fieldname = *pfieldname;
+ int bitoffs = 0;
+ u32 anon_offs;
+ char *next;
+ int is_ptr;
+ s32 tid;
+
+ do {
+ next = NULL;
+ is_ptr = split_next_field(fieldname, &next, ctx);
+ if (is_ptr < 0)
+ return is_ptr;
+
+ anon_offs = 0;
+ field = btf_find_struct_member(btf, type, fieldname,
+ &anon_offs);
+ if (IS_ERR(field)) {
+ trace_probe_log_err(ctx->offset, BAD_BTF_TID);
+ return PTR_ERR(field);
+ }
+ if (!field) {
+ trace_probe_log_err(ctx->offset, NO_BTF_FIELD);
+ return -ENOENT;
+ }
+ /* Add anonymous structure/union offset */
+ bitoffs += anon_offs;
+
+ /* Accumulate the bit-offsets of the dot-connected fields */
+ if (btf_type_kflag(type)) {
+ bitoffs += BTF_MEMBER_BIT_OFFSET(field->offset);
+ ctx->last_bitsize = BTF_MEMBER_BITFIELD_SIZE(field->offset);
+ } else {
+ bitoffs += field->offset;
+ ctx->last_bitsize = 0;
+ }
+
+ type = btf_type_skip_modifiers(btf, field->type, &tid);
+ if (!type) {
+ trace_probe_log_err(ctx->offset, BAD_BTF_TID);
+ return -EINVAL;
+ }
+
+ if (next)
+ ctx->offset += next - fieldname;
+ fieldname = next;
+ } while (!is_ptr && fieldname);
+
+ *pfieldname = fieldname;
+ *ptype = type;
+
+ return bitoffs;
+}
/*
* Parse the field of data structure. The @type must be a pointer type
* pointing the target data structure type.
@@ -583,16 +642,14 @@ static int parse_btf_field(char *fieldname, const struct btf_type *type,
struct traceprobe_parse_context *ctx)
{
struct fetch_insn *code = *pcode;
- const struct btf_member *field;
- u32 bitoffs, anon_offs;
- bool is_struct = ctx->struct_btf != NULL;
struct btf *btf = ctx_btf(ctx);
- char *next;
- int is_ptr;
+ bool is_first_field = true;
+ int bitoffs;
s32 tid;
do {
- if (!is_struct) {
+ /* For the first field of typecast, @type will be the target structure type. */
+ if (!(is_first_field && ctx->struct_btf)) {
/* Outer loop for solving arrow operator ('->') */
if (BTF_INFO_KIND(type->info) != BTF_KIND_PTR) {
trace_probe_log_err(ctx->offset, NO_PTR_STRCT);
@@ -606,60 +663,25 @@ static int parse_btf_field(char *fieldname, const struct btf_type *type,
return -EINVAL;
}
}
- /* Only the first type can skip being a pointer */
- is_struct = false;
-
- bitoffs = 0;
- do {
- /* Inner loop for solving dot operator ('.') */
- next = NULL;
- is_ptr = split_next_field(fieldname, &next, ctx);
- if (is_ptr < 0)
- return is_ptr;
-
- anon_offs = 0;
- field = btf_find_struct_member(btf, type, fieldname,
- &anon_offs);
- if (IS_ERR(field)) {
- trace_probe_log_err(ctx->offset, BAD_BTF_TID);
- return PTR_ERR(field);
- }
- if (!field) {
- trace_probe_log_err(ctx->offset, NO_BTF_FIELD);
- return -ENOENT;
- }
- /* Add anonymous structure/union offset */
- bitoffs += anon_offs;
-
- /* Accumulate the bit-offsets of the dot-connected fields */
- if (btf_type_kflag(type)) {
- bitoffs += BTF_MEMBER_BIT_OFFSET(field->offset);
- ctx->last_bitsize = BTF_MEMBER_BITFIELD_SIZE(field->offset);
- } else {
- bitoffs += field->offset;
- ctx->last_bitsize = 0;
- }
-
- type = btf_type_skip_modifiers(btf, field->type, &tid);
- if (!type) {
- trace_probe_log_err(ctx->offset, BAD_BTF_TID);
- return -EINVAL;
- }
-
- ctx->offset += next - fieldname;
- fieldname = next;
- } while (!is_ptr && fieldname);
+ bitoffs = get_bitoffset_of_field(&fieldname, &type, ctx);
+ if (bitoffs < 0)
+ return bitoffs;
if (++code == end) {
trace_probe_log_err(ctx->offset, TOO_MANY_OPS);
return -EINVAL;
}
code->op = FETCH_OP_DEREF; /* TODO: user deref support */
code->offset = bitoffs / 8;
+ if (is_first_field && ctx->struct_btf) {
+ /* The first field can be typecasted with field option. */
+ code->offset -= ctx->prefix_byteoffs;
+ }
*pcode = code;
ctx->last_bitoffs = bitoffs % 8;
ctx->last_type = type;
+ is_first_field = false;
} while (fieldname);
return 0;
@@ -690,6 +712,11 @@ static int parse_btf_arg(char *varname,
NOSUP_DAT_ARG);
return -EOPNOTSUPP;
}
+ if (!field && ctx->struct_btf) {
+ /* Typecast without field option is not supported */
+ trace_probe_log_err(ctx->offset + strlen(varname), TYPECAST_REQ_FIELD);
+ return -EOPNOTSUPP;
+ }
if (ctx->flags & TPARG_FL_TEVENT) {
ret = parse_trace_event(varname, code, ctx);
@@ -700,8 +727,7 @@ static int parse_btf_arg(char *varname,
/* TEVENT is only here via a typecast */
if (WARN_ON_ONCE(ctx->struct_btf == NULL))
return -EINVAL;
- type = ctx->last_struct;
- goto found_type;
+ goto found;
}
if (ctx->flags & TPARG_FL_RETURN && !strcmp(varname, "$retval")) {
@@ -763,7 +789,6 @@ static int parse_btf_arg(char *varname,
type = ctx->last_struct;
else
type = btf_type_skip_modifiers(ctx->btf, tid, &tid);
-found_type:
if (!type) {
trace_probe_log_err(ctx->offset, BAD_BTF_TID);
return -EINVAL;
@@ -832,6 +857,46 @@ static int query_btf_struct(const char *sname, struct traceprobe_parse_context *
return 0;
}
+static int parse_btf_casttype(char *casttype, struct traceprobe_parse_context *ctx)
+{
+ char *field;
+ int ret;
+
+ /* Field option - evaluated later. */
+ field = strchr(casttype, ',');
+ if (field)
+ *field++ = '\0';
+
+ ret = query_btf_struct(casttype, ctx);
+ if (ret < 0) {
+ trace_probe_log_err(ctx->offset, NO_PTR_STRCT);
+ return -EINVAL;
+ }
+
+ if (field) {
+ struct btf_type *type = (struct btf_type *)ctx->last_struct;
+
+ ctx->offset += field - casttype;
+ ret = get_bitoffset_of_field(&field, &ctx->last_struct, ctx);
+ if (ret < 0)
+ return ret;
+ if (ret % 8) {
+ trace_probe_log_err(ctx->offset, TYPECAST_NOT_ALIGNED);
+ return -EINVAL;
+ }
+ if (field != NULL) {
+ /* this means @field skips an arrow operator ("->"). */
+ trace_probe_log_err(ctx->offset - 2, TYPECAST_BAD_ARROW);
+ return -EINVAL;
+ }
+ ctx->prefix_byteoffs = ret / 8;
+ /* Restore the original struct type (overwritten by get_bitoffset_of_field) */
+ ctx->last_struct = type;
+ }
+
+ return ret;
+}
+
/* Find the matching closing parenthesis for a given opening parenthesis. */
static char *find_matched_close_paren(char *s)
{
@@ -915,11 +980,10 @@ static int handle_typecast(char *arg, struct fetch_insn **pcode,
nested = true;
}
- ret = query_btf_struct(arg + 1, ctx);
- if (ret < 0) {
- trace_probe_log_err(orig_offset + 1, NO_PTR_STRCT);
- return -EINVAL;
- }
+ ctx->offset = orig_offset + 1; /* for the '(' */
+ ret = parse_btf_casttype(arg + 1, ctx);
+ if (ret < 0)
+ return ret;
ctx->offset = orig_offset + tmp - arg;
/* If it is nested, tmp points to the field name. */
@@ -927,6 +991,7 @@ static int handle_typecast(char *arg, struct fetch_insn **pcode,
ret = parse_btf_field(tmp, ctx->last_struct, pcode, end, ctx);
else
ret = parse_btf_arg(tmp, pcode, end, ctx);
+ ctx->prefix_byteoffs = 0;
return ret;
}
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 982d32a5df8b..44f113faae61 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -436,6 +436,7 @@ struct traceprobe_parse_context {
unsigned int flags;
int offset;
int nested_level;
+ int prefix_byteoffs; /* The byte offset of the prefix field of typecast */
};
#define TRACEPROBE_MAX_NESTED_LEVEL 3
@@ -576,7 +577,9 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
C(EVENT_TOO_BIG, "Event too big (too many fields?)"), \
C(TYPECAST_NOT_EVENT, "Typecasts are only for eprobe fields"), \
C(TYPECAST_REQ_FIELD, "Typecast requires a field access"), \
- C(TOO_MANY_NESTED, "Too many nested typecasts/dereferences"),
+ C(TOO_MANY_NESTED, "Too many nested typecasts/dereferences"), \
+ C(TYPECAST_NOT_ALIGNED, "Typecast field option is not byte-aligned"), \
+ C(TYPECAST_BAD_ARROW, "Typecast field option does not support -> operator"),
#undef C
#define C(a, b) TP_ERR_##a
^ permalink raw reply related
* [PATCH v4 5/7] tracing/probes: Add $current variable support
From: Masami Hiramatsu (Google) @ 2026-06-15 1:14 UTC (permalink / raw)
To: Steven Rostedt, Mathieu Desnoyers
Cc: Jonathan Corbet, Shuah Khan, Masami Hiramatsu, linux-kernel,
linux-trace-kernel, linux-doc, linux-kselftest
In-Reply-To: <178148603548.185520.3389196102475741865.stgit@devnote2>
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Since we can use the BTF to cast value to a structure pointer type,
it is useful to introduce "$current" special variable support to
fetcharg.
User can define a fetcharg to access current task_struct properties
using BTF info. e.g.
$current->cpus_ptr
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v4:
- Add $current in README when CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y case.
- Fix to prohibit using $current in eprobes and address based kprobes.
Changes in v3:
- Remove $current support from eprobes (because eprobes is only for event)
- Prohibit uprobes to use $current.
Changes in v2:
- Support to parse $current in parse_btf_arg().
- If no typecast on $current, it automatically casted to task_struct.
- Check error case if $current follows something except for "-".
---
Documentation/trace/fprobetrace.rst | 1 +
Documentation/trace/kprobetrace.rst | 1 +
kernel/trace/trace.c | 4 ++--
kernel/trace/trace_probe.c | 34 +++++++++++++++++++++++++++++++++-
kernel/trace/trace_probe.h | 1 +
kernel/trace/trace_probe_tmpl.h | 3 +++
6 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/Documentation/trace/fprobetrace.rst b/Documentation/trace/fprobetrace.rst
index 290a9e6f7491..3392cab016b3 100644
--- a/Documentation/trace/fprobetrace.rst
+++ b/Documentation/trace/fprobetrace.rst
@@ -50,6 +50,7 @@ Synopsis of fprobe-events
$argN : Fetch the Nth function argument. (N >= 1) (\*2)
$retval : Fetch return value.(\*3)
$comm : Fetch current task comm.
+ $current : Fetch the address of the current task_struct.
+|-[u]OFFS(FETCHARG) : Fetch memory at FETCHARG +|- OFFS address.(\*4)(\*5)
\IMM : Store an immediate value to the argument.
NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
diff --git a/Documentation/trace/kprobetrace.rst b/Documentation/trace/kprobetrace.rst
index a62707e6a9f2..81e4fe38791d 100644
--- a/Documentation/trace/kprobetrace.rst
+++ b/Documentation/trace/kprobetrace.rst
@@ -53,6 +53,7 @@ Synopsis of kprobe_events
$argN : Fetch the Nth function argument. (N >= 1) (\*1)
$retval : Fetch return value.(\*2)
$comm : Fetch current task comm.
+ $current : Fetch the address of the current task_struct.
+|-[u]OFFS(FETCHARG) : Fetch memory at FETCHARG +|- OFFS address.(\*3)(\*4)
\IMM : Store an immediate value to the argument.
NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 0e36af853199..7a5676524f1a 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4323,13 +4323,13 @@ static const char readme_msg[] =
"\t args: <name>=fetcharg[:type]\n"
"\t fetcharg: (%<register>|$<efield>), @<address>, @<symbol>[+|-<offset>],\n"
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
- "\t $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
+ "\t $stack<index>, $stack, $retval, $comm, $arg<N>, $current\n"
#ifdef CONFIG_PROBE_EVENTS_BTF_ARGS
"\t [(structname[,field])]<argname>[->field[->field|.field...]],\n"
"\t [(structname[,field])](fetcharg)->field[->field|.field...],\n"
#endif
#else
- "\t $stack<index>, $stack, $retval, $comm,\n"
+ "\t $stack<index>, $stack, $retval, $comm, $current\n"
#endif
"\t +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n"
"\t kernel return probes support: $retval, $arg<N>, $comm\n"
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index 3ead93de2d93..f5155340a325 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -730,6 +730,20 @@ static int parse_btf_arg(char *varname,
goto found;
}
+ if (strcmp(varname, "$current") == 0) {
+ code->op = FETCH_OP_CURRENT;
+ /* If no typecast is specified for $current, use task_struct by default */
+ if (!ctx->struct_btf) {
+ tid = bpf_find_btf_id("task_struct", BTF_KIND_STRUCT, &ctx->struct_btf);
+ if (tid < 0) {
+ trace_probe_log_err(ctx->offset, NO_BTF_ENTRY);
+ return -ENOENT;
+ }
+ ctx->last_struct = btf_type_skip_modifiers(ctx->struct_btf, tid, &tid);
+ }
+ goto found;
+ }
+
if (ctx->flags & TPARG_FL_RETURN && !strcmp(varname, "$retval")) {
code->op = FETCH_OP_RETVAL;
/* Check whether the function return type is not void */
@@ -756,8 +770,8 @@ static int parse_btf_arg(char *varname,
return -ENOENT;
}
}
- params = ctx->params;
+ params = ctx->params;
for (i = 0; i < ctx->nr_params; i++) {
const char *name = btf_name_by_offset(ctx->btf, params[i].name_off);
@@ -1247,6 +1261,24 @@ static int parse_probe_vars(char *orig_arg, const struct fetch_type *t,
return 0;
}
+ /* $current returns the address of the current task_struct. */
+ if (str_has_prefix(arg, "current")) {
+ /* $current is only supported by kernel probe and need function name. */
+ if (!(ctx->flags & TPARG_FL_KERNEL) || !ctx->funcname) {
+ err = TP_ERR_BAD_VAR;
+ goto inval;
+ }
+ arg += strlen("current");
+ if (*arg == '-' && IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS))
+ return parse_btf_arg(orig_arg, pcode, end, ctx);
+
+ if (*arg != '\0')
+ goto inval;
+
+ code->op = FETCH_OP_CURRENT;
+ return 0;
+ }
+
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
len = str_has_prefix(arg, "arg");
if (len) {
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 44f113faae61..62645e847bd1 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -96,6 +96,7 @@ enum fetch_op {
FETCH_OP_FOFFS, /* File offset: .immediate */
FETCH_OP_DATA, /* Allocated data: .data */
FETCH_OP_EDATA, /* Entry data: .offset */
+ FETCH_OP_CURRENT, /* Current task_struct address */
// Stage 2 (dereference) op
FETCH_OP_DEREF, /* Dereference: .offset */
FETCH_OP_UDEREF, /* User-space Dereference: .offset */
diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h
index f39b37fcdb3b..f630930288d2 100644
--- a/kernel/trace/trace_probe_tmpl.h
+++ b/kernel/trace/trace_probe_tmpl.h
@@ -112,6 +112,9 @@ process_common_fetch_insn(struct fetch_insn *code, unsigned long *val)
case FETCH_OP_DATA:
*val = (unsigned long)code->data;
break;
+ case FETCH_OP_CURRENT:
+ *val = (unsigned long)current;
+ break;
default:
return -EILSEQ;
}
^ permalink raw reply related
* [PATCH v4 6/7] tracing/probes: Add this_cpu_read() and this_cpu_ptr() dereference method to fetcharg
From: Masami Hiramatsu (Google) @ 2026-06-15 1:14 UTC (permalink / raw)
To: Steven Rostedt, Mathieu Desnoyers
Cc: Jonathan Corbet, Shuah Khan, Masami Hiramatsu, linux-kernel,
linux-trace-kernel, linux-doc, linux-kselftest
In-Reply-To: <178148603548.185520.3389196102475741865.stgit@devnote2>
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
When tracing the kernel local variables, sometimes we need to get the
CPU local variables. To access it, current simple dereference is not
enough.
Thus, introduce a special this_cpu_read() dereference to access per-cpu
variable for the current CPU (accessing other CPU variable may race with
updates on other CPUs). Also this_cpu_ptr() is for accessing per-cpu
pointer.
Those are working as same as the kernel percpu macro.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v3:
- Remove NULL check for percpu var because it is just an offset, could be 0.
- Simplify process_fetch_insn_bottom() code.
- If the last operation is this_cpu_read(), read only memory of the specific
size (of type).
Changes in v2:
- Drop +CPU/+PCPU and introduce this_cpu_read() and this_cpu_ptr().
- Support these method with BTF typecast.
- Just check the base address is NOT NULL instead of is_kernel_percpu_address().
---
Documentation/trace/eprobetrace.rst | 2 +
Documentation/trace/fprobetrace.rst | 2 +
Documentation/trace/kprobetrace.rst | 2 +
kernel/trace/trace.c | 1
kernel/trace/trace_probe.c | 138 ++++++++++++++++++++++++-----------
kernel/trace/trace_probe.h | 3 +
kernel/trace/trace_probe_tmpl.h | 30 ++++++--
7 files changed, 129 insertions(+), 49 deletions(-)
diff --git a/Documentation/trace/eprobetrace.rst b/Documentation/trace/eprobetrace.rst
index 680e0af43d5d..279396951b34 100644
--- a/Documentation/trace/eprobetrace.rst
+++ b/Documentation/trace/eprobetrace.rst
@@ -39,6 +39,8 @@ Synopsis of eprobe_events
@SYM[+|-offs] : Fetch memory at SYM +|- offs (SYM should be a data symbol)
$comm : Fetch current task comm.
+|-[u]OFFS(FETCHARG) : Fetch memory at FETCHARG +|- OFFS address.(\*3)(\*4)
+ this_cpu_read(FETCHARG) : Read the value of the per-CPU variable FETCHARG on the current CPU.
+ this_cpu_ptr(FETCHARG) : Get the address of the per-CPU variable FETCHARG on the current CPU.
\IMM : Store an immediate value to the argument.
NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
diff --git a/Documentation/trace/fprobetrace.rst b/Documentation/trace/fprobetrace.rst
index 3392cab016b3..3439bc9bd351 100644
--- a/Documentation/trace/fprobetrace.rst
+++ b/Documentation/trace/fprobetrace.rst
@@ -52,6 +52,8 @@ Synopsis of fprobe-events
$comm : Fetch current task comm.
$current : Fetch the address of the current task_struct.
+|-[u]OFFS(FETCHARG) : Fetch memory at FETCHARG +|- OFFS address.(\*4)(\*5)
+ this_cpu_read(FETCHARG) : Read the value of the per-CPU variable FETCHARG on the current CPU.
+ this_cpu_ptr(FETCHARG) : Get the address of the per-CPU variable FETCHARG on the current CPU.
\IMM : Store an immediate value to the argument.
NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
diff --git a/Documentation/trace/kprobetrace.rst b/Documentation/trace/kprobetrace.rst
index 81e4fe38791d..9ae330eb0a52 100644
--- a/Documentation/trace/kprobetrace.rst
+++ b/Documentation/trace/kprobetrace.rst
@@ -55,6 +55,8 @@ Synopsis of kprobe_events
$comm : Fetch current task comm.
$current : Fetch the address of the current task_struct.
+|-[u]OFFS(FETCHARG) : Fetch memory at FETCHARG +|- OFFS address.(\*3)(\*4)
+ this_cpu_read(FETCHARG) : Read the value of the per-CPU variable FETCHARG on the current CPU.
+ this_cpu_ptr(FETCHARG) : Get the address of the per-CPU variable FETCHARG on the current CPU.
\IMM : Store an immediate value to the argument.
NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 7a5676524f1a..d4121acc2938 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4332,6 +4332,7 @@ static const char readme_msg[] =
"\t $stack<index>, $stack, $retval, $comm, $current\n"
#endif
"\t +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n"
+ "\t this_cpu_read(<fetcharg>), this_cpu_ptr(<fetcharg>)\n"
"\t kernel return probes support: $retval, $arg<N>, $comm\n"
"\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, char, string, symbol,\n"
"\t b<bit-width>@<bit-offset>/<container-size>, ustring,\n"
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index f5155340a325..a7aaba3d5375 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -349,6 +349,77 @@ static int parse_trace_event(char *arg, struct fetch_insn *code,
return -EINVAL;
}
+/* this_cpu_* parser */
+#define THIS_CPU_PTR_PREFIX "this_cpu_ptr("
+#define THIS_CPU_READ_PREFIX "this_cpu_read("
+#define THIS_CPU_PTR_LEN (sizeof(THIS_CPU_PTR_PREFIX) - 1)
+#define THIS_CPU_READ_LEN (sizeof(THIS_CPU_READ_PREFIX) - 1)
+
+static int
+parse_probe_arg(char *arg, const struct fetch_type *type,
+ struct fetch_insn **pcode, struct fetch_insn *end,
+ struct traceprobe_parse_context *ctx);
+
+/* handle dereference nested call */
+static inline int handle_dereference(char *arg, struct fetch_insn **pcode,
+ struct fetch_insn *end, struct traceprobe_parse_context *ctx,
+ int deref, long offset)
+{
+ const struct fetch_type *type = find_fetch_type(NULL, ctx->flags);
+ struct fetch_insn *code = *pcode;
+ int cur_offs = ctx->offset;
+ char *tmp;
+ int ret;
+
+ tmp = strrchr(arg, ')');
+ if (!tmp) {
+ trace_probe_log_err(ctx->offset + strlen(arg),
+ DEREF_OPEN_BRACE);
+ return -EINVAL;
+ }
+
+ *tmp = '\0';
+ ret = parse_probe_arg(arg, type, &code, end, ctx);
+ if (ret)
+ return ret;
+ ctx->offset = cur_offs;
+ if (code->op == FETCH_OP_COMM || code->op == FETCH_OP_DATA) {
+ trace_probe_log_err(ctx->offset, COMM_CANT_DEREF);
+ return -EINVAL;
+ }
+ code++;
+ if (code == end) {
+ trace_probe_log_err(ctx->offset, TOO_MANY_OPS);
+ return -EINVAL;
+ }
+ *pcode = code;
+
+ code->op = deref;
+ code->offset = offset;
+ /* Reset the last type if used */
+ ctx->last_type = NULL;
+ return 0;
+}
+
+static int parse_this_cpu(char *arg, struct fetch_insn **pcode,
+ struct fetch_insn *end,
+ struct traceprobe_parse_context *ctx)
+{
+ int deref;
+
+ if (str_has_prefix(arg, THIS_CPU_PTR_PREFIX)) {
+ arg += THIS_CPU_PTR_LEN;
+ ctx->offset += THIS_CPU_PTR_LEN;
+ deref = FETCH_OP_CPU_PTR;
+ } else if (str_has_prefix(arg, THIS_CPU_READ_PREFIX)) {
+ arg += THIS_CPU_READ_LEN;
+ ctx->offset += THIS_CPU_READ_LEN;
+ deref = FETCH_OP_DEREF_CPU;
+ } else
+ return -EINVAL;
+ return handle_dereference(arg, pcode, end, ctx, deref, 0);
+}
+
#ifdef CONFIG_PROBE_EVENTS_BTF_ARGS
static u32 btf_type_int(const struct btf_type *t)
@@ -929,11 +1000,6 @@ static char *find_matched_close_paren(char *s)
return NULL;
}
-static int
-parse_probe_arg(char *arg, const struct fetch_type *type,
- struct fetch_insn **pcode, struct fetch_insn *end,
- struct traceprobe_parse_context *ctx);
-
static int handle_typecast(char *arg, struct fetch_insn **pcode,
struct fetch_insn *end,
struct traceprobe_parse_context *ctx)
@@ -959,7 +1025,8 @@ static int handle_typecast(char *arg, struct fetch_insn **pcode,
*tmp++ = '\0';
/* Handle the nested structure like (STRUCT)(VAR->FIELD)->... */
- if (*tmp == '(') {
+ if (*tmp == '(' || str_has_prefix(tmp, THIS_CPU_PTR_PREFIX) ||
+ str_has_prefix(tmp, THIS_CPU_READ_PREFIX)) {
char *close = find_matched_close_paren(tmp);
ctx->offset += tmp - arg;
@@ -979,12 +1046,18 @@ static int handle_typecast(char *arg, struct fetch_insn **pcode,
trace_probe_log_err(ctx->offset, TOO_MANY_NESTED);
return -E2BIG;
}
- *close = '\0';
- ctx->offset += 1; /* for the '(' */
- /* We need to parse the nested one */
- ret = parse_probe_arg(tmp + 1, find_fetch_type(NULL, ctx->flags),
- pcode, end, ctx);
+ if (*tmp == '(') {
+ /* Extract the inner argument */
+ *close = '\0';
+ ctx->offset += 1;/* for the '(' */
+ /* Parse the nested one */
+ ret = parse_probe_arg(tmp + 1, find_fetch_type(NULL, ctx->flags),
+ pcode, end, ctx);
+ } else {
+ /* this_cpu_* will be parsed in parse_this_cpu() */
+ ret = parse_this_cpu(tmp, pcode, end, ctx);
+ }
if (ret < 0)
return ret;
ctx->nested_level--;
@@ -1454,36 +1527,9 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
}
ctx->offset += (tmp + 1 - arg) + (arg[0] != '-' ? 1 : 0);
arg = tmp + 1;
- tmp = strrchr(arg, ')');
- if (!tmp) {
- trace_probe_log_err(ctx->offset + strlen(arg),
- DEREF_OPEN_BRACE);
- return -EINVAL;
- } else {
- const struct fetch_type *t2 = find_fetch_type(NULL, ctx->flags);
- int cur_offs = ctx->offset;
-
- *tmp = '\0';
- ret = parse_probe_arg(arg, t2, &code, end, ctx);
- if (ret)
- break;
- ctx->offset = cur_offs;
- if (code->op == FETCH_OP_COMM ||
- code->op == FETCH_OP_DATA) {
- trace_probe_log_err(ctx->offset, COMM_CANT_DEREF);
- return -EINVAL;
- }
- if (++code == end) {
- trace_probe_log_err(ctx->offset, TOO_MANY_OPS);
- return -EINVAL;
- }
- *pcode = code;
-
- code->op = deref;
- code->offset = offset;
- /* Reset the last type if used */
- ctx->last_type = NULL;
- }
+ ret = handle_dereference(arg, pcode, end, ctx, deref, offset);
+ if (ret < 0)
+ return ret;
break;
case '\\': /* Immediate value */
if (arg[1] == '"') { /* Immediate string */
@@ -1504,15 +1550,18 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
ret = handle_typecast(arg, pcode, end, ctx);
break;
default:
- if (isalpha(arg[0]) || arg[0] == '_') { /* BTF variable */
+ if (str_has_prefix(arg, THIS_CPU_PTR_PREFIX) ||
+ str_has_prefix(arg, THIS_CPU_READ_PREFIX)) {
+ ret = parse_this_cpu(arg, pcode, end, ctx);
+ } else if (isalpha(arg[0]) || arg[0] == '_') { /* BTF variable */
if (!tparg_is_function_entry(ctx->flags) &&
!tparg_is_function_return(ctx->flags)) {
trace_probe_log_err(ctx->offset, NOSUP_BTFARG);
return -EINVAL;
}
ret = parse_btf_arg(arg, pcode, end, ctx);
- break;
}
+ break;
}
if (!ret && code->op == FETCH_OP_NOP) {
/* Parsed, but do not find fetch method */
@@ -1687,6 +1736,9 @@ static int finalize_fetch_insn(struct fetch_insn *code,
} else if (code->op == FETCH_OP_UDEREF) {
code->op = FETCH_OP_ST_UMEM;
code->size = parg->type->size;
+ } else if (code->op == FETCH_OP_DEREF_CPU) {
+ code->op = FETCH_OP_ST_CPUMEM;
+ code->size = parg->type->size;
} else {
code++;
if (code->op != FETCH_OP_NOP) {
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 62645e847bd1..523612023608 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -100,10 +100,13 @@ enum fetch_op {
// Stage 2 (dereference) op
FETCH_OP_DEREF, /* Dereference: .offset */
FETCH_OP_UDEREF, /* User-space Dereference: .offset */
+ FETCH_OP_DEREF_CPU, /* Per-CPU Dereference for this CPU */
+ FETCH_OP_CPU_PTR, /* Per-CPU pointer for this CPU */
// Stage 3 (store) ops
FETCH_OP_ST_RAW, /* Raw: .size */
FETCH_OP_ST_MEM, /* Mem: .offset, .size */
FETCH_OP_ST_UMEM, /* Mem: .offset, .size */
+ FETCH_OP_ST_CPUMEM, /* Per-CPU Mem: .size */
FETCH_OP_ST_STRING, /* String: .offset, .size */
FETCH_OP_ST_USTRING, /* User String: .offset, .size */
FETCH_OP_ST_SYMSTR, /* Kernel Symbol String: .offset, .size */
diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h
index f630930288d2..83111c167b74 100644
--- a/kernel/trace/trace_probe_tmpl.h
+++ b/kernel/trace/trace_probe_tmpl.h
@@ -129,25 +129,39 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
struct fetch_insn *s3 = NULL;
int total = 0, ret = 0, i = 0;
u32 loc = 0;
- unsigned long lval = val;
+ unsigned long lval, llval = val;
stage2:
/* 2nd stage: dereference memory if needed */
do {
- if (code->op == FETCH_OP_DEREF) {
- lval = val;
+ lval = val;
+ switch (code->op) {
+ case FETCH_OP_DEREF:
ret = probe_mem_read(&val, (void *)val + code->offset,
sizeof(val));
- } else if (code->op == FETCH_OP_UDEREF) {
- lval = val;
+ break;
+ case FETCH_OP_UDEREF:
ret = probe_mem_read_user(&val,
(void *)val + code->offset, sizeof(val));
- } else
break;
+ case FETCH_OP_DEREF_CPU:
+ val = (unsigned long)this_cpu_ptr((void __percpu *)val);
+ ret = probe_mem_read(&val, (void *)val, sizeof(val));
+ break;
+ case FETCH_OP_CPU_PTR:
+ val = (unsigned long)this_cpu_ptr((void __percpu *)val);
+ ret = 0;
+ break;
+ default:
+ lval = llval;
+ goto out;
+ }
if (ret)
return ret;
+ llval = lval;
code++;
} while (1);
+out:
s3 = code;
stage3:
@@ -181,6 +195,10 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
case FETCH_OP_ST_UMEM:
probe_mem_read_user(dest, (void *)val + code->offset, code->size);
break;
+ case FETCH_OP_ST_CPUMEM:
+ val = (unsigned long)this_cpu_ptr((void __percpu *)val);
+ probe_mem_read(dest, (void *)val, code->size);
+ break;
case FETCH_OP_ST_STRING:
loc = *(u32 *)dest;
ret = fetch_store_string(val + code->offset, dest, base);
^ permalink raw reply related
* [PATCH v4 7/7] tracing/probes: Add a new testcase for BTF typecasts
From: Masami Hiramatsu (Google) @ 2026-06-15 1:15 UTC (permalink / raw)
To: Steven Rostedt, Mathieu Desnoyers
Cc: Jonathan Corbet, Shuah Khan, Masami Hiramatsu, linux-kernel,
linux-trace-kernel, linux-doc, linux-kselftest
In-Reply-To: <178148603548.185520.3389196102475741865.stgit@devnote2>
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
With the introduction of container_of-style BTF typecasting and
per-CPU variable access support in trace probes, we need a way to
verify their functionality and prevent regressions.
Add a new ftrace kselftest and update the trace event sample module
to test and validate these features.
Specifically, update the trace-events-sample module to set up a
periodic timer whose callback accesses a per-CPU counter. Introduce
a new sample trace event, foo_timer_fn, to trace this callback
and log the current counter value.
Then, add a new test case, btf_probe_event.tc, which defines a
dynamic probe on the timer callback. The probe uses BTF typecasting
to recover the parent structure from the timer argument and
this_cpu_read() to fetch the per-CPU counter. The test verifies
the integrity of the implementation by ensuring the values
recorded by the dynamic probe match those from the static tracepoint.
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v4:
- Fix uprobe $current test.
Changes in v3:
- Add syntax test case.
- Update testcase to use this_cpu_read()
Changes in v2:
- Use timer_shutdown_sync() instead of timer_delete_sync() for teardown.
---
samples/trace_events/trace-events-sample.c | 40 +++++++++++++++-
samples/trace_events/trace-events-sample.h | 34 ++++++++++++-
.../ftrace/test.d/dynevent/btf_probe_event.tc | 51 ++++++++++++++++++++
.../ftrace/test.d/dynevent/fprobe_syntax_errors.tc | 9 ++++
.../ftrace/test.d/kprobe/kprobe_syntax_errors.tc | 9 ++++
.../ftrace/test.d/kprobe/uprobe_syntax_errors.tc | 5 ++
6 files changed, 143 insertions(+), 5 deletions(-)
create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/btf_probe_event.tc
diff --git a/samples/trace_events/trace-events-sample.c b/samples/trace_events/trace-events-sample.c
index 0b7a6efdb247..ca5d98c360cb 100644
--- a/samples/trace_events/trace-events-sample.c
+++ b/samples/trace_events/trace-events-sample.c
@@ -94,6 +94,20 @@ static int simple_thread_fn(void *arg)
static DEFINE_MUTEX(thread_mutex);
static int simple_thread_cnt;
+static struct foo_timer_data *foo_timer_data;
+
+static void sample_timer_cb(struct timer_list *t)
+{
+ struct foo_timer_data *data = container_of(t, struct foo_timer_data, timer);
+
+ get_cpu();
+ trace_foo_timer_fn(data);
+ (*this_cpu_ptr(data->counter))++;
+ put_cpu();
+
+ mod_timer(t, jiffies + HZ);
+}
+
int foo_bar_reg(void)
{
mutex_lock(&thread_mutex);
@@ -132,9 +146,27 @@ void foo_bar_unreg(void)
static int __init trace_event_init(void)
{
+ foo_timer_data = kzalloc_obj(*foo_timer_data, GFP_KERNEL);
+ if (!foo_timer_data)
+ return -ENOMEM;
+
+ foo_timer_data->name = "sample_timer_counter";
+ foo_timer_data->counter = alloc_percpu(int);
+ if (!foo_timer_data->counter) {
+ kfree(foo_timer_data);
+ return -ENOMEM;
+ }
+
+ timer_setup(&foo_timer_data->timer, sample_timer_cb, 0);
+ mod_timer(&foo_timer_data->timer, jiffies + HZ);
+
simple_tsk = kthread_run(simple_thread, NULL, "event-sample");
- if (IS_ERR(simple_tsk))
- return -1;
+ if (IS_ERR(simple_tsk)) {
+ timer_shutdown_sync(&foo_timer_data->timer);
+ free_percpu(foo_timer_data->counter);
+ kfree(foo_timer_data);
+ return PTR_ERR(simple_tsk);
+ }
return 0;
}
@@ -147,6 +179,10 @@ static void __exit trace_event_exit(void)
kthread_stop(simple_tsk_fn);
simple_tsk_fn = NULL;
mutex_unlock(&thread_mutex);
+
+ timer_shutdown_sync(&foo_timer_data->timer);
+ free_percpu(foo_timer_data->counter);
+ kfree(foo_timer_data);
}
module_init(trace_event_init);
diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h
index 1a05fc153353..816848a456a2 100644
--- a/samples/trace_events/trace-events-sample.h
+++ b/samples/trace_events/trace-events-sample.h
@@ -247,12 +247,14 @@
*/
/*
- * It is OK to have helper functions in the file, but they need to be protected
- * from being defined more than once. Remember, this file gets included more
- * than once.
+ * It is OK to have helper functions and data structures in the file, but they
+ * need to be protected from being defined more than once. Remember, this file
+ * gets included more than once.
*/
#ifndef __TRACE_EVENT_SAMPLE_HELPER_FUNCTIONS
#define __TRACE_EVENT_SAMPLE_HELPER_FUNCTIONS
+#include <linux/timer.h>
+
static inline int __length_of(const int *list)
{
int i;
@@ -270,6 +272,13 @@ enum {
TRACE_SAMPLE_BAR = 4,
TRACE_SAMPLE_ZOO = 8,
};
+
+struct foo_timer_data {
+ const char *name;
+ struct timer_list timer;
+ int __percpu *counter;
+};
+
#endif
/*
@@ -595,6 +604,25 @@ TRACE_EVENT(foo_rel_loc,
__get_rel_bitmask(bitmask),
__get_rel_cpumask(cpumask))
);
+
+TRACE_EVENT(foo_timer_fn,
+
+ TP_PROTO(struct foo_timer_data *data),
+
+ TP_ARGS(data),
+
+ TP_STRUCT__entry(
+ __string( name, data->name )
+ __field( int, count )
+ ),
+
+ TP_fast_assign(
+ __assign_str(name);
+ __entry->count = *this_cpu_ptr(data->counter);
+ ),
+
+ TP_printk("name=%s count=%d", __get_str(name), __entry->count)
+);
#endif
/***** NOTICE! The #if protection ends here. *****/
diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/btf_probe_event.tc b/tools/testing/selftests/ftrace/test.d/dynevent/btf_probe_event.tc
new file mode 100644
index 000000000000..96791e120b7d
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/dynevent/btf_probe_event.tc
@@ -0,0 +1,51 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: BTF event with typecast and percpu access
+# requires: dynamic_events "this_cpu_read(<fetcharg>)":README "[(structname[,field])]<argname>[->field[->field|.field...]]":README
+
+# Check if the sample module is loaded
+if ! lsmod | grep -q trace_events_sample; then
+ modprobe trace-events-sample || exit_unsupported
+fi
+
+echo 0 > events/enable
+echo > dynamic_events
+
+# The sample_timer_cb(struct timer_list *t) is called.
+# We want to check (STRUCT,FIELD)VAR typecast and this_cpu_read() access.
+# (foo_timer_data,timer)t converts t to struct foo_timer_data * using container_of.
+# data->counter is a per-cpu pointer to int.
+# this_cpu_read(data->counter) should give the value of the counter.
+
+echo 'f:mysample/myevent sample_timer_cb name=(foo_timer_data,timer)t->name:string count=this_cpu_read((foo_timer_data,timer)t->counter)' >> dynamic_events
+
+echo 1 > events/mysample/myevent/enable
+echo 1 > events/sample-trace/foo_timer_fn/enable
+
+sleep 2
+
+echo 0 > events/mysample/myevent/enable
+echo 0 > events/sample-trace/foo_timer_fn/enable
+
+# Compare the values.
+MATCH=0
+while read line; do
+ if echo $line | grep -q "foo_timer_fn:"; then
+ NAME=`echo $line | sed 's/.*name=\([^ ]*\) .*/\1/'`
+ COUNT=`echo $line | sed 's/.*count=\([^ ]*\).*/\1/'`
+ if grep -q "myevent:.*name=\"${NAME}\" count=$COUNT" trace; then
+ MATCH=$((MATCH+1))
+ fi
+ fi
+done < trace
+
+if [ $MATCH -eq 0 ]; then
+ echo "No matching events found"
+ exit_fail
+fi
+
+# Clean up
+echo 0 > events/mysample/myevent/enable
+echo 0 > events/sample-trace/foo_timer_fn/enable
+echo > dynamic_events
+clear_trace
diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc
index fee479295e2f..b781ec07c0d0 100644
--- a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc
+++ b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc
@@ -112,6 +112,15 @@ check_error 'f vfs_read%return $retval->^foo' # NO_PTR_STRCT
check_error 'f vfs_read file->^foo' # NO_BTF_FIELD
check_error 'f vfs_read file^-.foo' # BAD_HYPHEN
check_error 'f vfs_read ^file:string' # BAD_TYPE4STR
+if grep -qF "[(structname" README ; then
+check_error 'f vfs_read arg1=(task_struct)file^' # TYPECAST_REQ_FIELD
+check_error 'f vfs_read arg1=(f)((f)((f)((f)^((f)file->f)->f)->f)->f)->f' # TOO_MANY_NESTED
+check_error 'f vfs_read arg1=(task_struct,^in_execve)file->comm' # TYPECAST_NOT_ALIGNED
+check_error 'f vfs_read arg1=(task_struct,se^->group_node)file->comm' # TYPECAST_BAD_ARROW
+check_error 'f vfs_read arg1=(task_struct,^->pid)file->comm' # TYPECAST_BAD_ARROW
+check_error 'f vfs_read arg1=(task_struct,^.pid)file->comm' # BTF_BAD_TID
+check_error 'f vfs_read arg1=(task_struct,^.)file->comm' # BTF_BAD_TID
+fi
fi
else
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
index 8f1c58f0c239..78f015c8c010 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
@@ -115,6 +115,15 @@ check_error 'p vfs_read+20 ^$arg*' # NOFENTRY_ARGS
check_error 'p vfs_read ^hoge' # NO_BTFARG
check_error 'p kfree ^$arg10' # NO_BTFARG (exceed the number of parameters)
check_error 'r kfree ^$retval' # NO_RETVAL
+if grep -qF "[(structname" README ; then
+check_error 'p vfs_read arg1=(task_struct)file^' # TYPECAST_REQ_FIELD
+check_error 'p vfs_read arg1=(f)((f)((f)((f)^((f)file->f)->f)->f)->f)->f' # TOO_MANY_NESTED
+check_error 'p vfs_read arg1=(task_struct,^in_execve)file->comm' # TYPECAST_NOT_ALIGNED
+check_error 'p vfs_read arg1=(task_struct,se^->group_node)file->comm' # TYPECAST_BAD_ARROW
+check_error 'p vfs_read arg1=(task_struct,^->pid)file->comm' # TYPECAST_BAD_ARROW
+check_error 'p vfs_read arg1=(task_struct,^.pid)file->comm' # BTF_BAD_TID
+check_error 'p vfs_read arg1=(task_struct,^.)file->comm' # BTF_BAD_TID
+fi
else
check_error 'p vfs_read ^$arg*' # NOSUP_BTFARG
fi
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/uprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/kprobe/uprobe_syntax_errors.tc
index c817158b99db..e12dc967ec76 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/uprobe_syntax_errors.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/uprobe_syntax_errors.tc
@@ -28,4 +28,9 @@ if grep -q ".*symstr.*" README; then
check_error 'p /bin/sh:10 $stack0:^symstr' # BAD_TYPE
fi
+# $current is not supported by uprobe
+if grep -q "\$current.*" README; then
+check_error 'p /bin/sh:10 ^$current:u8' # BAD_VAR
+fi
+
exit 0
^ permalink raw reply related
* Re: [PATCH v4 10/16] riscv: dts: spacemit: k3: Add Zic64b ISA extension
From: Yixun Lan @ 2026-06-15 1:20 UTC (permalink / raw)
To: Guodong Xu
Cc: Jonathan Corbet, Shuah Khan, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Zong Li, Deepak Gupta, Anup Patel,
Atish Patra, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen Wang, Inochi Amaoto, linux-doc, linux-riscv, linux-kernel,
kvm, kvm-riscv, Paul Walmsley, Conor Dooley, devicetree, spacemit,
sophgo, linux-kselftest, Palmer Dabbelt
In-Reply-To: <20260611-rva23u64-hwprobe-v2-v4-10-3f01a2449488@gmail.com>
Hi Guodong,
On 16:12 Thu 11 Jun , Guodong Xu wrote:
> The K3 X100 cores have 64-byte cache blocks, already described by their
> cbom/cbop/cboz-block-size of 64, so they implement Zic64b, a mandatory
> RVA23 extension. Declare it in each core's riscv,isa-extensions.
>
> Signed-off-by: Guodong Xu <docular.xu@gmail.com>
Reviewed-by: Yixun Lan <dlan@kernel.org>
> ---
> v4: No change.
> v3: New patch.
> ---
> arch/riscv/boot/dts/spacemit/k3.dtsi | 48 ++++++++++++++++++------------------
> 1 file changed, 24 insertions(+), 24 deletions(-)
>
> diff --git a/arch/riscv/boot/dts/spacemit/k3.dtsi b/arch/riscv/boot/dts/spacemit/k3.dtsi
> index 4ac457399b583..b5aa983f0bfa1 100644
> --- a/arch/riscv/boot/dts/spacemit/k3.dtsi
> +++ b/arch/riscv/boot/dts/spacemit/k3.dtsi
> @@ -35,9 +35,9 @@ cpu_0: cpu@0 {
> "svinval", "svnapot", "svpbmt", "za64rs",
> "zawrs", "zba", "zbb", "zbc", "zbs", "zca",
> "zcb", "zcd", "zcmop", "zfa", "zfbfmin",
> - "zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
> - "ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
> - "zicond", "zicsr", "zifencei", "zihintntl",
> + "zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
> + "zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
> + "zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
> "zihintpause", "zihpm", "zimop", "zkt", "zvbb",
> "zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
> "zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
> @@ -76,9 +76,9 @@ cpu_1: cpu@1 {
> "svinval", "svnapot", "svpbmt", "za64rs",
> "zawrs", "zba", "zbb", "zbc", "zbs", "zca",
> "zcb", "zcd", "zcmop", "zfa", "zfbfmin",
> - "zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
> - "ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
> - "zicond", "zicsr", "zifencei", "zihintntl",
> + "zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
> + "zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
> + "zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
> "zihintpause", "zihpm", "zimop", "zkt", "zvbb",
> "zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
> "zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
> @@ -117,9 +117,9 @@ cpu_2: cpu@2 {
> "svinval", "svnapot", "svpbmt", "za64rs",
> "zawrs", "zba", "zbb", "zbc", "zbs", "zca",
> "zcb", "zcd", "zcmop", "zfa", "zfbfmin",
> - "zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
> - "ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
> - "zicond", "zicsr", "zifencei", "zihintntl",
> + "zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
> + "zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
> + "zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
> "zihintpause", "zihpm", "zimop", "zkt", "zvbb",
> "zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
> "zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
> @@ -158,9 +158,9 @@ cpu_3: cpu@3 {
> "svinval", "svnapot", "svpbmt", "za64rs",
> "zawrs", "zba", "zbb", "zbc", "zbs", "zca",
> "zcb", "zcd", "zcmop", "zfa", "zfbfmin",
> - "zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
> - "ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
> - "zicond", "zicsr", "zifencei", "zihintntl",
> + "zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
> + "zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
> + "zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
> "zihintpause", "zihpm", "zimop", "zkt", "zvbb",
> "zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
> "zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
> @@ -199,9 +199,9 @@ cpu_4: cpu@4 {
> "svinval", "svnapot", "svpbmt", "za64rs",
> "zawrs", "zba", "zbb", "zbc", "zbs", "zca",
> "zcb", "zcd", "zcmop", "zfa", "zfbfmin",
> - "zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
> - "ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
> - "zicond", "zicsr", "zifencei", "zihintntl",
> + "zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
> + "zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
> + "zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
> "zihintpause", "zihpm", "zimop", "zkt", "zvbb",
> "zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
> "zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
> @@ -240,9 +240,9 @@ cpu_5: cpu@5 {
> "svinval", "svnapot", "svpbmt", "za64rs",
> "zawrs", "zba", "zbb", "zbc", "zbs", "zca",
> "zcb", "zcd", "zcmop", "zfa", "zfbfmin",
> - "zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
> - "ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
> - "zicond", "zicsr", "zifencei", "zihintntl",
> + "zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
> + "zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
> + "zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
> "zihintpause", "zihpm", "zimop", "zkt", "zvbb",
> "zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
> "zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
> @@ -281,9 +281,9 @@ cpu_6: cpu@6 {
> "svinval", "svnapot", "svpbmt", "za64rs",
> "zawrs", "zba", "zbb", "zbc", "zbs", "zca",
> "zcb", "zcd", "zcmop", "zfa", "zfbfmin",
> - "zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
> - "ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
> - "zicond", "zicsr", "zifencei", "zihintntl",
> + "zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
> + "zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
> + "zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
> "zihintpause", "zihpm", "zimop", "zkt", "zvbb",
> "zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
> "zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
> @@ -322,9 +322,9 @@ cpu_7: cpu@7 {
> "svinval", "svnapot", "svpbmt", "za64rs",
> "zawrs", "zba", "zbb", "zbc", "zbs", "zca",
> "zcb", "zcd", "zcmop", "zfa", "zfbfmin",
> - "zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
> - "ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
> - "zicond", "zicsr", "zifencei", "zihintntl",
> + "zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
> + "zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
> + "zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
> "zihintpause", "zihpm", "zimop", "zkt", "zvbb",
> "zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
> "zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
>
> --
> 2.43.0
>
--
Yixun Lan (dlan)
^ permalink raw reply
* Re: [PATCH 1/3] mm/page_io: let block drivers register custom swap I/O ops
From: YoungJun Park @ 2026-06-15 1:50 UTC (permalink / raw)
To: Jianyue Wu
Cc: Andrew Morton, Christoph Hellwig, Chris Li, Baoquan He, Nhat Pham,
Barry Song, Kairui Song, Kemeng Shi, Minchan Kim,
Sergey Senozhatsky, Jens Axboe, Matthew Wilcox (Oracle), Jan Kara,
linux-mm, linux-kernel, linux-block, linux-doc
In-Reply-To: <20260614-zram-swap-ops-block-register-v1-1-6c1a6639c222@gmail.com>
On Sun, Jun 14, 2026 at 11:35:29PM +0800, Jianyue Wu wrote:
...
Hello Jianyue.
Currently, the patch commit log indicates only a single custom swap
registration is supported. Shouldn't we allow multiple block drivers to
register their custom ops simultaneously from the beginning?
> int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,
> struct list_head *folio_list);
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 284eebc40a70..ebdc96092961 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -2849,6 +2849,10 @@ static int setup_swap_extents(struct swap_info_struct *sis,
> sis->ops = &swap_bdev_ops;
>
> if (S_ISBLK(inode->i_mode)) {
> + const struct swap_ops *block_ops = lookup_swap_block_ops(sis);
Also, just a personal thought on this part.
Instead of using `block_device_fops` as a lookup key, what if we handle
this similarly to how filesystems use the `a_ops->swap_activate` callback?
We could add a `swap_activate` callback directly into
struct block_device_operations (zram's zram_devops). This way, the
block device itself can set up and replace the swap `ops` directly without
needing a separate registration/lookup mechanism.
What are your thoughts on this approach?
Thanks,
Youngjun Park
^ permalink raw reply
* Re: [PATCH 0/3] usb: gadget: f_fs: Add R/W proxy EPs and ZLP support
From: Greg KH @ 2026-06-15 2:30 UTC (permalink / raw)
To: Neill Kapron
Cc: corbet, skhan, linux-usb, linux-doc, linux-kernel, kernel-team
In-Reply-To: <20260614181006.3648010-1-nkapron@google.com>
On Sun, Jun 14, 2026 at 06:09:59PM +0000, Neill Kapron wrote:
> We are working to deprecate a widely used, out of tree gadget driver by
> moving the functionality to userspace via functionfs. To do so, we have to
> maintain strict compatibility with the legacy driver, as there are many
> third party applications which can’t be modified and are reliant on this
> interface. Specifically, the following requirements must be met:
>
> - The function must expose a single file descriptor to userspace for both
> reads and writes,
> - It must block on writes when it can not handle more data,
> - It must handle arbitrary write transaction sizes,
> - It must automatically append a zero length packet (ZLP) when the write
> transaction ends on a boundary of a multiple of the max packet size.
>
> Initially, we pursued a compatibility layer in userspace which implemented
> a socket pair to combine the OUT and IN endpoint files. This approach
> proved problematic for several reasons.
>
> To preserve the write transaction boundary for ZLP calculation, we
> attempted to use SOCK_SEQPACKET. This created problems as larger
> transactions required contiguous buffers to be allocated, and, even if we
> ignore the constraint to the arbitrary write size and limited it to 1MB,
> the socket would occasionally return -ENOBUFS to the end user if a write
> operation was attempted when other sockets on the system were consuming
> more than 7MB of the 8MB wmem_max limit.
>
> After significant investigation including switching to SOCK_STREAM and
> attempting a heuristic timeout approach, we decided the best path forward
> was to pursue a native proxy endpoint approach in the functionfs driver
> itself.
>
> This patchset introduces the `FUNCTIONFS_RW_PROXY_EPS` flag to functionfs
> which, when set, creates an additional proxy file for reading or writing
> to a pair of endpoints. In an attempt to limit the change to the UAPI
> surface, we added several constraints to this proxy file. We chose not to
> handle ioctls on this proxy file, as the current ioctls do not have a
> directionality associated with them, and would require essentially
> creating duplicate ioctls with a direction argument. To use this flag, an
> even number of in/out endpoints must be created, and a proxy ep is created
> for each pair of endpoints in the descriptors.
>
> With this new r/w proxy ep, we are able to transparently hand it to the
> end application. However, to match the legacy driver’s ZLP functionality,
> a new ioctl is added, `FUNCTIONFS_ENDPOINT_ENABLE_ZLP`. This allows the
> userspace functionfs daemon to write the necessary descriptors, configure
> the auto ZLP functionality on the IN EP, then handoff the proxy ep to the
> application. When enabled, functionfs sets the req->zero flag. The UDC
> driver then automatically adds the ZLP if the transaction length % max
> packet size is 0.
>
> An addition, a patch is included which fixes an issue if certain ioctls
> (like the new `FUNCTIONFS_ENDPOINT_ENABLE_ZLP` or
> `FUNCTIONFS_DMABUF_ATTACH`) are called prior to the host being connected.
>
> This patchset has been tested on a kernel based on 7.1-rc7, as well as a
> backported version tested on 6.1. Existing functionfs implementations
> continue to work without modification, and the new functionality passes
> tests designed for our legacy kernel driver implementation.
Very cool, thanks for these changes. I'll look at them after -rc1 is
out!
greg k-h
^ permalink raw reply
* Re: [PATCH 1/3] usb: gadget: f_fs: Initialize epfile->in early to fix endpoint direction checks
From: Greg KH @ 2026-06-15 2:30 UTC (permalink / raw)
To: Neill Kapron
Cc: corbet, skhan, Paul Cercueil, Christian König, Simona Vetter,
linux-usb, linux-doc, linux-kernel, kernel-team
In-Reply-To: <20260614181006.3648010-2-nkapron@google.com>
On Sun, Jun 14, 2026 at 06:10:00PM +0000, Neill Kapron wrote:
> When parsing endpoint descriptors, ffs_data_got_descs() generates the
> eps_addrmap which contains the endpoint direction. However, epfile->in
> was previously only populated in ffs_func_eps_enable() which executes
> upon USB host connection. As a result, early userspace ioctls like
> FUNCTIONFS_DMABUF_ATTACH that run before the host connects would see
> epfile->in as 0, leading to incorrect DMA directions.
>
> By moving the initialization to ffs_epfiles_create(), epfile->in is
> accurate before userspace opens the endpoint files.
>
> Fixes: 7b07a2a7ca02 ("usb: gadget: functionfs: Add DMABUF import interface")
> Assisted-by: Antigravity:gemini-3.1-pro
> Signed-off-by: Neill Kapron <nkapron@google.com>
> ---
> drivers/usb/gadget/function/f_fs.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
This should also go to stable, right?
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH 3/3] usb: gadget: f_fs: Introduce rw_proxy file descriptors
From: Greg KH @ 2026-06-15 2:35 UTC (permalink / raw)
To: Neill Kapron
Cc: corbet, skhan, linux-usb, linux-doc, linux-kernel, kernel-team
In-Reply-To: <20260614181006.3648010-4-nkapron@google.com>
On Sun, Jun 14, 2026 at 06:10:02PM +0000, Neill Kapron wrote:
> Currently, FunctionFS exposes each USB endpoint as a separate,
> unidirectional file descriptor (e.g., `ep1` for IN, `ep2` for OUT).
> While this mirrors the underlying hardware structure, it forces
> userspace daemons implementing bidirectional protocols to manage
> multiple file descriptors. When dealing with legacy protocols which
> require exposing a single, bi-directional fd to userspace, this becomes
> problematic.
>
> This patch introduces the `FUNCTIONFS_RW_PROXY_EPS` UAPI flag. When
> passed in the descriptor header during initialization, FunctionFS
> provisions a "rw_proxy" bidirectional file descriptor (e.g., `ep1_rw`)
> alongside every pair of IN/OUT endpoints.
>
> Implementation details:
> - RW proxy files act as a pure VFS alias, proxying operations
> directly to the base ffs_epfile instances. A `read()` proxies to
> the OUT endpoint's file, and a `write()` proxies to the IN file.
> - Because operations are proxied natively, they reuse the underlying
> base endpoint's lock (`epfile->mutex`) and tracking state. This
> serializes concurrent read or write operations, preventing buffer
> corruption and race conditions even if userspace mixes transfers across
> both the rw_proxy and base files. This approach allows full-duplex
> synchronous operations to occur concurrently without serializing on a
> single lock.
> - Control operations (like IOCTLs) and intentional stalls (via
> reverse-direction I/O) must still be issued on the base endpoints, as the
> rw_proxy returns `-ENOTTY` for IOCTLs and cannot trigger stalls.
>
> Assisted-by: Antigravity:gemini-3.1-pro
> Signed-off-by: Neill Kapron <nkapron@google.com>
> ---
> Documentation/usb/functionfs.rst | 56 ++++++++++++++
> drivers/usb/gadget/function/f_fs.c | 109 +++++++++++++++++++++++-----
> drivers/usb/gadget/function/u_fs.h | 8 +-
> include/uapi/linux/usb/functionfs.h | 1 +
> 4 files changed, 156 insertions(+), 18 deletions(-)
>
> diff --git a/Documentation/usb/functionfs.rst b/Documentation/usb/functionfs.rst
> index 582e53549d5b..b189cf5626ba 100644
> --- a/Documentation/usb/functionfs.rst
> +++ b/Documentation/usb/functionfs.rst
> @@ -96,6 +96,58 @@ One such IOCTL is:
> * ``-ENODEV``: The FunctionFS instance is not active.
> * ``-EINVAL``: The endpoint is not an IN endpoint.
> * ``-EFAULT``: Invalid user space pointer for the argument.
> +
> +RW Proxy Endpoints
> +==================
> +
> +If the ``FUNCTIONFS_RW_PROXY_EPS`` flag is passed in the descriptor header
> +(requires ``FUNCTIONFS_DESCRIPTORS_MAGIC_V2``), FunctionFS will provision a
> +bidirectional rw_proxy file descriptor (e.g., "ep1_rw") alongside each pair
> +of IN and OUT endpoints. The rw_proxy file aliases the underlying hardware
> +endpoints, allowing userspace to use a single file descriptor for both reading
> +(OUT) and writing (IN).
> +
> +This flag requires the total number of hardware endpoints to be an even number.
> +FunctionFS will automatically walk the provided endpoints and group them into
> +adjacent pairs (e.g., ep1 and ep2 form the first pair, ep3 and ep4 form the
> +second pair). Each pair must consist of exactly one IN endpoint and one OUT
> +endpoint.
> +
> +For each valid pair, a rw_proxy file is created and named after the first
> +endpoint in the pair with a "_rw" suffix. For example, if ep1 and ep2 are
> +paired, a rw_proxy file named "ep1_rw" is created. If ep3 and ep4 are paired,
> +"ep3_rw" is created.
> +
> +If the ``FUNCTIONFS_VIRTUAL_ADDR`` flag is also enabled, the endpoints will be
> +named using their physical endpoint address in hexadecimal instead of their
> +index. RW proxy files will inherit this naming convention. For example, if the
> +first endpoint of a pair maps to address 0x02, the rw_proxy file will be
> +named "ep02_rw".
> +
> +When this flag is enabled, userspace has the choice of performing data transfers
> +via the single rw_proxy file descriptor or the two base file descriptors. The
> +rw_proxy file descriptor acts as a pure VFS alias that proxies all operations
> +directly to the underlying base file descriptors.
> +
> +Because it is a pure proxy, there are no data races or buffer corruptions if
> +userspace uses both the rw_proxy endpoint and the base endpoints concurrently.
> +The native mutexes of the base endpoints perfectly serialize all concurrent
> +transfers. However, userspace should generally pick one method and stick to it
> +to avoid interleaving its own data stream.
> +
> +- **IOCTLs (Clear Halt, etc.):** RW proxy endpoints do not support IOCTLs and
> + will return ``-ENOTTY``. To clear a host-initiated halt, userspace must issue
> + the ``FUNCTIONFS_CLEAR_HALT`` ioctl directly on the corresponding base
> + endpoint file descriptor.
> +- **Intentional Stalls:** The traditional mechanism for intentionally halting an
> + endpoint by issuing a reverse-direction data operation (e.g., attempting to
> + read from an IN endpoint) continues to work, but it must be issued on the
> + base endpoint. RW proxy endpoints cannot be used to trigger a stall because
> + they are fully bidirectional.
> +
> +Note that DMABUF data transfers (``FUNCTIONFS_DMABUF_TRANSFER``) are unsupported
> +via the rw_proxy endpoint because it does not support IOCTLs. If DMABUF
> +transfers are required, users must use the standard base endpoints.
> DMABUF interface
> ================
>
> @@ -103,6 +155,10 @@ FunctionFS additionally supports a DMABUF based interface, where the
> userspace can attach DMABUF objects (externally created) to an endpoint,
> and subsequently use them for data transfers.
>
> +Note: The DMABUF interface is unsupported on rw_proxy endpoints. See
> +the RW Proxy Endpoints section for details on using DMABUF alongside
> +the ``FUNCTIONFS_RW_PROXY_EPS`` flag.
> +
> A userspace application can then use this interface to share DMABUF
> objects between several interfaces, allowing it to transfer data in a
> zero-copy fashion, for instance between IIO and the USB stack.
> diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
> index 4c1bafb3eef5..0ccfdcfb1810 100644
> --- a/drivers/usb/gadget/function/f_fs.c
> +++ b/drivers/usb/gadget/function/f_fs.c
> @@ -159,7 +159,9 @@ struct ffs_epfile {
> struct mutex mutex;
>
> struct ffs_data *ffs;
> - struct ffs_ep *ep; /* P: ffs->eps_lock */
> + struct ffs_ep *ep; /* P: ffs->eps_lock */
> + struct ffs_epfile *epfile_in; /* P: ffs->eps_lock */
> + struct ffs_epfile *epfile_out; /* P: ffs->eps_lock */
>
> /*
> * Buffer for holding data from partial reads which may happen since
> @@ -219,17 +221,20 @@ struct ffs_epfile {
> struct ffs_buffer *read_buffer;
> #define READ_BUFFER_DROP ((struct ffs_buffer *)ERR_PTR(-ESHUTDOWN))
>
> - char name[5];
> + char name[10];
Why change the size? Shouldn't that be a separate patch?
>
> unsigned char in; /* P: ffs->eps_lock */
> unsigned char isoc; /* P: ffs->eps_lock */
>
> u8 zlp_enabled; /* P: ffs->eps_lock */
> + bool is_rw_proxy;
>
> /* Protects dmabufs */
> struct mutex dmabufs_mutex;
> struct list_head dmabufs; /* P: dmabufs_mutex */
> atomic_t seqno;
> +
> + int opened_count; /* P: ffs->eps_lock */
Attempting to track "is this file open or not" almost always fails
horribly. Think about file descriptors that can be dup() and passed
around, the kernel has no idea what is going on with them, nor does it
have to.
Yes, we do track if the file is opened or not already, but I'd argue
that too is broken and should probably be removed and just use the
normal file descriptor logic instead.
> @@ -1378,8 +1393,18 @@ ffs_epfile_release(struct inode *inode, struct file *file)
>
> mutex_unlock(&epfile->dmabufs_mutex);
>
> - __ffs_epfile_read_buffer_free(epfile);
> - ffs_data_closed(epfile->ffs);
> + spin_lock_irq(&ffs->eps_lock);
> + if (epfile->is_rw_proxy) {
> + epfile->epfile_in->opened_count--;
> + if (--epfile->epfile_out->opened_count == 0)
> + __ffs_epfile_read_buffer_free(epfile->epfile_out);
> + } else {
> + if (--epfile->opened_count == 0)
> + __ffs_epfile_read_buffer_free(epfile);
If you drop the opened_count, shouldn't these buffers just get freed
when the structure themselves get freed? You are treating the count as
a "reference counted structure" in a hand-rolled way that might not
really be right here as it's kind of hard to prove.
Either use a real reference count for the whole structure (i.e. kref)
because you need to, or just tie the lifetime of the buffer to the
larger structure itself. Otherwise these fake references are going to
be a pain to track that all is correct with them...
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Hao Jia @ 2026-06-15 2:45 UTC (permalink / raw)
To: Yosry Ahmed, Shakeel Butt
Cc: Nhat Pham, akpm, tj, hannes, mhocko, mkoutny, chengming.zhou,
muchun.song, roman.gushchin, cgroups, linux-mm, linux-kernel,
linux-doc, Hao Jia
In-Reply-To: <CAO9r8zM=CMtUfV0RX3YyztqMNcw=s8M3WX6Q0epR5YHUvwTTKw@mail.gmail.com>
On 2026/6/13 02:15, Yosry Ahmed wrote:
> On Fri, Jun 12, 2026 at 9:40 AM Shakeel Butt <shakeel.butt@linux.dev> wrote:
>>
>> On Thu, Jun 11, 2026 at 05:39:16PM +0000, Yosry Ahmed wrote:
>>> On Tue, Jun 09, 2026 at 11:18:26AM +0800, Hao Jia wrote:
>>>>
>>>>
>>>> On 2026/6/9 02:01, Nhat Pham wrote:
>>>>> On Mon, Jun 8, 2026 at 9:48 AM Yosry Ahmed <yosry@kernel.org> wrote:
>>>>>>
>>>>>>> But OTOH, this does seem like a recipe for inefficient reclaim. We
>>>>>>> might exhaust hotter memory of a cgroup while sparing colder memory of
>>>>>>> another cgroup... But maybe if they're all cold anyway, then who
>>>>>>> cares, and eventually you'll get to the cold stuff of other child?
>>>>>>
>>>>>> Forgot to respond to this part, the unfairness is limited to the batch
>>>>>> size per-invocation, so it should be fine as long as you don't divide
>>>>>> the amount over 100 iterations for some reason. Also yes, all memory
>>>>>> in zswap is cold, the relative coldness is not that important (e.g.
>>>>>> compared to relative coldness during reclaim).
>>>>>
>>>>> Ok then yeah, I think we should shelve per-memcg cursor for the next
>>>>> version. Down the line, if we have more data that unfairness is an
>>>>> issue, we can always fix it. One step at a time :)
>>>>
>>>> Thanks a lot to Yosry, Nhat, and Shakeel for the great suggestions!
>>>>
>>>> Let me summarize what I plan to do in the next version to make sure we are
>>>> on the same page:
>>>>
>>>> - Drop the per-memcg cursor and keep the root cgroup cursor
>>>> (zswap_next_shrink) logic intact.
>>>> - Stick to using the zswap_writeback_only key, and change the proactive
>>>> writeback size to use the compressed size.
>>>> - Consolidate and reuse the logic between shrink_worker() and
>>>> shrink_memcg(). Enable batch writeback in the shrink_worker() path, while
>>>> keeping the writeback behavior in the zswap_store() path unchanged.
>>>>
>>>> Please let me know if I missed or misunderstood anything. Thanks again for
>>>> clearing things up!
>>>
>>> Sorry for the late response, yes I think this makes sense. However, I
>>> have some comment about how this interacts with swap tiering, let me
>>> reply to the other thread.
>>>
>>
>> I think the swap tiers interaction will be figured out over next cycle. However
>> Hao can/should continue to push and we may decide to let it in orthogonal to
>> swap tiers.
>
> Yeah I think there are a lot of changes we discussed outside of the
> memcg interface, so maybe keep the interface as-is for now, work on a
> new version with the other changes, and we can finalize the interface
> at the end?
Okay, I will split the non-memcg interface parts into a few separate
patches. These will serve as the preparation work for proactive
writeback and enable batch writeback in the shrink_worker() path.
However, I will still send the complete patchset using the
zswap_writeback_only key approach in the next version. This should make
it easier to review whether the preparation logic is reasonable, and to
decide whether it should eventually be merged independently of the swap
tiers.
Thanks,
Hao
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox