From: Zdenek Kabelac Date: Fri, 17 Apr 2026 14:55:43 +0000 (+0200) Subject: libblkid: introduce sysfs_devno_is_dm_hidden() for pre-open check X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a42fbbb5a446f8f97a7b401653c98042be45d3df;p=thirdparty%2Futil-linux.git libblkid: introduce sysfs_devno_is_dm_hidden() for pre-open check 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 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 --- diff --git a/include/sysfs.h b/include/sysfs.h index 758340702..37f3b71ca 100644 --- a/include/sysfs.h +++ b/include/sysfs.h @@ -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); diff --git a/lib/sysfs.c b/lib/sysfs.c index c2ffd429e..a856854bd 100644 --- a/lib/sysfs.c +++ b/lib/sysfs.c @@ -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 format (important + * is the "LVM" prefix and "-" 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. diff --git a/libblkid/src/probe.c b/libblkid/src/probe.c index 84cffa40f..bbe6d8c46 100644 --- a/libblkid/src/probe.c +++ b/libblkid/src/probe.c @@ -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; }