diff options
author | Zdenek Kabelac <zkabelac@redhat.com> | 2018-03-20 11:13:22 +0100 |
---|---|---|
committer | Zdenek Kabelac <zkabelac@redhat.com> | 2018-03-23 17:24:58 +0100 |
commit | 30975a3328a0d101dda935644349dac58e2fb97f (patch) | |
tree | 4aaa5e5ca364014f5860b0b431ec4c3b559b5c82 /libdm/libdm-common.c | |
parent | 8c02cc9e8ffba777a92d798ca08c60e73dd2c109 (diff) | |
download | lvm2-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.c | 30 |
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; |