Re: [PATCH v2] virtio-scsi: hotplug support for virtio-scsi
On Tue, Jul 3, 2012 at 1:41 PM, Cong Meng m...@linux.vnet.ibm.com wrote: This patch implements the hotplug support for virtio-scsi. When there is a device attached/detached, the virtio-scsi driver will be signaled via event virtual queue and it will add/remove the scsi device in question automatically. v2: handle no_event event Signed-off-by: Cong Meng m...@linux.vnet.ibm.com Signed-off-by: Sen Wang senw...@linux.vnet.ibm.com --- drivers/scsi/virtio_scsi.c | 113 ++- include/linux/virtio_scsi.h |9 2 files changed, 121 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 9fc5e67..e44b2d6 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -25,6 +25,7 @@ #include scsi/scsi_cmnd.h #define VIRTIO_SCSI_MEMPOOL_SZ 64 +#define VIRTIO_SCSI_EVENT_LEN 8 /* Command queue element */ struct virtio_scsi_cmd { @@ -43,6 +44,12 @@ struct virtio_scsi_cmd { } resp; } cacheline_aligned_in_smp; +struct virtio_scsi_event_node { + struct virtio_scsi *vscsi; + struct virtio_scsi_event event; + struct work_struct work; +}; + struct virtio_scsi_vq { /* Protects vq */ spinlock_t vq_lock; @@ -67,6 +74,9 @@ struct virtio_scsi { struct virtio_scsi_vq event_vq; struct virtio_scsi_vq req_vq; + /* Get some buffers reday for event vq */ s/reday/ready/ + struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN]; + struct virtio_scsi_target_state *tgt[]; }; @@ -202,6 +212,97 @@ static void virtscsi_ctrl_done(struct virtqueue *vq) spin_unlock_irqrestore(vscsi-ctrl_vq.vq_lock, flags); }; +static int virtscsi_kick_event(struct virtio_scsi *vscsi, + struct virtio_scsi_event_node *event_node) +{ + int ret; + struct scatterlist sg; + unsigned long flags; + + sg_set_buf(sg, event_node-event, sizeof(struct virtio_scsi_event)); + + spin_lock_irqsave(vscsi-event_vq.vq_lock, flags); + + ret = virtqueue_add_buf(vscsi-event_vq.vq, sg, 0, 1, event_node, GFP_ATOMIC); + if (ret = 0) + virtqueue_kick(vscsi-event_vq.vq); + + spin_unlock_irqrestore(vscsi-event_vq.vq_lock, flags); + + return ret; +} + +static int virtscsi_kick_event_all(struct virtio_scsi *vscsi) +{ + int i; + + for (i = 0; i VIRTIO_SCSI_EVENT_LEN; i++) { + vscsi-event_list[i].vscsi = vscsi; + virtscsi_kick_event(vscsi, vscsi-event_list[i]); + } + + return 0; +} + +static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi, +struct virtio_scsi_event *event) +{ + struct scsi_device *sdev; + struct Scsi_Host *shost = virtio_scsi_host(vscsi-vdev); + unsigned int target = event-lun[1]; + unsigned int lun = (event-lun[2] 8) | event-lun[3]; + + switch (event-reason) { + case VIRTIO_SCSI_EVT_RESET_RESCAN: + scsi_add_device(shost, 0, target, lun); + break; + case VIRTIO_SCSI_EVT_RESET_REMOVED: + sdev = scsi_device_lookup(shost, 0, target, lun); + if (sdev) { + scsi_remove_device(sdev); + scsi_device_put(sdev); + } else { + pr_err(SCSI device %d 0 %d %d not found\n, + shost-host_no, target, lun); + } + break; + default: + pr_info(Unsupport virtio scsi event reason %x\n, event-reason); + } +} + +static void virtscsi_handle_event(struct work_struct *work) +{ + struct virtio_scsi_event_node *event_node = + container_of(work, struct virtio_scsi_event_node, work); + struct virtio_scsi *vscsi = event_node-vscsi; + struct virtio_scsi_event *event = event_node-event; + + if (event-event VIRTIO_SCSI_T_EVENTS_MISSED) { + event-event = (~VIRTIO_SCSI_T_EVENTS_MISSED); + /* FIXME: handle event missed here */ + } + + switch (event-event) { + case VIRTIO_SCSI_T_NO_EVENT: + break; + case VIRTIO_SCSI_T_TRANSPORT_RESET: + virtscsi_handle_transport_reset(vscsi, event); + break; + default: + pr_err(Unsupport virtio scsi event %x\n, event-event); + } + virtscsi_kick_event(vscsi, event_node); +} + +static void virtscsi_complete_event(void *buf) +{ + struct virtio_scsi_event_node *event_node = buf; + + INIT_WORK(event_node-work, virtscsi_handle_event); + schedule_work(event_node-work); +} + static void virtscsi_event_done(struct virtqueue *vq) { struct Scsi_Host *sh =
Re: [PATCH v2] virtio-scsi: hotplug support for virtio-scsi
Quoting Paolo Bonzini pbonz...@redhat.com: Il 03/07/2012 07:41, Cong Meng ha scritto: This patch implements the hotplug support for virtio-scsi. When there is a device attached/detached, the virtio-scsi driver will be signaled via event virtual queue and it will add/remove the scsi device in question automatically. v2: handle no_event event Signed-off-by: Cong Meng m...@linux.vnet.ibm.com Signed-off-by: Sen Wang senw...@linux.vnet.ibm.com The SoB lines are swapped. Otherwise looks good. Since you have to respin, please add dropped event support too, it shouldn't be hard. What does The SoB lines are swapped mean? should the changelog be placed after SoB lines? Paolo --- drivers/scsi/virtio_scsi.c | 113 ++- include/linux/virtio_scsi.h |9 2 files changed, 121 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 9fc5e67..e44b2d6 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -25,6 +25,7 @@ #include scsi/scsi_cmnd.h #define VIRTIO_SCSI_MEMPOOL_SZ 64 +#define VIRTIO_SCSI_EVENT_LEN 8 /* Command queue element */ struct virtio_scsi_cmd { @@ -43,6 +44,12 @@ struct virtio_scsi_cmd { } resp; } cacheline_aligned_in_smp; +struct virtio_scsi_event_node { + struct virtio_scsi *vscsi; + struct virtio_scsi_event event; + struct work_struct work; +}; + struct virtio_scsi_vq { /* Protects vq */ spinlock_t vq_lock; @@ -67,6 +74,9 @@ struct virtio_scsi { struct virtio_scsi_vq event_vq; struct virtio_scsi_vq req_vq; + /* Get some buffers reday for event vq */ + struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN]; + struct virtio_scsi_target_state *tgt[]; }; @@ -202,6 +212,97 @@ static void virtscsi_ctrl_done(struct virtqueue *vq) spin_unlock_irqrestore(vscsi-ctrl_vq.vq_lock, flags); }; +static int virtscsi_kick_event(struct virtio_scsi *vscsi, + struct virtio_scsi_event_node *event_node) +{ + int ret; + struct scatterlist sg; + unsigned long flags; + + sg_set_buf(sg, event_node-event, sizeof(struct virtio_scsi_event)); + + spin_lock_irqsave(vscsi-event_vq.vq_lock, flags); + + ret = virtqueue_add_buf(vscsi-event_vq.vq, sg, 0, 1, event_node, GFP_ATOMIC); + if (ret = 0) + virtqueue_kick(vscsi-event_vq.vq); + + spin_unlock_irqrestore(vscsi-event_vq.vq_lock, flags); + + return ret; +} + +static int virtscsi_kick_event_all(struct virtio_scsi *vscsi) +{ + int i; + + for (i = 0; i VIRTIO_SCSI_EVENT_LEN; i++) { + vscsi-event_list[i].vscsi = vscsi; + virtscsi_kick_event(vscsi, vscsi-event_list[i]); + } + + return 0; +} + +static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi, +struct virtio_scsi_event *event) +{ + struct scsi_device *sdev; + struct Scsi_Host *shost = virtio_scsi_host(vscsi-vdev); + unsigned int target = event-lun[1]; + unsigned int lun = (event-lun[2] 8) | event-lun[3]; + + switch (event-reason) { + case VIRTIO_SCSI_EVT_RESET_RESCAN: + scsi_add_device(shost, 0, target, lun); + break; + case VIRTIO_SCSI_EVT_RESET_REMOVED: + sdev = scsi_device_lookup(shost, 0, target, lun); + if (sdev) { + scsi_remove_device(sdev); + scsi_device_put(sdev); + } else { + pr_err(SCSI device %d 0 %d %d not found\n, + shost-host_no, target, lun); + } + break; + default: + pr_info(Unsupport virtio scsi event reason %x\n, event-reason); + } +} + +static void virtscsi_handle_event(struct work_struct *work) +{ + struct virtio_scsi_event_node *event_node = + container_of(work, struct virtio_scsi_event_node, work); + struct virtio_scsi *vscsi = event_node-vscsi; + struct virtio_scsi_event *event = event_node-event; + + if (event-event VIRTIO_SCSI_T_EVENTS_MISSED) { + event-event = (~VIRTIO_SCSI_T_EVENTS_MISSED); + /* FIXME: handle event missed here */ + } + + switch (event-event) { + case VIRTIO_SCSI_T_NO_EVENT: + break; + case VIRTIO_SCSI_T_TRANSPORT_RESET: + virtscsi_handle_transport_reset(vscsi, event); + break; + default: + pr_err(Unsupport virtio scsi event %x\n, event-event); + } + virtscsi_kick_event(vscsi, event_node); +} + +static void virtscsi_complete_event(void *buf) +{ + struct virtio_scsi_event_node *event_node = buf; + + INIT_WORK(event_node-work, virtscsi_handle_event); + schedule_work(event_node-work); +} + static
Re: [PATCH v2] virtio-scsi: hotplug support for virtio-scsi
Il 04/07/2012 10:11, m...@linux.vnet.ibm.com ha scritto: Signed-off-by: Cong Meng m...@linux.vnet.ibm.com Signed-off-by: Sen Wang senw...@linux.vnet.ibm.com The SoB lines are swapped. Otherwise looks good. Since you have to respin, please add dropped event support too, it shouldn't be hard. What does The SoB lines are swapped mean? should the changelog be placed after SoB lines? No, the patch sender should be the last SoB line. Sen Wang should hence come before you, not after. Paolo ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH v2] virtio-scsi: hotplug support for virtio-scsi
Il 03/07/2012 07:41, Cong Meng ha scritto: This patch implements the hotplug support for virtio-scsi. When there is a device attached/detached, the virtio-scsi driver will be signaled via event virtual queue and it will add/remove the scsi device in question automatically. v2: handle no_event event Signed-off-by: Cong Meng m...@linux.vnet.ibm.com Signed-off-by: Sen Wang senw...@linux.vnet.ibm.com The SoB lines are swapped. Otherwise looks good. Since you have to respin, please add dropped event support too, it shouldn't be hard. Paolo --- drivers/scsi/virtio_scsi.c | 113 ++- include/linux/virtio_scsi.h |9 2 files changed, 121 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 9fc5e67..e44b2d6 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -25,6 +25,7 @@ #include scsi/scsi_cmnd.h #define VIRTIO_SCSI_MEMPOOL_SZ 64 +#define VIRTIO_SCSI_EVENT_LEN 8 /* Command queue element */ struct virtio_scsi_cmd { @@ -43,6 +44,12 @@ struct virtio_scsi_cmd { } resp; } cacheline_aligned_in_smp; +struct virtio_scsi_event_node { + struct virtio_scsi *vscsi; + struct virtio_scsi_event event; + struct work_struct work; +}; + struct virtio_scsi_vq { /* Protects vq */ spinlock_t vq_lock; @@ -67,6 +74,9 @@ struct virtio_scsi { struct virtio_scsi_vq event_vq; struct virtio_scsi_vq req_vq; + /* Get some buffers reday for event vq */ + struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN]; + struct virtio_scsi_target_state *tgt[]; }; @@ -202,6 +212,97 @@ static void virtscsi_ctrl_done(struct virtqueue *vq) spin_unlock_irqrestore(vscsi-ctrl_vq.vq_lock, flags); }; +static int virtscsi_kick_event(struct virtio_scsi *vscsi, +struct virtio_scsi_event_node *event_node) +{ + int ret; + struct scatterlist sg; + unsigned long flags; + + sg_set_buf(sg, event_node-event, sizeof(struct virtio_scsi_event)); + + spin_lock_irqsave(vscsi-event_vq.vq_lock, flags); + + ret = virtqueue_add_buf(vscsi-event_vq.vq, sg, 0, 1, event_node, GFP_ATOMIC); + if (ret = 0) + virtqueue_kick(vscsi-event_vq.vq); + + spin_unlock_irqrestore(vscsi-event_vq.vq_lock, flags); + + return ret; +} + +static int virtscsi_kick_event_all(struct virtio_scsi *vscsi) +{ + int i; + + for (i = 0; i VIRTIO_SCSI_EVENT_LEN; i++) { + vscsi-event_list[i].vscsi = vscsi; + virtscsi_kick_event(vscsi, vscsi-event_list[i]); + } + + return 0; +} + +static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi, +struct virtio_scsi_event *event) +{ + struct scsi_device *sdev; + struct Scsi_Host *shost = virtio_scsi_host(vscsi-vdev); + unsigned int target = event-lun[1]; + unsigned int lun = (event-lun[2] 8) | event-lun[3]; + + switch (event-reason) { + case VIRTIO_SCSI_EVT_RESET_RESCAN: + scsi_add_device(shost, 0, target, lun); + break; + case VIRTIO_SCSI_EVT_RESET_REMOVED: + sdev = scsi_device_lookup(shost, 0, target, lun); + if (sdev) { + scsi_remove_device(sdev); + scsi_device_put(sdev); + } else { + pr_err(SCSI device %d 0 %d %d not found\n, + shost-host_no, target, lun); + } + break; + default: + pr_info(Unsupport virtio scsi event reason %x\n, event-reason); + } +} + +static void virtscsi_handle_event(struct work_struct *work) +{ + struct virtio_scsi_event_node *event_node = + container_of(work, struct virtio_scsi_event_node, work); + struct virtio_scsi *vscsi = event_node-vscsi; + struct virtio_scsi_event *event = event_node-event; + + if (event-event VIRTIO_SCSI_T_EVENTS_MISSED) { + event-event = (~VIRTIO_SCSI_T_EVENTS_MISSED); + /* FIXME: handle event missed here */ + } + + switch (event-event) { + case VIRTIO_SCSI_T_NO_EVENT: + break; + case VIRTIO_SCSI_T_TRANSPORT_RESET: + virtscsi_handle_transport_reset(vscsi, event); + break; + default: + pr_err(Unsupport virtio scsi event %x\n, event-event); + } + virtscsi_kick_event(vscsi, event_node); +} + +static void virtscsi_complete_event(void *buf) +{ + struct virtio_scsi_event_node *event_node = buf; + + INIT_WORK(event_node-work, virtscsi_handle_event); + schedule_work(event_node-work); +} + static void virtscsi_event_done(struct virtqueue *vq) { struct Scsi_Host *sh = virtio_scsi_host(vq-vdev); @@ -209,7 +310,7 @@ static
[PATCH v2] virtio-scsi: hotplug support for virtio-scsi
This patch implements the hotplug support for virtio-scsi. When there is a device attached/detached, the virtio-scsi driver will be signaled via event virtual queue and it will add/remove the scsi device in question automatically. v2: handle no_event event Signed-off-by: Cong Meng m...@linux.vnet.ibm.com Signed-off-by: Sen Wang senw...@linux.vnet.ibm.com --- drivers/scsi/virtio_scsi.c | 113 ++- include/linux/virtio_scsi.h |9 2 files changed, 121 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 9fc5e67..e44b2d6 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -25,6 +25,7 @@ #include scsi/scsi_cmnd.h #define VIRTIO_SCSI_MEMPOOL_SZ 64 +#define VIRTIO_SCSI_EVENT_LEN 8 /* Command queue element */ struct virtio_scsi_cmd { @@ -43,6 +44,12 @@ struct virtio_scsi_cmd { } resp; } cacheline_aligned_in_smp; +struct virtio_scsi_event_node { + struct virtio_scsi *vscsi; + struct virtio_scsi_event event; + struct work_struct work; +}; + struct virtio_scsi_vq { /* Protects vq */ spinlock_t vq_lock; @@ -67,6 +74,9 @@ struct virtio_scsi { struct virtio_scsi_vq event_vq; struct virtio_scsi_vq req_vq; + /* Get some buffers reday for event vq */ + struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN]; + struct virtio_scsi_target_state *tgt[]; }; @@ -202,6 +212,97 @@ static void virtscsi_ctrl_done(struct virtqueue *vq) spin_unlock_irqrestore(vscsi-ctrl_vq.vq_lock, flags); }; +static int virtscsi_kick_event(struct virtio_scsi *vscsi, + struct virtio_scsi_event_node *event_node) +{ + int ret; + struct scatterlist sg; + unsigned long flags; + + sg_set_buf(sg, event_node-event, sizeof(struct virtio_scsi_event)); + + spin_lock_irqsave(vscsi-event_vq.vq_lock, flags); + + ret = virtqueue_add_buf(vscsi-event_vq.vq, sg, 0, 1, event_node, GFP_ATOMIC); + if (ret = 0) + virtqueue_kick(vscsi-event_vq.vq); + + spin_unlock_irqrestore(vscsi-event_vq.vq_lock, flags); + + return ret; +} + +static int virtscsi_kick_event_all(struct virtio_scsi *vscsi) +{ + int i; + + for (i = 0; i VIRTIO_SCSI_EVENT_LEN; i++) { + vscsi-event_list[i].vscsi = vscsi; + virtscsi_kick_event(vscsi, vscsi-event_list[i]); + } + + return 0; +} + +static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi, +struct virtio_scsi_event *event) +{ + struct scsi_device *sdev; + struct Scsi_Host *shost = virtio_scsi_host(vscsi-vdev); + unsigned int target = event-lun[1]; + unsigned int lun = (event-lun[2] 8) | event-lun[3]; + + switch (event-reason) { + case VIRTIO_SCSI_EVT_RESET_RESCAN: + scsi_add_device(shost, 0, target, lun); + break; + case VIRTIO_SCSI_EVT_RESET_REMOVED: + sdev = scsi_device_lookup(shost, 0, target, lun); + if (sdev) { + scsi_remove_device(sdev); + scsi_device_put(sdev); + } else { + pr_err(SCSI device %d 0 %d %d not found\n, + shost-host_no, target, lun); + } + break; + default: + pr_info(Unsupport virtio scsi event reason %x\n, event-reason); + } +} + +static void virtscsi_handle_event(struct work_struct *work) +{ + struct virtio_scsi_event_node *event_node = + container_of(work, struct virtio_scsi_event_node, work); + struct virtio_scsi *vscsi = event_node-vscsi; + struct virtio_scsi_event *event = event_node-event; + + if (event-event VIRTIO_SCSI_T_EVENTS_MISSED) { + event-event = (~VIRTIO_SCSI_T_EVENTS_MISSED); + /* FIXME: handle event missed here */ + } + + switch (event-event) { + case VIRTIO_SCSI_T_NO_EVENT: + break; + case VIRTIO_SCSI_T_TRANSPORT_RESET: + virtscsi_handle_transport_reset(vscsi, event); + break; + default: + pr_err(Unsupport virtio scsi event %x\n, event-event); + } + virtscsi_kick_event(vscsi, event_node); +} + +static void virtscsi_complete_event(void *buf) +{ + struct virtio_scsi_event_node *event_node = buf; + + INIT_WORK(event_node-work, virtscsi_handle_event); + schedule_work(event_node-work); +} + static void virtscsi_event_done(struct virtqueue *vq) { struct Scsi_Host *sh = virtio_scsi_host(vq-vdev); @@ -209,7 +310,7 @@ static void virtscsi_event_done(struct virtqueue *vq) unsigned long flags; spin_lock_irqsave(vscsi-event_vq.vq_lock, flags); - virtscsi_vq_done(vq, virtscsi_complete_free); +