Add storage driver based functions to access headers of storage files for metadata extraction. Along with this patch a local filesystem and gluster via libgfapi implementation is provided. The gluster implementation is based on code of the saferead_lim function. --- src/storage/storage_backend.h | 7 ++++ src/storage/storage_backend_fs.c | 30 ++++++++++++++++ src/storage/storage_backend_gluster.c | 66 +++++++++++++++++++++++++++++++++++ src/storage/storage_driver.c | 40 +++++++++++++++++++++ src/storage/storage_driver.h | 3 ++ 5 files changed, 146 insertions(+) diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h index fcbb6da..6be5ca7 100644 --- a/src/storage/storage_backend.h +++ b/src/storage/storage_backend.h @@ -190,6 +190,12 @@ typedef int (*virStorageFileBackendStat)(virStorageSourcePtr src, struct stat *st); +typedef ssize_t +(*virStorageFileBackendReadHeader)(virStorageSourcePtr src, + ssize_t max_len, + char **buf); + + virStorageFileBackendPtr virStorageFileBackendForType(int type, int protocol); @@ -204,6 +210,7 @@ struct _virStorageFileBackend { * error on failure. */ virStorageFileBackendInit backendInit; virStorageFileBackendDeinit backendDeinit; + virStorageFileBackendReadHeader storageFileReadHeader; /* The following group of callbacks is expected to set errno * and return -1 on error. No libvirt error shall be reported */ diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index 3d088ba..33551e7 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -1375,6 +1375,34 @@ virStorageFileBackendFileStat(virStorageSourcePtr src, } +static ssize_t +virStorageFileBackendFileReadHeader(virStorageSourcePtr src, + ssize_t max_len, + char **buf) +{ + int fd = -1; + ssize_t ret = -1; + + if ((fd = virFileOpenAs(src->path, O_RDONLY, 0, + src->drv->uid, src->drv->gid, 0)) < 0) { + virReportSystemError(-fd, _("Failed to open file '%s'"), + src->path); + return -1; + } + + if ((ret = virFileReadHeaderFD(fd, max_len, buf)) < 0) { + virReportSystemError(errno, + _("cannot read header '%s'"), src->path); + goto cleanup; + } + + cleanup: + VIR_FORCE_CLOSE(fd); + + return ret; +} + + virStorageFileBackend virStorageFileBackendFile = { .type = VIR_STORAGE_TYPE_FILE, @@ -1383,6 +1411,7 @@ virStorageFileBackend virStorageFileBackendFile = { .storageFileUnlink = virStorageFileBackendFileUnlink, .storageFileStat = virStorageFileBackendFileStat, + .storageFileReadHeader = virStorageFileBackendFileReadHeader, }; @@ -1393,6 +1422,7 @@ virStorageFileBackend virStorageFileBackendBlock = { .backendDeinit = virStorageFileBackendFileDeinit, .storageFileStat = virStorageFileBackendFileStat, + .storageFileReadHeader = virStorageFileBackendFileReadHeader, }; diff --git a/src/storage/storage_backend_gluster.c b/src/storage/storage_backend_gluster.c index e578e73..badffae 100644 --- a/src/storage/storage_backend_gluster.c +++ b/src/storage/storage_backend_gluster.c @@ -638,6 +638,71 @@ virStorageFileBackendGlusterStat(virStorageSourcePtr src, } +static ssize_t +virStorageFileBackendGlusterReadHeader(virStorageSourcePtr src, + ssize_t max_len, + char **buf) +{ + virStorageFileBackendGlusterPrivPtr priv = src->drv->priv; + glfs_fd_t *fd = NULL; + size_t alloc = 0; + size_t size = 0; + int save_errno; + ssize_t ret = -1; + + *buf = NULL; + + if (!(fd = glfs_open(priv->vol, src->path, O_RDONLY))) { + virReportSystemError(errno, _("Failed to open file '%s'"), + src->path); + goto cleanup; + } + + /* code below is shamelesly stolen from saferead_lim */ + for (;;) { + int count; + int requested; + + if (size + BUFSIZ + 1 > alloc) { + alloc += alloc / 2; + if (alloc < size + BUFSIZ + 1) + alloc = size + BUFSIZ + 1; + + if (VIR_REALLOC_N(*buf, alloc) < 0) { + save_errno = errno; + break; + } + } + + /* Ensure that (size + requested <= max_len); */ + requested = MIN(size < max_len ? max_len - size : 0, + alloc - size - 1); + count = glfs_read(fd, *buf + size, requested, 0); + size += count; + + if (count != requested || requested == 0) { + save_errno = errno; + if (count < 0) { + virReportSystemError(errno, + _("cannot read header '%s'"), src->path); + break; + } + ret = size; + goto cleanup; + } + } + + VIR_FREE(*buf); + errno = save_errno; + + cleanup: + if (fd) + glfs_close(fd); + + return ret; +} + + virStorageFileBackend virStorageFileBackendGluster = { .type = VIR_STORAGE_TYPE_NETWORK, .protocol = VIR_STORAGE_NET_PROTOCOL_GLUSTER, @@ -647,4 +712,5 @@ virStorageFileBackend virStorageFileBackendGluster = { .storageFileUnlink = virStorageFileBackendGlusterUnlink, .storageFileStat = virStorageFileBackendGlusterStat, + .storageFileReadHeader = virStorageFileBackendGlusterReadHeader, }; diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 5e740f9..3019531 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -2947,3 +2947,43 @@ virStorageFileStat(virStorageSourcePtr src, return ret; } + + +/** + * virStorageFileReadHeader: read the beginning bytes of a file into a buffer + * + * @src: file structure pointing to the file + * @max_len: maximum number of bytes read from the storage file + * @buf: buffer to read the data into. buffer shall be freed by caller) + * + * Returns the count of bytes read on success and -1 on failure, -2 if the + * function isn't supported by the backend. Libvirt error is reported on failure. + */ +ssize_t +virStorageFileReadHeader(virStorageSourcePtr src, + ssize_t max_len, + char **buf) +{ + ssize_t ret; + + if (!virStorageFileIsInitialized(src)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("storage file backend not initialized")); + return -1; + } + + if (!src->drv->backend->storageFileReadHeader) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("storage file header reading is not supported for " + "storage type %s (protocol: %s)'"), + virStorageTypeToString(src->type), + virStorageNetProtocolTypeToString(src->protocol)); + return -1; + } + + ret = src->drv->backend->storageFileReadHeader(src, max_len, buf); + + VIR_DEBUG("read of storage header %p: ret=%zd", src, ret); + + return ret; +} diff --git a/src/storage/storage_driver.h b/src/storage/storage_driver.h index 49be999..d67d74b 100644 --- a/src/storage/storage_driver.h +++ b/src/storage/storage_driver.h @@ -38,6 +38,9 @@ int virStorageFileCreate(virStorageSourcePtr src); int virStorageFileUnlink(virStorageSourcePtr src); int virStorageFileStat(virStorageSourcePtr src, struct stat *stat); +ssize_t virStorageFileReadHeader(virStorageSourcePtr src, + ssize_t max_len, + char **buf); int storageRegister(void); -- 1.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list