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\n",
176 poolname,
177 scparam.tslice_ms,
178 scparam.ratelimit_us);
179 }
180 free(poolname);
181 return 0;
182 }
183
sched_credit2_params_set(int poolid,libxl_sched_credit2_params * scinfo)184 static int sched_credit2_params_set(int poolid,
185 libxl_sched_credit2_params *scinfo)
186 {
187 if (libxl_sched_credit2_params_set(ctx, poolid, scinfo)) {
188 fprintf(stderr, "libxl_sched_credit2_params_set failed.\n");
189 return 1;
190 }
191
192 return 0;
193 }
194
sched_credit2_params_get(int poolid,libxl_sched_credit2_params * scinfo)195 static int sched_credit2_params_get(int poolid,
196 libxl_sched_credit2_params *scinfo)
197 {
198 if (libxl_sched_credit2_params_get(ctx, poolid, scinfo)) {
199 fprintf(stderr, "libxl_sched_credit2_params_get failed.\n");
200 return 1;
201 }
202
203 return 0;
204 }
205
sched_credit2_domain_output(int domid)206 static int sched_credit2_domain_output(int domid)
207 {
208 char *domname;
209 libxl_domain_sched_params scinfo;
210
211 if (domid < 0) {
212 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
213 return 0;
214 }
215
216 libxl_domain_sched_params_init(&scinfo);
217 if (sched_domain_get(LIBXL_SCHEDULER_CREDIT2, domid, &scinfo)) {
218 libxl_domain_sched_params_dispose(&scinfo);
219 return 1;
220 }
221 domname = libxl_domid_to_name(ctx, domid);
222 printf("%-33s %4d %6d %4d\n",
223 domname,
224 domid,
225 scinfo.weight,
226 scinfo.cap);
227 free(domname);
228 libxl_domain_sched_params_dispose(&scinfo);
229 return 0;
230 }
231
sched_credit2_pool_output(uint32_t poolid)232 static int sched_credit2_pool_output(uint32_t poolid)
233 {
234 libxl_sched_credit2_params scparam;
235 char *poolname = libxl_cpupoolid_to_name(ctx, poolid);
236
237 if (sched_credit2_params_get(poolid, &scparam))
238 printf("Cpupool %s: [sched params unavailable]\n", poolname);
239 else
240 printf("Cpupool %s: ratelimit=%dus\n",
241 poolname, scparam.ratelimit_us);
242
243 free(poolname);
244
245 return 0;
246 }
247
sched_rtds_domain_output(int domid)248 static int sched_rtds_domain_output(
249 int domid)
250 {
251 char *domname;
252 libxl_domain_sched_params scinfo;
253
254 if (domid < 0) {
255 printf("%-33s %4s %9s %9s %10s\n", "Name", "ID", "Period", "Budget", "Extratime");
256 return 0;
257 }
258
259 libxl_domain_sched_params_init(&scinfo);
260 if (sched_domain_get(LIBXL_SCHEDULER_RTDS, domid, &scinfo)) {
261 libxl_domain_sched_params_dispose(&scinfo);
262 return 1;
263 }
264
265 domname = libxl_domid_to_name(ctx, domid);
266 printf("%-33s %4d %9d %9d %10s\n",
267 domname,
268 domid,
269 scinfo.period,
270 scinfo.budget,
271 scinfo.extratime ? "yes" : "no");
272 free(domname);
273 libxl_domain_sched_params_dispose(&scinfo);
274 return 0;
275 }
276
sched_rtds_vcpu_output(int domid,libxl_vcpu_sched_params * scinfo)277 static int sched_rtds_vcpu_output(int domid, libxl_vcpu_sched_params *scinfo)
278 {
279 char *domname;
280 int rc = 0;
281 int i;
282
283 if (domid < 0) {
284 printf("%-33s %4s %4s %9s %9s %10s\n", "Name", "ID",
285 "VCPU", "Period", "Budget", "Extratime");
286 return 0;
287 }
288
289 rc = sched_vcpu_get(LIBXL_SCHEDULER_RTDS, domid, scinfo);
290 if (rc)
291 return 1;
292
293 domname = libxl_domid_to_name(ctx, domid);
294 for ( i = 0; i < scinfo->num_vcpus; i++ ) {
295 printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32" %10s\n",
296 domname,
297 domid,
298 scinfo->vcpus[i].vcpuid,
299 scinfo->vcpus[i].period,
300 scinfo->vcpus[i].budget,
301 scinfo->vcpus[i].extratime ? "yes" : "no");
302 }
303 free(domname);
304 return 0;
305 }
306
sched_rtds_vcpu_output_all(int domid,libxl_vcpu_sched_params * scinfo)307 static int sched_rtds_vcpu_output_all(int domid,
308 libxl_vcpu_sched_params *scinfo)
309 {
310 char *domname;
311 int rc = 0;
312 int i;
313
314 if (domid < 0) {
315 printf("%-33s %4s %4s %9s %9s %10s\n", "Name", "ID",
316 "VCPU", "Period", "Budget", "Extratime");
317 return 0;
318 }
319
320 scinfo->num_vcpus = 0;
321 rc = sched_vcpu_get_all(LIBXL_SCHEDULER_RTDS, domid, scinfo);
322 if (rc)
323 return 1;
324
325 domname = libxl_domid_to_name(ctx, domid);
326 for ( i = 0; i < scinfo->num_vcpus; i++ ) {
327 printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32" %10s\n",
328 domname,
329 domid,
330 scinfo->vcpus[i].vcpuid,
331 scinfo->vcpus[i].period,
332 scinfo->vcpus[i].budget,
333 scinfo->vcpus[i].extratime ? "yes" : "no");
334 }
335 free(domname);
336 return 0;
337 }
338
sched_rtds_pool_output(uint32_t poolid)339 static int sched_rtds_pool_output(uint32_t poolid)
340 {
341 char *poolname;
342
343 poolname = libxl_cpupoolid_to_name(ctx, poolid);
344 printf("Cpupool %s: sched=RTDS\n", poolname);
345
346 free(poolname);
347 return 0;
348 }
349
sched_domain_output(libxl_scheduler sched,int (* output)(int),int (* pooloutput)(uint32_t),const char * cpupool)350 static int sched_domain_output(libxl_scheduler sched, int (*output)(int),
351 int (*pooloutput)(uint32_t), const char *cpupool)
352 {
353 libxl_dominfo *info;
354 libxl_cpupoolinfo *poolinfo = NULL;
355 uint32_t poolid;
356 int nb_domain, n_pools = 0, i, p;
357 int rc = 0;
358
359 if (cpupool) {
360 if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL) ||
361 !libxl_cpupoolid_is_valid(ctx, poolid)) {
362 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
363 return 1;
364 }
365 }
366
367 info = libxl_list_domain(ctx, &nb_domain);
368 if (!info) {
369 fprintf(stderr, "libxl_list_domain failed.\n");
370 return 1;
371 }
372 poolinfo = libxl_list_cpupool(ctx, &n_pools);
373 if (!poolinfo) {
374 fprintf(stderr, "error getting cpupool info\n");
375 libxl_dominfo_list_free(info, nb_domain);
376 return 1;
377 }
378
379 for (p = 0; !rc && (p < n_pools); p++) {
380 if ((poolinfo[p].sched != sched) ||
381 (cpupool && (poolid != poolinfo[p].poolid)))
382 continue;
383
384 pooloutput(poolinfo[p].poolid);
385
386 output(-1);
387 for (i = 0; i < nb_domain; i++) {
388 if (info[i].cpupool != poolinfo[p].poolid)
389 continue;
390 rc = output(info[i].domid);
391 if (rc)
392 break;
393 }
394 }
395
396 libxl_cpupoolinfo_list_free(poolinfo, n_pools);
397 libxl_dominfo_list_free(info, nb_domain);
398 return 0;
399 }
400
sched_vcpu_output(libxl_scheduler sched,int (* output)(int,libxl_vcpu_sched_params *),int (* pooloutput)(uint32_t),const char * cpupool)401 static int sched_vcpu_output(libxl_scheduler sched,
402 int (*output)(int, libxl_vcpu_sched_params *),
403 int (*pooloutput)(uint32_t), const char *cpupool)
404 {
405 libxl_dominfo *info;
406 libxl_cpupoolinfo *poolinfo = NULL;
407 uint32_t poolid;
408 int nb_domain, n_pools = 0, i, p;
409 int rc = 0;
410
411 if (cpupool) {
412 if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL)
413 || !libxl_cpupoolid_is_valid(ctx, poolid)) {
414 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
415 return 1;
416 }
417 }
418
419 info = libxl_list_domain(ctx, &nb_domain);
420 if (!info) {
421 fprintf(stderr, "libxl_list_domain failed.\n");
422 return 1;
423 }
424 poolinfo = libxl_list_cpupool(ctx, &n_pools);
425 if (!poolinfo) {
426 fprintf(stderr, "error getting cpupool info\n");
427 libxl_dominfo_list_free(info, nb_domain);
428 return 1;
429 }
430
431 for (p = 0; !rc && (p < n_pools); p++) {
432 if ((poolinfo[p].sched != sched) ||
433 (cpupool && (poolid != poolinfo[p].poolid)))
434 continue;
435
436 pooloutput(poolinfo[p].poolid);
437
438 output(-1, NULL);
439 for (i = 0; i < nb_domain; i++) {
440 libxl_vcpu_sched_params scinfo;
441 if (info[i].cpupool != poolinfo[p].poolid)
442 continue;
443 libxl_vcpu_sched_params_init(&scinfo);
444 rc = output(info[i].domid, &scinfo);
445 libxl_vcpu_sched_params_dispose(&scinfo);
446 if (rc)
447 break;
448 }
449 }
450
451 libxl_cpupoolinfo_list_free(poolinfo, n_pools);
452 libxl_dominfo_list_free(info, nb_domain);
453 return 0;
454 }
455
456 /*
457 * <nothing> : List all domain params and sched params from all pools
458 * -d [domid] : List domain params for domain
459 * -d [domid] [params] : Set domain params for domain
460 * -p [pool] : list all domains and sched params for pool
461 * -s : List sched params for poolid 0
462 * -s [params] : Set sched params for poolid 0
463 * -p [pool] -s : List sched params for pool
464 * -p [pool] -s [params] : Set sched params for pool
465 * -p [pool] -d... : Illegal
466 */
main_sched_credit(int argc,char ** argv)467 int main_sched_credit(int argc, char **argv)
468 {
469 const char *dom = NULL;
470 const char *cpupool = NULL;
471 int weight = 256, cap = 0;
472 int tslice = 0, ratelimit = 0;
473 bool opt_w = false, opt_c = false;
474 bool opt_t = false, opt_r = false;
475 bool opt_s = false;
476 int opt, rc;
477 static struct option opts[] = {
478 {"domain", 1, 0, 'd'},
479 {"weight", 1, 0, 'w'},
480 {"cap", 1, 0, 'c'},
481 {"schedparam", 0, 0, 's'},
482 {"tslice_ms", 1, 0, 't'},
483 {"ratelimit_us", 1, 0, 'r'},
484 {"cpupool", 1, 0, 'p'},
485 COMMON_LONG_OPTS
486 };
487
488 SWITCH_FOREACH_OPT(opt, "d:w:c:p:t:r:s", opts, "sched-credit", 0) {
489 case 'd':
490 dom = optarg;
491 break;
492 case 'w':
493 weight = strtol(optarg, NULL, 10);
494 opt_w = true;
495 break;
496 case 'c':
497 cap = strtol(optarg, NULL, 10);
498 opt_c = true;
499 break;
500 case 't':
501 tslice = strtol(optarg, NULL, 10);
502 opt_t = true;
503 break;
504 case 'r':
505 ratelimit = strtol(optarg, NULL, 10);
506 opt_r = true;
507 break;
508 case 's':
509 opt_s = true;
510 break;
511 case 'p':
512 cpupool = optarg;
513 break;
514 }
515
516 if ((cpupool || opt_s) && (dom || opt_w || opt_c)) {
517 fprintf(stderr, "Specifying a cpupool or schedparam is not "
518 "allowed with domain options.\n");
519 return EXIT_FAILURE;
520 }
521 if (!dom && (opt_w || opt_c)) {
522 fprintf(stderr, "Must specify a domain.\n");
523 return EXIT_FAILURE;
524 }
525 if (!opt_s && (opt_t || opt_r)) {
526 fprintf(stderr, "Must specify schedparam to set schedule "
527 "parameter values.\n");
528 return EXIT_FAILURE;
529 }
530
531 if (opt_s) {
532 libxl_sched_credit_params scparam;
533 uint32_t poolid = 0;
534
535 if (cpupool) {
536 if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
537 &poolid, NULL) ||
538 !libxl_cpupoolid_is_valid(ctx, poolid)) {
539 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
540 return EXIT_FAILURE;
541 }
542 }
543
544 if (!opt_t && !opt_r) { /* Output scheduling parameters */
545 if (sched_credit_pool_output(poolid))
546 return EXIT_FAILURE;
547 } else { /* Set scheduling parameters*/
548 if (sched_credit_params_get(poolid, &scparam))
549 return EXIT_FAILURE;
550
551 if (opt_t)
552 scparam.tslice_ms = tslice;
553
554 if (opt_r)
555 scparam.ratelimit_us = ratelimit;
556
557 if (sched_credit_params_set(poolid, &scparam))
558 return EXIT_FAILURE;
559 }
560 } else if (!dom) { /* list all domain's credit scheduler info */
561 if (sched_domain_output(LIBXL_SCHEDULER_CREDIT,
562 sched_credit_domain_output,
563 sched_credit_pool_output,
564 cpupool))
565 return EXIT_FAILURE;
566 } else {
567 uint32_t domid = find_domain(dom);
568
569 if (!opt_w && !opt_c) { /* output credit scheduler info */
570 sched_credit_domain_output(-1);
571 if (sched_credit_domain_output(domid))
572 return EXIT_FAILURE;
573 } else { /* set credit scheduler paramaters */
574 libxl_domain_sched_params scinfo;
575 libxl_domain_sched_params_init(&scinfo);
576 scinfo.sched = LIBXL_SCHEDULER_CREDIT;
577 if (opt_w)
578 scinfo.weight = weight;
579 if (opt_c)
580 scinfo.cap = cap;
581 rc = sched_domain_set(domid, &scinfo);
582 libxl_domain_sched_params_dispose(&scinfo);
583 if (rc)
584 return EXIT_FAILURE;
585 }
586 }
587
588 return EXIT_SUCCESS;
589 }
590
main_sched_credit2(int argc,char ** argv)591 int main_sched_credit2(int argc, char **argv)
592 {
593 const char *dom = NULL;
594 const char *cpupool = NULL;
595 int ratelimit = 0;
596 int weight = 256, cap = 0;
597 bool opt_s = false;
598 bool opt_r = false;
599 bool opt_w = false;
600 bool opt_c = false;
601 int opt, rc;
602 static struct option opts[] = {
603 {"domain", 1, 0, 'd'},
604 {"weight", 1, 0, 'w'},
605 {"cap", 1, 0, 'c'},
606 {"schedparam", 0, 0, 's'},
607 {"ratelimit_us", 1, 0, 'r'},
608 {"cpupool", 1, 0, 'p'},
609 COMMON_LONG_OPTS
610 };
611
612 SWITCH_FOREACH_OPT(opt, "d:w:c:p:r:s", opts, "sched-credit2", 0) {
613 case 'd':
614 dom = optarg;
615 break;
616 case 'w':
617 weight = strtol(optarg, NULL, 10);
618 opt_w = true;
619 break;
620 case 'c':
621 cap = strtol(optarg, NULL, 10);
622 opt_c = true;
623 break;
624 case 's':
625 opt_s = true;
626 break;
627 case 'r':
628 ratelimit = strtol(optarg, NULL, 10);
629 opt_r = true;
630 break;
631 case 'p':
632 cpupool = optarg;
633 break;
634 }
635
636 if (cpupool && (dom || opt_w || opt_c)) {
637 fprintf(stderr, "Specifying a cpupool is not allowed with other "
638 "options.\n");
639 return EXIT_FAILURE;
640 }
641 if (!dom && (opt_w || opt_c)) {
642 fprintf(stderr, "Must specify a domain.\n");
643 return EXIT_FAILURE;
644 }
645
646 if (opt_s) {
647 libxl_sched_credit2_params scparam;
648 uint32_t poolid = 0;
649
650 if (cpupool) {
651 if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
652 &poolid, NULL) ||
653 !libxl_cpupoolid_is_valid(ctx, poolid)) {
654 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
655 return EXIT_FAILURE;
656 }
657 }
658
659 if (!opt_r) { /* Output scheduling parameters */
660 if (sched_credit2_pool_output(poolid))
661 return EXIT_FAILURE;
662 } else { /* Set scheduling parameters (so far, just ratelimit) */
663 scparam.ratelimit_us = ratelimit;
664 if (sched_credit2_params_set(poolid, &scparam))
665 return EXIT_FAILURE;
666 }
667 } else if (!dom) { /* list all domain's credit scheduler info */
668 if (sched_domain_output(LIBXL_SCHEDULER_CREDIT2,
669 sched_credit2_domain_output,
670 sched_credit2_pool_output,
671 cpupool))
672 return EXIT_FAILURE;
673 } else {
674 uint32_t domid = find_domain(dom);
675
676 if (!opt_w && !opt_c) { /* output credit2 scheduler info */
677 sched_credit2_domain_output(-1);
678 if (sched_credit2_domain_output(domid))
679 return EXIT_FAILURE;
680 } else { /* set credit2 scheduler paramaters */
681 libxl_domain_sched_params scinfo;
682 libxl_domain_sched_params_init(&scinfo);
683 scinfo.sched = LIBXL_SCHEDULER_CREDIT2;
684 if (opt_w)
685 scinfo.weight = weight;
686 if (opt_c)
687 scinfo.cap = cap;
688 rc = sched_domain_set(domid, &scinfo);
689 libxl_domain_sched_params_dispose(&scinfo);
690 if (rc)
691 return EXIT_FAILURE;
692 }
693 }
694
695 return EXIT_SUCCESS;
696 }
697
698 /*
699 * <nothing> : List all domain paramters and sched params
700 * -d [domid] : List default domain params for domain
701 * -d [domid] [params] : Set domain params for domain
702 * -d [domid] -v [vcpuid 1] -v [vcpuid 2] ... :
703 * List per-VCPU params for domain
704 * -d [domid] -v all : List all per-VCPU params for domain
705 * -v all : List all per-VCPU params for all domains
706 * -d [domid] -v [vcpuid 1] [params] -v [vcpuid 2] [params] ... :
707 * Set per-VCPU params for domain
708 * -d [domid] -v all [params] : Set all per-VCPU params for domain
709 */
main_sched_rtds(int argc,char ** argv)710 int main_sched_rtds(int argc, char **argv)
711 {
712 const char *dom = NULL;
713 const char *cpupool = NULL;
714 int *vcpus = (int *)xmalloc(sizeof(int)); /* IDs of VCPUs that change */
715 int *periods = (int *)xmalloc(sizeof(int)); /* period is in microsecond */
716 int *budgets = (int *)xmalloc(sizeof(int)); /* budget is in microsecond */
717 bool *extratimes = (bool *)xmalloc(sizeof(bool)); /* extratime is bool */
718 int v_size = 1; /* size of vcpus array */
719 int p_size = 1; /* size of periods array */
720 int b_size = 1; /* size of budgets array */
721 int e_size = 1; /* size of extratimes array */
722 int v_index = 0; /* index in vcpus array */
723 int p_index =0; /* index in periods array */
724 int b_index =0; /* index for in budgets array */
725 int e_index = 0; /* index in extratimes array */
726 bool opt_p = false;
727 bool opt_b = false;
728 bool opt_e = false;
729 bool opt_v = false;
730 bool opt_all = false; /* output per-dom parameters */
731 int opt, i, rc, r;
732 static struct option opts[] = {
733 {"domain", 1, 0, 'd'},
734 {"period", 1, 0, 'p'},
735 {"budget", 1, 0, 'b'},
736 {"extratime", 1, 0, 'e'},
737 {"vcpuid",1, 0, 'v'},
738 {"cpupool", 1, 0, 'c'},
739 COMMON_LONG_OPTS
740 };
741
742 SWITCH_FOREACH_OPT(opt, "d:p:b:e:v:c", opts, "sched-rtds", 0) {
743 case 'd':
744 dom = optarg;
745 break;
746 case 'p':
747 if (p_index >= p_size) {
748 /*
749 * periods array is full
750 * double the array size for new elements
751 */
752 p_size *= 2;
753 periods = xrealloc(periods, p_size);
754 }
755 periods[p_index++] = strtol(optarg, NULL, 10);
756 opt_p = 1;
757 break;
758 case 'b':
759 if (b_index >= b_size) { /* budgets array is full */
760 b_size *= 2;
761 budgets = xrealloc(budgets, b_size);
762 }
763 budgets[b_index++] = strtol(optarg, NULL, 10);
764 opt_b = 1;
765 break;
766 case 'e':
767 if (e_index >= e_size) { /* extratime array is full */
768 e_size *= 2;
769 extratimes = xrealloc(extratimes, e_size);
770 }
771 if (strcmp(optarg, "0") && strcmp(optarg, "1"))
772 {
773 fprintf(stderr, "Invalid extratime.\n");
774 r = EXIT_FAILURE;
775 goto out;
776 }
777 extratimes[e_index++] = strtol(optarg, NULL, 10);
778 opt_e = 1;
779 break;
780 case 'v':
781 if (!strcmp(optarg, "all")) { /* get or set all vcpus of a domain */
782 opt_all = 1;
783 break;
784 }
785 if (v_index >= v_size) { /* vcpus array is full */
786 v_size *= 2;
787 vcpus = xrealloc(vcpus, v_size);
788 }
789 vcpus[v_index++] = strtol(optarg, NULL, 10);
790 opt_v = 1;
791 break;
792 case 'c':
793 cpupool = optarg;
794 break;
795 }
796
797 if (cpupool && (dom || opt_p || opt_b || opt_e || opt_v || opt_all)) {
798 fprintf(stderr, "Specifying a cpupool is not allowed with "
799 "other options.\n");
800 r = EXIT_FAILURE;
801 goto out;
802 }
803 if (!dom && (opt_p || opt_b || opt_e || opt_v)) {
804 fprintf(stderr, "Missing parameters.\n");
805 r = EXIT_FAILURE;
806 goto out;
807 }
808 if (dom && !opt_v && !opt_all && (opt_p || opt_b || opt_e)) {
809 fprintf(stderr, "Must specify VCPU.\n");
810 r = EXIT_FAILURE;
811 goto out;
812 }
813 if (opt_v && opt_all) {
814 fprintf(stderr, "Incorrect VCPU IDs.\n");
815 r = EXIT_FAILURE;
816 goto out;
817 }
818 if (((v_index > b_index) && opt_b) || ((v_index > p_index) && opt_p)
819 || ((v_index > e_index) && opt_e) || p_index != b_index
820 || p_index != e_index ) {
821 fprintf(stderr, "Incorrect number of period, budget and extratime\n");
822 r = EXIT_FAILURE;
823 goto out;
824 }
825
826 if ((!dom) && opt_all) {
827 /* get all domain's per-vcpu rtds scheduler parameters */
828 rc = -sched_vcpu_output(LIBXL_SCHEDULER_RTDS,
829 sched_rtds_vcpu_output_all,
830 sched_rtds_pool_output,
831 cpupool);
832 if (rc) {
833 r = EXIT_FAILURE;
834 goto out;
835 }
836 } else if (!dom && !opt_all) {
837 /* list all domain's default scheduling parameters */
838 rc = -sched_domain_output(LIBXL_SCHEDULER_RTDS,
839 sched_rtds_domain_output,
840 sched_rtds_pool_output,
841 cpupool);
842 if (rc) {
843 r = EXIT_FAILURE;
844 goto out;
845 }
846 } else {
847 uint32_t domid = find_domain(dom);
848 if (!opt_v && !opt_all) { /* output default scheduling parameters */
849 sched_rtds_domain_output(-1);
850 rc = -sched_rtds_domain_output(domid);
851 if (rc) {
852 r = EXIT_FAILURE;
853 goto out;
854 }
855 } else if (!opt_p && !opt_b && !opt_e) {
856 /* get per-vcpu rtds scheduling parameters */
857 libxl_vcpu_sched_params scinfo;
858 libxl_vcpu_sched_params_init(&scinfo);
859 sched_rtds_vcpu_output(-1, &scinfo);
860 scinfo.num_vcpus = v_index;
861 if (v_index > 0) {
862 scinfo.vcpus = (libxl_sched_params *)
863 xmalloc(sizeof(libxl_sched_params) * (v_index));
864 for (i = 0; i < v_index; i++)
865 scinfo.vcpus[i].vcpuid = vcpus[i];
866 rc = -sched_rtds_vcpu_output(domid, &scinfo);
867 } else /* get params for all vcpus */
868 rc = -sched_rtds_vcpu_output_all(domid, &scinfo);
869 libxl_vcpu_sched_params_dispose(&scinfo);
870 if (rc) {
871 r = EXIT_FAILURE;
872 goto out;
873 }
874 } else if (opt_v || opt_all) {
875 /* set per-vcpu rtds scheduling parameters */
876 libxl_vcpu_sched_params scinfo;
877 libxl_vcpu_sched_params_init(&scinfo);
878 scinfo.sched = LIBXL_SCHEDULER_RTDS;
879 if (v_index > 0) {
880 scinfo.num_vcpus = v_index;
881 scinfo.vcpus = (libxl_sched_params *)
882 xmalloc(sizeof(libxl_sched_params) * (v_index));
883 for (i = 0; i < v_index; i++) {
884 scinfo.vcpus[i].vcpuid = vcpus[i];
885 scinfo.vcpus[i].period = periods[i];
886 scinfo.vcpus[i].budget = budgets[i];
887 scinfo.vcpus[i].extratime = extratimes[i] ? 1 : 0;
888 }
889 rc = sched_vcpu_set(domid, &scinfo);
890 } else { /* set params for all vcpus */
891 scinfo.num_vcpus = 1;
892 scinfo.vcpus = (libxl_sched_params *)
893 xmalloc(sizeof(libxl_sched_params));
894 scinfo.vcpus[0].period = periods[0];
895 scinfo.vcpus[0].budget = budgets[0];
896 scinfo.vcpus[0].extratime = extratimes[0] ? 1 : 0;
897 rc = sched_vcpu_set_all(domid, &scinfo);
898 }
899
900 libxl_vcpu_sched_params_dispose(&scinfo);
901 if (rc) {
902 r = EXIT_FAILURE;
903 goto out;
904 }
905 }
906 }
907
908 r = EXIT_SUCCESS;
909 out:
910 free(vcpus);
911 free(periods);
912 free(budgets);
913 free(extratimes);
914 return r;
915 }
916
917 /*
918 * Local variables:
919 * mode: C
920 * c-basic-offset: 4
921 * indent-tabs-mode: nil
922 * End:
923 */
924