c401cc
From 62a72076e2fe3431de116d0ddc9f5811a9bbbce0 Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <62a72076e2fe3431de116d0ddc9f5811a9bbbce0@dist-git>
c401cc
From: Eric Blake <eblake@redhat.com>
c401cc
Date: Wed, 26 Feb 2014 14:54:28 +0100
c401cc
Subject: [PATCH] storage: probe qcow2 volumes in gluster pool
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1032370
c401cc
c401cc
Putting together pieces from previous patches, it is now possible
c401cc
for 'virsh vol-dumpxml --pool gluster volname' to report metadata
c401cc
about a qcow2 file stored on gluster.  The backing file is still
c401cc
treated as raw; to fix that, more patches are needed to make the
c401cc
storage backing chain analysis recursive rather than halting at
c401cc
a network protocol name, but that work will not need any further
c401cc
calls into libgfapi so much as just reusing this code, and that
c401cc
should be the only code outside of the storage driver that needs
c401cc
any help from libgfapi.  Any additional use of libgfapi within
c401cc
libvirt should only be needed for implementing storage pool APIs
c401cc
such as volume creation or resizing, where backing chain analysis
c401cc
should be unaffected.
c401cc
c401cc
* src/storage/storage_backend_gluster.c
c401cc
(virStorageBackendGlusterReadHeader): New helper function.
c401cc
(virStorageBackendGlusterRefreshVol): Probe non-raw files.
c401cc
c401cc
Signed-off-by: Eric Blake <eblake@redhat.com>
c401cc
(cherry picked from commit 14daa81280dfabb8c553c4d5a84cfcc4a0235366)
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/storage/storage_backend_gluster.c | 79 ++++++++++++++++++++++++++++++++++-
c401cc
 1 file changed, 78 insertions(+), 1 deletion(-)
c401cc
c401cc
diff --git a/src/storage/storage_backend_gluster.c b/src/storage/storage_backend_gluster.c
c401cc
index f0ec357..01af4bd 100644
c401cc
--- a/src/storage/storage_backend_gluster.c
c401cc
+++ b/src/storage/storage_backend_gluster.c
c401cc
@@ -147,6 +147,37 @@ error:
c401cc
 }
c401cc
 
c401cc
 
c401cc
+static ssize_t
c401cc
+virStorageBackendGlusterReadHeader(glfs_fd_t *fd,
c401cc
+                                   const char *name,
c401cc
+                                   ssize_t maxlen,
c401cc
+                                   char **buf)
c401cc
+{
c401cc
+    char *s;
c401cc
+    size_t nread = 0;
c401cc
+
c401cc
+    if (VIR_ALLOC_N(*buf, maxlen) < 0)
c401cc
+        return -1;
c401cc
+
c401cc
+    s = *buf;
c401cc
+    while (maxlen) {
c401cc
+        ssize_t r = glfs_read(fd, s, maxlen, 0);
c401cc
+        if (r < 0 && errno == EINTR)
c401cc
+            continue;
c401cc
+        if (r < 0) {
c401cc
+            VIR_FREE(*buf);
c401cc
+            virReportSystemError(errno, _("unable to read '%s'"), name);
c401cc
+            return r;
c401cc
+        }
c401cc
+        if (r == 0)
c401cc
+            return nread;
c401cc
+        buf += r;
c401cc
+        maxlen -= r;
c401cc
+        nread += r;
c401cc
+    }
c401cc
+    return nread;
c401cc
+}
c401cc
+
c401cc
 /* Populate *volptr for the given name and stat information, or leave
c401cc
  * it NULL if the entry should be skipped (such as ".").  Return 0 on
c401cc
  * success, -1 on failure. */
c401cc
@@ -159,6 +190,10 @@ virStorageBackendGlusterRefreshVol(virStorageBackendGlusterStatePtr state,
c401cc
     char *tmp;
c401cc
     int ret = -1;
c401cc
     virStorageVolDefPtr vol = NULL;
c401cc
+    glfs_fd_t *fd = NULL;
c401cc
+    virStorageFileMetadata *meta = NULL;
c401cc
+    char *header = NULL;
c401cc
+    ssize_t len = VIR_STORAGE_MAX_HEADER;
c401cc
 
c401cc
     *volptr = NULL;
c401cc
 
c401cc
@@ -208,15 +243,57 @@ virStorageBackendGlusterRefreshVol(virStorageBackendGlusterStatePtr state,
c401cc
         goto cleanup;
c401cc
     }
c401cc
 
c401cc
-    /* FIXME - must open files to determine if they are non-raw */
c401cc
     vol->type = VIR_STORAGE_VOL_NETWORK;
c401cc
     vol->target.format = VIR_STORAGE_FILE_RAW;
c401cc
+    /* No need to worry about O_NONBLOCK - gluster doesn't allow creation
c401cc
+     * of fifos, so there's nothing it would protect us from. */
c401cc
+    if (!(fd = glfs_open(state->vol, name, O_RDONLY | O_NOCTTY))) {
c401cc
+        /* A dangling symlink now implies a TOCTTOU race; report it.  */
c401cc
+        virReportSystemError(errno, _("cannot open volume '%s'"), name);
c401cc
+        goto cleanup;
c401cc
+    }
c401cc
+
c401cc
+    if ((len = virStorageBackendGlusterReadHeader(fd, name, len, &header)) < 0)
c401cc
+        goto cleanup;
c401cc
+
c401cc
+    if ((vol->target.format = virStorageFileProbeFormatFromBuf(name,
c401cc
+                                                               header,
c401cc
+                                                               len)) < 0)
c401cc
+        goto clenaup;
c401cc
+    if (!(meta = virStorageFileGetMetadataFromBuf(name, header, len,
c401cc
+                                                  vol->target.format)))
c401cc
+        goto cleanup;
c401cc
+
c401cc
+    if (meta->backingStore) {
c401cc
+        vol->backingStore.path = meta->backingStore;
c401cc
+        meta->backingStore = NULL;
c401cc
+        vol->backingStore.format = meta->backingStoreFormat;
c401cc
+        if (vol->backingStore.format < 0)
c401cc
+            vol->backingStore.format = VIR_STORAGE_FILE_RAW;
c401cc
+    }
c401cc
+    if (meta->capacity)
c401cc
+        vol->capacity = meta->capacity;
c401cc
+    if (meta->encrypted) {
c401cc
+        if (VIR_ALLOC(vol->target.encryption) < 0)
c401cc
+            goto cleanup;
c401cc
+        if (vol->target.format == VIR_STORAGE_FILE_QCOW ||
c401cc
+            vol->target.format == VIR_STORAGE_FILE_QCOW2)
c401cc
+            vol->target.encryption->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW;
c401cc
+    }
c401cc
+    vol->target.features = meta->features;
c401cc
+    meta->features = NULL;
c401cc
+    vol->target.compat = meta->compat;
c401cc
+    meta->compat = NULL;
c401cc
 
c401cc
     *volptr = vol;
c401cc
     vol = NULL;
c401cc
     ret = 0;
c401cc
 cleanup:
c401cc
+    virStorageFileFreeMetadata(meta);
c401cc
     virStorageVolDefFree(vol);
c401cc
+    if (fd)
c401cc
+        glfs_close(fd);
c401cc
+    VIR_FREE(header);
c401cc
     return ret;
c401cc
 }
c401cc
 
c401cc
-- 
c401cc
1.9.0
c401cc