Re: [PATCH v2] virtio-scsi: hotplug support for virtio-scsi

2012-07-04 Thread Zhi Yong Wu
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

2012-07-04 Thread mc


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

2012-07-04 Thread Paolo Bonzini
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

2012-07-03 Thread Paolo Bonzini
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

2012-07-02 Thread Cong Meng
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);
+