]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: introduce sysfs_devno_is_dm_hidden() for pre-open check
authorZdenek Kabelac <zkabelac@redhat.com>
Fri, 17 Apr 2026 14:55:43 +0000 (16:55 +0200)
committerZdenek Kabelac <zkabelac@redhat.com>
Fri, 17 Apr 2026 15:02:42 +0000 (17:02 +0200)
Stratis reuses the DM "private" UUID convention ("stratis-1-private")
but its devices are legitimately opened by tools like mkfs.xfs to
obtain device geometry.  The pre-open check added in the previous
commit (d05a84b22) used sysfs_devno_is_dm_private() which also
blocks Stratis devices, breaking mkfs.xfs on Stratis pools.

Introduce sysfs_devno_is_dm_hidden() which only checks for LVM
internal devices (the "LVM-<uuid>-<name>" UUID pattern).  A "hidden"
DM device is one that exists solely as a building block for another
DM target -- no user-space tool should normally open or write to it.

Use sysfs_devno_is_dm_hidden() in blkid_new_probe_from_filename()
so that Stratis devices remain accessible while LVM internal devices
are still skipped before open().

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
include/sysfs.h
lib/sysfs.c
libblkid/src/probe.c

index 7583407028bdc8b3eb9440caf332f253f8c4fb1c..37f3b71caef6bec0b5bdd6cb713a5e6f9ef580ef 100644 (file)
@@ -95,6 +95,7 @@ int sysfs_blkdev_get_wholedisk( struct path_cxt *pc,
 
 int sysfs_devno_to_wholedisk(dev_t dev, char *diskname,
                              size_t len, dev_t *diskdevno);
+int sysfs_devno_is_dm_hidden(dev_t devno, char **uuid);
 int sysfs_devno_is_dm_private(dev_t devno, char **uuid);
 int sysfs_devno_is_wholedisk(dev_t devno);
 
index c2ffd429e32987499b9031f3a100a9838e146826..a856854bd6c096143814a311f88e0ab265ed2a6d 100644 (file)
@@ -652,6 +652,48 @@ int sysfs_devno_to_wholedisk(dev_t devno, char *diskname,
        return rc;
 }
 
+/*
+ * Returns 1 if the device is a hidden device-mapper device -- i.e. a device
+ * that exists only as a building block for another DM target and should not
+ * be opened by user-space tools (blkid, mkfs, etc.) during udev processing.
+ *
+ * Unlike sysfs_devno_is_dm_private(), this does NOT flag Stratis devices.
+ * Stratis places its own UUID ("stratis-1-private*") in the DM uuid field,
+ * but its devices are legitimately opened by tools such as mkfs.xfs to
+ * obtain device geometry.
+ *
+ * The @uuid (if not NULL) returns DM device UUID, use free() to deallocate.
+ */
+int sysfs_devno_is_dm_hidden(dev_t devno, char **uuid)
+{
+       struct path_cxt *pc = NULL;
+       char *id = NULL;
+       int rc = 0;
+
+       pc = ul_new_sysfs_path(devno, NULL, NULL);
+       if (!pc)
+               goto done;
+       if (ul_path_read_string(pc, &id, "dm/uuid") <= 0 || !id)
+               goto done;
+
+       /* Private LVM devices use "LVM-<uuid>-<name>" uuid format (important
+        * is the "LVM" prefix and "-<name>" postfix).
+        */
+       if (strncmp(id, "LVM-", 4) == 0) {
+               char *p = strrchr(id + 4, '-');
+
+               if (p && *(p + 1))
+                       rc = 1;
+       }
+done:
+       ul_unref_path(pc);
+       if (uuid)
+               *uuid = id;
+       else
+               free(id);
+       return rc;
+}
+
 /*
  * Returns 1 if the device is private device mapper device. The @uuid
  * (if not NULL) returns DM device UUID, use free() to deallocate.
index 84cffa40f658adaa55b30c1ff05a65fba2ffea44..bbe6d8c4651ca84bff718f39f92b8be6b83715e4 100644 (file)
@@ -219,13 +219,17 @@ blkid_probe blkid_new_probe_from_filename(const char *filename)
        struct stat sb;
 
        /*
-        * Check for private device-mapper devices (LVM internals, etc.)
+        * Check for hidden device-mapper devices (LVM internals, etc.)
         * before open() to avoid bumping the kernel open count.  A racing
         * DM_DEVICE_REMOVE would otherwise see EBUSY.
+        *
+        * Use sysfs_devno_is_dm_hidden() rather than _dm_private() so that
+        * Stratis devices remain accessible to tools like mkfs.xfs that
+        * need to probe device geometry.
         */
        if (stat(filename, &sb) == 0 && S_ISBLK(sb.st_mode) &&
-           sysfs_devno_is_dm_private(sb.st_rdev, NULL)) {
-               DBG(LOWPROBE, ul_debug("ignore private device mapper device"));
+           sysfs_devno_is_dm_hidden(sb.st_rdev, NULL)) {
+               DBG(LOWPROBE, ul_debug("ignore hidden device mapper device"));
                errno = EINVAL;
                return NULL;
        }