ACK/Cmnt: [SRU][R][PATCH 0/1] linux: dtbs_install fails on Resolute builders due to uutils install(1) EEXIST race under parallel make (LP: #2166356)

Stefan Bader stefan.bader at canonical.com
Thu Sep 3 15:06:16 UTC 2026


On 03/09/2026 15:55, Edoardo Canepa via kernel-team wrote:
> BugLink: https://bugs.launchpad.net/bugs/2166356
> 
> SRU Justification
> 
> [Impact]
> 
> Kernel source package builds for Resolute (26.04) fail intermittently
> during dtbs_install on Launchpad builders. The failure surfaces as:
> 
>    INSTALL .../device-tree/nuvoton/ma35d1-iot-512m.dtb
>    INSTALL .../device-tree/nuvoton/ma35d1-som-256m.dtb
>    INSTALL .../device-tree/nuvoton/nuvoton-npcm845-evb.dtb
>    install: cannot create directory '.../device-tree/nuvoton'
>    make[4]: *** [scripts/Makefile.dtbinst:23:
>        .../nuvoton/ma35d1-iot-512m.dtb] Error 1
> 
> The root cause is a race in the rust-coreutils implementation of
> install(1), which provides /usr/bin/install on Resolute. In uutils'
> `install -D`, parent-directory creation is done by stat_at() followed
> by mkdir_at() without retry: two concurrent invocations sharing a
> parent both observe NotFound before either issues mkdir_at(), the
> loser then receives EEXIST from the kernel and uutils bubbles it up
> as a hard error instead of treating an existing directory as success.
> 
> scripts/Makefile.dtbinst hard-codes literal `install -D -m 0644`,
> one invocation per .dtb file:
> 
>    quiet_cmd_dtb_install = INSTALL $@
>          cmd_dtb_install = install -D -m 0644 $< $@
> 
> Under `make -j`, every .dtb inside a given vendor directory (e.g.
> device-tree/apple/, device-tree/nuvoton/) races on that directory's
> creation, and the build fails non-deterministically.
> 
> Impact:
>    - Series: Resolute (26.04) only.
>    - Arches: any that enable do_dtbs=true (arm64, armhf); observed
>      on arm64 Launchpad builders for linux 7.0.0-37.37.
>    - Severity: hard build failure, blocks source package uploads.
> 
> [Fix]
> 
> Serialise the dtbs_install sub-make by forcing `-j1` for that single
> target in debian/rules.d/2-binary-arch.mk. All other targets in the
> package build ($(bldimg), modules, modules_install, headers_install)
> retain full parallelism via $(conc_level).
> 
> A tree-side fix is not viable in the SRU timeframe:
> 
>    - scripts/Makefile.dtbinst hard-codes the literal `install`; there
>      is no $(INSTALL) variable defined anywhere in the tree to hook.
>    - Resolute ships no GNU coreutils install(1) that we could point
>      to via an override even if the recipe were parametric.
>    - Fixing uutils is out of scope; the upstream fix (uutils/coreutils
>      PR #12429) is open but unmerged, and will need to land in
>      rust-coreutils before Resolute can benefit.
> 
> The workaround is intentionally minimal and self-documenting: an
> inline comment references the uutils issues so it can be reverted
> cleanly once #12429 lands in Resolute.
> 
> [Test Case]
> 
> Reproducer (without the patch):
> 
>    1. On a Resolute build environment with rust-coreutils providing
>       /usr/bin/install (default), obtain the linux source package
>       and run:
>           dpkg-buildpackage -B -aarm64 -j$(nproc)
>    2. Repeat 5-10 times. dtbs_install fails intermittently with
>       "install: cannot create directory '.../device-tree/<vendor>'"
>       and a non-zero exit from make[4].
> 
> Verification (with the patch):
> 
>    1. Same environment, same command. Run 10 consecutive builds.
>       None fail in dtbs_install.
>    2. Confirm the resulting linux-image-* package contains the full
>       set of .dtb files under
>           usr/lib/firmware/<abi>-<flavour>/device-tree/
>       matching the pre-patch layout (diff of installed file lists).
>    3. Wall-clock delta for dtbs_install between $(conc_level) and -j1
>       is under 10s on a Launchpad builder (I/O-bound, short target).
> 
> Additionally, a successful Launchpad rebuild of the affected source
> (linux 7.0.0-37.37) with the patch applied is the definitive test.
> 
> [Where problems could occur]
> 
> The change is one line: swap $(conc_level) for -j1 on the single
> `$(kmake) ... dtbs_install` invocation in
> debian/rules.d/2-binary-arch.mk. Scope of risk:
> 
>    - Build time: dtbs_install runs serially. In practice this is a
>      few seconds on arm64/armhf; the target is I/O-bound.
>    - No other build stage is touched; all other sub-makes still run
>      at $(conc_level).
>    - No change to compiler flags, config, ABI, module layout,
>      installed artefacts, or package contents.
>    - No effect on arches with do_dtbs != true (e.g. amd64), where
>      the guarded block is not entered at all.
>    - No runtime effect on end users; the change is confined to
>      package build.
> 
> If regressions do occur, they would manifest at build time (not on
> target systems) and can be reverted trivially by restoring
> $(conc_level).
> 
> [Other Info]
> 
> Upstream uutils references:
>    - uutils/coreutils#12355 — install -D loses some files to EEXIST
>    - uutils/coreutils#12429 — install: fix EEXIST race losing files
>                               in parallel install -D (open PR)
> 
> This is a SAUCE patch (packaging-only, no upstream analogue) tagged
> appropriately in the subject. It should be dropped when uutils
> PR #12429 is merged and lands in Resolute's rust-coreutils; the
> revert is a one-line change to restore $(conc_level).
> 
At least worth a try...

Acked-by: Stefan Bader <stefan.bader at canonical.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20260903/035cfcd6/attachment.sig>


More information about the kernel-team mailing list