https://bugzilla.redhat.com/show_bug.cgi?id=1138516 The disk backend uses 'parted' in order to create and delete partitions on the disk for use in the pool. At creation time, one can specify a specific "name" for the volume as well as a specific volume target format type. The name and volume target type "survive" only as long as the pool is not refreshed or the libvirtd not restarted/reloaded. The action immediately prior to the calling all the backend refreshPool API's is to clear out all the existing volumes from the pool. The theory being the refresh will be able to find all elements of the pool using some mechanism. The disk refreshPool backend will use the libvirt_parthelper utility to read the partitions found on the disk in order to regenerate the elements of the pool Unfortunately, since the "name" and target format type cannot be encoded, the data is now lost and the defaults are used (for the "name", the partition path is used and the default of 'none' is used for the target format type). This patch solves this by adding the ability to save the XML generated at create time into the stateDir and then use that during the refreshPool backend API call to restore the specific fields that are lost. Once the partition has been successfully created during the backend call to createVol (virStorageBackendDiskCreateVol) and the various XML fields updated, call the virStorageVolSaveStatus() API in order to save the XML for later use. Conversely, once the partition has been successfully removed during the backend call to deleteVol (virStorageBackendDiskDeleteVol) call the virStorageVolDeleteStatus() API in order to remove the XML file. The virStorageBackendDiskUpdateStatus called after reading the data about the partitions during the refreshPool will scan the pool->stateDir for XML files. For each found and successfully parsed file, look through the recently updated pool's volume list for a volume with the same key. If one is found with a different name than in use for the pool, then use the one from the stateDir and update the target format type and save the updated pool volume. Signed-off-by: John Ferlan <jferlan@xxxxxxxxxx> --- src/storage/storage_backend_disk.c | 90 +++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/src/storage/storage_backend_disk.c b/src/storage/storage_backend_disk.c index 3f97fd9..90b468c 100644 --- a/src/storage/storage_backend_disk.c +++ b/src/storage/storage_backend_disk.c @@ -1,7 +1,7 @@ /* * storage_backend_disk.c: storage backend for disk handling * - * Copyright (C) 2007-2014 Red Hat, Inc. + * Copyright (C) 2007-2015 Red Hat, Inc. * Copyright (C) 2007-2008 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -333,6 +333,78 @@ virStorageBackendDiskReadGeometry(virStoragePoolObjPtr pool) } static int +virStorageBackendDiskUpdateStatus(virStoragePoolObjPtr pool) +{ + DIR *dir; + struct dirent *entry; + virStorageVolDefPtr voldef = NULL, poolvol = NULL; + int ret = -1; + + if (!(dir = opendir(pool->stateDir))) { + if (errno == ENOENT) + return 0; + + virReportSystemError(errno, _("Failed to open dir '%s'"), + pool->stateDir); + return -1; + } + + while ((ret = virDirRead(dir, &entry, pool->stateDir)) > 0) { + char *path; + + if (entry->d_name[0] == '.' || + !virFileHasSuffix(entry->d_name, ".xml")) + continue; + + if (!(path = virFileBuildPath(pool->stateDir, entry->d_name, NULL))) + continue; + + /* Unable to parse */ + voldef = virStorageVolDefParseFile(pool->def, path); + VIR_FREE(path); + if (!voldef) { + ret = -1; + goto cleanup; + } + + /* Search the current storage pool for the key from the file */ + if ((poolvol = virStorageVolDefFindByKey(pool, voldef->key))) { + + /* Swap name if necessary */ + if (STRNEQ(voldef->name, poolvol->name)) { + char *tmp = poolvol->name; + poolvol->name = voldef->name; + voldef->name = tmp; + } + + /* Same for target format type */ + poolvol->target.format = voldef->target.format; + + /* Update the saved file since we could have other changes + * as determined through refresh. + */ + if (virStorageVolSaveStatus(pool, poolvol) < 0) { + virStorageVolDefFree(voldef); + ret = -1; + goto cleanup; + } + } else { + /* If we don't find the key in our current pool, + * then remove stale or transient file + */ + unlink(entry->d_name); + } + + /* Free the voldef (poolvol is just a pointer into poolobj */ + virStorageVolDefFree(voldef); + } + + cleanup: + closedir(dir); + return ret; +} + +static int virStorageBackendDiskRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool) { @@ -351,7 +423,13 @@ virStorageBackendDiskRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED, if (virStorageBackendDiskReadGeometry(pool) != 0) return -1; - return virStorageBackendDiskReadPartitions(pool, NULL); + if (virStorageBackendDiskReadPartitions(pool, NULL) < 0) + return -1; + + if (virStorageBackendDiskUpdateStatus(pool) < 0) + return -1; + + return 0; } @@ -690,6 +768,10 @@ virStorageBackendDiskCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED, if (virStorageBackendDiskReadPartitions(pool, vol) < 0) goto cleanup; + /* Save the XML file in the stateDir for use by reload, restart, refresh */ + if (virStorageVolSaveStatus(pool, vol) < 0) + goto cleanup; + res = 0; cleanup: @@ -775,6 +857,10 @@ virStorageBackendDiskDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED, goto cleanup; } + /* Remove the XML status file from stateDir */ + if (virStorageVolDeleteStatus(pool, vol) < 0) + goto cleanup; + rc = 0; cleanup: VIR_FREE(devpath); -- 2.1.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list