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:
Jiri Denemark 2012-01-18 22:01:30 +01:00
parent bc1edeb611
commit 65c27e2935
7 changed files with 95 additions and 60 deletions

View File

@ -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;
}

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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);
eol = p + strlen(p) - 1;
p += devnamelen + 2; /* Skip to first label. */
dev = p;
p = strchr(p, ':');
if (p && p < eol && *(p + 1) == ' ') {
if (VIR_ALLOC(info) < 0) {
virReportOOMError();
goto cleanup;
}
while (*p) {
*p = '\0';
p += 2;
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++;
}
if (virHashAddEntry(table, dev, info) < 0)
goto cleanup;
else
info = NULL;
}
/* skip to the next line */
p = eol + 1;
}
ret = 0;
goto cleanup;
}
/* skip to next line */
p = strchr(p, '\n');
if (!p) break;
p++;
}
qemuReportError(VIR_ERR_INVALID_ARG,
_("no info for device '%s'"), devname);
cleanup:
VIR_FREE(info);
VIR_FREE(reply);
return ret;
}

View File

@ -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,