public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/cloud-init] f45: Pick a proposed patch for util-linux 2.42 compatibility
@ 2026-09-15 13:00 Jeremy Cline
  0 siblings, 0 replies; only message in thread
From: Jeremy Cline @ 2026-09-15 13:00 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/cloud-init
            Branch : f45
            Commit : 3eb8ae8ad5095cbee0eb3446bb2d30d2613db836
            Author : Jeremy Cline <jeremycline@microsoft.com>
            Date   : 2026-09-14T10:54:00-04:00
            Stats  : +53/-428 in 4 file(s)
            URL    : https://src.fedoraproject.org/rpms/cloud-init/c/3eb8ae8ad5095cbee0eb3446bb2d30d2613db836?branch=f45

            Log:
            Pick a proposed patch for util-linux 2.42 compatibility

Fedora 45+ ships util-linux 2.42, which started using udev for
determining filesystem types when mounting a filesystem using type
"auto". This can lead to a race condition when reformatting a disk with
a different filesystem and then immediately trying to mount it without
specifying its new type.

A common example of this is (non-OS) disks in Azure which are presented
to the guest as NTFS; these are then by default reformatted to ext4 in
Fedora's image and the subsequent command to mount them fails because
mount selects the ntfs tooling, rather than ext4, since udev hasn't
necessarily settled with the new values.

The patch is still undergoing discussion upstream since just calling
udev settle isn't ideal, but it's not clear whether cloud-init
can/should be writing its fstab entry with an explicit filesystem type,
or whether util-linux will re-consider relying on udev for the
filesystem type. In the mean time, this allows users to continue to have
their additional disks mounted on first boot.

---
diff --git a/6339.patch b/6339.patch
deleted file mode 100644
index cc08a1e..0000000
--- a/6339.patch
+++ /dev/null
@@ -1,407 +0,0 @@
-From 2d864b3346270d045242c7de2ca124077a0850d5 Mon Sep 17 00:00:00 2001
-From: Brett Holman <brett.holman@canonical.com>
-Date: Mon, 28 Jul 2025 10:41:51 -0600
-Subject: [PATCH 1/6] feat: support nmap in socket protocol
-
----
- cloudinit/socket.py                     | 35 ++++++++++++++-----------
- systemd/cloud-config.service            |  2 +-
- systemd/cloud-final.service             |  2 +-
- systemd/cloud-init-local.service.tmpl   |  2 +-
- systemd/cloud-init-network.service.tmpl |  2 +-
- tests/unittests/test_all_stages.py      |  3 +--
- 6 files changed, 25 insertions(+), 21 deletions(-)
-
-diff --git a/cloudinit/socket.py b/cloudinit/socket.py
-index 98c82886ff6..d7bc7108c51 100644
---- a/cloudinit/socket.py
-+++ b/cloudinit/socket.py
-@@ -5,6 +5,8 @@
- import socket
- import sys
- from contextlib import suppress
-+from dataclasses import dataclass
-+from typing import Optional
- 
- from cloudinit import performance
- from cloudinit.settings import DEFAULT_RUN_DIR
-@@ -12,6 +14,12 @@
- LOG = logging.getLogger(__name__)
- 
- 
-+@dataclass
-+class StreamSocket:
-+    socket: socket.socket
-+    connection: Optional[socket.socket]
-+
-+
- def sd_notify(message: str):
-     """Send a sd_notify message.
- 
-@@ -55,13 +63,15 @@ def __init__(self, *names: str):
-         :param names: stage names, used as a unique identifiers
-         """
-         self.stage = ""
--        self.remote = ""
-         self.first_exception = ""
-         self.systemd_exit_code = 0
-         self.experienced_any_error = False
-         self.sockets = {
--            name: socket.socket(
--                socket.AF_UNIX, socket.SOCK_DGRAM | socket.SOCK_CLOEXEC
-+            name: StreamSocket(
-+                socket.socket(
-+                    socket.AF_UNIX, socket.SOCK_STREAM | socket.SOCK_CLOEXEC
-+                ),
-+                None,
-             )
-             for name in names
-         }
-@@ -72,7 +82,8 @@ def __init__(self, *names: str):
-             socket_path = f"{DEFAULT_RUN_DIR}/share/{name}.sock"
-             with suppress(FileNotFoundError):
-                 os.remove(socket_path)
--            sock.bind(socket_path)
-+            sock.socket.bind(socket_path)
-+            sock.socket.listen()
- 
-     def __call__(self, stage: str):
-         """Set the stage before entering context.
-@@ -116,19 +127,13 @@ def __enter__(self):
-         #     reply, which is expected to be /path/to/{self.stage}-return.sock
-         sock = self.sockets[self.stage]
-         with performance.Timed(f"Waiting to start stage {self.stage}"):
--            chunk, self.remote = sock.recvfrom(5)
-+            sock.connection, _ = sock.socket.accept()
-+            chunk, _ = sock.connection.recvfrom(5)
- 
-         if b"start" != chunk:
-             # The protocol expects to receive a command "start"
-             self.__exit__(None, None, None)
-             raise ValueError(f"Received invalid message: [{str(chunk)}]")
--        elif f"{DEFAULT_RUN_DIR}/share/{self.stage}-return.sock" != str(
--            self.remote
--        ):
--            # assert that the return path is in a directory with appropriate
--            # permissions
--            self.__exit__(None, None, None)
--            raise ValueError(f"Unexpected path to unix socket: {self.remote}")
- 
-         sd_notify(f"STATUS=Running ({self.stage} stage)")
-         return self
-@@ -157,15 +162,15 @@ def __exit__(self, exc_type, exc_val, exc_tb):
-             self.systemd_exit_code
-         )
-         sock = self.sockets[self.stage]
--        sock.connect(self.remote)
-+        assert isinstance(sock.connection, socket.socket)
- 
-         # the returned message will be executed in a subshell
-         # hardcode this message rather than sending a more informative message
-         # to avoid having to sanitize inputs (to prevent escaping the shell)
--        sock.sendall(
-+        sock.connection.sendall(
-             f"echo '{message}'; exit {self.systemd_exit_code};".encode()
-         )
--        sock.close()
-+        sock.connection.close()
- 
-         # suppress exception - the exception was logged and the init system
-         # notified of stage completion (and the exception received as a status
-diff --git a/systemd/cloud-config.service b/systemd/cloud-config.service
-index 68f80d2b3f8..3fe62f9d961 100644
---- a/systemd/cloud-config.service
-+++ b/systemd/cloud-config.service
-@@ -16,7 +16,7 @@ Type=oneshot
- # process has completed this stage. The output from the return socket is piped
- # into a shell so that the process can send a completion message (defaults to
- # "done", otherwise includes an error message) and an exit code to systemd.
--ExecStart=sh -c 'echo "start" | nc -Uu -W1 /run/cloud-init/share/config.sock -s /run/cloud-init/share/config-return.sock | sh'
-+ExecStart=sh -c 'echo "start" | nc -U /run/cloud-init/share/config.sock | sh'
- RemainAfterExit=yes
- TimeoutSec=0
- 
-diff --git a/systemd/cloud-final.service b/systemd/cloud-final.service
-index fb74a47c8eb..e7e892ab9a4 100644
---- a/systemd/cloud-final.service
-+++ b/systemd/cloud-final.service
-@@ -19,7 +19,7 @@ Type=oneshot
- # process has completed this stage. The output from the return socket is piped
- # into a shell so that the process can send a completion message (defaults to
- # "done", otherwise includes an error message) and an exit code to systemd.
--ExecStart=sh -c 'echo "start" | nc -Uu -W1 /run/cloud-init/share/final.sock -s /run/cloud-init/share/final-return.sock | sh'
-+ExecStart=sh -c 'echo "start" | nc -U /run/cloud-init/share/final.sock | sh'
- RemainAfterExit=yes
- TimeoutSec=0
- TasksMax=infinity
-diff --git a/systemd/cloud-init-local.service.tmpl b/systemd/cloud-init-local.service.tmpl
-index 26a6aee1d05..b8a2f33111c 100644
---- a/systemd/cloud-init-local.service.tmpl
-+++ b/systemd/cloud-init-local.service.tmpl
-@@ -33,7 +33,7 @@ ExecStartPre=/sbin/restorecon /run/cloud-init
- # process has completed this stage. The output from the return socket is piped
- # into a shell so that the process can send a completion message (defaults to
- # "done", otherwise includes an error message) and an exit code to systemd.
--ExecStart=sh -c 'echo "start" | nc -Uu -W1 /run/cloud-init/share/local.sock -s /run/cloud-init/share/local-return.sock | sh'
-+ExecStart=sh -c 'echo "start" | nc -U /run/cloud-init/share/local.sock | sh'
- RemainAfterExit=yes
- TimeoutSec=0
- 
-diff --git a/systemd/cloud-init-network.service.tmpl b/systemd/cloud-init-network.service.tmpl
-index 61425b4a9fd..9658af1d633 100644
---- a/systemd/cloud-init-network.service.tmpl
-+++ b/systemd/cloud-init-network.service.tmpl
-@@ -56,7 +56,7 @@ Type=oneshot
- # process has completed this stage. The output from the return socket is piped
- # into a shell so that the process can send a completion message (defaults to
- # "done", otherwise includes an error message) and an exit code to systemd.
--ExecStart=sh -c 'echo "start" | nc -Uu -W1 /run/cloud-init/share/network.sock -s /run/cloud-init/share/network-return.sock | sh'
-+ExecStart=sh -c 'echo "start" | nc -U /run/cloud-init/share/network.sock | sh'
- RemainAfterExit=yes
- TimeoutSec=0
- 
-diff --git a/tests/unittests/test_all_stages.py b/tests/unittests/test_all_stages.py
-index 90bde5e1add..1b66e6955ba 100644
---- a/tests/unittests/test_all_stages.py
-+++ b/tests/unittests/test_all_stages.py
-@@ -15,9 +15,8 @@ class Sync:
-     """
- 
-     def __init__(self, name: str, path: str):
--        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
-+        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-         self.sock.connect(f"{path}/share/{name}.sock")
--        self.sock.bind(f"{path}/share/{name}-return.sock")
-         self.sock.sendall(b"start")
- 
-     def receive(self):
-
-From 41fe777167a5d7c1cdfbe60bb825e61c2f132cef Mon Sep 17 00:00:00 2001
-From: Brett Holman <brett.holman@canonical.com>
-Date: Mon, 28 Jul 2025 11:01:48 -0600
-Subject: [PATCH 2/6] fixup! feat: support nmap in socket protocol
-
----
- cloudinit/socket.py | 9 +++++----
- 1 file changed, 5 insertions(+), 4 deletions(-)
-
-diff --git a/cloudinit/socket.py b/cloudinit/socket.py
-index d7bc7108c51..29d38f8067f 100644
---- a/cloudinit/socket.py
-+++ b/cloudinit/socket.py
-@@ -6,18 +6,18 @@
- import sys
- from contextlib import suppress
- from dataclasses import dataclass
--from typing import Optional
--
-+from typing import Optional, TypeAlias
- from cloudinit import performance
- from cloudinit.settings import DEFAULT_RUN_DIR
- 
- LOG = logging.getLogger(__name__)
- 
-+Socket: TypeAlias = socket.socket
- 
- @dataclass
- class StreamSocket:
--    socket: socket.socket
--    connection: Optional[socket.socket]
-+    socket: Socket
-+    connection: Optional[Socket]
- 
- 
- def sd_notify(message: str):
-@@ -128,6 +128,7 @@ def __enter__(self):
-         sock = self.sockets[self.stage]
-         with performance.Timed(f"Waiting to start stage {self.stage}"):
-             sock.connection, _ = sock.socket.accept()
-+            assert isinstance(sock.connection, socket.socket)
-             chunk, _ = sock.connection.recvfrom(5)
- 
-         if b"start" != chunk:
-
-From 78d2308291061bd849491845dfb681c4aa048826 Mon Sep 17 00:00:00 2001
-From: Brett Holman <brett.holman@canonical.com>
-Date: Mon, 28 Jul 2025 11:07:52 -0600
-Subject: [PATCH 3/6] fixup! fixup! feat: support nmap in socket protocol
-
----
- cloudinit/socket.py | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/cloudinit/socket.py b/cloudinit/socket.py
-index 29d38f8067f..475beb27ac0 100644
---- a/cloudinit/socket.py
-+++ b/cloudinit/socket.py
-@@ -6,13 +6,13 @@
- import sys
- from contextlib import suppress
- from dataclasses import dataclass
--from typing import Optional, TypeAlias
-+from typing import Optional
- from cloudinit import performance
- from cloudinit.settings import DEFAULT_RUN_DIR
- 
- LOG = logging.getLogger(__name__)
- 
--Socket: TypeAlias = socket.socket
-+Socket = socket.socket
- 
- @dataclass
- class StreamSocket:
-
-From 6822b50e204486e9c3806ac6837dbc7df5ef86c5 Mon Sep 17 00:00:00 2001
-From: Brett Holman <brett.holman@canonical.com>
-Date: Mon, 28 Jul 2025 11:13:52 -0600
-Subject: [PATCH 4/6] fixup! fixup! fixup! feat: support nmap in socket
- protocol
-
----
- cloudinit/socket.py | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/cloudinit/socket.py b/cloudinit/socket.py
-index 475beb27ac0..6d4a3e699d3 100644
---- a/cloudinit/socket.py
-+++ b/cloudinit/socket.py
-@@ -7,6 +7,7 @@
- from contextlib import suppress
- from dataclasses import dataclass
- from typing import Optional
-+
- from cloudinit import performance
- from cloudinit.settings import DEFAULT_RUN_DIR
- 
-@@ -14,6 +15,7 @@
- 
- Socket = socket.socket
- 
-+
- @dataclass
- class StreamSocket:
-     socket: Socket
-
-From 39f81452627bcde7e04574137f9e527098966584 Mon Sep 17 00:00:00 2001
-From: Brett Holman <brett.holman@canonical.com>
-Date: Tue, 29 Jul 2025 10:20:16 -0600
-Subject: [PATCH 5/6] fixup! fixup! fixup! fixup! feat: support nmap in socket
- protocol
-
----
- cloudinit/socket.py | 34 ++++++++++++----------------------
- 1 file changed, 12 insertions(+), 22 deletions(-)
-
-diff --git a/cloudinit/socket.py b/cloudinit/socket.py
-index 6d4a3e699d3..bc14b01c726 100644
---- a/cloudinit/socket.py
-+++ b/cloudinit/socket.py
-@@ -5,8 +5,7 @@
- import socket
- import sys
- from contextlib import suppress
--from dataclasses import dataclass
--from typing import Optional
-+from typing import Dict
- 
- from cloudinit import performance
- from cloudinit.settings import DEFAULT_RUN_DIR
-@@ -16,12 +15,6 @@
- Socket = socket.socket
- 
- 
--@dataclass
--class StreamSocket:
--    socket: Socket
--    connection: Optional[Socket]
--
--
- def sd_notify(message: str):
-     """Send a sd_notify message.
- 
-@@ -69,14 +62,12 @@ def __init__(self, *names: str):
-         self.systemd_exit_code = 0
-         self.experienced_any_error = False
-         self.sockets = {
--            name: StreamSocket(
--                socket.socket(
--                    socket.AF_UNIX, socket.SOCK_STREAM | socket.SOCK_CLOEXEC
--                ),
--                None,
-+            name: socket.socket(
-+                socket.AF_UNIX, socket.SOCK_STREAM | socket.SOCK_CLOEXEC
-             )
-             for name in names
-         }
-+        self.connections: Dict[str, socket.socket] = {}
-         # ensure the directory exists
-         os.makedirs(f"{DEFAULT_RUN_DIR}/share", mode=0o700, exist_ok=True)
-         # removing stale sockets and bind
-@@ -84,8 +75,8 @@ def __init__(self, *names: str):
-             socket_path = f"{DEFAULT_RUN_DIR}/share/{name}.sock"
-             with suppress(FileNotFoundError):
-                 os.remove(socket_path)
--            sock.socket.bind(socket_path)
--            sock.socket.listen()
-+            sock.bind(socket_path)
-+            sock.listen()
- 
-     def __call__(self, stage: str):
-         """Set the stage before entering context.
-@@ -129,9 +120,9 @@ def __enter__(self):
-         #     reply, which is expected to be /path/to/{self.stage}-return.sock
-         sock = self.sockets[self.stage]
-         with performance.Timed(f"Waiting to start stage {self.stage}"):
--            sock.connection, _ = sock.socket.accept()
--            assert isinstance(sock.connection, socket.socket)
--            chunk, _ = sock.connection.recvfrom(5)
-+            connection, _ = sock.accept()
-+            chunk, _ = connection.recvfrom(5)
-+            self.connections[self.stage] = connection
- 
-         if b"start" != chunk:
-             # The protocol expects to receive a command "start"
-@@ -164,16 +155,15 @@ def __exit__(self, exc_type, exc_val, exc_tb):
-         self.experienced_any_error = self.experienced_any_error or bool(
-             self.systemd_exit_code
-         )
--        sock = self.sockets[self.stage]
--        assert isinstance(sock.connection, socket.socket)
-+        sock = self.connections[self.stage]
- 
-         # the returned message will be executed in a subshell
-         # hardcode this message rather than sending a more informative message
-         # to avoid having to sanitize inputs (to prevent escaping the shell)
--        sock.connection.sendall(
-+        sock.sendall(
-             f"echo '{message}'; exit {self.systemd_exit_code};".encode()
-         )
--        sock.connection.close()
-+        sock.close()
- 
-         # suppress exception - the exception was logged and the init system
-         # notified of stage completion (and the exception received as a status
-
-From e6b0d4eab8b3f6d2c5fb8ce841582fde88b53fa9 Mon Sep 17 00:00:00 2001
-From: Brett Holman <brett.holman@canonical.com>
-Date: Tue, 19 Aug 2025 09:12:51 -0600
-Subject: [PATCH 6/6] fixup! fixup! fixup! fixup! fixup! feat: support nmap in
- socket protocol
-
----
- cloudinit/socket.py | 2 --
- 1 file changed, 2 deletions(-)
-
-diff --git a/cloudinit/socket.py b/cloudinit/socket.py
-index bc14b01c726..0a5485a07e6 100644
---- a/cloudinit/socket.py
-+++ b/cloudinit/socket.py
-@@ -12,8 +12,6 @@
- 
- LOG = logging.getLogger(__name__)
- 
--Socket = socket.socket
--
- 
- def sd_notify(message: str):
-     """Send a sd_notify message.

diff --git a/6448.patch b/6448.patch
deleted file mode 100644
index 1830e43..0000000
--- a/6448.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-From ffe13614ba5a47a262abba7e4867493595e3b92b Mon Sep 17 00:00:00 2001
-From: Brett Holman <brett.holman@canonical.com>
-Date: Tue, 2 Sep 2025 10:24:52 -0600
-Subject: [PATCH] fix(systemd): revert auditd.service dependency
-
----
- systemd/cloud-init-local.service.tmpl | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/systemd/cloud-init-local.service.tmpl b/systemd/cloud-init-local.service.tmpl
-index b8a2f33111c..e88b15ca246 100644
---- a/systemd/cloud-init-local.service.tmpl
-+++ b/systemd/cloud-init-local.service.tmpl
-@@ -7,7 +7,6 @@ DefaultDependencies=no
- {% endif %}
- Wants=network-pre.target
- After=hv_kvp_daemon.service
--Before=auditd.service
- Before=network-pre.target
- Before=shutdown.target
- {% if variant in ["almalinux", "cloudlinux", "rhel"] %}

diff --git a/7082.patch b/7082.patch
new file mode 100644
index 0000000..955bf71
--- /dev/null
+++ b/7082.patch
@@ -0,0 +1,50 @@
+From 21239ffeb8af8b1b379a62341f8eb2e8354fe374 Mon Sep 17 00:00:00 2001
+From: Bala Konda Reddy M <bala12352@gmail.com>
+Date: Tue, 8 Sep 2026 13:36:44 -0700
+Subject: [PATCH] fix(mount): settle udev before mounting filesystems
+
+Wait for pending udev events before running mount -a. This ensures mount
+uses current filesystem information after a disk has been reformatted.
+
+fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2525858
+
+Signed-off-by: Bala Konda Reddy M <bala12352@gmail.com>
+---
+ cloudinit/config/cc_mounts.py            | 1 +
+ tests/unittests/config/test_cc_mounts.py | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py
+index e83fbd8dff8..eb535520a39 100644
+--- a/cloudinit/config/cc_mounts.py
++++ b/cloudinit/config/cc_mounts.py
+@@ -508,6 +508,7 @@ def mount_if_needed(
+         do_mount = bool(set(dirs).difference(mount_points))
+ 
+     if do_mount:
++        util.udevadm_settle()
+         subp.subp(["mount", "-a"])
+         if uses_systemd:
+             subp.subp(["systemctl", "daemon-reload"])
+diff --git a/tests/unittests/config/test_cc_mounts.py b/tests/unittests/config/test_cc_mounts.py
+index 7da080544fb..1d23f725674 100644
+--- a/tests/unittests/config/test_cc_mounts.py
++++ b/tests/unittests/config/test_cc_mounts.py
+@@ -298,6 +298,9 @@ def setup(self, mocker, fake_fs):
+         fake_fs.create_dir("/etc")
+ 
+         self.m_subp = mocker.patch(f"{M_PATH}subp.subp")
++        self.m_udevadm_settle = mocker.patch(
++            f"{M_PATH}util.udevadm_settle"
++        )
+         self.m_mounts = mocker.patch(
+             f"{M_PATH}util.mounts",
+             return_value={
+@@ -473,6 +476,7 @@ def test_no_change_fstab_sets_needs_mount_all(self):
+         with open(cc_mounts.FSTAB_PATH, "r") as fd:
+             fstab_new_content = fd.read()
+             assert fstab_original_content == fstab_new_content.strip()
++        self.m_udevadm_settle.assert_called_once_with()
+         self.m_subp.assert_has_calls(
+             [
+                 mock.call(["mount", "-a"]),

diff --git a/cloud-init.spec b/cloud-init.spec
index 9ff28b9..d96bd44 100644
--- a/cloud-init.spec
+++ b/cloud-init.spec
@@ -21,6 +21,9 @@ Patch:          0001-fix-avoid-dependency-cycle-on-Fedora.patch
 # https://github.com/canonical/cloud-init/pull/6922
 # feat: add ELN support to distros
 Patch:          0002-feat-add-ELN-support-to-distros.patch
+# https://github.com/canonical/cloud-init/pull/7082.patch
+# Fixes reformatting disks with util-linux 2.42.
+Patch:          7082.patch
 
 BuildArch:      noarch
 

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-15 13:00 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-15 13:00 [rpms/cloud-init] f45: Pick a proposed patch for util-linux 2.42 compatibility Jeremy Cline

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox