virStorageBackendProbeTarget(virStorageVolTargetPtr target, char **backingStore, int *backingStoreFormat, unsigned long long *allocation, unsigned long long *capacity, virStorageEncryptionPtr *encryption) { int fd = -1; int ret = -1; virStorageFileMetadata *meta; if (VIR_ALLOC(meta) < 0) { virReportOOMError(); return ret; } *backingStore = NULL; *backingStoreFormat = VIR_STORAGE_FILE_AUTO; if (encryption) *encryption = NULL; if ((ret = virStorageBackendVolOpenCheckMode(target->path, VIR_STORAGE_VOL_FS_REFRESH_FLAGS)) < 0) goto error; /* Take care to propagate ret, it is not always -1 */ fd = ret; if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd, allocation, capacity)) < 0) { goto error; } if ((target->format = virStorageFileProbeFormatFromFD(target->path, fd)) < 0) { ret = -1; goto error; } if (virStorageFileGetMetadataFromFD(target->path, fd, target->format, meta) < 0) { ret = -1; goto error; } VIR_FORCE_CLOSE(fd); if (meta->backingStore) { *backingStore = meta->backingStore; meta->backingStore = NULL; if (meta->backingStoreFormat == VIR_STORAGE_FILE_AUTO) { if ((ret = virStorageFileProbeFormat(*backingStore)) < 0) { /* If the backing file is currently unavailable, only log an error, * but continue. Returning -1 here would disable the whole storage * pool, making it unavailable for even maintenance. */ virStorageReportError(VIR_ERR_INTERNAL_ERROR, _("cannot probe backing volume format: %s"), *backingStore); ret = -3; } else { *backingStoreFormat = ret; ret = 0; } } else { *backingStoreFormat = meta->backingStoreFormat; ret = 0; } } else { ret = 0; } if (capacity && meta->capacity) *capacity = meta->capacity; if (encryption != NULL && meta->encrypted) { if (VIR_ALLOC(*encryption) < 0) { virReportOOMError(); goto cleanup; } switch (target->format) { case VIR_STORAGE_FILE_QCOW: case VIR_STORAGE_FILE_QCOW2: (*encryption)->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW; break; default: break; } /* XXX ideally we'd fill in secret UUID here * but we cannot guarantee 'conn' is non-NULL * at this point in time :-( So we only fill * in secrets when someone first queries a vol */ } virStorageFileFreeMetadata(meta); return ret; error: VIR_FORCE_CLOSE(fd); cleanup: virStorageFileFreeMetadata(meta); return ret; }
virStorageBackendProbeTarget(virStorageSourcePtr target, char **backingStore, int *backingStoreFormat, virStorageEncryptionPtr *encryption) { int fd = -1; int ret = -1; virStorageFileMetadata *meta = NULL; struct stat sb; char *header = NULL; ssize_t len = VIR_STORAGE_MAX_HEADER; *backingStore = NULL; *backingStoreFormat = VIR_STORAGE_FILE_AUTO; if (encryption) *encryption = NULL; if ((ret = virStorageBackendVolOpen(target->path, &sb, VIR_STORAGE_VOL_FS_PROBE_FLAGS)) < 0) goto error; /* Take care to propagate ret, it is not always -1 */ fd = ret; if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb)) < 0) { goto error; } if (S_ISDIR(sb.st_mode)) { target->format = VIR_STORAGE_FILE_DIR; } else { if ((len = virFileReadHeaderFD(fd, len, &header)) < 0) { virReportSystemError(errno, _("cannot read header '%s'"), target->path); goto error; } target->format = virStorageFileProbeFormatFromBuf(target->path, header, len); if (target->format < 0) { ret = -1; goto error; } if (!(meta = virStorageFileGetMetadataFromBuf(target->path, header, len, target->format, backingStore, backingStoreFormat))) { ret = -1; goto error; } } VIR_FORCE_CLOSE(fd); if (meta && *backingStore && *backingStoreFormat == VIR_STORAGE_FILE_AUTO && virStorageIsFile(*backingStore)) { if ((ret = virStorageFileProbeFormat(*backingStore, -1, -1)) < 0) { /* If the backing file is currently unavailable, only log an error, * but continue. Returning -1 here would disable the whole storage * pool, making it unavailable for even maintenance. */ virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot probe backing volume format: %s"), *backingStore); ret = -3; } else { *backingStoreFormat = ret; ret = 0; } } else { ret = 0; } if (meta && meta->capacity) target->capacity = meta->capacity; if (encryption && meta && meta->encryption) { *encryption = meta->encryption; meta->encryption = NULL; switch (target->format) { case VIR_STORAGE_FILE_QCOW: case VIR_STORAGE_FILE_QCOW2: (*encryption)->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW; break; default: break; } /* XXX ideally we'd fill in secret UUID here * but we cannot guarantee 'conn' is non-NULL * at this point in time :-( So we only fill * in secrets when someone first queries a vol */ } virBitmapFree(target->features); if (meta) { target->features = meta->features; meta->features = NULL; } if (meta && meta->compat) { VIR_FREE(target->compat); target->compat = meta->compat; meta->compat = NULL; } goto cleanup; error: VIR_FORCE_CLOSE(fd); cleanup: virStorageFileFreeMetadata(meta); VIR_FREE(header); return ret; }
static int virStorageBackendProbeTarget(virStorageSourcePtr target, virStorageEncryptionPtr *encryption) { int backingStoreFormat; int fd = -1; int ret = -1; int rc; virStorageSourcePtr meta = NULL; struct stat sb; if (encryption) *encryption = NULL; if ((rc = virStorageBackendVolOpen(target->path, &sb, VIR_STORAGE_VOL_FS_PROBE_FLAGS)) < 0) return rc; /* Take care to propagate rc, it is not always -1 */ fd = rc; if (virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb) < 0) goto cleanup; if (S_ISDIR(sb.st_mode)) { target->format = VIR_STORAGE_FILE_DIR; ret = 0; goto cleanup; } if (!(meta = virStorageFileGetMetadataFromFD(target->path, fd, VIR_STORAGE_FILE_AUTO, &backingStoreFormat))) goto cleanup; if (meta->backingStoreRaw) { if (!(target->backingStore = virStorageSourceNewFromBacking(meta))) goto cleanup; target->backingStore->format = backingStoreFormat; /* XXX: Remote storage doesn't play nicely with volumes backed by * remote storage. To avoid trouble, just fake the backing store is RAW * and put the string from the metadata as the path of the target. */ if (!virStorageSourceIsLocalStorage(target->backingStore)) { virStorageSourceFree(target->backingStore); if (VIR_ALLOC(target->backingStore) < 0) goto cleanup; target->backingStore->type = VIR_STORAGE_TYPE_NETWORK; target->backingStore->path = meta->backingStoreRaw; meta->backingStoreRaw = NULL; target->backingStore->format = VIR_STORAGE_FILE_RAW; } if (target->backingStore->format == VIR_STORAGE_FILE_AUTO) { if ((rc = virStorageFileProbeFormat(target->backingStore->path, -1, -1)) < 0) { /* If the backing file is currently unavailable or is * accessed via remote protocol only log an error, fake the * format as RAW and continue. Returning -1 here would * disable the whole storage pool, making it unavailable for * even maintenance. */ target->backingStore->format = VIR_STORAGE_FILE_RAW; virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot probe backing volume format: %s"), target->backingStore->path); } else { target->backingStore->format = rc; } } } target->format = meta->format; /* Default to success below this point */ ret = 0; if (meta->capacity) target->capacity = meta->capacity; if (encryption && meta->encryption) { *encryption = meta->encryption; meta->encryption = NULL; switch (target->format) { case VIR_STORAGE_FILE_QCOW: case VIR_STORAGE_FILE_QCOW2: (*encryption)->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW; break; default: break; } /* XXX ideally we'd fill in secret UUID here * but we cannot guarantee 'conn' is non-NULL * at this point in time :-( So we only fill * in secrets when someone first queries a vol */ } virBitmapFree(target->features); target->features = meta->features; meta->features = NULL; if (meta->compat) { VIR_FREE(target->compat); target->compat = meta->compat; meta->compat = NULL; } cleanup: VIR_FORCE_CLOSE(fd); virStorageSourceFree(meta); return ret; }