Blob Blame History Raw
From 85f4948dd875586b7fa36370d74f0eee828d8322 Mon Sep 17 00:00:00 2001
Message-Id: <85f4948dd875586b7fa36370d74f0eee828d8322@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 26 Feb 2014 14:55:25 +0100
Subject: [PATCH] storage: Add file storage APIs in the default storage driver

https://bugzilla.redhat.com/show_bug.cgi?id=1032370

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.

(cherry picked from commit e32268184b4fd1611ed5ffd3c758b8f6a34152e6)

Conflicts:
	tests/Makefile.am - minor context conflict

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 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 17168a7..aa620f7 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,
@@ -1123,6 +1129,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 2eb751d..4e8c8ca 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -2568,6 +2568,7 @@ cleanup:
     return ret;
 }
 
+
 static virStorageDriver storageDriver = {
     .name = "storage",
     .storageOpen = storageOpen, /* 0.4.0 */
@@ -2630,3 +2631,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 88b2224..e49eadc 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -394,6 +394,9 @@ qemu_LDADDS = ../src/libvirt_driver_qemu_impl.la
 if WITH_NETWORK
 qemu_LDADDS += ../src/libvirt_driver_network_impl.la
 endif
+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
-- 
1.9.0