#define QEMU_NBD_OPT_OBJECT 260
#define QEMU_NBD_OPT_TLSCREDS 261
#define QEMU_NBD_OPT_IMAGE_OPTS 262
+#define QEMU_NBD_OPT_FORK 263
#define MBR_SIZE 512
" passwords and/or encryption keys\n"
" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
" specify tracing options\n"
+" --fork fork off the server process and exit the parent\n"
+" once the server is running\n"
#ifdef __linux__
"Kernel NBD client support:\n"
" -c, --connect=DEV connect FILE to the local NBD device DEV\n"
{
char *device = arg;
off_t size;
- uint32_t nbdflags;
+ uint16_t nbdflags;
QIOChannelSocket *sioc;
int fd;
int ret;
BlockBackend *blk;
BlockDriverState *bs;
off_t dev_offset = 0;
- uint32_t nbdflags = 0;
+ uint16_t nbdflags = 0;
bool disconnect = false;
const char *bindto = "0.0.0.0";
const char *port = NULL;
{ "tls-creds", required_argument, NULL, QEMU_NBD_OPT_TLSCREDS },
{ "image-opts", no_argument, NULL, QEMU_NBD_OPT_IMAGE_OPTS },
{ "trace", required_argument, NULL, 'T' },
+ { "fork", no_argument, NULL, QEMU_NBD_OPT_FORK },
{ NULL, 0, NULL, 0 }
};
int ch;
bool imageOpts = false;
bool writethrough = true;
char *trace_file = NULL;
+ bool fork_process = false;
+ int old_stderr = -1;
/* The client thread uses SIGTERM to interrupt the server. A signal
* handler ensures that "qemu-nbd -v -c" exits with a nice status code.
sa_sigterm.sa_handler = termsig_handler;
sigaction(SIGTERM, &sa_sigterm, NULL);
+ module_call_init(MODULE_INIT_TRACE);
qcrypto_init(&error_fatal);
module_call_init(MODULE_INIT_QOM);
g_free(trace_file);
trace_file = trace_opt_parse(optarg);
break;
+ case QEMU_NBD_OPT_FORK:
+ fork_process = true;
+ break;
}
}
return 0;
}
- if (device && !verbose) {
+ if ((device && !verbose) || fork_process) {
int stderr_fd[2];
pid_t pid;
int ret;
ret = qemu_daemon(1, 0);
/* Temporarily redirect stderr to the parent's pipe... */
+ old_stderr = dup(STDERR_FILENO);
dup2(stderr_fd[1], STDERR_FILENO);
if (ret < 0) {
error_report("Failed to daemonize: %s", strerror(errno));
exit(EXIT_FAILURE);
}
+ if (dev_offset >= fd_size) {
+ error_report("Offset (%lld) has to be smaller than the image size "
+ "(%lld)",
+ (long long int)dev_offset, (long long int)fd_size);
+ exit(EXIT_FAILURE);
+ }
+ fd_size -= dev_offset;
+
if (partition != -1) {
ret = find_partition(blk, partition, &dev_offset, &fd_size);
if (ret < 0) {
}
}
- exp = nbd_export_new(blk, dev_offset, fd_size, nbdflags, nbd_export_closed,
- &local_err);
+ exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed,
+ writethrough, NULL, &local_err);
if (!exp) {
error_report_err(local_err);
exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
+ if (fork_process) {
+ dup2(old_stderr, STDERR_FILENO);
+ close(old_stderr);
+ }
+
state = RUNNING;
do {
main_loop_wait(false);