diff --git a/ChangeLog b/ChangeLog index 544ea11045..1d07167235 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Tue Jun 5 14:03:38 CEST 2007 Daniel Veillard + + * include/libvirt/libvirt.h include/libvirt/libvirt.h.in + src/driver.h src/libvirt.c src/libvirt_sym.version + src/proxy_internal.c src/qemu_internal.c src/test.c + src/virsh.c src/xen_internal.c src/xen_internal.h src/xen_unified.c + src/xend_internal.c src/xm_internal.c src/xs_internal.c: + Applied patches from Atsushi SAKAI to add the scheduler API, + with patch from Rich Jones for error handing, and a number + of cleanups and more error checking from me + Mon Jun 4 10:41:25 CEST 2007 Daniel Veillard * src/xml.c: apply patch from Masayuki Sunou about an uninitialized diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h index 7ce8c38d69..a17b9a5b61 100644 --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -168,6 +168,71 @@ struct _virNodeInfo { }; +/** + * virDomainSchedParameterType: + * + * A scheduler parameter field type + */ +typedef enum { + VIR_DOMAIN_SCHED_FIELD_INT = 1, /* integer case */ + VIR_DOMAIN_SCHED_FIELD_UINT = 2, /* unsigned integer case */ + VIR_DOMAIN_SCHED_FIELD_LLONG = 3, /* long long case */ + VIR_DOMAIN_SCHED_FIELD_ULLONG = 4, /* unsigned long long case */ + VIR_DOMAIN_SCHED_FIELD_DOUBLE = 5, /* double case */ + VIR_DOMAIN_SCHED_FIELD_BOOLEAN = 6 /* boolean(character) case */ +} virSchedParameterType; + +/** + * VIR_DOMAIN_SCHED_FIELD_LENGTH: + * + * Macro providing the field length of virSchedParameter + */ + +#define VIR_DOMAIN_SCHED_FIELD_LENGTH 80 + +/** + * virDomainSchedParameter: + * + * a virDomainSchedParameter is the set of scheduler parameters + */ + +typedef struct _virSchedParameter virSchedParameter; + +struct _virSchedParameter { + char field[VIR_DOMAIN_SCHED_FIELD_LENGTH]; /* parameter name */ + int type; /* parameter type */ + union { + int i; /* data for integer case */ + unsigned int ui; /* data for unsigned integer case */ + long long int l; /* data for long long integer case */ + unsigned long long int ul; /* data for unsigned long long integer case */ + double d; /* data for double case */ + char b; /* data for char case */ + } value; /* parameter value */ +}; + +/** + * virSchedParameterPtr: + * + * a virSchedParameterPtr is a pointer to a virSchedParameter structure. + */ + +typedef virSchedParameter *virSchedParameterPtr; + +/* + * Fetch scheduler parameters, caller allocates 'params' field of size 'nparams' + */ +int virDomainGetSchedulerParameters (virDomainPtr domain, + virSchedParameterPtr params, + int *nparams); + +/* + * Change scheduler parameters + */ +int virDomainSetSchedulerParameters (virDomainPtr domain, + virSchedParameterPtr params, + int nparams); + /** * VIR_NODEINFO_MAXCPUS: * @nodeinfo: virNodeInfo instance @@ -302,6 +367,12 @@ int virDomainCoreDump (virDomainPtr domain, int virDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info); +/* + * Return scheduler type in effect 'sedf', 'credit', 'linux' + */ +char * virDomainGetSchedulerType(virDomainPtr domain, + int *nparams); + /* * Dynamic control of domains */ diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index e5496283e1..75578e080f 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -168,6 +168,71 @@ struct _virNodeInfo { }; +/** + * virDomainSchedParameterType: + * + * A scheduler parameter field type + */ +typedef enum { + VIR_DOMAIN_SCHED_FIELD_INT = 1, /* integer case */ + VIR_DOMAIN_SCHED_FIELD_UINT = 2, /* unsigned integer case */ + VIR_DOMAIN_SCHED_FIELD_LLONG = 3, /* long long case */ + VIR_DOMAIN_SCHED_FIELD_ULLONG = 4, /* unsigned long long case */ + VIR_DOMAIN_SCHED_FIELD_DOUBLE = 5, /* double case */ + VIR_DOMAIN_SCHED_FIELD_BOOLEAN = 6 /* boolean(character) case */ +} virSchedParameterType; + +/** + * VIR_DOMAIN_SCHED_FIELD_LENGTH: + * + * Macro providing the field length of virSchedParameter + */ + +#define VIR_DOMAIN_SCHED_FIELD_LENGTH 80 + +/** + * virDomainSchedParameter: + * + * a virDomainSchedParameter is the set of scheduler parameters + */ + +typedef struct _virSchedParameter virSchedParameter; + +struct _virSchedParameter { + char field[VIR_DOMAIN_SCHED_FIELD_LENGTH]; /* parameter name */ + int type; /* parameter type */ + union { + int i; /* data for integer case */ + unsigned int ui; /* data for unsigned integer case */ + long long int l; /* data for long long integer case */ + unsigned long long int ul; /* data for unsigned long long integer case */ + double d; /* data for double case */ + char b; /* data for char case */ + } value; /* parameter value */ +}; + +/** + * virSchedParameterPtr: + * + * a virSchedParameterPtr is a pointer to a virSchedParameter structure. + */ + +typedef virSchedParameter *virSchedParameterPtr; + +/* + * Fetch scheduler parameters, caller allocates 'params' field of size 'nparams' + */ +int virDomainGetSchedulerParameters (virDomainPtr domain, + virSchedParameterPtr params, + int *nparams); + +/* + * Change scheduler parameters + */ +int virDomainSetSchedulerParameters (virDomainPtr domain, + virSchedParameterPtr params, + int nparams); + /** * VIR_NODEINFO_MAXCPUS: * @nodeinfo: virNodeInfo instance @@ -302,6 +367,12 @@ int virDomainCoreDump (virDomainPtr domain, int virDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info); +/* + * Return scheduler type in effect 'sedf', 'credit', 'linux' + */ +char * virDomainGetSchedulerType(virDomainPtr domain, + int *nparams); + /* * Dynamic control of domains */ diff --git a/src/driver.h b/src/driver.h index a287477752..6ed1080ff4 100644 --- a/src/driver.h +++ b/src/driver.h @@ -43,9 +43,9 @@ typedef enum { } virDrvOpenStatus; typedef virDrvOpenStatus - (*virDrvOpen) (virConnectPtr conn, - const char *name, - int flags); + (*virDrvOpen) (virConnectPtr conn, + const char *name, + int flags); typedef int (*virDrvClose) (virConnectPtr conn); typedef const char * @@ -54,7 +54,8 @@ typedef int (*virDrvGetVersion) (virConnectPtr conn, unsigned long *hvVer); typedef int - (*virDrvGetMaxVcpus) (virConnectPtr conn, const char *type); + (*virDrvGetMaxVcpus) (virConnectPtr conn, + const char *type); typedef int (*virDrvNodeGetInfo) (virConnectPtr conn, virNodeInfoPtr info); @@ -123,11 +124,12 @@ typedef int typedef int (*virDrvNumOfDefinedDomains) (virConnectPtr conn); typedef int - (*virDrvDomainCreate) (virDomainPtr dom); + (*virDrvDomainCreate) (virDomainPtr dom); typedef virDomainPtr - (*virDrvDomainDefineXML)(virConnectPtr conn, const char *xml); + (*virDrvDomainDefineXML) (virConnectPtr conn, + const char *xml); typedef int - (*virDrvDomainUndefine) (virDomainPtr dom); + (*virDrvDomainUndefine) (virDomainPtr dom); typedef int (*virDrvDomainSetVcpus) (virDomainPtr domain, unsigned int nvcpus); @@ -157,6 +159,22 @@ typedef int (*virDrvDomainSetAutostart) (virDomainPtr domain, int autostart); +typedef char * + (*virDrvDomainGetSchedulerType) (virDomainPtr domain, + int *nparams); + +typedef int + (*virDrvDomainGetSchedulerParameters) + (virDomainPtr domain, + virSchedParameterPtr params, + int *nparams); + +typedef int + (*virDrvDomainSetSchedulerParameters) + (virDomainPtr domain, + virSchedParameterPtr params, + int nparams); + typedef struct _virDriver virDriver; typedef virDriver *virDriverPtr; @@ -182,7 +200,7 @@ struct _virDriver { virDrvGetVersion version; virDrvGetMaxVcpus getMaxVcpus; virDrvNodeGetInfo nodeGetInfo; - virDrvGetCapabilities getCapabilities; + virDrvGetCapabilities getCapabilities; virDrvListDomains listDomains; virDrvNumOfDomains numOfDomains; virDrvDomainCreateLinux domainCreateLinux; @@ -216,6 +234,9 @@ struct _virDriver { virDrvDomainDetachDevice domainDetachDevice; virDrvDomainGetAutostart domainGetAutostart; virDrvDomainSetAutostart domainSetAutostart; + virDrvDomainGetSchedulerType domainGetSchedulerType; + virDrvDomainGetSchedulerParameters domainGetSchedulerParameters; + virDrvDomainSetSchedulerParameters domainSetSchedulerParameters; }; typedef int @@ -240,7 +261,8 @@ typedef virNetworkPtr (*virDrvNetworkCreateXML) (virConnectPtr conn, const char *xmlDesc); typedef virNetworkPtr - (*virDrvNetworkDefineXML) (virConnectPtr conn, const char *xml); + (*virDrvNetworkDefineXML) (virConnectPtr conn, + const char *xml); typedef int (*virDrvNetworkUndefine) (virNetworkPtr network); typedef int diff --git a/src/libvirt.c b/src/libvirt.c index 9918a9166a..f7a9968ac1 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -1427,6 +1427,118 @@ virConnectGetCapabilities (virConnectPtr conn) return NULL; } +/** + * virDomainGetSchedulerType: + * @domain: pointer to domain object + * @nparams: number of scheduler parameters(return value) + * + * Get the scheduler type. + * + * Returns NULL in case of error. The caller must free the returned string. + */ +char * +virDomainGetSchedulerType(virDomainPtr domain, int *nparams) +{ + virConnectPtr conn; + char *schedtype; + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return NULL; + } + conn = domain->conn; + + if (!VIR_IS_CONNECT (conn)) { + virLibConnError (conn, VIR_ERR_INVALID_CONN, __FUNCTION__); + return NULL; + } + + if (conn->driver->domainGetSchedulerType){ + schedtype = conn->driver->domainGetSchedulerType (domain, nparams); + return schedtype; + } + + virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__); + return NULL; +} + + +/** + * virDomainGetSchedulerParameters: + * @domain: pointer to domain object + * @params: pointer to scheduler parameter object + * (return value) + * @nparams: pointer to number of scheduler parameter + * (this value should be same than the returned value + * nparams of virDomainGetSchedulerType) + * + * Get the scheduler parameters, the @params array will be filled with the + * values. + * + * Returns -1 in case of error, 0 in case of success. + */ +int +virDomainGetSchedulerParameters(virDomainPtr domain, + virSchedParameterPtr params, int *nparams) +{ + virConnectPtr conn; + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return -1; + } + conn = domain->conn; + + if (!VIR_IS_CONNECT (conn)) { + virLibConnError (conn, VIR_ERR_INVALID_CONN, __FUNCTION__); + return -1; + } + + if (conn->driver->domainGetSchedulerParameters) + return conn->driver->domainGetSchedulerParameters (domain, params, nparams); + + virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__); + return -1; +} + +/** + * virDomainSetSchedulerParameters: + * @domain: pointer to domain object + * @params: pointer to scheduler parameter objects + * @nparams: number of scheduler parameter + * (this value should be same or less than the returned value + * nparams of virDomainGetSchedulerType) + * + * Change the scheduler parameters + * + * Returns -1 in case of error, 0 in case of success. + */ +int +virDomainSetSchedulerParameters(virDomainPtr domain, + virSchedParameterPtr params, int nparams) +{ + virConnectPtr conn; + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return -1; + } + conn = domain->conn; + + if (!VIR_IS_CONNECT (conn)) { + virLibConnError (conn, VIR_ERR_INVALID_CONN, __FUNCTION__); + return -1; + } + + if (conn->driver->domainSetSchedulerParameters) + return conn->driver->domainSetSchedulerParameters (domain, params, nparams); + + virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__); + return -1; +} + + + /************************************************************************ * * * Handling of defined but not running domains * diff --git a/src/libvirt_sym.version b/src/libvirt_sym.version index 1d00ad988f..e705bc8a23 100644 --- a/src/libvirt_sym.version +++ b/src/libvirt_sym.version @@ -59,6 +59,9 @@ virDomainPinVcpu; virDomainGetVcpus; virDomainGetMaxVcpus; + virDomainGetSchedulerType; + virDomainGetSchedulerParameters; + virDomainSetSchedulerParameters; virDomainAttachDevice; virDomainDetachDevice; diff --git a/src/proxy_internal.c b/src/proxy_internal.c index 267ffd0719..620cf1f4c1 100644 --- a/src/proxy_internal.c +++ b/src/proxy_internal.c @@ -88,6 +88,9 @@ virDriver xenProxyDriver = { NULL, /* domainDetachDevice */ NULL, /* domainGetAutostart */ NULL, /* domainSetAutostart */ + NULL, /* domainGetSchedulerType */ + NULL, /* domainGetSchedulerParameters */ + NULL, /* domainSetSchedulerParameters */ }; /** diff --git a/src/qemu_internal.c b/src/qemu_internal.c index 6362bf2b3e..4d2e97e976 100644 --- a/src/qemu_internal.c +++ b/src/qemu_internal.c @@ -1350,6 +1350,9 @@ static virDriver qemuDriver = { NULL, /* domainDetachDevice */ qemuDomainGetAutostart, /* domainGetAutostart */ qemuDomainSetAutostart, /* domainSetAutostart */ + NULL, /* domainGetSchedulerType */ + NULL, /* domainGetSchedulerParameters */ + NULL, /* domainSetSchedulerParameters */ }; static virNetworkDriver qemuNetworkDriver = { diff --git a/src/test.c b/src/test.c index c748d2dc8a..ddd64fe1e3 100644 --- a/src/test.c +++ b/src/test.c @@ -132,6 +132,9 @@ static virDriver testDriver = { NULL, /* domainDetachDevice */ NULL, /* domainGetAutostart */ NULL, /* domainSetAutostart */ + NULL, /* domainGetSchedulerType */ + NULL, /* domainGetSchedulerParameters */ + NULL, /* domainSetSchedulerParameters */ }; /* Per-connection private data. */ diff --git a/src/virsh.c b/src/virsh.c index 5725b502e4..de0d6c4aaa 100644 --- a/src/virsh.c +++ b/src/virsh.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -939,6 +940,129 @@ cmdSave(vshControl * ctl, vshCmd * cmd) return ret; } +/* + * "schedinfo" command + */ +static vshCmdInfo info_schedinfo[] = { + {"syntax", "sched "}, + {"help", gettext_noop("show/set scheduler parameters")}, + {"desc", gettext_noop("Show/Set scheduler parameters.")}, + {NULL, NULL} +}; + +static vshCmdOptDef opts_schedinfo[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")}, + {"weight", VSH_OT_INT, VSH_OFLAG_NONE, gettext_noop("weight for XEN_CREDIT")}, + {"cap", VSH_OT_INT, VSH_OFLAG_NONE, gettext_noop("cap for XEN_CREDIT")}, + {NULL, 0, 0, NULL} +}; + +static int +cmdSchedinfo(vshControl * ctl, vshCmd * cmd) +{ + char *schedulertype; + virDomainPtr dom; + virSchedParameterPtr params; + int i, ret; + int nparams = 0; + int nr_inputparams = 0; + int inputparams = 0; + int weightfound = 0; + int weight; + int capfound = 0; + int cap; + char str_weight[] = "weight"; + char str_cap[] = "cap"; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + return FALSE; + + if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL))) + return FALSE; + + /* Currently supports Xen Credit only */ + weight = vshCommandOptInt(cmd, "weight", &weightfound); + if (weightfound) nr_inputparams++; + + cap = vshCommandOptInt(cmd, "cap", &capfound); + if (capfound) nr_inputparams++; + + params = vshMalloc(ctl, sizeof (virSchedParameter) * nr_inputparams); + if (params == NULL) return FALSE; + + if (weightfound) { + strncpy(params[inputparams].field,str_weight,sizeof(str_weight)); + params[inputparams].type = VIR_DOMAIN_SCHED_FIELD_UINT; + params[inputparams].value.ui = weight; + inputparams++; + } + + if (capfound) { + strncpy(params[inputparams].field,str_cap,sizeof(str_cap)); + params[inputparams].type = VIR_DOMAIN_SCHED_FIELD_UINT; + params[inputparams].value.ui = cap; + inputparams++; + } + /* End Currently supports Xen Credit only */ + + assert (inputparams == nr_inputparams); + + /* Set SchedulerParameters */ + if (inputparams > 0) { + ret = virDomainSetSchedulerParameters(dom, params, inputparams); + if (ret == -1) return FALSE; + } + free(params); + + /* Print SchedulerType */ + schedulertype = virDomainGetSchedulerType(dom, &nparams); + if (schedulertype!= NULL){ + vshPrint(ctl, "%-15s %s\n", _("Scheduler:"), + schedulertype); + free(schedulertype); + } else { + vshPrint(ctl, "%-15s %s\n", _("Scheduler:"), _("Unknown")); + return FALSE; + } + + /* Get SchedulerParameters */ + params = vshMalloc(ctl, sizeof(virSchedParameter)* nparams); + for (i = 0; i < nparams; i++){ + params[i].type = 0; + memset (params[i].field, 0, sizeof params[i].field); + } + ret = virDomainGetSchedulerParameters(dom, params, &nparams); + if (ret == -1) return FALSE; + if(nparams){ + for (i = 0; i < nparams; i++){ + switch (params[i].type) { + case VIR_DOMAIN_SCHED_FIELD_INT: + printf("%-15s: %d\n", params[i].field, params[i].value.i); + break; + case VIR_DOMAIN_SCHED_FIELD_UINT: + printf("%-15s: %u\n", params[i].field, params[i].value.ui); + break; + case VIR_DOMAIN_SCHED_FIELD_LLONG: + printf("%-15s: %Ld\n", params[i].field, params[i].value.l); + break; + case VIR_DOMAIN_SCHED_FIELD_ULLONG: + printf("%-15s: %Lu\n", params[i].field, params[i].value.ul); + break; + case VIR_DOMAIN_SCHED_FIELD_DOUBLE: + printf("%-15s: %f\n", params[i].field, params[i].value.d); + break; + case VIR_DOMAIN_SCHED_FIELD_BOOLEAN: + printf("%-15s: %d\n", params[i].field, params[i].value.b); + break; + default: + printf("not implemented scheduler parameter type\n"); + } + } + } + free(params); + return TRUE; +} + /* * "restore" command */ @@ -2592,6 +2716,7 @@ static vshCmdDef commands[] = { {"restore", cmdRestore, opts_restore, info_restore}, {"resume", cmdResume, opts_resume, info_resume}, {"save", cmdSave, opts_save, info_save}, + {"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo}, {"dump", cmdDump, opts_dump, info_dump}, {"shutdown", cmdShutdown, opts_shutdown, info_shutdown}, {"setmem", cmdSetmem, opts_setmem, info_setmem}, diff --git a/src/xen_internal.c b/src/xen_internal.c index a837b7047c..6d7df038e5 100644 --- a/src/xen_internal.c +++ b/src/xen_internal.c @@ -180,6 +180,19 @@ union xen_getdomaininfolist { }; typedef union xen_getdomaininfolist xen_getdomaininfolist; + +struct xen_v2_getschedulerid { + uint32_t sched_id; /* Get Scheduler ID from Xen */ +}; +typedef struct xen_v2_getschedulerid xen_v2_getschedulerid; + + +union xen_getschedulerid { + struct xen_v2_getschedulerid *v2; +}; +typedef union xen_getschedulerid xen_getschedulerid; + + #define XEN_GETDOMAININFOLIST_ALLOC(domlist, size) \ (hypervisor_version < 2 ? \ ((domlist.v0 = malloc(sizeof(xen_v0_getdomaininfo)*(size))) != NULL) : \ @@ -468,6 +481,43 @@ typedef struct xen_v2d5_vcpuinfo xen_v2d5_vcpuinfo; typedef struct xen_v2_setvcpumap xen_v2_getvcpumap; typedef struct xen_v2d5_setvcpumap xen_v2d5_getvcpumap; +/* + * from V2 we get the scheduler information + */ +#define XEN_V2_OP_GETSCHEDULERID 4 + +/* + * from V2 we get the scheduler parameter + */ +#define XEN_V2_OP_SCHEDULER 16 +/* Scheduler types. */ +#define XEN_SCHEDULER_SEDF 4 +#define XEN_SCHEDULER_CREDIT 5 +/* get/set scheduler parameters */ +#define XEN_DOMCTL_SCHEDOP_putinfo 0 +#define XEN_DOMCTL_SCHEDOP_getinfo 1 + +struct xen_v2_setschedinfo { + uint32_t sched_id; + uint32_t cmd; + union { + struct xen_domctl_sched_sedf { + uint64_t period ALIGN_64; + uint64_t slice ALIGN_64; + uint64_t latency ALIGN_64; + uint32_t extratime; + uint32_t weight; + } sedf; + struct xen_domctl_sched_credit { + uint16_t weight; + uint16_t cap; + } credit; + } u; +}; +typedef struct xen_v2_setschedinfo xen_v2_setschedinfo; +typedef struct xen_v2_setschedinfo xen_v2_getschedinfo; + + /* * The hypercall operation structures also have changed on * changeset 86d26e6ec89b @@ -496,6 +546,7 @@ struct xen_op_v2_sys { union { xen_v2_getdomaininfolistop getdomaininfolist; xen_v2s3_getdomaininfolistop getdomaininfolists3; + xen_v2_getschedulerid getschedulerid; uint8_t padding[128]; } u; }; @@ -516,6 +567,8 @@ struct xen_op_v2_dom { xen_v2d5_vcpuinfo getvcpuinfod5; xen_v2_getvcpumap getvcpumap; xen_v2d5_getvcpumap getvcpumapd5; + xen_v2_setschedinfo setschedinfo; + xen_v2_getschedinfo getschedinfo; uint8_t padding[128]; } u; }; @@ -580,6 +633,9 @@ virDriver xenHypervisorDriver = { NULL, /* domainDetachDevice */ NULL, /* domainGetAutostart */ NULL, /* domainSetAutostart */ + xenHypervisorGetSchedulerType, /* domainGetSchedulerType */ + xenHypervisorGetSchedulerParameters, /* domainGetSchedulerParameters */ + xenHypervisorSetSchedulerParameters, /* domainSetSchedulerParameters */ }; #endif /* !PROXY */ @@ -604,6 +660,38 @@ virXenError(virErrorNumber error, const char *info, int value) errmsg, info, NULL, value, 0, errmsg, info); } +/** + * virXenErrorFunc: + * @error: the error number + * @func: the function failing + * @info: extra information string + * @value: extra information number + * + * Handle an error at the xend daemon interface + */ +static void +virXenErrorFunc(virErrorNumber error, const char *func, const char *info, + int value) +{ + char fullinfo[1000] + const char *errmsg; + + if ((error == VIR_ERR_OK) || (in_init != 0)) + return; + + + errmsg = __virErrorMsg(error, info); + if (func != NULL) { + snprintf(fullinfo, 999, "%s: %s", func, info); + fullinfo[999] = 0; + __virRaiseError(NULL, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR, + errmsg, fullinfo, NULL, value, 0, errmsg, fullinfo); + } else { + __virRaiseError(NULL, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR, + errmsg, info, NULL, value, 0, errmsg, info); + } +} + /** * virXenPerror: * @conn: the connection (if available) @@ -739,7 +827,7 @@ xenHypervisorDoV2Sys(int handle, xen_op_v2_sys* op) ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc); if (ret < 0) { - virXenError(VIR_ERR_XEN_CALL, " ioctl ", xen_ioctl_hypercall_cmd); + virXenError(VIR_ERR_XEN_CALL, " sys ioctl ", xen_ioctl_hypercall_cmd); } if (munlock(op, sizeof(dom0_op_t)) < 0) { @@ -893,6 +981,278 @@ virXen_getdomaininfo(int handle, int first_domain, #ifndef PROXY +/** + * xenHypervisorGetSchedulerType: + * @domain: pointer to the Xen Hypervisor block + * @nparams:give a number of scheduler parameters. + * + * Do a low level hypercall to get scheduler type + * + * Returns scheduler name or NULL in case of failure + */ +char * +xenHypervisorGetSchedulerType(virDomainPtr domain, int *nparams) +{ + char *schedulertype = NULL; + xenUnifiedPrivatePtr priv; + + if ((domain == NULL) || (domain->conn == NULL)) { + virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, + "domain or conn is NULL", 0); + return NULL; + } + + priv = (xenUnifiedPrivatePtr) domain->conn->privateData; + if (priv->handle < 0 || domain->id < 0) { + virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, + "priv->handle or domain->id invalid", 0); + return NULL; + } + + /* + * Support only dom_interface_version >=5 + * (Xen3.1.0 or later) + */ + if (dom_interface_version < 5) { + virXenErrorFunc(VIR_ERR_NO_XEN, __FUNCTION__, + "unsupported in dom interface < 5", 0); + return NULL; + } + + if (hypervisor_version > 1) { + xen_op_v2_sys op; + int ret; + + memset(&op, 0, sizeof(op)); + op.cmd = XEN_V2_OP_GETSCHEDULERID; + ret = xenHypervisorDoV2Sys(priv->handle, &op); + if (ret < 0) + return(NULL); + + switch (op.u.getschedulerid.sched_id){ + case XEN_SCHEDULER_SEDF: + schedulertype = strdup("sedf"); + if (nparams) + *nparams = 6; + break; + case XEN_SCHEDULER_CREDIT: + schedulertype = strdup("credit"); + if (nparams) + *nparams = 2; + break; + default: + break; + } + } + + return schedulertype; +} + +/** + * xenHypervisorGetSchedulerParameters: + * @domain: pointer to the Xen Hypervisor block + * @params: pointer to scheduler parameters. + * This memory area should be allocated before calling. + * @nparams:this parameter should be same as + * a given number of scheduler parameters. + * from xenHypervisorGetSchedulerType(). + * + * Do a low level hypercall to get scheduler parameters + * + * Returns 0 or -1 in case of failure + */ +int +xenHypervisorGetSchedulerParameters(virDomainPtr domain, + virSchedParameterPtr params, int *nparams) +{ + xenUnifiedPrivatePtr priv; + char str_weight[] ="weight"; + char str_cap[] ="cap"; + + if ((domain == NULL) || (domain->conn == NULL)) { + virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, + "domain or conn is NULL", 0); + return -1; + } + + priv = (xenUnifiedPrivatePtr) domain->conn->privateData; + if (priv->handle < 0 || domain->id < 0) { + virXenErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, + "priv->handle or domain->id invalid", 0); + return -1; + } + + /* + * Support only dom_interface_version >=5 + * (Xen3.1.0 or later) + * TODO: check on Xen 3.0.3 + */ + if (dom_interface_version < 5) { + virXenErrorFunc(VIR_ERR_NO_XEN, __FUNCTION__, + "unsupported in dom interface < 5", 0); + return -1; + } + + if (hypervisor_version > 1) { + xen_op_v2_sys op_sys; + xen_op_v2_dom op_dom; + int ret; + + memset(&op_sys, 0, sizeof(op_sys)); + op_sys.cmd = XEN_V2_OP_GETSCHEDULERID; + ret = xenHypervisorDoV2Sys(priv->handle, &op_sys); + if (ret < 0) + return -1; + + switch (op_sys.u.getschedulerid.sched_id){ + case XEN_SCHEDULER_SEDF: + /* TODO: Implement for Xen/SEDF */ + TODO + return(-1); + case XEN_SCHEDULER_CREDIT: + if (*nparams < 2) + return(-1); + memset(&op_dom, 0, sizeof(op_dom)); + op_dom.cmd = XEN_V2_OP_SCHEDULER; + op_dom.domain = (domid_t) domain->id; + op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT; + op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_getinfo; + ret = xenHypervisorDoV2Dom(priv->handle, &op_dom); + if (ret < 0) + return(-1); + + strncpy(params[0].field, str_weight, strlen(str_weight)); + params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT; + params[0].value.ui = op_dom.u.getschedinfo.u.credit.weight; + + strncpy(params[1].field, str_cap, strlen(str_cap)); + params[1].type = VIR_DOMAIN_SCHED_FIELD_UINT; + params[1].value.ui = op_dom.u.getschedinfo.u.credit.cap; + + *nparams = 2; + break; + default: + virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, + "Unknown scheduler", op_sys.u.getschedulerid.sched_id); + return -1; + } + } + + return 0; +} + +/** + * xenHypervisorSetSchedulerParameters: + * @domain: pointer to the Xen Hypervisor block + * @nparams:give a number of scheduler setting parameters . + * + * Do a low level hypercall to set scheduler parameters + * + * Returns 0 or -1 in case of failure + */ +int +xenHypervisorSetSchedulerParameters(virDomainPtr domain, + virSchedParameterPtr params, int nparams) +{ + int i; + xenUnifiedPrivatePtr priv; + char str_weight[] ="weight"; + char str_cap[] ="cap"; + + if ((domain == NULL) || (domain->conn == NULL)) { + virXenErrorFunc (VIR_ERR_INTERNAL_ERROR, __FUNCTION__, + "domain or conn is NULL", 0); + return -1; + } + + if ((nparams == 0) || (params == NULL)) { + virXenErrorFunc (VIR_ERR_INVALID_ARG, __FUNCTION__, + "Noparameters given", 0); + return(-1); + } + + priv = (xenUnifiedPrivatePtr) domain->conn->privateData; + if (priv->handle < 0 || domain->id < 0) { + virXenErrorFunc (VIR_ERR_INTERNAL_ERROR, __FUNCTION__, + "priv->handle or domain->id invalid", 0); + return -1; + } + + /* + * Support only dom_interface_version >=5 + * (Xen3.1.0 or later) + * TODO: check on Xen 3.0.3 + */ + if (dom_interface_version < 5) { + virXenError(VIR_ERR_NO_XEN, __FUNCTION__, + "unsupported in dom interface < 5", 0); + return -1; + } + + if (hypervisor_version > 1) { + xen_op_v2_sys op_sys; + xen_op_v2_dom op_dom; + int ret; + + memset(&op_sys, 0, sizeof(op_sys)); + op_sys.cmd = XEN_V2_OP_GETSCHEDULERID; + ret = xenHypervisorDoV2Sys(priv->handle, &op_sys); + if (ret == -1) return -1; + + switch (op_sys.u.getschedulerid.sched_id){ + case XEN_SCHEDULER_SEDF: + /* TODO: Implement for Xen/SEDF */ + TODO + return(-1); + case XEN_SCHEDULER_CREDIT: { + int weight_set = 0; + int cap_set = 0; + + memset(&op_dom, 0, sizeof(op_dom)); + op_dom.cmd = XEN_V2_OP_SCHEDULER; + op_dom.domain = (domid_t) domain->id; + op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT; + op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_putinfo; + + /* + * credit scheduler parameters + * following values do not change the parameters + */ + op_dom.u.getschedinfo.u.credit.weight = 0; + op_dom.u.getschedinfo.u.credit.cap = (uint16_t)~0U; + + for (i = 0; i < nparams; i++) { + if (!strncmp(params[i].field,str_weight,strlen(str_weight)) && + params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) { + op_dom.u.getschedinfo.u.credit.weight = params[i].value.ui; + weight_set = 1; + } else if (!strncmp(params[i].field,str_cap,strlen(str_cap)) && + params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) { + op_dom.u.getschedinfo.u.credit.cap = params[i].value.ui; + cap_set = 1; + } else { + virXenErrorFunc (VIR_ERR_INVALID_ARG, __FUNCTION__, + "Credit scheduler accepts 'cap' and 'weight' integer parameters", + 0); + return(-1); + } + } + + ret = xenHypervisorDoV2Dom(priv->handle, &op_dom); + if (ret < 0) + return -1; + break; + } + default: + virXenErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, + "Unknown scheduler", op_sys.u.getschedulerid.sched_id); + return -1; + } + } + + return 0; +} + /** * virXen_pausedomain: * @handle: the hypervisor handle diff --git a/src/xen_internal.h b/src/xen_internal.h index 339dcaddf5..b77fd27529 100644 --- a/src/xen_internal.h +++ b/src/xen_internal.h @@ -66,6 +66,17 @@ int xenHypervisorGetVcpus (virDomainPtr domain, int maplen); int xenHypervisorGetVcpuMax (virDomainPtr domain); +char * xenHypervisorGetSchedulerType (virDomainPtr domain, + int *nparams); + +int xenHypervisorGetSchedulerParameters (virDomainPtr domain, + virSchedParameterPtr params, + int *nparams); + +int xenHypervisorSetSchedulerParameters (virDomainPtr domain, + virSchedParameterPtr params, + int nparams); + #ifdef __cplusplus } #endif diff --git a/src/xen_unified.c b/src/xen_unified.c index 5c740d8745..8e913aeb19 100644 --- a/src/xen_unified.c +++ b/src/xen_unified.c @@ -775,6 +775,58 @@ xenUnifiedDomainSetAutostart (virDomainPtr dom, int autostart) return -1; } +static char * +xenUnifiedDomainGetSchedulerType (virDomainPtr dom, int *nparams) +{ + GET_PRIVATE(dom->conn); + int i; + char *schedulertype; + + for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; i++) { + if (priv->opened[i] && drivers[i]->domainGetSchedulerType) { + schedulertype = drivers[i]->domainGetSchedulerType (dom, nparams); + if (schedulertype != NULL) + return(schedulertype); + } + } + return(NULL); +} + +static int +xenUnifiedDomainGetSchedulerParameters (virDomainPtr dom, + virSchedParameterPtr params, int *nparams) +{ + GET_PRIVATE(dom->conn); + int i, ret; + + for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) { + if (priv->opened[i] && drivers[i]->domainGetSchedulerParameters) { + ret = drivers[i]->domainGetSchedulerParameters(dom, params, nparams); + if (ret == 0) + return(0); + } + } + return(-1); +} + +static int +xenUnifiedDomainSetSchedulerParameters (virDomainPtr dom, + virSchedParameterPtr params, int nparams) +{ + GET_PRIVATE(dom->conn); + int i, ret; + + for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) { + if (priv->opened[i] && drivers[i]->domainSetSchedulerParameters) { + ret = drivers[i]->domainSetSchedulerParameters(dom, params, nparams); + if (ret == 0) + return 0; + } + } + + return(-1); +} + /*----- Register with libvirt.c, and initialise Xen drivers. -----*/ #define VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 + \ @@ -826,6 +878,9 @@ static virDriver xenUnifiedDriver = { .domainDetachDevice = xenUnifiedDomainDetachDevice, .domainGetAutostart = xenUnifiedDomainGetAutostart, .domainSetAutostart = xenUnifiedDomainSetAutostart, + .domainGetSchedulerType = xenUnifiedDomainGetSchedulerType, + .domainGetSchedulerParameters = xenUnifiedDomainGetSchedulerParameters, + .domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters, }; /** diff --git a/src/xend_internal.c b/src/xend_internal.c index 2e35e08842..44a4b10700 100644 --- a/src/xend_internal.c +++ b/src/xend_internal.c @@ -108,6 +108,9 @@ virDriver xenDaemonDriver = { xenDaemonDetachDevice, /* domainDetachDevice */ NULL, /* domainGetAutostart */ NULL, /* domainSetAutostart */ + NULL, /* domainGetSchedulerType */ + NULL, /* domainGetSchedulerParameters */ + NULL, /* domainSetSchedulerParameters */ }; /** diff --git a/src/xm_internal.c b/src/xm_internal.c index 2ca25cd562..b1580b2f97 100644 --- a/src/xm_internal.c +++ b/src/xm_internal.c @@ -113,6 +113,9 @@ virDriver xenXMDriver = { NULL, /* domainDetachDevice */ NULL, /* domainGetAutostart */ NULL, /* domainSetAutostart */ + NULL, /* domainGetSchedulerType */ + NULL, /* domainGetSchedulerParameters */ + NULL, /* domainSetSchedulerParameters */ }; static void diff --git a/src/xs_internal.c b/src/xs_internal.c index 9cc40759ca..ace3ee0a27 100644 --- a/src/xs_internal.c +++ b/src/xs_internal.c @@ -82,6 +82,9 @@ virDriver xenStoreDriver = { NULL, /* domainDetachDevice */ NULL, /* domainGetAutostart */ NULL, /* domainSetAutostart */ + NULL, /* domainGetSchedulerType */ + NULL, /* domainGetSchedulerParameters */ + NULL, /* domainSetSchedulerParameters */ }; /**