19dba6721SSasha Levin #include <kvm/util.h>
29dba6721SSasha Levin #include <kvm/kvm-cmd.h>
32a24f96dSSasha Levin #include <kvm/builtin-list.h>
49dba6721SSasha Levin #include <kvm/kvm.h>
50725673aSSasha Levin #include <kvm/parse-options.h>
64b1addaeSSasha Levin #include <kvm/kvm-ipc.h>
79dba6721SSasha Levin
8076e946eSSasha Levin #include <dirent.h>
99dba6721SSasha Levin #include <stdio.h>
109dba6721SSasha Levin #include <string.h>
119dba6721SSasha Levin #include <signal.h>
121b1577dcSSasha Levin #include <fcntl.h>
131b1577dcSSasha Levin
14076e946eSSasha Levin static bool run;
15076e946eSSasha Levin static bool rootfs;
16076e946eSSasha Levin
170725673aSSasha Levin static const char * const list_usage[] = {
188d2ff5daSWanlong Gao "lkvm list",
190725673aSSasha Levin NULL
200725673aSSasha Levin };
210725673aSSasha Levin
220725673aSSasha Levin static const struct option list_options[] = {
23076e946eSSasha Levin OPT_GROUP("General options:"),
24076e946eSSasha Levin OPT_BOOLEAN('i', "run", &run, "List running instances"),
25076e946eSSasha Levin OPT_BOOLEAN('r', "rootfs", &rootfs, "List rootfs instances"),
260725673aSSasha Levin OPT_END()
270725673aSSasha Levin };
280725673aSSasha Levin
2978c684b1SOsier Yang #define KVM_INSTANCE_RUNNING "running"
305bf27f05SAsias He #define KVM_INSTANCE_PAUSED "paused"
3178c684b1SOsier Yang #define KVM_INSTANCE_SHUTOFF "shut off"
3278c684b1SOsier Yang
kvm_list_help(void)330725673aSSasha Levin void kvm_list_help(void)
340725673aSSasha Levin {
350725673aSSasha Levin usage_with_options(list_usage, list_options);
360725673aSSasha Levin }
370725673aSSasha Levin
get_pid(int sock)384b1addaeSSasha Levin static pid_t get_pid(int sock)
394b1addaeSSasha Levin {
404b1addaeSSasha Levin pid_t pid;
410579e1d7SAsias He int r;
424b1addaeSSasha Levin
430579e1d7SAsias He r = kvm_ipc__send(sock, KVM_IPC_PID);
444b1addaeSSasha Levin if (r < 0)
454b1addaeSSasha Levin return r;
464b1addaeSSasha Levin
474b1addaeSSasha Levin r = read(sock, &pid, sizeof(pid));
484b1addaeSSasha Levin if (r < 0)
494b1addaeSSasha Levin return r;
504b1addaeSSasha Levin
514b1addaeSSasha Levin return pid;
524b1addaeSSasha Levin }
534b1addaeSSasha Levin
get_vmstate(int sock)5408ffc82aSLai Jiangshan int get_vmstate(int sock)
555bf27f05SAsias He {
565bf27f05SAsias He int vmstate;
570579e1d7SAsias He int r;
585bf27f05SAsias He
590579e1d7SAsias He r = kvm_ipc__send(sock, KVM_IPC_VMSTATE);
605bf27f05SAsias He if (r < 0)
615bf27f05SAsias He return r;
625bf27f05SAsias He
635bf27f05SAsias He r = read(sock, &vmstate, sizeof(vmstate));
645bf27f05SAsias He if (r < 0)
655bf27f05SAsias He return r;
665bf27f05SAsias He
675bf27f05SAsias He return vmstate;
685bf27f05SAsias He
695bf27f05SAsias He }
705bf27f05SAsias He
print_guest(const char * name,int sock)714b1addaeSSasha Levin static int print_guest(const char *name, int sock)
729dba6721SSasha Levin {
735bf27f05SAsias He pid_t pid;
745bf27f05SAsias He int vmstate;
755bf27f05SAsias He
765bf27f05SAsias He pid = get_pid(sock);
775bf27f05SAsias He vmstate = get_vmstate(sock);
781b1577dcSSasha Levin
790a56c424SLai Jiangshan if ((int)pid < 0 || vmstate < 0)
8049dca54dSLai Jiangshan return -1;
811b1577dcSSasha Levin
825bf27f05SAsias He if (vmstate == KVM_VMSTATE_PAUSED)
835bf27f05SAsias He printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_PAUSED);
845bf27f05SAsias He else
8578c684b1SOsier Yang printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_RUNNING);
861b1577dcSSasha Levin
87886af5f2SLiming Wang return 0;
889dba6721SSasha Levin }
899dba6721SSasha Levin
kvm_list_running_instances(void)90076e946eSSasha Levin static int kvm_list_running_instances(void)
919dba6721SSasha Levin {
92886af5f2SLiming Wang return kvm__enumerate_instances(print_guest);
939dba6721SSasha Levin }
94076e946eSSasha Levin
kvm_list_rootfs(void)95076e946eSSasha Levin static int kvm_list_rootfs(void)
96076e946eSSasha Levin {
97076e946eSSasha Levin DIR *dir;
98076e946eSSasha Levin struct dirent *dirent;
99076e946eSSasha Levin
100da08dcdbSLai Jiangshan dir = opendir(kvm__get_dir());
101076e946eSSasha Levin if (dir == NULL)
102076e946eSSasha Levin return -1;
103076e946eSSasha Levin
104076e946eSSasha Levin while ((dirent = readdir(dir))) {
105076e946eSSasha Levin if (dirent->d_type == DT_DIR &&
106076e946eSSasha Levin strcmp(dirent->d_name, ".") &&
107076e946eSSasha Levin strcmp(dirent->d_name, ".."))
10878c684b1SOsier Yang printf("%5s %-20s %s\n", "", dirent->d_name, KVM_INSTANCE_SHUTOFF);
109076e946eSSasha Levin }
110076e946eSSasha Levin
111076e946eSSasha Levin return 0;
112076e946eSSasha Levin }
113076e946eSSasha Levin
parse_setup_options(int argc,const char ** argv)114076e946eSSasha Levin static void parse_setup_options(int argc, const char **argv)
115076e946eSSasha Levin {
116076e946eSSasha Levin while (argc != 0) {
117076e946eSSasha Levin argc = parse_options(argc, argv, list_options, list_usage,
118076e946eSSasha Levin PARSE_OPT_STOP_AT_NON_OPTION);
119076e946eSSasha Levin if (argc != 0)
120076e946eSSasha Levin kvm_list_help();
121076e946eSSasha Levin }
122076e946eSSasha Levin }
123076e946eSSasha Levin
kvm_cmd_list(int argc,const char ** argv,const char * prefix)124076e946eSSasha Levin int kvm_cmd_list(int argc, const char **argv, const char *prefix)
125076e946eSSasha Levin {
126*0cf9e1f4SMichael Ellerman int status, r;
127076e946eSSasha Levin
128076e946eSSasha Levin parse_setup_options(argc, argv);
129076e946eSSasha Levin
130076e946eSSasha Levin if (!run && !rootfs)
13184e10404SPekka Enberg run = rootfs = true;
13284e10404SPekka Enberg
13378c684b1SOsier Yang printf("%6s %-20s %s\n", "PID", "NAME", "STATE");
13478c684b1SOsier Yang printf("------------------------------------\n");
135076e946eSSasha Levin
136*0cf9e1f4SMichael Ellerman status = 0;
137*0cf9e1f4SMichael Ellerman
138076e946eSSasha Levin if (run) {
139076e946eSSasha Levin r = kvm_list_running_instances();
140076e946eSSasha Levin if (r < 0)
141076e946eSSasha Levin perror("Error listing instances");
142*0cf9e1f4SMichael Ellerman
143*0cf9e1f4SMichael Ellerman status |= r;
144076e946eSSasha Levin }
145076e946eSSasha Levin
146076e946eSSasha Levin if (rootfs) {
147076e946eSSasha Levin r = kvm_list_rootfs();
148076e946eSSasha Levin if (r < 0)
149076e946eSSasha Levin perror("Error listing rootfs");
150*0cf9e1f4SMichael Ellerman
151*0cf9e1f4SMichael Ellerman status |= r;
152076e946eSSasha Levin }
153076e946eSSasha Levin
154*0cf9e1f4SMichael Ellerman return status;
155076e946eSSasha Levin }
156