vhost-scsi.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. * vhost_scsi host device
  3. *
  4. * Copyright IBM, Corp. 2011
  5. *
  6. * Authors:
  7. * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
  8. *
  9. * Changes for QEMU mainline + tcm_vhost kernel upstream:
  10. * Nicholas Bellinger <nab@risingtidesystems.com>
  11. *
  12. * This work is licensed under the terms of the GNU LGPL, version 2 or later.
  13. * See the COPYING.LIB file in the top-level directory.
  14. *
  15. */
  16. #include "qemu/osdep.h"
  17. #include <linux/vhost.h>
  18. #include <sys/ioctl.h>
  19. #include "qapi/error.h"
  20. #include "qemu/error-report.h"
  21. #include "qemu/module.h"
  22. #include "monitor/monitor.h"
  23. #include "migration/blocker.h"
  24. #include "hw/virtio/vhost-scsi.h"
  25. #include "hw/virtio/vhost.h"
  26. #include "hw/virtio/virtio-scsi.h"
  27. #include "hw/virtio/virtio-bus.h"
  28. #include "hw/virtio/virtio-access.h"
  29. #include "hw/fw-path-provider.h"
  30. #include "hw/qdev-properties.h"
  31. #include "qemu/cutils.h"
  32. #include "sysemu/sysemu.h"
  33. /* Features supported by host kernel. */
  34. static const int kernel_feature_bits[] = {
  35. VIRTIO_F_NOTIFY_ON_EMPTY,
  36. VIRTIO_RING_F_INDIRECT_DESC,
  37. VIRTIO_RING_F_EVENT_IDX,
  38. VIRTIO_SCSI_F_HOTPLUG,
  39. VIRTIO_F_RING_RESET,
  40. VHOST_INVALID_FEATURE_BIT
  41. };
  42. static int vhost_scsi_set_endpoint(VHostSCSI *s)
  43. {
  44. VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
  45. VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
  46. const VhostOps *vhost_ops = vsc->dev.vhost_ops;
  47. struct vhost_scsi_target backend;
  48. int ret;
  49. memset(&backend, 0, sizeof(backend));
  50. pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwpn);
  51. ret = vhost_ops->vhost_scsi_set_endpoint(&vsc->dev, &backend);
  52. if (ret < 0) {
  53. return -errno;
  54. }
  55. return 0;
  56. }
  57. static void vhost_scsi_clear_endpoint(VHostSCSI *s)
  58. {
  59. VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
  60. VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
  61. struct vhost_scsi_target backend;
  62. const VhostOps *vhost_ops = vsc->dev.vhost_ops;
  63. memset(&backend, 0, sizeof(backend));
  64. pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwpn);
  65. vhost_ops->vhost_scsi_clear_endpoint(&vsc->dev, &backend);
  66. }
  67. static int vhost_scsi_start(VHostSCSI *s)
  68. {
  69. int ret, abi_version;
  70. VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
  71. const VhostOps *vhost_ops = vsc->dev.vhost_ops;
  72. ret = vhost_ops->vhost_scsi_get_abi_version(&vsc->dev, &abi_version);
  73. if (ret < 0) {
  74. return -errno;
  75. }
  76. if (abi_version > VHOST_SCSI_ABI_VERSION) {
  77. error_report("vhost-scsi: The running tcm_vhost kernel abi_version:"
  78. " %d is greater than vhost_scsi userspace supports: %d,"
  79. " please upgrade your version of QEMU", abi_version,
  80. VHOST_SCSI_ABI_VERSION);
  81. return -ENOSYS;
  82. }
  83. ret = vhost_scsi_common_start(vsc);
  84. if (ret < 0) {
  85. return ret;
  86. }
  87. ret = vhost_scsi_set_endpoint(s);
  88. if (ret < 0) {
  89. error_report("Error setting vhost-scsi endpoint");
  90. vhost_scsi_common_stop(vsc);
  91. }
  92. return ret;
  93. }
  94. static void vhost_scsi_stop(VHostSCSI *s)
  95. {
  96. VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
  97. vhost_scsi_clear_endpoint(s);
  98. vhost_scsi_common_stop(vsc);
  99. }
  100. static void vhost_scsi_set_status(VirtIODevice *vdev, uint8_t val)
  101. {
  102. VHostSCSI *s = VHOST_SCSI(vdev);
  103. VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
  104. bool start = (val & VIRTIO_CONFIG_S_DRIVER_OK);
  105. if (!vdev->vm_running) {
  106. start = false;
  107. }
  108. if (vhost_dev_is_started(&vsc->dev) == start) {
  109. return;
  110. }
  111. if (start) {
  112. int ret;
  113. ret = vhost_scsi_start(s);
  114. if (ret < 0) {
  115. error_report("unable to start vhost-scsi: %s", strerror(-ret));
  116. exit(1);
  117. }
  118. } else {
  119. vhost_scsi_stop(s);
  120. }
  121. }
  122. static void vhost_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq)
  123. {
  124. }
  125. static int vhost_scsi_pre_save(void *opaque)
  126. {
  127. VHostSCSICommon *vsc = opaque;
  128. /* At this point, backend must be stopped, otherwise
  129. * it might keep writing to memory. */
  130. assert(!vhost_dev_is_started(&vsc->dev));
  131. return 0;
  132. }
  133. static const VMStateDescription vmstate_virtio_vhost_scsi = {
  134. .name = "virtio-vhost_scsi",
  135. .minimum_version_id = 1,
  136. .version_id = 1,
  137. .fields = (VMStateField[]) {
  138. VMSTATE_VIRTIO_DEVICE,
  139. VMSTATE_END_OF_LIST()
  140. },
  141. .pre_save = vhost_scsi_pre_save,
  142. };
  143. static void vhost_scsi_realize(DeviceState *dev, Error **errp)
  144. {
  145. VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
  146. VHostSCSICommon *vsc = VHOST_SCSI_COMMON(dev);
  147. Error *err = NULL;
  148. int vhostfd = -1;
  149. int ret;
  150. struct vhost_virtqueue *vqs = NULL;
  151. if (!vs->conf.wwpn) {
  152. error_setg(errp, "vhost-scsi: missing wwpn");
  153. return;
  154. }
  155. if (vs->conf.vhostfd) {
  156. vhostfd = monitor_fd_param(monitor_cur(), vs->conf.vhostfd, errp);
  157. if (vhostfd == -1) {
  158. error_prepend(errp, "vhost-scsi: unable to parse vhostfd: ");
  159. return;
  160. }
  161. } else {
  162. vhostfd = open("/dev/vhost-scsi", O_RDWR);
  163. if (vhostfd < 0) {
  164. error_setg(errp, "vhost-scsi: open vhost char device failed: %s",
  165. strerror(errno));
  166. return;
  167. }
  168. }
  169. virtio_scsi_common_realize(dev,
  170. vhost_dummy_handle_output,
  171. vhost_dummy_handle_output,
  172. vhost_dummy_handle_output,
  173. &err);
  174. if (err != NULL) {
  175. error_propagate(errp, err);
  176. goto close_fd;
  177. }
  178. if (!vsc->migratable) {
  179. error_setg(&vsc->migration_blocker,
  180. "vhost-scsi does not support migration in all cases. "
  181. "When external environment supports it (Orchestrator migrates "
  182. "target SCSI device state or use shared storage over network), "
  183. "set 'migratable' property to true to enable migration.");
  184. if (migrate_add_blocker(vsc->migration_blocker, errp) < 0) {
  185. goto free_virtio;
  186. }
  187. }
  188. vsc->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
  189. vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs);
  190. vsc->dev.vqs = vqs;
  191. vsc->dev.vq_index = 0;
  192. vsc->dev.backend_features = 0;
  193. ret = vhost_dev_init(&vsc->dev, (void *)(uintptr_t)vhostfd,
  194. VHOST_BACKEND_TYPE_KERNEL, 0, errp);
  195. if (ret < 0) {
  196. /*
  197. * vhost_dev_init calls vhost_dev_cleanup on error, which closes
  198. * vhostfd, don't double close it.
  199. */
  200. vhostfd = -1;
  201. goto free_vqs;
  202. }
  203. /* At present, channel and lun both are 0 for bootable vhost-scsi disk */
  204. vsc->channel = 0;
  205. vsc->lun = 0;
  206. /* Note: we can also get the minimum tpgt from kernel */
  207. vsc->target = vs->conf.boot_tpgt;
  208. return;
  209. free_vqs:
  210. g_free(vqs);
  211. if (!vsc->migratable) {
  212. migrate_del_blocker(vsc->migration_blocker);
  213. }
  214. free_virtio:
  215. error_free(vsc->migration_blocker);
  216. virtio_scsi_common_unrealize(dev);
  217. close_fd:
  218. if (vhostfd >= 0) {
  219. close(vhostfd);
  220. }
  221. return;
  222. }
  223. static void vhost_scsi_unrealize(DeviceState *dev)
  224. {
  225. VirtIODevice *vdev = VIRTIO_DEVICE(dev);
  226. VHostSCSICommon *vsc = VHOST_SCSI_COMMON(dev);
  227. struct vhost_virtqueue *vqs = vsc->dev.vqs;
  228. if (!vsc->migratable) {
  229. migrate_del_blocker(vsc->migration_blocker);
  230. error_free(vsc->migration_blocker);
  231. }
  232. /* This will stop vhost backend. */
  233. vhost_scsi_set_status(vdev, 0);
  234. vhost_dev_cleanup(&vsc->dev);
  235. g_free(vqs);
  236. virtio_scsi_common_unrealize(dev);
  237. }
  238. static struct vhost_dev *vhost_scsi_get_vhost(VirtIODevice *vdev)
  239. {
  240. VHostSCSI *s = VHOST_SCSI(vdev);
  241. VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
  242. return &vsc->dev;
  243. }
  244. static Property vhost_scsi_properties[] = {
  245. DEFINE_PROP_STRING("vhostfd", VirtIOSCSICommon, conf.vhostfd),
  246. DEFINE_PROP_STRING("wwpn", VirtIOSCSICommon, conf.wwpn),
  247. DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0),
  248. DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues,
  249. VIRTIO_SCSI_AUTO_NUM_QUEUES),
  250. DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon, conf.virtqueue_size,
  251. 128),
  252. DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSICommon, conf.seg_max_adjust,
  253. true),
  254. DEFINE_PROP_UINT32("max_sectors", VirtIOSCSICommon, conf.max_sectors,
  255. 0xFFFF),
  256. DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSICommon, conf.cmd_per_lun, 128),
  257. DEFINE_PROP_BIT64("t10_pi", VHostSCSICommon, host_features,
  258. VIRTIO_SCSI_F_T10_PI,
  259. false),
  260. DEFINE_PROP_BOOL("migratable", VHostSCSICommon, migratable, false),
  261. DEFINE_PROP_END_OF_LIST(),
  262. };
  263. static void vhost_scsi_class_init(ObjectClass *klass, void *data)
  264. {
  265. DeviceClass *dc = DEVICE_CLASS(klass);
  266. VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
  267. FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(klass);
  268. device_class_set_props(dc, vhost_scsi_properties);
  269. dc->vmsd = &vmstate_virtio_vhost_scsi;
  270. set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
  271. vdc->realize = vhost_scsi_realize;
  272. vdc->unrealize = vhost_scsi_unrealize;
  273. vdc->get_features = vhost_scsi_common_get_features;
  274. vdc->set_config = vhost_scsi_common_set_config;
  275. vdc->set_status = vhost_scsi_set_status;
  276. vdc->get_vhost = vhost_scsi_get_vhost;
  277. fwc->get_dev_path = vhost_scsi_common_get_fw_dev_path;
  278. }
  279. static void vhost_scsi_instance_init(Object *obj)
  280. {
  281. VHostSCSICommon *vsc = VHOST_SCSI_COMMON(obj);
  282. vsc->feature_bits = kernel_feature_bits;
  283. device_add_bootindex_property(obj, &vsc->bootindex, "bootindex", NULL,
  284. DEVICE(vsc));
  285. }
  286. static const TypeInfo vhost_scsi_info = {
  287. .name = TYPE_VHOST_SCSI,
  288. .parent = TYPE_VHOST_SCSI_COMMON,
  289. .instance_size = sizeof(VHostSCSI),
  290. .class_init = vhost_scsi_class_init,
  291. .instance_init = vhost_scsi_instance_init,
  292. .interfaces = (InterfaceInfo[]) {
  293. { TYPE_FW_PATH_PROVIDER },
  294. { }
  295. },
  296. };
  297. static void virtio_register_types(void)
  298. {
  299. type_register_static(&vhost_scsi_info);
  300. }
  301. type_init(virtio_register_types)