Refreshes meta-information such as allocation, capacity, format, etc.
Ploop volumes differ from other volume types. Path to volume is the path
to directory with image file root.hds and DiskDescriptor.xml.
https://openvz.org/Ploop/format
Due to this fact, operations of opening the volume have to be done once
again. get the information.
To decide whether the given volume is ploops one, it is necessary to check
the presence of root.hds and DiskDescriptor.xml files in volumes' directory.
Only in this case the volume can be manipulated as the ploops one.
Such strategy helps us to resolve problems that might occure, when we
upload some other volume type from ploop source.
Signed-off-by: Olga Krishtal <okrishtal(a)virtuozzo.com>
---
src/storage/storage_backend.c | 62 ++++++++++++++++++++++++++++++++++++--
src/storage/storage_backend.h | 5 ++++
src/storage/storage_backend_fs.c | 64 +++++++++++++++++++++++++++++++++++++---
src/util/virstoragefile.c | 7 +++--
4 files changed, 129 insertions(+), 9 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 8b936ae..e159334 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -1702,6 +1702,56 @@ virStorageBackendVolOpen(const char *path, struct stat *sb,
return fd;
}
+/* virStorageIsPloop function checks whether given directory is ploop volume's
+ * directory.
+ */
+bool
+virStorageBackendIsPloopDir(char *path)
+{
+ bool ret = false;
+ char *root = NULL;
+ char *desc = NULL;
+ if (virAsprintf(&root, "%s/root.hds", path) < 0)
+ return ret;
+ if (!virFileExists(root))
+ goto cleanup;
+ if (virAsprintf(&desc, "%s/DiskDescriptor.xml", path) < 0)
+ goto cleanup;
+ if (!virFileExists(desc))
+ goto cleanup;
+
+ ret = true;
+ cleanup:
+ VIR_FREE(root);
+ VIR_FREE(desc);
+ return ret;
+}
+
+/* In case of ploop volumes, path to volume is the path to the ploop
+ * directory. To get information about allocation, header information
+ * and etc. we need to perform virStorageBackendVolOpen and
+ * virStorageBackendUpdateVolTargetFd once again.
+ */
+int
+virStorageBackendRedoPloopUpdate(virStorageSourcePtr target, struct stat *sb,
+ int *fd, unsigned int flags)
+{
+ char *path = NULL;
+ int ret = -1;
+
+ if (virAsprintf(&path, "%s/root.hds", target->path) < 0)
+ return -1;
+ VIR_FORCE_CLOSE(*fd);
+ if ((*fd = virStorageBackendVolOpen(path, sb, flags)) < 0)
+ goto cleanup;
+ ret = virStorageBackendUpdateVolTargetInfoFD(target, *fd, sb);
+
+ cleanup:
+
+ VIR_FREE(path);
+ return ret;
+}
+
/*
* virStorageBackendUpdateVolTargetInfo
* @target: target definition ptr of volume to update
@@ -1709,7 +1759,6 @@ virStorageBackendVolOpen(const char *path, struct stat *sb,
* @openflags: various VolOpenCheckMode flags to handle errors on open
* @readflags: VolReadErrorMode flags to handle read error after open
* is successful, but read is not.
- *
* Returns 0 for success, -1 on a legitimate error condition, and -2
* if the openflags used VIR_STORAGE_VOL_OPEN_NOERROR and some sort of
* open error occurred. It is up to the caller to handle. A -2 may also
@@ -1737,8 +1786,15 @@ virStorageBackendUpdateVolTargetInfo(virStorageSourcePtr target,
if (target->type == VIR_STORAGE_VOL_FILE &&
target->format != VIR_STORAGE_FILE_NONE) {
if (S_ISDIR(sb.st_mode)) {
- ret = 0;
- goto cleanup;
+ if (virStorageBackendIsPloopDir(target->path)) {
+ if ((ret = virStorageBackendRedoPloopUpdate(target, &sb, &fd,
+ openflags)) < 0)
+ goto cleanup;
+ target->format = VIR_STORAGE_FILE_PLOOP;
+ } else {
+ ret = 0;
+ goto cleanup;
+ }
}
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
index 73f2bfa..a1e39c5 100644
--- a/src/storage/storage_backend.h
+++ b/src/storage/storage_backend.h
@@ -118,6 +118,11 @@ int virStorageBackendCreatePloop(virConnectPtr conn,
int virStoragePloopResize(virStorageVolDefPtr vol,
unsigned long long capacity);
+int virStorageBackendRedoPloopUpdate(virStorageSourcePtr target,
+ struct stat *sb, int *fd,
+ unsigned int flags);
+bool virStorageBackendIsPloopDir(char *path);
+
virStorageBackendBuildVolFrom
virStorageBackendGetBuildVolFromFunction(virStorageVolDefPtr vol,
virStorageVolDefPtr inputvol);
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index eae2b2e..53b0572 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -62,6 +62,46 @@ VIR_LOG_INIT("storage.storage_backend_fs");
VIR_STORAGE_VOL_OPEN_NOERROR)
static int
+virStorageBackendPloopRestoreDesc(char *path)
+{
+ int ret = -1;
+ virCommandPtr cmd = NULL;
+ char *refresh_tool = NULL;
+ char *desc = NULL;
+
+ if (virAsprintf(&desc, "%s/DiskDescriptor.xml", path) < 0)
+ return ret;
+
+ if (virFileRemove(desc, 0, 0) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("refresh ploop failed:"
+ " unuble to delete DiskDescriptor.xml"));
+ goto cleanup;
+ }
+
+ refresh_tool = virFindFileInPath("ploop");
+ if (!refresh_tool) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("unable to find ploop, please install ploop tools"));
+ goto cleanup;
+ }
+
+ cmd = virCommandNewArgList(refresh_tool, "restore-descriptor",
+ path, NULL);
+ virCommandAddArgFormat(cmd, "%s/root.hds", path);
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(refresh_tool);
+ virCommandFree(cmd);
+ VIR_FREE(desc);
+ return ret;
+}
+
+static int
virStorageBackendProbeTarget(virStorageSourcePtr target,
virStorageEncryptionPtr *encryption)
{
@@ -69,6 +109,7 @@ virStorageBackendProbeTarget(virStorageSourcePtr target,
int fd = -1;
int ret = -1;
int rc;
+ int format = VIR_STORAGE_FILE_AUTO;
virStorageSourcePtr meta = NULL;
struct stat sb;
@@ -84,14 +125,26 @@ virStorageBackendProbeTarget(virStorageSourcePtr target,
goto cleanup;
if (S_ISDIR(sb.st_mode)) {
- target->format = VIR_STORAGE_FILE_DIR;
- ret = 0;
- goto cleanup;
+ if (virStorageBackendIsPloopDir(target->path)) {
+ if (virStorageBackendRedoPloopUpdate(target, &sb, &fd,
+ VIR_STORAGE_VOL_FS_PROBE_FLAGS)
+ < 0)
+ goto cleanup;
+ /* Refresh information stored in DiskDescriptor.xml according
+ * to ploop image file content.*/
+ if (virStorageBackendPloopRestoreDesc(target->path) < 0)
+ goto cleanup;
+ format = VIR_STORAGE_FILE_PLOOP;
+ } else {
+ target->format = VIR_STORAGE_FILE_DIR;
+ ret = 0;
+ goto cleanup;
+ }
}
if (!(meta = virStorageFileGetMetadataFromFD(target->path,
fd,
- VIR_STORAGE_FILE_AUTO,
+ format,
&backingStoreFormat)))
goto cleanup;
@@ -949,6 +1002,9 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn
ATTRIBUTE_UNUSED,
if (vol->target.format == VIR_STORAGE_FILE_DIR)
vol->type = VIR_STORAGE_VOL_DIR;
+ if (vol->target.format == VIR_STORAGE_FILE_PLOOP)
+ vol->type = VIR_STORAGE_VOL_PLOOP;
+
if (vol->target.backingStore) {
ignore_value(virStorageBackendUpdateVolTargetInfo(vol->target.backingStore,
false,
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 49b1745..05ac254 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -184,6 +184,8 @@ qedGetBackingStore(char **, int *, const char *, size_t);
#define QED_F_BACKING_FILE 0x01
#define QED_F_BACKING_FORMAT_NO_PROBE 0x04
+#define PLOOP_IMAGE_SIZE_OFFSET 36
+#define PLOOP_SIZE_MULTIPLIER 512
static struct FileTypeInfo const fileTypeInfo[] = {
[VIR_STORAGE_FILE_NONE] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
@@ -236,8 +238,9 @@ static struct FileTypeInfo const fileTypeInfo[] = {
-1, {0}, 0, 0, 0, 0, NULL, NULL },
[VIR_STORAGE_FILE_VHD] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
-1, {0}, 0, 0, 0, 0, NULL, NULL },
- [VIR_STORAGE_FILE_PLOOP] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
- -1, {0}, 0, 0, 0, 0, NULL, NULL },
+ [VIR_STORAGE_FILE_PLOOP] = { 0, "WithouFreSpacExt", NULL,
LV_LITTLE_ENDIAN,
+ -2, {0}, PLOOP_IMAGE_SIZE_OFFSET, 0,
+ PLOOP_SIZE_MULTIPLIER, -1, NULL, NULL },
/* All formats with a backing store probe below here */
[VIR_STORAGE_FILE_COW] = {
--
1.8.3.1