c401cc
From 85f4948dd875586b7fa36370d74f0eee828d8322 Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <85f4948dd875586b7fa36370d74f0eee828d8322@dist-git>
c401cc
From: Peter Krempa <pkrempa@redhat.com>
c401cc
Date: Wed, 26 Feb 2014 14:55:25 +0100
c401cc
Subject: [PATCH] storage: Add file storage APIs in the default storage driver
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1032370
c401cc
c401cc
Add APIs that will allow to use the storage driver to assist in
c401cc
operations on files even for remote filesystems without native
c401cc
representation as files in the host.
c401cc
c401cc
(cherry picked from commit e32268184b4fd1611ed5ffd3c758b8f6a34152e6)
c401cc
c401cc
Conflicts:
c401cc
	tests/Makefile.am - minor context conflict
c401cc
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/storage/storage_backend.c |  37 +++++++++++
c401cc
 src/storage/storage_backend.h |  41 ++++++++++++
c401cc
 src/storage/storage_driver.c  | 145 ++++++++++++++++++++++++++++++++++++++++++
c401cc
 src/storage/storage_driver.h  |  32 +++++++++-
c401cc
 tests/Makefile.am             |   3 +
c401cc
 5 files changed, 257 insertions(+), 1 deletion(-)
c401cc
c401cc
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
c401cc
index 17168a7..aa620f7 100644
c401cc
--- a/src/storage/storage_backend.c
c401cc
+++ b/src/storage/storage_backend.c
c401cc
@@ -121,6 +121,12 @@ static virStorageBackendPtr backends[] = {
c401cc
     NULL
c401cc
 };
c401cc
 
c401cc
+
c401cc
+static virStorageFileBackendPtr fileBackends[] = {
c401cc
+    NULL
c401cc
+};
c401cc
+
c401cc
+
c401cc
 enum {
c401cc
     TOOL_QEMU_IMG,
c401cc
     TOOL_KVM_IMG,
c401cc
@@ -1123,6 +1129,37 @@ virStorageBackendForType(int type)
c401cc
 }
c401cc
 
c401cc
 
c401cc
+virStorageFileBackendPtr
c401cc
+virStorageFileBackendForType(int type,
c401cc
+                             int protocol)
c401cc
+{
c401cc
+    size_t i;
c401cc
+
c401cc
+    for (i = 0; fileBackends[i]; i++) {
c401cc
+        if (fileBackends[i]->type == type) {
c401cc
+            if (type == VIR_DOMAIN_DISK_TYPE_NETWORK &&
c401cc
+                fileBackends[i]->protocol != protocol)
c401cc
+                continue;
c401cc
+
c401cc
+            return fileBackends[i];
c401cc
+        }
c401cc
+    }
c401cc
+
c401cc
+    if (type == VIR_DOMAIN_DISK_TYPE_NETWORK) {
c401cc
+        virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
+                       _("missing storage backend for network files "
c401cc
+                         "using %s protocol"),
c401cc
+                       virDomainDiskProtocolTypeToString(protocol));
c401cc
+    } else {
c401cc
+        virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
+                       _("missing storage backend for '%s' storage"),
c401cc
+                       virDomainDiskTypeToString(type));
c401cc
+    }
c401cc
+
c401cc
+    return NULL;
c401cc
+}
c401cc
+
c401cc
+
c401cc
 /*
c401cc
  * Allows caller to silently ignore files with improper mode
c401cc
  *
c401cc
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
c401cc
index 378bc4d..1c7ad1e 100644
c401cc
--- a/src/storage/storage_backend.h
c401cc
+++ b/src/storage/storage_backend.h
c401cc
@@ -29,6 +29,7 @@
c401cc
 # include "internal.h"
c401cc
 # include "storage_conf.h"
c401cc
 # include "vircommand.h"
c401cc
+# include "storage_driver.h"
c401cc
 
c401cc
 typedef char * (*virStorageBackendFindPoolSources)(virConnectPtr conn,
c401cc
                                                    const char *srcSpec,
c401cc
@@ -189,4 +190,44 @@ virStorageBackendCreateQemuImgCmd(virConnectPtr conn,
c401cc
                                   const char *create_tool,
c401cc
                                   int imgformat);
c401cc
 
c401cc
+/* ------- virStorageFile backends ------------ */
c401cc
+typedef int
c401cc
+(*virStorageFileBackendInit)(virStorageFilePtr file);
c401cc
+
c401cc
+typedef void
c401cc
+(*virStorageFileBackendDeinit)(virStorageFilePtr file);
c401cc
+
c401cc
+typedef int
c401cc
+(*virStorageFileBackendCreate)(virStorageFilePtr file);
c401cc
+
c401cc
+typedef int
c401cc
+(*virStorageFileBackendUnlink)(virStorageFilePtr file);
c401cc
+
c401cc
+typedef int
c401cc
+(*virStorageFileBackendStat)(virStorageFilePtr file,
c401cc
+                             struct stat *st);
c401cc
+
c401cc
+typedef struct _virStorageFileBackend virStorageFileBackend;
c401cc
+typedef virStorageFileBackend *virStorageFileBackendPtr;
c401cc
+
c401cc
+virStorageFileBackendPtr virStorageFileBackendForType(int type, int protocol);
c401cc
+
c401cc
+struct _virStorageFileBackend {
c401cc
+    int type;
c401cc
+    int protocol;
c401cc
+
c401cc
+    /* All storage file callbacks may be omitted if not implemented */
c401cc
+
c401cc
+    /* The following group of callbacks is expected to set a libvirt
c401cc
+     * error on failure. */
c401cc
+    virStorageFileBackendInit backendInit;
c401cc
+    virStorageFileBackendDeinit backendDeinit;
c401cc
+
c401cc
+    /* The following group of callbacks is expected to set errno
c401cc
+     * and return -1 on error. No libvirt error shall be reported */
c401cc
+    virStorageFileBackendCreate storageFileCreate;
c401cc
+    virStorageFileBackendUnlink storageFileUnlink;
c401cc
+    virStorageFileBackendStat   storageFileStat;
c401cc
+};
c401cc
+
c401cc
 #endif /* __VIR_STORAGE_BACKEND_H__ */
c401cc
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
c401cc
index 2eb751d..4e8c8ca 100644
c401cc
--- a/src/storage/storage_driver.c
c401cc
+++ b/src/storage/storage_driver.c
c401cc
@@ -2568,6 +2568,7 @@ cleanup:
c401cc
     return ret;
c401cc
 }
c401cc
 
c401cc
+
c401cc
 static virStorageDriver storageDriver = {
c401cc
     .name = "storage",
c401cc
     .storageOpen = storageOpen, /* 0.4.0 */
c401cc
@@ -2630,3 +2631,147 @@ int storageRegister(void) {
c401cc
     virRegisterStateDriver(&stateDriver);
c401cc
     return 0;
c401cc
 }
c401cc
+
c401cc
+
c401cc
+/* ----------- file handlers cooperating with storage driver --------------- */
c401cc
+void
c401cc
+virStorageFileFree(virStorageFilePtr file)
c401cc
+{
c401cc
+    if (!file)
c401cc
+        return;
c401cc
+
c401cc
+    if (file->backend &&
c401cc
+        file->backend->backendDeinit)
c401cc
+        file->backend->backendDeinit(file);
c401cc
+
c401cc
+    VIR_FREE(file->path);
c401cc
+    virDomainDiskHostDefFree(file->nhosts, file->hosts);
c401cc
+    VIR_FREE(file);
c401cc
+}
c401cc
+
c401cc
+
c401cc
+static virStorageFilePtr
c401cc
+virStorageFileInitInternal(int type,
c401cc
+                           const char *path,
c401cc
+                           int protocol,
c401cc
+                           size_t nhosts,
c401cc
+                           virDomainDiskHostDefPtr hosts)
c401cc
+{
c401cc
+    virStorageFilePtr file = NULL;
c401cc
+
c401cc
+    if (VIR_ALLOC(file) < 0)
c401cc
+        return NULL;
c401cc
+
c401cc
+    file->type = type;
c401cc
+    file->protocol = protocol;
c401cc
+    file->nhosts = nhosts;
c401cc
+
c401cc
+    if (VIR_STRDUP(file->path, path) < 0)
c401cc
+        goto error;
c401cc
+
c401cc
+    if (!(file->hosts = virDomainDiskHostDefCopy(nhosts, hosts)))
c401cc
+        goto error;
c401cc
+
c401cc
+    if (!(file->backend = virStorageFileBackendForType(file->type,
c401cc
+                                                       file->protocol)))
c401cc
+        goto error;
c401cc
+
c401cc
+    if (file->backend->backendInit &&
c401cc
+        file->backend->backendInit(file) < 0)
c401cc
+        goto error;
c401cc
+
c401cc
+    return file;
c401cc
+
c401cc
+error:
c401cc
+    VIR_FREE(file->path);
c401cc
+    virDomainDiskHostDefFree(file->nhosts, file->hosts);
c401cc
+    VIR_FREE(file);
c401cc
+    return NULL;
c401cc
+}
c401cc
+
c401cc
+
c401cc
+virStorageFilePtr
c401cc
+virStorageFileInitFromDiskDef(virDomainDiskDefPtr disk)
c401cc
+{
c401cc
+    return virStorageFileInitInternal(virDomainDiskGetActualType(disk),
c401cc
+                                      disk->src,
c401cc
+                                      disk->protocol,
c401cc
+                                      disk->nhosts,
c401cc
+                                      disk->hosts);
c401cc
+}
c401cc
+
c401cc
+
c401cc
+virStorageFilePtr
c401cc
+virStorageFileInitFromSnapshotDef(virDomainSnapshotDiskDefPtr disk)
c401cc
+{
c401cc
+    return virStorageFileInitInternal(virDomainSnapshotDiskGetActualType(disk),
c401cc
+                                      disk->file,
c401cc
+                                      disk->protocol,
c401cc
+                                      disk->nhosts,
c401cc
+                                      disk->hosts);
c401cc
+}
c401cc
+
c401cc
+
c401cc
+
c401cc
+/**
c401cc
+ * virStorageFileCreate: Creates an empty storage file via storage driver
c401cc
+ *
c401cc
+ * @file: file structure pointing to the file
c401cc
+ *
c401cc
+ * Returns 0 on success, -2 if the function isn't supported by the backend,
c401cc
+ * -1 on other failure. Errno is set in case of failure.
c401cc
+ */
c401cc
+int
c401cc
+virStorageFileCreate(virStorageFilePtr file)
c401cc
+{
c401cc
+    if (!file->backend->storageFileCreate) {
c401cc
+        errno = ENOSYS;
c401cc
+        return -2;
c401cc
+    }
c401cc
+
c401cc
+    return file->backend->storageFileCreate(file);
c401cc
+}
c401cc
+
c401cc
+
c401cc
+/**
c401cc
+ * virStorageFileUnlink: Unlink storage file via storage driver
c401cc
+ *
c401cc
+ * @file: file structure pointing to the file
c401cc
+ *
c401cc
+ * Unlinks the file described by the @file structure.
c401cc
+ *
c401cc
+ * Returns 0 on success, -2 if the function isn't supported by the backend,
c401cc
+ * -1 on other failure. Errno is set in case of failure.
c401cc
+ */
c401cc
+int
c401cc
+virStorageFileUnlink(virStorageFilePtr file)
c401cc
+{
c401cc
+    if (!file->backend->storageFileUnlink) {
c401cc
+        errno = ENOSYS;
c401cc
+        return -2;
c401cc
+    }
c401cc
+
c401cc
+    return file->backend->storageFileUnlink(file);
c401cc
+}
c401cc
+
c401cc
+
c401cc
+/**
c401cc
+ * virStorageFileStat: returns stat struct of a file via storage driver
c401cc
+ *
c401cc
+ * @file: file structure pointing to the file
c401cc
+ * @stat: stat structure to return data
c401cc
+ *
c401cc
+ * Returns 0 on success, -2 if the function isn't supported by the backend,
c401cc
+ * -1 on other failure. Errno is set in case of failure.
c401cc
+*/
c401cc
+int
c401cc
+virStorageFileStat(virStorageFilePtr file,
c401cc
+                   struct stat *st)
c401cc
+{
c401cc
+    if (!(file->backend->storageFileStat)) {
c401cc
+        errno = ENOSYS;
c401cc
+        return -2;
c401cc
+    }
c401cc
+
c401cc
+    return file->backend->storageFileStat(file, st);
c401cc
+}
c401cc
diff --git a/src/storage/storage_driver.h b/src/storage/storage_driver.h
c401cc
index 8ccfd75..993bba5 100644
c401cc
--- a/src/storage/storage_driver.h
c401cc
+++ b/src/storage/storage_driver.h
c401cc
@@ -1,7 +1,7 @@
c401cc
 /*
c401cc
  * storage_driver.h: core driver for storage APIs
c401cc
  *
c401cc
- * Copyright (C) 2006-2008 Red Hat, Inc.
c401cc
+ * Copyright (C) 2006-2008, 2014 Red Hat, Inc.
c401cc
  * Copyright (C) 2006-2008 Daniel P. Berrange
c401cc
  *
c401cc
  * This library is free software; you can redistribute it and/or
c401cc
@@ -25,6 +25,36 @@
c401cc
 # define __VIR_STORAGE_DRIVER_H__
c401cc
 
c401cc
 # include "storage_conf.h"
c401cc
+# include "conf/domain_conf.h"
c401cc
+# include "conf/snapshot_conf.h"
c401cc
+
c401cc
+typedef struct _virStorageFileBackend virStorageFileBackend;
c401cc
+typedef virStorageFileBackend *virStorageFileBackendPtr;
c401cc
+
c401cc
+typedef struct _virStorageFile virStorageFile;
c401cc
+typedef virStorageFile *virStorageFilePtr;
c401cc
+struct _virStorageFile {
c401cc
+    virStorageFileBackendPtr backend;
c401cc
+    void *priv;
c401cc
+
c401cc
+    char *path;
c401cc
+    int type;
c401cc
+    int protocol;
c401cc
+
c401cc
+    size_t nhosts;
c401cc
+    virDomainDiskHostDefPtr hosts;
c401cc
+};
c401cc
+
c401cc
+virStorageFilePtr
c401cc
+virStorageFileInitFromDiskDef(virDomainDiskDefPtr disk);
c401cc
+virStorageFilePtr
c401cc
+virStorageFileInitFromSnapshotDef(virDomainSnapshotDiskDefPtr disk);
c401cc
+void virStorageFileFree(virStorageFilePtr file);
c401cc
+
c401cc
+int virStorageFileCreate(virStorageFilePtr file);
c401cc
+int virStorageFileUnlink(virStorageFilePtr file);
c401cc
+int virStorageFileStat(virStorageFilePtr file,
c401cc
+                       struct stat *stat);
c401cc
 
c401cc
 int storageRegister(void);
c401cc
 
c401cc
diff --git a/tests/Makefile.am b/tests/Makefile.am
c401cc
index 88b2224..e49eadc 100644
c401cc
--- a/tests/Makefile.am
c401cc
+++ b/tests/Makefile.am
c401cc
@@ -394,6 +394,9 @@ qemu_LDADDS = ../src/libvirt_driver_qemu_impl.la
c401cc
 if WITH_NETWORK
c401cc
 qemu_LDADDS += ../src/libvirt_driver_network_impl.la
c401cc
 endif
c401cc
+if WITH_STORAGE
c401cc
+qemu_LDADDS += ../src/libvirt_driver_storage_impl.la
c401cc
+endif WITH_STORAGE
c401cc
 if WITH_DTRACE_PROBES
c401cc
 qemu_LDADDS += ../src/libvirt_qemu_probes.lo
c401cc
 endif
c401cc
-- 
c401cc
1.9.0
c401cc