25aafc
From 29a17260cc1875640e62f63bfe7fa9661dc9fe70 Mon Sep 17 00:00:00 2001
25aafc
Message-Id: <29a17260cc1875640e62f63bfe7fa9661dc9fe70@dist-git>
25aafc
From: Michal Privoznik <mprivozn@redhat.com>
25aafc
Date: Wed, 20 Nov 2019 14:34:11 +0100
25aafc
Subject: [PATCH] qemu: Forcibly mknod() even if it exists
25aafc
MIME-Version: 1.0
25aafc
Content-Type: text/plain; charset=UTF-8
25aafc
Content-Transfer-Encoding: 8bit
25aafc
25aafc
Another weird bug appeared concerning qemu namespaces. Basically
25aafc
the problem is as follows:
25aafc
25aafc
1) Issue an API that causes libvirt to create a node in domain's
25aafc
   namespace, say /dev/nvme0n1 with 8:0 as major:minor (the API can
25aafc
   be attach-disk for instance). Or simply create the node from a
25aafc
   console by hand.
25aafc
25aafc
2) Detach the disk from qemu.
25aafc
25aafc
3) Do something that makes /dev/nvme0n1 change it's minor number.
25aafc
25aafc
4) Try to attach the disk again.
25aafc
25aafc
The problem is, in a few cases - like disk-detach - we don't
25aafc
remove the corresponding /dev node from the mount namespace
25aafc
(because it may be used by some other disk's backing chain). But
25aafc
this creates a problem, because if the node changes its MAJ:MIN
25aafc
numbers we don't propagate the change into the domain's
25aafc
namespace. We do plain mknod() and ignore EEXIST which obviously
25aafc
is not enough because it doesn't guarantee that the node has
25aafc
updated MAJ:MIN pair.
25aafc
25aafc
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1752978
25aafc
25aafc
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
25aafc
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
25aafc
(cherry picked from commit cdd8a6690ee3fa4b4b8ca1d4531924bd33be136a)
25aafc
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
25aafc
Message-Id: <058a9025fdcb817d3334e6c5a7c6a4fe1e95e761.1574256841.git.mprivozn@redhat.com>
25aafc
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
25aafc
---
25aafc
 src/qemu/qemu_domain.c | 25 +++++++++----------------
25aafc
 1 file changed, 9 insertions(+), 16 deletions(-)
25aafc
25aafc
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
25aafc
index e7d7a3baeb..3c67769771 100644
25aafc
--- a/src/qemu/qemu_domain.c
25aafc
+++ b/src/qemu/qemu_domain.c
25aafc
@@ -11191,16 +11191,14 @@ qemuDomainCreateDeviceRecursive(const char *device,
25aafc
                                             allow_noent, ttl - 1) < 0)
25aafc
             goto cleanup;
25aafc
     } else if (isDev) {
25aafc
-        if (create &&
25aafc
-            mknod(devicePath, sb.st_mode, sb.st_rdev) < 0) {
25aafc
-            if (errno == EEXIST) {
25aafc
-                ret = 0;
25aafc
-            } else {
25aafc
+        if (create) {
25aafc
+            unlink(devicePath);
25aafc
+            if (mknod(devicePath, sb.st_mode, sb.st_rdev) < 0) {
25aafc
                 virReportSystemError(errno,
25aafc
                                      _("Failed to make device %s"),
25aafc
                                      devicePath);
25aafc
+                goto cleanup;
25aafc
             }
25aafc
-            goto cleanup;
25aafc
         }
25aafc
     } else if (isReg) {
25aafc
         if (create &&
25aafc
@@ -11969,17 +11967,12 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED,
25aafc
     } else if (isDev) {
25aafc
         VIR_DEBUG("Creating dev %s (%d,%d)",
25aafc
                   data->file, major(data->sb.st_rdev), minor(data->sb.st_rdev));
25aafc
+        unlink(data->file);
25aafc
         if (mknod(data->file, data->sb.st_mode, data->sb.st_rdev) < 0) {
25aafc
-            /* Because we are not removing devices on hotunplug, or
25aafc
-             * we might be creating part of backing chain that
25aafc
-             * already exist due to a different disk plugged to
25aafc
-             * domain, accept EEXIST. */
25aafc
-            if (errno != EEXIST) {
25aafc
-                virReportSystemError(errno,
25aafc
-                                     _("Unable to create device %s"),
25aafc
-                                     data->file);
25aafc
-                goto cleanup;
25aafc
-            }
25aafc
+            virReportSystemError(errno,
25aafc
+                                 _("Unable to create device %s"),
25aafc
+                                 data->file);
25aafc
+            goto cleanup;
25aafc
         } else {
25aafc
             delDevice = true;
25aafc
         }
25aafc
-- 
25aafc
2.24.0
25aafc