File libvirt-qemu-add-helper-functions-for-diskchain-checking.patch of Package libvirt

From 310c92635a8f7973dd5574e7acd0667616a87f0d Mon Sep 17 00:00:00 2001
Message-Id: <310c92635a8f7973dd5574e7acd0667616a87f0d@dist-git>
From: Guannan Ren <gren@redhat.com>
Date: Fri, 11 Apr 2014 16:34:00 +0200
Subject: [PATCH] qemu: add helper functions for diskchain checking

*src/util/virstoragefile.c: Add a helper function to get
the first name of missing backing files, if the name is NULL,
it means the diskchain is not broken.
*src/qemu/qemu_domain.c: qemuDiskChainCheckBroken(disk) to
check if its chain is broken

(cherry picked from commit d7b7aa2c206951bef3b1bfece656394d1775cb7d)

(https://bugzilla.redhat.com/show_bug.cgi?id=1014730)

Conflicts:
	src/libvirt_private.syms
	src/qemu/qemu_domain.c
	src/qemu/qemu_domain.h

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 src/libvirt_private.syms |  1 +
 src/qemu/qemu_domain.c   | 22 ++++++++++++++++++++++
 src/qemu/qemu_domain.h   |  3 +++
 src/util/storage_file.c  | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 src/util/storage_file.h  |  2 ++
 5 files changed, 75 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d742c72..6b58c99 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1177,6 +1177,7 @@ virStorageGenerateQcowPassphrase;
 
 
 # storage_file.h
+virStorageFileChainGetBroken;
 virStorageFileChainLookup;
 virStorageFileFormatTypeFromString;
 virStorageFileFormatTypeToString;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 3b91a71..d942ba0 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2024,6 +2024,28 @@ qemuDomainCleanupRun(struct qemud_driver *driver,
 }
 
 int
+qemuDiskChainCheckBroken(virDomainDiskDefPtr disk)
+{
+    char *brokenFile = NULL;
+
+    if (!disk->src || !disk->backingChain)
+        return 0;
+
+    if (virStorageFileChainGetBroken(disk->backingChain, &brokenFile) < 0)
+        return -1;
+
+    if (brokenFile) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("Backing file '%s' of image '%s' is missing."),
+                       brokenFile, disk->src);
+        VIR_FREE(brokenFile);
+        return -1;
+    }
+
+    return 0;
+}
+
+int
 qemuDomainDetermineDiskChain(struct qemud_driver *driver,
                              virDomainDiskDefPtr disk,
                              bool force)
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index c010a3e..b5c61ac 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -353,6 +353,9 @@ bool qemuDomainJobAllowed(qemuDomainObjPrivatePtr priv,
 int qemuDomainCheckDiskPresence(struct qemud_driver *driver,
                                 virDomainObjPtr vm,
                                 bool start_with_state);
+
+int qemuDiskChainCheckBroken(virDomainDiskDefPtr disk);
+
 int qemuDomainDetermineDiskChain(struct qemud_driver *driver,
                                  virDomainDiskDefPtr disk,
                                  bool force);
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
index 3ff04e1..cda62de 100644
--- a/src/util/storage_file.c
+++ b/src/util/storage_file.c
@@ -523,6 +523,13 @@ virFindBackingFile(const char *start, bool start_is_dir, const char *path,
         goto cleanup;
     }
 
+    if (virFileAccessibleAs(combined, F_OK, getuid(), getgid()) < 0) {
+        virReportSystemError(errno,
+                             _("Cannot access backing file '%s'"),
+                             combined);
+        goto cleanup;
+    }
+
     if (!(*canonical = canonicalize_file_name(combined))) {
         virReportSystemError(errno,
                              _("Can't canonicalize path '%s'"), path);
@@ -1007,6 +1014,46 @@ virStorageFileGetMetadata(const char *path, int format,
 }
 
 /**
+ * virStorageFileChainCheckBroken
+ *
+ * If CHAIN is broken, set *brokenFile to the broken file name,
+ * otherwise set it to NULL. Caller MUST free *brokenFile after use.
+ * Return 0 on success, negative on error.
+ */
+int
+virStorageFileChainGetBroken(virStorageFileMetadataPtr chain,
+                             char **brokenFile)
+{
+    virStorageFileMetadataPtr tmp;
+    int ret = -1;
+
+    if (!chain)
+        return 0;
+
+    *brokenFile = NULL;
+
+    tmp = chain;
+    while (tmp) {
+        /* Break if no backing store or backing store is not file */
+       if (!tmp->backingStoreRaw)
+           break;
+       if (!tmp->backingStore) {
+           if (!(*brokenFile = strdup(tmp->backingStoreRaw))) {
+                virReportOOMError();
+                goto error;
+           }
+           break;
+       }
+       tmp = tmp->backingMeta;
+    }
+
+    ret = 0;
+
+error:
+    return ret;
+}
+
+/**
  * virStorageFileFreeMetadata:
  *
  * Free pointers in passed structure and structure itself.
diff --git a/src/util/storage_file.h b/src/util/storage_file.h
index c3209e5..8d77e3d 100644
--- a/src/util/storage_file.h
+++ b/src/util/storage_file.h
@@ -78,6 +78,8 @@ virStorageFileMetadataPtr virStorageFileGetMetadata(const char *path,
 virStorageFileMetadataPtr virStorageFileGetMetadataFromFD(const char *path,
                                                           int fd,
                                                           int format);
+int virStorageFileChainGetBroken(virStorageFileMetadataPtr chain,
+                                 char **broken_file);
 
 const char *virStorageFileChainLookup(virStorageFileMetadataPtr chain,
                                       const char *start,
-- 
1.9.2

openSUSE Build Service is sponsored by