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:
parent
342fc56f58
commit
e17e3ed6aa
@ -175,6 +175,7 @@ struct qemuDomainDiskInfo {
|
||||
bool removable;
|
||||
bool locked;
|
||||
bool tray_open;
|
||||
int io_status;
|
||||
};
|
||||
|
||||
#endif /* __QEMUD_CONF_H */
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user