blockdev-nbd.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * Serving QEMU block devices via NBD
  3. *
  4. * Copyright (c) 2012 Red Hat, Inc.
  5. *
  6. * Author: Paolo Bonzini <pbonzini@redhat.com>
  7. *
  8. * This work is licensed under the terms of the GNU GPL, version 2 or
  9. * later. See the COPYING file in the top-level directory.
  10. */
  11. #include "qemu/osdep.h"
  12. #include "sysemu/blockdev.h"
  13. #include "sysemu/block-backend.h"
  14. #include "hw/block/block.h"
  15. #include "qapi/qmp/qerror.h"
  16. #include "sysemu/sysemu.h"
  17. #include "qmp-commands.h"
  18. #include "trace.h"
  19. #include "block/nbd.h"
  20. #include "qemu/sockets.h"
  21. static int server_fd = -1;
  22. static void nbd_accept(void *opaque)
  23. {
  24. struct sockaddr_in addr;
  25. socklen_t addr_len = sizeof(addr);
  26. int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
  27. if (fd >= 0) {
  28. nbd_client_new(NULL, fd, nbd_client_put);
  29. }
  30. }
  31. void qmp_nbd_server_start(SocketAddress *addr, Error **errp)
  32. {
  33. if (server_fd != -1) {
  34. error_setg(errp, "NBD server already running");
  35. return;
  36. }
  37. server_fd = socket_listen(addr, errp);
  38. if (server_fd != -1) {
  39. qemu_set_fd_handler(server_fd, nbd_accept, NULL, NULL);
  40. }
  41. }
  42. void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
  43. Error **errp)
  44. {
  45. BlockBackend *blk;
  46. NBDExport *exp;
  47. if (server_fd == -1) {
  48. error_setg(errp, "NBD server not running");
  49. return;
  50. }
  51. if (nbd_export_find(device)) {
  52. error_setg(errp, "NBD server already exporting device '%s'", device);
  53. return;
  54. }
  55. blk = blk_by_name(device);
  56. if (!blk) {
  57. error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
  58. "Device '%s' not found", device);
  59. return;
  60. }
  61. if (!blk_is_inserted(blk)) {
  62. error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
  63. return;
  64. }
  65. if (!has_writable) {
  66. writable = false;
  67. }
  68. if (blk_is_read_only(blk)) {
  69. writable = false;
  70. }
  71. exp = nbd_export_new(blk, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL,
  72. errp);
  73. if (!exp) {
  74. return;
  75. }
  76. nbd_export_set_name(exp, device);
  77. /* The list of named exports has a strong reference to this export now and
  78. * our only way of accessing it is through nbd_export_find(), so we can drop
  79. * the strong reference that is @exp. */
  80. nbd_export_put(exp);
  81. }
  82. void qmp_nbd_server_stop(Error **errp)
  83. {
  84. nbd_export_close_all();
  85. if (server_fd != -1) {
  86. qemu_set_fd_handler(server_fd, NULL, NULL, NULL);
  87. close(server_fd);
  88. server_fd = -1;
  89. }
  90. }