From e32268184b4fd1611ed5ffd3c758b8f6a34152e6 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Mon, 3 Feb 2014 16:12:57 +0100 Subject: [PATCH] storage: Add file storage APIs in the default storage driver 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. --- 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 19fb1f05e0..b59b5b7b80 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 378bc4d4bc..1c7ad1e72d 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 2f7b2e559a..64451c572a 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 8ccfd75dd5..993bba5e3c 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 62a19cbfc3..0718a69173 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 -- GitLab