mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
qemu: refactor qemuDomainGetBlockInfo to work with remote storage
The qemu block info function relied on working with local storage. Break this assumption by adding support for remote volumes. Unfortunately we still need to take a hybrid approach as some of the operations require a filedescriptor. Previously you'd get: $ virsh domblkinfo gl vda error: cannot stat file '/img10': Bad file descriptor Now you get some stats: $ virsh domblkinfo gl vda Capacity: 10485760 Allocation: 197120 Physical: 197120 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1110198
This commit is contained in:
parent
912911a497
commit
3ea661deea
@ -1910,6 +1910,7 @@ virStorageFileGetSCSIKey;
|
||||
virStorageFileIsClusterFS;
|
||||
virStorageFileParseChainIndex;
|
||||
virStorageFileProbeFormat;
|
||||
virStorageFileProbeFormatFromBuf;
|
||||
virStorageFileResize;
|
||||
virStorageIsFile;
|
||||
virStorageNetHostDefClear;
|
||||
|
@ -10334,11 +10334,13 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
|
||||
int activeFail = false;
|
||||
virQEMUDriverConfigPtr cfg = NULL;
|
||||
char *alias = NULL;
|
||||
char *buf = NULL;
|
||||
ssize_t len;
|
||||
|
||||
virCheckFlags(0, -1);
|
||||
|
||||
if (!(vm = qemuDomObjFromDomain(dom)))
|
||||
goto cleanup;
|
||||
return -1;
|
||||
|
||||
cfg = virQEMUDriverGetConfig(driver);
|
||||
|
||||
@ -10346,8 +10348,7 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
|
||||
goto cleanup;
|
||||
|
||||
if (!path || path[0] == '\0') {
|
||||
virReportError(VIR_ERR_INVALID_ARG,
|
||||
"%s", _("NULL or empty path"));
|
||||
virReportError(VIR_ERR_INVALID_ARG, "%s", _("NULL or empty path"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -10357,48 +10358,68 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
|
||||
_("invalid path %s not assigned to domain"), path);
|
||||
goto cleanup;
|
||||
}
|
||||
disk = vm->def->disks[idx];
|
||||
path = virDomainDiskGetSource(disk);
|
||||
if (!path) {
|
||||
virReportError(VIR_ERR_INVALID_ARG,
|
||||
_("disk %s does not currently have a source assigned"),
|
||||
path);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* The path is correct, now try to open it and get its size. */
|
||||
fd = qemuOpenFile(driver, vm, path, O_RDONLY, NULL, NULL);
|
||||
if (fd == -1)
|
||||
goto cleanup;
|
||||
disk = vm->def->disks[idx];
|
||||
|
||||
if (virStorageSourceIsLocalStorage(disk->src)) {
|
||||
if (!disk->src->path) {
|
||||
virReportError(VIR_ERR_INVALID_ARG,
|
||||
_("disk '%s' does not currently have a source assigned"),
|
||||
path);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((fd = qemuOpenFile(driver, vm, path, O_RDONLY, NULL, NULL)) == -1)
|
||||
goto cleanup;
|
||||
|
||||
if (fstat(fd, &sb) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("cannot stat file '%s'"), disk->src->path);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((len = virFileReadHeaderFD(fd, VIR_STORAGE_MAX_HEADER, &buf)) < 0) {
|
||||
virReportSystemError(errno, _("cannot read header '%s'"),
|
||||
disk->src->path);
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
if (virStorageFileInitAs(disk->src, cfg->user, cfg->group) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((len = virStorageFileReadHeader(disk->src, VIR_STORAGE_MAX_HEADER,
|
||||
&buf)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virStorageFileStat(disk->src, &sb) < 0) {
|
||||
virReportSystemError(errno, _("failed to stat remote file '%s'"),
|
||||
NULLSTR(disk->src->path));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Probe for magic formats */
|
||||
if (virDomainDiskGetFormat(disk)) {
|
||||
format = virDomainDiskGetFormat(disk);
|
||||
} else {
|
||||
if (cfg->allowDiskFormatProbing) {
|
||||
if ((format = virStorageFileProbeFormat(path,
|
||||
cfg->user,
|
||||
cfg->group)) < 0)
|
||||
goto cleanup;
|
||||
} else {
|
||||
if (!cfg->allowDiskFormatProbing) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("no disk format for %s and probing is disabled"),
|
||||
path);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((format = virStorageFileProbeFormatFromBuf(disk->src->path,
|
||||
buf, len)) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(meta = virStorageFileGetMetadataFromFD(path, fd, format, NULL)))
|
||||
if (!(meta = virStorageFileGetMetadataFromBuf(disk->src->path, buf, len,
|
||||
format, NULL)))
|
||||
goto cleanup;
|
||||
|
||||
/* Get info for normal formats */
|
||||
if (fstat(fd, &sb) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("cannot stat file '%s'"), path);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (S_ISREG(sb.st_mode)) {
|
||||
if (S_ISREG(sb.st_mode) || fd == -1) {
|
||||
#ifndef WIN32
|
||||
info->physical = (unsigned long long)sb.st_blocks *
|
||||
(unsigned long long)DEV_BSIZE;
|
||||
@ -10434,7 +10455,7 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
|
||||
/* ..but if guest is not using raw disk format and on a block device,
|
||||
* then query highest allocated extent from QEMU
|
||||
*/
|
||||
if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_BLOCK &&
|
||||
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_BLOCK &&
|
||||
format != VIR_STORAGE_FILE_RAW &&
|
||||
S_ISBLK(sb.st_mode)) {
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
@ -10475,6 +10496,8 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
|
||||
VIR_FREE(alias);
|
||||
virStorageSourceFree(meta);
|
||||
VIR_FORCE_CLOSE(fd);
|
||||
if (disk)
|
||||
virStorageFileDeinit(disk->src);
|
||||
|
||||
/* If we failed to get data from a domain because it's inactive and
|
||||
* it's not a persistent domain, then force failure.
|
||||
@ -10484,8 +10507,7 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
|
||||
_("domain is not running"));
|
||||
ret = -1;
|
||||
}
|
||||
if (vm)
|
||||
virObjectUnlock(vm);
|
||||
virObjectUnlock(vm);
|
||||
virObjectUnref(cfg);
|
||||
return ret;
|
||||
}
|
||||
|
@ -682,7 +682,7 @@ virStorageIsRelative(const char *backing)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
int
|
||||
virStorageFileProbeFormatFromBuf(const char *path,
|
||||
char *buf,
|
||||
size_t buflen)
|
||||
|
@ -276,6 +276,9 @@ struct _virStorageSource {
|
||||
# endif
|
||||
|
||||
int virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid);
|
||||
int virStorageFileProbeFormatFromBuf(const char *path,
|
||||
char *buf,
|
||||
size_t buflen);
|
||||
|
||||
int virStorageFileGetMetadataInternal(virStorageSourcePtr meta,
|
||||
char *buf,
|
||||
|
Loading…
x
Reference in New Issue
Block a user