virtio-9p-device.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Virtio 9p backend
  3. *
  4. * Copyright IBM, Corp. 2010
  5. *
  6. * Authors:
  7. * Anthony Liguori <aliguori@us.ibm.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2. See
  10. * the COPYING file in the top-level directory.
  11. *
  12. */
  13. #include "hw/virtio.h"
  14. #include "hw/pc.h"
  15. #include "qemu_socket.h"
  16. #include "hw/virtio-pci.h"
  17. #include "virtio-9p.h"
  18. #include "fsdev/qemu-fsdev.h"
  19. #include "virtio-9p-xattr.h"
  20. #include "virtio-9p-coth.h"
  21. static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
  22. {
  23. features |= 1 << VIRTIO_9P_MOUNT_TAG;
  24. return features;
  25. }
  26. static V9fsState *to_virtio_9p(VirtIODevice *vdev)
  27. {
  28. return (V9fsState *)vdev;
  29. }
  30. static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
  31. {
  32. struct virtio_9p_config *cfg;
  33. V9fsState *s = to_virtio_9p(vdev);
  34. cfg = g_malloc0(sizeof(struct virtio_9p_config) +
  35. s->tag_len);
  36. stw_raw(&cfg->tag_len, s->tag_len);
  37. memcpy(cfg->tag, s->tag, s->tag_len);
  38. memcpy(config, cfg, s->config_size);
  39. g_free(cfg);
  40. }
  41. VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
  42. {
  43. V9fsState *s;
  44. int i, len;
  45. struct stat stat;
  46. FsTypeEntry *fse;
  47. s = (V9fsState *)virtio_common_init("virtio-9p",
  48. VIRTIO_ID_9P,
  49. sizeof(struct virtio_9p_config)+
  50. MAX_TAG_LEN,
  51. sizeof(V9fsState));
  52. /* initialize pdu allocator */
  53. QLIST_INIT(&s->free_list);
  54. for (i = 0; i < (MAX_REQ - 1); i++) {
  55. QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next);
  56. }
  57. s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
  58. fse = get_fsdev_fsentry(conf->fsdev_id);
  59. if (!fse) {
  60. /* We don't have a fsdev identified by fsdev_id */
  61. fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
  62. "id = %s\n", conf->fsdev_id ? conf->fsdev_id : "NULL");
  63. exit(1);
  64. }
  65. if (!fse->path || !conf->tag) {
  66. /* we haven't specified a mount_tag or the path */
  67. fprintf(stderr, "fsdev with id %s needs path "
  68. "and Virtio-9p device needs mount_tag arguments\n",
  69. conf->fsdev_id);
  70. exit(1);
  71. }
  72. if (!strcmp(fse->security_model, "passthrough")) {
  73. /* Files on the Fileserver set to client user credentials */
  74. s->ctx.fs_sm = SM_PASSTHROUGH;
  75. s->ctx.xops = passthrough_xattr_ops;
  76. } else if (!strcmp(fse->security_model, "mapped")) {
  77. /* Files on the fileserver are set to QEMU credentials.
  78. * Client user credentials are saved in extended attributes.
  79. */
  80. s->ctx.fs_sm = SM_MAPPED;
  81. s->ctx.xops = mapped_xattr_ops;
  82. } else if (!strcmp(fse->security_model, "none")) {
  83. /*
  84. * Files on the fileserver are set to QEMU credentials.
  85. */
  86. s->ctx.fs_sm = SM_NONE;
  87. s->ctx.xops = none_xattr_ops;
  88. } else {
  89. fprintf(stderr, "Default to security_model=none. You may want"
  90. " enable advanced security model using "
  91. "security option:\n\t security_model=passthrough\n\t "
  92. "security_model=mapped\n");
  93. s->ctx.fs_sm = SM_NONE;
  94. s->ctx.xops = none_xattr_ops;
  95. }
  96. if (lstat(fse->path, &stat)) {
  97. fprintf(stderr, "share path %s does not exist\n", fse->path);
  98. exit(1);
  99. } else if (!S_ISDIR(stat.st_mode)) {
  100. fprintf(stderr, "share path %s is not a directory\n", fse->path);
  101. exit(1);
  102. }
  103. s->ctx.fs_root = g_strdup(fse->path);
  104. len = strlen(conf->tag);
  105. if (len > MAX_TAG_LEN) {
  106. len = MAX_TAG_LEN;
  107. }
  108. /* s->tag is non-NULL terminated string */
  109. s->tag = g_malloc(len);
  110. memcpy(s->tag, conf->tag, len);
  111. s->tag_len = len;
  112. s->ctx.uid = -1;
  113. s->ops = fse->ops;
  114. s->vdev.get_features = virtio_9p_get_features;
  115. s->config_size = sizeof(struct virtio_9p_config) +
  116. s->tag_len;
  117. s->vdev.get_config = virtio_9p_get_config;
  118. if (v9fs_init_worker_threads() < 0) {
  119. fprintf(stderr, "worker thread initialization failed\n");
  120. exit(1);
  121. }
  122. return &s->vdev;
  123. }
  124. static int virtio_9p_init_pci(PCIDevice *pci_dev)
  125. {
  126. VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
  127. VirtIODevice *vdev;
  128. vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
  129. vdev->nvectors = proxy->nvectors;
  130. virtio_init_pci(proxy, vdev);
  131. /* make the actual value visible */
  132. proxy->nvectors = vdev->nvectors;
  133. return 0;
  134. }
  135. static PCIDeviceInfo virtio_9p_info = {
  136. .qdev.name = "virtio-9p-pci",
  137. .qdev.size = sizeof(VirtIOPCIProxy),
  138. .init = virtio_9p_init_pci,
  139. .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
  140. .device_id = 0x1009,
  141. .revision = VIRTIO_PCI_ABI_VERSION,
  142. .class_id = 0x2,
  143. .qdev.props = (Property[]) {
  144. DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
  145. DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
  146. DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
  147. DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
  148. DEFINE_PROP_END_OF_LIST(),
  149. }
  150. };
  151. static void virtio_9p_register_devices(void)
  152. {
  153. pci_qdev_register(&virtio_9p_info);
  154. }
  155. device_init(virtio_9p_register_devices)