* [PATCH v9 0/3] tcm_vhost hotplug
@ 2013-04-25 3:10 Asias He
2013-04-25 3:10 ` [PATCH v9 1/3] tcm_vhost: Refactor the lock nesting rule Asias He
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Asias He @ 2013-04-25 3:10 UTC (permalink / raw)
To: Nicholas Bellinger
Cc: kvm, Michael S. Tsirkin, virtualization, target-devel,
Stefan Hajnoczi, Paolo Bonzini
Asias He (3):
tcm_vhost: Refactor the lock nesting rule
tcm_vhost: Add hotplug/hotunplug support
tcm_vhost: Add ioctl to get and set events missed flag
drivers/vhost/tcm_vhost.c | 263 +++++++++++++++++++++++++++++++++++++++++++---
drivers/vhost/tcm_vhost.h | 13 +++
2 files changed, 260 insertions(+), 16 deletions(-)
--
1.8.1.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v9 1/3] tcm_vhost: Refactor the lock nesting rule
2013-04-25 3:10 [PATCH v9 0/3] tcm_vhost hotplug Asias He
@ 2013-04-25 3:10 ` Asias He
2013-04-25 5:44 ` Michael S. Tsirkin
2013-04-25 3:10 ` [PATCH v9 2/3] tcm_vhost: Add hotplug/hotunplug support Asias He
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Asias He @ 2013-04-25 3:10 UTC (permalink / raw)
To: Nicholas Bellinger
Cc: kvm, Michael S. Tsirkin, virtualization, target-devel,
Stefan Hajnoczi, Paolo Bonzini
We want to use tcm_vhost_mutex to make sure hotplug/hotunplug will not
happen when set_endpoint/clear_endpoint is in process.
Signed-off-by: Asias He <asias@redhat.com>
---
drivers/vhost/tcm_vhost.c | 32 +++++++++++++++++++-------------
1 file changed, 19 insertions(+), 13 deletions(-)
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
index 957a0b9..822cd1f 100644
--- a/drivers/vhost/tcm_vhost.c
+++ b/drivers/vhost/tcm_vhost.c
@@ -808,6 +808,9 @@ static void vhost_scsi_flush(struct vhost_scsi *vs)
/*
* Called from vhost_scsi_ioctl() context to walk the list of available
* tcm_vhost_tpg with an active struct tcm_vhost_nexus
+ *
+ * The lock nesting rule is:
+ * tcm_vhost_mutex -> vs->dev.mutex -> tpg->tv_tpg_mutex -> vq->mutex
*/
static int vhost_scsi_set_endpoint(
struct vhost_scsi *vs,
@@ -820,26 +823,27 @@ static int vhost_scsi_set_endpoint(
int index, ret, i, len;
bool match = false;
+ mutex_lock(&tcm_vhost_mutex);
mutex_lock(&vs->dev.mutex);
+
/* Verify that ring has been setup correctly. */
for (index = 0; index < vs->dev.nvqs; ++index) {
/* Verify that ring has been setup correctly. */
if (!vhost_vq_access_ok(&vs->vqs[index])) {
- mutex_unlock(&vs->dev.mutex);
- return -EFAULT;
+ ret = -EFAULT;
+ goto out;
}
}
len = sizeof(vs_tpg[0]) * VHOST_SCSI_MAX_TARGET;
vs_tpg = kzalloc(len, GFP_KERNEL);
if (!vs_tpg) {
- mutex_unlock(&vs->dev.mutex);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
if (vs->vs_tpg)
memcpy(vs_tpg, vs->vs_tpg, len);
- mutex_lock(&tcm_vhost_mutex);
list_for_each_entry(tv_tpg, &tcm_vhost_list, tv_tpg_list) {
mutex_lock(&tv_tpg->tv_tpg_mutex);
if (!tv_tpg->tpg_nexus) {
@@ -854,11 +858,10 @@ static int vhost_scsi_set_endpoint(
if (!strcmp(tv_tport->tport_name, t->vhost_wwpn)) {
if (vs->vs_tpg && vs->vs_tpg[tv_tpg->tport_tpgt]) {
- mutex_unlock(&tv_tpg->tv_tpg_mutex);
- mutex_unlock(&tcm_vhost_mutex);
- mutex_unlock(&vs->dev.mutex);
kfree(vs_tpg);
- return -EEXIST;
+ mutex_unlock(&tv_tpg->tv_tpg_mutex);
+ ret = -EEXIST;
+ goto out;
}
tv_tpg->tv_tpg_vhost_count++;
vs_tpg[tv_tpg->tport_tpgt] = tv_tpg;
@@ -867,7 +870,6 @@ static int vhost_scsi_set_endpoint(
}
mutex_unlock(&tv_tpg->tv_tpg_mutex);
}
- mutex_unlock(&tcm_vhost_mutex);
if (match) {
memcpy(vs->vs_vhost_wwpn, t->vhost_wwpn,
@@ -893,7 +895,9 @@ static int vhost_scsi_set_endpoint(
kfree(vs->vs_tpg);
vs->vs_tpg = vs_tpg;
+out:
mutex_unlock(&vs->dev.mutex);
+ mutex_unlock(&tcm_vhost_mutex);
return ret;
}
@@ -908,6 +912,7 @@ static int vhost_scsi_clear_endpoint(
int index, ret, i;
u8 target;
+ mutex_lock(&tcm_vhost_mutex);
mutex_lock(&vs->dev.mutex);
/* Verify that ring has been setup correctly. */
for (index = 0; index < vs->dev.nvqs; ++index) {
@@ -918,8 +923,8 @@ static int vhost_scsi_clear_endpoint(
}
if (!vs->vs_tpg) {
- mutex_unlock(&vs->dev.mutex);
- return 0;
+ ret = 0;
+ goto err_dev;
}
for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) {
@@ -965,13 +970,14 @@ static int vhost_scsi_clear_endpoint(
kfree(vs->vs_tpg);
vs->vs_tpg = NULL;
mutex_unlock(&vs->dev.mutex);
-
+ mutex_unlock(&tcm_vhost_mutex);
return 0;
err_tpg:
mutex_unlock(&tv_tpg->tv_tpg_mutex);
err_dev:
mutex_unlock(&vs->dev.mutex);
+ mutex_unlock(&tcm_vhost_mutex);
return ret;
}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v9 2/3] tcm_vhost: Add hotplug/hotunplug support
2013-04-25 3:10 [PATCH v9 0/3] tcm_vhost hotplug Asias He
2013-04-25 3:10 ` [PATCH v9 1/3] tcm_vhost: Refactor the lock nesting rule Asias He
@ 2013-04-25 3:10 ` Asias He
2013-04-25 5:52 ` Michael S. Tsirkin
2013-04-25 3:10 ` [PATCH v9 3/3] tcm_vhost: Add ioctl to get and set events missed flag Asias He
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Asias He @ 2013-04-25 3:10 UTC (permalink / raw)
To: Nicholas Bellinger
Cc: kvm, Michael S. Tsirkin, virtualization, target-devel,
Stefan Hajnoczi, Paolo Bonzini
In commit 365a7150094 ([SCSI] virtio-scsi: hotplug support for
virtio-scsi), hotplug support is added to virtio-scsi.
This patch adds hotplug and hotunplug support to tcm_vhost.
You can create or delete a LUN in targetcli to hotplug or hotunplug a
LUN in guest.
Changes in v8:
- Use vq->mutex for event
- Drop tcm_vhost: Add helper to check if endpoint is setup
- Rename vs_events_dropped to vs_events_missed
- Init lun[] explicitly
Changes in v7:
- Add vhost_work_flush for vs->vs_event_work to this series
Changes in v6:
- Pass tcm_vhost_evt to tcm_vhost_do_evt_work
Changes in v5:
- Switch to int from u64 to vs_events_nr
- Set s->vs_events_dropped flag in tcm_vhost_allocate_evt
- Do not nest dev mutex within vq mutex
- Use vs_events_lock to protect vs_events_dropped and vs_events_nr
- Rebase to target/master
Changes in v4:
- Drop tcm_vhost_check_endpoint in tcm_vhost_send_evt
- Add tcm_vhost_check_endpoint in vhost_scsi_evt_handle_kick
Changes in v3:
- Separate the bug fix to another thread
Changes in v2:
- Remove code duplication in tcm_vhost_{hotplug,hotunplug}
- Fix racing of vs_events_nr
- Add flush fix patch to this series
Signed-off-by: Asias He <asias@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
drivers/vhost/tcm_vhost.c | 214 +++++++++++++++++++++++++++++++++++++++++++++-
drivers/vhost/tcm_vhost.h | 10 +++
2 files changed, 221 insertions(+), 3 deletions(-)
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
index 822cd1f..137ae34 100644
--- a/drivers/vhost/tcm_vhost.c
+++ b/drivers/vhost/tcm_vhost.c
@@ -66,11 +66,13 @@ enum {
* TODO: debug and remove the workaround.
*/
enum {
- VHOST_SCSI_FEATURES = VHOST_FEATURES & (~VIRTIO_RING_F_EVENT_IDX)
+ VHOST_SCSI_FEATURES = (VHOST_FEATURES & (~VIRTIO_RING_F_EVENT_IDX)) |
+ (1ULL << VIRTIO_SCSI_F_HOTPLUG)
};
#define VHOST_SCSI_MAX_TARGET 256
#define VHOST_SCSI_MAX_VQ 128
+#define VHOST_SCSI_MAX_EVENT 128
struct vhost_scsi {
/* Protected by vhost_scsi->dev.mutex */
@@ -82,6 +84,12 @@ struct vhost_scsi {
struct vhost_work vs_completion_work; /* cmd completion work item */
struct llist_head vs_completion_list; /* cmd completion queue */
+
+ struct vhost_work vs_event_work; /* evt injection work item */
+ struct llist_head vs_event_list; /* evt injection queue */
+
+ bool vs_events_missed; /* any missed events, protected by vq->mutex */
+ int vs_events_nr; /* num of pending events, protected by vq->mutex */
};
/* Local pointer to allocated TCM configfs fabric module */
@@ -349,6 +357,37 @@ static int tcm_vhost_queue_tm_rsp(struct se_cmd *se_cmd)
return 0;
}
+static void tcm_vhost_free_evt(struct vhost_scsi *vs, struct tcm_vhost_evt *evt)
+{
+ vs->vs_events_nr--;
+ kfree(evt);
+}
+
+static struct tcm_vhost_evt *tcm_vhost_allocate_evt(struct vhost_scsi *vs,
+ u32 event, u32 reason)
+{
+ struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
+ struct tcm_vhost_evt *evt;
+
+ if (vs->vs_events_nr > VHOST_SCSI_MAX_EVENT) {
+ vs->vs_events_missed = true;
+ return NULL;
+ }
+
+ evt = kzalloc(sizeof(*evt), GFP_KERNEL);
+ if (!evt) {
+ vq_err(vq, "Failed to allocate tcm_vhost_evt\n");
+ vs->vs_events_missed = true;
+ return NULL;
+ }
+
+ evt->event.event = event;
+ evt->event.reason = reason;
+ vs->vs_events_nr++;
+
+ return evt;
+}
+
static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd)
{
struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd;
@@ -367,6 +406,75 @@ static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd)
kfree(tv_cmd);
}
+static void tcm_vhost_do_evt_work(struct vhost_scsi *vs,
+ struct tcm_vhost_evt *evt)
+{
+ struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
+ struct virtio_scsi_event *event = &evt->event;
+ struct virtio_scsi_event __user *eventp;
+ unsigned out, in;
+ int head, ret;
+
+ if (!vq->private_data) {
+ vs->vs_events_missed = true;
+ return;
+ }
+
+again:
+ vhost_disable_notify(&vs->dev, vq);
+ head = vhost_get_vq_desc(&vs->dev, vq, vq->iov,
+ ARRAY_SIZE(vq->iov), &out, &in,
+ NULL, NULL);
+ if (head < 0) {
+ vs->vs_events_missed = true;
+ return;
+ }
+ if (head == vq->num) {
+ if (vhost_enable_notify(&vs->dev, vq))
+ goto again;
+ vs->vs_events_missed = true;
+ return;
+ }
+
+ if ((vq->iov[out].iov_len != sizeof(struct virtio_scsi_event))) {
+ vq_err(vq, "Expecting virtio_scsi_event, got %zu bytes\n",
+ vq->iov[out].iov_len);
+ vs->vs_events_missed = true;
+ return;
+ }
+
+ if (vs->vs_events_missed) {
+ event->event |= VIRTIO_SCSI_T_EVENTS_MISSED;
+ vs->vs_events_missed = false;
+ }
+
+ eventp = vq->iov[out].iov_base;
+ ret = __copy_to_user(eventp, event, sizeof(*event));
+ if (!ret)
+ vhost_add_used_and_signal(&vs->dev, vq, head, 0);
+ else
+ vq_err(vq, "Faulted on tcm_vhost_send_event\n");
+}
+
+static void tcm_vhost_evt_work(struct vhost_work *work)
+{
+ struct vhost_scsi *vs = container_of(work, struct vhost_scsi,
+ vs_event_work);
+ struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
+ struct tcm_vhost_evt *evt;
+ struct llist_node *llnode;
+
+ mutex_lock(&vq->mutex);
+ llnode = llist_del_all(&vs->vs_event_list);
+ while (llnode) {
+ evt = llist_entry(llnode, struct tcm_vhost_evt, list);
+ llnode = llist_next(llnode);
+ tcm_vhost_do_evt_work(vs, evt);
+ tcm_vhost_free_evt(vs, evt);
+ }
+ mutex_unlock(&vq->mutex);
+}
+
/* Fill in status and signal that we are done processing this command
*
* This is scheduled in the vhost work queue so we are called with the owner
@@ -777,9 +885,49 @@ static void vhost_scsi_ctl_handle_kick(struct vhost_work *work)
pr_debug("%s: The handling func for control queue.\n", __func__);
}
+static void tcm_vhost_send_evt(struct vhost_scsi *vs, struct tcm_vhost_tpg *tpg,
+ struct se_lun *lun, u32 event, u32 reason)
+{
+ struct tcm_vhost_evt *evt;
+
+ evt = tcm_vhost_allocate_evt(vs, event, reason);
+ if (!evt)
+ return;
+
+ /* TODO: Can lun ever be NULL? */
+ if (lun) {
+ /* TODO: share lun setup code with virtio-scsi.ko */
+ /*
+ * Note: evt->event is zeroed when we allocate it and
+ * lun[4-7] need to be zero according to virtio-scsi spec.
+ */
+ evt->event.lun[0] = 0x01;
+ evt->event.lun[1] = tpg->tport_tpgt & 0xFF;
+ if (lun->unpacked_lun >= 256)
+ evt->event.lun[2] = lun->unpacked_lun >> 8 | 0x40 ;
+ evt->event.lun[3] = lun->unpacked_lun & 0xFF;
+ }
+
+ llist_add(&evt->list, &vs->vs_event_list);
+ vhost_work_queue(&vs->dev, &vs->vs_event_work);
+
+ return;
+}
+
static void vhost_scsi_evt_handle_kick(struct vhost_work *work)
{
- pr_debug("%s: The handling func for event queue.\n", __func__);
+ struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
+ poll.work);
+ struct vhost_scsi *vs = container_of(vq->dev, struct vhost_scsi, dev);
+
+ mutex_lock(&vq->mutex);
+ if (!vq->private_data)
+ goto out;
+
+ if (vs->vs_events_missed)
+ tcm_vhost_send_evt(vs, NULL, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
+out:
+ mutex_unlock(&vq->mutex);
}
static void vhost_scsi_handle_kick(struct vhost_work *work)
@@ -803,6 +951,7 @@ static void vhost_scsi_flush(struct vhost_scsi *vs)
for (i = 0; i < VHOST_SCSI_MAX_VQ; i++)
vhost_scsi_flush_vq(vs, i);
vhost_work_flush(&vs->dev, &vs->vs_completion_work);
+ vhost_work_flush(&vs->dev, &vs->vs_event_work);
}
/*
@@ -864,6 +1013,7 @@ static int vhost_scsi_set_endpoint(
goto out;
}
tv_tpg->tv_tpg_vhost_count++;
+ tv_tpg->vhost_scsi = vs;
vs_tpg[tv_tpg->tport_tpgt] = tv_tpg;
smp_mb__after_atomic_inc();
match = true;
@@ -949,6 +1099,7 @@ static int vhost_scsi_clear_endpoint(
goto err_tpg;
}
tv_tpg->tv_tpg_vhost_count--;
+ tv_tpg->vhost_scsi = NULL;
vs->vs_tpg[target] = NULL;
match = true;
mutex_unlock(&tv_tpg->tv_tpg_mutex);
@@ -969,6 +1120,7 @@ static int vhost_scsi_clear_endpoint(
vhost_scsi_flush(vs);
kfree(vs->vs_tpg);
vs->vs_tpg = NULL;
+ WARN_ON(vs->vs_events_nr);
mutex_unlock(&vs->dev.mutex);
mutex_unlock(&tcm_vhost_mutex);
return 0;
@@ -1009,6 +1161,10 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
return -ENOMEM;
vhost_work_init(&s->vs_completion_work, vhost_scsi_complete_cmd_work);
+ vhost_work_init(&s->vs_event_work, tcm_vhost_evt_work);
+
+ s->vs_events_nr = 0;
+ s->vs_events_missed = false;
s->vqs[VHOST_SCSI_VQ_CTL].handle_kick = vhost_scsi_ctl_handle_kick;
s->vqs[VHOST_SCSI_VQ_EVT].handle_kick = vhost_scsi_evt_handle_kick;
@@ -1139,28 +1295,80 @@ static char *tcm_vhost_dump_proto_id(struct tcm_vhost_tport *tport)
return "Unknown";
}
+static void tcm_vhost_do_plug(struct tcm_vhost_tpg *tpg,
+ struct se_lun *lun, bool plug)
+{
+
+ struct vhost_scsi *vs = tpg->vhost_scsi;
+ struct vhost_virtqueue *vq;
+ u32 reason;
+
+ if (!vs)
+ return;
+
+ mutex_lock(&vs->dev.mutex);
+ if (!vhost_has_feature(&vs->dev, VIRTIO_SCSI_F_HOTPLUG)) {
+ mutex_unlock(&vs->dev.mutex);
+ return;
+ }
+
+ if (plug)
+ reason = VIRTIO_SCSI_EVT_RESET_RESCAN;
+ else
+ reason = VIRTIO_SCSI_EVT_RESET_REMOVED;
+
+ vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
+ mutex_lock(&vq->mutex);
+ tcm_vhost_send_evt(vs, tpg, lun,
+ VIRTIO_SCSI_T_TRANSPORT_RESET, reason);
+ mutex_unlock(&vq->mutex);
+ mutex_unlock(&vs->dev.mutex);
+}
+
+static void tcm_vhost_hotplug(struct tcm_vhost_tpg *tpg, struct se_lun *lun)
+{
+ tcm_vhost_do_plug(tpg, lun, true);
+}
+
+static void tcm_vhost_hotunplug(struct tcm_vhost_tpg *tpg, struct se_lun *lun)
+{
+ tcm_vhost_do_plug(tpg, lun, false);
+}
+
static int tcm_vhost_port_link(struct se_portal_group *se_tpg,
struct se_lun *lun)
{
struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg,
struct tcm_vhost_tpg, se_tpg);
+ mutex_lock(&tcm_vhost_mutex);
+
mutex_lock(&tv_tpg->tv_tpg_mutex);
tv_tpg->tv_tpg_port_count++;
mutex_unlock(&tv_tpg->tv_tpg_mutex);
+ tcm_vhost_hotplug(tv_tpg, lun);
+
+ mutex_unlock(&tcm_vhost_mutex);
+
return 0;
}
static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg,
- struct se_lun *se_lun)
+ struct se_lun *lun)
{
struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg,
struct tcm_vhost_tpg, se_tpg);
+ mutex_lock(&tcm_vhost_mutex);
+
mutex_lock(&tv_tpg->tv_tpg_mutex);
tv_tpg->tv_tpg_port_count--;
mutex_unlock(&tv_tpg->tv_tpg_mutex);
+
+ tcm_vhost_hotunplug(tv_tpg, lun);
+
+ mutex_unlock(&tcm_vhost_mutex);
}
static struct se_node_acl *tcm_vhost_make_nodeacl(
diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h
index 1d2ae7a..a545a5b 100644
--- a/drivers/vhost/tcm_vhost.h
+++ b/drivers/vhost/tcm_vhost.h
@@ -53,6 +53,7 @@ struct tcm_vhost_nacl {
struct se_node_acl se_node_acl;
};
+struct vhost_scsi;
struct tcm_vhost_tpg {
/* Vhost port target portal group tag for TCM */
u16 tport_tpgt;
@@ -70,6 +71,8 @@ struct tcm_vhost_tpg {
struct tcm_vhost_tport *tport;
/* Returned by tcm_vhost_make_tpg() */
struct se_portal_group se_tpg;
+ /* Pointer back to vhost_scsi, protected by tv_tpg_mutex */
+ struct vhost_scsi *vhost_scsi;
};
struct tcm_vhost_tport {
@@ -83,6 +86,13 @@ struct tcm_vhost_tport {
struct se_wwn tport_wwn;
};
+struct tcm_vhost_evt {
+ /* event to be sent to guest */
+ struct virtio_scsi_event event;
+ /* event list, serviced from vhost worker thread */
+ struct llist_node list;
+};
+
/*
* As per request from MST, keep TCM_VHOST related ioctl defines out of
* linux/vhost.h (user-space) for now..
--
1.8.1.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v9 3/3] tcm_vhost: Add ioctl to get and set events missed flag
2013-04-25 3:10 [PATCH v9 0/3] tcm_vhost hotplug Asias He
2013-04-25 3:10 ` [PATCH v9 1/3] tcm_vhost: Refactor the lock nesting rule Asias He
2013-04-25 3:10 ` [PATCH v9 2/3] tcm_vhost: Add hotplug/hotunplug support Asias He
@ 2013-04-25 3:10 ` Asias He
2013-04-25 3:10 ` Asias He
2013-04-25 5:55 ` [PATCH v9 0/3] tcm_vhost hotplug Michael S. Tsirkin
4 siblings, 0 replies; 10+ messages in thread
From: Asias He @ 2013-04-25 3:10 UTC (permalink / raw)
To: Nicholas Bellinger
Cc: kvm, Michael S. Tsirkin, virtualization, target-devel,
Stefan Hajnoczi, Paolo Bonzini
Signed-off-by: Asias He <asias@redhat.com>
---
drivers/vhost/tcm_vhost.c | 17 +++++++++++++++++
drivers/vhost/tcm_vhost.h | 3 +++
2 files changed, 20 insertions(+)
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
index 137ae34..9c01d2a 100644
--- a/drivers/vhost/tcm_vhost.c
+++ b/drivers/vhost/tcm_vhost.c
@@ -1202,8 +1202,11 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
struct vhost_scsi_target backend;
void __user *argp = (void __user *)arg;
u64 __user *featurep = argp;
+ u32 __user *eventsp = argp;
+ u32 events_missed;
u64 features;
int r, abi_version = VHOST_SCSI_ABI_VERSION;
+ struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
switch (ioctl) {
case VHOST_SCSI_SET_ENDPOINT:
@@ -1224,6 +1227,20 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
if (copy_to_user(argp, &abi_version, sizeof abi_version))
return -EFAULT;
return 0;
+ case VHOST_SCSI_SET_EVENTS_MISSED:
+ if (get_user(events_missed, eventsp))
+ return -EFAULT;
+ mutex_lock(&vq->mutex);
+ vs->vs_events_missed = events_missed;
+ mutex_unlock(&vq->mutex);
+ return 0;
+ case VHOST_SCSI_GET_EVENTS_MISSED:
+ mutex_lock(&vq->mutex);
+ events_missed = vs->vs_events_missed;
+ mutex_unlock(&vq->mutex);
+ if (put_user(events_missed, eventsp))
+ return -EFAULT;
+ return 0;
case VHOST_GET_FEATURES:
features = VHOST_SCSI_FEATURES;
if (copy_to_user(featurep, &features, sizeof features))
diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h
index a545a5b..514b9fd 100644
--- a/drivers/vhost/tcm_vhost.h
+++ b/drivers/vhost/tcm_vhost.h
@@ -123,3 +123,6 @@ struct vhost_scsi_target {
#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
/* Changing this breaks userspace. */
#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
+/* Set and get the events missed flag */
+#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
+#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v9 3/3] tcm_vhost: Add ioctl to get and set events missed flag
2013-04-25 3:10 [PATCH v9 0/3] tcm_vhost hotplug Asias He
` (2 preceding siblings ...)
2013-04-25 3:10 ` [PATCH v9 3/3] tcm_vhost: Add ioctl to get and set events missed flag Asias He
@ 2013-04-25 3:10 ` Asias He
2013-04-25 5:54 ` Michael S. Tsirkin
2013-04-25 5:55 ` Michael S. Tsirkin
2013-04-25 5:55 ` [PATCH v9 0/3] tcm_vhost hotplug Michael S. Tsirkin
4 siblings, 2 replies; 10+ messages in thread
From: Asias He @ 2013-04-25 3:10 UTC (permalink / raw)
To: Nicholas Bellinger
Cc: Paolo Bonzini, Stefan Hajnoczi, Michael S. Tsirkin, Rusty Russell,
kvm, virtualization, target-devel, Asias He
Signed-off-by: Asias He <asias@redhat.com>
---
drivers/vhost/tcm_vhost.c | 17 +++++++++++++++++
drivers/vhost/tcm_vhost.h | 3 +++
2 files changed, 20 insertions(+)
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
index 137ae34..9c01d2a 100644
--- a/drivers/vhost/tcm_vhost.c
+++ b/drivers/vhost/tcm_vhost.c
@@ -1202,8 +1202,11 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
struct vhost_scsi_target backend;
void __user *argp = (void __user *)arg;
u64 __user *featurep = argp;
+ u32 __user *eventsp = argp;
+ u32 events_missed;
u64 features;
int r, abi_version = VHOST_SCSI_ABI_VERSION;
+ struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
switch (ioctl) {
case VHOST_SCSI_SET_ENDPOINT:
@@ -1224,6 +1227,20 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
if (copy_to_user(argp, &abi_version, sizeof abi_version))
return -EFAULT;
return 0;
+ case VHOST_SCSI_SET_EVENTS_MISSED:
+ if (get_user(events_missed, eventsp))
+ return -EFAULT;
+ mutex_lock(&vq->mutex);
+ vs->vs_events_missed = events_missed;
+ mutex_unlock(&vq->mutex);
+ return 0;
+ case VHOST_SCSI_GET_EVENTS_MISSED:
+ mutex_lock(&vq->mutex);
+ events_missed = vs->vs_events_missed;
+ mutex_unlock(&vq->mutex);
+ if (put_user(events_missed, eventsp))
+ return -EFAULT;
+ return 0;
case VHOST_GET_FEATURES:
features = VHOST_SCSI_FEATURES;
if (copy_to_user(featurep, &features, sizeof features))
diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h
index a545a5b..514b9fd 100644
--- a/drivers/vhost/tcm_vhost.h
+++ b/drivers/vhost/tcm_vhost.h
@@ -123,3 +123,6 @@ struct vhost_scsi_target {
#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
/* Changing this breaks userspace. */
#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
+/* Set and get the events missed flag */
+#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
+#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v9 1/3] tcm_vhost: Refactor the lock nesting rule
2013-04-25 3:10 ` [PATCH v9 1/3] tcm_vhost: Refactor the lock nesting rule Asias He
@ 2013-04-25 5:44 ` Michael S. Tsirkin
0 siblings, 0 replies; 10+ messages in thread
From: Michael S. Tsirkin @ 2013-04-25 5:44 UTC (permalink / raw)
To: Asias He
Cc: kvm, virtualization, target-devel, Stefan Hajnoczi, Paolo Bonzini
On Thu, Apr 25, 2013 at 11:10:04AM +0800, Asias He wrote:
> We want to use tcm_vhost_mutex to make sure hotplug/hotunplug will not
> happen when set_endpoint/clear_endpoint is in process.
>
> Signed-off-by: Asias He <asias@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
> ---
> drivers/vhost/tcm_vhost.c | 32 +++++++++++++++++++-------------
> 1 file changed, 19 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
> index 957a0b9..822cd1f 100644
> --- a/drivers/vhost/tcm_vhost.c
> +++ b/drivers/vhost/tcm_vhost.c
> @@ -808,6 +808,9 @@ static void vhost_scsi_flush(struct vhost_scsi *vs)
> /*
> * Called from vhost_scsi_ioctl() context to walk the list of available
> * tcm_vhost_tpg with an active struct tcm_vhost_nexus
> + *
> + * The lock nesting rule is:
> + * tcm_vhost_mutex -> vs->dev.mutex -> tpg->tv_tpg_mutex -> vq->mutex
> */
> static int vhost_scsi_set_endpoint(
> struct vhost_scsi *vs,
> @@ -820,26 +823,27 @@ static int vhost_scsi_set_endpoint(
> int index, ret, i, len;
> bool match = false;
>
> + mutex_lock(&tcm_vhost_mutex);
> mutex_lock(&vs->dev.mutex);
> +
> /* Verify that ring has been setup correctly. */
> for (index = 0; index < vs->dev.nvqs; ++index) {
> /* Verify that ring has been setup correctly. */
> if (!vhost_vq_access_ok(&vs->vqs[index])) {
> - mutex_unlock(&vs->dev.mutex);
> - return -EFAULT;
> + ret = -EFAULT;
> + goto out;
> }
> }
>
> len = sizeof(vs_tpg[0]) * VHOST_SCSI_MAX_TARGET;
> vs_tpg = kzalloc(len, GFP_KERNEL);
> if (!vs_tpg) {
> - mutex_unlock(&vs->dev.mutex);
> - return -ENOMEM;
> + ret = -ENOMEM;
> + goto out;
> }
> if (vs->vs_tpg)
> memcpy(vs_tpg, vs->vs_tpg, len);
>
> - mutex_lock(&tcm_vhost_mutex);
> list_for_each_entry(tv_tpg, &tcm_vhost_list, tv_tpg_list) {
> mutex_lock(&tv_tpg->tv_tpg_mutex);
> if (!tv_tpg->tpg_nexus) {
> @@ -854,11 +858,10 @@ static int vhost_scsi_set_endpoint(
>
> if (!strcmp(tv_tport->tport_name, t->vhost_wwpn)) {
> if (vs->vs_tpg && vs->vs_tpg[tv_tpg->tport_tpgt]) {
> - mutex_unlock(&tv_tpg->tv_tpg_mutex);
> - mutex_unlock(&tcm_vhost_mutex);
> - mutex_unlock(&vs->dev.mutex);
> kfree(vs_tpg);
> - return -EEXIST;
> + mutex_unlock(&tv_tpg->tv_tpg_mutex);
> + ret = -EEXIST;
> + goto out;
> }
> tv_tpg->tv_tpg_vhost_count++;
> vs_tpg[tv_tpg->tport_tpgt] = tv_tpg;
> @@ -867,7 +870,6 @@ static int vhost_scsi_set_endpoint(
> }
> mutex_unlock(&tv_tpg->tv_tpg_mutex);
> }
> - mutex_unlock(&tcm_vhost_mutex);
>
> if (match) {
> memcpy(vs->vs_vhost_wwpn, t->vhost_wwpn,
> @@ -893,7 +895,9 @@ static int vhost_scsi_set_endpoint(
> kfree(vs->vs_tpg);
> vs->vs_tpg = vs_tpg;
>
> +out:
> mutex_unlock(&vs->dev.mutex);
> + mutex_unlock(&tcm_vhost_mutex);
> return ret;
> }
>
> @@ -908,6 +912,7 @@ static int vhost_scsi_clear_endpoint(
> int index, ret, i;
> u8 target;
>
> + mutex_lock(&tcm_vhost_mutex);
> mutex_lock(&vs->dev.mutex);
> /* Verify that ring has been setup correctly. */
> for (index = 0; index < vs->dev.nvqs; ++index) {
> @@ -918,8 +923,8 @@ static int vhost_scsi_clear_endpoint(
> }
>
> if (!vs->vs_tpg) {
> - mutex_unlock(&vs->dev.mutex);
> - return 0;
> + ret = 0;
> + goto err_dev;
> }
>
> for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) {
> @@ -965,13 +970,14 @@ static int vhost_scsi_clear_endpoint(
> kfree(vs->vs_tpg);
> vs->vs_tpg = NULL;
> mutex_unlock(&vs->dev.mutex);
> -
> + mutex_unlock(&tcm_vhost_mutex);
> return 0;
>
> err_tpg:
> mutex_unlock(&tv_tpg->tv_tpg_mutex);
> err_dev:
> mutex_unlock(&vs->dev.mutex);
> + mutex_unlock(&tcm_vhost_mutex);
> return ret;
> }
>
> --
> 1.8.1.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v9 2/3] tcm_vhost: Add hotplug/hotunplug support
2013-04-25 3:10 ` [PATCH v9 2/3] tcm_vhost: Add hotplug/hotunplug support Asias He
@ 2013-04-25 5:52 ` Michael S. Tsirkin
0 siblings, 0 replies; 10+ messages in thread
From: Michael S. Tsirkin @ 2013-04-25 5:52 UTC (permalink / raw)
To: Asias He
Cc: kvm, virtualization, target-devel, Stefan Hajnoczi, Paolo Bonzini
On Thu, Apr 25, 2013 at 11:10:05AM +0800, Asias He wrote:
> In commit 365a7150094 ([SCSI] virtio-scsi: hotplug support for
> virtio-scsi), hotplug support is added to virtio-scsi.
>
> This patch adds hotplug and hotunplug support to tcm_vhost.
>
> You can create or delete a LUN in targetcli to hotplug or hotunplug a
> LUN in guest.
Patch looks correct, so
Acked-by: Michael S. Tsirkin <mst@redhat.com>
A couple of trivial formatting comments.
It's up to you whether to address them.
> Changes in v8:
> - Use vq->mutex for event
> - Drop tcm_vhost: Add helper to check if endpoint is setup
> - Rename vs_events_dropped to vs_events_missed
> - Init lun[] explicitly
>
> Changes in v7:
> - Add vhost_work_flush for vs->vs_event_work to this series
>
> Changes in v6:
> - Pass tcm_vhost_evt to tcm_vhost_do_evt_work
>
> Changes in v5:
> - Switch to int from u64 to vs_events_nr
> - Set s->vs_events_dropped flag in tcm_vhost_allocate_evt
> - Do not nest dev mutex within vq mutex
> - Use vs_events_lock to protect vs_events_dropped and vs_events_nr
> - Rebase to target/master
>
> Changes in v4:
> - Drop tcm_vhost_check_endpoint in tcm_vhost_send_evt
> - Add tcm_vhost_check_endpoint in vhost_scsi_evt_handle_kick
>
> Changes in v3:
> - Separate the bug fix to another thread
>
> Changes in v2:
> - Remove code duplication in tcm_vhost_{hotplug,hotunplug}
> - Fix racing of vs_events_nr
> - Add flush fix patch to this series
>
> Signed-off-by: Asias He <asias@redhat.com>
> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
> drivers/vhost/tcm_vhost.c | 214 +++++++++++++++++++++++++++++++++++++++++++++-
> drivers/vhost/tcm_vhost.h | 10 +++
> 2 files changed, 221 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
> index 822cd1f..137ae34 100644
> --- a/drivers/vhost/tcm_vhost.c
> +++ b/drivers/vhost/tcm_vhost.c
> @@ -66,11 +66,13 @@ enum {
> * TODO: debug and remove the workaround.
> */
> enum {
> - VHOST_SCSI_FEATURES = VHOST_FEATURES & (~VIRTIO_RING_F_EVENT_IDX)
> + VHOST_SCSI_FEATURES = (VHOST_FEATURES & (~VIRTIO_RING_F_EVENT_IDX)) |
> + (1ULL << VIRTIO_SCSI_F_HOTPLUG)
> };
>
> #define VHOST_SCSI_MAX_TARGET 256
> #define VHOST_SCSI_MAX_VQ 128
> +#define VHOST_SCSI_MAX_EVENT 128
>
> struct vhost_scsi {
> /* Protected by vhost_scsi->dev.mutex */
> @@ -82,6 +84,12 @@ struct vhost_scsi {
>
> struct vhost_work vs_completion_work; /* cmd completion work item */
> struct llist_head vs_completion_list; /* cmd completion queue */
> +
> + struct vhost_work vs_event_work; /* evt injection work item */
> + struct llist_head vs_event_list; /* evt injection queue */
> +
> + bool vs_events_missed; /* any missed events, protected by vq->mutex */
> + int vs_events_nr; /* num of pending events, protected by vq->mutex */
> };
>
> /* Local pointer to allocated TCM configfs fabric module */
> @@ -349,6 +357,37 @@ static int tcm_vhost_queue_tm_rsp(struct se_cmd *se_cmd)
> return 0;
> }
>
> +static void tcm_vhost_free_evt(struct vhost_scsi *vs, struct tcm_vhost_evt *evt)
> +{
> + vs->vs_events_nr--;
> + kfree(evt);
> +}
> +
> +static struct tcm_vhost_evt *tcm_vhost_allocate_evt(struct vhost_scsi *vs,
> + u32 event, u32 reason)
> +{
> + struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
> + struct tcm_vhost_evt *evt;
> +
> + if (vs->vs_events_nr > VHOST_SCSI_MAX_EVENT) {
> + vs->vs_events_missed = true;
> + return NULL;
> + }
> +
> + evt = kzalloc(sizeof(*evt), GFP_KERNEL);
> + if (!evt) {
> + vq_err(vq, "Failed to allocate tcm_vhost_evt\n");
> + vs->vs_events_missed = true;
> + return NULL;
> + }
> +
> + evt->event.event = event;
> + evt->event.reason = reason;
> + vs->vs_events_nr++;
> +
> + return evt;
> +}
> +
> static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd)
> {
> struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd;
> @@ -367,6 +406,75 @@ static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd)
> kfree(tv_cmd);
> }
>
> +static void tcm_vhost_do_evt_work(struct vhost_scsi *vs,
> + struct tcm_vhost_evt *evt)
> +{
> + struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
> + struct virtio_scsi_event *event = &evt->event;
> + struct virtio_scsi_event __user *eventp;
> + unsigned out, in;
> + int head, ret;
> +
> + if (!vq->private_data) {
> + vs->vs_events_missed = true;
> + return;
> + }
> +
> +again:
> + vhost_disable_notify(&vs->dev, vq);
> + head = vhost_get_vq_desc(&vs->dev, vq, vq->iov,
> + ARRAY_SIZE(vq->iov), &out, &in,
> + NULL, NULL);
> + if (head < 0) {
> + vs->vs_events_missed = true;
> + return;
> + }
> + if (head == vq->num) {
> + if (vhost_enable_notify(&vs->dev, vq))
> + goto again;
> + vs->vs_events_missed = true;
> + return;
> + }
> +
> + if ((vq->iov[out].iov_len != sizeof(struct virtio_scsi_event))) {
> + vq_err(vq, "Expecting virtio_scsi_event, got %zu bytes\n",
> + vq->iov[out].iov_len);
> + vs->vs_events_missed = true;
> + return;
> + }
> +
> + if (vs->vs_events_missed) {
> + event->event |= VIRTIO_SCSI_T_EVENTS_MISSED;
> + vs->vs_events_missed = false;
> + }
> +
> + eventp = vq->iov[out].iov_base;
> + ret = __copy_to_user(eventp, event, sizeof(*event));
> + if (!ret)
> + vhost_add_used_and_signal(&vs->dev, vq, head, 0);
> + else
> + vq_err(vq, "Faulted on tcm_vhost_send_event\n");
> +}
> +
> +static void tcm_vhost_evt_work(struct vhost_work *work)
> +{
> + struct vhost_scsi *vs = container_of(work, struct vhost_scsi,
> + vs_event_work);
> + struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
> + struct tcm_vhost_evt *evt;
> + struct llist_node *llnode;
> +
> + mutex_lock(&vq->mutex);
> + llnode = llist_del_all(&vs->vs_event_list);
> + while (llnode) {
> + evt = llist_entry(llnode, struct tcm_vhost_evt, list);
> + llnode = llist_next(llnode);
> + tcm_vhost_do_evt_work(vs, evt);
> + tcm_vhost_free_evt(vs, evt);
> + }
> + mutex_unlock(&vq->mutex);
> +}
> +
> /* Fill in status and signal that we are done processing this command
> *
> * This is scheduled in the vhost work queue so we are called with the owner
> @@ -777,9 +885,49 @@ static void vhost_scsi_ctl_handle_kick(struct vhost_work *work)
> pr_debug("%s: The handling func for control queue.\n", __func__);
> }
>
> +static void tcm_vhost_send_evt(struct vhost_scsi *vs, struct tcm_vhost_tpg *tpg,
> + struct se_lun *lun, u32 event, u32 reason)
Please shift second line:
static void tcm_vhost_send_evt(struct vhost_scsi *vs, struct tcm_vhost_tpg *tpg,
struct se_lun *lun, u32 event, u32 reason)
CodingStyle says:
Descendants are always substantially shorter than the parent and
are placed substantially to the right.
and here it's actually to the left if the parent (.
> +{
> + struct tcm_vhost_evt *evt;
> +
> + evt = tcm_vhost_allocate_evt(vs, event, reason);
> + if (!evt)
> + return;
> +
> + /* TODO: Can lun ever be NULL? */
Well, can it? You pass in NULL just below. So drop this comment
then?
> + if (lun) {
> + /* TODO: share lun setup code with virtio-scsi.ko */
> + /*
> + * Note: evt->event is zeroed when we allocate it and
> + * lun[4-7] need to be zero according to virtio-scsi spec.
> + */
> + evt->event.lun[0] = 0x01;
> + evt->event.lun[1] = tpg->tport_tpgt & 0xFF;
> + if (lun->unpacked_lun >= 256)
> + evt->event.lun[2] = lun->unpacked_lun >> 8 | 0x40 ;
> + evt->event.lun[3] = lun->unpacked_lun & 0xFF;
> + }
> +
> + llist_add(&evt->list, &vs->vs_event_list);
> + vhost_work_queue(&vs->dev, &vs->vs_event_work);
> +
> + return;
> +}
> +
> static void vhost_scsi_evt_handle_kick(struct vhost_work *work)
> {
> - pr_debug("%s: The handling func for event queue.\n", __func__);
> + struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
> + poll.work);
> + struct vhost_scsi *vs = container_of(vq->dev, struct vhost_scsi, dev);
> +
> + mutex_lock(&vq->mutex);
> + if (!vq->private_data)
> + goto out;
> +
> + if (vs->vs_events_missed)
> + tcm_vhost_send_evt(vs, NULL, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
> +out:
> + mutex_unlock(&vq->mutex);
> }
>
> static void vhost_scsi_handle_kick(struct vhost_work *work)
> @@ -803,6 +951,7 @@ static void vhost_scsi_flush(struct vhost_scsi *vs)
> for (i = 0; i < VHOST_SCSI_MAX_VQ; i++)
> vhost_scsi_flush_vq(vs, i);
> vhost_work_flush(&vs->dev, &vs->vs_completion_work);
> + vhost_work_flush(&vs->dev, &vs->vs_event_work);
> }
>
> /*
> @@ -864,6 +1013,7 @@ static int vhost_scsi_set_endpoint(
> goto out;
> }
> tv_tpg->tv_tpg_vhost_count++;
> + tv_tpg->vhost_scsi = vs;
> vs_tpg[tv_tpg->tport_tpgt] = tv_tpg;
> smp_mb__after_atomic_inc();
> match = true;
> @@ -949,6 +1099,7 @@ static int vhost_scsi_clear_endpoint(
> goto err_tpg;
> }
> tv_tpg->tv_tpg_vhost_count--;
> + tv_tpg->vhost_scsi = NULL;
> vs->vs_tpg[target] = NULL;
> match = true;
> mutex_unlock(&tv_tpg->tv_tpg_mutex);
> @@ -969,6 +1120,7 @@ static int vhost_scsi_clear_endpoint(
> vhost_scsi_flush(vs);
> kfree(vs->vs_tpg);
> vs->vs_tpg = NULL;
> + WARN_ON(vs->vs_events_nr);
> mutex_unlock(&vs->dev.mutex);
> mutex_unlock(&tcm_vhost_mutex);
> return 0;
> @@ -1009,6 +1161,10 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
> return -ENOMEM;
>
> vhost_work_init(&s->vs_completion_work, vhost_scsi_complete_cmd_work);
> + vhost_work_init(&s->vs_event_work, tcm_vhost_evt_work);
> +
> + s->vs_events_nr = 0;
> + s->vs_events_missed = false;
>
> s->vqs[VHOST_SCSI_VQ_CTL].handle_kick = vhost_scsi_ctl_handle_kick;
> s->vqs[VHOST_SCSI_VQ_EVT].handle_kick = vhost_scsi_evt_handle_kick;
> @@ -1139,28 +1295,80 @@ static char *tcm_vhost_dump_proto_id(struct tcm_vhost_tport *tport)
> return "Unknown";
> }
>
> +static void tcm_vhost_do_plug(struct tcm_vhost_tpg *tpg,
> + struct se_lun *lun, bool plug)
> +{
> +
> + struct vhost_scsi *vs = tpg->vhost_scsi;
> + struct vhost_virtqueue *vq;
> + u32 reason;
> +
> + if (!vs)
> + return;
> +
> + mutex_lock(&vs->dev.mutex);
> + if (!vhost_has_feature(&vs->dev, VIRTIO_SCSI_F_HOTPLUG)) {
> + mutex_unlock(&vs->dev.mutex);
> + return;
> + }
> +
> + if (plug)
> + reason = VIRTIO_SCSI_EVT_RESET_RESCAN;
> + else
> + reason = VIRTIO_SCSI_EVT_RESET_REMOVED;
> +
> + vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
> + mutex_lock(&vq->mutex);
> + tcm_vhost_send_evt(vs, tpg, lun,
> + VIRTIO_SCSI_T_TRANSPORT_RESET, reason);
> + mutex_unlock(&vq->mutex);
> + mutex_unlock(&vs->dev.mutex);
> +}
> +
> +static void tcm_vhost_hotplug(struct tcm_vhost_tpg *tpg, struct se_lun *lun)
> +{
> + tcm_vhost_do_plug(tpg, lun, true);
> +}
> +
> +static void tcm_vhost_hotunplug(struct tcm_vhost_tpg *tpg, struct se_lun *lun)
> +{
> + tcm_vhost_do_plug(tpg, lun, false);
> +}
> +
> static int tcm_vhost_port_link(struct se_portal_group *se_tpg,
> struct se_lun *lun)
> {
> struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg,
> struct tcm_vhost_tpg, se_tpg);
>
> + mutex_lock(&tcm_vhost_mutex);
> +
> mutex_lock(&tv_tpg->tv_tpg_mutex);
> tv_tpg->tv_tpg_port_count++;
> mutex_unlock(&tv_tpg->tv_tpg_mutex);
>
> + tcm_vhost_hotplug(tv_tpg, lun);
> +
> + mutex_unlock(&tcm_vhost_mutex);
> +
> return 0;
> }
>
> static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg,
> - struct se_lun *se_lun)
> + struct se_lun *lun)
> {
> struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg,
> struct tcm_vhost_tpg, se_tpg);
>
> + mutex_lock(&tcm_vhost_mutex);
> +
> mutex_lock(&tv_tpg->tv_tpg_mutex);
> tv_tpg->tv_tpg_port_count--;
> mutex_unlock(&tv_tpg->tv_tpg_mutex);
> +
> + tcm_vhost_hotunplug(tv_tpg, lun);
> +
> + mutex_unlock(&tcm_vhost_mutex);
> }
>
> static struct se_node_acl *tcm_vhost_make_nodeacl(
> diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h
> index 1d2ae7a..a545a5b 100644
> --- a/drivers/vhost/tcm_vhost.h
> +++ b/drivers/vhost/tcm_vhost.h
> @@ -53,6 +53,7 @@ struct tcm_vhost_nacl {
> struct se_node_acl se_node_acl;
> };
>
> +struct vhost_scsi;
> struct tcm_vhost_tpg {
> /* Vhost port target portal group tag for TCM */
> u16 tport_tpgt;
> @@ -70,6 +71,8 @@ struct tcm_vhost_tpg {
> struct tcm_vhost_tport *tport;
> /* Returned by tcm_vhost_make_tpg() */
> struct se_portal_group se_tpg;
> + /* Pointer back to vhost_scsi, protected by tv_tpg_mutex */
> + struct vhost_scsi *vhost_scsi;
> };
>
> struct tcm_vhost_tport {
> @@ -83,6 +86,13 @@ struct tcm_vhost_tport {
> struct se_wwn tport_wwn;
> };
>
> +struct tcm_vhost_evt {
> + /* event to be sent to guest */
> + struct virtio_scsi_event event;
> + /* event list, serviced from vhost worker thread */
> + struct llist_node list;
> +};
> +
> /*
> * As per request from MST, keep TCM_VHOST related ioctl defines out of
> * linux/vhost.h (user-space) for now..
> --
> 1.8.1.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v9 3/3] tcm_vhost: Add ioctl to get and set events missed flag
2013-04-25 3:10 ` Asias He
@ 2013-04-25 5:54 ` Michael S. Tsirkin
2013-04-25 5:55 ` Michael S. Tsirkin
1 sibling, 0 replies; 10+ messages in thread
From: Michael S. Tsirkin @ 2013-04-25 5:54 UTC (permalink / raw)
To: Asias He
Cc: kvm, virtualization, target-devel, Stefan Hajnoczi, Paolo Bonzini
On Thu, Apr 25, 2013 at 11:10:06AM +0800, Asias He wrote:
> Signed-off-by: Asias He <asias@redhat.com>
Please merge with patch 2 so we can use feature flag to
know whether ioctl is supported.
> ---
> drivers/vhost/tcm_vhost.c | 17 +++++++++++++++++
> drivers/vhost/tcm_vhost.h | 3 +++
> 2 files changed, 20 insertions(+)
>
> diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
> index 137ae34..9c01d2a 100644
> --- a/drivers/vhost/tcm_vhost.c
> +++ b/drivers/vhost/tcm_vhost.c
> @@ -1202,8 +1202,11 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
> struct vhost_scsi_target backend;
> void __user *argp = (void __user *)arg;
> u64 __user *featurep = argp;
> + u32 __user *eventsp = argp;
> + u32 events_missed;
> u64 features;
> int r, abi_version = VHOST_SCSI_ABI_VERSION;
> + struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
>
> switch (ioctl) {
> case VHOST_SCSI_SET_ENDPOINT:
> @@ -1224,6 +1227,20 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
> if (copy_to_user(argp, &abi_version, sizeof abi_version))
> return -EFAULT;
> return 0;
> + case VHOST_SCSI_SET_EVENTS_MISSED:
> + if (get_user(events_missed, eventsp))
> + return -EFAULT;
> + mutex_lock(&vq->mutex);
> + vs->vs_events_missed = events_missed;
> + mutex_unlock(&vq->mutex);
> + return 0;
> + case VHOST_SCSI_GET_EVENTS_MISSED:
> + mutex_lock(&vq->mutex);
> + events_missed = vs->vs_events_missed;
> + mutex_unlock(&vq->mutex);
> + if (put_user(events_missed, eventsp))
> + return -EFAULT;
> + return 0;
> case VHOST_GET_FEATURES:
> features = VHOST_SCSI_FEATURES;
> if (copy_to_user(featurep, &features, sizeof features))
> diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h
> index a545a5b..514b9fd 100644
> --- a/drivers/vhost/tcm_vhost.h
> +++ b/drivers/vhost/tcm_vhost.h
> @@ -123,3 +123,6 @@ struct vhost_scsi_target {
> #define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
> /* Changing this breaks userspace. */
> #define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
> +/* Set and get the events missed flag */
> +#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
> +#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
> --
> 1.8.1.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v9 0/3] tcm_vhost hotplug
2013-04-25 3:10 [PATCH v9 0/3] tcm_vhost hotplug Asias He
` (3 preceding siblings ...)
2013-04-25 3:10 ` Asias He
@ 2013-04-25 5:55 ` Michael S. Tsirkin
4 siblings, 0 replies; 10+ messages in thread
From: Michael S. Tsirkin @ 2013-04-25 5:55 UTC (permalink / raw)
To: Asias He
Cc: kvm, virtualization, target-devel, Stefan Hajnoczi, Paolo Bonzini
On Thu, Apr 25, 2013 at 11:10:03AM +0800, Asias He wrote:
> Asias He (3):
> tcm_vhost: Refactor the lock nesting rule
> tcm_vhost: Add hotplug/hotunplug support
> tcm_vhost: Add ioctl to get and set events missed flag
For the series:
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reported a minor formatting nit, we can
address these in tree as well.
> drivers/vhost/tcm_vhost.c | 263 +++++++++++++++++++++++++++++++++++++++++++---
> drivers/vhost/tcm_vhost.h | 13 +++
> 2 files changed, 260 insertions(+), 16 deletions(-)
>
> --
> 1.8.1.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v9 3/3] tcm_vhost: Add ioctl to get and set events missed flag
2013-04-25 3:10 ` Asias He
2013-04-25 5:54 ` Michael S. Tsirkin
@ 2013-04-25 5:55 ` Michael S. Tsirkin
1 sibling, 0 replies; 10+ messages in thread
From: Michael S. Tsirkin @ 2013-04-25 5:55 UTC (permalink / raw)
To: Asias He
Cc: kvm, virtualization, target-devel, Stefan Hajnoczi, Paolo Bonzini
On Thu, Apr 25, 2013 at 11:10:06AM +0800, Asias He wrote:
> Signed-off-by: Asias He <asias@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
> ---
> drivers/vhost/tcm_vhost.c | 17 +++++++++++++++++
> drivers/vhost/tcm_vhost.h | 3 +++
> 2 files changed, 20 insertions(+)
>
> diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
> index 137ae34..9c01d2a 100644
> --- a/drivers/vhost/tcm_vhost.c
> +++ b/drivers/vhost/tcm_vhost.c
> @@ -1202,8 +1202,11 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
> struct vhost_scsi_target backend;
> void __user *argp = (void __user *)arg;
> u64 __user *featurep = argp;
> + u32 __user *eventsp = argp;
> + u32 events_missed;
> u64 features;
> int r, abi_version = VHOST_SCSI_ABI_VERSION;
> + struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT];
>
> switch (ioctl) {
> case VHOST_SCSI_SET_ENDPOINT:
> @@ -1224,6 +1227,20 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
> if (copy_to_user(argp, &abi_version, sizeof abi_version))
> return -EFAULT;
> return 0;
> + case VHOST_SCSI_SET_EVENTS_MISSED:
> + if (get_user(events_missed, eventsp))
> + return -EFAULT;
> + mutex_lock(&vq->mutex);
> + vs->vs_events_missed = events_missed;
> + mutex_unlock(&vq->mutex);
> + return 0;
> + case VHOST_SCSI_GET_EVENTS_MISSED:
> + mutex_lock(&vq->mutex);
> + events_missed = vs->vs_events_missed;
> + mutex_unlock(&vq->mutex);
> + if (put_user(events_missed, eventsp))
> + return -EFAULT;
> + return 0;
> case VHOST_GET_FEATURES:
> features = VHOST_SCSI_FEATURES;
> if (copy_to_user(featurep, &features, sizeof features))
> diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h
> index a545a5b..514b9fd 100644
> --- a/drivers/vhost/tcm_vhost.h
> +++ b/drivers/vhost/tcm_vhost.h
> @@ -123,3 +123,6 @@ struct vhost_scsi_target {
> #define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
> /* Changing this breaks userspace. */
> #define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
> +/* Set and get the events missed flag */
> +#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
> +#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
> --
> 1.8.1.4
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-04-25 5:55 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-25 3:10 [PATCH v9 0/3] tcm_vhost hotplug Asias He
2013-04-25 3:10 ` [PATCH v9 1/3] tcm_vhost: Refactor the lock nesting rule Asias He
2013-04-25 5:44 ` Michael S. Tsirkin
2013-04-25 3:10 ` [PATCH v9 2/3] tcm_vhost: Add hotplug/hotunplug support Asias He
2013-04-25 5:52 ` Michael S. Tsirkin
2013-04-25 3:10 ` [PATCH v9 3/3] tcm_vhost: Add ioctl to get and set events missed flag Asias He
2013-04-25 3:10 ` Asias He
2013-04-25 5:54 ` Michael S. Tsirkin
2013-04-25 5:55 ` Michael S. Tsirkin
2013-04-25 5:55 ` [PATCH v9 0/3] tcm_vhost hotplug Michael S. Tsirkin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.