diff --git a/SOURCES/libvirt-virdevmapper-Don-t-cache-device-mapper-major.patch b/SOURCES/libvirt-virdevmapper-Don-t-cache-device-mapper-major.patch new file mode 100644 index 0000000..c02e3ab --- /dev/null +++ b/SOURCES/libvirt-virdevmapper-Don-t-cache-device-mapper-major.patch @@ -0,0 +1,99 @@ +From bc406e0919e72b1f108ded76a380212b179c8572 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Tue, 25 Aug 2020 17:16:05 +0200 +Subject: [PATCH] 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 +Reviewed-by: Peter Krempa +Reviewed-by: Christian Ehrhardt +Tested-by: Christian Ehrhardt +(cherry picked from commit 82bb167f0d15b733b23931205be3488b83cb9ec6) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1860421 + +Signed-off-by: Michal Privoznik +Message-Id: <64b6d6124918bc8cfe220464752eac93cd6d6734.1598364552.git.mprivozn@redhat.com> +Reviewed-by: Jiri Denemark +--- + src/util/virdevmapper.c | 17 +++++------------ + 1 file changed, 5 insertions(+), 12 deletions(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index a471504176..b43dbefa9a 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -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) + { +@@ -305,9 +300,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; + +@@ -319,13 +311,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; +-- +2.28.0 + diff --git a/SOURCES/libvirt-virdevmapper-Handle-kernel-without-device-mapper-support.patch b/SOURCES/libvirt-virdevmapper-Handle-kernel-without-device-mapper-support.patch new file mode 100644 index 0000000..c55aa74 --- /dev/null +++ b/SOURCES/libvirt-virdevmapper-Handle-kernel-without-device-mapper-support.patch @@ -0,0 +1,87 @@ +From a9c950dcbac1f708bcd01111d4ec9b550db37fe3 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Tue, 25 Aug 2020 17:16:06 +0200 +Subject: [PATCH] virdevmapper: Handle kernel without device-mapper support + +In one of my latest patch (v6.6.0~30) I was trying to remove +libdevmapper use in favor of our own implementation. However, the +code did not take into account that device mapper can be not +compiled into the kernel (e.g. be a separate module that's not +loaded) in which case /proc/devices won't have the device-mapper +major number and thus virDevMapperGetTargets() and/or +virIsDevMapperDevice() fails. + +However, such failure is safe to ignore, because if device mapper +is missing then there can't be any multipath devices and thus we +don't need to allow the deps in CGroups, nor create them in the +domain private namespace, etc. + +Fixes: 22494556542c676d1b9e7f1c1f2ea13ac17e1e3e +Reported-by: Andrea Bolognani +Reported-by: Christian Ehrhardt +Signed-off-by: Michal Privoznik +Reviewed-by: Peter Krempa +Reviewed-by: Christian Ehrhardt +Tested-by: Christian Ehrhardt +(cherry picked from commit feb8564a3cc63bc8f68284063d53ec0d2d81a1cc) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1860421 + +Signed-off-by: Michal Privoznik +Message-Id: <71fcd93071dffdf4942ccce8671af7fcbcec397f.1598364552.git.mprivozn@redhat.com> +Reviewed-by: Jiri Denemark +--- + src/util/virdevmapper.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index b43dbefa9a..a81e2edee4 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -54,6 +54,9 @@ virDevMapperGetMajor(unsigned int *major) + VIR_AUTOSTRINGLIST lines = NULL; + size_t i; + ++ if (!virFileExists(CONTROL_PATH)) ++ return -2; ++ + if (virFileReadAll(PROC_DEVICES, BUF_SIZE, &buf) < 0) + return -1; + +@@ -126,8 +129,13 @@ virDMOpen(void) + + memset(&dm, 0, sizeof(dm)); + +- if ((controlFD = open(CONTROL_PATH, O_RDWR)) < 0) ++ if ((controlFD = open(CONTROL_PATH, O_RDWR)) < 0) { ++ if (errno == ENOENT) ++ return -2; ++ ++ virReportSystemError(errno, _("Unable to open %s"), CONTROL_PATH); + return -1; ++ } + + if (!virDMIoctl(controlFD, DM_VERSION, &dm, &tmp)) { + virReportSystemError(errno, "%s", +@@ -300,8 +308,16 @@ virDevMapperGetTargets(const char *path, + * consist of devices or yet another targets. If that's the + * case, we have to stop recursion somewhere. */ + +- if ((controlFD = virDMOpen()) < 0) ++ if ((controlFD = virDMOpen()) < 0) { ++ if (controlFD == -2) { ++ /* The CONTROL_PATH doesn't exist. Probably the ++ * module isn't loaded, yet. Don't error out, just ++ * exit. */ ++ return 0; ++ } ++ + return -1; ++ } + + return virDevMapperGetTargetsImpl(controlFD, path, devPaths, ttl); + } +-- +2.28.0 + diff --git a/SOURCES/libvirt-virdevmapper-Ignore-all-errors-when-opening-dev-mapper-control.patch b/SOURCES/libvirt-virdevmapper-Ignore-all-errors-when-opening-dev-mapper-control.patch new file mode 100644 index 0000000..d7ab070 --- /dev/null +++ b/SOURCES/libvirt-virdevmapper-Ignore-all-errors-when-opening-dev-mapper-control.patch @@ -0,0 +1,88 @@ +From b38ab86a0a2cf3453d37a5fe96b2e022d8a1d48a Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Tue, 25 Aug 2020 17:16:07 +0200 +Subject: [PATCH] virdevmapper: Ignore all errors when opening + /dev/mapper/control + +So far, only ENOENT is ignored (to deal with kernels without +devmapper). However, as reported on the list, under certain +scenarios a different error can occur. For instance, when libvirt +is running inside a container which doesn't have permissions to +talk to the devmapper. If this is the case, then open() returns +-1 and sets errno=EPERM. + +Assuming that multipath devices are fairly narrow use case and +using them in a restricted container is even more narrow the best +fix seems to be to ignore all open errors BUT produce a warning +on failure. To avoid flooding logs with warnings on kernels +without devmapper the level is reduced to a plain debug message. + +Reported-by: Christian Ehrhardt +Reviewed-by: Christian Ehrhardt +Signed-off-by: Michal Privoznik +(cherry picked from commit 53d9af1e7924757e3b5f661131dd707d7110d094) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1860421 + +Signed-off-by: Michal Privoznik +Message-Id: +Reviewed-by: Jiri Denemark +--- + src/util/virdevmapper.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index a81e2edee4..ee2fab5ae3 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -35,9 +35,12 @@ + # include "viralloc.h" + # include "virstring.h" + # include "virfile.h" ++# include "virlog.h" + + # define VIR_FROM_THIS VIR_FROM_STORAGE + ++VIR_LOG_INIT("util.virdevmapper"); ++ + # define PROC_DEVICES "/proc/devices" + # define DM_NAME "device-mapper" + # define DEV_DM_DIR "/dev/" DM_DIR +@@ -130,11 +133,15 @@ virDMOpen(void) + memset(&dm, 0, sizeof(dm)); + + if ((controlFD = open(CONTROL_PATH, O_RDWR)) < 0) { +- if (errno == ENOENT) +- return -2; +- +- virReportSystemError(errno, _("Unable to open %s"), CONTROL_PATH); +- return -1; ++ /* We can't talk to devmapper. Produce a warning and let ++ * the caller decide what to do next. */ ++ if (errno == ENOENT) { ++ VIR_DEBUG("device mapper not available"); ++ } else { ++ VIR_WARN("unable to open %s: %s", ++ CONTROL_PATH, g_strerror(errno)); ++ } ++ return -2; + } + + if (!virDMIoctl(controlFD, DM_VERSION, &dm, &tmp)) { +@@ -310,9 +317,9 @@ virDevMapperGetTargets(const char *path, + + if ((controlFD = virDMOpen()) < 0) { + if (controlFD == -2) { +- /* The CONTROL_PATH doesn't exist. Probably the +- * module isn't loaded, yet. Don't error out, just +- * exit. */ ++ /* The CONTROL_PATH doesn't exist or is unusable. ++ * Probably the module isn't loaded, yet. Don't error ++ * out, just exit. */ + return 0; + } + +-- +2.28.0 + diff --git a/SPECS/libvirt.spec b/SPECS/libvirt.spec index f8dfb3c..f221a1b 100644 --- a/SPECS/libvirt.spec +++ b/SPECS/libvirt.spec @@ -219,7 +219,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 6.0.0 -Release: 27%{?dist}%{?extra_release} +Release: 28%{?dist}%{?extra_release} License: LGPLv2+ URL: https://libvirt.org/ @@ -666,6 +666,9 @@ Patch434: libvirt-virdevmapper.c-Join-two-WITH_DEVMAPPER-sections-together.patch Patch435: libvirt-virDevMapperGetTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch Patch436: libvirt-virdevmapper-Don-t-use-libdevmapper-to-obtain-dependencies.patch Patch437: libvirt-virDevMapperGetTargets-Don-t-ignore-EBADF.patch +Patch438: libvirt-virdevmapper-Don-t-cache-device-mapper-major.patch +Patch439: libvirt-virdevmapper-Handle-kernel-without-device-mapper-support.patch +Patch440: libvirt-virdevmapper-Ignore-all-errors-when-opening-dev-mapper-control.patch Requires: libvirt-daemon = %{version}-%{release} Requires: libvirt-daemon-config-network = %{version}-%{release} @@ -2442,6 +2445,11 @@ exit 0 %changelog +* Wed Aug 26 2020 Jiri Denemark - 6.0.0-28 +- virdevmapper: Don't cache device-mapper major (rhbz#1860421) +- virdevmapper: Handle kernel without device-mapper support (rhbz#1860421) +- virdevmapper: Ignore all errors when opening /dev/mapper/control (rhbz#1860421) + * Fri Aug 7 2020 Jiri Denemark - 6.0.0-27 - src: assume sys/sysmacros.h always exists on Linux (rhbz#1860421) - virdevmapper.c: Join two WITH_DEVMAPPER sections together (rhbz#1860421)