summaryrefslogtreecommitdiff
path: root/libdm/libdm-common.c
diff options
context:
space:
mode:
authorZdenek Kabelac <zkabelac@redhat.com>2018-03-20 11:13:22 +0100
committerZdenek Kabelac <zkabelac@redhat.com>2018-03-23 17:24:58 +0100
commit30975a3328a0d101dda935644349dac58e2fb97f (patch)
tree4aaa5e5ca364014f5860b0b431ec4c3b559b5c82 /libdm/libdm-common.c
parent8c02cc9e8ffba777a92d798ca08c60e73dd2c109 (diff)
downloadlvm2-30975a3328a0d101dda935644349dac58e2fb97f.tar.gz
libdm: enhance mounted fs detection
btrfs is using fake major:minor device numbers. try to be smarter and detect used node via DM device name. This shortens delays, where i.e. lvm2 is asked to deactivate volume with mounted btrfs as such operation is not retryed and user is informed about device being in use.
Diffstat (limited to 'libdm/libdm-common.c')
-rw-r--r--libdm/libdm-common.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
index 99cf0c8a6..094e61854 100644
--- a/libdm/libdm-common.c
+++ b/libdm/libdm-common.c
@@ -1742,6 +1742,10 @@ static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min,
{
char root[PATH_MAX + 1]; /* sscanf needs extra '\0' */
char target[PATH_MAX + 1];
+ char *devmapper;
+ struct dm_task *dmt;
+ struct dm_info info;
+ unsigned i;
/* TODO: maybe detect availability of %ms glib support ? */
if (sscanf(line, "%*u %*u %u:%u %" DM_TO_STRING(PATH_MAX)
@@ -1751,6 +1755,32 @@ static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min,
return 0;
}
+ /* btrfs fakes device numbers, but there is still /dev/mapper name
+ * placed in mountinfo, so try to detect proper major:minor via this */
+ if (*maj == 0 && (devmapper = strstr(line, "/dev/mapper/"))) {
+ if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
+ log_error("Mount info task creation failed.");
+ return 0;
+ }
+ devmapper += 12; /* skip fixed prefix */
+ for (i = 0; devmapper[i] && devmapper[i] != ' ' && i < sizeof(root); ++i)
+ root[i] = devmapper[i];
+ root[i] = 0;
+ _unmangle_mountinfo_string(root, buf);
+ buf[DM_NAME_LEN] = 0; /* cut away */
+
+ if (dm_task_set_name(dmt, buf) &&
+ dm_task_no_open_count(dmt) &&
+ dm_task_run(dmt) &&
+ dm_task_get_info(dmt, &info)) {
+ log_debug("Replacing mountinfo device (%u:%u) with matching DM device %s (%u:%u).",
+ *maj, *min, buf, info.major, info.minor);
+ *maj = info.major;
+ *min = info.minor;
+ }
+ dm_task_destroy(dmt);
+ }
+
_unmangle_mountinfo_string(target, buf);
return 1;