1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-01-11 09:17:52 +03:00

qemu: Implement virDomainGetDiskErrors

This commit is contained in:
Jiri Denemark 2012-01-19 17:58:58 +01:00
parent 342fc56f58
commit e17e3ed6aa
6 changed files with 151 additions and 0 deletions

View File

@ -175,6 +175,7 @@ struct qemuDomainDiskInfo {
bool removable;
bool locked;
bool tray_open;
int io_status;
};
#endif /* __QEMUD_CONF_H */

View File

@ -11728,6 +11728,91 @@ cleanup:
return ret;
}
static int
qemuDomainGetDiskErrors(virDomainPtr dom,
virDomainDiskErrorPtr errors,
unsigned int nerrors,
unsigned int flags)
{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = NULL;
qemuDomainObjPrivatePtr priv;
char uuidstr[VIR_UUID_STRING_BUFLEN];
virHashTablePtr table = NULL;
int ret = -1;
int i;
int n = 0;
virCheckFlags(0, -1);
qemuDriverLock(driver);
virUUIDFormat(dom->uuid, uuidstr);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
qemuDriverUnlock(driver);
if (!vm) {
qemuReportError(VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
priv = vm->privateData;
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
goto cleanup;
if (!virDomainObjIsActive(vm)) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto endjob;
}
if (!errors) {
ret = vm->def->ndisks;
goto endjob;
}
qemuDomainObjEnterMonitor(driver, vm);
table = qemuMonitorGetBlockInfo(priv->mon);
qemuDomainObjExitMonitor(driver, vm);
if (!table)
goto endjob;
for (i = n = 0; i < vm->def->ndisks; i++) {
struct qemuDomainDiskInfo *info;
virDomainDiskDefPtr disk = vm->def->disks[i];
if ((info = virHashLookup(table, disk->info.alias)) &&
info->io_status != VIR_DOMAIN_DISK_ERROR_NONE) {
if (n == nerrors)
break;
if (!(errors[n].disk = strdup(disk->dst))) {
virReportOOMError();
goto endjob;
}
errors[n].error = info->io_status;
n++;
}
}
ret = n;
endjob:
if (qemuDomainObjEndJob(driver, vm) == 0)
vm = NULL;
cleanup:
if (vm)
virDomainObjUnlock(vm);
virHashFree(table);
if (ret < 0) {
for (i = 0; i < n; i++)
VIR_FREE(errors[i].disk);
}
return ret;
}
static virDriver qemuDriver = {
.no = VIR_DRV_QEMU,
.name = "QEMU",
@ -11881,6 +11966,7 @@ static virDriver qemuDriver = {
.domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
.domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
.domainSetInterfaceParameters = qemuDomainSetInterfaceParameters, /* 0.9.9 */
.domainGetDiskErrors = qemuDomainGetDiskErrors, /* 0.9.10 */
};

View File

@ -87,6 +87,20 @@ VIR_ENUM_IMPL(qemuMonitorVMStatus,
"postmigrate", "prelaunch", "finish-migrate", "restore-vm",
"running", "save-vm", "shutdown", "watchdog")
typedef enum {
QEMU_MONITOR_BLOCK_IO_STATUS_OK,
QEMU_MONITOR_BLOCK_IO_STATUS_FAILED,
QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE,
QEMU_MONITOR_BLOCK_IO_STATUS_LAST
} qemuMonitorBlockIOStatus;
VIR_ENUM_DECL(qemuMonitorBlockIOStatus)
VIR_ENUM_IMPL(qemuMonitorBlockIOStatus,
QEMU_MONITOR_BLOCK_IO_STATUS_LAST,
"ok", "failed", "nospace")
char *qemuMonitorEscapeArg(const char *in)
{
int len = 0;
@ -1227,6 +1241,32 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
return ret;
}
int
qemuMonitorBlockIOStatusToError(const char *status)
{
int st = qemuMonitorBlockIOStatusTypeFromString(status);
if (st < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("unknown block IO status: %s"), status);
return -1;
}
switch ((qemuMonitorBlockIOStatus) st) {
case QEMU_MONITOR_BLOCK_IO_STATUS_OK:
return VIR_DOMAIN_DISK_ERROR_NONE;
case QEMU_MONITOR_BLOCK_IO_STATUS_FAILED:
return VIR_DOMAIN_DISK_ERROR_UNSPEC;
case QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE:
return VIR_DOMAIN_DISK_ERROR_NO_SPACE;
/* unreachable */
case QEMU_MONITOR_BLOCK_IO_STATUS_LAST:
break;
}
return -1;
}
virHashTablePtr
qemuMonitorGetBlockInfo(qemuMonitorPtr mon)
{

View File

@ -236,6 +236,7 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
virDomainMemoryStatPtr stats,
unsigned int nr_stats);
int qemuMonitorBlockIOStatusToError(const char *status);
virHashTablePtr qemuMonitorGetBlockInfo(qemuMonitorPtr mon);
struct qemuDomainDiskInfo *
qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,

View File

@ -1389,6 +1389,7 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
struct qemuDomainDiskInfo *info;
const char *thisdev;
const char *status;
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@ -1434,6 +1435,13 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
*/
ignore_value(virJSONValueObjectGetBoolean(dev, "tray-open",
&info->tray_open));
/* Missing io-status indicates no error */
if ((status = virJSONValueObjectGetString(dev, "io-status"))) {
info->io_status = qemuMonitorBlockIOStatusToError(status);
if (info->io_status < 0)
goto cleanup;
}
}
ret = 0;

View File

@ -839,6 +839,21 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
VIR_DEBUG("error reading tray_open: %s", p);
else
info->tray_open = (tmp != 0);
} else if (STRPREFIX(p, "io-status=")) {
char *end;
char c;
p += strlen("io-status=");
end = strchr(p, ' ');
if (!end || end > eol)
end = eol;
c = *end;
*end = '\0';
info->io_status = qemuMonitorBlockIOStatusToError(p);
*end = c;
if (info->io_status < 0)
goto cleanup;
} else {
/* ignore because we don't parse all options */
}