[libvirt] [PATCH 4/4] storage: Add checks for buildVol create file

John Ferlan jferlan at redhat.com
Tue Oct 6 22:34:56 UTC 2015


The buildVol function can fail in numerous ways, but for cleaner or
clearer error path handling we want to know whether the calls we made
actually created the volume prior to blindly deleting the volume.
It could very well be that in between refreshing the pool, checking
whether the volume was already in the pool, and trying to create the
volume that something 'external' created a volume of the same name.
In this case, failure is likely and since we didn't create the volume
we shouldn't delete it either.

This patch may set the 'created' boolean for the following functions:

virStorageBackendCreateQemuImg (in virStorageBackendCreateExecCommand)
virStorageBackendCreateQcowCreate (in virStorageBackendCreateExecCommand)
virStorageBackendCreateFileDir (in virDirCreate)
virStorageBackendCreateRaw (in virFileOpenAs)
virStorageBackendRBDBuildVol
virStorageBackendSheepdogBuildVol

The patch avoids setting 'created' for the following function since
the 'target' of the buildVolFrom would be some sort of block device:

virStorageBackendCreateBlockFrom

NB: The fs, disk, and logical backends use the same common API
virStorageBackendGetBuildVolFromFunction in order to handle the
volBuildFrom calls to one of the virStorageBackendCreate* APIs

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/storage/storage_backend.c          | 20 ++++++++++++--------
 src/storage/storage_backend.h          |  3 +++
 src/storage/storage_backend_disk.c     |  3 ++-
 src/storage/storage_backend_fs.c       | 16 +++++++++++-----
 src/storage/storage_backend_logical.c  |  3 ++-
 src/storage/storage_backend_rbd.c      |  2 ++
 src/storage/storage_backend_sheepdog.c |  2 ++
 src/storage/storage_driver.c           | 16 +++++++++++-----
 8 files changed, 45 insertions(+), 20 deletions(-)

diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index b0535e5..112bb80 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -310,6 +310,7 @@ virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
                                  virStorageVolDefPtr vol,
                                  virStorageVolDefPtr inputvol,
+                                 bool *created ATTRIBUTE_UNUSED,
                                  unsigned int flags)
 {
     int fd = -1;
@@ -478,12 +479,12 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
                            virStoragePoolObjPtr pool,
                            virStorageVolDefPtr vol,
                            virStorageVolDefPtr inputvol,
+                           bool *created,
                            unsigned int flags)
 {
     int ret = -1;
     int fd = -1;
     int operation_flags;
-    bool created = false;
     bool reflink_copy = false;
     mode_t open_mode = VIR_STORAGE_DEFAULT_VOL_PERM_MODE;
 
@@ -526,7 +527,7 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
                             open_mode,
                             vol->target.perms->uid,
                             vol->target.perms->gid,
-                            &created,
+                            created,
                             operation_flags)) < 0) {
         virReportSystemError(-fd,
                              _("Failed to create file '%s'"),
@@ -674,13 +675,13 @@ virStorageGenerateQcowEncryption(virConnectPtr conn,
 static int
 virStorageBackendCreateExecCommand(virStoragePoolObjPtr pool,
                                    virStorageVolDefPtr vol,
-                                   virCommandPtr cmd)
+                                   virCommandPtr cmd,
+                                   bool *created)
 {
     struct stat st;
     gid_t gid;
     uid_t uid;
     mode_t mode;
-    bool filecreated = false;
 
     if ((pool->def->type == VIR_STORAGE_POOL_NETFS)
         && (((geteuid() == 0)
@@ -695,7 +696,7 @@ virStorageBackendCreateExecCommand(virStoragePoolObjPtr pool,
         if (virCommandRun(cmd, NULL) == 0) {
             /* command was successfully run, check if the file was created */
             if (stat(vol->target.path, &st) >= 0)
-                filecreated = true;
+                *created = true;
         }
     }
 
@@ -703,7 +704,7 @@ virStorageBackendCreateExecCommand(virStoragePoolObjPtr pool,
     virCommandSetUID(cmd, -1);
     virCommandSetGID(cmd, -1);
 
-    if (!filecreated) {
+    if (!*created) {
         if (virCommandRun(cmd, NULL) < 0)
             return -1;
         if (stat(vol->target.path, &st) < 0) {
@@ -711,6 +712,7 @@ virStorageBackendCreateExecCommand(virStoragePoolObjPtr pool,
                                  _("failed to create %s"), vol->target.path);
             return -1;
         }
+        *created = true;
     }
 
     uid = (vol->target.perms->uid != st.st_uid) ? vol->target.perms->uid
@@ -1088,6 +1090,7 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
                                virStoragePoolObjPtr pool,
                                virStorageVolDefPtr vol,
                                virStorageVolDefPtr inputvol,
+                               bool *created,
                                unsigned int flags)
 {
     int ret = -1;
@@ -1117,7 +1120,7 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
     if (!cmd)
         goto cleanup;
 
-    ret = virStorageBackendCreateExecCommand(pool, vol, cmd);
+    ret = virStorageBackendCreateExecCommand(pool, vol, cmd, created);
 
     virCommandFree(cmd);
  cleanup:
@@ -1134,6 +1137,7 @@ virStorageBackendCreateQcowCreate(virConnectPtr conn ATTRIBUTE_UNUSED,
                                   virStoragePoolObjPtr pool,
                                   virStorageVolDefPtr vol,
                                   virStorageVolDefPtr inputvol,
+                                  bool *created,
                                   unsigned int flags)
 {
     int ret;
@@ -1181,7 +1185,7 @@ virStorageBackendCreateQcowCreate(virConnectPtr conn ATTRIBUTE_UNUSED,
 
     cmd = virCommandNewArgList("qcow-create", size, vol->target.path, NULL);
 
-    ret = virStorageBackendCreateExecCommand(pool, vol, cmd);
+    ret = virStorageBackendCreateExecCommand(pool, vol, cmd, created);
     virCommandFree(cmd);
     VIR_FREE(size);
 
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
index 39c00b1..d574adb 100644
--- a/src/storage/storage_backend.h
+++ b/src/storage/storage_backend.h
@@ -51,6 +51,7 @@ typedef int (*virStorageBackendDeletePool)(virConnectPtr conn,
 typedef int (*virStorageBackendBuildVol)(virConnectPtr conn,
                                          virStoragePoolObjPtr pool,
                                          virStorageVolDefPtr vol,
+                                         bool *created,
                                          unsigned int flags);
 typedef int (*virStorageBackendCreateVol)(virConnectPtr conn,
                                           virStoragePoolObjPtr pool,
@@ -66,6 +67,7 @@ typedef int (*virStorageBackendBuildVolFrom)(virConnectPtr conn,
                                              virStoragePoolObjPtr pool,
                                              virStorageVolDefPtr origvol,
                                              virStorageVolDefPtr newvol,
+                                             bool *created,
                                              unsigned int flags);
 typedef int (*virStorageBackendVolumeResize)(virConnectPtr conn,
                                              virStoragePoolObjPtr pool,
@@ -97,6 +99,7 @@ int virStorageBackendCreateRaw(virConnectPtr conn,
                                virStoragePoolObjPtr pool,
                                virStorageVolDefPtr vol,
                                virStorageVolDefPtr inputvol,
+                               bool *created,
                                unsigned int flags);
 virStorageBackendBuildVolFrom
 virStorageBackendGetBuildVolFromFunction(virStorageVolDefPtr vol,
diff --git a/src/storage/storage_backend_disk.c b/src/storage/storage_backend_disk.c
index 7baecc1..b696c07 100644
--- a/src/storage/storage_backend_disk.c
+++ b/src/storage/storage_backend_disk.c
@@ -945,6 +945,7 @@ virStorageBackendDiskBuildVolFrom(virConnectPtr conn,
                                   virStoragePoolObjPtr pool,
                                   virStorageVolDefPtr vol,
                                   virStorageVolDefPtr inputvol,
+                                  bool *created,
                                   unsigned int flags)
 {
     virStorageBackendBuildVolFrom build_func;
@@ -953,7 +954,7 @@ virStorageBackendDiskBuildVolFrom(virConnectPtr conn,
     if (!build_func)
         return -1;
 
-    return build_func(conn, pool, vol, inputvol, flags);
+    return build_func(conn, pool, vol, inputvol, created, flags);
 }
 
 
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index fddec4b..a9e9e5d 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -1080,10 +1080,10 @@ static int createFileDir(virConnectPtr conn ATTRIBUTE_UNUSED,
                          virStoragePoolObjPtr pool,
                          virStorageVolDefPtr vol,
                          virStorageVolDefPtr inputvol,
+                         bool *created,
                          unsigned int flags)
 {
     int err;
-    bool created = false;
 
     virCheckFlags(0, -1);
 
@@ -1107,11 +1107,12 @@ static int createFileDir(virConnectPtr conn ATTRIBUTE_UNUSED,
                              vol->target.perms->mode),
                             vol->target.perms->uid,
                             vol->target.perms->gid,
-                            &created,
+                            created,
                             (pool->def->type == VIR_STORAGE_POOL_NETFS
                              ? VIR_DIR_CREATE_AS_UID : 0))) < 0) {
         return -1;
     }
+    *created = true;
 
     return 0;
 }
@@ -1121,6 +1122,7 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
                                      virStoragePoolObjPtr pool,
                                      virStorageVolDefPtr vol,
                                      virStorageVolDefPtr inputvol,
+                                     bool *created,
                                      unsigned int flags)
 {
     virStorageBackendBuildVolFrom create_func;
@@ -1154,7 +1156,7 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
         return -1;
     }
 
-    if (create_func(conn, pool, vol, inputvol, flags) < 0)
+    if (create_func(conn, pool, vol, inputvol, created, flags) < 0)
         return -1;
     return 0;
 }
@@ -1168,13 +1170,15 @@ static int
 virStorageBackendFileSystemVolBuild(virConnectPtr conn,
                                     virStoragePoolObjPtr pool,
                                     virStorageVolDefPtr vol,
+                                    bool *created,
                                     unsigned int flags)
 {
     virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
                   VIR_STORAGE_VOL_CREATE_REFLINK,
                   -1);
 
-    return _virStorageBackendFileSystemVolBuild(conn, pool, vol, NULL, flags);
+    return _virStorageBackendFileSystemVolBuild(conn, pool, vol, NULL,
+                                                created, flags);
 }
 
 /*
@@ -1185,13 +1189,15 @@ virStorageBackendFileSystemVolBuildFrom(virConnectPtr conn,
                                         virStoragePoolObjPtr pool,
                                         virStorageVolDefPtr vol,
                                         virStorageVolDefPtr inputvol,
+                                        bool *created,
                                         unsigned int flags)
 {
     virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
                   VIR_STORAGE_VOL_CREATE_REFLINK,
                   -1);
 
-    return _virStorageBackendFileSystemVolBuild(conn, pool, vol, inputvol, flags);
+    return _virStorageBackendFileSystemVolBuild(conn, pool, vol, inputvol,
+                                                created, flags);
 }
 
 /**
diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c
index 070f2bd..3702140 100644
--- a/src/storage/storage_backend_logical.c
+++ b/src/storage/storage_backend_logical.c
@@ -828,6 +828,7 @@ virStorageBackendLogicalBuildVolFrom(virConnectPtr conn,
                                      virStoragePoolObjPtr pool,
                                      virStorageVolDefPtr vol,
                                      virStorageVolDefPtr inputvol,
+                                     bool *created,
                                      unsigned int flags)
 {
     virStorageBackendBuildVolFrom build_func;
@@ -836,7 +837,7 @@ virStorageBackendLogicalBuildVolFrom(virConnectPtr conn,
     if (!build_func)
         return -1;
 
-    return build_func(conn, pool, vol, inputvol, flags);
+    return build_func(conn, pool, vol, inputvol, created, flags);
 }
 
 static int
diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c
index ac5085a..90d8596 100644
--- a/src/storage/storage_backend_rbd.c
+++ b/src/storage/storage_backend_rbd.c
@@ -491,6 +491,7 @@ static int
 virStorageBackendRBDBuildVol(virConnectPtr conn,
                              virStoragePoolObjPtr pool,
                              virStorageVolDefPtr vol,
+                             bool *created,
                              unsigned int flags)
 {
     virStorageBackendRBDState ptr;
@@ -531,6 +532,7 @@ virStorageBackendRBDBuildVol(virConnectPtr conn,
                              vol->name);
         goto cleanup;
     }
+    *created = true;
 
     if (volStorageBackendRBDRefreshVolInfo(vol, pool, &ptr) < 0)
         goto cleanup;
diff --git a/src/storage/storage_backend_sheepdog.c b/src/storage/storage_backend_sheepdog.c
index 69ba7836..3104578 100644
--- a/src/storage/storage_backend_sheepdog.c
+++ b/src/storage/storage_backend_sheepdog.c
@@ -260,6 +260,7 @@ static int
 virStorageBackendSheepdogBuildVol(virConnectPtr conn,
                                   virStoragePoolObjPtr pool,
                                   virStorageVolDefPtr vol,
+                                  bool *created,
                                   unsigned int flags)
 {
     int ret = -1;
@@ -278,6 +279,7 @@ virStorageBackendSheepdogBuildVol(virConnectPtr conn,
     virStorageBackendSheepdogAddHostArg(cmd, pool);
     if (virCommandRun(cmd, NULL) < 0)
         goto cleanup;
+    *created = true;
 
     if (virStorageBackendSheepdogRefreshVol(conn, pool, vol) < 0)
         goto cleanup;
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index ddf4405..66e5be2 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -1766,6 +1766,7 @@ storageVolCreateXML(virStoragePoolPtr obj,
     virStorageBackendPtr backend;
     virStorageVolDefPtr voldef = NULL;
     virStorageVolPtr ret = NULL, volobj = NULL;
+    bool created = false;
 
     virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
 
@@ -1857,7 +1858,8 @@ storageVolCreateXML(virStoragePoolPtr obj,
         voldef->building = true;
         virStoragePoolObjUnlock(pool);
 
-        buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
+        buildret = backend->buildVol(obj->conn, pool, buildvoldef,
+                                     &created, flags);
 
         storageDriverLock();
         virStoragePoolObjLock(pool);
@@ -1868,8 +1870,9 @@ storageVolCreateXML(virStoragePoolPtr obj,
 
         if (buildret < 0) {
             VIR_FREE(buildvoldef);
-            storageVolDeleteInternal(volobj, backend, pool, voldef,
-                                     0, false);
+            if (created)
+                storageVolDeleteInternal(volobj, backend, pool, voldef,
+                                         0, false);
             voldef = NULL;
             goto cleanup;
         }
@@ -1917,6 +1920,7 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
     virStorageVolDefPtr origvol = NULL, newvol = NULL, shadowvol = NULL;
     virStorageVolPtr ret = NULL, volobj = NULL;
     int buildret;
+    bool created = false;
 
     virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
                   VIR_STORAGE_VOL_CREATE_REFLINK,
@@ -2048,7 +2052,8 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
         virStoragePoolObjUnlock(origpool);
     }
 
-    buildret = backend->buildVolFrom(obj->conn, pool, shadowvol, origvol, flags);
+    buildret = backend->buildVolFrom(obj->conn, pool, shadowvol, origvol,
+                                     &created, flags);
 
     storageDriverLock();
     virStoragePoolObjLock(pool);
@@ -2069,7 +2074,8 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
     if (buildret < 0 ||
         (backend->refreshVol &&
          backend->refreshVol(obj->conn, pool, newvol) < 0)) {
-        storageVolDeleteInternal(volobj, backend, pool, newvol, 0, false);
+        if (created)
+            storageVolDeleteInternal(volobj, backend, pool, newvol, 0, false);
         newvol = NULL;
         goto cleanup;
     }
-- 
2.1.0




More information about the libvir-list mailing list