Add APIs that will allow to use the storage driver to assist in operations on files even for remote filesystems without native representation as files in the host. --- Notes: Version 6: - rewrite due to change of exporting approach Version 5: - adapt to error reporting change src/storage/storage_backend.c | 37 +++++++++++ src/storage/storage_backend.h | 41 ++++++++++++ src/storage/storage_driver.c | 145 ++++++++++++++++++++++++++++++++++++++++++ src/storage/storage_driver.h | 32 +++++++++- tests/Makefile.am | 3 + 5 files changed, 257 insertions(+), 1 deletion(-) diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index 19fb1f0..b59b5b7 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -121,6 +121,12 @@ static virStorageBackendPtr backends[] = { NULL }; + +static virStorageFileBackendPtr fileBackends[] = { + NULL +}; + + enum { TOOL_QEMU_IMG, TOOL_KVM_IMG, @@ -1152,6 +1158,37 @@ virStorageBackendForType(int type) } +virStorageFileBackendPtr +virStorageFileBackendForType(int type, + int protocol) +{ + size_t i; + + for (i = 0; fileBackends[i]; i++) { + if (fileBackends[i]->type == type) { + if (type == VIR_DOMAIN_DISK_TYPE_NETWORK && + fileBackends[i]->protocol != protocol) + continue; + + return fileBackends[i]; + } + } + + if (type == VIR_DOMAIN_DISK_TYPE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing storage backend for network files " + "using %s protocol"), + virDomainDiskProtocolTypeToString(protocol)); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing storage backend for '%s' storage"), + virDomainDiskTypeToString(type)); + } + + return NULL; +} + + /* * Allows caller to silently ignore files with improper mode * diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h index 378bc4d..1c7ad1e 100644 --- a/src/storage/storage_backend.h +++ b/src/storage/storage_backend.h @@ -29,6 +29,7 @@ # include "internal.h" # include "storage_conf.h" # include "vircommand.h" +# include "storage_driver.h" typedef char * (*virStorageBackendFindPoolSources)(virConnectPtr conn, const char *srcSpec, @@ -189,4 +190,44 @@ virStorageBackendCreateQemuImgCmd(virConnectPtr conn, const char *create_tool, int imgformat); +/* ------- virStorageFile backends ------------ */ +typedef int +(*virStorageFileBackendInit)(virStorageFilePtr file); + +typedef void +(*virStorageFileBackendDeinit)(virStorageFilePtr file); + +typedef int +(*virStorageFileBackendCreate)(virStorageFilePtr file); + +typedef int +(*virStorageFileBackendUnlink)(virStorageFilePtr file); + +typedef int +(*virStorageFileBackendStat)(virStorageFilePtr file, + struct stat *st); + +typedef struct _virStorageFileBackend virStorageFileBackend; +typedef virStorageFileBackend *virStorageFileBackendPtr; + +virStorageFileBackendPtr virStorageFileBackendForType(int type, int protocol); + +struct _virStorageFileBackend { + int type; + int protocol; + + /* All storage file callbacks may be omitted if not implemented */ + + /* The following group of callbacks is expected to set a libvirt + * error on failure. */ + virStorageFileBackendInit backendInit; + virStorageFileBackendDeinit backendDeinit; + + /* The following group of callbacks is expected to set errno + * and return -1 on error. No libvirt error shall be reported */ + virStorageFileBackendCreate storageFileCreate; + virStorageFileBackendUnlink storageFileUnlink; + virStorageFileBackendStat storageFileStat; +}; + #endif /* __VIR_STORAGE_BACKEND_H__ */ diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 2f7b2e5..64451c5 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -2589,6 +2589,7 @@ cleanup: return ret; } + static virStorageDriver storageDriver = { .name = "storage", .storageOpen = storageOpen, /* 0.4.0 */ @@ -2653,3 +2654,147 @@ int storageRegister(void) virRegisterStateDriver(&stateDriver); return 0; } + + +/* ----------- file handlers cooperating with storage driver --------------- */ +void +virStorageFileFree(virStorageFilePtr file) +{ + if (!file) + return; + + if (file->backend && + file->backend->backendDeinit) + file->backend->backendDeinit(file); + + VIR_FREE(file->path); + virDomainDiskHostDefFree(file->nhosts, file->hosts); + VIR_FREE(file); +} + + +static virStorageFilePtr +virStorageFileInitInternal(int type, + const char *path, + int protocol, + size_t nhosts, + virDomainDiskHostDefPtr hosts) +{ + virStorageFilePtr file = NULL; + + if (VIR_ALLOC(file) < 0) + return NULL; + + file->type = type; + file->protocol = protocol; + file->nhosts = nhosts; + + if (VIR_STRDUP(file->path, path) < 0) + goto error; + + if (!(file->hosts = virDomainDiskHostDefCopy(nhosts, hosts))) + goto error; + + if (!(file->backend = virStorageFileBackendForType(file->type, + file->protocol))) + goto error; + + if (file->backend->backendInit && + file->backend->backendInit(file) < 0) + goto error; + + return file; + +error: + VIR_FREE(file->path); + virDomainDiskHostDefFree(file->nhosts, file->hosts); + VIR_FREE(file); + return NULL; +} + + +virStorageFilePtr +virStorageFileInitFromDiskDef(virDomainDiskDefPtr disk) +{ + return virStorageFileInitInternal(virDomainDiskGetActualType(disk), + disk->src, + disk->protocol, + disk->nhosts, + disk->hosts); +} + + +virStorageFilePtr +virStorageFileInitFromSnapshotDef(virDomainSnapshotDiskDefPtr disk) +{ + return virStorageFileInitInternal(virDomainSnapshotDiskGetActualType(disk), + disk->file, + disk->protocol, + disk->nhosts, + disk->hosts); +} + + + +/** + * virStorageFileCreate: Creates an empty storage file via storage driver + * + * @file: file structure pointing to the file + * + * Returns 0 on success, -2 if the function isn't supported by the backend, + * -1 on other failure. Errno is set in case of failure. + */ +int +virStorageFileCreate(virStorageFilePtr file) +{ + if (!file->backend->storageFileCreate) { + errno = ENOSYS; + return -2; + } + + return file->backend->storageFileCreate(file); +} + + +/** + * virStorageFileUnlink: Unlink storage file via storage driver + * + * @file: file structure pointing to the file + * + * Unlinks the file described by the @file structure. + * + * Returns 0 on success, -2 if the function isn't supported by the backend, + * -1 on other failure. Errno is set in case of failure. + */ +int +virStorageFileUnlink(virStorageFilePtr file) +{ + if (!file->backend->storageFileUnlink) { + errno = ENOSYS; + return -2; + } + + return file->backend->storageFileUnlink(file); +} + + +/** + * virStorageFileStat: returns stat struct of a file via storage driver + * + * @file: file structure pointing to the file + * @stat: stat structure to return data + * + * Returns 0 on success, -2 if the function isn't supported by the backend, + * -1 on other failure. Errno is set in case of failure. +*/ +int +virStorageFileStat(virStorageFilePtr file, + struct stat *st) +{ + if (!(file->backend->storageFileStat)) { + errno = ENOSYS; + return -2; + } + + return file->backend->storageFileStat(file, st); +} diff --git a/src/storage/storage_driver.h b/src/storage/storage_driver.h index 8ccfd75..993bba5 100644 --- a/src/storage/storage_driver.h +++ b/src/storage/storage_driver.h @@ -1,7 +1,7 @@ /* * storage_driver.h: core driver for storage APIs * - * Copyright (C) 2006-2008 Red Hat, Inc. + * Copyright (C) 2006-2008, 2014 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -25,6 +25,36 @@ # define __VIR_STORAGE_DRIVER_H__ # include "storage_conf.h" +# include "conf/domain_conf.h" +# include "conf/snapshot_conf.h" + +typedef struct _virStorageFileBackend virStorageFileBackend; +typedef virStorageFileBackend *virStorageFileBackendPtr; + +typedef struct _virStorageFile virStorageFile; +typedef virStorageFile *virStorageFilePtr; +struct _virStorageFile { + virStorageFileBackendPtr backend; + void *priv; + + char *path; + int type; + int protocol; + + size_t nhosts; + virDomainDiskHostDefPtr hosts; +}; + +virStorageFilePtr +virStorageFileInitFromDiskDef(virDomainDiskDefPtr disk); +virStorageFilePtr +virStorageFileInitFromSnapshotDef(virDomainSnapshotDiskDefPtr disk); +void virStorageFileFree(virStorageFilePtr file); + +int virStorageFileCreate(virStorageFilePtr file); +int virStorageFileUnlink(virStorageFilePtr file); +int virStorageFileStat(virStorageFilePtr file, + struct stat *stat); int storageRegister(void); diff --git a/tests/Makefile.am b/tests/Makefile.am index 62a19cb..0718a69 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -433,6 +433,9 @@ qemu_LDADDS = ../src/libvirt_driver_qemu_impl.la if WITH_NETWORK qemu_LDADDS += ../src/libvirt_driver_network_impl.la endif WITH_NETWORK +if WITH_STORAGE +qemu_LDADDS += ../src/libvirt_driver_storage_impl.la +endif WITH_STORAGE if WITH_DTRACE_PROBES qemu_LDADDS += ../src/libvirt_qemu_probes.lo endif WITH_DTRACE_PROBES -- 1.8.5.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list