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