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 19076e946eSSasha Levin static bool run; 20076e946eSSasha Levin static bool rootfs; 21076e946eSSasha Levin 220725673aSSasha Levin static const char * const list_usage[] = { 23*8d2ff5daSWanlong Gao "lkvm list", 240725673aSSasha Levin NULL 250725673aSSasha Levin }; 260725673aSSasha Levin 270725673aSSasha Levin static const struct option list_options[] = { 28076e946eSSasha Levin OPT_GROUP("General options:"), 29076e946eSSasha Levin OPT_BOOLEAN('i', "run", &run, "List running instances"), 30076e946eSSasha Levin OPT_BOOLEAN('r', "rootfs", &rootfs, "List rootfs instances"), 310725673aSSasha Levin OPT_END() 320725673aSSasha Levin }; 330725673aSSasha Levin 3478c684b1SOsier Yang #define KVM_INSTANCE_RUNNING "running" 3578c684b1SOsier Yang #define KVM_INSTANCE_SHUTOFF "shut off" 3678c684b1SOsier Yang 370725673aSSasha Levin void kvm_list_help(void) 380725673aSSasha Levin { 390725673aSSasha Levin usage_with_options(list_usage, list_options); 400725673aSSasha Levin } 410725673aSSasha Levin 424b1addaeSSasha Levin static pid_t get_pid(int sock) 434b1addaeSSasha Levin { 444b1addaeSSasha Levin struct pid_cmd cmd = {KVM_IPC_PID, 0}; 454b1addaeSSasha Levin int r; 464b1addaeSSasha Levin pid_t pid; 474b1addaeSSasha Levin 484b1addaeSSasha Levin r = write(sock, &cmd, sizeof(cmd)); 494b1addaeSSasha Levin if (r < 0) 504b1addaeSSasha Levin return r; 514b1addaeSSasha Levin 524b1addaeSSasha Levin r = read(sock, &pid, sizeof(pid)); 534b1addaeSSasha Levin if (r < 0) 544b1addaeSSasha Levin return r; 554b1addaeSSasha Levin 564b1addaeSSasha Levin return pid; 574b1addaeSSasha Levin } 584b1addaeSSasha Levin 594b1addaeSSasha Levin static int print_guest(const char *name, int sock) 609dba6721SSasha Levin { 611b1577dcSSasha Levin char proc_name[PATH_MAX]; 62ebc49f06SSasha Levin char *comm = NULL; 63ebc49f06SSasha Levin FILE *fd; 644b1addaeSSasha Levin pid_t pid = get_pid(sock); 651b1577dcSSasha Levin 66ebc49f06SSasha Levin sprintf(proc_name, "/proc/%d/stat", pid); 67ebc49f06SSasha Levin fd = fopen(proc_name, "r"); 68ebc49f06SSasha Levin if (fd == NULL) 691b1577dcSSasha Levin goto cleanup; 70ebc49f06SSasha Levin if (fscanf(fd, "%*u (%as)", &comm) == 0) 711b1577dcSSasha Levin goto cleanup; 721b1577dcSSasha Levin 7378c684b1SOsier Yang printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_RUNNING); 741b1577dcSSasha Levin 75ebc49f06SSasha Levin free(comm); 76ebc49f06SSasha Levin 77ebc49f06SSasha Levin fclose(fd); 781a0ef251SSasha Levin 79886af5f2SLiming Wang return 0; 801b1577dcSSasha Levin 811b1577dcSSasha Levin cleanup: 82ebc49f06SSasha Levin if (fd) 83ebc49f06SSasha Levin fclose(fd); 84ebc49f06SSasha Levin if (comm) 85ebc49f06SSasha Levin free(comm); 86ebc49f06SSasha Levin 874b1addaeSSasha Levin kvm__remove_socket(name); 88886af5f2SLiming Wang return 0; 899dba6721SSasha Levin } 909dba6721SSasha Levin 91076e946eSSasha Levin static int kvm_list_running_instances(void) 929dba6721SSasha Levin { 93886af5f2SLiming Wang return kvm__enumerate_instances(print_guest); 949dba6721SSasha Levin } 95076e946eSSasha Levin 96076e946eSSasha Levin static int kvm_list_rootfs(void) 97076e946eSSasha Levin { 98076e946eSSasha Levin DIR *dir; 99076e946eSSasha Levin struct dirent *dirent; 100076e946eSSasha Levin 101da08dcdbSLai Jiangshan dir = opendir(kvm__get_dir()); 102076e946eSSasha Levin if (dir == NULL) 103076e946eSSasha Levin return -1; 104076e946eSSasha Levin 105076e946eSSasha Levin while ((dirent = readdir(dir))) { 106076e946eSSasha Levin if (dirent->d_type == DT_DIR && 107076e946eSSasha Levin strcmp(dirent->d_name, ".") && 108076e946eSSasha Levin strcmp(dirent->d_name, "..")) 10978c684b1SOsier Yang printf("%5s %-20s %s\n", "", dirent->d_name, KVM_INSTANCE_SHUTOFF); 110076e946eSSasha Levin } 111076e946eSSasha Levin 112076e946eSSasha Levin return 0; 113076e946eSSasha Levin } 114076e946eSSasha Levin 115076e946eSSasha Levin static void parse_setup_options(int argc, const char **argv) 116076e946eSSasha Levin { 117076e946eSSasha Levin while (argc != 0) { 118076e946eSSasha Levin argc = parse_options(argc, argv, list_options, list_usage, 119076e946eSSasha Levin PARSE_OPT_STOP_AT_NON_OPTION); 120076e946eSSasha Levin if (argc != 0) 121076e946eSSasha Levin kvm_list_help(); 122076e946eSSasha Levin } 123076e946eSSasha Levin } 124076e946eSSasha Levin 125076e946eSSasha Levin int kvm_cmd_list(int argc, const char **argv, const char *prefix) 126076e946eSSasha Levin { 127076e946eSSasha Levin int r; 128076e946eSSasha Levin 129076e946eSSasha Levin parse_setup_options(argc, argv); 130076e946eSSasha Levin 131076e946eSSasha Levin if (!run && !rootfs) 13284e10404SPekka Enberg run = rootfs = true; 13384e10404SPekka Enberg 13478c684b1SOsier Yang printf("%6s %-20s %s\n", "PID", "NAME", "STATE"); 13578c684b1SOsier Yang printf("------------------------------------\n"); 136076e946eSSasha Levin 137076e946eSSasha Levin if (run) { 138076e946eSSasha Levin r = kvm_list_running_instances(); 139076e946eSSasha Levin if (r < 0) 140076e946eSSasha Levin perror("Error listing instances"); 141076e946eSSasha Levin } 142076e946eSSasha Levin 143076e946eSSasha Levin if (rootfs) { 144076e946eSSasha Levin r = kvm_list_rootfs(); 145076e946eSSasha Levin if (r < 0) 146076e946eSSasha Levin perror("Error listing rootfs"); 147076e946eSSasha Levin } 148076e946eSSasha Levin 149076e946eSSasha Levin return 0; 150076e946eSSasha Levin } 151