]> xenbits.xensource.com Git - libvirt.git/commitdiff
storage: wipe: Move helper code into storage backend
authorPeter Krempa <pkrempa@redhat.com>
Mon, 7 Jul 2014 13:41:33 +0000 (15:41 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Thu, 17 Jul 2014 08:12:34 +0000 (10:12 +0200)
The next patch will move the storage volume wiping code into the
individual backends. This patch splits out the common code to wipe a
local volume into a separate backend helper so that the next patch is
simpler.

src/storage/storage_backend.c
src/storage/storage_backend.h
src/storage/storage_driver.c

index dc835d36bad0832a47690f51a6bc2b449cc36524..5e7aa3ca813dae5c00abd98656323219882c52ed 100644 (file)
@@ -1724,6 +1724,209 @@ virStorageBackendVolDownloadLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
     return virFDStreamOpenFile(stream, vol->target.path, offset, len, O_RDONLY);
 }
 
+
+/* If the volume we're wiping is already a sparse file, we simply
+ * truncate and extend it to its original size, filling it with
+ * zeroes.  This behavior is guaranteed by POSIX:
+ *
+ * http://www.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
+ *
+ * If fildes refers to a regular file, the ftruncate() function shall
+ * cause the size of the file to be truncated to length. If the size
+ * of the file previously exceeded length, the extra data shall no
+ * longer be available to reads on the file. If the file previously
+ * was smaller than this size, ftruncate() shall increase the size of
+ * the file. If the file size is increased, the extended area shall
+ * appear as if it were zero-filled.
+ */
+static int
+virStorageBackendVolZeroSparseFileLocal(virStorageVolDefPtr vol,
+                                        off_t size,
+                                        int fd)
+{
+    int ret = -1;
+
+    ret = ftruncate(fd, 0);
+    if (ret == -1) {
+        virReportSystemError(errno,
+                             _("Failed to truncate volume with "
+                               "path '%s' to 0 bytes"),
+                             vol->target.path);
+        return ret;
+    }
+
+    ret = ftruncate(fd, size);
+    if (ret == -1) {
+        virReportSystemError(errno,
+                             _("Failed to truncate volume with "
+                               "path '%s' to %ju bytes"),
+                             vol->target.path, (uintmax_t)size);
+    }
+
+    return ret;
+}
+
+
+static int
+virStorageBackendWipeExtentLocal(virStorageVolDefPtr vol,
+                                 int fd,
+                                 off_t extent_start,
+                                 off_t extent_length,
+                                 char *writebuf,
+                                 size_t writebuf_length,
+                                 size_t *bytes_wiped)
+{
+    int ret = -1, written = 0;
+    off_t remaining = 0;
+    size_t write_size = 0;
+
+    VIR_DEBUG("extent logical start: %ju len: %ju",
+              (uintmax_t)extent_start, (uintmax_t)extent_length);
+
+    if ((ret = lseek(fd, extent_start, SEEK_SET)) < 0) {
+        virReportSystemError(errno,
+                             _("Failed to seek to position %ju in volume "
+                               "with path '%s'"),
+                             (uintmax_t)extent_start, vol->target.path);
+        goto cleanup;
+    }
+
+    remaining = extent_length;
+    while (remaining > 0) {
+
+        write_size = (writebuf_length < remaining) ? writebuf_length : remaining;
+        written = safewrite(fd, writebuf, write_size);
+        if (written < 0) {
+            virReportSystemError(errno,
+                                 _("Failed to write %zu bytes to "
+                                   "storage volume with path '%s'"),
+                                 write_size, vol->target.path);
+
+            goto cleanup;
+        }
+
+        *bytes_wiped += written;
+        remaining -= written;
+    }
+
+    if (fdatasync(fd) < 0) {
+        ret = -errno;
+        virReportSystemError(errno,
+                             _("cannot sync data to volume with path '%s'"),
+                             vol->target.path);
+        goto cleanup;
+    }
+
+    VIR_DEBUG("Wrote %zu bytes to volume with path '%s'",
+              *bytes_wiped, vol->target.path);
+
+    ret = 0;
+
+ cleanup:
+    return ret;
+}
+
+
+int
+virStorageBackendVolWipeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
+                              virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+                              virStorageVolDefPtr vol,
+                              unsigned int algorithm,
+                              unsigned int flags)
+{
+    int ret = -1, fd = -1;
+    struct stat st;
+    char *writebuf = NULL;
+    size_t bytes_wiped = 0;
+    virCommandPtr cmd = NULL;
+
+    virCheckFlags(0, -1);
+
+    VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
+              vol->target.path, algorithm);
+
+    fd = open(vol->target.path, O_RDWR);
+    if (fd == -1) {
+        virReportSystemError(errno,
+                             _("Failed to open storage volume with path '%s'"),
+                             vol->target.path);
+        goto cleanup;
+    }
+
+    if (fstat(fd, &st) == -1) {
+        virReportSystemError(errno,
+                             _("Failed to stat storage volume with path '%s'"),
+                             vol->target.path);
+        goto cleanup;
+    }
+
+    if (algorithm != VIR_STORAGE_VOL_WIPE_ALG_ZERO) {
+        const char *alg_char ATTRIBUTE_UNUSED = NULL;
+        switch (algorithm) {
+        case VIR_STORAGE_VOL_WIPE_ALG_NNSA:
+            alg_char = "nnsa";
+            break;
+        case VIR_STORAGE_VOL_WIPE_ALG_DOD:
+            alg_char = "dod";
+            break;
+        case VIR_STORAGE_VOL_WIPE_ALG_BSI:
+            alg_char = "bsi";
+            break;
+        case VIR_STORAGE_VOL_WIPE_ALG_GUTMANN:
+            alg_char = "gutmann";
+            break;
+        case VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER:
+            alg_char = "schneier";
+            break;
+        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
+            alg_char = "pfitzner7";
+            break;
+        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
+            alg_char = "pfitzner33";
+            break;
+        case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
+            alg_char = "random";
+            break;
+        default:
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("unsupported algorithm %d"),
+                           algorithm);
+        }
+        cmd = virCommandNew(SCRUB);
+        virCommandAddArgList(cmd, "-f", "-p", alg_char,
+                             vol->target.path, NULL);
+
+        if (virCommandRun(cmd, NULL) < 0)
+            goto cleanup;
+
+        ret = 0;
+        goto cleanup;
+    } else {
+        if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
+            ret = virStorageBackendVolZeroSparseFileLocal(vol, st.st_size, fd);
+        } else {
+
+            if (VIR_ALLOC_N(writebuf, st.st_blksize) < 0)
+                goto cleanup;
+
+            ret = virStorageBackendWipeExtentLocal(vol,
+                                                   fd,
+                                                   0,
+                                                   vol->target.allocation,
+                                                   writebuf,
+                                                   st.st_blksize,
+                                                   &bytes_wiped);
+        }
+    }
+
+ cleanup:
+    virCommandFree(cmd);
+    VIR_FREE(writebuf);
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+
+
 #ifdef GLUSTER_CLI
 int
 virStorageBackendFindGlusterPoolSources(const char *host,
index 4d7d4b0272a454bbbb4866b512f62607995d5d1e..5e251d7b79a7c7cd6a0765b5ccc85914e3848c3e 100644 (file)
@@ -120,6 +120,12 @@ int virStorageBackendVolDownloadLocal(virConnectPtr conn,
                                       unsigned long long len,
                                       unsigned int flags);
 
+int virStorageBackendVolWipeLocal(virConnectPtr conn,
+                                  virStoragePoolObjPtr pool,
+                                  virStorageVolDefPtr vol,
+                                  unsigned int algorithm,
+                                  unsigned int flags);
+
 typedef struct _virStorageBackend virStorageBackend;
 typedef virStorageBackend *virStorageBackendPtr;
 
index 5407dfb2a5e038fd1f6dcd91c859724e35724165..97571e8fe64d816ecbc8ab0b5e78b9e06b895fed 100644 (file)
@@ -2094,202 +2094,6 @@ storageVolResize(virStorageVolPtr obj,
     return ret;
 }
 
-/* If the volume we're wiping is already a sparse file, we simply
- * truncate and extend it to its original size, filling it with
- * zeroes.  This behavior is guaranteed by POSIX:
- *
- * http://www.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
- *
- * If fildes refers to a regular file, the ftruncate() function shall
- * cause the size of the file to be truncated to length. If the size
- * of the file previously exceeded length, the extra data shall no
- * longer be available to reads on the file. If the file previously
- * was smaller than this size, ftruncate() shall increase the size of
- * the file. If the file size is increased, the extended area shall
- * appear as if it were zero-filled.
- */
-static int
-storageVolZeroSparseFile(virStorageVolDefPtr vol,
-                         off_t size,
-                         int fd)
-{
-    int ret = -1;
-
-    ret = ftruncate(fd, 0);
-    if (ret == -1) {
-        virReportSystemError(errno,
-                             _("Failed to truncate volume with "
-                               "path '%s' to 0 bytes"),
-                             vol->target.path);
-        return ret;
-    }
-
-    ret = ftruncate(fd, size);
-    if (ret == -1) {
-        virReportSystemError(errno,
-                             _("Failed to truncate volume with "
-                               "path '%s' to %ju bytes"),
-                             vol->target.path, (uintmax_t)size);
-    }
-
-    return ret;
-}
-
-
-static int
-storageWipeExtent(virStorageVolDefPtr vol,
-                  int fd,
-                  off_t extent_start,
-                  off_t extent_length,
-                  char *writebuf,
-                  size_t writebuf_length,
-                  size_t *bytes_wiped)
-{
-    int ret = -1, written = 0;
-    off_t remaining = 0;
-    size_t write_size = 0;
-
-    VIR_DEBUG("extent logical start: %ju len: %ju",
-              (uintmax_t)extent_start, (uintmax_t)extent_length);
-
-    if ((ret = lseek(fd, extent_start, SEEK_SET)) < 0) {
-        virReportSystemError(errno,
-                             _("Failed to seek to position %ju in volume "
-                               "with path '%s'"),
-                             (uintmax_t)extent_start, vol->target.path);
-        goto cleanup;
-    }
-
-    remaining = extent_length;
-    while (remaining > 0) {
-
-        write_size = (writebuf_length < remaining) ? writebuf_length : remaining;
-        written = safewrite(fd, writebuf, write_size);
-        if (written < 0) {
-            virReportSystemError(errno,
-                                 _("Failed to write %zu bytes to "
-                                   "storage volume with path '%s'"),
-                                 write_size, vol->target.path);
-
-            goto cleanup;
-        }
-
-        *bytes_wiped += written;
-        remaining -= written;
-    }
-
-    if (fdatasync(fd) < 0) {
-        ret = -errno;
-        virReportSystemError(errno,
-                             _("cannot sync data to volume with path '%s'"),
-                             vol->target.path);
-        goto cleanup;
-    }
-
-    VIR_DEBUG("Wrote %zu bytes to volume with path '%s'",
-              *bytes_wiped, vol->target.path);
-
-    ret = 0;
-
- cleanup:
-    return ret;
-}
-
-
-static int
-storageVolWipeInternal(virStorageVolDefPtr def,
-                       unsigned int algorithm)
-{
-    int ret = -1, fd = -1;
-    struct stat st;
-    char *writebuf = NULL;
-    size_t bytes_wiped = 0;
-    virCommandPtr cmd = NULL;
-
-    VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
-              def->target.path, algorithm);
-
-    fd = open(def->target.path, O_RDWR);
-    if (fd == -1) {
-        virReportSystemError(errno,
-                             _("Failed to open storage volume with path '%s'"),
-                             def->target.path);
-        goto cleanup;
-    }
-
-    if (fstat(fd, &st) == -1) {
-        virReportSystemError(errno,
-                             _("Failed to stat storage volume with path '%s'"),
-                             def->target.path);
-        goto cleanup;
-    }
-
-    if (algorithm != VIR_STORAGE_VOL_WIPE_ALG_ZERO) {
-        const char *alg_char ATTRIBUTE_UNUSED = NULL;
-        switch (algorithm) {
-        case VIR_STORAGE_VOL_WIPE_ALG_NNSA:
-            alg_char = "nnsa";
-            break;
-        case VIR_STORAGE_VOL_WIPE_ALG_DOD:
-            alg_char = "dod";
-            break;
-        case VIR_STORAGE_VOL_WIPE_ALG_BSI:
-            alg_char = "bsi";
-            break;
-        case VIR_STORAGE_VOL_WIPE_ALG_GUTMANN:
-            alg_char = "gutmann";
-            break;
-        case VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER:
-            alg_char = "schneier";
-            break;
-        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
-            alg_char = "pfitzner7";
-            break;
-        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
-            alg_char = "pfitzner33";
-            break;
-        case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
-            alg_char = "random";
-            break;
-        default:
-            virReportError(VIR_ERR_INVALID_ARG,
-                           _("unsupported algorithm %d"),
-                           algorithm);
-        }
-        cmd = virCommandNew(SCRUB);
-        virCommandAddArgList(cmd, "-f", "-p", alg_char,
-                             def->target.path, NULL);
-
-        if (virCommandRun(cmd, NULL) < 0)
-            goto cleanup;
-
-        ret = 0;
-        goto cleanup;
-    } else {
-        if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
-            ret = storageVolZeroSparseFile(def, st.st_size, fd);
-        } else {
-
-            if (VIR_ALLOC_N(writebuf, st.st_blksize) < 0)
-                goto cleanup;
-
-            ret = storageWipeExtent(def,
-                                    fd,
-                                    0,
-                                    def->target.allocation,
-                                    writebuf,
-                                    st.st_blksize,
-                                    &bytes_wiped);
-        }
-    }
-
- cleanup:
-    virCommandFree(cmd);
-    VIR_FREE(writebuf);
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
 
 static int
 storageVolWipePattern(virStorageVolPtr obj,
@@ -2330,9 +2134,8 @@ storageVolWipePattern(virStorageVolPtr obj,
         goto cleanup;
     }
 
-    if (storageVolWipeInternal(vol, algorithm) == -1) {
+    if (virStorageBackendVolWipeLocal(obj->conn, pool, vol, algorithm, flags) < 0)
         goto cleanup;
-    }
 
     ret = 0;