Commit 48aced6e authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Jim Harris
Browse files

virtio: move virtio_dev allocation to upper layers



This allows the to use a virtio_dev allocated as
a part of bigger struct - possibly a SCSI/BLK
specific wrapper.

As a part of this refactor, multiple vdev-related
functions have been renamed to keep the API clean.

Change-Id: If84bf03e4a1642869c2f1ba93939fb32c8fb5d57
Signed-off-by: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/388298


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent 04f52893
Loading
Loading
Loading
Loading
+30 −13
Original line number Diff line number Diff line
@@ -574,8 +574,9 @@ scan_target_abort(struct virtio_scsi_scan_base *base, int error)
	}

	TAILQ_REMOVE(&g_virtio_driver.init_ctrlrs, base->vdev, tailq);
	virtio_dev_reset(base->vdev);
	virtio_dev_free(base->vdev);
	virtio_dev_stop(base->vdev);
	virtio_dev_destruct(base->vdev);
	free(base->vdev);


	if (base->cb_fn) {
@@ -1147,19 +1148,26 @@ bdev_virtio_process_config(void)
			num_queues = 1;
		}

		vdev = calloc(1, sizeof(*vdev));
		if (vdev == NULL) {
			SPDK_ERRLOG("virtio device calloc failed\n");
			goto out;
		}

		name = spdk_conf_section_get_val(sp, "Name");
		if (name == NULL) {
			default_name = spdk_sprintf_alloc("VirtioScsi%u", vdev_num);
			name = default_name;
		}

		vdev = virtio_user_dev_init(name, path, num_queues, 512, SPDK_VIRTIO_SCSI_QUEUE_NUM_FIXED);
		rc = virtio_user_dev_init(vdev, name, path, num_queues, 512,
					  SPDK_VIRTIO_SCSI_QUEUE_NUM_FIXED);

		free(default_name);
		default_name = NULL;

		if (vdev == NULL) {
			rc = -1;
		if (rc != 0) {
			free(vdev);
			goto out;
		}
	}
@@ -1191,8 +1199,9 @@ bdev_virtio_scsi_free(struct virtio_dev *vdev)
		virtio_dev_release_queue(vdev, VIRTIO_SCSI_REQUESTQ);
	}

	virtio_dev_reset(vdev);
	virtio_dev_free(vdev);
	virtio_dev_stop(vdev);
	virtio_dev_destruct(vdev);
	free(vdev);
}

static int
@@ -1211,7 +1220,7 @@ bdev_virtio_scsi_scan(struct virtio_dev *vdev, virtio_create_device_cb cb_fn, vo
	base->cb_fn = cb_fn;
	base->cb_arg = cb_arg;

	rc = virtio_dev_init(vdev, VIRTIO_SCSI_DEV_SUPPORTED_FEATURES);
	rc = virtio_dev_restart(vdev, VIRTIO_SCSI_DEV_SUPPORTED_FEATURES);
	if (rc != 0) {
		spdk_dma_free(base);
		return rc;
@@ -1312,8 +1321,9 @@ virtio_scsi_dev_unregister_cb(void *io_device)
		virtio_dev_release_queue(vdev, VIRTIO_SCSI_CONTROLQ);
	}

	virtio_dev_reset(vdev);
	virtio_dev_free(vdev);
	virtio_dev_stop(vdev);
	virtio_dev_destruct(vdev);
	free(vdev);

	TAILQ_REMOVE(&g_virtio_driver.attached_ctrlrs, vdev, tailq);
	finish_module = TAILQ_EMPTY(&g_virtio_driver.attached_ctrlrs);
@@ -1345,10 +1355,17 @@ create_virtio_user_scsi_device(const char *base_name, const char *path, unsigned
	struct virtio_dev *vdev;
	int rc;

	vdev = virtio_user_dev_init(base_name, path, num_queues, queue_size,
	vdev = calloc(1, sizeof(*vdev));
	if (vdev == NULL) {
		SPDK_ERRLOG("calloc failed for virtio device %s: %s\n", base_name, path);
		return -ENOMEM;
	}

	rc = virtio_user_dev_init(vdev, base_name, path, num_queues, queue_size,
				  SPDK_VIRTIO_SCSI_QUEUE_NUM_FIXED);
	if (!vdev) {
	if (rc != 0) {
		SPDK_ERRLOG("Failed to create virito device %s: %s\n", base_name, path);
		free(vdev);
		return -EINVAL;
	}

+8 −17
Original line number Diff line number Diff line
@@ -315,31 +315,23 @@ virtio_negotiate_features(struct virtio_dev *dev, uint64_t req_features)
	return 0;
}

struct virtio_dev *
	virtio_dev_construct(const struct virtio_dev_ops *ops, void *ctx)
int
virtio_dev_construct(struct virtio_dev *vdev, const struct virtio_dev_ops *ops, void *ctx)
{
	struct virtio_dev *vdev;

	vdev = calloc(1, sizeof(*vdev));
	if (vdev == NULL) {
		SPDK_ERRLOG("virtio device calloc failed\n");
		return NULL;
	}

	pthread_mutex_init(&vdev->mutex, NULL);
	vdev->backend_ops = ops;
	vdev->ctx = ctx;

	return vdev;
	return 0;
}

int
virtio_dev_init(struct virtio_dev *dev, uint64_t req_features)
virtio_dev_restart(struct virtio_dev *dev, uint64_t req_features)
{
	int ret;

	/* Reset the device although not necessary at startup */
	virtio_dev_reset(dev);
	virtio_dev_stop(dev);

	/* Tell the host we've noticed this device. */
	virtio_dev_set_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
@@ -358,12 +350,11 @@ virtio_dev_init(struct virtio_dev *dev, uint64_t req_features)
}

void
virtio_dev_free(struct virtio_dev *dev)
virtio_dev_destruct(struct virtio_dev *dev)
{
	virtio_free_queues(dev);
	virtio_dev_backend_ops(dev)->free_vdev(dev);
	virtio_dev_backend_ops(dev)->destruct_dev(dev);
	pthread_mutex_destroy(&dev->mutex);
	free(dev);
}

static void
@@ -688,7 +679,7 @@ virtio_dev_write_dev_config(struct virtio_dev *dev, size_t offset,
}

void
virtio_dev_reset(struct virtio_dev *dev)
virtio_dev_stop(struct virtio_dev *dev)
{
	virtio_dev_backend_ops(dev)->set_status(dev, VIRTIO_CONFIG_S_RESET);
	/* flush status write */
+38 −24
Original line number Diff line number Diff line
@@ -112,8 +112,8 @@ struct virtio_dev_ops {
	 */
	int (*set_features)(struct virtio_dev *vdev, uint64_t features);

	/** Deinit and free virtio device */
	void (*free_vdev)(struct virtio_dev *vdev);
	/** Destruct virtio device */
	void (*destruct_dev)(struct virtio_dev *vdev);

	uint16_t (*get_queue_num)(struct virtio_dev *hw, uint16_t queue_id);
	int (*setup_queue)(struct virtio_dev *hw, struct virtqueue *vq);
@@ -210,22 +210,42 @@ uint16_t virtio_recv_pkts(struct virtqueue *vq, struct virtio_req **reqs,
int virtio_xmit_pkt(struct virtqueue *vq, struct virtio_req *req);

/**
 * Construct virtio device.  This will set vdev->id field.
 * The device has to be freed with \c virtio_dev_free.
 * Construct a virtio device.  The device will be in stopped state by default.
 * Before doing any I/O, it has to be manually started via \c virtio_dev_restart.
 *
 * \param vdev memory for virtio device, must be zeroed
 * \param ops backend callbacks
 * \param ctx argument for the backend callbacks
 */
struct virtio_dev *virtio_dev_construct(const struct virtio_dev_ops *ops, void *ctx);
int virtio_dev_construct(struct virtio_dev *vdev, const struct virtio_dev_ops *ops,
			 void *ctx);

/**
 * Reset and reinit a virtio device.  This will also renegotiate feature flags.
 * Notify the host to start processing this virtio device.  This is
 * a blocking call that won't return until the host has started.
 * This call will also allocate virtqueues and renegotiate feature flags.
 *
 * \param vdev vhost device
 * \param vdev virtio device
 * \param req_features features this driver supports
 */
int virtio_dev_init(struct virtio_dev *vdev, uint64_t req_features);
void virtio_dev_free(struct virtio_dev *dev);
int virtio_dev_restart(struct virtio_dev *vdev, uint64_t req_features);

/**
 * Stop the host from processing the device.  This is a blocking call
 * that won't return until all outstanding I/O has been processed on
 * the host (virtio device) side.
 *
 * \param vdev virtio device
 */
void virtio_dev_stop(struct virtio_dev *vdev);

/**
 * Destruct a virtio device.  Note that it must be in the stopped state.
 * The virtio_dev should be manually freed afterwards.
 *
 * \param vdev virtio device
 */
void virtio_dev_destruct(struct virtio_dev *vdev);

/**
 * Bind a virtqueue with given index to the current thread;
@@ -286,14 +306,6 @@ bool virtio_dev_queue_is_acquired(struct virtio_dev *vdev, uint16_t index);
 */
void virtio_dev_release_queue(struct virtio_dev *vdev, uint16_t index);

/**
 * Reset given virtio device.  This will leave the device in unusable state.
 * To reuse the device, call \c virtio_dev_init.
 *
 * \param vdev virtio device
 */
void virtio_dev_reset(struct virtio_dev *vdev);

/**
 * Get Virtio status flags.
 *
@@ -303,9 +315,9 @@ uint8_t virtio_dev_get_status(struct virtio_dev *vdev);

/**
 * Set Virtio status flag.  The flags have to be set in very specific order
 * defined the VirtIO 1.0 spec section 3.1.1. To unset the flags, call
 * \c virtio_dev_reset or set \c VIRTIO_CONFIG_S_RESET flag. There is
 * no way to unset particular flags.
 * defined the VIRTIO 1.0 spec section 3.1.1. To unset the flags, stop the
 * device or set \c VIRTIO_CONFIG_S_RESET status flag. There is no way to
 * unset only particular flags.
 *
 * \param vdev virtio device
 * \param flag flag to set
@@ -367,8 +379,10 @@ void virtio_dev_dump_json_config(struct virtio_dev *vdev, struct spdk_json_write
int virtio_enumerate_pci(void);

/**
 * Connect to a vhost-user device and create corresponding virtio_dev.
 * Connect to a vhost-user device and init corresponding virtio_dev struct.
 * The virtio_dev will have to be freed with \c virtio_dev_free.
 *
 * \param vdev preallocated vhost device struct to operate on
 * \param name name of this virtio device
 * \param path path to the Unix domain socket of the vhost-user device
 * \param requested_queues maximum number of request queues that this
@@ -379,8 +393,8 @@ int virtio_enumerate_pci(void);
 * additional event and control queues.
 * \return virtio device
 */
struct virtio_dev *virtio_user_dev_init(const char *name, const char *path,
					uint16_t requested_queues,
					uint32_t queue_size, uint16_t fixed_queue_num);
int virtio_user_dev_init(struct virtio_dev *vdev, const char *name, const char *path,
			 uint16_t requested_queues, uint32_t queue_size,
			 uint16_t fixed_queue_num);

#endif /* SPDK_VIRTIO_H */
+12 −4
Original line number Diff line number Diff line
@@ -198,7 +198,7 @@ modern_set_features(struct virtio_dev *dev, uint64_t features)
}

static void
modern_free_vdev(struct virtio_dev *vdev)
modern_destruct_dev(struct virtio_dev *vdev)
{
	struct virtio_hw *hw = vdev->ctx;

@@ -301,7 +301,7 @@ static const struct virtio_dev_ops modern_ops = {
	.set_status	= modern_set_status,
	.get_features	= modern_get_features,
	.set_features	= modern_set_features,
	.free_vdev	= modern_free_vdev,
	.destruct_dev	= modern_destruct_dev,
	.get_queue_num	= modern_get_queue_num,
	.setup_queue	= modern_setup_queue,
	.del_queue	= modern_del_queue,
@@ -470,8 +470,16 @@ pci_enum_virtio_probe_cb(void *ctx, struct spdk_pci_device *pci_dev)
		return -1;
	}

	vdev = virtio_dev_construct(&modern_ops, hw);
	vdev = calloc(1, sizeof(*vdev));
	if (vdev == NULL) {
		SPDK_ERRLOG("calloc failed\n");
		free_virtio_hw(hw);
		return -1;
	}

	rc = virtio_dev_construct(vdev, &modern_ops, hw);
	if (rc != 0) {
		free(vdev);
		free_virtio_hw(hw);
		return -1;
	}
@@ -486,7 +494,7 @@ pci_enum_virtio_probe_cb(void *ctx, struct spdk_pci_device *pci_dev)
	return 0;

err:
	virtio_dev_free(vdev);
	virtio_dev_destruct(vdev);
	return -1;
}

+15 −16
Original line number Diff line number Diff line
@@ -345,7 +345,7 @@ virtio_user_notify_queue(struct virtio_dev *vdev, struct virtqueue *vq)
}

static void
virtio_user_free(struct virtio_dev *vdev)
virtio_user_destroy(struct virtio_dev *vdev)
{
	struct virtio_user_dev *dev = vdev->ctx;

@@ -373,7 +373,7 @@ static const struct virtio_dev_ops virtio_user_ops = {
	.set_status	= virtio_user_set_status,
	.get_features	= virtio_user_get_features,
	.set_features	= virtio_user_set_features,
	.free_vdev	= virtio_user_free,
	.destruct_dev	= virtio_user_destroy,
	.get_queue_num	= virtio_user_get_queue_num,
	.setup_queue	= virtio_user_setup_queue,
	.del_queue	= virtio_user_del_queue,
@@ -381,34 +381,33 @@ static const struct virtio_dev_ops virtio_user_ops = {
	.dump_json_config = virtio_user_dump_json_config,
};

struct virtio_dev *
virtio_user_dev_init(const char *name, const char *path, uint16_t requested_queues,
		     uint32_t queue_size,
		     uint16_t fixed_queue_num)
int
virtio_user_dev_init(struct virtio_dev *vdev, const char *name, const char *path,
		     uint16_t requested_queues, uint32_t queue_size, uint16_t fixed_queue_num)
{
	struct virtio_dev *vdev;
	struct virtio_user_dev *dev;
	uint64_t max_queues;
	char err_str[64];
	int rc;

	if (name == NULL) {
		SPDK_ERRLOG("No name gived for controller: %s\n", path);
		return NULL;
		return -1;
	} else if (requested_queues == 0) {
		SPDK_ERRLOG("Can't create controller with no queues: %s\n", path);
		return NULL;
		return -1;
	}

	dev = calloc(1, sizeof(*dev));
	if (dev == NULL) {
		return NULL;
		return -1;
	}

	vdev = virtio_dev_construct(&virtio_user_ops, dev);
	if (vdev == NULL) {
	rc = virtio_dev_construct(vdev, &virtio_user_ops, dev);
	if (rc != 0) {
		SPDK_ERRLOG("Failed to init device: %s\n", path);
		free(dev);
		return NULL;
		return -1;
	}

	vdev->is_hw = 0;
@@ -447,9 +446,9 @@ virtio_user_dev_init(const char *name, const char *path, uint16_t requested_queu
	}

	TAILQ_INSERT_TAIL(&g_virtio_driver.init_ctrlrs, vdev, tailq);
	return vdev;
	return 0;

err:
	virtio_dev_free(vdev);
	return NULL;
	virtio_dev_destruct(vdev);
	return -1;
}