1 /*
2 * Copyright 2009-2017 Citrix Ltd and other contributors
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; version 2.1 only. with the special
7 * exception on linking described in file LICENSE.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 */
14
15 #include <inttypes.h>
16 #include <stdlib.h>
17
18 #include <libxl.h>
19 #include <libxl_utils.h>
20 #include <libxlutil.h>
21
22 #include "xl.h"
23 #include "xl_utils.h"
24 #include "xl_parse.h"
25
sched_domain_get(libxl_scheduler sched,int domid,libxl_domain_sched_params * scinfo)26 static int sched_domain_get(libxl_scheduler sched, int domid,
27 libxl_domain_sched_params *scinfo)
28 {
29 if (libxl_domain_sched_params_get(ctx, domid, scinfo)) {
30 fprintf(stderr, "libxl_domain_sched_params_get failed.\n");
31 return 1;
32 }
33 if (scinfo->sched != sched) {
34 fprintf(stderr, "libxl_domain_sched_params_get returned %s not %s.\n",
35 libxl_scheduler_to_string(scinfo->sched),
36 libxl_scheduler_to_string(sched));
37 return 1;
38 }
39
40 return 0;
41 }
42
sched_domain_set(int domid,const libxl_domain_sched_params * scinfo)43 static int sched_domain_set(int domid, const libxl_domain_sched_params *scinfo)
44 {
45 if (libxl_domain_sched_params_set(ctx, domid, scinfo)) {
46 fprintf(stderr, "libxl_domain_sched_params_set failed.\n");
47 return 1;
48 }
49
50 return 0;
51 }
52
sched_vcpu_get(libxl_scheduler sched,int domid,libxl_vcpu_sched_params * scinfo)53 static int sched_vcpu_get(libxl_scheduler sched, int domid,
54 libxl_vcpu_sched_params *scinfo)
55 {
56 int rc;
57
58 rc = libxl_vcpu_sched_params_get(ctx, domid, scinfo);
59 if (rc) {
60 fprintf(stderr, "libxl_vcpu_sched_params_get failed.\n");
61 exit(EXIT_FAILURE);
62 }
63 if (scinfo->sched != sched) {
64 fprintf(stderr, "libxl_vcpu_sched_params_get returned %s not %s.\n",
65 libxl_scheduler_to_string(scinfo->sched),
66 libxl_scheduler_to_string(sched));
67 return 1;
68 }
69
70 return 0;
71 }
72
sched_vcpu_get_all(libxl_scheduler sched,int domid,libxl_vcpu_sched_params * scinfo)73 static int sched_vcpu_get_all(libxl_scheduler sched, int domid,
74 libxl_vcpu_sched_params *scinfo)
75 {
76 int rc;
77
78 rc = libxl_vcpu_sched_params_get_all(ctx, domid, scinfo);
79 if (rc) {
80 fprintf(stderr, "libxl_vcpu_sched_params_get_all failed.\n");
81 exit(EXIT_FAILURE);
82 }
83 if (scinfo->sched != sched) {
84 fprintf(stderr, "libxl_vcpu_sched_params_get_all returned %s not %s.\n",
85 libxl_scheduler_to_string(scinfo->sched),
86 libxl_scheduler_to_string(sched));
87 return 1;
88 }
89
90 return 0;
91 }
92
sched_vcpu_set(int domid,const libxl_vcpu_sched_params * scinfo)93 static int sched_vcpu_set(int domid, const libxl_vcpu_sched_params *scinfo)
94 {
95 int rc;
96
97 rc = libxl_vcpu_sched_params_set(ctx, domid, scinfo);
98 if (rc) {
99 fprintf(stderr, "libxl_vcpu_sched_params_set failed.\n");
100 exit(EXIT_FAILURE);
101 }
102
103 return 0;
104 }
105
sched_vcpu_set_all(int domid,const libxl_vcpu_sched_params * scinfo)106 static int sched_vcpu_set_all(int domid, const libxl_vcpu_sched_params *scinfo)
107 {
108 int rc;
109
110 rc = libxl_vcpu_sched_params_set_all(ctx, domid, scinfo);
111 if (rc) {
112 fprintf(stderr, "libxl_vcpu_sched_params_set_all failed.\n");
113 exit(EXIT_FAILURE);
114 }
115
116 return 0;
117 }
118
sched_credit_params_set(int poolid,libxl_sched_credit_params * scinfo)119 static int sched_credit_params_set(int poolid, libxl_sched_credit_params *scinfo)
120 {
121 if (libxl_sched_credit_params_set(ctx, poolid, scinfo)) {
122 fprintf(stderr, "libxl_sched_credit_params_set failed.\n");
123 return 1;
124 }
125
126 return 0;
127 }
128
sched_credit_params_get(int poolid,libxl_sched_credit_params * scinfo)129 static int sched_credit_params_get(int poolid, libxl_sched_credit_params *scinfo)
130 {
131 if (libxl_sched_credit_params_get(ctx, poolid, scinfo)) {
132 fprintf(stderr, "libxl_sched_credit_params_get failed.\n");
133 return 1;
134 }
135
136 return 0;
137 }
138
sched_credit_domain_output(int domid)139 static int sched_credit_domain_output(int domid)
140 {
141 char *domname;
142 libxl_domain_sched_params scinfo;
143
144 if (domid < 0) {
145 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
146 return 0;
147 }
148
149 libxl_domain_sched_params_init(&scinfo);
150 if (sched_domain_get(LIBXL_SCHEDULER_CREDIT, domid, &scinfo)) {
151 libxl_domain_sched_params_dispose(&scinfo);
152 return 1;
153 }
154 domname = libxl_domid_to_name(ctx, domid);
155 printf("%-33s %4d %6d %4d\n",
156 domname,
157 domid,
158 scinfo.weight,
159 scinfo.cap);
160 free(domname);
161 libxl_domain_sched_params_dispose(&scinfo);
162 return 0;
163 }
164
sched_credit_pool_output(uint32_t poolid)165 static int sched_credit_pool_output(uint32_t poolid)
166 {
167 libxl_sched_credit_params scparam;
168 char *poolname;
169
170 poolname = libxl_cpupoolid_to_name(ctx, poolid);
171 if (sched_credit_params_get(poolid, &scparam)) {
172 printf("Cpupool %s: [sched params unavailable]\n",
173 poolname);
174 } else {
175 printf("Cpupool %s: tslice=%dms ratelimit=%dus migration-delay=%dus\n",
176 poolname,
177 scparam.tslice_ms,
178 scparam.ratelimit_us,
179 scparam.vcpu_migr_delay_us);
180 }
181 free(poolname);
182 return 0;
183 }
184
sched_credit2_params_set(int poolid,libxl_sched_credit2_params * scinfo)185 static int sched_credit2_params_set(int poolid,
186 libxl_sched_credit2_params *scinfo)
187 {
188 if (libxl_sched_credit2_params_set(ctx, poolid, scinfo)) {
189 fprintf(stderr, "libxl_sched_credit2_params_set failed.\n");
190 return 1;
191 }
192
193 return 0;
194 }
195
sched_credit2_params_get(int poolid,libxl_sched_credit2_params * scinfo)196 static int sched_credit2_params_get(int poolid,
197 libxl_sched_credit2_params *scinfo)
198 {
199 if (libxl_sched_credit2_params_get(ctx, poolid, scinfo)) {
200 fprintf(stderr, "libxl_sched_credit2_params_get failed.\n");
201 return 1;
202 }
203
204 return 0;
205 }
206
sched_credit2_domain_output(int domid)207 static int sched_credit2_domain_output(int domid)
208 {
209 char *domname;
210 libxl_domain_sched_params scinfo;
211
212 if (domid < 0) {
213 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
214 return 0;
215 }
216
217 libxl_domain_sched_params_init(&scinfo);
218 if (sched_domain_get(LIBXL_SCHEDULER_CREDIT2, domid, &scinfo)) {
219 libxl_domain_sched_params_dispose(&scinfo);
220 return 1;
221 }
222 domname = libxl_domid_to_name(ctx, domid);
223 printf("%-33s %4d %6d %4d\n",
224 domname,
225 domid,
226 scinfo.weight,
227 scinfo.cap);
228 free(domname);
229 libxl_domain_sched_params_dispose(&scinfo);
230 return 0;
231 }
232
sched_credit2_pool_output(uint32_t poolid)233 static int sched_credit2_pool_output(uint32_t poolid)
234 {
235 libxl_sched_credit2_params scparam;
236 char *poolname = libxl_cpupoolid_to_name(ctx, poolid);
237
238 if (sched_credit2_params_get(poolid, &scparam))
239 printf("Cpupool %s: [sched params unavailable]\n", poolname);
240 else
241 printf("Cpupool %s: ratelimit=%dus\n",
242 poolname, scparam.ratelimit_us);
243
244 free(poolname);
245
246 return 0;
247 }
248
sched_rtds_domain_output(int domid)249 static int sched_rtds_domain_output(
250 int domid)
251 {
252 char *domname;
253 libxl_domain_sched_params scinfo;
254
255 if (domid < 0) {
256 printf("%-33s %4s %9s %9s %10s\n", "Name", "ID", "Period", "Budget", "Extratime");
257 return 0;
258 }
259
260 libxl_domain_sched_params_init(&scinfo);
261 if (sched_domain_get(LIBXL_SCHEDULER_RTDS, domid, &scinfo)) {
262 libxl_domain_sched_params_dispose(&scinfo);
263 return 1;
264 }
265
266 domname = libxl_domid_to_name(ctx, domid);
267 printf("%-33s %4d %9d %9d %10s\n",
268 domname,
269 domid,
270 scinfo.period,
271 scinfo.budget,
272 scinfo.extratime ? "yes" : "no");
273 free(domname);
274 libxl_domain_sched_params_dispose(&scinfo);
275 return 0;
276 }
277
sched_rtds_vcpu_output(int domid,libxl_vcpu_sched_params * scinfo)278 static int sched_rtds_vcpu_output(int domid, libxl_vcpu_sched_params *scinfo)
279 {
280 char *domname;
281 int rc = 0;
282 int i;
283
284 if (domid < 0) {
285 printf("%-33s %4s %4s %9s %9s %10s\n", "Name", "ID",
286 "VCPU", "Period", "Budget", "Extratime");
287 return 0;
288 }
289
290 rc = sched_vcpu_get(LIBXL_SCHEDULER_RTDS, domid, scinfo);
291 if (rc)
292 return 1;
293
294 domname = libxl_domid_to_name(ctx, domid);
295 for ( i = 0; i < scinfo->num_vcpus; i++ ) {
296 printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32" %10s\n",
297 domname,
298 domid,
299 scinfo->vcpus[i].vcpuid,
300 scinfo->vcpus[i].period,
301 scinfo->vcpus[i].budget,
302 scinfo->vcpus[i].extratime ? "yes" : "no");
303 }
304 free(domname);
305 return 0;
306 }
307
sched_rtds_vcpu_output_all(int domid,libxl_vcpu_sched_params * scinfo)308 static int sched_rtds_vcpu_output_all(int domid,
309 libxl_vcpu_sched_params *scinfo)
310 {
311 char *domname;
312 int rc = 0;
313 int i;
314
315 if (domid < 0) {
316 printf("%-33s %4s %4s %9s %9s %10s\n", "Name", "ID",
317 "VCPU", "Period", "Budget", "Extratime");
318 return 0;
319 }
320
321 scinfo->num_vcpus = 0;
322 rc = sched_vcpu_get_all(LIBXL_SCHEDULER_RTDS, domid, scinfo);
323 if (rc)
324 return 1;
325
326 domname = libxl_domid_to_name(ctx, domid);
327 for ( i = 0; i < scinfo->num_vcpus; i++ ) {
328 printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32" %10s\n",
329 domname,
330 domid,
331 scinfo->vcpus[i].vcpuid,
332 scinfo->vcpus[i].period,
333 scinfo->vcpus[i].budget,
334 scinfo->vcpus[i].extratime ? "yes" : "no");
335 }
336 free(domname);
337 return 0;
338 }
339
sched_rtds_pool_output(uint32_t poolid)340 static int sched_rtds_pool_output(uint32_t poolid)
341 {
342 char *poolname;
343
344 poolname = libxl_cpupoolid_to_name(ctx, poolid);
345 printf("Cpupool %s: sched=RTDS\n", poolname);
346
347 free(poolname);
348 return 0;
349 }
350
sched_domain_output(libxl_scheduler sched,int (* output)(int),int (* pooloutput)(uint32_t),const char * cpupool)351 static int sched_domain_output(libxl_scheduler sched, int (*output)(int),
352 int (*pooloutput)(uint32_t), const char *cpupool)
353 {
354 libxl_dominfo *info;
355 libxl_cpupoolinfo *poolinfo = NULL;
356 uint32_t poolid;
357 int nb_domain, n_pools = 0, i, p;
358 int rc = 0;
359
360 if (cpupool) {
361 if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL) ||
362 !libxl_cpupoolid_is_valid(ctx, poolid)) {
363 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
364 return 1;
365 }
366 }
367
368 info = libxl_list_domain(ctx, &nb_domain);
369 if (!info) {
370 fprintf(stderr, "libxl_list_domain failed.\n");
371 return 1;
372 }
373 poolinfo = libxl_list_cpupool(ctx, &n_pools);
374 if (!poolinfo) {
375 fprintf(stderr, "error getting cpupool info\n");
376 libxl_dominfo_list_free(info, nb_domain);
377 return 1;
378 }
379
380 for (p = 0; !rc && (p < n_pools); p++) {
381 if ((poolinfo[p].sched != sched) ||
382 (cpupool && (poolid != poolinfo[p].poolid)))
383 continue;
384
385 pooloutput(poolinfo[p].poolid);
386
387 output(-1);
388 for (i = 0; i < nb_domain; i++) {
389 if (info[i].cpupool != poolinfo[p].poolid)
390 continue;
391 rc = output(info[i].domid);
392 if (rc)
393 break;
394 }
395 }
396
397 libxl_cpupoolinfo_list_free(poolinfo, n_pools);
398 libxl_dominfo_list_free(info, nb_domain);
399 return 0;
400 }
401
sched_vcpu_output(libxl_scheduler sched,int (* output)(int,libxl_vcpu_sched_params *),int (* pooloutput)(uint32_t),const char * cpupool)402 static int sched_vcpu_output(libxl_scheduler sched,
403 int (*output)(int, libxl_vcpu_sched_params *),
404 int (*pooloutput)(uint32_t), const char *cpupool)
405 {
406 libxl_dominfo *info;
407 libxl_cpupoolinfo *poolinfo = NULL;
408 uint32_t poolid;
409 int nb_domain, n_pools = 0, i, p;
410 int rc = 0;
411
412 if (cpupool) {
413 if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL)
414 || !libxl_cpupoolid_is_valid(ctx, poolid)) {
415 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
416 return 1;
417 }
418 }
419
420 info = libxl_list_domain(ctx, &nb_domain);
421 if (!info) {
422 fprintf(stderr, "libxl_list_domain failed.\n");
423 return 1;
424 }
425 poolinfo = libxl_list_cpupool(ctx, &n_pools);
426 if (!poolinfo) {
427 fprintf(stderr, "error getting cpupool info\n");
428 libxl_dominfo_list_free(info, nb_domain);
429 return 1;
430 }
431
432 for (p = 0; !rc && (p < n_pools); p++) {
433 if ((poolinfo[p].sched != sched) ||
434 (cpupool && (poolid != poolinfo[p].poolid)))
435 continue;
436
437 pooloutput(poolinfo[p].poolid);
438
439 output(-1, NULL);
440 for (i = 0; i < nb_domain; i++) {
441 libxl_vcpu_sched_params scinfo;
442 if (info[i].cpupool != poolinfo[p].poolid)
443 continue;
444 libxl_vcpu_sched_params_init(&scinfo);
445 rc = output(info[i].domid, &scinfo);
446 libxl_vcpu_sched_params_dispose(&scinfo);
447 if (rc)
448 break;
449 }
450 }
451
452 libxl_cpupoolinfo_list_free(poolinfo, n_pools);
453 libxl_dominfo_list_free(info, nb_domain);
454 return 0;
455 }
456
457 /*
458 * <nothing> : List all domain params and sched params from all pools
459 * -d [domid] : List domain params for domain
460 * -d [domid] [params] : Set domain params for domain
461 * -p [pool] : list all domains and sched params for pool
462 * -s : List sched params for poolid 0
463 * -s [params] : Set sched params for poolid 0
464 * -p [pool] -s : List sched params for pool
465 * -p [pool] -s [params] : Set sched params for pool
466 * -p [pool] -d... : Illegal
467 */
main_sched_credit(int argc,char ** argv)468 int main_sched_credit(int argc, char **argv)
469 {
470 const char *dom = NULL;
471 const char *cpupool = NULL;
472 int weight = 256, cap = 0;
473 int tslice = 0, ratelimit = 0, migrdelay = 0;
474 bool opt_w = false, opt_c = false;
475 bool opt_t = false, opt_r = false;
476 bool opt_s = false, opt_m = false;
477 int opt, rc;
478 static struct option opts[] = {
479 {"domain", 1, 0, 'd'},
480 {"weight", 1, 0, 'w'},
481 {"cap", 1, 0, 'c'},
482 {"schedparam", 0, 0, 's'},
483 {"tslice_ms", 1, 0, 't'},
484 {"ratelimit_us", 1, 0, 'r'},
485 {"migration_delay_us", 1, 0, 'm'},
486 {"cpupool", 1, 0, 'p'},
487 COMMON_LONG_OPTS
488 };
489
490 SWITCH_FOREACH_OPT(opt, "d:w:c:p:t:r:m:s", opts, "sched-credit", 0) {
491 case 'd':
492 dom = optarg;
493 break;
494 case 'w':
495 weight = strtol(optarg, NULL, 10);
496 opt_w = true;
497 break;
498 case 'c':
499 cap = strtol(optarg, NULL, 10);
500 opt_c = true;
501 break;
502 case 't':
503 tslice = strtol(optarg, NULL, 10);
504 opt_t = true;
505 break;
506 case 'r':
507 ratelimit = strtol(optarg, NULL, 10);
508 opt_r = true;
509 break;
510 case 'm':
511 migrdelay = strtol(optarg, NULL, 10);
512 opt_m = true;
513 break;
514 case 's':
515 opt_s = true;
516 break;
517 case 'p':
518 cpupool = optarg;
519 break;
520 }
521
522 if ((cpupool || opt_s) && (dom || opt_w || opt_c)) {
523 fprintf(stderr, "Specifying a cpupool or schedparam is not "
524 "allowed with domain options.\n");
525 return EXIT_FAILURE;
526 }
527 if (!dom && (opt_w || opt_c)) {
528 fprintf(stderr, "Must specify a domain.\n");
529 return EXIT_FAILURE;
530 }
531 if (!opt_s && (opt_t || opt_r || opt_m)) {
532 fprintf(stderr, "Must specify schedparam to set schedule "
533 "parameter values.\n");
534 return EXIT_FAILURE;
535 }
536
537 if (opt_s) {
538 libxl_sched_credit_params scparam;
539 uint32_t poolid = 0;
540
541 if (cpupool) {
542 if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
543 &poolid, NULL) ||
544 !libxl_cpupoolid_is_valid(ctx, poolid)) {
545 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
546 return EXIT_FAILURE;
547 }
548 }
549
550 if (!opt_t && !opt_r && !opt_m) { /* Output scheduling parameters */
551 if (sched_credit_pool_output(poolid))
552 return EXIT_FAILURE;
553 } else { /* Set scheduling parameters*/
554 if (sched_credit_params_get(poolid, &scparam))
555 return EXIT_FAILURE;
556
557 if (opt_t)
558 scparam.tslice_ms = tslice;
559
560 if (opt_r)
561 scparam.ratelimit_us = ratelimit;
562
563 if (opt_m)
564 scparam.vcpu_migr_delay_us = migrdelay;
565
566 if (sched_credit_params_set(poolid, &scparam))
567 return EXIT_FAILURE;
568 }
569 } else if (!dom) { /* list all domain's credit scheduler info */
570 if (sched_domain_output(LIBXL_SCHEDULER_CREDIT,
571 sched_credit_domain_output,
572 sched_credit_pool_output,
573 cpupool))
574 return EXIT_FAILURE;
575 } else {
576 uint32_t domid = find_domain(dom);
577
578 if (!opt_w && !opt_c) { /* output credit scheduler info */
579 sched_credit_domain_output(-1);
580 if (sched_credit_domain_output(domid))
581 return EXIT_FAILURE;
582 } else { /* set credit scheduler paramaters */
583 libxl_domain_sched_params scinfo;
584 libxl_domain_sched_params_init(&scinfo);
585 scinfo.sched = LIBXL_SCHEDULER_CREDIT;
586 if (opt_w)
587 scinfo.weight = weight;
588 if (opt_c)
589 scinfo.cap = cap;
590 rc = sched_domain_set(domid, &scinfo);
591 libxl_domain_sched_params_dispose(&scinfo);
592 if (rc)
593 return EXIT_FAILURE;
594 }
595 }
596
597 return EXIT_SUCCESS;
598 }
599
main_sched_credit2(int argc,char ** argv)600 int main_sched_credit2(int argc, char **argv)
601 {
602 const char *dom = NULL;
603 const char *cpupool = NULL;
604 int ratelimit = 0;
605 int weight = 256, cap = 0;
606 bool opt_s = false;
607 bool opt_r = false;
608 bool opt_w = false;
609 bool opt_c = false;
610 int opt, rc;
611 static struct option opts[] = {
612 {"domain", 1, 0, 'd'},
613 {"weight", 1, 0, 'w'},
614 {"cap", 1, 0, 'c'},
615 {"schedparam", 0, 0, 's'},
616 {"ratelimit_us", 1, 0, 'r'},
617 {"cpupool", 1, 0, 'p'},
618 COMMON_LONG_OPTS
619 };
620
621 SWITCH_FOREACH_OPT(opt, "d:w:c:p:r:s", opts, "sched-credit2", 0) {
622 case 'd':
623 dom = optarg;
624 break;
625 case 'w':
626 weight = strtol(optarg, NULL, 10);
627 opt_w = true;
628 break;
629 case 'c':
630 cap = strtol(optarg, NULL, 10);
631 opt_c = true;
632 break;
633 case 's':
634 opt_s = true;
635 break;
636 case 'r':
637 ratelimit = strtol(optarg, NULL, 10);
638 opt_r = true;
639 break;
640 case 'p':
641 cpupool = optarg;
642 break;
643 }
644
645 if (cpupool && (dom || opt_w || opt_c)) {
646 fprintf(stderr, "Specifying a cpupool is not allowed with other "
647 "options.\n");
648 return EXIT_FAILURE;
649 }
650 if (!dom && (opt_w || opt_c)) {
651 fprintf(stderr, "Must specify a domain.\n");
652 return EXIT_FAILURE;
653 }
654
655 if (opt_s) {
656 libxl_sched_credit2_params scparam;
657 uint32_t poolid = 0;
658
659 if (cpupool) {
660 if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
661 &poolid, NULL) ||
662 !libxl_cpupoolid_is_valid(ctx, poolid)) {
663 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
664 return EXIT_FAILURE;
665 }
666 }
667
668 if (!opt_r) { /* Output scheduling parameters */
669 if (sched_credit2_pool_output(poolid))
670 return EXIT_FAILURE;
671 } else { /* Set scheduling parameters (so far, just ratelimit) */
672 scparam.ratelimit_us = ratelimit;
673 if (sched_credit2_params_set(poolid, &scparam))
674 return EXIT_FAILURE;
675 }
676 } else if (!dom) { /* list all domain's credit scheduler info */
677 if (sched_domain_output(LIBXL_SCHEDULER_CREDIT2,
678 sched_credit2_domain_output,
679 sched_credit2_pool_output,
680 cpupool))
681 return EXIT_FAILURE;
682 } else {
683 uint32_t domid = find_domain(dom);
684
685 if (!opt_w && !opt_c) { /* output credit2 scheduler info */
686 sched_credit2_domain_output(-1);
687 if (sched_credit2_domain_output(domid))
688 return EXIT_FAILURE;
689 } else { /* set credit2 scheduler paramaters */
690 libxl_domain_sched_params scinfo;
691 libxl_domain_sched_params_init(&scinfo);
692 scinfo.sched = LIBXL_SCHEDULER_CREDIT2;
693 if (opt_w)
694 scinfo.weight = weight;
695 if (opt_c)
696 scinfo.cap = cap;
697 rc = sched_domain_set(domid, &scinfo);
698 libxl_domain_sched_params_dispose(&scinfo);
699 if (rc)
700 return EXIT_FAILURE;
701 }
702 }
703
704 return EXIT_SUCCESS;
705 }
706
707 /*
708 * <nothing> : List all domain paramters and sched params
709 * -d [domid] : List default domain params for domain
710 * -d [domid] [params] : Set domain params for domain
711 * -d [domid] -v [vcpuid 1] -v [vcpuid 2] ... :
712 * List per-VCPU params for domain
713 * -d [domid] -v all : List all per-VCPU params for domain
714 * -v all : List all per-VCPU params for all domains
715 * -d [domid] -v [vcpuid 1] [params] -v [vcpuid 2] [params] ... :
716 * Set per-VCPU params for domain
717 * -d [domid] -v all [params] : Set all per-VCPU params for domain
718 */
main_sched_rtds(int argc,char ** argv)719 int main_sched_rtds(int argc, char **argv)
720 {
721 const char *dom = NULL;
722 const char *cpupool = NULL;
723 int *vcpus = (int *)xmalloc(sizeof(int)); /* IDs of VCPUs that change */
724 int *periods = (int *)xmalloc(sizeof(int)); /* period is in microsecond */
725 int *budgets = (int *)xmalloc(sizeof(int)); /* budget is in microsecond */
726 bool *extratimes = (bool *)xmalloc(sizeof(bool)); /* extratime is bool */
727 int v_size = 1; /* size of vcpus array */
728 int p_size = 1; /* size of periods array */
729 int b_size = 1; /* size of budgets array */
730 int e_size = 1; /* size of extratimes array */
731 int v_index = 0; /* index in vcpus array */
732 int p_index =0; /* index in periods array */
733 int b_index =0; /* index for in budgets array */
734 int e_index = 0; /* index in extratimes array */
735 bool opt_p = false;
736 bool opt_b = false;
737 bool opt_e = false;
738 bool opt_v = false;
739 bool opt_all = false; /* output per-dom parameters */
740 int opt, i, rc, r;
741 static struct option opts[] = {
742 {"domain", 1, 0, 'd'},
743 {"period", 1, 0, 'p'},
744 {"budget", 1, 0, 'b'},
745 {"extratime", 1, 0, 'e'},
746 {"vcpuid",1, 0, 'v'},
747 {"cpupool", 1, 0, 'c'},
748 COMMON_LONG_OPTS
749 };
750
751 SWITCH_FOREACH_OPT(opt, "d:p:b:e:v:c", opts, "sched-rtds", 0) {
752 case 'd':
753 dom = optarg;
754 break;
755 case 'p':
756 if (p_index >= p_size) {
757 /*
758 * periods array is full
759 * double the array size for new elements
760 */
761 p_size *= 2;
762 periods = xrealloc(periods, p_size);
763 }
764 periods[p_index++] = strtol(optarg, NULL, 10);
765 opt_p = 1;
766 break;
767 case 'b':
768 if (b_index >= b_size) { /* budgets array is full */
769 b_size *= 2;
770 budgets = xrealloc(budgets, b_size);
771 }
772 budgets[b_index++] = strtol(optarg, NULL, 10);
773 opt_b = 1;
774 break;
775 case 'e':
776 if (e_index >= e_size) { /* extratime array is full */
777 e_size *= 2;
778 extratimes = xrealloc(extratimes, e_size);
779 }
780 if (strcmp(optarg, "0") && strcmp(optarg, "1"))
781 {
782 fprintf(stderr, "Invalid extratime.\n");
783 r = EXIT_FAILURE;
784 goto out;
785 }
786 extratimes[e_index++] = strtol(optarg, NULL, 10);
787 opt_e = 1;
788 break;
789 case 'v':
790 if (!strcmp(optarg, "all")) { /* get or set all vcpus of a domain */
791 opt_all = 1;
792 break;
793 }
794 if (v_index >= v_size) { /* vcpus array is full */
795 v_size *= 2;
796 vcpus = xrealloc(vcpus, v_size);
797 }
798 vcpus[v_index++] = strtol(optarg, NULL, 10);
799 opt_v = 1;
800 break;
801 case 'c':
802 cpupool = optarg;
803 break;
804 }
805
806 if (cpupool && (dom || opt_p || opt_b || opt_e || opt_v || opt_all)) {
807 fprintf(stderr, "Specifying a cpupool is not allowed with "
808 "other options.\n");
809 r = EXIT_FAILURE;
810 goto out;
811 }
812 if (!dom && (opt_p || opt_b || opt_e || opt_v)) {
813 fprintf(stderr, "Missing parameters.\n");
814 r = EXIT_FAILURE;
815 goto out;
816 }
817 if (dom && !opt_v && !opt_all && (opt_p || opt_b || opt_e)) {
818 fprintf(stderr, "Must specify VCPU.\n");
819 r = EXIT_FAILURE;
820 goto out;
821 }
822 if (opt_v && opt_all) {
823 fprintf(stderr, "Incorrect VCPU IDs.\n");
824 r = EXIT_FAILURE;
825 goto out;
826 }
827 if (((v_index > b_index) && opt_b) || ((v_index > p_index) && opt_p)
828 || ((v_index > e_index) && opt_e) || p_index != b_index
829 || p_index != e_index ) {
830 fprintf(stderr, "Incorrect number of period, budget and extratime\n");
831 r = EXIT_FAILURE;
832 goto out;
833 }
834
835 if ((!dom) && opt_all) {
836 /* get all domain's per-vcpu rtds scheduler parameters */
837 rc = -sched_vcpu_output(LIBXL_SCHEDULER_RTDS,
838 sched_rtds_vcpu_output_all,
839 sched_rtds_pool_output,
840 cpupool);
841 if (rc) {
842 r = EXIT_FAILURE;
843 goto out;
844 }
845 } else if (!dom && !opt_all) {
846 /* list all domain's default scheduling parameters */
847 rc = -sched_domain_output(LIBXL_SCHEDULER_RTDS,
848 sched_rtds_domain_output,
849 sched_rtds_pool_output,
850 cpupool);
851 if (rc) {
852 r = EXIT_FAILURE;
853 goto out;
854 }
855 } else {
856 uint32_t domid = find_domain(dom);
857 if (!opt_v && !opt_all) { /* output default scheduling parameters */
858 sched_rtds_domain_output(-1);
859 rc = -sched_rtds_domain_output(domid);
860 if (rc) {
861 r = EXIT_FAILURE;
862 goto out;
863 }
864 } else if (!opt_p && !opt_b && !opt_e) {
865 /* get per-vcpu rtds scheduling parameters */
866 libxl_vcpu_sched_params scinfo;
867 libxl_vcpu_sched_params_init(&scinfo);
868 sched_rtds_vcpu_output(-1, &scinfo);
869 scinfo.num_vcpus = v_index;
870 if (v_index > 0) {
871 scinfo.vcpus = (libxl_sched_params *)
872 xmalloc(sizeof(libxl_sched_params) * (v_index));
873 for (i = 0; i < v_index; i++)
874 scinfo.vcpus[i].vcpuid = vcpus[i];
875 rc = -sched_rtds_vcpu_output(domid, &scinfo);
876 } else /* get params for all vcpus */
877 rc = -sched_rtds_vcpu_output_all(domid, &scinfo);
878 libxl_vcpu_sched_params_dispose(&scinfo);
879 if (rc) {
880 r = EXIT_FAILURE;
881 goto out;
882 }
883 } else if (opt_v || opt_all) {
884 /* set per-vcpu rtds scheduling parameters */
885 libxl_vcpu_sched_params scinfo;
886 libxl_vcpu_sched_params_init(&scinfo);
887 scinfo.sched = LIBXL_SCHEDULER_RTDS;
888 if (v_index > 0) {
889 scinfo.num_vcpus = v_index;
890 scinfo.vcpus = (libxl_sched_params *)
891 xmalloc(sizeof(libxl_sched_params) * (v_index));
892 for (i = 0; i < v_index; i++) {
893 scinfo.vcpus[i].vcpuid = vcpus[i];
894 scinfo.vcpus[i].period = periods[i];
895 scinfo.vcpus[i].budget = budgets[i];
896 scinfo.vcpus[i].extratime = extratimes[i] ? 1 : 0;
897 }
898 rc = sched_vcpu_set(domid, &scinfo);
899 } else { /* set params for all vcpus */
900 scinfo.num_vcpus = 1;
901 scinfo.vcpus = (libxl_sched_params *)
902 xmalloc(sizeof(libxl_sched_params));
903 scinfo.vcpus[0].period = periods[0];
904 scinfo.vcpus[0].budget = budgets[0];
905 scinfo.vcpus[0].extratime = extratimes[0] ? 1 : 0;
906 rc = sched_vcpu_set_all(domid, &scinfo);
907 }
908
909 libxl_vcpu_sched_params_dispose(&scinfo);
910 if (rc) {
911 r = EXIT_FAILURE;
912 goto out;
913 }
914 }
915 }
916
917 r = EXIT_SUCCESS;
918 out:
919 free(vcpus);
920 free(periods);
921 free(budgets);
922 free(extratimes);
923 return r;
924 }
925
926 /*
927 * Local variables:
928 * mode: C
929 * c-basic-offset: 4
930 * indent-tabs-mode: nil
931 * End:
932 */
933