Revision a61c6782 qemu-nbd.c
b/qemu-nbd.c | ||
---|---|---|
35 | 35 |
|
36 | 36 |
#define SOCKET_PATH "/var/lock/qemu-nbd-%s" |
37 | 37 |
|
38 |
static int sigterm_wfd; |
|
39 | 38 |
static NBDExport *exp; |
40 | 39 |
static int verbose; |
41 | 40 |
static char *device; |
42 | 41 |
static char *srcpath; |
43 | 42 |
static char *sockpath; |
43 |
static bool sigterm_reported; |
|
44 |
static bool nbd_started; |
|
45 |
static int shared = 1; |
|
46 |
static int nb_fds; |
|
44 | 47 |
|
45 | 48 |
static void usage(const char *name) |
46 | 49 |
{ |
... | ... | |
169 | 172 |
|
170 | 173 |
static void termsig_handler(int signum) |
171 | 174 |
{ |
172 |
static int sigterm_reported; |
|
173 |
if (!sigterm_reported) { |
|
174 |
sigterm_reported = (write(sigterm_wfd, "", 1) == 1); |
|
175 |
} |
|
175 |
sigterm_reported = true; |
|
176 |
qemu_notify_event(); |
|
176 | 177 |
} |
177 | 178 |
|
178 | 179 |
static void *show_parts(void *arg) |
... | ... | |
243 | 244 |
return (void *) EXIT_FAILURE; |
244 | 245 |
} |
245 | 246 |
|
247 |
static int nbd_can_accept(void *opaque) |
|
248 |
{ |
|
249 |
return nb_fds < shared; |
|
250 |
} |
|
251 |
|
|
252 |
static void nbd_read(void *opaque) |
|
253 |
{ |
|
254 |
int fd = (uintptr_t) opaque; |
|
255 |
|
|
256 |
if (nbd_trip(exp, fd) != 0) { |
|
257 |
qemu_set_fd_handler2(fd, NULL, NULL, NULL, NULL); |
|
258 |
close(fd); |
|
259 |
nb_fds--; |
|
260 |
} |
|
261 |
} |
|
262 |
|
|
263 |
static void nbd_accept(void *opaque) |
|
264 |
{ |
|
265 |
int server_fd = (uintptr_t) opaque; |
|
266 |
struct sockaddr_in addr; |
|
267 |
socklen_t addr_len = sizeof(addr); |
|
268 |
|
|
269 |
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); |
|
270 |
nbd_started = true; |
|
271 |
if (fd != -1 && nbd_negotiate(exp, fd) != -1) { |
|
272 |
qemu_set_fd_handler2(fd, NULL, nbd_read, NULL, (void *) (intptr_t) fd); |
|
273 |
nb_fds++; |
|
274 |
} |
|
275 |
} |
|
276 |
|
|
246 | 277 |
int main(int argc, char **argv) |
247 | 278 |
{ |
248 | 279 |
BlockDriverState *bs; |
... | ... | |
251 | 282 |
bool disconnect = false; |
252 | 283 |
const char *bindto = "0.0.0.0"; |
253 | 284 |
int port = NBD_DEFAULT_PORT; |
254 |
struct sockaddr_in addr; |
|
255 |
socklen_t addr_len = sizeof(addr); |
|
256 | 285 |
off_t fd_size; |
257 | 286 |
const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t"; |
258 | 287 |
struct option lopt[] = { |
... | ... | |
280 | 309 |
int flags = BDRV_O_RDWR; |
281 | 310 |
int partition = -1; |
282 | 311 |
int ret; |
283 |
int shared = 1; |
|
284 |
fd_set fds; |
|
285 |
int *sharing_fds; |
|
286 | 312 |
int fd; |
287 |
int i; |
|
288 |
int nb_fds = 0; |
|
289 |
int max_fd; |
|
290 | 313 |
int persistent = 0; |
291 | 314 |
pthread_t client_thread; |
292 | 315 |
|
... | ... | |
294 | 317 |
* handler ensures that "qemu-nbd -v -c" exits with a nice status code. |
295 | 318 |
*/ |
296 | 319 |
struct sigaction sa_sigterm; |
297 |
int sigterm_fd[2]; |
|
298 |
if (qemu_pipe(sigterm_fd) == -1) { |
|
299 |
err(EXIT_FAILURE, "Error setting up communication pipe"); |
|
300 |
} |
|
301 |
|
|
302 |
sigterm_wfd = sigterm_fd[1]; |
|
303 | 320 |
memset(&sa_sigterm, 0, sizeof(sa_sigterm)); |
304 | 321 |
sa_sigterm.sa_handler = termsig_handler; |
305 | 322 |
sigaction(SIGTERM, &sa_sigterm, NULL); |
... | ... | |
490 | 507 |
} |
491 | 508 |
|
492 | 509 |
exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags); |
493 |
sharing_fds = g_malloc((shared + 1) * sizeof(int)); |
|
494 | 510 |
|
495 | 511 |
if (sockpath) { |
496 |
sharing_fds[0] = unix_socket_incoming(sockpath);
|
|
512 |
fd = unix_socket_incoming(sockpath);
|
|
497 | 513 |
} else { |
498 |
sharing_fds[0] = tcp_socket_incoming(bindto, port);
|
|
514 |
fd = tcp_socket_incoming(bindto, port);
|
|
499 | 515 |
} |
500 | 516 |
|
501 |
if (sharing_fds[0] == -1)
|
|
517 |
if (fd == -1) {
|
|
502 | 518 |
return 1; |
519 |
} |
|
503 | 520 |
|
504 | 521 |
if (device) { |
505 | 522 |
int ret; |
... | ... | |
514 | 531 |
memset(&client_thread, 0, sizeof(client_thread)); |
515 | 532 |
} |
516 | 533 |
|
517 |
max_fd = sharing_fds[0]; |
|
518 |
nb_fds++; |
|
534 |
qemu_init_main_loop(); |
|
535 |
qemu_set_fd_handler2(fd, nbd_can_accept, nbd_accept, NULL, |
|
536 |
(void *)(uintptr_t)fd); |
|
519 | 537 |
|
520 | 538 |
do { |
521 |
FD_ZERO(&fds); |
|
522 |
FD_SET(sigterm_fd[0], &fds); |
|
523 |
for (i = 0; i < nb_fds; i++) |
|
524 |
FD_SET(sharing_fds[i], &fds); |
|
525 |
|
|
526 |
do { |
|
527 |
ret = select(max_fd + 1, &fds, NULL, NULL, NULL); |
|
528 |
} while (ret == -1 && errno == EINTR); |
|
529 |
if (ret == -1 || FD_ISSET(sigterm_fd[0], &fds)) { |
|
530 |
break; |
|
531 |
} |
|
532 |
|
|
533 |
if (FD_ISSET(sharing_fds[0], &fds)) |
|
534 |
ret--; |
|
535 |
for (i = 1; i < nb_fds && ret; i++) { |
|
536 |
if (FD_ISSET(sharing_fds[i], &fds)) { |
|
537 |
if (nbd_trip(exp, sharing_fds[i]) != 0) { |
|
538 |
close(sharing_fds[i]); |
|
539 |
nb_fds--; |
|
540 |
sharing_fds[i] = sharing_fds[nb_fds]; |
|
541 |
i--; |
|
542 |
} |
|
543 |
ret--; |
|
544 |
} |
|
545 |
} |
|
546 |
/* new connection ? */ |
|
547 |
if (FD_ISSET(sharing_fds[0], &fds)) { |
|
548 |
if (nb_fds < shared + 1) { |
|
549 |
sharing_fds[nb_fds] = accept(sharing_fds[0], |
|
550 |
(struct sockaddr *)&addr, |
|
551 |
&addr_len); |
|
552 |
if (sharing_fds[nb_fds] != -1 && |
|
553 |
nbd_negotiate(exp, sharing_fds[nb_fds]) != -1) { |
|
554 |
if (sharing_fds[nb_fds] > max_fd) |
|
555 |
max_fd = sharing_fds[nb_fds]; |
|
556 |
nb_fds++; |
|
557 |
} |
|
558 |
} |
|
559 |
} |
|
560 |
} while (persistent || nb_fds > 1); |
|
539 |
main_loop_wait(false); |
|
540 |
} while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0)); |
|
561 | 541 |
|
562 |
close(sharing_fds[0]); |
|
563 | 542 |
nbd_export_close(exp); |
564 |
g_free(sharing_fds); |
|
565 | 543 |
if (sockpath) { |
566 | 544 |
unlink(sockpath); |
567 | 545 |
} |
Also available in: Unified diff