1 /*
2  * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
3  */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <err.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <xenctrl.h>
12 
13 #include <xen/errno.h>
14 #include <xen-tools/libs.h>
15 
16 static xc_interface *xch;
17 
18 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
19 
show_help(void)20 void show_help(void)
21 {
22     fprintf(stderr,
23             "xen-diag: xen diagnostic utility\n"
24             "Usage: xen-diag command [args]\n"
25             "Commands:\n"
26             "  help                       display this help\n"
27             "  gnttab_query_size <domid>  dump the current and max grant frames for <domid>\n");
28 }
29 
30 /* wrapper function */
help_func(int argc,char * argv[])31 static int help_func(int argc, char *argv[])
32 {
33     show_help();
34     return 0;
35 }
36 
gnttab_query_size_func(int argc,char * argv[])37 static int gnttab_query_size_func(int argc, char *argv[])
38 {
39     int domid, rc = 1;
40     struct gnttab_query_size query;
41 
42     if ( argc != 1 )
43     {
44         show_help();
45         return rc;
46     }
47 
48     domid = strtol(argv[0], NULL, 10);
49     query.dom = domid;
50     rc = xc_gnttab_query_size(xch, &query);
51 
52     if ( rc == 0 && (query.status == GNTST_okay) )
53         printf("domid=%d: nr_frames=%d, max_nr_frames=%d\n",
54                query.dom, query.nr_frames, query.max_nr_frames);
55 
56     return rc == 0 && (query.status == GNTST_okay) ? 0 : 1;
57 }
58 
59 struct {
60     const char *name;
61     int (*function)(int argc, char *argv[]);
62 } main_options[] = {
63     { "help", help_func },
64     { "gnttab_query_size", gnttab_query_size_func},
65 };
66 
main(int argc,char * argv[])67 int main(int argc, char *argv[])
68 {
69     int ret, i;
70 
71     /*
72      * Set stdout to be unbuffered to avoid having to fflush when
73      * printing without a newline.
74      */
75     setvbuf(stdout, NULL, _IONBF, 0);
76 
77     if ( argc <= 1 )
78     {
79         show_help();
80         return 0;
81     }
82 
83     for ( i = 0; i < ARRAY_SIZE(main_options); i++ )
84         if ( !strncmp(main_options[i].name, argv[1], strlen(argv[1])) )
85             break;
86 
87     if ( i == ARRAY_SIZE(main_options) )
88     {
89         show_help();
90         return 0;
91     }
92     else
93     {
94         xch = xc_interface_open(0, 0, 0);
95         if ( !xch )
96         {
97             fprintf(stderr, "failed to get the handler\n");
98             return 0;
99         }
100 
101         ret = main_options[i].function(argc - 2, argv + 2);
102 
103         xc_interface_close(xch);
104     }
105 
106     /*
107      * Exitcode 0 for success.
108      * Exitcode 1 for an error.
109      * Exitcode 2 if the operation should be retried for any reason (e.g. a
110      * timeout or because another operation was in progress).
111      */
112 
113 #define EXIT_TIMEOUT (EXIT_FAILURE + 1)
114 
115     BUILD_BUG_ON(EXIT_SUCCESS != 0);
116     BUILD_BUG_ON(EXIT_FAILURE != 1);
117     BUILD_BUG_ON(EXIT_TIMEOUT != 2);
118 
119     switch ( ret )
120     {
121     case 0:
122         return EXIT_SUCCESS;
123     case EAGAIN:
124     case EBUSY:
125         return EXIT_TIMEOUT;
126     default:
127         return EXIT_FAILURE;
128     }
129 }
130