1
0
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:
Peter Krempa 2014-07-07 12:56:23 +02:00
parent 912911a497
commit 3ea661deea
4 changed files with 59 additions and 33 deletions

View File

@ -1910,6 +1910,7 @@ virStorageFileGetSCSIKey;
virStorageFileIsClusterFS; virStorageFileIsClusterFS;
virStorageFileParseChainIndex; virStorageFileParseChainIndex;
virStorageFileProbeFormat; virStorageFileProbeFormat;
virStorageFileProbeFormatFromBuf;
virStorageFileResize; virStorageFileResize;
virStorageIsFile; virStorageIsFile;
virStorageNetHostDefClear; virStorageNetHostDefClear;

View File

@ -10334,11 +10334,13 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
int activeFail = false; int activeFail = false;
virQEMUDriverConfigPtr cfg = NULL; virQEMUDriverConfigPtr cfg = NULL;
char *alias = NULL; char *alias = NULL;
char *buf = NULL;
ssize_t len;
virCheckFlags(0, -1); virCheckFlags(0, -1);
if (!(vm = qemuDomObjFromDomain(dom))) if (!(vm = qemuDomObjFromDomain(dom)))
goto cleanup; return -1;
cfg = virQEMUDriverGetConfig(driver); cfg = virQEMUDriverGetConfig(driver);
@ -10346,8 +10348,7 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
goto cleanup; goto cleanup;
if (!path || path[0] == '\0') { if (!path || path[0] == '\0') {
virReportError(VIR_ERR_INVALID_ARG, virReportError(VIR_ERR_INVALID_ARG, "%s", _("NULL or empty path"));
"%s", _("NULL or empty path"));
goto cleanup; goto cleanup;
} }
@ -10357,48 +10358,68 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
_("invalid path %s not assigned to domain"), path); _("invalid path %s not assigned to domain"), path);
goto cleanup; goto cleanup;
} }
disk = vm->def->disks[idx]; disk = vm->def->disks[idx];
path = virDomainDiskGetSource(disk);
if (!path) { if (virStorageSourceIsLocalStorage(disk->src)) {
if (!disk->src->path) {
virReportError(VIR_ERR_INVALID_ARG, virReportError(VIR_ERR_INVALID_ARG,
_("disk %s does not currently have a source assigned"), _("disk '%s' does not currently have a source assigned"),
path); path);
goto cleanup; goto cleanup;
} }
/* The path is correct, now try to open it and get its size. */ if ((fd = qemuOpenFile(driver, vm, path, O_RDONLY, NULL, NULL)) == -1)
fd = qemuOpenFile(driver, vm, path, O_RDONLY, NULL, NULL);
if (fd == -1)
goto cleanup; 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 */ /* Probe for magic formats */
if (virDomainDiskGetFormat(disk)) { if (virDomainDiskGetFormat(disk)) {
format = virDomainDiskGetFormat(disk); format = virDomainDiskGetFormat(disk);
} else { } else {
if (cfg->allowDiskFormatProbing) { if (!cfg->allowDiskFormatProbing) {
if ((format = virStorageFileProbeFormat(path,
cfg->user,
cfg->group)) < 0)
goto cleanup;
} else {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("no disk format for %s and probing is disabled"), _("no disk format for %s and probing is disabled"),
path); path);
goto cleanup; 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; goto cleanup;
/* Get info for normal formats */ /* Get info for normal formats */
if (fstat(fd, &sb) < 0) { if (S_ISREG(sb.st_mode) || fd == -1) {
virReportSystemError(errno,
_("cannot stat file '%s'"), path);
goto cleanup;
}
if (S_ISREG(sb.st_mode)) {
#ifndef WIN32 #ifndef WIN32
info->physical = (unsigned long long)sb.st_blocks * info->physical = (unsigned long long)sb.st_blocks *
(unsigned long long)DEV_BSIZE; (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, /* ..but if guest is not using raw disk format and on a block device,
* then query highest allocated extent from QEMU * 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 && format != VIR_STORAGE_FILE_RAW &&
S_ISBLK(sb.st_mode)) { S_ISBLK(sb.st_mode)) {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
@ -10475,6 +10496,8 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
VIR_FREE(alias); VIR_FREE(alias);
virStorageSourceFree(meta); virStorageSourceFree(meta);
VIR_FORCE_CLOSE(fd); VIR_FORCE_CLOSE(fd);
if (disk)
virStorageFileDeinit(disk->src);
/* If we failed to get data from a domain because it's inactive and /* If we failed to get data from a domain because it's inactive and
* it's not a persistent domain, then force failure. * it's not a persistent domain, then force failure.
@ -10484,7 +10507,6 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
_("domain is not running")); _("domain is not running"));
ret = -1; ret = -1;
} }
if (vm)
virObjectUnlock(vm); virObjectUnlock(vm);
virObjectUnref(cfg); virObjectUnref(cfg);
return ret; return ret;

View File

@ -682,7 +682,7 @@ virStorageIsRelative(const char *backing)
} }
static int int
virStorageFileProbeFormatFromBuf(const char *path, virStorageFileProbeFormatFromBuf(const char *path,
char *buf, char *buf,
size_t buflen) size_t buflen)

View File

@ -276,6 +276,9 @@ struct _virStorageSource {
# endif # endif
int virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid); 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, int virStorageFileGetMetadataInternal(virStorageSourcePtr meta,
char *buf, char *buf,