virdevmapper: Don't cache device-mapper major

The device mapper major is needed in virIsDevMapperDevice() which
determines whether given device is managed by device-mapper. This
number is obtained by parsing /proc/devices and then stored in a
global variable so that the file doesn't have to be parsed again.
However, as it turns out this logic is flawed - the major number
is not static and can change as it can be specified as a
parameter when loading the dm-mod module.

Unfortunately, I was not able to come up with a good solution and
thus the /proc/devices file is being parsed every time we need
the device mapper major.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
Tested-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
This commit is contained in:
Michal Privoznik 2020-08-18 11:08:15 +02:00
parent cbce7a12b7
commit 82bb167f0d

View File

@ -46,11 +46,9 @@
G_STATIC_ASSERT(BUF_SIZE > sizeof(struct dm_ioctl));
static unsigned int virDMMajor;
static int
virDevMapperOnceInit(void)
virDevMapperGetMajor(unsigned int *major)
{
g_autofree char *buf = NULL;
VIR_AUTOSTRINGLIST lines = NULL;
@ -69,7 +67,7 @@ virDevMapperOnceInit(void)
if (sscanf(lines[i], "%u %ms\n", &maj, &dev) == 2 &&
STREQ(dev, DM_NAME)) {
virDMMajor = maj;
*major = maj;
break;
}
}
@ -85,9 +83,6 @@ virDevMapperOnceInit(void)
}
VIR_ONCE_GLOBAL_INIT(virDevMapper);
static void *
virDMIoctl(int controlFD, int cmd, struct dm_ioctl *dm, char **buf)
{
@ -304,9 +299,6 @@ virDevMapperGetTargets(const char *path,
* consist of devices or yet another targets. If that's the
* case, we have to stop recursion somewhere. */
if (virDevMapperInitialize() < 0)
return -1;
if ((controlFD = virDMOpen()) < 0)
return -1;
@ -318,13 +310,14 @@ bool
virIsDevMapperDevice(const char *dev_name)
{
struct stat buf;
unsigned int major;
if (virDevMapperInitialize() < 0)
if (virDevMapperGetMajor(&major) < 0)
return false;
if (!stat(dev_name, &buf) &&
S_ISBLK(buf.st_mode) &&
major(buf.st_rdev) == virDMMajor)
major(buf.st_rdev) == major)
return true;
return false;