On 11/12/13 05:19, Eric Blake wrote:
Putting together pieces from previous patches, it is now possible
for 'virsh dumpxml --pool gluster volname' to report metadata
Did you mean 'virsh vol-dumpxml --pool ... '?
about a qcow2 file stored on gluster. The backing file is still
treated as raw; to fix that, more patches are needed to make the
storage backing chain analysis recursive rather than halting at
a network protocol name, but that work will not need any further
calls into libgfapi so much as just reusing this code, and that
should be the only code outside of the storage driver that needs
any help from libgfapi. Any additional use of libgfapi within
libvirt should only be needed for implementing storage pool APIs
such as volume creation or resizing, where backing chain analysis
should be unaffected.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterOpen): Make relative name handling easier.
(virStorageBackendGlusterReadHeader): New helper function.
(virStorageBackendGlusterRefreshVol): Probe non-raw files.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
src/storage/storage_backend_gluster.c | 87 +++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
diff --git a/src/storage/storage_backend_gluster.c
b/src/storage/storage_backend_gluster.c
index bc90de9..69e8e61 100644
--- a/src/storage/storage_backend_gluster.c
+++ b/src/storage/storage_backend_gluster.c
...
@@ -124,6 +130,37 @@ error:
}
+static int
This function is declared as an int, but ...
+virStorageBackendGlusterReadHeader(glfs_fd_t *fd,
+ const char *name,
+ int maxlen,
+ char **buf)
+{
+ char *s;
+ size_t nread = 0;
.. returns size_t. This could overflow normally, but is guarded by
maxlen. Okay.
+
+ if (VIR_ALLOC_N(*buf, maxlen) < 0)
+ return -1;
+
+ s = *buf;
+ while (maxlen) {
+ ssize_t r = glfs_read(fd, s, maxlen, 0);
+ if (r < 0 && errno == EINTR)
+ continue;
+ if (r < 0) {
+ VIR_FREE(*buf);
+ virReportSystemError(errno, _("unable to read '%s'"),
name);
+ return r;
+ }
+ if (r == 0)
+ return nread;
+ buf += r;
+ maxlen -= r;
+ nread += r;
+ }
+ return nread;
+}
+
/* Populate *volptr for the given name and stat information, or leave
* it NULL if the entry should be skipped (such as "."). Return 0 on
* success, -1 on failure. */
...
@@ -162,11 +203,57 @@
virStorageBackendGlusterRefreshVol(virStorageBackendGlusterStatePtr state,
}
state->uri->path = tmp;
+ if (!(fd = glfs_open(state->vol, name, O_RDONLY| O_NONBLOCK | O_NOCTTY))) {
+ if ((errno == ENOENT || errno == ELOOP) &&
+ S_ISLNK(st->st_mode)) {
+ VIR_WARN("ignoring dangling symlink '%s'", name);
+ ret = 0;
+ } else {
+ virReportSystemError(errno, _("cannot open volume '%s'"),
name);
+ }
+ goto cleanup;
+ }
Now that you actually open the volume file and probe it, you need to
kill the comment added in previous patch:
+ if (VIR_ALLOC(vol) < 0 ||
+ VIR_STRDUP(vol->name, name) < 0 ||
+ virAsprintf(&vol->key, "%s%s/%s",
+ *pool == '/' ? "" : "/", pool,
vol->name) < 0)
+ goto cleanup;
+
+ /* FIXME - must open files to determine if they are non-raw */
+ vol->type = VIR_STORAGE_VOL_NETWORK;
+ vol->target.format = VIR_STORAGE_FILE_RAW;
+ vol->capacity = vol->allocation = st->st_size;
+ tmp = state->uri->path;
+ state->uri->path = vol->key;
+ if (!(vol->target.path = virURIFormat(state->uri))) {
+ state->uri->path = tmp;
+ goto cleanup;
+
+ if ((len = virStorageBackendGlusterReadHeader(fd, name, len, &header)) < 0)
+ goto cleanup;
+
+ if ((vol->target.format = virStorageFileProbeFormatFromBuf(name,
+ header,
+ len)) < 0 ||
+ !(meta = virStorageFileGetMetadataFromBuf(name, header, len,
+ vol->target.format)))
+ goto cleanup;
Also as you are erroring out in case of failure, you can remove the
lines setting some of the defaults.
+
+ if (meta->backingStore) {
+ vol->backingStore.path = meta->backingStore;
+ meta->backingStore = NULL;
+ vol->backingStore.format = meta->backingStoreFormat;
+ if (vol->backingStore.format < 0)
+ vol->backingStore.format = VIR_STORAGE_FILE_RAW;
+ }
+ if (meta->capacity)
+ vol->capacity = meta->capacity;
+ if (meta->encrypted) {
+ if (VIR_ALLOC(vol->target.encryption) < 0)
+ goto cleanup;
+ if (vol->target.format == VIR_STORAGE_FILE_QCOW ||
+ vol->target.format == VIR_STORAGE_FILE_QCOW2)
+ vol->target.encryption->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW;
+ }
+ vol->target.features = meta->features;
+ meta->features = NULL;
+ vol->target.compat = meta->compat;
+ meta->compat = NULL;
+
*volptr = vol;
vol = NULL;
ret = 0;
cleanup:
+ virStorageFileFreeMetadata(meta);
virStorageVolDefFree(vol);
+ if (fd)
+ glfs_close(fd);
+ VIR_FREE(header);
return ret;
}
ACK with the comment nit fixed.
Peter