mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 15:27:47 +00:00
qemu: Refactor qemuMonitorGetBlockInfo
QEMU always sends details about all available block devices as an answer for "info block"/"query-block" command. On the other hand, our qemuMonitorGetBlockInfo was made for a single block devices queries only. Thus, when asking for multiple devices, we asked qemu multiple times to always get the same answer from which different parts were filtered. This patch makes qemuMonitorGetBlockInfo return a hash table of all block devices, which may later be used for getting details about specific devices.
This commit is contained in:
parent
bc1edeb611
commit
65c27e2935
@ -155,34 +155,38 @@ qemuDomainCheckEjectableMedia(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm)
|
||||
{
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
virHashTablePtr table;
|
||||
int ret = -1;
|
||||
int i;
|
||||
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
table = qemuMonitorGetBlockInfo(priv->mon);
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
|
||||
if (!table)
|
||||
goto cleanup;
|
||||
|
||||
for (i = 0; i < vm->def->ndisks; i++) {
|
||||
virDomainDiskDefPtr disk = vm->def->disks[i];
|
||||
struct qemuDomainDiskInfo info;
|
||||
struct qemuDomainDiskInfo *info;
|
||||
|
||||
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK ||
|
||||
disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
if (qemuMonitorGetBlockInfo(priv->mon, disk->info.alias, &info) < 0) {
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
info = qemuMonitorBlockInfoLookup(table, disk->info.alias);
|
||||
if (!info)
|
||||
goto cleanup;
|
||||
}
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
|
||||
if (info.tray_open && disk->src)
|
||||
if (info->tray_open && disk->src)
|
||||
VIR_FREE(disk->src);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
virHashFree(table);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1227,24 +1227,51 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qemuMonitorGetBlockInfo(qemuMonitorPtr mon,
|
||||
const char *devname,
|
||||
struct qemuDomainDiskInfo *info)
|
||||
virHashTablePtr
|
||||
qemuMonitorGetBlockInfo(qemuMonitorPtr mon)
|
||||
{
|
||||
int ret;
|
||||
virHashTablePtr table;
|
||||
|
||||
VIR_DEBUG("mon=%p", mon);
|
||||
|
||||
VIR_DEBUG("mon=%p dev=%p info=%p", mon, devname, info);
|
||||
if (!mon) {
|
||||
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
_("monitor must not be NULL"));
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(table = virHashCreate(32, (virHashDataFree) free)))
|
||||
return NULL;
|
||||
|
||||
if (mon->json)
|
||||
ret = qemuMonitorJSONGetBlockInfo(mon, devname, info);
|
||||
ret = qemuMonitorJSONGetBlockInfo(mon, table);
|
||||
else
|
||||
ret = qemuMonitorTextGetBlockInfo(mon, devname, info);
|
||||
return ret;
|
||||
ret = qemuMonitorTextGetBlockInfo(mon, table);
|
||||
|
||||
if (ret < 0) {
|
||||
virHashFree(table);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
struct qemuDomainDiskInfo *
|
||||
qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,
|
||||
const char *devname)
|
||||
{
|
||||
struct qemuDomainDiskInfo *info;
|
||||
|
||||
VIR_DEBUG("blockInfo=%p dev=%s", blockInfo, NULLSTR(devname));
|
||||
|
||||
if (!(info = virHashLookup(blockInfo, devname))) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot find info for device '%s'"),
|
||||
NULLSTR(devname));
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
||||
|
@ -235,9 +235,12 @@ int qemuMonitorGetBalloonInfo(qemuMonitorPtr mon,
|
||||
int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
|
||||
virDomainMemoryStatPtr stats,
|
||||
unsigned int nr_stats);
|
||||
int qemuMonitorGetBlockInfo(qemuMonitorPtr mon,
|
||||
const char *devname,
|
||||
struct qemuDomainDiskInfo *info);
|
||||
|
||||
virHashTablePtr qemuMonitorGetBlockInfo(qemuMonitorPtr mon);
|
||||
struct qemuDomainDiskInfo *
|
||||
qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,
|
||||
const char *devname);
|
||||
|
||||
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
||||
const char *dev_name,
|
||||
long long *rd_req,
|
||||
|
@ -1357,11 +1357,9 @@ cleanup:
|
||||
|
||||
|
||||
int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
||||
const char *devname,
|
||||
struct qemuDomainDiskInfo *info)
|
||||
virHashTablePtr table)
|
||||
{
|
||||
int ret = 0;
|
||||
bool found = false;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-block",
|
||||
@ -1389,6 +1387,7 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
||||
|
||||
for (i = 0; i < virJSONValueArraySize(devices); i++) {
|
||||
virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
|
||||
struct qemuDomainDiskInfo *info;
|
||||
const char *thisdev;
|
||||
|
||||
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
|
||||
@ -1406,10 +1405,16 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
||||
if (STRPREFIX(thisdev, QEMU_DRIVE_HOST_PREFIX))
|
||||
thisdev += strlen(QEMU_DRIVE_HOST_PREFIX);
|
||||
|
||||
if (STRNEQ(thisdev, devname))
|
||||
continue;
|
||||
if (VIR_ALLOC(info) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virHashAddEntry(table, thisdev, info) < 0) {
|
||||
VIR_FREE(info);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
found = true;
|
||||
if (virJSONValueObjectGetBoolean(dev, "removable", &info->removable) < 0) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot read %s value"),
|
||||
@ -1429,15 +1434,6 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
||||
*/
|
||||
ignore_value(virJSONValueObjectGetBoolean(dev, "tray-open",
|
||||
&info->tray_open));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot find info for device '%s'"),
|
||||
devname);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
@ -63,8 +63,7 @@ int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
|
||||
virDomainMemoryStatPtr stats,
|
||||
unsigned int nr_stats);
|
||||
int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
||||
const char *devname,
|
||||
struct qemuDomainDiskInfo *info);
|
||||
virHashTablePtr table);
|
||||
int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
||||
const char *dev_name,
|
||||
long long *rd_req,
|
||||
|
@ -772,14 +772,14 @@ int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
|
||||
|
||||
|
||||
int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
||||
const char *devname,
|
||||
struct qemuDomainDiskInfo *info)
|
||||
virHashTablePtr table)
|
||||
{
|
||||
struct qemuDomainDiskInfo *info;
|
||||
char *reply = NULL;
|
||||
int ret = -1;
|
||||
char *dummy;
|
||||
const char *p, *eol;
|
||||
int devnamelen = strlen(devname);
|
||||
char *p, *eol;
|
||||
char *dev;
|
||||
int tmp;
|
||||
|
||||
if (qemuMonitorHMPCommand(mon, "info block", &reply) < 0) {
|
||||
@ -805,16 +805,22 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
||||
if (STRPREFIX(p, QEMU_DRIVE_HOST_PREFIX))
|
||||
p += strlen(QEMU_DRIVE_HOST_PREFIX);
|
||||
|
||||
if (STREQLEN(p, devname, devnamelen) &&
|
||||
p[devnamelen] == ':' && p[devnamelen+1] == ' ') {
|
||||
eol = strchr(p, '\n');
|
||||
if (!eol)
|
||||
eol = p + strlen(p) - 1;
|
||||
|
||||
eol = strchr(p, '\n');
|
||||
if (!eol)
|
||||
eol = p + strlen(p);
|
||||
dev = p;
|
||||
p = strchr(p, ':');
|
||||
if (p && p < eol && *(p + 1) == ' ') {
|
||||
if (VIR_ALLOC(info) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
p += devnamelen + 2; /* Skip to first label. */
|
||||
*p = '\0';
|
||||
p += 2;
|
||||
|
||||
while (*p) {
|
||||
while (p < eol) {
|
||||
if (STRPREFIX(p, "removable=")) {
|
||||
p += strlen("removable=");
|
||||
if (virStrToLong_i(p, &dummy, 10, &tmp) == -1)
|
||||
@ -839,24 +845,25 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
||||
|
||||
/* skip to next label */
|
||||
p = strchr(p, ' ');
|
||||
if (!p || p >= eol) break;
|
||||
if (!p)
|
||||
break;
|
||||
p++;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
if (virHashAddEntry(table, dev, info) < 0)
|
||||
goto cleanup;
|
||||
else
|
||||
info = NULL;
|
||||
}
|
||||
|
||||
/* skip to next line */
|
||||
p = strchr(p, '\n');
|
||||
if (!p) break;
|
||||
p++;
|
||||
/* skip to the next line */
|
||||
p = eol + 1;
|
||||
}
|
||||
|
||||
qemuReportError(VIR_ERR_INVALID_ARG,
|
||||
_("no info for device '%s'"), devname);
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(info);
|
||||
VIR_FREE(reply);
|
||||
return ret;
|
||||
}
|
||||
|
@ -59,8 +59,7 @@ int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
|
||||
virDomainMemoryStatPtr stats,
|
||||
unsigned int nr_stats);
|
||||
int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
||||
const char *devname,
|
||||
struct qemuDomainDiskInfo *info);
|
||||
virHashTablePtr table);
|
||||
int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
|
||||
const char *dev_name,
|
||||
long long *rd_req,
|
||||
|
Loading…
Reference in New Issue
Block a user