From 3c3281de9733c9dc04073477ced77fde8b085564 Mon Sep 17 00:00:00 2001 From: Dariusz Stojaczyk Date: Thu, 10 Aug 2017 19:51:40 +0200 Subject: [PATCH] vhost: added public documentation Change-Id: Ib857d996ebc971ee28f5c9e88725ff6ee2a4febe Signed-off-by: Dariusz Stojaczyk Reviewed-on: https://review.gerrithub.io/373761 Tested-by: SPDK Automated Test System Reviewed-by: Daniel Verkamp Reviewed-by: Pawel Wodkowski Reviewed-by: Jim Harris --- include/spdk/vhost.h | 193 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 177 insertions(+), 16 deletions(-) diff --git a/include/spdk/vhost.h b/include/spdk/vhost.h index 565281503..15e20c2bb 100644 --- a/include/spdk/vhost.h +++ b/include/spdk/vhost.h @@ -47,40 +47,202 @@ int spdk_vhost_init(void); int spdk_vhost_fini(void); /** - * \param event event object. event arg1 is optional path to vhost socket. + * Init vhost application. This is called once by SPDK app layer. + * \param arg1 optional path to directory where sockets will + * be created + * \param arg2 unused */ void spdk_vhost_startup(void *arg1, void *arg2); + +/** + * Deinit vhost application. This is called once by SPDK app layer. + */ void spdk_vhost_shutdown_cb(void); -/* Forward declaration */ +/** + * SPDK vhost device (vdev). An equivalent of Virtio device. + * Both virtio-blk and virtio-scsi devices are represented by this + * struct. For virtio-scsi a single vhost device (also called SCSI + * controller) may contain multiple devices (SCSI targets), each of + * which may contain multiple logical units (SCSI LUNs). For now + * only one LUN per device is available. + * + * All vdev-changing functions operate directly on this object. + * Note that \c spdk_vhost_dev cannot be acquired. This object is + * only accessible as a callback parameter via \c + * spdk_vhost_call_external_event and it's derivatives. This ensures + * that all access to the vdev is piped through a single, + * thread-safe API. + */ struct spdk_vhost_dev; -typedef int (*spdk_vhost_event_fn)(struct spdk_vhost_dev *, void *); +/** + * Synchronized vhost event used for user callbacks. + * + * \param vdev vhost device + * \param arg user-provided parameter + * \return 0 on success, -1 on failure + */ +typedef int (*spdk_vhost_event_fn)(struct spdk_vhost_dev *vdev, void *arg); -const char *spdk_vhost_dev_get_name(struct spdk_vhost_dev *ctrl); -uint64_t spdk_vhost_dev_get_cpumask(struct spdk_vhost_dev *ctrl); +/** + * Get name of the vhost device. This is equal to the filename + * of socket file. The name is constant throughout the lifetime of + * a vdev. + * + * \param vdev vhost device + * \return name of the vdev + */ +const char *spdk_vhost_dev_get_name(struct spdk_vhost_dev *vdev); +/** + * Get cpumask of the vhost device. The mask is constant + * throughout the lifetime of a vdev. It is be a subset + * of SPDK app cpumask vhost was started with. + * + * \param dev vhost device + * \return cpumask of the vdev. The mask is constructed as: + * ((1 << cpu0) | (1 << cpu1) | ... | (1 << cpuN)). + */ +uint64_t spdk_vhost_dev_get_cpumask(struct spdk_vhost_dev *vdev); + +/** + * Construct an empty vhost SCSI device. This will create a + * Unix domain socket together with a vhost-user slave server waiting + * for a connection on this socket. Creating the vdev does not + * start any I/O pollers and does not hog the CPU. I/O processing + * starts after receiving proper message on the created socket. + * See QEMU's vhost-user documentation for details. + * All physical devices have to be separately attached to this + * vdev via \c spdk_vhost_scsi_dev_add_dev(). + * + * This function is thread-safe. + * + * \param name name of the vhost device. The name will also be used + * for socket name, which is exactly \c socket_base_dir/name + * \param mask string containing cpumask in hex. The leading *0x* + * is allowed but not required. The mask itself can be constructed as: + * ((1 << cpu0) | (1 << cpu1) | ... | (1 << cpuN)). + * \return 0 on success, negative errno on error. + */ int spdk_vhost_scsi_dev_construct(const char *name, const char *cpumask); + +/** + * Remove an empty vhost SCSI device. The vdev must not + * have any SCSI devices attached nor have any open connection on + * it's socket. + * + * \param vdev vhost SCSI device + * \return 0 on success, negative errno on error. + */ int spdk_vhost_scsi_dev_remove(struct spdk_vhost_dev *vdev); -struct spdk_scsi_dev *spdk_vhost_scsi_dev_get_dev(struct spdk_vhost_dev *ctrl, uint8_t num); + +/** + * Construct and attach new SCSI device to the vhost SCSI device + * on given (unoccupied) slot. The device will be created with a single + * LUN0 associated with given SPDK bdev. Currently only one LUN per + * device is supported. + * + * If vhost SCSI device has an active socket connection, it is + * required that it has negotiated \c VIRTIO_SCSI_F_HOTPLUG feature + * flag. Otherwise an -ENOTSUP error code is returned. + * + * \param vdev vhost SCSI device + * \param scsi_dev_num slot to attach to + * \param lun_name name of the SPDK bdev to associate with SCSI LUN0 + * \return 0 on success, negative errno on error. + */ int spdk_vhost_scsi_dev_add_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_num, const char *lun_name); + +/** + * Get SCSI device from vhost SCSI device on given slot. Max + * number of available slots is defined by + * \c SPDK_VHOST_SCSI_CTRLR_MAX_DEVS. + * + * \param vdev vhost SCSI device + * \param num slot id + * \return SCSI device on given slot or NULL + */ +struct spdk_scsi_dev *spdk_vhost_scsi_dev_get_dev(struct spdk_vhost_dev *vdev, uint8_t num); + +/** + * Detach and destruct SCSI device from a vhost SCSI device. + * + * If vhost SCSI device has an active socket connection, it is + * required that it has negotiated \c VIRTIO_SCSI_F_HOTPLUG feature + * flag.Otherwise an -ENOTSUP error code is returned. If the flag has + * been negotiated, the device will be marked to be deleted. Actual + * deletion is deferred until after all pending I/O to this device + * has finished. + * + * Once the device has been deleted (whether or not vhost SCSI + * device is in use) given callback will be called. + * + * \param vdev vhost SCSI device + * \param scsi_dev_num slot id to delete device from + * \param cb_fn callback to be fired once device has been successfully + * deleted. The first parameter of callback function is the vhost SCSI + * device, the second is user provided argument *cb_arg*. + * \param cb_arg parameter to be passed to *cb_fn*. + * \return 0 on success, negative errno on error. + */ int spdk_vhost_scsi_dev_remove_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_num, spdk_vhost_event_fn cb_fn, void *cb_arg); +/** + * Construct a vhost blk device. This will create a Unix domain + * socket together with a vhost-user slave server waiting for a + * connection on this socket. Creating the vdev does not start + * any I/O pollers and does not hog the CPU. I/O processing starts + * after receiving proper message on the created socket. + * See QEMU's vhost-user documentation for details. Vhost blk + * device is tightly associated with given SPDK bdev. Given + * bdev can not be changed, unless it has been hotremoved. This + * would result in all I/O failing with virtio \c VIRTIO_BLK_S_IOERR + * error code. + * + * This function is thread-safe. + * + * \param name name of the vhost blk device. The name will also be + * used for socket name, which is exactly \c socket_base_dir/name + * \param mask string containing cpumask in hex. The leading *0x* + * is allowed but not required. The mask itself can be constructed as: + * ((1 << cpu0) | (1 << cpu1) | ... | (1 << cpuN)). + * \param dev_name bdev name to associate with this vhost device + * \param readonly if set, all writes to the device will fail with + * \c VIRTIO_BLK_S_IOERR error code. + * \return 0 on success, negative errno on error. + */ int spdk_vhost_blk_construct(const char *name, const char *cpumask, const char *dev_name, bool readonly); + +/** + * Remove a vhost blk device. The device must not have any + * open connections on it's socket. + * + * \param vdev vhost blk device + * \return 0 on success, negative errno on error. + */ int spdk_vhost_blk_destroy(struct spdk_vhost_dev *dev); + +/** + * Get underlying SPDK bdev from vhost blk device. The + * bdev might be NULL, as it could have been hotremoved. + * + * \param ctrl vhost blk device + * \return SPDK bdev associated with given vdev + */ struct spdk_bdev *spdk_vhost_blk_get_dev(struct spdk_vhost_dev *ctrlr); /** - * Call function on reactor of given vhost controller. - * If controller is not in use, the event will be called + * Call function on reactor of given vhost device. If + * device is not in use, the event will be called * right away on the caller's thread. * * This function is thread safe. * - * \param ctrlr_name name of the vhost controller to run + * \param vdev_name name of the vhost device to run * this event on * \param fn function to be called. The first parameter * of callback function is either actual spdk_vhost_dev @@ -88,20 +250,19 @@ struct spdk_bdev *spdk_vhost_blk_get_dev(struct spdk_vhost_dev *ctrlr); * exist. The second param is user provided argument *arg*. * \param arg parameter to be passed to *fn*. */ -void spdk_vhost_call_external_event(const char *ctrlr_name, spdk_vhost_event_fn fn, void *arg); +void spdk_vhost_call_external_event(const char *vdev_name, spdk_vhost_event_fn fn, void *arg); /** - * Call function for each available vhost controller on - * it's reactor. This will call given function in a chain, + * Call function for each available vhost device on + * it's reactor. This will call given function in a chain, * meaning that each callback will be called after the * previous one has finished. After given function has - * been called for all controllers, it will be called - * once again with first param - vhost controller - set - * to NULL. + * been called for all vdevs, it will be called once + * again with first param - vhost device- set to NULL. * * This function is thread safe. * - * \param fn function to be called for each controller. + * \param fn function to be called for each vdev. * The first param will be either vdev pointer or NULL. * The second param is user provided argument *arg*. * \param arg parameter to be passed to *fn*.