>From 494b96317334716f846436a5ec485963411cb4a3 Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Mon, 14 Jun 2010 18:09:15 +0100 Subject: [PATCH 05/10] Add an API for iterating over disk paths There is duplicated code which iterates over disk backing stores performing some action. Provide a convenient helper for doing this to eliminate duplication & risk of mistakes with disk format probing * src/conf/domain_conf.c, src/conf/domain_conf.h, src/libvirt_private.syms: Add virDomainDiskDefForeachPath() --- src/conf/domain_conf.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 11 +++++ src/libvirt_private.syms | 1 + 3 files changed, 111 insertions(+), 0 deletions(-) Index: libvirt-0.8.1/src/conf/domain_conf.c =================================================================== --- libvirt-0.8.1.orig/src/conf/domain_conf.c +++ libvirt-0.8.1/src/conf/domain_conf.c @@ -45,6 +45,7 @@ #include "macvtap.h" #include "nwfilter_conf.h" #include "ignore-value.h" +#include "storage_file.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -6928,4 +6929,102 @@ int virDomainSnapshotHasChildren(virDoma } +int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk, + bool allowProbing, + bool ignoreOpenFailure, + virDomainDiskDefPathIterator iter, + void *opaque) +{ + virHashTablePtr paths; + int format; + int ret = -1; + int depth = 0; + char *nextpath = NULL; + + if (!disk->src) + return 0; + + if (disk->driverType) { + const char *formatStr = disk->driverType; + if (STREQ(formatStr, "aio")) + formatStr = "raw"; /* Xen compat */ + + if ((format = virStorageFileFormatTypeFromString(formatStr)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown disk format '%s' for %s"), + disk->driverType, disk->src); + return -1; + } + } else { + if (allowProbing) { + format = VIR_STORAGE_FILE_AUTO; + } else { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("no disk format for %s and probing is disabled"), + disk->src); + return -1; + } + } + + paths = virHashCreate(5); + + do { + virStorageFileMetadata meta; + const char *path = nextpath ? nextpath : disk->src; + int fd; + + if (iter(disk, path, depth, opaque) < 0) + goto cleanup; + + if (virHashLookup(paths, path)) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("backing store for %s is self-referential"), + disk->src); + goto cleanup; + } + + if ((fd = open(path, O_RDONLY)) < 0) { + if (ignoreOpenFailure) { + char ebuf[1024]; + VIR_WARN("Ignoring open failure on %s: %s", path, + virStrerror(errno, ebuf, sizeof(ebuf))); + break; + } else { + virReportSystemError(errno, + _("unable to open disk path %s"), + path); + goto cleanup; + } + } + + if (virStorageFileGetMetadataFromFD(path, fd, format, &meta) < 0) { + close(fd); + goto cleanup; + } + close(fd); + + if (virHashAddEntry(paths, path, (void*)0x1) < 0) { + virReportOOMError(); + goto cleanup; + } + + depth++; + nextpath = meta.backingStore; + + format = meta.backingStoreFormat; + + if (format == VIR_STORAGE_FILE_AUTO && + !allowProbing) + format = VIR_STORAGE_FILE_RAW; /* Stops further recursion */ + } while (nextpath); + + ret = 0; + +cleanup: + virHashFree(paths, NULL); + VIR_FREE(nextpath); + + return ret; +} + #endif /* ! PROXY */ Index: libvirt-0.8.1/src/conf/domain_conf.h =================================================================== --- libvirt-0.8.1.orig/src/conf/domain_conf.h +++ libvirt-0.8.1/src/conf/domain_conf.h @@ -1057,6 +1057,17 @@ int virDomainObjListGetInactiveNames(vir int maxnames); +typedef int (*virDomainDiskDefPathIterator)(virDomainDiskDefPtr disk, + const char *path, + unsigned int depth, + void *opaque); + +int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk, + bool allowProbing, + bool ignoreOpenFailure, + virDomainDiskDefPathIterator iter, + void *opaque); + VIR_ENUM_DECL(virDomainVirt) VIR_ENUM_DECL(virDomainBoot) VIR_ENUM_DECL(virDomainFeature) Index: libvirt-0.8.1/src/libvirt_private.syms =================================================================== --- libvirt-0.8.1.orig/src/libvirt_private.syms +++ libvirt-0.8.1/src/libvirt_private.syms @@ -223,6 +223,7 @@ virDomainSnapshotObjUnref; virDomainSnapshotDefParseString; virDomainSnapshotDefFormat; virDomainSnapshotAssignDef; +virDomainDiskDefForeachPath; # domain_event.h