*/
#include "qemu-common.h"
-#include "block.h"
-#include "nbd.h"
+#include "block/block.h"
+#include "block/nbd.h"
+#include "qemu/main-loop.h"
#include <stdarg.h>
#include <stdio.h>
#include <libgen.h>
#include <pthread.h>
-#define SOCKET_PATH "/var/lock/qemu-nbd-%s"
-#define QEMU_NBD_OPT_CACHE 1
-#define QEMU_NBD_OPT_AIO 2
+#define SOCKET_PATH "/var/lock/qemu-nbd-%s"
+#define QEMU_NBD_OPT_CACHE 1
+#define QEMU_NBD_OPT_AIO 2
+#define QEMU_NBD_OPT_DISCARD 3
static NBDExport *exp;
static int verbose;
int main(int argc, char **argv)
{
BlockDriverState *bs;
+ BlockDriver *drv;
off_t dev_offset = 0;
uint32_t nbdflags = 0;
bool disconnect = false;
char *device = NULL;
int port = NBD_DEFAULT_PORT;
off_t fd_size;
- const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t";
+ const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:t";
struct option lopt[] = {
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'V' },
#ifdef CONFIG_LINUX_AIO
{ "aio", 1, NULL, QEMU_NBD_OPT_AIO },
#endif
+ { "discard", 1, NULL, QEMU_NBD_OPT_DISCARD },
{ "shared", 1, NULL, 'e' },
+ { "format", 1, NULL, 'f' },
{ "persistent", 0, NULL, 't' },
{ "verbose", 0, NULL, 'v' },
{ NULL, 0, NULL, 0 }
int ret;
int fd;
bool seen_cache = false;
+ bool seen_discard = false;
#ifdef CONFIG_LINUX_AIO
bool seen_aio = false;
#endif
pthread_t client_thread;
+ const char *fmt = NULL;
/* The client thread uses SIGTERM to interrupt the server. A signal
* handler ensures that "qemu-nbd -v -c" exits with a nice status code.
}
break;
#endif
+ case QEMU_NBD_OPT_DISCARD:
+ if (seen_discard) {
+ errx(EXIT_FAILURE, "--discard can only be specified once");
+ }
+ seen_discard = true;
+ if (bdrv_parse_discard_flags(optarg, &flags) == -1) {
+ errx(EXIT_FAILURE, "Invalid discard mode `%s'", optarg);
+ }
+ break;
case 'b':
bindto = optarg;
break;
errx(EXIT_FAILURE, "Shared device number must be greater than 0\n");
}
break;
+ case 'f':
+ fmt = optarg;
+ break;
case 't':
persistent = 1;
break;
bdrv_init();
atexit(bdrv_close_all);
+ if (fmt) {
+ drv = bdrv_find_format(fmt);
+ if (!drv) {
+ errx(EXIT_FAILURE, "Unknown file format '%s'", fmt);
+ }
+ } else {
+ drv = NULL;
+ }
+
bs = bdrv_new("hda");
srcpath = argv[optind];
- if ((ret = bdrv_open(bs, srcpath, flags, NULL)) < 0) {
+ ret = bdrv_open(bs, srcpath, NULL, flags, drv);
+ if (ret < 0) {
errno = -ret;
err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]);
}