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)
|
virDomainObjPtr vm)
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virHashTablePtr table;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
|
table = qemuMonitorGetBlockInfo(priv->mon);
|
||||||
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
|
|
||||||
|
if (!table)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
for (i = 0; i < vm->def->ndisks; i++) {
|
for (i = 0; i < vm->def->ndisks; i++) {
|
||||||
virDomainDiskDefPtr disk = vm->def->disks[i];
|
virDomainDiskDefPtr disk = vm->def->disks[i];
|
||||||
struct qemuDomainDiskInfo info;
|
struct qemuDomainDiskInfo *info;
|
||||||
|
|
||||||
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK ||
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK ||
|
||||||
disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
info = qemuMonitorBlockInfoLookup(table, disk->info.alias);
|
||||||
|
if (!info)
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
|
||||||
if (qemuMonitorGetBlockInfo(priv->mon, disk->info.alias, &info) < 0) {
|
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
|
||||||
|
|
||||||
if (info.tray_open && disk->src)
|
if (info->tray_open && disk->src)
|
||||||
VIR_FREE(disk->src);
|
VIR_FREE(disk->src);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
virHashFree(table);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,24 +1227,51 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemuMonitorGetBlockInfo(qemuMonitorPtr mon,
|
virHashTablePtr
|
||||||
const char *devname,
|
qemuMonitorGetBlockInfo(qemuMonitorPtr mon)
|
||||||
struct qemuDomainDiskInfo *info)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
virHashTablePtr table;
|
||||||
|
|
||||||
|
VIR_DEBUG("mon=%p", mon);
|
||||||
|
|
||||||
VIR_DEBUG("mon=%p dev=%p info=%p", mon, devname, info);
|
|
||||||
if (!mon) {
|
if (!mon) {
|
||||||
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
|
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||||
_("monitor must not be NULL"));
|
_("monitor must not be NULL"));
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(table = virHashCreate(32, (virHashDataFree) free)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (mon->json)
|
if (mon->json)
|
||||||
ret = qemuMonitorJSONGetBlockInfo(mon, devname, info);
|
ret = qemuMonitorJSONGetBlockInfo(mon, table);
|
||||||
else
|
else
|
||||||
ret = qemuMonitorTextGetBlockInfo(mon, devname, info);
|
ret = qemuMonitorTextGetBlockInfo(mon, table);
|
||||||
return ret;
|
|
||||||
|
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,
|
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
||||||
|
@ -235,9 +235,12 @@ int qemuMonitorGetBalloonInfo(qemuMonitorPtr mon,
|
|||||||
int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
|
int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
|
||||||
virDomainMemoryStatPtr stats,
|
virDomainMemoryStatPtr stats,
|
||||||
unsigned int nr_stats);
|
unsigned int nr_stats);
|
||||||
int qemuMonitorGetBlockInfo(qemuMonitorPtr mon,
|
|
||||||
const char *devname,
|
virHashTablePtr qemuMonitorGetBlockInfo(qemuMonitorPtr mon);
|
||||||
struct qemuDomainDiskInfo *info);
|
struct qemuDomainDiskInfo *
|
||||||
|
qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,
|
||||||
|
const char *devname);
|
||||||
|
|
||||||
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
||||||
const char *dev_name,
|
const char *dev_name,
|
||||||
long long *rd_req,
|
long long *rd_req,
|
||||||
|
@ -1357,11 +1357,9 @@ cleanup:
|
|||||||
|
|
||||||
|
|
||||||
int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
||||||
const char *devname,
|
virHashTablePtr table)
|
||||||
struct qemuDomainDiskInfo *info)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret;
|
||||||
bool found = false;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-block",
|
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-block",
|
||||||
@ -1389,6 +1387,7 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
|||||||
|
|
||||||
for (i = 0; i < virJSONValueArraySize(devices); i++) {
|
for (i = 0; i < virJSONValueArraySize(devices); i++) {
|
||||||
virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
|
virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
|
||||||
|
struct qemuDomainDiskInfo *info;
|
||||||
const char *thisdev;
|
const char *thisdev;
|
||||||
|
|
||||||
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
|
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
|
||||||
@ -1406,10 +1405,16 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
|||||||
if (STRPREFIX(thisdev, QEMU_DRIVE_HOST_PREFIX))
|
if (STRPREFIX(thisdev, QEMU_DRIVE_HOST_PREFIX))
|
||||||
thisdev += strlen(QEMU_DRIVE_HOST_PREFIX);
|
thisdev += strlen(QEMU_DRIVE_HOST_PREFIX);
|
||||||
|
|
||||||
if (STRNEQ(thisdev, devname))
|
if (VIR_ALLOC(info) < 0) {
|
||||||
continue;
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virHashAddEntry(table, thisdev, info) < 0) {
|
||||||
|
VIR_FREE(info);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
found = true;
|
|
||||||
if (virJSONValueObjectGetBoolean(dev, "removable", &info->removable) < 0) {
|
if (virJSONValueObjectGetBoolean(dev, "removable", &info->removable) < 0) {
|
||||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot read %s value"),
|
_("cannot read %s value"),
|
||||||
@ -1429,15 +1434,6 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
|||||||
*/
|
*/
|
||||||
ignore_value(virJSONValueObjectGetBoolean(dev, "tray-open",
|
ignore_value(virJSONValueObjectGetBoolean(dev, "tray-open",
|
||||||
&info->tray_open));
|
&info->tray_open));
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("cannot find info for device '%s'"),
|
|
||||||
devname);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -63,8 +63,7 @@ int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
|
|||||||
virDomainMemoryStatPtr stats,
|
virDomainMemoryStatPtr stats,
|
||||||
unsigned int nr_stats);
|
unsigned int nr_stats);
|
||||||
int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
||||||
const char *devname,
|
virHashTablePtr table);
|
||||||
struct qemuDomainDiskInfo *info);
|
|
||||||
int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
||||||
const char *dev_name,
|
const char *dev_name,
|
||||||
long long *rd_req,
|
long long *rd_req,
|
||||||
|
@ -772,14 +772,14 @@ int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
|
|||||||
|
|
||||||
|
|
||||||
int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
||||||
const char *devname,
|
virHashTablePtr table)
|
||||||
struct qemuDomainDiskInfo *info)
|
|
||||||
{
|
{
|
||||||
|
struct qemuDomainDiskInfo *info;
|
||||||
char *reply = NULL;
|
char *reply = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
char *dummy;
|
char *dummy;
|
||||||
const char *p, *eol;
|
char *p, *eol;
|
||||||
int devnamelen = strlen(devname);
|
char *dev;
|
||||||
int tmp;
|
int tmp;
|
||||||
|
|
||||||
if (qemuMonitorHMPCommand(mon, "info block", &reply) < 0) {
|
if (qemuMonitorHMPCommand(mon, "info block", &reply) < 0) {
|
||||||
@ -805,16 +805,22 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
|||||||
if (STRPREFIX(p, QEMU_DRIVE_HOST_PREFIX))
|
if (STRPREFIX(p, QEMU_DRIVE_HOST_PREFIX))
|
||||||
p += strlen(QEMU_DRIVE_HOST_PREFIX);
|
p += strlen(QEMU_DRIVE_HOST_PREFIX);
|
||||||
|
|
||||||
if (STREQLEN(p, devname, devnamelen) &&
|
eol = strchr(p, '\n');
|
||||||
p[devnamelen] == ':' && p[devnamelen+1] == ' ') {
|
if (!eol)
|
||||||
|
eol = p + strlen(p) - 1;
|
||||||
|
|
||||||
eol = strchr(p, '\n');
|
dev = p;
|
||||||
if (!eol)
|
p = strchr(p, ':');
|
||||||
eol = p + strlen(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=")) {
|
if (STRPREFIX(p, "removable=")) {
|
||||||
p += strlen("removable=");
|
p += strlen("removable=");
|
||||||
if (virStrToLong_i(p, &dummy, 10, &tmp) == -1)
|
if (virStrToLong_i(p, &dummy, 10, &tmp) == -1)
|
||||||
@ -839,24 +845,25 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
|||||||
|
|
||||||
/* skip to next label */
|
/* skip to next label */
|
||||||
p = strchr(p, ' ');
|
p = strchr(p, ' ');
|
||||||
if (!p || p >= eol) break;
|
if (!p)
|
||||||
|
break;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
if (virHashAddEntry(table, dev, info) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
else
|
||||||
|
info = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* skip to next line */
|
/* skip to the next line */
|
||||||
p = strchr(p, '\n');
|
p = eol + 1;
|
||||||
if (!p) break;
|
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qemuReportError(VIR_ERR_INVALID_ARG,
|
ret = 0;
|
||||||
_("no info for device '%s'"), devname);
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
VIR_FREE(info);
|
||||||
VIR_FREE(reply);
|
VIR_FREE(reply);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,7 @@ int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
|
|||||||
virDomainMemoryStatPtr stats,
|
virDomainMemoryStatPtr stats,
|
||||||
unsigned int nr_stats);
|
unsigned int nr_stats);
|
||||||
int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
||||||
const char *devname,
|
virHashTablePtr table);
|
||||||
struct qemuDomainDiskInfo *info);
|
|
||||||
int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
|
int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
|
||||||
const char *dev_name,
|
const char *dev_name,
|
||||||
long long *rd_req,
|
long long *rd_req,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user