xref: /kvmtool/builtin-list.c (revision 5bf27f057f78e79fe3bc08cec7cf7ad97980135c)
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 
144b1addaeSSasha Levin struct pid_cmd {
154b1addaeSSasha Levin 	u32 type;
164b1addaeSSasha Levin 	u32 len;
174b1addaeSSasha Levin };
184b1addaeSSasha Levin 
19*5bf27f05SAsias He struct vmstate_cmd {
20*5bf27f05SAsias He 	u32 type;
21*5bf27f05SAsias He 	u32 len;
22*5bf27f05SAsias He };
23*5bf27f05SAsias He 
24076e946eSSasha Levin static bool run;
25076e946eSSasha Levin static bool rootfs;
26076e946eSSasha Levin 
270725673aSSasha Levin static const char * const list_usage[] = {
288d2ff5daSWanlong Gao 	"lkvm list",
290725673aSSasha Levin 	NULL
300725673aSSasha Levin };
310725673aSSasha Levin 
320725673aSSasha Levin static const struct option list_options[] = {
33076e946eSSasha Levin 	OPT_GROUP("General options:"),
34076e946eSSasha Levin 	OPT_BOOLEAN('i', "run", &run, "List running instances"),
35076e946eSSasha Levin 	OPT_BOOLEAN('r', "rootfs", &rootfs, "List rootfs instances"),
360725673aSSasha Levin 	OPT_END()
370725673aSSasha Levin };
380725673aSSasha Levin 
3978c684b1SOsier Yang #define KVM_INSTANCE_RUNNING	"running"
40*5bf27f05SAsias He #define KVM_INSTANCE_PAUSED	"paused"
4178c684b1SOsier Yang #define KVM_INSTANCE_SHUTOFF	"shut off"
4278c684b1SOsier Yang 
430725673aSSasha Levin void kvm_list_help(void)
440725673aSSasha Levin {
450725673aSSasha Levin 	usage_with_options(list_usage, list_options);
460725673aSSasha Levin }
470725673aSSasha Levin 
484b1addaeSSasha Levin static pid_t get_pid(int sock)
494b1addaeSSasha Levin {
504b1addaeSSasha Levin 	struct pid_cmd cmd = {KVM_IPC_PID, 0};
514b1addaeSSasha Levin 	int r;
524b1addaeSSasha Levin 	pid_t pid;
534b1addaeSSasha Levin 
544b1addaeSSasha Levin 	r = write(sock, &cmd, sizeof(cmd));
554b1addaeSSasha Levin 	if (r < 0)
564b1addaeSSasha Levin 		return r;
574b1addaeSSasha Levin 
584b1addaeSSasha Levin 	r = read(sock, &pid, sizeof(pid));
594b1addaeSSasha Levin 	if (r < 0)
604b1addaeSSasha Levin 		return r;
614b1addaeSSasha Levin 
624b1addaeSSasha Levin 	return pid;
634b1addaeSSasha Levin }
644b1addaeSSasha Levin 
65*5bf27f05SAsias He static int get_vmstate(int sock)
66*5bf27f05SAsias He {
67*5bf27f05SAsias He 	struct vmstate_cmd cmd = {KVM_IPC_VMSTATE, 0};
68*5bf27f05SAsias He 	int r;
69*5bf27f05SAsias He 	int vmstate;
70*5bf27f05SAsias He 
71*5bf27f05SAsias He 	r = write(sock, &cmd, sizeof(cmd));
72*5bf27f05SAsias He 	if (r < 0)
73*5bf27f05SAsias He 		return r;
74*5bf27f05SAsias He 
75*5bf27f05SAsias He 	r = read(sock, &vmstate, sizeof(vmstate));
76*5bf27f05SAsias He 	if (r < 0)
77*5bf27f05SAsias He 		return r;
78*5bf27f05SAsias He 
79*5bf27f05SAsias He 	return vmstate;
80*5bf27f05SAsias He 
81*5bf27f05SAsias He }
82*5bf27f05SAsias He 
834b1addaeSSasha Levin static int print_guest(const char *name, int sock)
849dba6721SSasha Levin {
851b1577dcSSasha Levin 	char proc_name[PATH_MAX];
86ebc49f06SSasha Levin 	char *comm = NULL;
87ebc49f06SSasha Levin 	FILE *fd;
88*5bf27f05SAsias He 	pid_t pid;
89*5bf27f05SAsias He 	int vmstate;
90*5bf27f05SAsias He 
91*5bf27f05SAsias He 	pid = get_pid(sock);
92*5bf27f05SAsias He 	vmstate = get_vmstate(sock);
931b1577dcSSasha Levin 
94ebc49f06SSasha Levin 	sprintf(proc_name, "/proc/%d/stat", pid);
95ebc49f06SSasha Levin 	fd = fopen(proc_name, "r");
96ebc49f06SSasha Levin 	if (fd == NULL)
971b1577dcSSasha Levin 		goto cleanup;
98ebc49f06SSasha Levin 	if (fscanf(fd, "%*u (%as)", &comm) == 0)
991b1577dcSSasha Levin 		goto cleanup;
1001b1577dcSSasha Levin 
101*5bf27f05SAsias He 	if (vmstate == KVM_VMSTATE_PAUSED)
102*5bf27f05SAsias He 		printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_PAUSED);
103*5bf27f05SAsias He 	else
10478c684b1SOsier Yang 		printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_RUNNING);
1051b1577dcSSasha Levin 
106ebc49f06SSasha Levin 	free(comm);
107ebc49f06SSasha Levin 
108ebc49f06SSasha Levin 	fclose(fd);
1091a0ef251SSasha Levin 
110886af5f2SLiming Wang 	return 0;
1111b1577dcSSasha Levin 
1121b1577dcSSasha Levin cleanup:
113ebc49f06SSasha Levin 	if (fd)
114ebc49f06SSasha Levin 		fclose(fd);
115ebc49f06SSasha Levin 	if (comm)
116ebc49f06SSasha Levin 		free(comm);
117ebc49f06SSasha Levin 
1184b1addaeSSasha Levin 	kvm__remove_socket(name);
119886af5f2SLiming Wang 	return 0;
1209dba6721SSasha Levin }
1219dba6721SSasha Levin 
122076e946eSSasha Levin static int kvm_list_running_instances(void)
1239dba6721SSasha Levin {
124886af5f2SLiming Wang 	return kvm__enumerate_instances(print_guest);
1259dba6721SSasha Levin }
126076e946eSSasha Levin 
127076e946eSSasha Levin static int kvm_list_rootfs(void)
128076e946eSSasha Levin {
129076e946eSSasha Levin 	DIR *dir;
130076e946eSSasha Levin 	struct dirent *dirent;
131076e946eSSasha Levin 
132da08dcdbSLai Jiangshan 	dir = opendir(kvm__get_dir());
133076e946eSSasha Levin 	if (dir == NULL)
134076e946eSSasha Levin 		return -1;
135076e946eSSasha Levin 
136076e946eSSasha Levin 	while ((dirent = readdir(dir))) {
137076e946eSSasha Levin 		if (dirent->d_type == DT_DIR &&
138076e946eSSasha Levin 			strcmp(dirent->d_name, ".") &&
139076e946eSSasha Levin 			strcmp(dirent->d_name, ".."))
14078c684b1SOsier Yang 			printf("%5s %-20s %s\n", "", dirent->d_name, KVM_INSTANCE_SHUTOFF);
141076e946eSSasha Levin 	}
142076e946eSSasha Levin 
143076e946eSSasha Levin 	return 0;
144076e946eSSasha Levin }
145076e946eSSasha Levin 
146076e946eSSasha Levin static void parse_setup_options(int argc, const char **argv)
147076e946eSSasha Levin {
148076e946eSSasha Levin 	while (argc != 0) {
149076e946eSSasha Levin 		argc = parse_options(argc, argv, list_options, list_usage,
150076e946eSSasha Levin 				PARSE_OPT_STOP_AT_NON_OPTION);
151076e946eSSasha Levin 		if (argc != 0)
152076e946eSSasha Levin 			kvm_list_help();
153076e946eSSasha Levin 	}
154076e946eSSasha Levin }
155076e946eSSasha Levin 
156076e946eSSasha Levin int kvm_cmd_list(int argc, const char **argv, const char *prefix)
157076e946eSSasha Levin {
158076e946eSSasha Levin 	int r;
159076e946eSSasha Levin 
160076e946eSSasha Levin 	parse_setup_options(argc, argv);
161076e946eSSasha Levin 
162076e946eSSasha Levin 	if (!run && !rootfs)
16384e10404SPekka Enberg 		run = rootfs = true;
16484e10404SPekka Enberg 
16578c684b1SOsier Yang 	printf("%6s %-20s %s\n", "PID", "NAME", "STATE");
16678c684b1SOsier Yang 	printf("------------------------------------\n");
167076e946eSSasha Levin 
168076e946eSSasha Levin 	if (run) {
169076e946eSSasha Levin 		r = kvm_list_running_instances();
170076e946eSSasha Levin 		if (r < 0)
171076e946eSSasha Levin 			perror("Error listing instances");
172076e946eSSasha Levin 	}
173076e946eSSasha Levin 
174076e946eSSasha Levin 	if (rootfs) {
175076e946eSSasha Levin 		r = kvm_list_rootfs();
176076e946eSSasha Levin 		if (r < 0)
177076e946eSSasha Levin 			perror("Error listing rootfs");
178076e946eSSasha Levin 	}
179076e946eSSasha Levin 
180076e946eSSasha Levin 	return 0;
181076e946eSSasha Levin }
182