1e3aff4f6Saliguori /* 2e3aff4f6Saliguori * Command line utility to exercise the QEMU I/O path. 3e3aff4f6Saliguori * 4e3aff4f6Saliguori * Copyright (C) 2009 Red Hat, Inc. 5e3aff4f6Saliguori * Copyright (c) 2003-2005 Silicon Graphics, Inc. 6e3aff4f6Saliguori * 7e3aff4f6Saliguori * This work is licensed under the terms of the GNU GPL, version 2 or later. 8e3aff4f6Saliguori * See the COPYING file in the top-level directory. 9e3aff4f6Saliguori */ 10c32d766aSStefan Weil #include <sys/time.h> 11e3aff4f6Saliguori #include <sys/types.h> 12e3aff4f6Saliguori #include <stdarg.h> 13e3aff4f6Saliguori #include <stdio.h> 14e3aff4f6Saliguori #include <getopt.h> 15c32d766aSStefan Weil #include <libgen.h> 16e3aff4f6Saliguori 173d21994fSKevin Wolf #include "qemu-io.h" 181de7afc9SPaolo Bonzini #include "qemu/main-loop.h" 19737e150eSPaolo Bonzini #include "block/block_int.h" 20d7bb72c8SStefan Hajnoczi #include "trace/control.h" 21e3aff4f6Saliguori 22e3aff4f6Saliguori #define CMD_NOFILE_OK 0x01 23e3aff4f6Saliguori 24e3aff4f6Saliguori char *progname; 25e3aff4f6Saliguori 26734c3b85SKevin Wolf BlockDriverState *qemuio_bs; 27797ac58cSKevin Wolf extern int qemuio_misalign; 28191c2890SKevin Wolf 29d1174f13SKevin Wolf /* qemu-io commands passed using -c */ 30d1174f13SKevin Wolf static int ncmdline; 31d1174f13SKevin Wolf static char **cmdline; 32d1174f13SKevin Wolf 33734c3b85SKevin Wolf static int close_f(BlockDriverState *bs, int argc, char **argv) 34e3aff4f6Saliguori { 35b4657855SStefan Hajnoczi bdrv_delete(bs); 36734c3b85SKevin Wolf qemuio_bs = NULL; 37e3aff4f6Saliguori return 0; 38e3aff4f6Saliguori } 39e3aff4f6Saliguori 40e3aff4f6Saliguori static const cmdinfo_t close_cmd = { 41e3aff4f6Saliguori .name = "close", 42e3aff4f6Saliguori .altname = "c", 43e3aff4f6Saliguori .cfunc = close_f, 44e3aff4f6Saliguori .oneline = "close the current open file", 45e3aff4f6Saliguori }; 46e3aff4f6Saliguori 479c4bab26SChristoph Hellwig static int openfile(char *name, int flags, int growable) 48e3aff4f6Saliguori { 49734c3b85SKevin Wolf if (qemuio_bs) { 50e3aff4f6Saliguori fprintf(stderr, "file open already, try 'help close'\n"); 51e3aff4f6Saliguori return 1; 52e3aff4f6Saliguori } 53e3aff4f6Saliguori 546db95603SChristoph Hellwig if (growable) { 55734c3b85SKevin Wolf if (bdrv_file_open(&qemuio_bs, name, NULL, flags)) { 566db95603SChristoph Hellwig fprintf(stderr, "%s: can't open device %s\n", progname, name); 576db95603SChristoph Hellwig return 1; 586db95603SChristoph Hellwig } 596db95603SChristoph Hellwig } else { 60734c3b85SKevin Wolf qemuio_bs = bdrv_new("hda"); 61e3aff4f6Saliguori 62734c3b85SKevin Wolf if (bdrv_open(qemuio_bs, name, NULL, flags, NULL) < 0) { 63e3aff4f6Saliguori fprintf(stderr, "%s: can't open device %s\n", progname, name); 64734c3b85SKevin Wolf bdrv_delete(qemuio_bs); 65734c3b85SKevin Wolf qemuio_bs = NULL; 66e3aff4f6Saliguori return 1; 67e3aff4f6Saliguori } 689c4bab26SChristoph Hellwig } 696db95603SChristoph Hellwig 70e3aff4f6Saliguori return 0; 71e3aff4f6Saliguori } 72e3aff4f6Saliguori 7343642b38SDevin Nakamura static void open_help(void) 74e3aff4f6Saliguori { 75e3aff4f6Saliguori printf( 76e3aff4f6Saliguori "\n" 77e3aff4f6Saliguori " opens a new file in the requested mode\n" 78e3aff4f6Saliguori "\n" 79e3aff4f6Saliguori " Example:\n" 80e3aff4f6Saliguori " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 81e3aff4f6Saliguori "\n" 82e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 83e3aff4f6Saliguori " -r, -- open file read-only\n" 84e3aff4f6Saliguori " -s, -- use snapshot file\n" 85e3aff4f6Saliguori " -n, -- disable host cache\n" 869c4bab26SChristoph Hellwig " -g, -- allow file to grow (only applies to protocols)" 87e3aff4f6Saliguori "\n"); 88e3aff4f6Saliguori } 89e3aff4f6Saliguori 90734c3b85SKevin Wolf static int open_f(BlockDriverState *bs, int argc, char **argv); 9122a2bdcbSBlue Swirl 9222a2bdcbSBlue Swirl static const cmdinfo_t open_cmd = { 9322a2bdcbSBlue Swirl .name = "open", 9422a2bdcbSBlue Swirl .altname = "o", 9522a2bdcbSBlue Swirl .cfunc = open_f, 9622a2bdcbSBlue Swirl .argmin = 1, 9722a2bdcbSBlue Swirl .argmax = -1, 9822a2bdcbSBlue Swirl .flags = CMD_NOFILE_OK, 9922a2bdcbSBlue Swirl .args = "[-Crsn] [path]", 10022a2bdcbSBlue Swirl .oneline = "open the file specified by path", 10122a2bdcbSBlue Swirl .help = open_help, 10222a2bdcbSBlue Swirl }; 103e3aff4f6Saliguori 104734c3b85SKevin Wolf static int open_f(BlockDriverState *bs, int argc, char **argv) 105e3aff4f6Saliguori { 106e3aff4f6Saliguori int flags = 0; 107e3aff4f6Saliguori int readonly = 0; 1089c4bab26SChristoph Hellwig int growable = 0; 109e3aff4f6Saliguori int c; 110e3aff4f6Saliguori 1119a2d77adSChristoph Hellwig while ((c = getopt(argc, argv, "snrg")) != EOF) { 112e3aff4f6Saliguori switch (c) { 113e3aff4f6Saliguori case 's': 114e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 115e3aff4f6Saliguori break; 116e3aff4f6Saliguori case 'n': 117a6599793SChristoph Hellwig flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 118e3aff4f6Saliguori break; 119e3aff4f6Saliguori case 'r': 120e3aff4f6Saliguori readonly = 1; 121e3aff4f6Saliguori break; 1229c4bab26SChristoph Hellwig case 'g': 1239c4bab26SChristoph Hellwig growable = 1; 1249c4bab26SChristoph Hellwig break; 125e3aff4f6Saliguori default: 126c2cdf5c5SKevin Wolf return qemuio_command_usage(&open_cmd); 127e3aff4f6Saliguori } 128e3aff4f6Saliguori } 129e3aff4f6Saliguori 130f5edb014SNaphtali Sprei if (!readonly) { 131e3aff4f6Saliguori flags |= BDRV_O_RDWR; 132f5edb014SNaphtali Sprei } 133e3aff4f6Saliguori 13443642b38SDevin Nakamura if (optind != argc - 1) { 135c2cdf5c5SKevin Wolf return qemuio_command_usage(&open_cmd); 13643642b38SDevin Nakamura } 137e3aff4f6Saliguori 1389c4bab26SChristoph Hellwig return openfile(argv[optind], flags, growable); 139e3aff4f6Saliguori } 140e3aff4f6Saliguori 141e681be7eSKevin Wolf static int quit_f(BlockDriverState *bs, int argc, char **argv) 142e681be7eSKevin Wolf { 143e681be7eSKevin Wolf return 1; 144e681be7eSKevin Wolf } 145e681be7eSKevin Wolf 146e681be7eSKevin Wolf static const cmdinfo_t quit_cmd = { 147e681be7eSKevin Wolf .name = "quit", 148e681be7eSKevin Wolf .altname = "q", 149e681be7eSKevin Wolf .cfunc = quit_f, 150e681be7eSKevin Wolf .argmin = -1, 151e681be7eSKevin Wolf .argmax = -1, 152e681be7eSKevin Wolf .flags = CMD_FLAG_GLOBAL, 153e681be7eSKevin Wolf .oneline = "exit the program", 154e681be7eSKevin Wolf }; 155e681be7eSKevin Wolf 156e3aff4f6Saliguori static void usage(const char *name) 157e3aff4f6Saliguori { 158e3aff4f6Saliguori printf( 1599a2d77adSChristoph Hellwig "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n" 16084844a20SStefan Weil "QEMU Disk exerciser\n" 161e3aff4f6Saliguori "\n" 162e3aff4f6Saliguori " -c, --cmd command to execute\n" 163e3aff4f6Saliguori " -r, --read-only export read-only\n" 164e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 165e3aff4f6Saliguori " -n, --nocache disable host cache\n" 1661db6947dSChristoph Hellwig " -g, --growable allow file to grow (only applies to protocols)\n" 167e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 1685c6c3a6cSChristoph Hellwig " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 169592fa070SKevin Wolf " -t, --cache=MODE use the given cache mode for the image\n" 170d7bb72c8SStefan Hajnoczi " -T, --trace FILE enable trace events listed in the given file\n" 171e3aff4f6Saliguori " -h, --help display this help and exit\n" 172e3aff4f6Saliguori " -V, --version output version information and exit\n" 173e3aff4f6Saliguori "\n", 174e3aff4f6Saliguori name); 175e3aff4f6Saliguori } 176e3aff4f6Saliguori 177e3aff4f6Saliguori 178d1174f13SKevin Wolf #if defined(ENABLE_READLINE) 179d1174f13SKevin Wolf # include <readline/history.h> 180d1174f13SKevin Wolf # include <readline/readline.h> 181d1174f13SKevin Wolf #elif defined(ENABLE_EDITLINE) 182d1174f13SKevin Wolf # include <histedit.h> 183d1174f13SKevin Wolf #endif 184d1174f13SKevin Wolf 185d1174f13SKevin Wolf static char *get_prompt(void) 186d1174f13SKevin Wolf { 187d1174f13SKevin Wolf static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ]; 188d1174f13SKevin Wolf 189d1174f13SKevin Wolf if (!prompt[0]) { 190d1174f13SKevin Wolf snprintf(prompt, sizeof(prompt), "%s> ", progname); 191d1174f13SKevin Wolf } 192d1174f13SKevin Wolf 193d1174f13SKevin Wolf return prompt; 194d1174f13SKevin Wolf } 195d1174f13SKevin Wolf 196d1174f13SKevin Wolf #if defined(ENABLE_READLINE) 197d1174f13SKevin Wolf static char *fetchline(void) 198d1174f13SKevin Wolf { 199d1174f13SKevin Wolf char *line = readline(get_prompt()); 200d1174f13SKevin Wolf if (line && *line) { 201d1174f13SKevin Wolf add_history(line); 202d1174f13SKevin Wolf } 203d1174f13SKevin Wolf return line; 204d1174f13SKevin Wolf } 205d1174f13SKevin Wolf #elif defined(ENABLE_EDITLINE) 206d1174f13SKevin Wolf static char *el_get_prompt(EditLine *e) 207d1174f13SKevin Wolf { 208d1174f13SKevin Wolf return get_prompt(); 209d1174f13SKevin Wolf } 210d1174f13SKevin Wolf 211d1174f13SKevin Wolf static char *fetchline(void) 212d1174f13SKevin Wolf { 213d1174f13SKevin Wolf static EditLine *el; 214d1174f13SKevin Wolf static History *hist; 215d1174f13SKevin Wolf HistEvent hevent; 216d1174f13SKevin Wolf char *line; 217d1174f13SKevin Wolf int count; 218d1174f13SKevin Wolf 219d1174f13SKevin Wolf if (!el) { 220d1174f13SKevin Wolf hist = history_init(); 221d1174f13SKevin Wolf history(hist, &hevent, H_SETSIZE, 100); 222d1174f13SKevin Wolf el = el_init(progname, stdin, stdout, stderr); 223d1174f13SKevin Wolf el_source(el, NULL); 224d1174f13SKevin Wolf el_set(el, EL_SIGNAL, 1); 225d1174f13SKevin Wolf el_set(el, EL_PROMPT, el_get_prompt); 226d1174f13SKevin Wolf el_set(el, EL_HIST, history, (const char *)hist); 227d1174f13SKevin Wolf } 228d1174f13SKevin Wolf line = strdup(el_gets(el, &count)); 229d1174f13SKevin Wolf if (line) { 230d1174f13SKevin Wolf if (count > 0) { 231d1174f13SKevin Wolf line[count-1] = '\0'; 232d1174f13SKevin Wolf } 233d1174f13SKevin Wolf if (*line) { 234d1174f13SKevin Wolf history(hist, &hevent, H_ENTER, line); 235d1174f13SKevin Wolf } 236d1174f13SKevin Wolf } 237d1174f13SKevin Wolf return line; 238d1174f13SKevin Wolf } 239d1174f13SKevin Wolf #else 240d1174f13SKevin Wolf # define MAXREADLINESZ 1024 241d1174f13SKevin Wolf static char *fetchline(void) 242d1174f13SKevin Wolf { 243d1174f13SKevin Wolf char *p, *line = g_malloc(MAXREADLINESZ); 244d1174f13SKevin Wolf 245d1174f13SKevin Wolf if (!fgets(line, MAXREADLINESZ, stdin)) { 246d1174f13SKevin Wolf g_free(line); 247d1174f13SKevin Wolf return NULL; 248d1174f13SKevin Wolf } 249d1174f13SKevin Wolf 250d1174f13SKevin Wolf p = line + strlen(line); 251d1174f13SKevin Wolf if (p != line && p[-1] == '\n') { 252d1174f13SKevin Wolf p[-1] = '\0'; 253d1174f13SKevin Wolf } 254d1174f13SKevin Wolf 255d1174f13SKevin Wolf return line; 256d1174f13SKevin Wolf } 257d1174f13SKevin Wolf #endif 258d1174f13SKevin Wolf 259d1174f13SKevin Wolf static void prep_fetchline(void *opaque) 260d1174f13SKevin Wolf { 261d1174f13SKevin Wolf int *fetchable = opaque; 262d1174f13SKevin Wolf 263d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL); 264d1174f13SKevin Wolf *fetchable= 1; 265d1174f13SKevin Wolf } 266d1174f13SKevin Wolf 267d1174f13SKevin Wolf static void command_loop(void) 268d1174f13SKevin Wolf { 269d1174f13SKevin Wolf int i, done = 0, fetchable = 0, prompted = 0; 270d1174f13SKevin Wolf char *input; 271d1174f13SKevin Wolf 272d1174f13SKevin Wolf for (i = 0; !done && i < ncmdline; i++) { 2733d21994fSKevin Wolf done = qemuio_command(qemuio_bs, cmdline[i]); 274d1174f13SKevin Wolf } 275d1174f13SKevin Wolf if (cmdline) { 276d1174f13SKevin Wolf g_free(cmdline); 277d1174f13SKevin Wolf return; 278d1174f13SKevin Wolf } 279d1174f13SKevin Wolf 280d1174f13SKevin Wolf while (!done) { 281d1174f13SKevin Wolf if (!prompted) { 282d1174f13SKevin Wolf printf("%s", get_prompt()); 283d1174f13SKevin Wolf fflush(stdout); 284d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable); 285d1174f13SKevin Wolf prompted = 1; 286d1174f13SKevin Wolf } 287d1174f13SKevin Wolf 288d1174f13SKevin Wolf main_loop_wait(false); 289d1174f13SKevin Wolf 290d1174f13SKevin Wolf if (!fetchable) { 291d1174f13SKevin Wolf continue; 292d1174f13SKevin Wolf } 293d1174f13SKevin Wolf 294d1174f13SKevin Wolf input = fetchline(); 295d1174f13SKevin Wolf if (input == NULL) { 296d1174f13SKevin Wolf break; 297d1174f13SKevin Wolf } 2983d21994fSKevin Wolf done = qemuio_command(qemuio_bs, input); 299d1174f13SKevin Wolf g_free(input); 300d1174f13SKevin Wolf 301d1174f13SKevin Wolf prompted = 0; 302d1174f13SKevin Wolf fetchable = 0; 303d1174f13SKevin Wolf } 304d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL); 305d1174f13SKevin Wolf } 306d1174f13SKevin Wolf 307d1174f13SKevin Wolf static void add_user_command(char *optarg) 308d1174f13SKevin Wolf { 309d1174f13SKevin Wolf cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *)); 310d1174f13SKevin Wolf cmdline[ncmdline-1] = optarg; 311d1174f13SKevin Wolf } 312d1174f13SKevin Wolf 313e3aff4f6Saliguori int main(int argc, char **argv) 314e3aff4f6Saliguori { 315e3aff4f6Saliguori int readonly = 0; 3169c4bab26SChristoph Hellwig int growable = 0; 3179e8f1835SPaolo Bonzini const char *sopt = "hVc:d:rsnmgkt:T:"; 318b32bb952SBlue Swirl const struct option lopt[] = { 319660f11beSBlue Swirl { "help", 0, NULL, 'h' }, 320660f11beSBlue Swirl { "version", 0, NULL, 'V' }, 321660f11beSBlue Swirl { "offset", 1, NULL, 'o' }, 322660f11beSBlue Swirl { "cmd", 1, NULL, 'c' }, 323660f11beSBlue Swirl { "read-only", 0, NULL, 'r' }, 324660f11beSBlue Swirl { "snapshot", 0, NULL, 's' }, 325660f11beSBlue Swirl { "nocache", 0, NULL, 'n' }, 326660f11beSBlue Swirl { "misalign", 0, NULL, 'm' }, 327660f11beSBlue Swirl { "growable", 0, NULL, 'g' }, 3285c6c3a6cSChristoph Hellwig { "native-aio", 0, NULL, 'k' }, 3299e8f1835SPaolo Bonzini { "discard", 1, NULL, 'd' }, 330592fa070SKevin Wolf { "cache", 1, NULL, 't' }, 331d7bb72c8SStefan Hajnoczi { "trace", 1, NULL, 'T' }, 332660f11beSBlue Swirl { NULL, 0, NULL, 0 } 333e3aff4f6Saliguori }; 334e3aff4f6Saliguori int c; 335e3aff4f6Saliguori int opt_index = 0; 3369e8f1835SPaolo Bonzini int flags = BDRV_O_UNMAP; 337e3aff4f6Saliguori 338*526eda14SMORITA Kazutaka #ifdef CONFIG_POSIX 339*526eda14SMORITA Kazutaka signal(SIGPIPE, SIG_IGN); 340*526eda14SMORITA Kazutaka #endif 341*526eda14SMORITA Kazutaka 342e3aff4f6Saliguori progname = basename(argv[0]); 343e3aff4f6Saliguori 344e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 345e3aff4f6Saliguori switch (c) { 346e3aff4f6Saliguori case 's': 347e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 348e3aff4f6Saliguori break; 349e3aff4f6Saliguori case 'n': 350a6599793SChristoph Hellwig flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 351e3aff4f6Saliguori break; 3529e8f1835SPaolo Bonzini case 'd': 3539e8f1835SPaolo Bonzini if (bdrv_parse_discard_flags(optarg, &flags) < 0) { 3549e8f1835SPaolo Bonzini error_report("Invalid discard option: %s", optarg); 3559e8f1835SPaolo Bonzini exit(1); 3569e8f1835SPaolo Bonzini } 3579e8f1835SPaolo Bonzini break; 358e3aff4f6Saliguori case 'c': 359e3aff4f6Saliguori add_user_command(optarg); 360e3aff4f6Saliguori break; 361e3aff4f6Saliguori case 'r': 362e3aff4f6Saliguori readonly = 1; 363e3aff4f6Saliguori break; 364e3aff4f6Saliguori case 'm': 365797ac58cSKevin Wolf qemuio_misalign = 1; 366e3aff4f6Saliguori break; 3679c4bab26SChristoph Hellwig case 'g': 3689c4bab26SChristoph Hellwig growable = 1; 3699c4bab26SChristoph Hellwig break; 3705c6c3a6cSChristoph Hellwig case 'k': 3715c6c3a6cSChristoph Hellwig flags |= BDRV_O_NATIVE_AIO; 3725c6c3a6cSChristoph Hellwig break; 373592fa070SKevin Wolf case 't': 374592fa070SKevin Wolf if (bdrv_parse_cache_flags(optarg, &flags) < 0) { 375592fa070SKevin Wolf error_report("Invalid cache option: %s", optarg); 376592fa070SKevin Wolf exit(1); 377592fa070SKevin Wolf } 378592fa070SKevin Wolf break; 379d7bb72c8SStefan Hajnoczi case 'T': 380d7bb72c8SStefan Hajnoczi if (!trace_backend_init(optarg, NULL)) { 381d7bb72c8SStefan Hajnoczi exit(1); /* error message will have been printed */ 382d7bb72c8SStefan Hajnoczi } 383d7bb72c8SStefan Hajnoczi break; 384e3aff4f6Saliguori case 'V': 38502da386aSKevin Wolf printf("%s version %s\n", progname, QEMU_VERSION); 386e3aff4f6Saliguori exit(0); 387e3aff4f6Saliguori case 'h': 388e3aff4f6Saliguori usage(progname); 389e3aff4f6Saliguori exit(0); 390e3aff4f6Saliguori default: 391e3aff4f6Saliguori usage(progname); 392e3aff4f6Saliguori exit(1); 393e3aff4f6Saliguori } 394e3aff4f6Saliguori } 395e3aff4f6Saliguori 396e3aff4f6Saliguori if ((argc - optind) > 1) { 397e3aff4f6Saliguori usage(progname); 398e3aff4f6Saliguori exit(1); 399e3aff4f6Saliguori } 400e3aff4f6Saliguori 401a57d1143SZhi Yong Wu qemu_init_main_loop(); 4022592c59aSPaolo Bonzini bdrv_init(); 403a57d1143SZhi Yong Wu 404e3aff4f6Saliguori /* initialize commands */ 405c2cdf5c5SKevin Wolf qemuio_add_command(&quit_cmd); 406c2cdf5c5SKevin Wolf qemuio_add_command(&open_cmd); 407c2cdf5c5SKevin Wolf qemuio_add_command(&close_cmd); 408e3aff4f6Saliguori 409e3aff4f6Saliguori /* open the device */ 410f5edb014SNaphtali Sprei if (!readonly) { 411e3aff4f6Saliguori flags |= BDRV_O_RDWR; 412f5edb014SNaphtali Sprei } 413e3aff4f6Saliguori 41443642b38SDevin Nakamura if ((argc - optind) == 1) { 4159c4bab26SChristoph Hellwig openfile(argv[optind], flags, growable); 41643642b38SDevin Nakamura } 417e3aff4f6Saliguori command_loop(); 418e3aff4f6Saliguori 41995533d5fSChristoph Hellwig /* 420922453bcSStefan Hajnoczi * Make sure all outstanding requests complete before the program exits. 42195533d5fSChristoph Hellwig */ 422922453bcSStefan Hajnoczi bdrv_drain_all(); 42395533d5fSChristoph Hellwig 424734c3b85SKevin Wolf if (qemuio_bs) { 425734c3b85SKevin Wolf bdrv_delete(qemuio_bs); 42643642b38SDevin Nakamura } 427e3aff4f6Saliguori return 0; 428e3aff4f6Saliguori } 429