All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/40] Staging: hv: Driver cleanup
@ 2011-06-29 14:38 K. Y. Srinivasan
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
  2011-06-30 19:33 ` [PATCH 00/40] Staging: hv: Driver cleanup Christoph Hellwig
  0 siblings, 2 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:38 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: K. Y. Srinivasan

Further cleanup of the hv drivers:

	1) Cleanup the reference counting mess for both stor and net devices.

	2) Handle all block devices using the storvsc driver.
	  
	3) Accomodate some host side scsi emulation bugs.

	4) In case of scsi errors off-line the device.


Regads,

K. Y 



^ permalink raw reply	[flat|nested] 122+ messages in thread

* [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device
  2011-06-29 14:38 [PATCH 00/40] Staging: hv: Driver cleanup K. Y. Srinivasan
@ 2011-06-29 14:38 ` K. Y. Srinivasan
  2011-06-29 14:38     ` K. Y. Srinivasan
                     ` (39 more replies)
  2011-06-30 19:33 ` [PATCH 00/40] Staging: hv: Driver cleanup Christoph Hellwig
  1 sibling, 40 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:38 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

On entry into storvsc_on_io_completion() we have already acquired a reference
on the stor_device; there is no need to acquire an additional reference here.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 8c62829..cd38cd6 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -232,9 +232,7 @@ static void storvsc_on_io_completion(struct hv_device *device,
 	struct storvsc_device *stor_device;
 	struct vstor_packet *stor_pkt;
 
-	stor_device = must_get_stor_device(device);
-	if (!stor_device)
-		return;
+	stor_device = (struct storvsc_device *)device->ext;
 
 	stor_pkt = &request->vstor_packet;
 
@@ -279,7 +277,6 @@ static void storvsc_on_io_completion(struct hv_device *device,
 		wake_up(&stor_device->waiting_to_drain);
 
 
-	put_stor_device(device);
 }
 
 static void storvsc_on_receive(struct hv_device *device,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 02/40] Staging: hv: storvsc: Rename must_get_stor_device()
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:38     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:38 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

In preparation for cleaning up how we manage reference counts on the stor
device, clearly distinguish why we are attempting to acquire a reference.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index cd38cd6..89708b1 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -41,7 +41,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 		return NULL;
 
 	/* Set to 2 to allow both inbound and outbound traffics */
-	/* (ie get_stor_device() and must_get_stor_device()) to proceed. */
+	/* (ie get_stor_device() and get_in_stor_device()) to proceed. */
 	atomic_cmpxchg(&stor_device->ref_count, 0, 2);
 
 	init_waitqueue_head(&stor_device->waiting_to_drain);
@@ -53,7 +53,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 
 
 /* Get the stordevice object iff exists and its refcount > 0 */
-static inline struct storvsc_device *must_get_stor_device(
+static inline struct storvsc_device *get_in_stor_device(
 					struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
@@ -305,7 +305,7 @@ static void storvsc_on_channel_callback(void *context)
 	int ret;
 
 
-	stor_device = must_get_stor_device(device);
+	stor_device = get_in_stor_device(device);
 	if (!stor_device)
 		return;
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 02/40] Staging: hv: storvsc: Rename must_get_stor_device()
@ 2011-06-29 14:38     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:38 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

In preparation for cleaning up how we manage reference counts on the stor
device, clearly distinguish why we are attempting to acquire a reference.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index cd38cd6..89708b1 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -41,7 +41,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 		return NULL;
 
 	/* Set to 2 to allow both inbound and outbound traffics */
-	/* (ie get_stor_device() and must_get_stor_device()) to proceed. */
+	/* (ie get_stor_device() and get_in_stor_device()) to proceed. */
 	atomic_cmpxchg(&stor_device->ref_count, 0, 2);
 
 	init_waitqueue_head(&stor_device->waiting_to_drain);
@@ -53,7 +53,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 
 
 /* Get the stordevice object iff exists and its refcount > 0 */
-static inline struct storvsc_device *must_get_stor_device(
+static inline struct storvsc_device *get_in_stor_device(
 					struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
@@ -305,7 +305,7 @@ static void storvsc_on_channel_callback(void *context)
 	int ret;
 
 
-	stor_device = must_get_stor_device(device);
+	stor_device = get_in_stor_device(device);
 	if (!stor_device)
 		return;
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 03/40] Staging: hv: storvsc: Rename get_stor_device()
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

In preparation for cleaning up how we manage reference counts on the stor
device, clearly distinguish why we are attempting to acquire a reference.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    3 ++-
 drivers/staging/hv/storvsc.c        |    8 ++++----
 drivers/staging/hv/storvsc_drv.c    |    2 +-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index a01f9a0..a224413 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -288,7 +288,8 @@ struct storvsc_device {
 
 
 /* Get the stordevice object iff exists and its refcount > 1 */
-static inline struct storvsc_device *get_stor_device(struct hv_device *device)
+static inline struct storvsc_device *get_out_stor_device(
+					struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
 
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 89708b1..313a3f8 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -41,7 +41,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 		return NULL;
 
 	/* Set to 2 to allow both inbound and outbound traffics */
-	/* (ie get_stor_device() and get_in_stor_device()) to proceed. */
+	/* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */
 	atomic_cmpxchg(&stor_device->ref_count, 0, 2);
 
 	init_waitqueue_head(&stor_device->waiting_to_drain);
@@ -67,7 +67,7 @@ static inline struct storvsc_device *get_in_stor_device(
 	return stor_device;
 }
 
-/* Drop ref count to 1 to effectively disable get_stor_device() */
+/* Drop ref count to 1 to effectively disable get_out_stor_device() */
 static inline struct storvsc_device *release_stor_device(
 					struct hv_device *device)
 {
@@ -105,7 +105,7 @@ static int storvsc_channel_init(struct hv_device *device)
 	struct vstor_packet *vstor_packet;
 	int ret, t;
 
-	stor_device = get_stor_device(device);
+	stor_device = get_out_stor_device(device);
 	if (!stor_device)
 		return -ENODEV;
 
@@ -427,7 +427,7 @@ int storvsc_do_io(struct hv_device *device,
 	int ret = 0;
 
 	vstor_packet = &request->vstor_packet;
-	stor_device = get_stor_device(device);
+	stor_device = get_out_stor_device(device);
 
 	if (!stor_device)
 		return -ENODEV;
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 7db5246..8d5be51 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -346,7 +346,7 @@ static int storvsc_host_reset(struct hv_device *device)
 	int ret, t;
 
 
-	stor_device = get_stor_device(device);
+	stor_device = get_out_stor_device(device);
 	if (!stor_device)
 		return -ENODEV;
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 03/40] Staging: hv: storvsc: Rename get_stor_device()
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

In preparation for cleaning up how we manage reference counts on the stor
device, clearly distinguish why we are attempting to acquire a reference.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    3 ++-
 drivers/staging/hv/storvsc.c        |    8 ++++----
 drivers/staging/hv/storvsc_drv.c    |    2 +-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index a01f9a0..a224413 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -288,7 +288,8 @@ struct storvsc_device {
 
 
 /* Get the stordevice object iff exists and its refcount > 1 */
-static inline struct storvsc_device *get_stor_device(struct hv_device *device)
+static inline struct storvsc_device *get_out_stor_device(
+					struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
 
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 89708b1..313a3f8 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -41,7 +41,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 		return NULL;
 
 	/* Set to 2 to allow both inbound and outbound traffics */
-	/* (ie get_stor_device() and get_in_stor_device()) to proceed. */
+	/* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */
 	atomic_cmpxchg(&stor_device->ref_count, 0, 2);
 
 	init_waitqueue_head(&stor_device->waiting_to_drain);
@@ -67,7 +67,7 @@ static inline struct storvsc_device *get_in_stor_device(
 	return stor_device;
 }
 
-/* Drop ref count to 1 to effectively disable get_stor_device() */
+/* Drop ref count to 1 to effectively disable get_out_stor_device() */
 static inline struct storvsc_device *release_stor_device(
 					struct hv_device *device)
 {
@@ -105,7 +105,7 @@ static int storvsc_channel_init(struct hv_device *device)
 	struct vstor_packet *vstor_packet;
 	int ret, t;
 
-	stor_device = get_stor_device(device);
+	stor_device = get_out_stor_device(device);
 	if (!stor_device)
 		return -ENODEV;
 
@@ -427,7 +427,7 @@ int storvsc_do_io(struct hv_device *device,
 	int ret = 0;
 
 	vstor_packet = &request->vstor_packet;
-	stor_device = get_stor_device(device);
+	stor_device = get_out_stor_device(device);
 
 	if (!stor_device)
 		return -ENODEV;
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 7db5246..8d5be51 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -346,7 +346,7 @@ static int storvsc_host_reset(struct hv_device *device)
 	int ret, t;
 
 
-	stor_device = get_stor_device(device);
+	stor_device = get_out_stor_device(device);
 	if (!stor_device)
 		return -ENODEV;
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 04/40] Staging: hv: storvsc: Cleanup alloc_stor_device()
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Cleanup alloc_stor_device(), we can set the ref_count directly.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 313a3f8..48bd8da 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -42,7 +42,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 
 	/* Set to 2 to allow both inbound and outbound traffics */
 	/* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */
-	atomic_cmpxchg(&stor_device->ref_count, 0, 2);
+	atomic_set(&stor_device->ref_count, 2);
 
 	init_waitqueue_head(&stor_device->waiting_to_drain);
 	stor_device->device = device;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 04/40] Staging: hv: storvsc: Cleanup alloc_stor_device()
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Cleanup alloc_stor_device(), we can set the ref_count directly.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 313a3f8..48bd8da 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -42,7 +42,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 
 	/* Set to 2 to allow both inbound and outbound traffics */
 	/* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */
-	atomic_cmpxchg(&stor_device->ref_count, 0, 2);
+	atomic_set(&stor_device->ref_count, 2);
 
 	init_waitqueue_head(&stor_device->waiting_to_drain);
 	stor_device->device = device;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 05/40] Staging: hv: storvsc: Introduce state to manage the lifecycle of stor device
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Introduce state to manage the lifecycle of stor device. This would be the
basis for managing the references on the stor object.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    2 +-
 drivers/staging/hv/storvsc.c        |    3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index a224413..d93bf93 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -266,7 +266,7 @@ struct storvsc_device {
 
 	/* 0 indicates the device is being destroyed */
 	atomic_t ref_count;
-
+	bool	 destroy;
 	bool	 drain_notify;
 	atomic_t num_outstanding_req;
 
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 48bd8da..357b08a 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -43,7 +43,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 	/* Set to 2 to allow both inbound and outbound traffics */
 	/* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */
 	atomic_set(&stor_device->ref_count, 2);
-
+	stor_device->destroy = false;
 	init_waitqueue_head(&stor_device->waiting_to_drain);
 	stor_device->device = device;
 	device->ext = stor_device;
@@ -401,6 +401,7 @@ int storvsc_dev_remove(struct hv_device *device)
 	struct storvsc_device *stor_device;
 
 	stor_device = release_stor_device(device);
+	stor_device->destroy = true;
 
 	/*
 	 * At this point, all outbound traffic should be disable. We
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 05/40] Staging: hv: storvsc: Introduce state to manage the lifecycle of stor device
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Introduce state to manage the lifecycle of stor device. This would be the
basis for managing the references on the stor object.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    2 +-
 drivers/staging/hv/storvsc.c        |    3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index a224413..d93bf93 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -266,7 +266,7 @@ struct storvsc_device {
 
 	/* 0 indicates the device is being destroyed */
 	atomic_t ref_count;
-
+	bool	 destroy;
 	bool	 drain_notify;
 	atomic_t num_outstanding_req;
 
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 48bd8da..357b08a 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -43,7 +43,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 	/* Set to 2 to allow both inbound and outbound traffics */
 	/* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */
 	atomic_set(&stor_device->ref_count, 2);
-
+	stor_device->destroy = false;
 	init_waitqueue_head(&stor_device->waiting_to_drain);
 	stor_device->device = device;
 	device->ext = stor_device;
@@ -401,6 +401,7 @@ int storvsc_dev_remove(struct hv_device *device)
 	struct storvsc_device *stor_device;
 
 	stor_device = release_stor_device(device);
+	stor_device->destroy = true;
 
 	/*
 	 * At this point, all outbound traffic should be disable. We
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 06/40] Staging: hv: vmbus: Introduce a lock to protect the ext field in hv_device
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

The current mechanism for handling references in broken. 
Introduce a lock to protect the ext field in hv_device.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv.h    |    3 +++
 drivers/staging/hv/vmbus_drv.c |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h
index 370b096..ff3c69d 100644
--- a/drivers/staging/hv/hyperv.h
+++ b/drivers/staging/hv/hyperv.h
@@ -830,6 +830,9 @@ struct hv_device {
 
 	struct vmbus_channel *channel;
 
+	/* This lock protects the device extension field */
+	spinlock_t ext_lock;
+
 	/* Device extension; */
 	void *ext;
 };
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index 2e6bfc1..903362e 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -557,6 +557,7 @@ struct hv_device *vmbus_child_device_create(struct hv_guid *type,
 		return NULL;
 	}
 
+	spin_lock_init(&child_device_obj->ext_lock);
 	child_device_obj->channel = channel;
 	/*
 	 * Get the human readable device type name and stash it away.
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 06/40] Staging: hv: vmbus: Introduce a lock to protect the ext field in hv_device
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

The current mechanism for handling references in broken. 
Introduce a lock to protect the ext field in hv_device.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv.h    |    3 +++
 drivers/staging/hv/vmbus_drv.c |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h
index 370b096..ff3c69d 100644
--- a/drivers/staging/hv/hyperv.h
+++ b/drivers/staging/hv/hyperv.h
@@ -830,6 +830,9 @@ struct hv_device {
 
 	struct vmbus_channel *channel;
 
+	/* This lock protects the device extension field */
+	spinlock_t ext_lock;
+
 	/* Device extension; */
 	void *ext;
 };
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index 2e6bfc1..903362e 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -557,6 +557,7 @@ struct hv_device *vmbus_child_device_create(struct hv_guid *type,
 		return NULL;
 	}
 
+	spin_lock_init(&child_device_obj->ext_lock);
 	child_device_obj->channel = channel;
 	/*
 	 * Get the human readable device type name and stash it away.
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 07/40] Staging: hv: storvsc: Use the newly introduced lock in accessing ext field
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
                     ` (4 preceding siblings ...)
  2011-06-29 14:39     ` K. Y. Srinivasan
@ 2011-06-29 14:39   ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                     ` (33 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Use the newly introduced lock in accessing ext field.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    6 ++++++
 drivers/staging/hv/storvsc.c        |    6 ++++++
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index d93bf93..6b20f1d 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -292,12 +292,15 @@ static inline struct storvsc_device *get_out_stor_device(
 					struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
 	if (stor_device && atomic_read(&stor_device->ref_count) > 1)
 		atomic_inc(&stor_device->ref_count);
 	else
 		stor_device = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 
 	return stor_device;
 }
@@ -306,10 +309,13 @@ static inline struct storvsc_device *get_out_stor_device(
 static inline void put_stor_device(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
 
 	atomic_dec(&stor_device->ref_count);
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 }
 
 static inline void storvsc_wait_to_drain(struct storvsc_device *dev)
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 357b08a..d1b6c4e 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -57,12 +57,15 @@ static inline struct storvsc_device *get_in_stor_device(
 					struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
 	if (stor_device && atomic_read(&stor_device->ref_count))
 		atomic_inc(&stor_device->ref_count);
 	else
 		stor_device = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 
 	return stor_device;
 }
@@ -87,6 +90,7 @@ static inline struct storvsc_device *final_release_stor_device(
 			struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
+	unsigned long flags;
 
 	stor_device = (struct storvsc_device *)device->ext;
 
@@ -94,7 +98,9 @@ static inline struct storvsc_device *final_release_stor_device(
 	while (atomic_cmpxchg(&stor_device->ref_count, 1, 0) != 1)
 		udelay(100);
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	device->ext = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 	return stor_device;
 }
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 08/40] Staging: hv: storvsc: Prevent outgoing traffic when stor dev is destroyed
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Prevent outgoing traffic when stor dev is destroyed.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index 6b20f1d..53b65be 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -296,7 +296,8 @@ static inline struct storvsc_device *get_out_stor_device(
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && atomic_read(&stor_device->ref_count) > 1)
+	if (stor_device && (atomic_read(&stor_device->ref_count) > 1) &&
+		!stor_device->destroy)
 		atomic_inc(&stor_device->ref_count);
 	else
 		stor_device = NULL;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 08/40] Staging: hv: storvsc: Prevent outgoing traffic when stor dev is destroyed
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Prevent outgoing traffic when stor dev is destroyed.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index 6b20f1d..53b65be 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -296,7 +296,8 @@ static inline struct storvsc_device *get_out_stor_device(
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && atomic_read(&stor_device->ref_count) > 1)
+	if (stor_device && (atomic_read(&stor_device->ref_count) > 1) &&
+		!stor_device->destroy)
 		atomic_inc(&stor_device->ref_count);
 	else
 		stor_device = NULL;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 09/40] Staging: hv: storvsc: Get rid of release_stor_device() by inlining the code
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Get rid of release_stor_device() by inlining the code.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc.c |   23 +++++++----------------
 1 files changed, 7 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index d1b6c4e..f52e610 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -70,21 +70,6 @@ static inline struct storvsc_device *get_in_stor_device(
 	return stor_device;
 }
 
-/* Drop ref count to 1 to effectively disable get_out_stor_device() */
-static inline struct storvsc_device *release_stor_device(
-					struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-
-	stor_device = (struct storvsc_device *)device->ext;
-
-	/* Busy wait until the ref drop to 2, then set it to 1 */
-	while (atomic_cmpxchg(&stor_device->ref_count, 2, 1) != 2)
-		udelay(100);
-
-	return stor_device;
-}
-
 /* Drop ref count to 0. No one can use stor_device object. */
 static inline struct storvsc_device *final_release_stor_device(
 			struct hv_device *device)
@@ -406,7 +391,13 @@ int storvsc_dev_remove(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
 
-	stor_device = release_stor_device(device);
+	/*
+	 * Since we currently hold a reference on the stor
+	 * device, it is safe to dereference the ext
+	 * pointer.
+	 */
+	stor_device = (struct storvsc_device *)device->ext;
+	atomic_dec(&stor_device->ref_count);
 	stor_device->destroy = true;
 
 	/*
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 09/40] Staging: hv: storvsc: Get rid of release_stor_device() by inlining the code
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Get rid of release_stor_device() by inlining the code.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc.c |   23 +++++++----------------
 1 files changed, 7 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index d1b6c4e..f52e610 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -70,21 +70,6 @@ static inline struct storvsc_device *get_in_stor_device(
 	return stor_device;
 }
 
-/* Drop ref count to 1 to effectively disable get_out_stor_device() */
-static inline struct storvsc_device *release_stor_device(
-					struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-
-	stor_device = (struct storvsc_device *)device->ext;
-
-	/* Busy wait until the ref drop to 2, then set it to 1 */
-	while (atomic_cmpxchg(&stor_device->ref_count, 2, 1) != 2)
-		udelay(100);
-
-	return stor_device;
-}
-
 /* Drop ref count to 0. No one can use stor_device object. */
 static inline struct storvsc_device *final_release_stor_device(
 			struct hv_device *device)
@@ -406,7 +391,13 @@ int storvsc_dev_remove(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
 
-	stor_device = release_stor_device(device);
+	/*
+	 * Since we currently hold a reference on the stor
+	 * device, it is safe to dereference the ext
+	 * pointer.
+	 */
+	stor_device = (struct storvsc_device *)device->ext;
+	atomic_dec(&stor_device->ref_count);
 	stor_device->destroy = true;
 
 	/*
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 10/40] Staging: hv: storvsc: Get rid of final_release_stor_device() by inlining code
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Get rid of final_release_stor_device() by inlining code.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc.c |   25 +++++--------------------
 1 files changed, 5 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index f52e610..c4cb170 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -70,25 +70,6 @@ static inline struct storvsc_device *get_in_stor_device(
 	return stor_device;
 }
 
-/* Drop ref count to 0. No one can use stor_device object. */
-static inline struct storvsc_device *final_release_stor_device(
-			struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	unsigned long flags;
-
-	stor_device = (struct storvsc_device *)device->ext;
-
-	/* Busy wait until the ref drop to 1, then set it to 0 */
-	while (atomic_cmpxchg(&stor_device->ref_count, 1, 0) != 1)
-		udelay(100);
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	device->ext = NULL;
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-	return stor_device;
-}
-
 static int storvsc_channel_init(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
@@ -390,6 +371,7 @@ int storvsc_dev_add(struct hv_device *device,
 int storvsc_dev_remove(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
+	unsigned long flags;
 
 	/*
 	 * Since we currently hold a reference on the stor
@@ -408,7 +390,10 @@ int storvsc_dev_remove(struct hv_device *device)
 
 	storvsc_wait_to_drain(stor_device);
 
-	stor_device = final_release_stor_device(device);
+	spin_lock_irqsave(&device->ext_lock, flags);
+	atomic_set(&stor_device->ref_count, 0);
+	device->ext = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 
 	/* Close the channel */
 	vmbus_close(device->channel);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 10/40] Staging: hv: storvsc: Get rid of final_release_stor_device() by inlining code
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Get rid of final_release_stor_device() by inlining code.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc.c |   25 +++++--------------------
 1 files changed, 5 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index f52e610..c4cb170 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -70,25 +70,6 @@ static inline struct storvsc_device *get_in_stor_device(
 	return stor_device;
 }
 
-/* Drop ref count to 0. No one can use stor_device object. */
-static inline struct storvsc_device *final_release_stor_device(
-			struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	unsigned long flags;
-
-	stor_device = (struct storvsc_device *)device->ext;
-
-	/* Busy wait until the ref drop to 1, then set it to 0 */
-	while (atomic_cmpxchg(&stor_device->ref_count, 1, 0) != 1)
-		udelay(100);
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	device->ext = NULL;
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-	return stor_device;
-}
-
 static int storvsc_channel_init(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
@@ -390,6 +371,7 @@ int storvsc_dev_add(struct hv_device *device,
 int storvsc_dev_remove(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
+	unsigned long flags;
 
 	/*
 	 * Since we currently hold a reference on the stor
@@ -408,7 +390,10 @@ int storvsc_dev_remove(struct hv_device *device)
 
 	storvsc_wait_to_drain(stor_device);
 
-	stor_device = final_release_stor_device(device);
+	spin_lock_irqsave(&device->ext_lock, flags);
+	atomic_set(&stor_device->ref_count, 0);
+	device->ext = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 
 	/* Close the channel */
 	vmbus_close(device->channel);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 11/40] Staging: hv: storvsc: Leverage the spinlock to manage ref_cnt
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Now that we have a spin lock protecting access to the stor device pointer,
use it manage the reference count as well.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    8 ++++----
 drivers/staging/hv/storvsc.c        |   10 +++++-----
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index 53b65be..d946211 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -265,7 +265,7 @@ struct storvsc_device {
 	struct hv_device *device;
 
 	/* 0 indicates the device is being destroyed */
-	atomic_t ref_count;
+	int	 ref_count;
 	bool	 destroy;
 	bool	 drain_notify;
 	atomic_t num_outstanding_req;
@@ -296,9 +296,9 @@ static inline struct storvsc_device *get_out_stor_device(
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && (atomic_read(&stor_device->ref_count) > 1) &&
+	if (stor_device && (stor_device->ref_count > 1) &&
 		!stor_device->destroy)
-		atomic_inc(&stor_device->ref_count);
+		stor_device->ref_count++;
 	else
 		stor_device = NULL;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
@@ -315,7 +315,7 @@ static inline void put_stor_device(struct hv_device *device)
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
 
-	atomic_dec(&stor_device->ref_count);
+	stor_device->ref_count--;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 }
 
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index c4cb170..a41be2a 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -42,7 +42,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 
 	/* Set to 2 to allow both inbound and outbound traffics */
 	/* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */
-	atomic_set(&stor_device->ref_count, 2);
+	stor_device->ref_count = 2;
 	stor_device->destroy = false;
 	init_waitqueue_head(&stor_device->waiting_to_drain);
 	stor_device->device = device;
@@ -61,8 +61,8 @@ static inline struct storvsc_device *get_in_stor_device(
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && atomic_read(&stor_device->ref_count))
-		atomic_inc(&stor_device->ref_count);
+	if (stor_device && stor_device->ref_count)
+		stor_device->ref_count++;
 	else
 		stor_device = NULL;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
@@ -379,7 +379,7 @@ int storvsc_dev_remove(struct hv_device *device)
 	 * pointer.
 	 */
 	stor_device = (struct storvsc_device *)device->ext;
-	atomic_dec(&stor_device->ref_count);
+
 	stor_device->destroy = true;
 
 	/*
@@ -391,7 +391,7 @@ int storvsc_dev_remove(struct hv_device *device)
 	storvsc_wait_to_drain(stor_device);
 
 	spin_lock_irqsave(&device->ext_lock, flags);
-	atomic_set(&stor_device->ref_count, 0);
+	stor_device->ref_count = 0;
 	device->ext = NULL;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 11/40] Staging: hv: storvsc: Leverage the spinlock to manage ref_cnt
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Now that we have a spin lock protecting access to the stor device pointer,
use it manage the reference count as well.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    8 ++++----
 drivers/staging/hv/storvsc.c        |   10 +++++-----
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index 53b65be..d946211 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -265,7 +265,7 @@ struct storvsc_device {
 	struct hv_device *device;
 
 	/* 0 indicates the device is being destroyed */
-	atomic_t ref_count;
+	int	 ref_count;
 	bool	 destroy;
 	bool	 drain_notify;
 	atomic_t num_outstanding_req;
@@ -296,9 +296,9 @@ static inline struct storvsc_device *get_out_stor_device(
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && (atomic_read(&stor_device->ref_count) > 1) &&
+	if (stor_device && (stor_device->ref_count > 1) &&
 		!stor_device->destroy)
-		atomic_inc(&stor_device->ref_count);
+		stor_device->ref_count++;
 	else
 		stor_device = NULL;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
@@ -315,7 +315,7 @@ static inline void put_stor_device(struct hv_device *device)
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
 
-	atomic_dec(&stor_device->ref_count);
+	stor_device->ref_count--;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 }
 
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index c4cb170..a41be2a 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -42,7 +42,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 
 	/* Set to 2 to allow both inbound and outbound traffics */
 	/* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */
-	atomic_set(&stor_device->ref_count, 2);
+	stor_device->ref_count = 2;
 	stor_device->destroy = false;
 	init_waitqueue_head(&stor_device->waiting_to_drain);
 	stor_device->device = device;
@@ -61,8 +61,8 @@ static inline struct storvsc_device *get_in_stor_device(
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && atomic_read(&stor_device->ref_count))
-		atomic_inc(&stor_device->ref_count);
+	if (stor_device && stor_device->ref_count)
+		stor_device->ref_count++;
 	else
 		stor_device = NULL;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
@@ -379,7 +379,7 @@ int storvsc_dev_remove(struct hv_device *device)
 	 * pointer.
 	 */
 	stor_device = (struct storvsc_device *)device->ext;
-	atomic_dec(&stor_device->ref_count);
+
 	stor_device->destroy = true;
 
 	/*
@@ -391,7 +391,7 @@ int storvsc_dev_remove(struct hv_device *device)
 	storvsc_wait_to_drain(stor_device);
 
 	spin_lock_irqsave(&device->ext_lock, flags);
-	atomic_set(&stor_device->ref_count, 0);
+	stor_device->ref_count = 0;
 	device->ext = NULL;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 12/40] Staging: hv: storvsc: Further cleanup reference counting of stor_device
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Further cleanup reference counting of stor_device - when the device is being
destroyed, we will permit incoming traffic only to drain outstanding
requests.


Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    3 +--
 drivers/staging/hv/storvsc.c        |   22 +++++++++++++---------
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index d946211..a1f3e27 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -287,7 +287,6 @@ struct storvsc_device {
 };
 
 
-/* Get the stordevice object iff exists and its refcount > 1 */
 static inline struct storvsc_device *get_out_stor_device(
 					struct hv_device *device)
 {
@@ -296,7 +295,7 @@ static inline struct storvsc_device *get_out_stor_device(
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && (stor_device->ref_count > 1) &&
+	if (stor_device && (stor_device->ref_count) &&
 		!stor_device->destroy)
 		stor_device->ref_count++;
 	else
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index a41be2a..4d13044 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -40,9 +40,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 	if (!stor_device)
 		return NULL;
 
-	/* Set to 2 to allow both inbound and outbound traffics */
-	/* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */
-	stor_device->ref_count = 2;
+	stor_device->ref_count = 1;
 	stor_device->destroy = false;
 	init_waitqueue_head(&stor_device->waiting_to_drain);
 	stor_device->device = device;
@@ -51,8 +49,6 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 	return stor_device;
 }
 
-
-/* Get the stordevice object iff exists and its refcount > 0 */
 static inline struct storvsc_device *get_in_stor_device(
 					struct hv_device *device)
 {
@@ -61,10 +57,18 @@ static inline struct storvsc_device *get_in_stor_device(
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && stor_device->ref_count)
-		stor_device->ref_count++;
-	else
-		stor_device = NULL;
+	if (!stor_device)
+		goto cleanup;
+
+	/*
+	 * If the device is being destroyed; allow incoming
+	 * traffic only to cleanup outstanding requests.
+	 */
+	if (stor_device->destroy &&
+		 (atomic_read(&stor_device->num_outstanding_req) == 0))
+		goto cleanup;
+	stor_device->ref_count++;
+cleanup:
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 
 	return stor_device;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 12/40] Staging: hv: storvsc: Further cleanup reference counting of stor_device
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Further cleanup reference counting of stor_device - when the device is being
destroyed, we will permit incoming traffic only to drain outstanding
requests.


Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    3 +--
 drivers/staging/hv/storvsc.c        |   22 +++++++++++++---------
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index d946211..a1f3e27 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -287,7 +287,6 @@ struct storvsc_device {
 };
 
 
-/* Get the stordevice object iff exists and its refcount > 1 */
 static inline struct storvsc_device *get_out_stor_device(
 					struct hv_device *device)
 {
@@ -296,7 +295,7 @@ static inline struct storvsc_device *get_out_stor_device(
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && (stor_device->ref_count > 1) &&
+	if (stor_device && (stor_device->ref_count) &&
 		!stor_device->destroy)
 		stor_device->ref_count++;
 	else
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index a41be2a..4d13044 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -40,9 +40,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 	if (!stor_device)
 		return NULL;
 
-	/* Set to 2 to allow both inbound and outbound traffics */
-	/* (ie get_out_stor_device() and get_in_stor_device()) to proceed. */
-	stor_device->ref_count = 2;
+	stor_device->ref_count = 1;
 	stor_device->destroy = false;
 	init_waitqueue_head(&stor_device->waiting_to_drain);
 	stor_device->device = device;
@@ -51,8 +49,6 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 	return stor_device;
 }
 
-
-/* Get the stordevice object iff exists and its refcount > 0 */
 static inline struct storvsc_device *get_in_stor_device(
 					struct hv_device *device)
 {
@@ -61,10 +57,18 @@ static inline struct storvsc_device *get_in_stor_device(
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && stor_device->ref_count)
-		stor_device->ref_count++;
-	else
-		stor_device = NULL;
+	if (!stor_device)
+		goto cleanup;
+
+	/*
+	 * If the device is being destroyed; allow incoming
+	 * traffic only to cleanup outstanding requests.
+	 */
+	if (stor_device->destroy &&
+		 (atomic_read(&stor_device->num_outstanding_req) == 0))
+		goto cleanup;
+	stor_device->ref_count++;
+cleanup:
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 
 	return stor_device;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 13/40] Staging: hv: netvsc: Introduce code to properly manage outstanding sends
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Introduce code to properly manage outstanding sends.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_net.h |   10 ++++++++++
 drivers/staging/hv/netvsc.c     |    6 +++++-
 2 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h
index 5782fea..b5bee9e 100644
--- a/drivers/staging/hv/hyperv_net.h
+++ b/drivers/staging/hv/hyperv_net.h
@@ -371,6 +371,8 @@ struct netvsc_device {
 
 	atomic_t refcnt;
 	atomic_t num_outstanding_sends;
+	bool drain_notify;
+	wait_queue_head_t waiting_to_drain;
 	/*
 	 * List of free preallocated hv_netvsc_packet to represent receive
 	 * packet
@@ -1051,6 +1053,14 @@ struct rndis_filter_packet {
 #define NDIS_PACKET_TYPE_FUNCTIONAL	0x00000400
 #define NDIS_PACKET_TYPE_MAC_FRAME	0x00000800
 
+static inline void netvsc_wait_to_drain(struct netvsc_device *dev)
+{
+	dev->drain_notify = true;
+	wait_event(dev->waiting_to_drain,
+		atomic_read(&dev->num_outstanding_sends) == 0);
+	dev->drain_notify = false;
+}
+
 
 
 #endif /* _HYPERV_NET_H */
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 551537a..bdd5c2b 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -42,6 +42,8 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 
 	/* Set to 2 to allow both inbound and outbound traffic */
 	atomic_cmpxchg(&net_device->refcnt, 0, 2);
+	net_device->drain_notify = false;
+	init_waitqueue_head(&net_device->waiting_to_drain);
 
 	net_device->dev = device;
 	device->ext = net_device;
@@ -483,7 +485,9 @@ static void netvsc_send_completion(struct hv_device *device,
 		nvsc_packet->completion.send.send_completion(
 			nvsc_packet->completion.send.send_completion_ctx);
 
-		atomic_dec(&net_device->num_outstanding_sends);
+		if (atomic_dec_and_test(&net_device->num_outstanding_sends) &&
+			net_device->drain_notify)
+			wake_up(&net_device->waiting_to_drain);
 	} else {
 		netdev_err(ndev, "Unknown send completion packet type- "
 			   "%d received!!\n", nvsp_packet->hdr.msg_type);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 13/40] Staging: hv: netvsc: Introduce code to properly manage outstanding sends
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Introduce code to properly manage outstanding sends.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_net.h |   10 ++++++++++
 drivers/staging/hv/netvsc.c     |    6 +++++-
 2 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h
index 5782fea..b5bee9e 100644
--- a/drivers/staging/hv/hyperv_net.h
+++ b/drivers/staging/hv/hyperv_net.h
@@ -371,6 +371,8 @@ struct netvsc_device {
 
 	atomic_t refcnt;
 	atomic_t num_outstanding_sends;
+	bool drain_notify;
+	wait_queue_head_t waiting_to_drain;
 	/*
 	 * List of free preallocated hv_netvsc_packet to represent receive
 	 * packet
@@ -1051,6 +1053,14 @@ struct rndis_filter_packet {
 #define NDIS_PACKET_TYPE_FUNCTIONAL	0x00000400
 #define NDIS_PACKET_TYPE_MAC_FRAME	0x00000800
 
+static inline void netvsc_wait_to_drain(struct netvsc_device *dev)
+{
+	dev->drain_notify = true;
+	wait_event(dev->waiting_to_drain,
+		atomic_read(&dev->num_outstanding_sends) == 0);
+	dev->drain_notify = false;
+}
+
 
 
 #endif /* _HYPERV_NET_H */
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 551537a..bdd5c2b 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -42,6 +42,8 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 
 	/* Set to 2 to allow both inbound and outbound traffic */
 	atomic_cmpxchg(&net_device->refcnt, 0, 2);
+	net_device->drain_notify = false;
+	init_waitqueue_head(&net_device->waiting_to_drain);
 
 	net_device->dev = device;
 	device->ext = net_device;
@@ -483,7 +485,9 @@ static void netvsc_send_completion(struct hv_device *device,
 		nvsc_packet->completion.send.send_completion(
 			nvsc_packet->completion.send.send_completion_ctx);
 
-		atomic_dec(&net_device->num_outstanding_sends);
+		if (atomic_dec_and_test(&net_device->num_outstanding_sends) &&
+			net_device->drain_notify)
+			wake_up(&net_device->waiting_to_drain);
 	} else {
 		netdev_err(ndev, "Unknown send completion packet type- "
 			   "%d received!!\n", nvsp_packet->hdr.msg_type);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 14/40] Staging: hv: netvsc: Inline the code for free_net_device()
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Inline the code for free_net_device().

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |   12 ++----------
 1 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index bdd5c2b..c3c934c 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -51,14 +51,6 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 	return net_device;
 }
 
-static void free_net_device(struct netvsc_device *device)
-{
-	WARN_ON(atomic_read(&device->refcnt) != 0);
-	device->dev->ext = NULL;
-	kfree(device);
-}
-
-
 /* Get the net device object iff exists and its refcount > 1 */
 static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 {
@@ -444,7 +436,7 @@ int netvsc_device_remove(struct hv_device *device)
 		kfree(netvsc_packet);
 	}
 
-	free_net_device(net_device);
+	kfree(net_device);
 	return 0;
 }
 
@@ -994,7 +986,7 @@ cleanup:
 		release_outbound_net_device(device);
 		release_inbound_net_device(device);
 
-		free_net_device(net_device);
+		kfree(net_device);
 	}
 
 	return ret;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 14/40] Staging: hv: netvsc: Inline the code for free_net_device()
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Inline the code for free_net_device().

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |   12 ++----------
 1 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index bdd5c2b..c3c934c 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -51,14 +51,6 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 	return net_device;
 }
 
-static void free_net_device(struct netvsc_device *device)
-{
-	WARN_ON(atomic_read(&device->refcnt) != 0);
-	device->dev->ext = NULL;
-	kfree(device);
-}
-
-
 /* Get the net device object iff exists and its refcount > 1 */
 static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 {
@@ -444,7 +436,7 @@ int netvsc_device_remove(struct hv_device *device)
 		kfree(netvsc_packet);
 	}
 
-	free_net_device(net_device);
+	kfree(net_device);
 	return 0;
 }
 
@@ -994,7 +986,7 @@ cleanup:
 		release_outbound_net_device(device);
 		release_inbound_net_device(device);
 
-		free_net_device(net_device);
+		kfree(net_device);
 	}
 
 	return ret;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 15/40] Staging: hv: netvsc: Cleanup alloc_net_device()
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Cleanup alloc_net_device(); we can directly set the refcnt.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index c3c934c..56749ca 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -41,7 +41,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 		return NULL;
 
 	/* Set to 2 to allow both inbound and outbound traffic */
-	atomic_cmpxchg(&net_device->refcnt, 0, 2);
+	atomic_set(&net_device->refcnt, 2);
 	net_device->drain_notify = false;
 	init_waitqueue_head(&net_device->waiting_to_drain);
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 15/40] Staging: hv: netvsc: Cleanup alloc_net_device()
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Cleanup alloc_net_device(); we can directly set the refcnt.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index c3c934c..56749ca 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -41,7 +41,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 		return NULL;
 
 	/* Set to 2 to allow both inbound and outbound traffic */
-	atomic_cmpxchg(&net_device->refcnt, 0, 2);
+	atomic_set(&net_device->refcnt, 2);
 	net_device->drain_notify = false;
 	init_waitqueue_head(&net_device->waiting_to_drain);
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 16/40] Staging: hv: netvsc: Introduce state to manage the lifecycle of net device
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

In preparation for cleaning up reference counts, introduce state to manage
the lifecycle of net device.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_net.h |    1 +
 drivers/staging/hv/netvsc.c     |    2 ++
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h
index b5bee9e..c6836be 100644
--- a/drivers/staging/hv/hyperv_net.h
+++ b/drivers/staging/hv/hyperv_net.h
@@ -371,6 +371,7 @@ struct netvsc_device {
 
 	atomic_t refcnt;
 	atomic_t num_outstanding_sends;
+	bool destroy;
 	bool drain_notify;
 	wait_queue_head_t waiting_to_drain;
 	/*
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 56749ca..f03018c 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -43,6 +43,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 	/* Set to 2 to allow both inbound and outbound traffic */
 	atomic_set(&net_device->refcnt, 2);
 	net_device->drain_notify = false;
+	net_device->destroy = false;
 	init_waitqueue_head(&net_device->waiting_to_drain);
 
 	net_device->dev = device;
@@ -409,6 +410,7 @@ int netvsc_device_remove(struct hv_device *device)
 		netdev_err(ndev, "No net device present!!\n");
 		return -ENODEV;
 	}
+	net_device->destroy = true;
 
 	/* Wait for all send completions */
 	while (atomic_read(&net_device->num_outstanding_sends)) {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 16/40] Staging: hv: netvsc: Introduce state to manage the lifecycle of net device
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

In preparation for cleaning up reference counts, introduce state to manage
the lifecycle of net device.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_net.h |    1 +
 drivers/staging/hv/netvsc.c     |    2 ++
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h
index b5bee9e..c6836be 100644
--- a/drivers/staging/hv/hyperv_net.h
+++ b/drivers/staging/hv/hyperv_net.h
@@ -371,6 +371,7 @@ struct netvsc_device {
 
 	atomic_t refcnt;
 	atomic_t num_outstanding_sends;
+	bool destroy;
 	bool drain_notify;
 	wait_queue_head_t waiting_to_drain;
 	/*
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 56749ca..f03018c 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -43,6 +43,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 	/* Set to 2 to allow both inbound and outbound traffic */
 	atomic_set(&net_device->refcnt, 2);
 	net_device->drain_notify = false;
+	net_device->destroy = false;
 	init_waitqueue_head(&net_device->waiting_to_drain);
 
 	net_device->dev = device;
@@ -409,6 +410,7 @@ int netvsc_device_remove(struct hv_device *device)
 		netdev_err(ndev, "No net device present!!\n");
 		return -ENODEV;
 	}
+	net_device->destroy = true;
 
 	/* Wait for all send completions */
 	while (atomic_read(&net_device->num_outstanding_sends)) {
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 17/40] Staging: hv: netvsc:  Use the newly introduced lock in accessing ext field
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

The current reference counting mechanism is broken; use the newly introduced
lock to access the net_device pointer in struct hv_device.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |   24 ++++++++++++++++++++++--
 1 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index f03018c..531de63 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -56,12 +56,15 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
 	if (net_device && atomic_read(&net_device->refcnt) > 1)
 		atomic_inc(&net_device->refcnt);
 	else
 		net_device = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 
 	return net_device;
 }
@@ -70,38 +73,50 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
 	if (net_device && atomic_read(&net_device->refcnt))
 		atomic_inc(&net_device->refcnt);
 	else
 		net_device = NULL;
 
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 	return net_device;
 }
 
 static void put_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device->ext_lock, flags);
 
 	net_device = device->ext;
 
 	atomic_dec(&net_device->refcnt);
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 }
 
 static struct netvsc_device *release_outbound_net_device(
 		struct hv_device *device)
 {
 	struct netvsc_device *net_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device == NULL)
+	if (net_device == NULL) {
+		spin_unlock_irqrestore(&device->ext_lock, flags);
 		return NULL;
+	}
 
 	/* Busy wait until the ref drop to 2, then set it to 1 */
 	while (atomic_cmpxchg(&net_device->refcnt, 2, 1) != 2)
 		udelay(100);
 
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 	return net_device;
 }
 
@@ -109,16 +124,21 @@ static struct netvsc_device *release_inbound_net_device(
 		struct hv_device *device)
 {
 	struct netvsc_device *net_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device == NULL)
+	if (net_device == NULL) {
+		spin_unlock_irqrestore(&device->ext_lock, flags);
 		return NULL;
+	}
 
 	/* Busy wait until the ref drop to 1, then set it to 0 */
 	while (atomic_cmpxchg(&net_device->refcnt, 1, 0) != 1)
 		udelay(100);
 
 	device->ext = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 	return net_device;
 }
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 17/40] Staging: hv: netvsc: Use the newly introduced lock in accessing ext field
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

The current reference counting mechanism is broken; use the newly introduced
lock to access the net_device pointer in struct hv_device.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |   24 ++++++++++++++++++++++--
 1 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index f03018c..531de63 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -56,12 +56,15 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
 	if (net_device && atomic_read(&net_device->refcnt) > 1)
 		atomic_inc(&net_device->refcnt);
 	else
 		net_device = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 
 	return net_device;
 }
@@ -70,38 +73,50 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
 	if (net_device && atomic_read(&net_device->refcnt))
 		atomic_inc(&net_device->refcnt);
 	else
 		net_device = NULL;
 
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 	return net_device;
 }
 
 static void put_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device->ext_lock, flags);
 
 	net_device = device->ext;
 
 	atomic_dec(&net_device->refcnt);
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 }
 
 static struct netvsc_device *release_outbound_net_device(
 		struct hv_device *device)
 {
 	struct netvsc_device *net_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device == NULL)
+	if (net_device == NULL) {
+		spin_unlock_irqrestore(&device->ext_lock, flags);
 		return NULL;
+	}
 
 	/* Busy wait until the ref drop to 2, then set it to 1 */
 	while (atomic_cmpxchg(&net_device->refcnt, 2, 1) != 2)
 		udelay(100);
 
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 	return net_device;
 }
 
@@ -109,16 +124,21 @@ static struct netvsc_device *release_inbound_net_device(
 		struct hv_device *device)
 {
 	struct netvsc_device *net_device;
+	unsigned long flags;
 
+	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device == NULL)
+	if (net_device == NULL) {
+		spin_unlock_irqrestore(&device->ext_lock, flags);
 		return NULL;
+	}
 
 	/* Busy wait until the ref drop to 1, then set it to 0 */
 	while (atomic_cmpxchg(&net_device->refcnt, 1, 0) != 1)
 		udelay(100);
 
 	device->ext = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 	return net_device;
 }
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 18/40] Staging: hv: netvsc: Prevent outgoing traffic when netvsc dev is destroyed
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Prevent outgoing traffic when netvsc dev is destroyed.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 531de63..3ac0e17 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -60,7 +60,8 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device && atomic_read(&net_device->refcnt) > 1)
+	if (net_device && (atomic_read(&net_device->refcnt) > 1) &&
+		!net_device->destroy)
 		atomic_inc(&net_device->refcnt);
 	else
 		net_device = NULL;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 18/40] Staging: hv: netvsc: Prevent outgoing traffic when netvsc dev is destroyed
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Prevent outgoing traffic when netvsc dev is destroyed.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 531de63..3ac0e17 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -60,7 +60,8 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device && atomic_read(&net_device->refcnt) > 1)
+	if (net_device && (atomic_read(&net_device->refcnt) > 1) &&
+		!net_device->destroy)
 		atomic_inc(&net_device->refcnt);
 	else
 		net_device = NULL;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 19/40] Staging: hv: netvsc: Get rid of release_outbound_net_device() by inlining the code
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Get rid of release_outbound_net_device() by inlining the code.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |   35 +++++++----------------------------
 1 files changed, 7 insertions(+), 28 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 3ac0e17..7761370 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -100,27 +100,6 @@ static void put_net_device(struct hv_device *device)
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 }
 
-static struct netvsc_device *release_outbound_net_device(
-		struct hv_device *device)
-{
-	struct netvsc_device *net_device;
-	unsigned long flags;
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	net_device = device->ext;
-	if (net_device == NULL) {
-		spin_unlock_irqrestore(&device->ext_lock, flags);
-		return NULL;
-	}
-
-	/* Busy wait until the ref drop to 2, then set it to 1 */
-	while (atomic_cmpxchg(&net_device->refcnt, 2, 1) != 2)
-		udelay(100);
-
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-	return net_device;
-}
-
 static struct netvsc_device *release_inbound_net_device(
 		struct hv_device *device)
 {
@@ -423,14 +402,15 @@ int netvsc_device_remove(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
 	struct hv_netvsc_packet *netvsc_packet, *pos;
-	struct net_device *ndev = dev_get_drvdata(&device->device);
 
 	/* Stop outbound traffic ie sends and receives completions */
-	net_device = release_outbound_net_device(device);
-	if (!net_device) {
-		netdev_err(ndev, "No net device present!!\n");
-		return -ENODEV;
-	}
+
+	/*
+	 * Since we currently hold a reference on the net_device,
+	 * it is safe to dereference the ext pointer.
+	 */
+	net_device = (struct netvsc_device *)device->ext;
+	atomic_dec(&net_device->refcnt);
 	net_device->destroy = true;
 
 	/* Wait for all send completions */
@@ -1006,7 +986,6 @@ cleanup:
 			kfree(packet);
 		}
 
-		release_outbound_net_device(device);
 		release_inbound_net_device(device);
 
 		kfree(net_device);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 19/40] Staging: hv: netvsc: Get rid of release_outbound_net_device() by inlining the code
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Get rid of release_outbound_net_device() by inlining the code.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |   35 +++++++----------------------------
 1 files changed, 7 insertions(+), 28 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 3ac0e17..7761370 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -100,27 +100,6 @@ static void put_net_device(struct hv_device *device)
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 }
 
-static struct netvsc_device *release_outbound_net_device(
-		struct hv_device *device)
-{
-	struct netvsc_device *net_device;
-	unsigned long flags;
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	net_device = device->ext;
-	if (net_device == NULL) {
-		spin_unlock_irqrestore(&device->ext_lock, flags);
-		return NULL;
-	}
-
-	/* Busy wait until the ref drop to 2, then set it to 1 */
-	while (atomic_cmpxchg(&net_device->refcnt, 2, 1) != 2)
-		udelay(100);
-
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-	return net_device;
-}
-
 static struct netvsc_device *release_inbound_net_device(
 		struct hv_device *device)
 {
@@ -423,14 +402,15 @@ int netvsc_device_remove(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
 	struct hv_netvsc_packet *netvsc_packet, *pos;
-	struct net_device *ndev = dev_get_drvdata(&device->device);
 
 	/* Stop outbound traffic ie sends and receives completions */
-	net_device = release_outbound_net_device(device);
-	if (!net_device) {
-		netdev_err(ndev, "No net device present!!\n");
-		return -ENODEV;
-	}
+
+	/*
+	 * Since we currently hold a reference on the net_device,
+	 * it is safe to dereference the ext pointer.
+	 */
+	net_device = (struct netvsc_device *)device->ext;
+	atomic_dec(&net_device->refcnt);
 	net_device->destroy = true;
 
 	/* Wait for all send completions */
@@ -1006,7 +986,6 @@ cleanup:
 			kfree(packet);
 		}
 
-		release_outbound_net_device(device);
 		release_inbound_net_device(device);
 
 		kfree(net_device);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 20/40] Staging: hv: netvsc: Get rid of release_inbound_net_device() by inlining the code
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
                     ` (17 preceding siblings ...)
  2011-06-29 14:39     ` K. Y. Srinivasan
@ 2011-06-29 14:39   ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                     ` (20 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Get rid of release_inbound_net_device() by inlining the code.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |   44 +++++++++---------------------------------
 1 files changed, 10 insertions(+), 34 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 7761370..f930b9e 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -100,28 +100,6 @@ static void put_net_device(struct hv_device *device)
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 }
 
-static struct netvsc_device *release_inbound_net_device(
-		struct hv_device *device)
-{
-	struct netvsc_device *net_device;
-	unsigned long flags;
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	net_device = device->ext;
-	if (net_device == NULL) {
-		spin_unlock_irqrestore(&device->ext_lock, flags);
-		return NULL;
-	}
-
-	/* Busy wait until the ref drop to 1, then set it to 0 */
-	while (atomic_cmpxchg(&net_device->refcnt, 1, 0) != 1)
-		udelay(100);
-
-	device->ext = NULL;
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-	return net_device;
-}
-
 static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
 {
 	struct nvsp_message *revoke_packet;
@@ -402,6 +380,7 @@ int netvsc_device_remove(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
 	struct hv_netvsc_packet *netvsc_packet, *pos;
+	unsigned long flags;
 
 	/* Stop outbound traffic ie sends and receives completions */
 
@@ -413,18 +392,17 @@ int netvsc_device_remove(struct hv_device *device)
 	atomic_dec(&net_device->refcnt);
 	net_device->destroy = true;
 
-	/* Wait for all send completions */
-	while (atomic_read(&net_device->num_outstanding_sends)) {
-		dev_info(&device->device,
-			"waiting for %d requests to complete...\n",
-			atomic_read(&net_device->num_outstanding_sends));
-		udelay(100);
-	}
-
+	/*
+	 * At this point, all outbound traffic is disabled. Wait
+	 * for outstanding sends to drain out.
+	 */
+	netvsc_wait_to_drain(net_device);
 	netvsc_disconnect_vsp(net_device);
 
-	/* Stop inbound traffic ie receives and sends completions */
-	net_device = release_inbound_net_device(device);
+	spin_lock_irqsave(&device->ext_lock, flags);
+	atomic_set(&net_device->refcnt, 0);
+	device->ext = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
 
 	/* At this point, no one should be accessing netDevice except in here */
 	dev_notice(&device->device, "net device safe to remove\n");
@@ -986,8 +964,6 @@ cleanup:
 			kfree(packet);
 		}
 
-		release_inbound_net_device(device);
-
 		kfree(net_device);
 	}
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 21/40] Staging: hv: netvsc: Leverage the spinlock to manage ref_cnt
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

We are using the lock to access the net_device; use this lock to manage the
ref_cnt as well.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_net.h |    2 +-
 drivers/staging/hv/netvsc.c     |   16 ++++++++--------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h
index c6836be..058ca79 100644
--- a/drivers/staging/hv/hyperv_net.h
+++ b/drivers/staging/hv/hyperv_net.h
@@ -369,7 +369,7 @@ struct nvsp_message {
 struct netvsc_device {
 	struct hv_device *dev;
 
-	atomic_t refcnt;
+	int refcnt;
 	atomic_t num_outstanding_sends;
 	bool destroy;
 	bool drain_notify;
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index f930b9e..9ee264c 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -41,7 +41,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 		return NULL;
 
 	/* Set to 2 to allow both inbound and outbound traffic */
-	atomic_set(&net_device->refcnt, 2);
+	net_device->refcnt = 2;
 	net_device->drain_notify = false;
 	net_device->destroy = false;
 	init_waitqueue_head(&net_device->waiting_to_drain);
@@ -60,9 +60,9 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device && (atomic_read(&net_device->refcnt) > 1) &&
+	if (net_device && (net_device->refcnt > 1) &&
 		!net_device->destroy)
-		atomic_inc(&net_device->refcnt);
+		net_device->refcnt++;
 	else
 		net_device = NULL;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
@@ -78,8 +78,8 @@ static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device && atomic_read(&net_device->refcnt))
-		atomic_inc(&net_device->refcnt);
+	if (net_device && net_device->refcnt)
+		net_device->refcnt++;
 	else
 		net_device = NULL;
 
@@ -96,7 +96,7 @@ static void put_net_device(struct hv_device *device)
 
 	net_device = device->ext;
 
-	atomic_dec(&net_device->refcnt);
+	net_device->refcnt--;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 }
 
@@ -389,7 +389,7 @@ int netvsc_device_remove(struct hv_device *device)
 	 * it is safe to dereference the ext pointer.
 	 */
 	net_device = (struct netvsc_device *)device->ext;
-	atomic_dec(&net_device->refcnt);
+	net_device->refcnt--;
 	net_device->destroy = true;
 
 	/*
@@ -400,7 +400,7 @@ int netvsc_device_remove(struct hv_device *device)
 	netvsc_disconnect_vsp(net_device);
 
 	spin_lock_irqsave(&device->ext_lock, flags);
-	atomic_set(&net_device->refcnt, 0);
+	net_device->refcnt = 0;
 	device->ext = NULL;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 21/40] Staging: hv: netvsc: Leverage the spinlock to manage ref_cnt
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

We are using the lock to access the net_device; use this lock to manage the
ref_cnt as well.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_net.h |    2 +-
 drivers/staging/hv/netvsc.c     |   16 ++++++++--------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h
index c6836be..058ca79 100644
--- a/drivers/staging/hv/hyperv_net.h
+++ b/drivers/staging/hv/hyperv_net.h
@@ -369,7 +369,7 @@ struct nvsp_message {
 struct netvsc_device {
 	struct hv_device *dev;
 
-	atomic_t refcnt;
+	int refcnt;
 	atomic_t num_outstanding_sends;
 	bool destroy;
 	bool drain_notify;
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index f930b9e..9ee264c 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -41,7 +41,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 		return NULL;
 
 	/* Set to 2 to allow both inbound and outbound traffic */
-	atomic_set(&net_device->refcnt, 2);
+	net_device->refcnt = 2;
 	net_device->drain_notify = false;
 	net_device->destroy = false;
 	init_waitqueue_head(&net_device->waiting_to_drain);
@@ -60,9 +60,9 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device && (atomic_read(&net_device->refcnt) > 1) &&
+	if (net_device && (net_device->refcnt > 1) &&
 		!net_device->destroy)
-		atomic_inc(&net_device->refcnt);
+		net_device->refcnt++;
 	else
 		net_device = NULL;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
@@ -78,8 +78,8 @@ static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device && atomic_read(&net_device->refcnt))
-		atomic_inc(&net_device->refcnt);
+	if (net_device && net_device->refcnt)
+		net_device->refcnt++;
 	else
 		net_device = NULL;
 
@@ -96,7 +96,7 @@ static void put_net_device(struct hv_device *device)
 
 	net_device = device->ext;
 
-	atomic_dec(&net_device->refcnt);
+	net_device->refcnt--;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 }
 
@@ -389,7 +389,7 @@ int netvsc_device_remove(struct hv_device *device)
 	 * it is safe to dereference the ext pointer.
 	 */
 	net_device = (struct netvsc_device *)device->ext;
-	atomic_dec(&net_device->refcnt);
+	net_device->refcnt--;
 	net_device->destroy = true;
 
 	/*
@@ -400,7 +400,7 @@ int netvsc_device_remove(struct hv_device *device)
 	netvsc_disconnect_vsp(net_device);
 
 	spin_lock_irqsave(&device->ext_lock, flags);
-	atomic_set(&net_device->refcnt, 0);
+	net_device->refcnt = 0;
 	device->ext = NULL;
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 22/40] Staging: hv: netvsc: Further cleanup reference counting of netvsc_device
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen


Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |   25 ++++++++++++++++---------
 1 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 9ee264c..caca82e 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -40,8 +40,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 	if (!net_device)
 		return NULL;
 
-	/* Set to 2 to allow both inbound and outbound traffic */
-	net_device->refcnt = 2;
+	net_device->refcnt = 1;
 	net_device->drain_notify = false;
 	net_device->destroy = false;
 	init_waitqueue_head(&net_device->waiting_to_drain);
@@ -52,7 +51,6 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 	return net_device;
 }
 
-/* Get the net device object iff exists and its refcount > 1 */
 static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
@@ -60,7 +58,7 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device && (net_device->refcnt > 1) &&
+	if (net_device && (net_device->refcnt) &&
 		!net_device->destroy)
 		net_device->refcnt++;
 	else
@@ -70,7 +68,6 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 	return net_device;
 }
 
-/* Get the net device object iff exists and its refcount > 0 */
 static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
@@ -78,11 +75,21 @@ static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device && net_device->refcnt)
-		net_device->refcnt++;
-	else
-		net_device = NULL;
 
+	if (!net_device)
+		goto cleanup;
+
+	/*
+	 * If the device is being destroyed; allow incoming
+	 * traffic only to cleanup outstanding requests.
+	 */
+	if (net_device->destroy &&
+		(atomic_read(&net_device->num_outstanding_sends) == 0))
+		goto cleanup;
+
+	net_device->refcnt++;
+
+cleanup:
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 	return net_device;
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 22/40] Staging: hv: netvsc: Further cleanup reference counting of netvsc_device
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane


Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/netvsc.c |   25 ++++++++++++++++---------
 1 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 9ee264c..caca82e 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -40,8 +40,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 	if (!net_device)
 		return NULL;
 
-	/* Set to 2 to allow both inbound and outbound traffic */
-	net_device->refcnt = 2;
+	net_device->refcnt = 1;
 	net_device->drain_notify = false;
 	net_device->destroy = false;
 	init_waitqueue_head(&net_device->waiting_to_drain);
@@ -52,7 +51,6 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 	return net_device;
 }
 
-/* Get the net device object iff exists and its refcount > 1 */
 static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
@@ -60,7 +58,7 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device && (net_device->refcnt > 1) &&
+	if (net_device && (net_device->refcnt) &&
 		!net_device->destroy)
 		net_device->refcnt++;
 	else
@@ -70,7 +68,6 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 	return net_device;
 }
 
-/* Get the net device object iff exists and its refcount > 0 */
 static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
@@ -78,11 +75,21 @@ static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
 
 	spin_lock_irqsave(&device->ext_lock, flags);
 	net_device = device->ext;
-	if (net_device && net_device->refcnt)
-		net_device->refcnt++;
-	else
-		net_device = NULL;
 
+	if (!net_device)
+		goto cleanup;
+
+	/*
+	 * If the device is being destroyed; allow incoming
+	 * traffic only to cleanup outstanding requests.
+	 */
+	if (net_device->destroy &&
+		(atomic_read(&net_device->num_outstanding_sends) == 0))
+		goto cleanup;
+
+	net_device->refcnt++;
+
+cleanup:
 	spin_unlock_irqrestore(&device->ext_lock, flags);
 	return net_device;
 }
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 23/40] Staging: hv: storvsc: Introduce code to manage IDE devices using storvsc HBA
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Introduce code to manage the (potentially four) IDE devices suning the storvsc
driver. To do so, we assign distinct channels to each of these devices
as well as add code to probe an IDE device.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |   13 +++++++++
 drivers/staging/hv/storvsc_drv.c    |   50 +++++++++++++++++++++++++++++++++-
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index a1f3e27..a15a53b 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -25,6 +25,19 @@
 #ifndef _HYPERV_STORAGE_H
 #define _HYPERV_STORAGE_H
 
+/*
+ * We want to manage the IDE devices using standard Linux SCSI drivers
+ * using the storvsc driver.
+ * Define special channels to support this.
+ */
+
+#define HV_MAX_IDE_DEVICES	4
+#define HV_IDE_BASE_CHANNEL	10
+#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
+#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
+#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
+#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)
+
 
 /* vstorage.w revision number.  This is used in the case of a version match, */
 /* to alert the user that structure sizes may be mismatched even though the */
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 8d5be51..cf659d7 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -61,6 +61,54 @@ struct storvsc_cmd_request {
 	struct hv_storvsc_request request;
 };
 
+static struct  Scsi_Host *storvsc_host;
+
+/*
+ * State to manage IDE devices that register with the storvsc driver.
+ *
+ */
+static struct hv_device *ide_devices[HV_MAX_IDE_DEVICES];
+
+static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
+{
+	*target =
+	dev->dev_instance.data[5] << 8 | dev->dev_instance.data[4];
+
+	*path =
+	dev->dev_instance.data[3] << 24 | dev->dev_instance.data[2] << 16 |
+	dev->dev_instance.data[1] << 8  | dev->dev_instance.data[0];
+}
+
+int storvsc_ide_probe(struct hv_device *dev)
+{
+	struct storvsc_device_info dev_info;
+	int target, path, channel;
+	int ret;
+
+	dev_info.ring_buffer_size = BLKVSC_RING_BUFFER_SIZE;
+	ret = storvsc_dev_add(dev, &dev_info);
+
+	if (ret)
+		return ret;
+
+	storvsc_get_ide_info(dev, &target, &path);
+
+	if (path)
+		/* IDE controller 1. */
+		if (target)
+			channel = HV_IDE1_DEV2;
+		else
+			channel = HV_IDE1_DEV1;
+	else
+		/* IDE controller 0 */
+		if (target)
+			channel = HV_IDE0_DEV2;
+		else
+			channel = HV_IDE0_DEV1;
+
+	ide_devices[channel - HV_IDE_BASE_CHANNEL] = dev;
+	return scsi_add_device(storvsc_host, channel, target, 0);
+}
 
 static int storvsc_device_alloc(struct scsi_device *sdevice)
 {
@@ -469,7 +517,6 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 	unsigned int sg_count = 0;
 	struct vmscsi_request *vm_srb;
 
-
 	/* If retrying, no need to prep the cmd */
 	if (scmnd->host_scribble) {
 
@@ -707,7 +754,6 @@ static int storvsc_probe(struct hv_device *device)
 		scsi_host_put(host);
 		return -ENODEV;
 	}
-
 	scsi_scan_host(host);
 	return ret;
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 23/40] Staging: hv: storvsc: Introduce code to manage IDE devices using storvsc HBA
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Introduce code to manage the (potentially four) IDE devices suning the storvsc
driver. To do so, we assign distinct channels to each of these devices
as well as add code to probe an IDE device.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |   13 +++++++++
 drivers/staging/hv/storvsc_drv.c    |   50 +++++++++++++++++++++++++++++++++-
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index a1f3e27..a15a53b 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -25,6 +25,19 @@
 #ifndef _HYPERV_STORAGE_H
 #define _HYPERV_STORAGE_H
 
+/*
+ * We want to manage the IDE devices using standard Linux SCSI drivers
+ * using the storvsc driver.
+ * Define special channels to support this.
+ */
+
+#define HV_MAX_IDE_DEVICES	4
+#define HV_IDE_BASE_CHANNEL	10
+#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
+#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
+#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
+#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)
+
 
 /* vstorage.w revision number.  This is used in the case of a version match, */
 /* to alert the user that structure sizes may be mismatched even though the */
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 8d5be51..cf659d7 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -61,6 +61,54 @@ struct storvsc_cmd_request {
 	struct hv_storvsc_request request;
 };
 
+static struct  Scsi_Host *storvsc_host;
+
+/*
+ * State to manage IDE devices that register with the storvsc driver.
+ *
+ */
+static struct hv_device *ide_devices[HV_MAX_IDE_DEVICES];
+
+static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
+{
+	*target =
+	dev->dev_instance.data[5] << 8 | dev->dev_instance.data[4];
+
+	*path =
+	dev->dev_instance.data[3] << 24 | dev->dev_instance.data[2] << 16 |
+	dev->dev_instance.data[1] << 8  | dev->dev_instance.data[0];
+}
+
+int storvsc_ide_probe(struct hv_device *dev)
+{
+	struct storvsc_device_info dev_info;
+	int target, path, channel;
+	int ret;
+
+	dev_info.ring_buffer_size = BLKVSC_RING_BUFFER_SIZE;
+	ret = storvsc_dev_add(dev, &dev_info);
+
+	if (ret)
+		return ret;
+
+	storvsc_get_ide_info(dev, &target, &path);
+
+	if (path)
+		/* IDE controller 1. */
+		if (target)
+			channel = HV_IDE1_DEV2;
+		else
+			channel = HV_IDE1_DEV1;
+	else
+		/* IDE controller 0 */
+		if (target)
+			channel = HV_IDE0_DEV2;
+		else
+			channel = HV_IDE0_DEV1;
+
+	ide_devices[channel - HV_IDE_BASE_CHANNEL] = dev;
+	return scsi_add_device(storvsc_host, channel, target, 0);
+}
 
 static int storvsc_device_alloc(struct scsi_device *sdevice)
 {
@@ -469,7 +517,6 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 	unsigned int sg_count = 0;
 	struct vmscsi_request *vm_srb;
 
-
 	/* If retrying, no need to prep the cmd */
 	if (scmnd->host_scribble) {
 
@@ -707,7 +754,6 @@ static int storvsc_probe(struct hv_device *device)
 		scsi_host_put(host);
 		return -ENODEV;
 	}
-
 	scsi_scan_host(host);
 	return ret;
 }
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

We use the channel number to distinguish an IDE device managed by the
storvsc driver from scsi devices. Add code to get the correct
device pointer based on the channel number.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index cf659d7..fcc3f5d 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -517,6 +517,16 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 	unsigned int sg_count = 0;
 	struct vmscsi_request *vm_srb;
 
+	if (scmnd->device->channel >= HV_IDE_BASE_CHANNEL) {
+		int channel = scmnd->device->channel;
+
+		/*
+		 * This is an IDE device; get the right dev.
+		 */
+
+		dev = ide_devices[channel - HV_IDE_BASE_CHANNEL];
+	}
+
 	/* If retrying, no need to prep the cmd */
 	if (scmnd->host_scribble) {
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

We use the channel number to distinguish an IDE device managed by the
storvsc driver from scsi devices. Add code to get the correct
device pointer based on the channel number.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index cf659d7..fcc3f5d 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -517,6 +517,16 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 	unsigned int sg_count = 0;
 	struct vmscsi_request *vm_srb;
 
+	if (scmnd->device->channel >= HV_IDE_BASE_CHANNEL) {
+		int channel = scmnd->device->channel;
+
+		/*
+		 * This is an IDE device; get the right dev.
+		 */
+
+		dev = ide_devices[channel - HV_IDE_BASE_CHANNEL];
+	}
+
 	/* If retrying, no need to prep the cmd */
 	if (scmnd->host_scribble) {
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 25/40] Staging: hv: storvsc: Add state to manage the lifecycle of emulated HBA
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

We setup a single emulated HBA for managing all IDE devices. To properly
deal with unloading of the driver, establish state to track who
should cleanup the emulated HBA.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    1 +
 drivers/staging/hv/storvsc.c        |    1 +
 drivers/staging/hv/storvsc_drv.c    |    9 ++++++++-
 3 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index a15a53b..865ede1 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -281,6 +281,7 @@ struct storvsc_device {
 	int	 ref_count;
 	bool	 destroy;
 	bool	 drain_notify;
+	bool	 hba_owner;
 	atomic_t num_outstanding_req;
 
 	wait_queue_head_t waiting_to_drain;
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 4d13044..c06f750 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -42,6 +42,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 
 	stor_device->ref_count = 1;
 	stor_device->destroy = false;
+	stor_device->hba_owner = false;
 	init_waitqueue_head(&stor_device->waiting_to_drain);
 	stor_device->device = device;
 	device->ext = stor_device;
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index fcc3f5d..898a311 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -349,6 +349,10 @@ static int storvsc_remove(struct hv_device *dev)
 	struct Scsi_Host *host = dev_get_drvdata(&dev->device);
 	struct hv_host_device *host_dev =
 			(struct hv_host_device *)host->hostdata;
+	struct storvsc_device *stor_dev = dev->ext;
+
+	if (!stor_dev->hba_owner)
+		return 0;
 
 	scsi_remove_host(host);
 
@@ -743,7 +747,10 @@ static int storvsc_probe(struct hv_device *device)
 		scsi_host_put(host);
 		return -ENODEV;
 	}
-
+	/*
+	 * This stor device owns the HBA; capture that state.
+	 */
+	((struct storvsc_device *)device->ext)->hba_owner = true;
 	host_dev->path = device_info.path_id;
 	host_dev->target = device_info.target_id;
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 25/40] Staging: hv: storvsc: Add state to manage the lifecycle of emulated HBA
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

We setup a single emulated HBA for managing all IDE devices. To properly
deal with unloading of the driver, establish state to track who
should cleanup the emulated HBA.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |    1 +
 drivers/staging/hv/storvsc.c        |    1 +
 drivers/staging/hv/storvsc_drv.c    |    9 ++++++++-
 3 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
index a15a53b..865ede1 100644
--- a/drivers/staging/hv/hyperv_storage.h
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -281,6 +281,7 @@ struct storvsc_device {
 	int	 ref_count;
 	bool	 destroy;
 	bool	 drain_notify;
+	bool	 hba_owner;
 	atomic_t num_outstanding_req;
 
 	wait_queue_head_t waiting_to_drain;
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 4d13044..c06f750 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -42,6 +42,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 
 	stor_device->ref_count = 1;
 	stor_device->destroy = false;
+	stor_device->hba_owner = false;
 	init_waitqueue_head(&stor_device->waiting_to_drain);
 	stor_device->device = device;
 	device->ext = stor_device;
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index fcc3f5d..898a311 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -349,6 +349,10 @@ static int storvsc_remove(struct hv_device *dev)
 	struct Scsi_Host *host = dev_get_drvdata(&dev->device);
 	struct hv_host_device *host_dev =
 			(struct hv_host_device *)host->hostdata;
+	struct storvsc_device *stor_dev = dev->ext;
+
+	if (!stor_dev->hba_owner)
+		return 0;
 
 	scsi_remove_host(host);
 
@@ -743,7 +747,10 @@ static int storvsc_probe(struct hv_device *device)
 		scsi_host_put(host);
 		return -ENODEV;
 	}
-
+	/*
+	 * This stor device owns the HBA; capture that state.
+	 */
+	((struct storvsc_device *)device->ext)->hba_owner = true;
 	host_dev->path = device_info.path_id;
 	host_dev->target = device_info.target_id;
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 26/40] Staging: hv: storvsc: Handle probing IDE devices
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Add code is storvsc_probe() to handle IDE devices. We currently boot
off of the first IDE disk. The emulated HBA assigned to manage the IDE
disks will be owned by this (boot) device. Subsequent IDE devices that
may be discovered will be managed by this HBA.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   23 ++++++++++++++++++++---
 1 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 898a311..c0d6e16 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -79,7 +79,7 @@ static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
 	dev->dev_instance.data[1] << 8  | dev->dev_instance.data[0];
 }
 
-int storvsc_ide_probe(struct hv_device *dev)
+static int storvsc_ide_probe(struct hv_device *dev)
 {
 	struct storvsc_device_info dev_info;
 	int target, path, channel;
@@ -713,6 +713,15 @@ static int storvsc_probe(struct hv_device *device)
 	struct Scsi_Host *host;
 	struct hv_host_device *host_dev;
 	struct storvsc_device_info device_info;
+	bool dev_is_ide;
+	int path, target;
+
+	if (!strcmp(device->device_type, "hv_block")) {
+		dev_is_ide = true;
+		if (storvsc_host)
+			return storvsc_ide_probe(device);
+	} else
+		dev_is_ide = false;
 
 	host = scsi_host_alloc(&scsi_driver,
 			       sizeof(struct hv_host_device));
@@ -751,8 +760,15 @@ static int storvsc_probe(struct hv_device *device)
 	 * This stor device owns the HBA; capture that state.
 	 */
 	((struct storvsc_device *)device->ext)->hba_owner = true;
-	host_dev->path = device_info.path_id;
-	host_dev->target = device_info.target_id;
+
+	if (dev_is_ide) {
+		storvsc_get_ide_info(device, &target, &path);
+		host_dev->path = path;
+		host_dev->target = target;
+	} else {
+		host_dev->path = device_info.path_id;
+		host_dev->target = device_info.target_id;
+	}
 
 	/* max # of devices per target */
 	host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;
@@ -772,6 +788,7 @@ static int storvsc_probe(struct hv_device *device)
 		return -ENODEV;
 	}
 	scsi_scan_host(host);
+	storvsc_host = host;
 	return ret;
 }
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 26/40] Staging: hv: storvsc: Handle probing IDE devices
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Add code is storvsc_probe() to handle IDE devices. We currently boot
off of the first IDE disk. The emulated HBA assigned to manage the IDE
disks will be owned by this (boot) device. Subsequent IDE devices that
may be discovered will be managed by this HBA.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   23 ++++++++++++++++++++---
 1 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 898a311..c0d6e16 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -79,7 +79,7 @@ static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
 	dev->dev_instance.data[1] << 8  | dev->dev_instance.data[0];
 }
 
-int storvsc_ide_probe(struct hv_device *dev)
+static int storvsc_ide_probe(struct hv_device *dev)
 {
 	struct storvsc_device_info dev_info;
 	int target, path, channel;
@@ -713,6 +713,15 @@ static int storvsc_probe(struct hv_device *device)
 	struct Scsi_Host *host;
 	struct hv_host_device *host_dev;
 	struct storvsc_device_info device_info;
+	bool dev_is_ide;
+	int path, target;
+
+	if (!strcmp(device->device_type, "hv_block")) {
+		dev_is_ide = true;
+		if (storvsc_host)
+			return storvsc_ide_probe(device);
+	} else
+		dev_is_ide = false;
 
 	host = scsi_host_alloc(&scsi_driver,
 			       sizeof(struct hv_host_device));
@@ -751,8 +760,15 @@ static int storvsc_probe(struct hv_device *device)
 	 * This stor device owns the HBA; capture that state.
 	 */
 	((struct storvsc_device *)device->ext)->hba_owner = true;
-	host_dev->path = device_info.path_id;
-	host_dev->target = device_info.target_id;
+
+	if (dev_is_ide) {
+		storvsc_get_ide_info(device, &target, &path);
+		host_dev->path = path;
+		host_dev->target = target;
+	} else {
+		host_dev->path = device_info.path_id;
+		host_dev->target = device_info.target_id;
+	}
 
 	/* max # of devices per target */
 	host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;
@@ -772,6 +788,7 @@ static int storvsc_probe(struct hv_device *device)
 		return -ENODEV;
 	}
 	scsi_scan_host(host);
+	storvsc_host = host;
 	return ret;
 }
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 27/40] Staging: hv: storvsc: Handle IDE devices correctly in storvsc_remove()
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Properly deal with cleaning up of resources on storvsc_remove().
Keep in mind that while on the scsi side, we don't get called for each
scsi disk configured for the guest, on the IDE side, we will get called
for each IDE device that was probed. Perform all the cleanup in the 
context of the HBA owner.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index c0d6e16..a6da132 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -350,6 +350,7 @@ static int storvsc_remove(struct hv_device *dev)
 	struct hv_host_device *host_dev =
 			(struct hv_host_device *)host->hostdata;
 	struct storvsc_device *stor_dev = dev->ext;
+	int i;
 
 	if (!stor_dev->hba_owner)
 		return 0;
@@ -359,6 +360,14 @@ static int storvsc_remove(struct hv_device *dev)
 	scsi_host_put(host);
 
 	storvsc_dev_remove(dev);
+
+	for (i = 0; i < 4; i++) {
+		struct hv_device *d = ide_devices[i];
+
+		if (d)
+			storvsc_dev_remove(d);
+	}
+
 	if (host_dev->request_pool) {
 		kmem_cache_destroy(host_dev->request_pool);
 		host_dev->request_pool = NULL;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 27/40] Staging: hv: storvsc: Handle IDE devices correctly in storvsc_remove()
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Properly deal with cleaning up of resources on storvsc_remove().
Keep in mind that while on the scsi side, we don't get called for each
scsi disk configured for the guest, on the IDE side, we will get called
for each IDE device that was probed. Perform all the cleanup in the 
context of the HBA owner.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index c0d6e16..a6da132 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -350,6 +350,7 @@ static int storvsc_remove(struct hv_device *dev)
 	struct hv_host_device *host_dev =
 			(struct hv_host_device *)host->hostdata;
 	struct storvsc_device *stor_dev = dev->ext;
+	int i;
 
 	if (!stor_dev->hba_owner)
 		return 0;
@@ -359,6 +360,14 @@ static int storvsc_remove(struct hv_device *dev)
 	scsi_host_put(host);
 
 	storvsc_dev_remove(dev);
+
+	for (i = 0; i < 4; i++) {
+		struct hv_device *d = ide_devices[i];
+
+		if (d)
+			storvsc_dev_remove(d);
+	}
+
 	if (host_dev->request_pool) {
 		kmem_cache_destroy(host_dev->request_pool);
 		host_dev->request_pool = NULL;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 28/40] Staging: hv: storvsc: Handle IDE devices using the storvsc driver
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Now, make storvsc driver handle all block devices. Make appropriate changes
to not build hv_blkvsc, since it won't be used.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/Kconfig       |    7 -------
 drivers/staging/hv/Makefile      |    2 --
 drivers/staging/hv/storvsc_drv.c |    1 +
 3 files changed, 1 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig
index 5e0c9f6..26b5064 100644
--- a/drivers/staging/hv/Kconfig
+++ b/drivers/staging/hv/Kconfig
@@ -15,13 +15,6 @@ config HYPERV_STORAGE
 	help
 	 Select this option to enable the Hyper-V virtual storage driver.
 
-config HYPERV_BLOCK
-	tristate "Microsoft Hyper-V virtual block driver"
-	depends on BLOCK && SCSI && (LBDAF || 64BIT)
-	default HYPERV
-	help
-	  Select this option to enable the Hyper-V virtual block driver.
-
 config HYPERV_NET
 	tristate "Microsoft Hyper-V virtual network driver"
 	depends on NET
diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
index 3004674..bb89437 100644
--- a/drivers/staging/hv/Makefile
+++ b/drivers/staging/hv/Makefile
@@ -1,6 +1,5 @@
 obj-$(CONFIG_HYPERV)		+= hv_vmbus.o hv_timesource.o
 obj-$(CONFIG_HYPERV_STORAGE)	+= hv_storvsc.o
-obj-$(CONFIG_HYPERV_BLOCK)	+= hv_blkvsc.o
 obj-$(CONFIG_HYPERV_NET)	+= hv_netvsc.o
 obj-$(CONFIG_HYPERV_UTILS)	+= hv_utils.o
 obj-$(CONFIG_HYPERV_MOUSE)	+= hv_mouse.o
@@ -9,6 +8,5 @@ hv_vmbus-y := vmbus_drv.o \
 		 hv.o connection.o channel.o \
 		 channel_mgmt.o ring_buffer.o
 hv_storvsc-y := storvsc_drv.o storvsc.o
-hv_blkvsc-y := blkvsc_drv.o  storvsc.o
 hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o
 hv_utils-y := hv_util.o hv_kvp.o
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index a6da132..fc53bf6 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -709,6 +709,7 @@ static struct scsi_host_template scsi_driver = {
 
 static const struct hv_vmbus_device_id id_table[] = {
 	{ "hv_scsi" },
+	{ "hv_block" },
 	{ "" }
 };
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 28/40] Staging: hv: storvsc: Handle IDE devices using the storvsc driver
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Now, make storvsc driver handle all block devices. Make appropriate changes
to not build hv_blkvsc, since it won't be used.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/Kconfig       |    7 -------
 drivers/staging/hv/Makefile      |    2 --
 drivers/staging/hv/storvsc_drv.c |    1 +
 3 files changed, 1 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig
index 5e0c9f6..26b5064 100644
--- a/drivers/staging/hv/Kconfig
+++ b/drivers/staging/hv/Kconfig
@@ -15,13 +15,6 @@ config HYPERV_STORAGE
 	help
 	 Select this option to enable the Hyper-V virtual storage driver.
 
-config HYPERV_BLOCK
-	tristate "Microsoft Hyper-V virtual block driver"
-	depends on BLOCK && SCSI && (LBDAF || 64BIT)
-	default HYPERV
-	help
-	  Select this option to enable the Hyper-V virtual block driver.
-
 config HYPERV_NET
 	tristate "Microsoft Hyper-V virtual network driver"
 	depends on NET
diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
index 3004674..bb89437 100644
--- a/drivers/staging/hv/Makefile
+++ b/drivers/staging/hv/Makefile
@@ -1,6 +1,5 @@
 obj-$(CONFIG_HYPERV)		+= hv_vmbus.o hv_timesource.o
 obj-$(CONFIG_HYPERV_STORAGE)	+= hv_storvsc.o
-obj-$(CONFIG_HYPERV_BLOCK)	+= hv_blkvsc.o
 obj-$(CONFIG_HYPERV_NET)	+= hv_netvsc.o
 obj-$(CONFIG_HYPERV_UTILS)	+= hv_utils.o
 obj-$(CONFIG_HYPERV_MOUSE)	+= hv_mouse.o
@@ -9,6 +8,5 @@ hv_vmbus-y := vmbus_drv.o \
 		 hv.o connection.o channel.o \
 		 channel_mgmt.o ring_buffer.o
 hv_storvsc-y := storvsc_drv.o storvsc.o
-hv_blkvsc-y := blkvsc_drv.o  storvsc.o
 hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o
 hv_utils-y := hv_util.o hv_kvp.o
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index a6da132..fc53bf6 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -709,6 +709,7 @@ static struct scsi_host_template scsi_driver = {
 
 static const struct hv_vmbus_device_id id_table[] = {
 	{ "hv_scsi" },
+	{ "hv_block" },
 	{ "" }
 };
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 29/40] Staging: hv: storvsc: Optimize bounce buffer handling for the "write" case
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Optimize bounce buffer handling for the "write" case; we need to copy
from bounce buffer only when we are performing a "read" operation.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index fc53bf6..c6838fd 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -478,17 +478,18 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
 	struct scsi_sense_hdr sense_hdr;
 	struct vmscsi_request *vm_srb;
 
+	vm_srb = &request->vstor_packet.vm_srb;
 	if (cmd_request->bounce_sgl_count) {
 
-		/* FIXME: We can optimize on writes by just skipping this */
-		copy_from_bounce_buffer(scsi_sglist(scmnd),
+		if (vm_srb->data_in == READ_TYPE) {
+			copy_from_bounce_buffer(scsi_sglist(scmnd),
 					cmd_request->bounce_sgl,
 					scsi_sg_count(scmnd));
-		destroy_bounce_buffer(cmd_request->bounce_sgl,
-				      cmd_request->bounce_sgl_count);
+			destroy_bounce_buffer(cmd_request->bounce_sgl,
+					cmd_request->bounce_sgl_count);
+		}
 	}
 
-	vm_srb = &request->vstor_packet.vm_srb;
 	scmnd->result = vm_srb->scsi_status;
 
 	if (scmnd->result) {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 29/40] Staging: hv: storvsc: Optimize bounce buffer handling for the "write" case
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Optimize bounce buffer handling for the "write" case; we need to copy
from bounce buffer only when we are performing a "read" operation.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index fc53bf6..c6838fd 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -478,17 +478,18 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
 	struct scsi_sense_hdr sense_hdr;
 	struct vmscsi_request *vm_srb;
 
+	vm_srb = &request->vstor_packet.vm_srb;
 	if (cmd_request->bounce_sgl_count) {
 
-		/* FIXME: We can optimize on writes by just skipping this */
-		copy_from_bounce_buffer(scsi_sglist(scmnd),
+		if (vm_srb->data_in == READ_TYPE) {
+			copy_from_bounce_buffer(scsi_sglist(scmnd),
 					cmd_request->bounce_sgl,
 					scsi_sg_count(scmnd));
-		destroy_bounce_buffer(cmd_request->bounce_sgl,
-				      cmd_request->bounce_sgl_count);
+			destroy_bounce_buffer(cmd_request->bounce_sgl,
+					cmd_request->bounce_sgl_count);
+		}
 	}
 
-	vm_srb = &request->vstor_packet.vm_srb;
 	scmnd->result = vm_srb->scsi_status;
 
 	if (scmnd->result) {
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 30/40] Staging: hv: storvsc: Optimize the bounce buffer handling in the "read" case
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Optimize the bounce buffer handling in the "read" case. Copy to bounce
buffers (if needed) when we initiate an I/O, only if we are
performing a "write" operation.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index c6838fd..23334ad 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -623,12 +623,10 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 				ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >>
 					PAGE_SHIFT;
 
-			/*
-			 * FIXME: We can optimize on reads by just skipping
-			 * this
-			 */
-			copy_to_bounce_buffer(sgl, cmd_request->bounce_sgl,
-					      scsi_sg_count(scmnd));
+			if (vm_srb->data_in == WRITE_TYPE)
+				copy_to_bounce_buffer(sgl,
+					cmd_request->bounce_sgl,
+					scsi_sg_count(scmnd));
 
 			sgl = cmd_request->bounce_sgl;
 			sg_count = cmd_request->bounce_sgl_count;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 30/40] Staging: hv: storvsc: Optimize the bounce buffer handling in the "read" case
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Optimize the bounce buffer handling in the "read" case. Copy to bounce
buffers (if needed) when we initiate an I/O, only if we are
performing a "write" operation.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index c6838fd..23334ad 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -623,12 +623,10 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 				ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >>
 					PAGE_SHIFT;
 
-			/*
-			 * FIXME: We can optimize on reads by just skipping
-			 * this
-			 */
-			copy_to_bounce_buffer(sgl, cmd_request->bounce_sgl,
-					      scsi_sg_count(scmnd));
+			if (vm_srb->data_in == WRITE_TYPE)
+				copy_to_bounce_buffer(sgl,
+					cmd_request->bounce_sgl,
+					scsi_sg_count(scmnd));
 
 			sgl = cmd_request->bounce_sgl;
 			sg_count = cmd_request->bounce_sgl_count;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 31/40] Staging: hv: storvsc: Get rid of blkvsc_drv.c as this code is not used
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Now that we are handling all block devices using the scsi stack, get rid of
blkvsc_drv.c as it is not used any more.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/blkvsc_drv.c | 1024 ---------------------------------------
 1 files changed, 0 insertions(+), 1024 deletions(-)
 delete mode 100644 drivers/staging/hv/blkvsc_drv.c

diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
deleted file mode 100644
index 9898ea3..0000000
--- a/drivers/staging/hv/blkvsc_drv.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *   K. Y. Srinivasan <kys@microsoft.com>
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/blkdev.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/hdreg.h>
-#include <linux/slab.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_dbg.h>
-
-#include "hyperv.h"
-#include "hyperv_storage.h"
-
-
-#define BLKVSC_MINORS	64
-
-enum blkvsc_device_type {
-	UNKNOWN_DEV_TYPE,
-	HARDDISK_TYPE,
-	DVD_TYPE,
-};
-
-enum blkvsc_op_type {
-	DO_INQUIRY,
-	DO_CAPACITY,
-	DO_FLUSH,
-};
-
-/*
- * This request ties the struct request and struct
- * blkvsc_request/hv_storvsc_request together A struct request may be
- * represented by 1 or more struct blkvsc_request
- */
-struct blkvsc_request_group {
-	int outstanding;
-	int status;
-	struct list_head blkvsc_req_list;	/* list of blkvsc_requests */
-};
-
-struct blkvsc_request {
-	/* blkvsc_request_group.blkvsc_req_list */
-	struct list_head req_entry;
-
-	/* block_device_context.pending_list */
-	struct list_head pend_entry;
-
-	/* This may be null if we generate a request internally */
-	struct request *req;
-
-	struct block_device_context *dev;
-
-	/* The group this request is part of. Maybe null */
-	struct blkvsc_request_group *group;
-
-	int write;
-	sector_t sector_start;
-	unsigned long sector_count;
-
-	unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
-	unsigned char cmd_len;
-	unsigned char cmnd[MAX_COMMAND_SIZE];
-
-	struct hv_storvsc_request request;
-};
-
-/* Per device structure */
-struct block_device_context {
-	/* point back to our device context */
-	struct hv_device *device_ctx;
-	struct kmem_cache *request_pool;
-	spinlock_t lock;
-	struct gendisk *gd;
-	enum blkvsc_device_type	device_type;
-	struct list_head pending_list;
-
-	unsigned char device_id[64];
-	unsigned int device_id_len;
-	int num_outstanding_reqs;
-	int shutting_down;
-	unsigned int sector_size;
-	sector_t capacity;
-	unsigned int port;
-	unsigned char path;
-	unsigned char target;
-	int users;
-};
-
-static const char *drv_name = "blkvsc";
-
-
-/*
- * There is a circular dependency involving blkvsc_request_completion()
- * and blkvsc_do_request().
- */
-static void blkvsc_request_completion(struct hv_storvsc_request *request);
-
-static int blkvsc_ringbuffer_size = BLKVSC_RING_BUFFER_SIZE;
-
-module_param(blkvsc_ringbuffer_size, int, S_IRUGO);
-MODULE_PARM_DESC(ring_size, "Ring buffer size (in bytes)");
-
-/*
- * There is a circular dependency involving blkvsc_probe()
- * and block_ops.
- */
-static int blkvsc_probe(struct hv_device *dev);
-
-static int blkvsc_device_add(struct hv_device *device,
-				void *additional_info)
-{
-	struct storvsc_device_info *device_info;
-	int ret = 0;
-
-	device_info = (struct storvsc_device_info *)additional_info;
-
-	device_info->ring_buffer_size = blkvsc_ringbuffer_size;
-
-	ret = storvsc_dev_add(device, additional_info);
-	if (ret != 0)
-		return ret;
-
-	/*
-	 * We need to use the device instance guid to set the path and target
-	 * id. For IDE devices, the device instance id is formatted as
-	 * <bus id> * - <device id> - 8899 - 000000000000.
-	 */
-	device_info->path_id = device->dev_instance.data[3] << 24 |
-			     device->dev_instance.data[2] << 16 |
-			     device->dev_instance.data[1] << 8  |
-			     device->dev_instance.data[0];
-
-	device_info->target_id = device->dev_instance.data[5] << 8 |
-			       device->dev_instance.data[4];
-
-	return ret;
-}
-
-static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
-			void (*request_completion)(struct hv_storvsc_request *))
-{
-	struct block_device_context *blkdev = blkvsc_req->dev;
-	struct hv_storvsc_request *storvsc_req;
-	struct vmscsi_request *vm_srb;
-	int ret;
-
-
-	storvsc_req = &blkvsc_req->request;
-	vm_srb = &storvsc_req->vstor_packet.vm_srb;
-
-	vm_srb->data_in = blkvsc_req->write ? WRITE_TYPE : READ_TYPE;
-
-	storvsc_req->on_io_completion = request_completion;
-	storvsc_req->context = blkvsc_req;
-
-	vm_srb->port_number = blkdev->port;
-	vm_srb->path_id = blkdev->path;
-	vm_srb->target_id = blkdev->target;
-	vm_srb->lun = 0;	 /* this is not really used at all */
-
-	vm_srb->cdb_length = blkvsc_req->cmd_len;
-
-	memcpy(vm_srb->cdb, blkvsc_req->cmnd, vm_srb->cdb_length);
-
-	storvsc_req->sense_buffer = blkvsc_req->sense_buffer;
-
-	ret =  storvsc_do_io(blkdev->device_ctx,
-					   &blkvsc_req->request);
-	if (ret == 0)
-		blkdev->num_outstanding_reqs++;
-
-	return ret;
-}
-
-
-static int blkvsc_open(struct block_device *bdev, fmode_t mode)
-{
-	struct block_device_context *blkdev = bdev->bd_disk->private_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	blkdev->users++;
-
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	return 0;
-}
-
-
-static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg)
-{
-	sector_t nsect = get_capacity(bd->bd_disk);
-	sector_t cylinders = nsect;
-
-	/*
-	 * We are making up these values; let us keep it simple.
-	 */
-	hg->heads = 0xff;
-	hg->sectors = 0x3f;
-	sector_div(cylinders, hg->heads * hg->sectors);
-	hg->cylinders = cylinders;
-	if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect)
-		hg->cylinders = 0xffff;
-	return 0;
-
-}
-
-
-static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req)
-{
-
-	blkvsc_req->cmd_len = 16;
-
-	if (rq_data_dir(blkvsc_req->req)) {
-		blkvsc_req->write = 1;
-		blkvsc_req->cmnd[0] = WRITE_16;
-	} else {
-		blkvsc_req->write = 0;
-		blkvsc_req->cmnd[0] = READ_16;
-	}
-
-	blkvsc_req->cmnd[1] |=
-	(blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0;
-
-	*(unsigned long long *)&blkvsc_req->cmnd[2] =
-	cpu_to_be64(blkvsc_req->sector_start);
-	*(unsigned int *)&blkvsc_req->cmnd[10] =
-	cpu_to_be32(blkvsc_req->sector_count);
-}
-
-
-static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
-			unsigned cmd, unsigned long arg)
-{
-	struct block_device_context *blkdev = bd->bd_disk->private_data;
-	int ret = 0;
-
-	switch (cmd) {
-	case HDIO_GET_IDENTITY:
-		if (copy_to_user((void __user *)arg, blkdev->device_id,
-				 blkdev->device_id_len))
-			ret = -EFAULT;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static void blkvsc_cmd_completion(struct hv_storvsc_request *request)
-{
-	struct blkvsc_request *blkvsc_req =
-			(struct blkvsc_request *)request->context;
-	struct block_device_context *blkdev =
-			(struct block_device_context *)blkvsc_req->dev;
-	struct scsi_sense_hdr sense_hdr;
-	struct vmscsi_request *vm_srb;
-	unsigned long flags;
-
-
-	vm_srb = &blkvsc_req->request.vstor_packet.vm_srb;
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-	blkdev->num_outstanding_reqs--;
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	if (vm_srb->scsi_status)
-		if (scsi_normalize_sense(blkvsc_req->sense_buffer,
-					 SCSI_SENSE_BUFFERSIZE, &sense_hdr))
-			scsi_print_sense_hdr("blkvsc", &sense_hdr);
-
-	complete(&blkvsc_req->request.wait_event);
-}
-
-
-static int blkvsc_do_operation(struct block_device_context *blkdev,
-				enum blkvsc_op_type op)
-{
-	struct blkvsc_request *blkvsc_req;
-	struct page *page_buf;
-	unsigned char *buf;
-	unsigned char device_type;
-	struct scsi_sense_hdr sense_hdr;
-	struct vmscsi_request *vm_srb;
-	unsigned long flags;
-
-	int ret = 0;
-
-	blkvsc_req = kmem_cache_zalloc(blkdev->request_pool, GFP_KERNEL);
-	if (!blkvsc_req)
-		return -ENOMEM;
-
-	page_buf = alloc_page(GFP_KERNEL);
-	if (!page_buf) {
-		kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
-		return -ENOMEM;
-	}
-
-	vm_srb = &blkvsc_req->request.vstor_packet.vm_srb;
-	init_completion(&blkvsc_req->request.wait_event);
-	blkvsc_req->dev = blkdev;
-	blkvsc_req->req = NULL;
-	blkvsc_req->write = 0;
-
-	blkvsc_req->request.data_buffer.pfn_array[0] =
-	page_to_pfn(page_buf);
-	blkvsc_req->request.data_buffer.offset = 0;
-
-	switch (op) {
-	case DO_INQUIRY:
-		blkvsc_req->cmnd[0] = INQUIRY;
-		blkvsc_req->cmnd[1] = 0x1;		/* Get product data */
-		blkvsc_req->cmnd[2] = 0x83;		/* mode page 83 */
-		blkvsc_req->cmnd[4] = 64;
-		blkvsc_req->cmd_len = 6;
-		blkvsc_req->request.data_buffer.len = 64;
-		break;
-
-	case DO_CAPACITY:
-		blkdev->sector_size = 0;
-		blkdev->capacity = 0;
-
-		blkvsc_req->cmnd[0] = READ_CAPACITY;
-		blkvsc_req->cmd_len = 16;
-		blkvsc_req->request.data_buffer.len = 8;
-		break;
-
-	case DO_FLUSH:
-		blkvsc_req->cmnd[0] = SYNCHRONIZE_CACHE;
-		blkvsc_req->cmd_len = 10;
-		blkvsc_req->request.data_buffer.pfn_array[0] = 0;
-		blkvsc_req->request.data_buffer.len = 0;
-		break;
-	default:
-		ret = -EINVAL;
-		goto cleanup;
-	}
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-	blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	wait_for_completion_interruptible(&blkvsc_req->request.wait_event);
-
-	/* check error */
-	if (vm_srb->scsi_status) {
-		scsi_normalize_sense(blkvsc_req->sense_buffer,
-				     SCSI_SENSE_BUFFERSIZE, &sense_hdr);
-
-		return 0;
-	}
-
-	buf = kmap(page_buf);
-
-	switch (op) {
-	case DO_INQUIRY:
-		device_type = buf[0] & 0x1F;
-
-		if (device_type == 0x0)
-			blkdev->device_type = HARDDISK_TYPE;
-		 else
-			blkdev->device_type = UNKNOWN_DEV_TYPE;
-
-		blkdev->device_id_len = buf[7];
-		if (blkdev->device_id_len > 64)
-			blkdev->device_id_len = 64;
-
-		memcpy(blkdev->device_id, &buf[8], blkdev->device_id_len);
-		break;
-
-	case DO_CAPACITY:
-		/* be to le */
-		blkdev->capacity =
-		((buf[0] << 24) | (buf[1] << 16) |
-		(buf[2] << 8) | buf[3]) + 1;
-
-		blkdev->sector_size =
-		(buf[4] << 24) | (buf[5] << 16) |
-		(buf[6] << 8) | buf[7];
-		break;
-	default:
-		break;
-
-	}
-
-cleanup:
-
-	kunmap(page_buf);
-
-	__free_page(page_buf);
-
-	kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
-
-	return ret;
-}
-
-
-static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
-{
-	struct blkvsc_request *pend_req, *tmp;
-	struct blkvsc_request *comp_req, *tmp2;
-	struct vmscsi_request *vm_srb;
-
-	int ret = 0;
-
-
-	/* Flush the pending list first */
-	list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list,
-				 pend_entry) {
-		/*
-		 * The pend_req could be part of a partially completed
-		 * request. If so, complete those req first until we
-		 * hit the pend_req
-		 */
-		list_for_each_entry_safe(comp_req, tmp2,
-					 &pend_req->group->blkvsc_req_list,
-					 req_entry) {
-
-			if (comp_req == pend_req)
-				break;
-
-			list_del(&comp_req->req_entry);
-
-			if (comp_req->req) {
-				vm_srb =
-				&comp_req->request.vstor_packet.
-				vm_srb;
-				ret = __blk_end_request(comp_req->req,
-					(!vm_srb->scsi_status ? 0 : -EIO),
-					comp_req->sector_count *
-					blkdev->sector_size);
-
-				/* FIXME: shouldn't this do more than return? */
-				if (ret)
-					goto out;
-			}
-
-			kmem_cache_free(blkdev->request_pool, comp_req);
-		}
-
-		list_del(&pend_req->pend_entry);
-
-		list_del(&pend_req->req_entry);
-
-		if (comp_req->req) {
-			if (!__blk_end_request(pend_req->req, -EIO,
-					       pend_req->sector_count *
-					       blkdev->sector_size)) {
-				/*
-				 * All the sectors have been xferred ie the
-				 * request is done
-				 */
-				kmem_cache_free(blkdev->request_pool,
-						pend_req->group);
-			}
-		}
-
-		kmem_cache_free(blkdev->request_pool, pend_req);
-	}
-
-out:
-	return ret;
-}
-
-
-/*
- * blkvsc_remove() - Callback when our device is removed
- */
-static int blkvsc_remove(struct hv_device *dev)
-{
-	struct block_device_context *blkdev = dev_get_drvdata(&dev->device);
-	unsigned long flags;
-
-
-	/* Get to a known state */
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	blkdev->shutting_down = 1;
-
-	blk_stop_queue(blkdev->gd->queue);
-
-	blkvsc_cancel_pending_reqs(blkdev);
-
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	blkvsc_do_operation(blkdev, DO_FLUSH);
-
-	if (blkdev->users == 0) {
-		del_gendisk(blkdev->gd);
-		put_disk(blkdev->gd);
-		blk_cleanup_queue(blkdev->gd->queue);
-
-		storvsc_dev_remove(blkdev->device_ctx);
-
-		kmem_cache_destroy(blkdev->request_pool);
-		kfree(blkdev);
-	}
-
-	return 0;
-}
-
-static void blkvsc_shutdown(struct hv_device *dev)
-{
-	struct block_device_context *blkdev = dev_get_drvdata(&dev->device);
-	unsigned long flags;
-
-	if (!blkdev)
-		return;
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	blkdev->shutting_down = 1;
-
-	blk_stop_queue(blkdev->gd->queue);
-
-	blkvsc_cancel_pending_reqs(blkdev);
-
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	blkvsc_do_operation(blkdev, DO_FLUSH);
-
-	/*
-	 * Now wait for all outgoing I/O to be drained.
-	 */
-	storvsc_wait_to_drain((struct storvsc_device *)dev->ext);
-
-}
-
-static int blkvsc_release(struct gendisk *disk, fmode_t mode)
-{
-	struct block_device_context *blkdev = disk->private_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	if ((--blkdev->users == 0) && (blkdev->shutting_down)) {
-		blk_stop_queue(blkdev->gd->queue);
-		spin_unlock_irqrestore(&blkdev->lock, flags);
-
-		blkvsc_do_operation(blkdev, DO_FLUSH);
-		del_gendisk(blkdev->gd);
-		put_disk(blkdev->gd);
-		blk_cleanup_queue(blkdev->gd->queue);
-
-		storvsc_dev_remove(blkdev->device_ctx);
-
-		kmem_cache_destroy(blkdev->request_pool);
-		kfree(blkdev);
-	} else
-		spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	return 0;
-}
-
-
-/*
- * We break the request into 1 or more blkvsc_requests and submit
- * them.  If we cant submit them all, we put them on the
- * pending_list. The blkvsc_request() will work on the pending_list.
- */
-static int blkvsc_do_request(struct block_device_context *blkdev,
-			     struct request *req)
-{
-	struct bio *bio = NULL;
-	struct bio_vec *bvec = NULL;
-	struct bio_vec *prev_bvec = NULL;
-	struct blkvsc_request *blkvsc_req = NULL;
-	struct blkvsc_request *tmp;
-	int databuf_idx = 0;
-	int seg_idx = 0;
-	sector_t start_sector;
-	unsigned long num_sectors = 0;
-	int ret = 0;
-	int pending = 0;
-	struct blkvsc_request_group *group = NULL;
-
-	/* Create a group to tie req to list of blkvsc_reqs */
-	group = kmem_cache_zalloc(blkdev->request_pool, GFP_ATOMIC);
-	if (!group)
-		return -ENOMEM;
-
-	INIT_LIST_HEAD(&group->blkvsc_req_list);
-	group->outstanding = group->status = 0;
-
-	start_sector = blk_rq_pos(req);
-
-	/* foreach bio in the request */
-	if (req->bio) {
-		for (bio = req->bio; bio; bio = bio->bi_next) {
-			/*
-			 * Map this bio into an existing or new storvsc request
-			 */
-			bio_for_each_segment(bvec, bio, seg_idx) {
-				/* Get a new storvsc request */
-				/* 1st-time */
-				if ((!blkvsc_req) ||
-				    (databuf_idx >= MAX_MULTIPAGE_BUFFER_COUNT)
-				    /* hole at the begin of page */
-				    || (bvec->bv_offset != 0) ||
-				    /* hold at the end of page */
-				    (prev_bvec &&
-				     (prev_bvec->bv_len != PAGE_SIZE))) {
-					/* submit the prev one */
-					if (blkvsc_req) {
-						blkvsc_req->sector_start =
-						start_sector;
-						sector_div(
-						blkvsc_req->sector_start,
-						(blkdev->sector_size >> 9));
-
-						blkvsc_req->sector_count =
-						num_sectors /
-						(blkdev->sector_size >> 9);
-						blkvsc_init_rw(blkvsc_req);
-					}
-
-					/*
-					 * Create new blkvsc_req to represent
-					 * the current bvec
-					 */
-					blkvsc_req =
-					kmem_cache_zalloc(
-					blkdev->request_pool, GFP_ATOMIC);
-					if (!blkvsc_req) {
-						/* free up everything */
-						list_for_each_entry_safe(
-							blkvsc_req, tmp,
-							&group->blkvsc_req_list,
-							req_entry) {
-							list_del(
-							&blkvsc_req->req_entry);
-							kmem_cache_free(
-							blkdev->request_pool,
-							blkvsc_req);
-						}
-
-						kmem_cache_free(
-						blkdev->request_pool, group);
-						return -ENOMEM;
-					}
-
-					memset(blkvsc_req, 0,
-					       sizeof(struct blkvsc_request));
-
-					blkvsc_req->dev = blkdev;
-					blkvsc_req->req = req;
-					blkvsc_req->request.
-					data_buffer.offset
-					= bvec->bv_offset;
-					blkvsc_req->request.
-					data_buffer.len = 0;
-
-					/* Add to the group */
-					blkvsc_req->group = group;
-					blkvsc_req->group->outstanding++;
-					list_add_tail(&blkvsc_req->req_entry,
-					&blkvsc_req->group->blkvsc_req_list);
-
-					start_sector += num_sectors;
-					num_sectors = 0;
-					databuf_idx = 0;
-				}
-
-				/*
-				 * Add the curr bvec/segment to the curr
-				 * blkvsc_req
-				 */
-				blkvsc_req->request.data_buffer.
-					pfn_array[databuf_idx]
-						= page_to_pfn(bvec->bv_page);
-				blkvsc_req->request.data_buffer.len
-					+= bvec->bv_len;
-
-				prev_bvec = bvec;
-
-				databuf_idx++;
-				num_sectors += bvec->bv_len >> 9;
-
-			} /* bio_for_each_segment */
-
-		} /* rq_for_each_bio */
-	}
-
-	/* Handle the last one */
-	if (blkvsc_req) {
-		blkvsc_req->sector_start = start_sector;
-		sector_div(blkvsc_req->sector_start,
-			   (blkdev->sector_size >> 9));
-
-		blkvsc_req->sector_count = num_sectors /
-					   (blkdev->sector_size >> 9);
-
-		blkvsc_init_rw(blkvsc_req);
-	}
-
-	list_for_each_entry(blkvsc_req, &group->blkvsc_req_list, req_entry) {
-		if (pending) {
-
-			list_add_tail(&blkvsc_req->pend_entry,
-				      &blkdev->pending_list);
-		} else {
-			ret = blkvsc_submit_request(blkvsc_req,
-						    blkvsc_request_completion);
-			if (ret == -EAGAIN) {
-				pending = 1;
-				list_add_tail(&blkvsc_req->pend_entry,
-					      &blkdev->pending_list);
-			}
-
-		}
-	}
-
-	return pending;
-}
-
-static int blkvsc_do_pending_reqs(struct block_device_context *blkdev)
-{
-	struct blkvsc_request *pend_req, *tmp;
-	int ret = 0;
-
-	/* Flush the pending list first */
-	list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list,
-				 pend_entry) {
-
-		ret = blkvsc_submit_request(pend_req,
-					    blkvsc_request_completion);
-		if (ret != 0)
-			break;
-		else
-			list_del(&pend_req->pend_entry);
-	}
-
-	return ret;
-}
-
-
-static void blkvsc_request(struct request_queue *queue)
-{
-	struct block_device_context *blkdev = NULL;
-	struct request *req;
-	int ret = 0;
-
-	while ((req = blk_peek_request(queue)) != NULL) {
-
-		blkdev = req->rq_disk->private_data;
-		if (blkdev->shutting_down || req->cmd_type != REQ_TYPE_FS) {
-			__blk_end_request_cur(req, 0);
-			continue;
-		}
-
-		ret = blkvsc_do_pending_reqs(blkdev);
-
-		if (ret != 0) {
-			blk_stop_queue(queue);
-			break;
-		}
-
-		blk_start_request(req);
-
-		ret = blkvsc_do_request(blkdev, req);
-		if (ret > 0) {
-			blk_stop_queue(queue);
-			break;
-		} else if (ret < 0) {
-			blk_requeue_request(queue, req);
-			blk_stop_queue(queue);
-			break;
-		}
-	}
-}
-
-static const struct hv_vmbus_device_id id_table[] = {
-	{ "hv_block" },
-	{ "" }
-};
-
-
-/* The one and only one */
-static  struct hv_driver blkvsc_drv = {
-	.id_table = id_table,
-	.probe =  blkvsc_probe,
-	.remove =  blkvsc_remove,
-	.shutdown = blkvsc_shutdown,
-};
-
-static const struct block_device_operations block_ops = {
-	.owner = THIS_MODULE,
-	.open = blkvsc_open,
-	.release = blkvsc_release,
-	.getgeo = blkvsc_getgeo,
-	.ioctl  = blkvsc_ioctl,
-};
-
-/*
- * blkvsc_drv_init -  BlkVsc driver initialization.
- */
-static int blkvsc_drv_init(void)
-{
-	struct hv_driver *drv = &blkvsc_drv;
-	int ret;
-
-	BUILD_BUG_ON(sizeof(sector_t) != 8);
-
-	drv->driver.name = drv_name;
-
-	/* The driver belongs to vmbus */
-	ret = vmbus_child_driver_register(&drv->driver);
-
-	return ret;
-}
-
-
-static void blkvsc_drv_exit(void)
-{
-
-	vmbus_child_driver_unregister(&blkvsc_drv.driver);
-}
-
-/*
- * blkvsc_probe - Add a new device for this driver
- */
-static int blkvsc_probe(struct hv_device *dev)
-{
-	struct block_device_context *blkdev = NULL;
-	struct storvsc_device_info device_info;
-	struct storvsc_major_info major_info;
-	int ret = 0;
-
-	blkdev = kzalloc(sizeof(struct block_device_context), GFP_KERNEL);
-	if (!blkdev) {
-		ret = -ENOMEM;
-		goto cleanup;
-	}
-
-	INIT_LIST_HEAD(&blkdev->pending_list);
-
-	/* Initialize what we can here */
-	spin_lock_init(&blkdev->lock);
-
-
-	blkdev->request_pool = kmem_cache_create(dev_name(&dev->device),
-					sizeof(struct blkvsc_request), 0,
-					SLAB_HWCACHE_ALIGN, NULL);
-	if (!blkdev->request_pool) {
-		ret = -ENOMEM;
-		goto cleanup;
-	}
-
-
-	ret = blkvsc_device_add(dev, &device_info);
-	if (ret != 0)
-		goto cleanup;
-
-	blkdev->device_ctx = dev;
-	/* this identified the device 0 or 1 */
-	blkdev->target = device_info.target_id;
-	/* this identified the ide ctrl 0 or 1 */
-	blkdev->path = device_info.path_id;
-
-	dev_set_drvdata(&dev->device, blkdev);
-
-	ret = storvsc_get_major_info(&device_info, &major_info);
-
-	if (ret)
-		goto cleanup;
-
-	if (major_info.do_register) {
-		ret = register_blkdev(major_info.major, major_info.devname);
-
-		if (ret != 0) {
-			DPRINT_ERR(BLKVSC_DRV,
-				   "register_blkdev() failed! ret %d", ret);
-			goto remove;
-		}
-	}
-
-	DPRINT_INFO(BLKVSC_DRV, "blkvsc registered for major %d!!",
-			major_info.major);
-
-	blkdev->gd = alloc_disk(BLKVSC_MINORS);
-	if (!blkdev->gd) {
-		ret = -1;
-		goto cleanup;
-	}
-
-	blkdev->gd->queue = blk_init_queue(blkvsc_request, &blkdev->lock);
-
-	blk_queue_max_segment_size(blkdev->gd->queue, PAGE_SIZE);
-	blk_queue_max_segments(blkdev->gd->queue, MAX_MULTIPAGE_BUFFER_COUNT);
-	blk_queue_segment_boundary(blkdev->gd->queue, PAGE_SIZE-1);
-	blk_queue_bounce_limit(blkdev->gd->queue, BLK_BOUNCE_ANY);
-	blk_queue_dma_alignment(blkdev->gd->queue, 511);
-
-	blkdev->gd->major = major_info.major;
-	if (major_info.index == 1 || major_info.index == 3)
-		blkdev->gd->first_minor = BLKVSC_MINORS;
-	else
-		blkdev->gd->first_minor = 0;
-	blkdev->gd->fops = &block_ops;
-	blkdev->gd->private_data = blkdev;
-	blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device);
-	sprintf(blkdev->gd->disk_name, "hd%c", 'a' + major_info.index);
-
-	blkvsc_do_operation(blkdev, DO_INQUIRY);
-	blkvsc_do_operation(blkdev, DO_CAPACITY);
-
-	set_capacity(blkdev->gd, blkdev->capacity * (blkdev->sector_size/512));
-	blk_queue_logical_block_size(blkdev->gd->queue, blkdev->sector_size);
-	/* go! */
-	add_disk(blkdev->gd);
-
-	DPRINT_INFO(BLKVSC_DRV, "%s added!! capacity %lu sector_size %d",
-		    blkdev->gd->disk_name, (unsigned long)blkdev->capacity,
-		    blkdev->sector_size);
-
-	return ret;
-
-remove:
-	storvsc_dev_remove(dev);
-
-cleanup:
-	if (blkdev) {
-		if (blkdev->request_pool) {
-			kmem_cache_destroy(blkdev->request_pool);
-			blkdev->request_pool = NULL;
-		}
-		kfree(blkdev);
-		blkdev = NULL;
-	}
-
-	return ret;
-}
-
-static void blkvsc_request_completion(struct hv_storvsc_request *request)
-{
-	struct blkvsc_request *blkvsc_req =
-			(struct blkvsc_request *)request->context;
-	struct block_device_context *blkdev =
-			(struct block_device_context *)blkvsc_req->dev;
-	unsigned long flags;
-	struct blkvsc_request *comp_req, *tmp;
-	struct vmscsi_request *vm_srb;
-
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	blkdev->num_outstanding_reqs--;
-	blkvsc_req->group->outstanding--;
-
-	/*
-	 * Only start processing when all the blkvsc_reqs are
-	 * completed. This guarantees no out-of-order blkvsc_req
-	 * completion when calling end_that_request_first()
-	 */
-	if (blkvsc_req->group->outstanding == 0) {
-		list_for_each_entry_safe(comp_req, tmp,
-					 &blkvsc_req->group->blkvsc_req_list,
-					 req_entry) {
-
-			list_del(&comp_req->req_entry);
-
-			vm_srb =
-			&comp_req->request.vstor_packet.vm_srb;
-			if (!__blk_end_request(comp_req->req,
-				(!vm_srb->scsi_status ? 0 : -EIO),
-				comp_req->sector_count * blkdev->sector_size)) {
-				/*
-				 * All the sectors have been xferred ie the
-				 * request is done
-				 */
-				kmem_cache_free(blkdev->request_pool,
-						comp_req->group);
-			}
-
-			kmem_cache_free(blkdev->request_pool, comp_req);
-		}
-
-		if (!blkdev->shutting_down) {
-			blkvsc_do_pending_reqs(blkdev);
-			blk_start_queue(blkdev->gd->queue);
-			blkvsc_request(blkdev->gd->queue);
-		}
-	}
-
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-}
-
-static void __exit blkvsc_exit(void)
-{
-	blkvsc_drv_exit();
-}
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION(HV_DRV_VERSION);
-MODULE_DESCRIPTION("Microsoft Hyper-V virtual block driver");
-MODULE_ALIAS("vmbus:hv_block");
-module_init(blkvsc_drv_init);
-module_exit(blkvsc_exit);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 31/40] Staging: hv: storvsc: Get rid of blkvsc_drv.c as this code is not used
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Now that we are handling all block devices using the scsi stack, get rid of
blkvsc_drv.c as it is not used any more.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/blkvsc_drv.c | 1024 ---------------------------------------
 1 files changed, 0 insertions(+), 1024 deletions(-)
 delete mode 100644 drivers/staging/hv/blkvsc_drv.c

diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
deleted file mode 100644
index 9898ea3..0000000
--- a/drivers/staging/hv/blkvsc_drv.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *   K. Y. Srinivasan <kys@microsoft.com>
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/blkdev.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/hdreg.h>
-#include <linux/slab.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_dbg.h>
-
-#include "hyperv.h"
-#include "hyperv_storage.h"
-
-
-#define BLKVSC_MINORS	64
-
-enum blkvsc_device_type {
-	UNKNOWN_DEV_TYPE,
-	HARDDISK_TYPE,
-	DVD_TYPE,
-};
-
-enum blkvsc_op_type {
-	DO_INQUIRY,
-	DO_CAPACITY,
-	DO_FLUSH,
-};
-
-/*
- * This request ties the struct request and struct
- * blkvsc_request/hv_storvsc_request together A struct request may be
- * represented by 1 or more struct blkvsc_request
- */
-struct blkvsc_request_group {
-	int outstanding;
-	int status;
-	struct list_head blkvsc_req_list;	/* list of blkvsc_requests */
-};
-
-struct blkvsc_request {
-	/* blkvsc_request_group.blkvsc_req_list */
-	struct list_head req_entry;
-
-	/* block_device_context.pending_list */
-	struct list_head pend_entry;
-
-	/* This may be null if we generate a request internally */
-	struct request *req;
-
-	struct block_device_context *dev;
-
-	/* The group this request is part of. Maybe null */
-	struct blkvsc_request_group *group;
-
-	int write;
-	sector_t sector_start;
-	unsigned long sector_count;
-
-	unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
-	unsigned char cmd_len;
-	unsigned char cmnd[MAX_COMMAND_SIZE];
-
-	struct hv_storvsc_request request;
-};
-
-/* Per device structure */
-struct block_device_context {
-	/* point back to our device context */
-	struct hv_device *device_ctx;
-	struct kmem_cache *request_pool;
-	spinlock_t lock;
-	struct gendisk *gd;
-	enum blkvsc_device_type	device_type;
-	struct list_head pending_list;
-
-	unsigned char device_id[64];
-	unsigned int device_id_len;
-	int num_outstanding_reqs;
-	int shutting_down;
-	unsigned int sector_size;
-	sector_t capacity;
-	unsigned int port;
-	unsigned char path;
-	unsigned char target;
-	int users;
-};
-
-static const char *drv_name = "blkvsc";
-
-
-/*
- * There is a circular dependency involving blkvsc_request_completion()
- * and blkvsc_do_request().
- */
-static void blkvsc_request_completion(struct hv_storvsc_request *request);
-
-static int blkvsc_ringbuffer_size = BLKVSC_RING_BUFFER_SIZE;
-
-module_param(blkvsc_ringbuffer_size, int, S_IRUGO);
-MODULE_PARM_DESC(ring_size, "Ring buffer size (in bytes)");
-
-/*
- * There is a circular dependency involving blkvsc_probe()
- * and block_ops.
- */
-static int blkvsc_probe(struct hv_device *dev);
-
-static int blkvsc_device_add(struct hv_device *device,
-				void *additional_info)
-{
-	struct storvsc_device_info *device_info;
-	int ret = 0;
-
-	device_info = (struct storvsc_device_info *)additional_info;
-
-	device_info->ring_buffer_size = blkvsc_ringbuffer_size;
-
-	ret = storvsc_dev_add(device, additional_info);
-	if (ret != 0)
-		return ret;
-
-	/*
-	 * We need to use the device instance guid to set the path and target
-	 * id. For IDE devices, the device instance id is formatted as
-	 * <bus id> * - <device id> - 8899 - 000000000000.
-	 */
-	device_info->path_id = device->dev_instance.data[3] << 24 |
-			     device->dev_instance.data[2] << 16 |
-			     device->dev_instance.data[1] << 8  |
-			     device->dev_instance.data[0];
-
-	device_info->target_id = device->dev_instance.data[5] << 8 |
-			       device->dev_instance.data[4];
-
-	return ret;
-}
-
-static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
-			void (*request_completion)(struct hv_storvsc_request *))
-{
-	struct block_device_context *blkdev = blkvsc_req->dev;
-	struct hv_storvsc_request *storvsc_req;
-	struct vmscsi_request *vm_srb;
-	int ret;
-
-
-	storvsc_req = &blkvsc_req->request;
-	vm_srb = &storvsc_req->vstor_packet.vm_srb;
-
-	vm_srb->data_in = blkvsc_req->write ? WRITE_TYPE : READ_TYPE;
-
-	storvsc_req->on_io_completion = request_completion;
-	storvsc_req->context = blkvsc_req;
-
-	vm_srb->port_number = blkdev->port;
-	vm_srb->path_id = blkdev->path;
-	vm_srb->target_id = blkdev->target;
-	vm_srb->lun = 0;	 /* this is not really used at all */
-
-	vm_srb->cdb_length = blkvsc_req->cmd_len;
-
-	memcpy(vm_srb->cdb, blkvsc_req->cmnd, vm_srb->cdb_length);
-
-	storvsc_req->sense_buffer = blkvsc_req->sense_buffer;
-
-	ret =  storvsc_do_io(blkdev->device_ctx,
-					   &blkvsc_req->request);
-	if (ret == 0)
-		blkdev->num_outstanding_reqs++;
-
-	return ret;
-}
-
-
-static int blkvsc_open(struct block_device *bdev, fmode_t mode)
-{
-	struct block_device_context *blkdev = bdev->bd_disk->private_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	blkdev->users++;
-
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	return 0;
-}
-
-
-static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg)
-{
-	sector_t nsect = get_capacity(bd->bd_disk);
-	sector_t cylinders = nsect;
-
-	/*
-	 * We are making up these values; let us keep it simple.
-	 */
-	hg->heads = 0xff;
-	hg->sectors = 0x3f;
-	sector_div(cylinders, hg->heads * hg->sectors);
-	hg->cylinders = cylinders;
-	if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect)
-		hg->cylinders = 0xffff;
-	return 0;
-
-}
-
-
-static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req)
-{
-
-	blkvsc_req->cmd_len = 16;
-
-	if (rq_data_dir(blkvsc_req->req)) {
-		blkvsc_req->write = 1;
-		blkvsc_req->cmnd[0] = WRITE_16;
-	} else {
-		blkvsc_req->write = 0;
-		blkvsc_req->cmnd[0] = READ_16;
-	}
-
-	blkvsc_req->cmnd[1] |=
-	(blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0;
-
-	*(unsigned long long *)&blkvsc_req->cmnd[2] =
-	cpu_to_be64(blkvsc_req->sector_start);
-	*(unsigned int *)&blkvsc_req->cmnd[10] =
-	cpu_to_be32(blkvsc_req->sector_count);
-}
-
-
-static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
-			unsigned cmd, unsigned long arg)
-{
-	struct block_device_context *blkdev = bd->bd_disk->private_data;
-	int ret = 0;
-
-	switch (cmd) {
-	case HDIO_GET_IDENTITY:
-		if (copy_to_user((void __user *)arg, blkdev->device_id,
-				 blkdev->device_id_len))
-			ret = -EFAULT;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static void blkvsc_cmd_completion(struct hv_storvsc_request *request)
-{
-	struct blkvsc_request *blkvsc_req =
-			(struct blkvsc_request *)request->context;
-	struct block_device_context *blkdev =
-			(struct block_device_context *)blkvsc_req->dev;
-	struct scsi_sense_hdr sense_hdr;
-	struct vmscsi_request *vm_srb;
-	unsigned long flags;
-
-
-	vm_srb = &blkvsc_req->request.vstor_packet.vm_srb;
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-	blkdev->num_outstanding_reqs--;
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	if (vm_srb->scsi_status)
-		if (scsi_normalize_sense(blkvsc_req->sense_buffer,
-					 SCSI_SENSE_BUFFERSIZE, &sense_hdr))
-			scsi_print_sense_hdr("blkvsc", &sense_hdr);
-
-	complete(&blkvsc_req->request.wait_event);
-}
-
-
-static int blkvsc_do_operation(struct block_device_context *blkdev,
-				enum blkvsc_op_type op)
-{
-	struct blkvsc_request *blkvsc_req;
-	struct page *page_buf;
-	unsigned char *buf;
-	unsigned char device_type;
-	struct scsi_sense_hdr sense_hdr;
-	struct vmscsi_request *vm_srb;
-	unsigned long flags;
-
-	int ret = 0;
-
-	blkvsc_req = kmem_cache_zalloc(blkdev->request_pool, GFP_KERNEL);
-	if (!blkvsc_req)
-		return -ENOMEM;
-
-	page_buf = alloc_page(GFP_KERNEL);
-	if (!page_buf) {
-		kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
-		return -ENOMEM;
-	}
-
-	vm_srb = &blkvsc_req->request.vstor_packet.vm_srb;
-	init_completion(&blkvsc_req->request.wait_event);
-	blkvsc_req->dev = blkdev;
-	blkvsc_req->req = NULL;
-	blkvsc_req->write = 0;
-
-	blkvsc_req->request.data_buffer.pfn_array[0] =
-	page_to_pfn(page_buf);
-	blkvsc_req->request.data_buffer.offset = 0;
-
-	switch (op) {
-	case DO_INQUIRY:
-		blkvsc_req->cmnd[0] = INQUIRY;
-		blkvsc_req->cmnd[1] = 0x1;		/* Get product data */
-		blkvsc_req->cmnd[2] = 0x83;		/* mode page 83 */
-		blkvsc_req->cmnd[4] = 64;
-		blkvsc_req->cmd_len = 6;
-		blkvsc_req->request.data_buffer.len = 64;
-		break;
-
-	case DO_CAPACITY:
-		blkdev->sector_size = 0;
-		blkdev->capacity = 0;
-
-		blkvsc_req->cmnd[0] = READ_CAPACITY;
-		blkvsc_req->cmd_len = 16;
-		blkvsc_req->request.data_buffer.len = 8;
-		break;
-
-	case DO_FLUSH:
-		blkvsc_req->cmnd[0] = SYNCHRONIZE_CACHE;
-		blkvsc_req->cmd_len = 10;
-		blkvsc_req->request.data_buffer.pfn_array[0] = 0;
-		blkvsc_req->request.data_buffer.len = 0;
-		break;
-	default:
-		ret = -EINVAL;
-		goto cleanup;
-	}
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-	blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	wait_for_completion_interruptible(&blkvsc_req->request.wait_event);
-
-	/* check error */
-	if (vm_srb->scsi_status) {
-		scsi_normalize_sense(blkvsc_req->sense_buffer,
-				     SCSI_SENSE_BUFFERSIZE, &sense_hdr);
-
-		return 0;
-	}
-
-	buf = kmap(page_buf);
-
-	switch (op) {
-	case DO_INQUIRY:
-		device_type = buf[0] & 0x1F;
-
-		if (device_type == 0x0)
-			blkdev->device_type = HARDDISK_TYPE;
-		 else
-			blkdev->device_type = UNKNOWN_DEV_TYPE;
-
-		blkdev->device_id_len = buf[7];
-		if (blkdev->device_id_len > 64)
-			blkdev->device_id_len = 64;
-
-		memcpy(blkdev->device_id, &buf[8], blkdev->device_id_len);
-		break;
-
-	case DO_CAPACITY:
-		/* be to le */
-		blkdev->capacity =
-		((buf[0] << 24) | (buf[1] << 16) |
-		(buf[2] << 8) | buf[3]) + 1;
-
-		blkdev->sector_size =
-		(buf[4] << 24) | (buf[5] << 16) |
-		(buf[6] << 8) | buf[7];
-		break;
-	default:
-		break;
-
-	}
-
-cleanup:
-
-	kunmap(page_buf);
-
-	__free_page(page_buf);
-
-	kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
-
-	return ret;
-}
-
-
-static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
-{
-	struct blkvsc_request *pend_req, *tmp;
-	struct blkvsc_request *comp_req, *tmp2;
-	struct vmscsi_request *vm_srb;
-
-	int ret = 0;
-
-
-	/* Flush the pending list first */
-	list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list,
-				 pend_entry) {
-		/*
-		 * The pend_req could be part of a partially completed
-		 * request. If so, complete those req first until we
-		 * hit the pend_req
-		 */
-		list_for_each_entry_safe(comp_req, tmp2,
-					 &pend_req->group->blkvsc_req_list,
-					 req_entry) {
-
-			if (comp_req == pend_req)
-				break;
-
-			list_del(&comp_req->req_entry);
-
-			if (comp_req->req) {
-				vm_srb =
-				&comp_req->request.vstor_packet.
-				vm_srb;
-				ret = __blk_end_request(comp_req->req,
-					(!vm_srb->scsi_status ? 0 : -EIO),
-					comp_req->sector_count *
-					blkdev->sector_size);
-
-				/* FIXME: shouldn't this do more than return? */
-				if (ret)
-					goto out;
-			}
-
-			kmem_cache_free(blkdev->request_pool, comp_req);
-		}
-
-		list_del(&pend_req->pend_entry);
-
-		list_del(&pend_req->req_entry);
-
-		if (comp_req->req) {
-			if (!__blk_end_request(pend_req->req, -EIO,
-					       pend_req->sector_count *
-					       blkdev->sector_size)) {
-				/*
-				 * All the sectors have been xferred ie the
-				 * request is done
-				 */
-				kmem_cache_free(blkdev->request_pool,
-						pend_req->group);
-			}
-		}
-
-		kmem_cache_free(blkdev->request_pool, pend_req);
-	}
-
-out:
-	return ret;
-}
-
-
-/*
- * blkvsc_remove() - Callback when our device is removed
- */
-static int blkvsc_remove(struct hv_device *dev)
-{
-	struct block_device_context *blkdev = dev_get_drvdata(&dev->device);
-	unsigned long flags;
-
-
-	/* Get to a known state */
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	blkdev->shutting_down = 1;
-
-	blk_stop_queue(blkdev->gd->queue);
-
-	blkvsc_cancel_pending_reqs(blkdev);
-
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	blkvsc_do_operation(blkdev, DO_FLUSH);
-
-	if (blkdev->users == 0) {
-		del_gendisk(blkdev->gd);
-		put_disk(blkdev->gd);
-		blk_cleanup_queue(blkdev->gd->queue);
-
-		storvsc_dev_remove(blkdev->device_ctx);
-
-		kmem_cache_destroy(blkdev->request_pool);
-		kfree(blkdev);
-	}
-
-	return 0;
-}
-
-static void blkvsc_shutdown(struct hv_device *dev)
-{
-	struct block_device_context *blkdev = dev_get_drvdata(&dev->device);
-	unsigned long flags;
-
-	if (!blkdev)
-		return;
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	blkdev->shutting_down = 1;
-
-	blk_stop_queue(blkdev->gd->queue);
-
-	blkvsc_cancel_pending_reqs(blkdev);
-
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	blkvsc_do_operation(blkdev, DO_FLUSH);
-
-	/*
-	 * Now wait for all outgoing I/O to be drained.
-	 */
-	storvsc_wait_to_drain((struct storvsc_device *)dev->ext);
-
-}
-
-static int blkvsc_release(struct gendisk *disk, fmode_t mode)
-{
-	struct block_device_context *blkdev = disk->private_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	if ((--blkdev->users == 0) && (blkdev->shutting_down)) {
-		blk_stop_queue(blkdev->gd->queue);
-		spin_unlock_irqrestore(&blkdev->lock, flags);
-
-		blkvsc_do_operation(blkdev, DO_FLUSH);
-		del_gendisk(blkdev->gd);
-		put_disk(blkdev->gd);
-		blk_cleanup_queue(blkdev->gd->queue);
-
-		storvsc_dev_remove(blkdev->device_ctx);
-
-		kmem_cache_destroy(blkdev->request_pool);
-		kfree(blkdev);
-	} else
-		spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	return 0;
-}
-
-
-/*
- * We break the request into 1 or more blkvsc_requests and submit
- * them.  If we cant submit them all, we put them on the
- * pending_list. The blkvsc_request() will work on the pending_list.
- */
-static int blkvsc_do_request(struct block_device_context *blkdev,
-			     struct request *req)
-{
-	struct bio *bio = NULL;
-	struct bio_vec *bvec = NULL;
-	struct bio_vec *prev_bvec = NULL;
-	struct blkvsc_request *blkvsc_req = NULL;
-	struct blkvsc_request *tmp;
-	int databuf_idx = 0;
-	int seg_idx = 0;
-	sector_t start_sector;
-	unsigned long num_sectors = 0;
-	int ret = 0;
-	int pending = 0;
-	struct blkvsc_request_group *group = NULL;
-
-	/* Create a group to tie req to list of blkvsc_reqs */
-	group = kmem_cache_zalloc(blkdev->request_pool, GFP_ATOMIC);
-	if (!group)
-		return -ENOMEM;
-
-	INIT_LIST_HEAD(&group->blkvsc_req_list);
-	group->outstanding = group->status = 0;
-
-	start_sector = blk_rq_pos(req);
-
-	/* foreach bio in the request */
-	if (req->bio) {
-		for (bio = req->bio; bio; bio = bio->bi_next) {
-			/*
-			 * Map this bio into an existing or new storvsc request
-			 */
-			bio_for_each_segment(bvec, bio, seg_idx) {
-				/* Get a new storvsc request */
-				/* 1st-time */
-				if ((!blkvsc_req) ||
-				    (databuf_idx >= MAX_MULTIPAGE_BUFFER_COUNT)
-				    /* hole at the begin of page */
-				    || (bvec->bv_offset != 0) ||
-				    /* hold at the end of page */
-				    (prev_bvec &&
-				     (prev_bvec->bv_len != PAGE_SIZE))) {
-					/* submit the prev one */
-					if (blkvsc_req) {
-						blkvsc_req->sector_start =
-						start_sector;
-						sector_div(
-						blkvsc_req->sector_start,
-						(blkdev->sector_size >> 9));
-
-						blkvsc_req->sector_count =
-						num_sectors /
-						(blkdev->sector_size >> 9);
-						blkvsc_init_rw(blkvsc_req);
-					}
-
-					/*
-					 * Create new blkvsc_req to represent
-					 * the current bvec
-					 */
-					blkvsc_req =
-					kmem_cache_zalloc(
-					blkdev->request_pool, GFP_ATOMIC);
-					if (!blkvsc_req) {
-						/* free up everything */
-						list_for_each_entry_safe(
-							blkvsc_req, tmp,
-							&group->blkvsc_req_list,
-							req_entry) {
-							list_del(
-							&blkvsc_req->req_entry);
-							kmem_cache_free(
-							blkdev->request_pool,
-							blkvsc_req);
-						}
-
-						kmem_cache_free(
-						blkdev->request_pool, group);
-						return -ENOMEM;
-					}
-
-					memset(blkvsc_req, 0,
-					       sizeof(struct blkvsc_request));
-
-					blkvsc_req->dev = blkdev;
-					blkvsc_req->req = req;
-					blkvsc_req->request.
-					data_buffer.offset
-					= bvec->bv_offset;
-					blkvsc_req->request.
-					data_buffer.len = 0;
-
-					/* Add to the group */
-					blkvsc_req->group = group;
-					blkvsc_req->group->outstanding++;
-					list_add_tail(&blkvsc_req->req_entry,
-					&blkvsc_req->group->blkvsc_req_list);
-
-					start_sector += num_sectors;
-					num_sectors = 0;
-					databuf_idx = 0;
-				}
-
-				/*
-				 * Add the curr bvec/segment to the curr
-				 * blkvsc_req
-				 */
-				blkvsc_req->request.data_buffer.
-					pfn_array[databuf_idx]
-						= page_to_pfn(bvec->bv_page);
-				blkvsc_req->request.data_buffer.len
-					+= bvec->bv_len;
-
-				prev_bvec = bvec;
-
-				databuf_idx++;
-				num_sectors += bvec->bv_len >> 9;
-
-			} /* bio_for_each_segment */
-
-		} /* rq_for_each_bio */
-	}
-
-	/* Handle the last one */
-	if (blkvsc_req) {
-		blkvsc_req->sector_start = start_sector;
-		sector_div(blkvsc_req->sector_start,
-			   (blkdev->sector_size >> 9));
-
-		blkvsc_req->sector_count = num_sectors /
-					   (blkdev->sector_size >> 9);
-
-		blkvsc_init_rw(blkvsc_req);
-	}
-
-	list_for_each_entry(blkvsc_req, &group->blkvsc_req_list, req_entry) {
-		if (pending) {
-
-			list_add_tail(&blkvsc_req->pend_entry,
-				      &blkdev->pending_list);
-		} else {
-			ret = blkvsc_submit_request(blkvsc_req,
-						    blkvsc_request_completion);
-			if (ret == -EAGAIN) {
-				pending = 1;
-				list_add_tail(&blkvsc_req->pend_entry,
-					      &blkdev->pending_list);
-			}
-
-		}
-	}
-
-	return pending;
-}
-
-static int blkvsc_do_pending_reqs(struct block_device_context *blkdev)
-{
-	struct blkvsc_request *pend_req, *tmp;
-	int ret = 0;
-
-	/* Flush the pending list first */
-	list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list,
-				 pend_entry) {
-
-		ret = blkvsc_submit_request(pend_req,
-					    blkvsc_request_completion);
-		if (ret != 0)
-			break;
-		else
-			list_del(&pend_req->pend_entry);
-	}
-
-	return ret;
-}
-
-
-static void blkvsc_request(struct request_queue *queue)
-{
-	struct block_device_context *blkdev = NULL;
-	struct request *req;
-	int ret = 0;
-
-	while ((req = blk_peek_request(queue)) != NULL) {
-
-		blkdev = req->rq_disk->private_data;
-		if (blkdev->shutting_down || req->cmd_type != REQ_TYPE_FS) {
-			__blk_end_request_cur(req, 0);
-			continue;
-		}
-
-		ret = blkvsc_do_pending_reqs(blkdev);
-
-		if (ret != 0) {
-			blk_stop_queue(queue);
-			break;
-		}
-
-		blk_start_request(req);
-
-		ret = blkvsc_do_request(blkdev, req);
-		if (ret > 0) {
-			blk_stop_queue(queue);
-			break;
-		} else if (ret < 0) {
-			blk_requeue_request(queue, req);
-			blk_stop_queue(queue);
-			break;
-		}
-	}
-}
-
-static const struct hv_vmbus_device_id id_table[] = {
-	{ "hv_block" },
-	{ "" }
-};
-
-
-/* The one and only one */
-static  struct hv_driver blkvsc_drv = {
-	.id_table = id_table,
-	.probe =  blkvsc_probe,
-	.remove =  blkvsc_remove,
-	.shutdown = blkvsc_shutdown,
-};
-
-static const struct block_device_operations block_ops = {
-	.owner = THIS_MODULE,
-	.open = blkvsc_open,
-	.release = blkvsc_release,
-	.getgeo = blkvsc_getgeo,
-	.ioctl  = blkvsc_ioctl,
-};
-
-/*
- * blkvsc_drv_init -  BlkVsc driver initialization.
- */
-static int blkvsc_drv_init(void)
-{
-	struct hv_driver *drv = &blkvsc_drv;
-	int ret;
-
-	BUILD_BUG_ON(sizeof(sector_t) != 8);
-
-	drv->driver.name = drv_name;
-
-	/* The driver belongs to vmbus */
-	ret = vmbus_child_driver_register(&drv->driver);
-
-	return ret;
-}
-
-
-static void blkvsc_drv_exit(void)
-{
-
-	vmbus_child_driver_unregister(&blkvsc_drv.driver);
-}
-
-/*
- * blkvsc_probe - Add a new device for this driver
- */
-static int blkvsc_probe(struct hv_device *dev)
-{
-	struct block_device_context *blkdev = NULL;
-	struct storvsc_device_info device_info;
-	struct storvsc_major_info major_info;
-	int ret = 0;
-
-	blkdev = kzalloc(sizeof(struct block_device_context), GFP_KERNEL);
-	if (!blkdev) {
-		ret = -ENOMEM;
-		goto cleanup;
-	}
-
-	INIT_LIST_HEAD(&blkdev->pending_list);
-
-	/* Initialize what we can here */
-	spin_lock_init(&blkdev->lock);
-
-
-	blkdev->request_pool = kmem_cache_create(dev_name(&dev->device),
-					sizeof(struct blkvsc_request), 0,
-					SLAB_HWCACHE_ALIGN, NULL);
-	if (!blkdev->request_pool) {
-		ret = -ENOMEM;
-		goto cleanup;
-	}
-
-
-	ret = blkvsc_device_add(dev, &device_info);
-	if (ret != 0)
-		goto cleanup;
-
-	blkdev->device_ctx = dev;
-	/* this identified the device 0 or 1 */
-	blkdev->target = device_info.target_id;
-	/* this identified the ide ctrl 0 or 1 */
-	blkdev->path = device_info.path_id;
-
-	dev_set_drvdata(&dev->device, blkdev);
-
-	ret = storvsc_get_major_info(&device_info, &major_info);
-
-	if (ret)
-		goto cleanup;
-
-	if (major_info.do_register) {
-		ret = register_blkdev(major_info.major, major_info.devname);
-
-		if (ret != 0) {
-			DPRINT_ERR(BLKVSC_DRV,
-				   "register_blkdev() failed! ret %d", ret);
-			goto remove;
-		}
-	}
-
-	DPRINT_INFO(BLKVSC_DRV, "blkvsc registered for major %d!!",
-			major_info.major);
-
-	blkdev->gd = alloc_disk(BLKVSC_MINORS);
-	if (!blkdev->gd) {
-		ret = -1;
-		goto cleanup;
-	}
-
-	blkdev->gd->queue = blk_init_queue(blkvsc_request, &blkdev->lock);
-
-	blk_queue_max_segment_size(blkdev->gd->queue, PAGE_SIZE);
-	blk_queue_max_segments(blkdev->gd->queue, MAX_MULTIPAGE_BUFFER_COUNT);
-	blk_queue_segment_boundary(blkdev->gd->queue, PAGE_SIZE-1);
-	blk_queue_bounce_limit(blkdev->gd->queue, BLK_BOUNCE_ANY);
-	blk_queue_dma_alignment(blkdev->gd->queue, 511);
-
-	blkdev->gd->major = major_info.major;
-	if (major_info.index == 1 || major_info.index == 3)
-		blkdev->gd->first_minor = BLKVSC_MINORS;
-	else
-		blkdev->gd->first_minor = 0;
-	blkdev->gd->fops = &block_ops;
-	blkdev->gd->private_data = blkdev;
-	blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device);
-	sprintf(blkdev->gd->disk_name, "hd%c", 'a' + major_info.index);
-
-	blkvsc_do_operation(blkdev, DO_INQUIRY);
-	blkvsc_do_operation(blkdev, DO_CAPACITY);
-
-	set_capacity(blkdev->gd, blkdev->capacity * (blkdev->sector_size/512));
-	blk_queue_logical_block_size(blkdev->gd->queue, blkdev->sector_size);
-	/* go! */
-	add_disk(blkdev->gd);
-
-	DPRINT_INFO(BLKVSC_DRV, "%s added!! capacity %lu sector_size %d",
-		    blkdev->gd->disk_name, (unsigned long)blkdev->capacity,
-		    blkdev->sector_size);
-
-	return ret;
-
-remove:
-	storvsc_dev_remove(dev);
-
-cleanup:
-	if (blkdev) {
-		if (blkdev->request_pool) {
-			kmem_cache_destroy(blkdev->request_pool);
-			blkdev->request_pool = NULL;
-		}
-		kfree(blkdev);
-		blkdev = NULL;
-	}
-
-	return ret;
-}
-
-static void blkvsc_request_completion(struct hv_storvsc_request *request)
-{
-	struct blkvsc_request *blkvsc_req =
-			(struct blkvsc_request *)request->context;
-	struct block_device_context *blkdev =
-			(struct block_device_context *)blkvsc_req->dev;
-	unsigned long flags;
-	struct blkvsc_request *comp_req, *tmp;
-	struct vmscsi_request *vm_srb;
-
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	blkdev->num_outstanding_reqs--;
-	blkvsc_req->group->outstanding--;
-
-	/*
-	 * Only start processing when all the blkvsc_reqs are
-	 * completed. This guarantees no out-of-order blkvsc_req
-	 * completion when calling end_that_request_first()
-	 */
-	if (blkvsc_req->group->outstanding == 0) {
-		list_for_each_entry_safe(comp_req, tmp,
-					 &blkvsc_req->group->blkvsc_req_list,
-					 req_entry) {
-
-			list_del(&comp_req->req_entry);
-
-			vm_srb =
-			&comp_req->request.vstor_packet.vm_srb;
-			if (!__blk_end_request(comp_req->req,
-				(!vm_srb->scsi_status ? 0 : -EIO),
-				comp_req->sector_count * blkdev->sector_size)) {
-				/*
-				 * All the sectors have been xferred ie the
-				 * request is done
-				 */
-				kmem_cache_free(blkdev->request_pool,
-						comp_req->group);
-			}
-
-			kmem_cache_free(blkdev->request_pool, comp_req);
-		}
-
-		if (!blkdev->shutting_down) {
-			blkvsc_do_pending_reqs(blkdev);
-			blk_start_queue(blkdev->gd->queue);
-			blkvsc_request(blkdev->gd->queue);
-		}
-	}
-
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-}
-
-static void __exit blkvsc_exit(void)
-{
-	blkvsc_drv_exit();
-}
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION(HV_DRV_VERSION);
-MODULE_DESCRIPTION("Microsoft Hyper-V virtual block driver");
-MODULE_ALIAS("vmbus:hv_block");
-module_init(blkvsc_drv_init);
-module_exit(blkvsc_exit);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 32/40] Staging: hv: storvsc: Include storvsc.c in storvsc_drv.c
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

As part of further cleanup of our storage drivers, include the content
of storvsc.c into storvsc_drv.c.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/Makefile      |    2 +-
 drivers/staging/hv/storvsc.c     |  527 -------------------------------------
 drivers/staging/hv/storvsc_drv.c |  528 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 529 insertions(+), 528 deletions(-)
 delete mode 100644 drivers/staging/hv/storvsc.c

diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
index bb89437..bd176b1 100644
--- a/drivers/staging/hv/Makefile
+++ b/drivers/staging/hv/Makefile
@@ -7,6 +7,6 @@ obj-$(CONFIG_HYPERV_MOUSE)	+= hv_mouse.o
 hv_vmbus-y := vmbus_drv.o \
 		 hv.o connection.o channel.o \
 		 channel_mgmt.o ring_buffer.o
-hv_storvsc-y := storvsc_drv.o storvsc.o
+hv_storvsc-y := storvsc_drv.o
 hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o
 hv_utils-y := hv_util.o hv_kvp.o
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
deleted file mode 100644
index c06f750..0000000
--- a/drivers/staging/hv/storvsc.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *   K. Y. Srinivasan <kys@microsoft.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/completion.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#include "hyperv.h"
-#include "hyperv_storage.h"
-
-
-static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-
-	stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL);
-	if (!stor_device)
-		return NULL;
-
-	stor_device->ref_count = 1;
-	stor_device->destroy = false;
-	stor_device->hba_owner = false;
-	init_waitqueue_head(&stor_device->waiting_to_drain);
-	stor_device->device = device;
-	device->ext = stor_device;
-
-	return stor_device;
-}
-
-static inline struct storvsc_device *get_in_stor_device(
-					struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	unsigned long flags;
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	stor_device = (struct storvsc_device *)device->ext;
-	if (!stor_device)
-		goto cleanup;
-
-	/*
-	 * If the device is being destroyed; allow incoming
-	 * traffic only to cleanup outstanding requests.
-	 */
-	if (stor_device->destroy &&
-		 (atomic_read(&stor_device->num_outstanding_req) == 0))
-		goto cleanup;
-	stor_device->ref_count++;
-cleanup:
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-
-	return stor_device;
-}
-
-static int storvsc_channel_init(struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	struct hv_storvsc_request *request;
-	struct vstor_packet *vstor_packet;
-	int ret, t;
-
-	stor_device = get_out_stor_device(device);
-	if (!stor_device)
-		return -ENODEV;
-
-	request = &stor_device->init_request;
-	vstor_packet = &request->vstor_packet;
-
-	/*
-	 * Now, initiate the vsc/vsp initialization protocol on the open
-	 * channel
-	 */
-	memset(request, 0, sizeof(struct hv_storvsc_request));
-	init_completion(&request->wait_event);
-	vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
-	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
-
-	ret = vmbus_sendpacket(device->channel, vstor_packet,
-			       sizeof(struct vstor_packet),
-			       (unsigned long)request,
-			       VM_PKT_DATA_INBAND,
-			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	if (ret != 0)
-		goto cleanup;
-
-	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
-	if (t == 0) {
-		ret = -ETIMEDOUT;
-		goto cleanup;
-	}
-
-	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
-	    vstor_packet->status != 0)
-		goto cleanup;
-
-
-	/* reuse the packet for version range supported */
-	memset(vstor_packet, 0, sizeof(struct vstor_packet));
-	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
-	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
-
-	vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT;
-	FILL_VMSTOR_REVISION(vstor_packet->version.revision);
-
-	ret = vmbus_sendpacket(device->channel, vstor_packet,
-			       sizeof(struct vstor_packet),
-			       (unsigned long)request,
-			       VM_PKT_DATA_INBAND,
-			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	if (ret != 0)
-		goto cleanup;
-
-	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
-	if (t == 0) {
-		ret = -ETIMEDOUT;
-		goto cleanup;
-	}
-
-	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
-	    vstor_packet->status != 0)
-		goto cleanup;
-
-
-	memset(vstor_packet, 0, sizeof(struct vstor_packet));
-	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
-	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
-	vstor_packet->storage_channel_properties.port_number =
-					stor_device->port_number;
-
-	ret = vmbus_sendpacket(device->channel, vstor_packet,
-			       sizeof(struct vstor_packet),
-			       (unsigned long)request,
-			       VM_PKT_DATA_INBAND,
-			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
-	if (ret != 0)
-		goto cleanup;
-
-	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
-	if (t == 0) {
-		ret = -ETIMEDOUT;
-		goto cleanup;
-	}
-
-	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
-	    vstor_packet->status != 0)
-		goto cleanup;
-
-	stor_device->path_id = vstor_packet->storage_channel_properties.path_id;
-	stor_device->target_id
-		= vstor_packet->storage_channel_properties.target_id;
-
-	memset(vstor_packet, 0, sizeof(struct vstor_packet));
-	vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
-	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
-
-	ret = vmbus_sendpacket(device->channel, vstor_packet,
-			       sizeof(struct vstor_packet),
-			       (unsigned long)request,
-			       VM_PKT_DATA_INBAND,
-			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
-	if (ret != 0)
-		goto cleanup;
-
-	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
-	if (t == 0) {
-		ret = -ETIMEDOUT;
-		goto cleanup;
-	}
-
-	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
-	    vstor_packet->status != 0)
-		goto cleanup;
-
-
-cleanup:
-	put_stor_device(device);
-	return ret;
-}
-
-static void storvsc_on_io_completion(struct hv_device *device,
-				  struct vstor_packet *vstor_packet,
-				  struct hv_storvsc_request *request)
-{
-	struct storvsc_device *stor_device;
-	struct vstor_packet *stor_pkt;
-
-	stor_device = (struct storvsc_device *)device->ext;
-
-	stor_pkt = &request->vstor_packet;
-
-
-	/* Copy over the status...etc */
-	stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status;
-	stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status;
-	stor_pkt->vm_srb.sense_info_length =
-	vstor_packet->vm_srb.sense_info_length;
-
-	if (vstor_packet->vm_srb.scsi_status != 0 ||
-		vstor_packet->vm_srb.srb_status != 1){
-		DPRINT_WARN(STORVSC,
-			    "cmd 0x%x scsi status 0x%x srb status 0x%x\n",
-			    stor_pkt->vm_srb.cdb[0],
-			    vstor_packet->vm_srb.scsi_status,
-			    vstor_packet->vm_srb.srb_status);
-	}
-
-	if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) {
-		/* CHECK_CONDITION */
-		if (vstor_packet->vm_srb.srb_status & 0x80) {
-			/* autosense data available */
-			DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data "
-				    "valid - len %d\n", request,
-				    vstor_packet->vm_srb.sense_info_length);
-
-			memcpy(request->sense_buffer,
-			       vstor_packet->vm_srb.sense_data,
-			       vstor_packet->vm_srb.sense_info_length);
-
-		}
-	}
-
-	stor_pkt->vm_srb.data_transfer_length =
-	vstor_packet->vm_srb.data_transfer_length;
-
-	request->on_io_completion(request);
-
-	if (atomic_dec_and_test(&stor_device->num_outstanding_req) &&
-		stor_device->drain_notify)
-		wake_up(&stor_device->waiting_to_drain);
-
-
-}
-
-static void storvsc_on_receive(struct hv_device *device,
-			     struct vstor_packet *vstor_packet,
-			     struct hv_storvsc_request *request)
-{
-	switch (vstor_packet->operation) {
-	case VSTOR_OPERATION_COMPLETE_IO:
-		storvsc_on_io_completion(device, vstor_packet, request);
-		break;
-	case VSTOR_OPERATION_REMOVE_DEVICE:
-
-	default:
-		break;
-	}
-}
-
-static void storvsc_on_channel_callback(void *context)
-{
-	struct hv_device *device = (struct hv_device *)context;
-	struct storvsc_device *stor_device;
-	u32 bytes_recvd;
-	u64 request_id;
-	unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)];
-	struct hv_storvsc_request *request;
-	int ret;
-
-
-	stor_device = get_in_stor_device(device);
-	if (!stor_device)
-		return;
-
-	do {
-		ret = vmbus_recvpacket(device->channel, packet,
-				       ALIGN(sizeof(struct vstor_packet), 8),
-				       &bytes_recvd, &request_id);
-		if (ret == 0 && bytes_recvd > 0) {
-
-			request = (struct hv_storvsc_request *)
-					(unsigned long)request_id;
-
-			if ((request == &stor_device->init_request) ||
-			    (request == &stor_device->reset_request)) {
-
-				memcpy(&request->vstor_packet, packet,
-				       sizeof(struct vstor_packet));
-				complete(&request->wait_event);
-			} else {
-				storvsc_on_receive(device,
-						(struct vstor_packet *)packet,
-						request);
-			}
-		} else {
-			break;
-		}
-	} while (1);
-
-	put_stor_device(device);
-	return;
-}
-
-static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
-{
-	struct vmstorage_channel_properties props;
-	int ret;
-
-	memset(&props, 0, sizeof(struct vmstorage_channel_properties));
-
-	/* Open the channel */
-	ret = vmbus_open(device->channel,
-			 ring_size,
-			 ring_size,
-			 (void *)&props,
-			 sizeof(struct vmstorage_channel_properties),
-			 storvsc_on_channel_callback, device);
-
-	if (ret != 0)
-		return ret;
-
-	ret = storvsc_channel_init(device);
-
-	return ret;
-}
-
-int storvsc_dev_add(struct hv_device *device,
-					void *additional_info)
-{
-	struct storvsc_device *stor_device;
-	struct storvsc_device_info *device_info;
-	int ret = 0;
-
-	device_info = (struct storvsc_device_info *)additional_info;
-	stor_device = alloc_stor_device(device);
-	if (!stor_device)
-		return -ENOMEM;
-
-	/* Save the channel properties to our storvsc channel */
-
-	/*
-	 * If we support more than 1 scsi channel, we need to set the
-	 * port number here to the scsi channel but how do we get the
-	 * scsi channel prior to the bus scan.
-	 *
-	 * The host does not support this.
-	 */
-
-	stor_device->port_number = device_info->port_number;
-	/* Send it back up */
-	ret = storvsc_connect_to_vsp(device, device_info->ring_buffer_size);
-	if (ret) {
-		kfree(stor_device);
-		return ret;
-	}
-	device_info->path_id = stor_device->path_id;
-	device_info->target_id = stor_device->target_id;
-
-	return ret;
-}
-
-int storvsc_dev_remove(struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	unsigned long flags;
-
-	/*
-	 * Since we currently hold a reference on the stor
-	 * device, it is safe to dereference the ext
-	 * pointer.
-	 */
-	stor_device = (struct storvsc_device *)device->ext;
-
-	stor_device->destroy = true;
-
-	/*
-	 * At this point, all outbound traffic should be disable. We
-	 * only allow inbound traffic (responses) to proceed so that
-	 * outstanding requests can be completed.
-	 */
-
-	storvsc_wait_to_drain(stor_device);
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	stor_device->ref_count = 0;
-	device->ext = NULL;
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-
-	/* Close the channel */
-	vmbus_close(device->channel);
-
-	kfree(stor_device);
-	return 0;
-}
-
-int storvsc_do_io(struct hv_device *device,
-			      struct hv_storvsc_request *request)
-{
-	struct storvsc_device *stor_device;
-	struct vstor_packet *vstor_packet;
-	int ret = 0;
-
-	vstor_packet = &request->vstor_packet;
-	stor_device = get_out_stor_device(device);
-
-	if (!stor_device)
-		return -ENODEV;
-
-
-	request->device  = device;
-
-
-	vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
-
-	vstor_packet->vm_srb.length = sizeof(struct vmscsi_request);
-
-
-	vstor_packet->vm_srb.sense_info_length = SENSE_BUFFER_SIZE;
-
-
-	vstor_packet->vm_srb.data_transfer_length =
-	request->data_buffer.len;
-
-	vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB;
-
-	if (request->data_buffer.len) {
-		ret = vmbus_sendpacket_multipagebuffer(device->channel,
-				&request->data_buffer,
-				vstor_packet,
-				sizeof(struct vstor_packet),
-				(unsigned long)request);
-	} else {
-		ret = vmbus_sendpacket(device->channel, vstor_packet,
-				       sizeof(struct vstor_packet),
-				       (unsigned long)request,
-				       VM_PKT_DATA_INBAND,
-				       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	}
-
-	if (ret != 0)
-		return ret;
-
-	atomic_inc(&stor_device->num_outstanding_req);
-
-	put_stor_device(device);
-	return ret;
-}
-
-/*
- * The channel properties uniquely specify how the device is to be
- * presented to the guest. Map this information for use by the block
- * driver. For Linux guests on Hyper-V, we emulate a scsi HBA in the guest
- * (storvsc_drv) and so scsi devices in the guest  are handled by
- * native upper level Linux drivers. Consequently, Hyper-V
- * block driver, while being a generic block driver, presently does not
- * deal with anything other than devices that would need to be presented
- * to the guest as an IDE disk.
- *
- * This function maps the channel properties as embedded in the input
- * parameter device_info onto information necessary to register the
- * corresponding block device.
- *
- * Currently, there is no way to stop the emulation of the block device
- * on the host side. And so, to prevent the native IDE drivers in Linux
- * from taking over these devices (to be managedby Hyper-V block
- * driver), we will take over if need be the major of the IDE controllers.
- *
- */
-
-int storvsc_get_major_info(struct storvsc_device_info *device_info,
-			    struct storvsc_major_info *major_info)
-{
-	static bool ide0_registered;
-	static bool ide1_registered;
-
-	/*
-	 * For now we only support IDE disks.
-	 */
-	major_info->devname = "ide";
-	major_info->diskname = "hd";
-
-	if (device_info->path_id) {
-		major_info->major = 22;
-		if (!ide1_registered) {
-			major_info->do_register = true;
-			ide1_registered = true;
-		} else
-			major_info->do_register = false;
-
-		if (device_info->target_id)
-			major_info->index = 3;
-		else
-			major_info->index = 2;
-
-		return 0;
-	} else {
-		major_info->major = 3;
-		if (!ide0_registered) {
-			major_info->do_register = true;
-			ide0_registered = true;
-		} else
-			major_info->do_register = false;
-
-		if (device_info->target_id)
-			major_info->index = 1;
-		else
-			major_info->index = 0;
-
-		return 0;
-	}
-
-	return -ENODEV;
-}
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 23334ad..f460741 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -41,6 +41,534 @@ static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
 module_param(storvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
 
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#include "hyperv.h"
+#include "hyperv_storage.h"
+
+
+static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+
+	stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL);
+	if (!stor_device)
+		return NULL;
+
+	stor_device->ref_count = 1;
+	stor_device->destroy = false;
+	stor_device->hba_owner = false;
+	init_waitqueue_head(&stor_device->waiting_to_drain);
+	stor_device->device = device;
+	device->ext = stor_device;
+
+	return stor_device;
+}
+
+static inline struct storvsc_device *get_in_stor_device(
+					struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device->ext_lock, flags);
+	stor_device = (struct storvsc_device *)device->ext;
+	if (!stor_device)
+		goto cleanup;
+
+	/*
+	 * If the device is being destroyed; allow incoming
+	 * traffic only to cleanup outstanding requests.
+	 */
+	if (stor_device->destroy &&
+		 (atomic_read(&stor_device->num_outstanding_req) == 0))
+		goto cleanup;
+	stor_device->ref_count++;
+cleanup:
+	spin_unlock_irqrestore(&device->ext_lock, flags);
+
+	return stor_device;
+}
+
+static int storvsc_channel_init(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	struct hv_storvsc_request *request;
+	struct vstor_packet *vstor_packet;
+	int ret, t;
+
+	stor_device = get_out_stor_device(device);
+	if (!stor_device)
+		return -ENODEV;
+
+	request = &stor_device->init_request;
+	vstor_packet = &request->vstor_packet;
+
+	/*
+	 * Now, initiate the vsc/vsp initialization protocol on the open
+	 * channel
+	 */
+	memset(request, 0, sizeof(struct hv_storvsc_request));
+	init_completion(&request->wait_event);
+	vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+
+	/* reuse the packet for version range supported */
+	memset(vstor_packet, 0, sizeof(struct vstor_packet));
+	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+
+	vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT;
+	FILL_VMSTOR_REVISION(vstor_packet->version.revision);
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+
+	memset(vstor_packet, 0, sizeof(struct vstor_packet));
+	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+	vstor_packet->storage_channel_properties.port_number =
+					stor_device->port_number;
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+	stor_device->path_id = vstor_packet->storage_channel_properties.path_id;
+	stor_device->target_id
+		= vstor_packet->storage_channel_properties.target_id;
+
+	memset(vstor_packet, 0, sizeof(struct vstor_packet));
+	vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+
+cleanup:
+	put_stor_device(device);
+	return ret;
+}
+
+static void storvsc_on_io_completion(struct hv_device *device,
+				  struct vstor_packet *vstor_packet,
+				  struct hv_storvsc_request *request)
+{
+	struct storvsc_device *stor_device;
+	struct vstor_packet *stor_pkt;
+
+	stor_device = (struct storvsc_device *)device->ext;
+
+	stor_pkt = &request->vstor_packet;
+
+
+	/* Copy over the status...etc */
+	stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status;
+	stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status;
+	stor_pkt->vm_srb.sense_info_length =
+	vstor_packet->vm_srb.sense_info_length;
+
+	if (vstor_packet->vm_srb.scsi_status != 0 ||
+		vstor_packet->vm_srb.srb_status != 1){
+		DPRINT_WARN(STORVSC,
+			    "cmd 0x%x scsi status 0x%x srb status 0x%x\n",
+			    stor_pkt->vm_srb.cdb[0],
+			    vstor_packet->vm_srb.scsi_status,
+			    vstor_packet->vm_srb.srb_status);
+	}
+
+	if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) {
+		/* CHECK_CONDITION */
+		if (vstor_packet->vm_srb.srb_status & 0x80) {
+			/* autosense data available */
+			DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data "
+				    "valid - len %d\n", request,
+				    vstor_packet->vm_srb.sense_info_length);
+
+			memcpy(request->sense_buffer,
+			       vstor_packet->vm_srb.sense_data,
+			       vstor_packet->vm_srb.sense_info_length);
+
+		}
+	}
+
+	stor_pkt->vm_srb.data_transfer_length =
+	vstor_packet->vm_srb.data_transfer_length;
+
+	request->on_io_completion(request);
+
+	if (atomic_dec_and_test(&stor_device->num_outstanding_req) &&
+		stor_device->drain_notify)
+		wake_up(&stor_device->waiting_to_drain);
+
+
+}
+
+static void storvsc_on_receive(struct hv_device *device,
+			     struct vstor_packet *vstor_packet,
+			     struct hv_storvsc_request *request)
+{
+	switch (vstor_packet->operation) {
+	case VSTOR_OPERATION_COMPLETE_IO:
+		storvsc_on_io_completion(device, vstor_packet, request);
+		break;
+	case VSTOR_OPERATION_REMOVE_DEVICE:
+
+	default:
+		break;
+	}
+}
+
+static void storvsc_on_channel_callback(void *context)
+{
+	struct hv_device *device = (struct hv_device *)context;
+	struct storvsc_device *stor_device;
+	u32 bytes_recvd;
+	u64 request_id;
+	unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)];
+	struct hv_storvsc_request *request;
+	int ret;
+
+
+	stor_device = get_in_stor_device(device);
+	if (!stor_device)
+		return;
+
+	do {
+		ret = vmbus_recvpacket(device->channel, packet,
+				       ALIGN(sizeof(struct vstor_packet), 8),
+				       &bytes_recvd, &request_id);
+		if (ret == 0 && bytes_recvd > 0) {
+
+			request = (struct hv_storvsc_request *)
+					(unsigned long)request_id;
+
+			if ((request == &stor_device->init_request) ||
+			    (request == &stor_device->reset_request)) {
+
+				memcpy(&request->vstor_packet, packet,
+				       sizeof(struct vstor_packet));
+				complete(&request->wait_event);
+			} else {
+				storvsc_on_receive(device,
+						(struct vstor_packet *)packet,
+						request);
+			}
+		} else {
+			break;
+		}
+	} while (1);
+
+	put_stor_device(device);
+	return;
+}
+
+static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
+{
+	struct vmstorage_channel_properties props;
+	int ret;
+
+	memset(&props, 0, sizeof(struct vmstorage_channel_properties));
+
+	/* Open the channel */
+	ret = vmbus_open(device->channel,
+			 ring_size,
+			 ring_size,
+			 (void *)&props,
+			 sizeof(struct vmstorage_channel_properties),
+			 storvsc_on_channel_callback, device);
+
+	if (ret != 0)
+		return ret;
+
+	ret = storvsc_channel_init(device);
+
+	return ret;
+}
+
+int storvsc_dev_add(struct hv_device *device,
+					void *additional_info)
+{
+	struct storvsc_device *stor_device;
+	struct storvsc_device_info *device_info;
+	int ret = 0;
+
+	device_info = (struct storvsc_device_info *)additional_info;
+	stor_device = alloc_stor_device(device);
+	if (!stor_device)
+		return -ENOMEM;
+
+	/* Save the channel properties to our storvsc channel */
+
+	/*
+	 * If we support more than 1 scsi channel, we need to set the
+	 * port number here to the scsi channel but how do we get the
+	 * scsi channel prior to the bus scan.
+	 *
+	 * The host does not support this.
+	 */
+
+	stor_device->port_number = device_info->port_number;
+	/* Send it back up */
+	ret = storvsc_connect_to_vsp(device, device_info->ring_buffer_size);
+	if (ret) {
+		kfree(stor_device);
+		return ret;
+	}
+	device_info->path_id = stor_device->path_id;
+	device_info->target_id = stor_device->target_id;
+
+	return ret;
+}
+
+int storvsc_dev_remove(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	unsigned long flags;
+
+	/*
+	 * Since we currently hold a reference on the stor
+	 * device, it is safe to dereference the ext
+	 * pointer.
+	 */
+	stor_device = (struct storvsc_device *)device->ext;
+
+	stor_device->destroy = true;
+
+	/*
+	 * At this point, all outbound traffic should be disable. We
+	 * only allow inbound traffic (responses) to proceed so that
+	 * outstanding requests can be completed.
+	 */
+
+	storvsc_wait_to_drain(stor_device);
+
+	spin_lock_irqsave(&device->ext_lock, flags);
+	stor_device->ref_count = 0;
+	device->ext = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
+
+	/* Close the channel */
+	vmbus_close(device->channel);
+
+	kfree(stor_device);
+	return 0;
+}
+
+int storvsc_do_io(struct hv_device *device,
+			      struct hv_storvsc_request *request)
+{
+	struct storvsc_device *stor_device;
+	struct vstor_packet *vstor_packet;
+	int ret = 0;
+
+	vstor_packet = &request->vstor_packet;
+	stor_device = get_out_stor_device(device);
+
+	if (!stor_device)
+		return -ENODEV;
+
+
+	request->device  = device;
+
+
+	vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
+
+	vstor_packet->vm_srb.length = sizeof(struct vmscsi_request);
+
+
+	vstor_packet->vm_srb.sense_info_length = SENSE_BUFFER_SIZE;
+
+
+	vstor_packet->vm_srb.data_transfer_length =
+	request->data_buffer.len;
+
+	vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB;
+
+	if (request->data_buffer.len) {
+		ret = vmbus_sendpacket_multipagebuffer(device->channel,
+				&request->data_buffer,
+				vstor_packet,
+				sizeof(struct vstor_packet),
+				(unsigned long)request);
+	} else {
+		ret =
+		vmbus_sendpacket(device->channel, vstor_packet,
+		       sizeof(struct vstor_packet),
+		       (unsigned long)request,
+		       VM_PKT_DATA_INBAND,
+		       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	}
+
+	if (ret != 0)
+		return ret;
+
+	atomic_inc(&stor_device->num_outstanding_req);
+
+	put_stor_device(device);
+	return ret;
+}
+
+/*
+ * The channel properties uniquely specify how the device is to be
+ * presented to the guest. Map this information for use by the block
+ * driver. For Linux guests on Hyper-V, we emulate a scsi HBA in the guest
+ * (storvsc_drv) and so scsi devices in the guest  are handled by
+ * native upper level Linux drivers. Consequently, Hyper-V
+ * block driver, while being a generic block driver, presently does not
+ * deal with anything other than devices that would need to be presented
+ * to the guest as an IDE disk.
+ *
+ * This function maps the channel properties as embedded in the input
+ * parameter device_info onto information necessary to register the
+ * corresponding block device.
+ *
+ * Currently, there is no way to stop the emulation of the block device
+ * on the host side. And so, to prevent the native IDE drivers in Linux
+ * from taking over these devices (to be managedby Hyper-V block
+ * driver), we will take over if need be the major of the IDE controllers.
+ *
+ */
+
+int storvsc_get_major_info(struct storvsc_device_info *device_info,
+			    struct storvsc_major_info *major_info)
+{
+	static bool ide0_registered;
+	static bool ide1_registered;
+
+	/*
+	 * For now we only support IDE disks.
+	 */
+	major_info->devname = "ide";
+	major_info->diskname = "hd";
+
+	if (device_info->path_id) {
+		major_info->major = 22;
+		if (!ide1_registered) {
+			major_info->do_register = true;
+			ide1_registered = true;
+		} else
+			major_info->do_register = false;
+
+		if (device_info->target_id)
+			major_info->index = 3;
+		else
+			major_info->index = 2;
+
+		return 0;
+	} else {
+		major_info->major = 3;
+		if (!ide0_registered) {
+			major_info->do_register = true;
+			ide0_registered = true;
+		} else
+			major_info->do_register = false;
+
+		if (device_info->target_id)
+			major_info->index = 1;
+		else
+			major_info->index = 0;
+
+		return 0;
+	}
+
+	return -ENODEV;
+}
 static const char *driver_name = "storvsc";
 
 struct hv_host_device {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 32/40] Staging: hv: storvsc: Include storvsc.c in storvsc_drv.c
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

As part of further cleanup of our storage drivers, include the content
of storvsc.c into storvsc_drv.c.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/Makefile      |    2 +-
 drivers/staging/hv/storvsc.c     |  527 -------------------------------------
 drivers/staging/hv/storvsc_drv.c |  528 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 529 insertions(+), 528 deletions(-)
 delete mode 100644 drivers/staging/hv/storvsc.c

diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
index bb89437..bd176b1 100644
--- a/drivers/staging/hv/Makefile
+++ b/drivers/staging/hv/Makefile
@@ -7,6 +7,6 @@ obj-$(CONFIG_HYPERV_MOUSE)	+= hv_mouse.o
 hv_vmbus-y := vmbus_drv.o \
 		 hv.o connection.o channel.o \
 		 channel_mgmt.o ring_buffer.o
-hv_storvsc-y := storvsc_drv.o storvsc.o
+hv_storvsc-y := storvsc_drv.o
 hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o
 hv_utils-y := hv_util.o hv_kvp.o
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
deleted file mode 100644
index c06f750..0000000
--- a/drivers/staging/hv/storvsc.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *   K. Y. Srinivasan <kys@microsoft.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/completion.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#include "hyperv.h"
-#include "hyperv_storage.h"
-
-
-static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-
-	stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL);
-	if (!stor_device)
-		return NULL;
-
-	stor_device->ref_count = 1;
-	stor_device->destroy = false;
-	stor_device->hba_owner = false;
-	init_waitqueue_head(&stor_device->waiting_to_drain);
-	stor_device->device = device;
-	device->ext = stor_device;
-
-	return stor_device;
-}
-
-static inline struct storvsc_device *get_in_stor_device(
-					struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	unsigned long flags;
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	stor_device = (struct storvsc_device *)device->ext;
-	if (!stor_device)
-		goto cleanup;
-
-	/*
-	 * If the device is being destroyed; allow incoming
-	 * traffic only to cleanup outstanding requests.
-	 */
-	if (stor_device->destroy &&
-		 (atomic_read(&stor_device->num_outstanding_req) == 0))
-		goto cleanup;
-	stor_device->ref_count++;
-cleanup:
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-
-	return stor_device;
-}
-
-static int storvsc_channel_init(struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	struct hv_storvsc_request *request;
-	struct vstor_packet *vstor_packet;
-	int ret, t;
-
-	stor_device = get_out_stor_device(device);
-	if (!stor_device)
-		return -ENODEV;
-
-	request = &stor_device->init_request;
-	vstor_packet = &request->vstor_packet;
-
-	/*
-	 * Now, initiate the vsc/vsp initialization protocol on the open
-	 * channel
-	 */
-	memset(request, 0, sizeof(struct hv_storvsc_request));
-	init_completion(&request->wait_event);
-	vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
-	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
-
-	ret = vmbus_sendpacket(device->channel, vstor_packet,
-			       sizeof(struct vstor_packet),
-			       (unsigned long)request,
-			       VM_PKT_DATA_INBAND,
-			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	if (ret != 0)
-		goto cleanup;
-
-	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
-	if (t == 0) {
-		ret = -ETIMEDOUT;
-		goto cleanup;
-	}
-
-	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
-	    vstor_packet->status != 0)
-		goto cleanup;
-
-
-	/* reuse the packet for version range supported */
-	memset(vstor_packet, 0, sizeof(struct vstor_packet));
-	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
-	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
-
-	vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT;
-	FILL_VMSTOR_REVISION(vstor_packet->version.revision);
-
-	ret = vmbus_sendpacket(device->channel, vstor_packet,
-			       sizeof(struct vstor_packet),
-			       (unsigned long)request,
-			       VM_PKT_DATA_INBAND,
-			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	if (ret != 0)
-		goto cleanup;
-
-	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
-	if (t == 0) {
-		ret = -ETIMEDOUT;
-		goto cleanup;
-	}
-
-	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
-	    vstor_packet->status != 0)
-		goto cleanup;
-
-
-	memset(vstor_packet, 0, sizeof(struct vstor_packet));
-	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
-	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
-	vstor_packet->storage_channel_properties.port_number =
-					stor_device->port_number;
-
-	ret = vmbus_sendpacket(device->channel, vstor_packet,
-			       sizeof(struct vstor_packet),
-			       (unsigned long)request,
-			       VM_PKT_DATA_INBAND,
-			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
-	if (ret != 0)
-		goto cleanup;
-
-	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
-	if (t == 0) {
-		ret = -ETIMEDOUT;
-		goto cleanup;
-	}
-
-	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
-	    vstor_packet->status != 0)
-		goto cleanup;
-
-	stor_device->path_id = vstor_packet->storage_channel_properties.path_id;
-	stor_device->target_id
-		= vstor_packet->storage_channel_properties.target_id;
-
-	memset(vstor_packet, 0, sizeof(struct vstor_packet));
-	vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
-	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
-
-	ret = vmbus_sendpacket(device->channel, vstor_packet,
-			       sizeof(struct vstor_packet),
-			       (unsigned long)request,
-			       VM_PKT_DATA_INBAND,
-			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
-	if (ret != 0)
-		goto cleanup;
-
-	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
-	if (t == 0) {
-		ret = -ETIMEDOUT;
-		goto cleanup;
-	}
-
-	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
-	    vstor_packet->status != 0)
-		goto cleanup;
-
-
-cleanup:
-	put_stor_device(device);
-	return ret;
-}
-
-static void storvsc_on_io_completion(struct hv_device *device,
-				  struct vstor_packet *vstor_packet,
-				  struct hv_storvsc_request *request)
-{
-	struct storvsc_device *stor_device;
-	struct vstor_packet *stor_pkt;
-
-	stor_device = (struct storvsc_device *)device->ext;
-
-	stor_pkt = &request->vstor_packet;
-
-
-	/* Copy over the status...etc */
-	stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status;
-	stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status;
-	stor_pkt->vm_srb.sense_info_length =
-	vstor_packet->vm_srb.sense_info_length;
-
-	if (vstor_packet->vm_srb.scsi_status != 0 ||
-		vstor_packet->vm_srb.srb_status != 1){
-		DPRINT_WARN(STORVSC,
-			    "cmd 0x%x scsi status 0x%x srb status 0x%x\n",
-			    stor_pkt->vm_srb.cdb[0],
-			    vstor_packet->vm_srb.scsi_status,
-			    vstor_packet->vm_srb.srb_status);
-	}
-
-	if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) {
-		/* CHECK_CONDITION */
-		if (vstor_packet->vm_srb.srb_status & 0x80) {
-			/* autosense data available */
-			DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data "
-				    "valid - len %d\n", request,
-				    vstor_packet->vm_srb.sense_info_length);
-
-			memcpy(request->sense_buffer,
-			       vstor_packet->vm_srb.sense_data,
-			       vstor_packet->vm_srb.sense_info_length);
-
-		}
-	}
-
-	stor_pkt->vm_srb.data_transfer_length =
-	vstor_packet->vm_srb.data_transfer_length;
-
-	request->on_io_completion(request);
-
-	if (atomic_dec_and_test(&stor_device->num_outstanding_req) &&
-		stor_device->drain_notify)
-		wake_up(&stor_device->waiting_to_drain);
-
-
-}
-
-static void storvsc_on_receive(struct hv_device *device,
-			     struct vstor_packet *vstor_packet,
-			     struct hv_storvsc_request *request)
-{
-	switch (vstor_packet->operation) {
-	case VSTOR_OPERATION_COMPLETE_IO:
-		storvsc_on_io_completion(device, vstor_packet, request);
-		break;
-	case VSTOR_OPERATION_REMOVE_DEVICE:
-
-	default:
-		break;
-	}
-}
-
-static void storvsc_on_channel_callback(void *context)
-{
-	struct hv_device *device = (struct hv_device *)context;
-	struct storvsc_device *stor_device;
-	u32 bytes_recvd;
-	u64 request_id;
-	unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)];
-	struct hv_storvsc_request *request;
-	int ret;
-
-
-	stor_device = get_in_stor_device(device);
-	if (!stor_device)
-		return;
-
-	do {
-		ret = vmbus_recvpacket(device->channel, packet,
-				       ALIGN(sizeof(struct vstor_packet), 8),
-				       &bytes_recvd, &request_id);
-		if (ret == 0 && bytes_recvd > 0) {
-
-			request = (struct hv_storvsc_request *)
-					(unsigned long)request_id;
-
-			if ((request == &stor_device->init_request) ||
-			    (request == &stor_device->reset_request)) {
-
-				memcpy(&request->vstor_packet, packet,
-				       sizeof(struct vstor_packet));
-				complete(&request->wait_event);
-			} else {
-				storvsc_on_receive(device,
-						(struct vstor_packet *)packet,
-						request);
-			}
-		} else {
-			break;
-		}
-	} while (1);
-
-	put_stor_device(device);
-	return;
-}
-
-static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
-{
-	struct vmstorage_channel_properties props;
-	int ret;
-
-	memset(&props, 0, sizeof(struct vmstorage_channel_properties));
-
-	/* Open the channel */
-	ret = vmbus_open(device->channel,
-			 ring_size,
-			 ring_size,
-			 (void *)&props,
-			 sizeof(struct vmstorage_channel_properties),
-			 storvsc_on_channel_callback, device);
-
-	if (ret != 0)
-		return ret;
-
-	ret = storvsc_channel_init(device);
-
-	return ret;
-}
-
-int storvsc_dev_add(struct hv_device *device,
-					void *additional_info)
-{
-	struct storvsc_device *stor_device;
-	struct storvsc_device_info *device_info;
-	int ret = 0;
-
-	device_info = (struct storvsc_device_info *)additional_info;
-	stor_device = alloc_stor_device(device);
-	if (!stor_device)
-		return -ENOMEM;
-
-	/* Save the channel properties to our storvsc channel */
-
-	/*
-	 * If we support more than 1 scsi channel, we need to set the
-	 * port number here to the scsi channel but how do we get the
-	 * scsi channel prior to the bus scan.
-	 *
-	 * The host does not support this.
-	 */
-
-	stor_device->port_number = device_info->port_number;
-	/* Send it back up */
-	ret = storvsc_connect_to_vsp(device, device_info->ring_buffer_size);
-	if (ret) {
-		kfree(stor_device);
-		return ret;
-	}
-	device_info->path_id = stor_device->path_id;
-	device_info->target_id = stor_device->target_id;
-
-	return ret;
-}
-
-int storvsc_dev_remove(struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	unsigned long flags;
-
-	/*
-	 * Since we currently hold a reference on the stor
-	 * device, it is safe to dereference the ext
-	 * pointer.
-	 */
-	stor_device = (struct storvsc_device *)device->ext;
-
-	stor_device->destroy = true;
-
-	/*
-	 * At this point, all outbound traffic should be disable. We
-	 * only allow inbound traffic (responses) to proceed so that
-	 * outstanding requests can be completed.
-	 */
-
-	storvsc_wait_to_drain(stor_device);
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	stor_device->ref_count = 0;
-	device->ext = NULL;
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-
-	/* Close the channel */
-	vmbus_close(device->channel);
-
-	kfree(stor_device);
-	return 0;
-}
-
-int storvsc_do_io(struct hv_device *device,
-			      struct hv_storvsc_request *request)
-{
-	struct storvsc_device *stor_device;
-	struct vstor_packet *vstor_packet;
-	int ret = 0;
-
-	vstor_packet = &request->vstor_packet;
-	stor_device = get_out_stor_device(device);
-
-	if (!stor_device)
-		return -ENODEV;
-
-
-	request->device  = device;
-
-
-	vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
-
-	vstor_packet->vm_srb.length = sizeof(struct vmscsi_request);
-
-
-	vstor_packet->vm_srb.sense_info_length = SENSE_BUFFER_SIZE;
-
-
-	vstor_packet->vm_srb.data_transfer_length =
-	request->data_buffer.len;
-
-	vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB;
-
-	if (request->data_buffer.len) {
-		ret = vmbus_sendpacket_multipagebuffer(device->channel,
-				&request->data_buffer,
-				vstor_packet,
-				sizeof(struct vstor_packet),
-				(unsigned long)request);
-	} else {
-		ret = vmbus_sendpacket(device->channel, vstor_packet,
-				       sizeof(struct vstor_packet),
-				       (unsigned long)request,
-				       VM_PKT_DATA_INBAND,
-				       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	}
-
-	if (ret != 0)
-		return ret;
-
-	atomic_inc(&stor_device->num_outstanding_req);
-
-	put_stor_device(device);
-	return ret;
-}
-
-/*
- * The channel properties uniquely specify how the device is to be
- * presented to the guest. Map this information for use by the block
- * driver. For Linux guests on Hyper-V, we emulate a scsi HBA in the guest
- * (storvsc_drv) and so scsi devices in the guest  are handled by
- * native upper level Linux drivers. Consequently, Hyper-V
- * block driver, while being a generic block driver, presently does not
- * deal with anything other than devices that would need to be presented
- * to the guest as an IDE disk.
- *
- * This function maps the channel properties as embedded in the input
- * parameter device_info onto information necessary to register the
- * corresponding block device.
- *
- * Currently, there is no way to stop the emulation of the block device
- * on the host side. And so, to prevent the native IDE drivers in Linux
- * from taking over these devices (to be managedby Hyper-V block
- * driver), we will take over if need be the major of the IDE controllers.
- *
- */
-
-int storvsc_get_major_info(struct storvsc_device_info *device_info,
-			    struct storvsc_major_info *major_info)
-{
-	static bool ide0_registered;
-	static bool ide1_registered;
-
-	/*
-	 * For now we only support IDE disks.
-	 */
-	major_info->devname = "ide";
-	major_info->diskname = "hd";
-
-	if (device_info->path_id) {
-		major_info->major = 22;
-		if (!ide1_registered) {
-			major_info->do_register = true;
-			ide1_registered = true;
-		} else
-			major_info->do_register = false;
-
-		if (device_info->target_id)
-			major_info->index = 3;
-		else
-			major_info->index = 2;
-
-		return 0;
-	} else {
-		major_info->major = 3;
-		if (!ide0_registered) {
-			major_info->do_register = true;
-			ide0_registered = true;
-		} else
-			major_info->do_register = false;
-
-		if (device_info->target_id)
-			major_info->index = 1;
-		else
-			major_info->index = 0;
-
-		return 0;
-	}
-
-	return -ENODEV;
-}
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 23334ad..f460741 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -41,6 +41,534 @@ static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
 module_param(storvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
 
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#include "hyperv.h"
+#include "hyperv_storage.h"
+
+
+static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+
+	stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL);
+	if (!stor_device)
+		return NULL;
+
+	stor_device->ref_count = 1;
+	stor_device->destroy = false;
+	stor_device->hba_owner = false;
+	init_waitqueue_head(&stor_device->waiting_to_drain);
+	stor_device->device = device;
+	device->ext = stor_device;
+
+	return stor_device;
+}
+
+static inline struct storvsc_device *get_in_stor_device(
+					struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device->ext_lock, flags);
+	stor_device = (struct storvsc_device *)device->ext;
+	if (!stor_device)
+		goto cleanup;
+
+	/*
+	 * If the device is being destroyed; allow incoming
+	 * traffic only to cleanup outstanding requests.
+	 */
+	if (stor_device->destroy &&
+		 (atomic_read(&stor_device->num_outstanding_req) == 0))
+		goto cleanup;
+	stor_device->ref_count++;
+cleanup:
+	spin_unlock_irqrestore(&device->ext_lock, flags);
+
+	return stor_device;
+}
+
+static int storvsc_channel_init(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	struct hv_storvsc_request *request;
+	struct vstor_packet *vstor_packet;
+	int ret, t;
+
+	stor_device = get_out_stor_device(device);
+	if (!stor_device)
+		return -ENODEV;
+
+	request = &stor_device->init_request;
+	vstor_packet = &request->vstor_packet;
+
+	/*
+	 * Now, initiate the vsc/vsp initialization protocol on the open
+	 * channel
+	 */
+	memset(request, 0, sizeof(struct hv_storvsc_request));
+	init_completion(&request->wait_event);
+	vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+
+	/* reuse the packet for version range supported */
+	memset(vstor_packet, 0, sizeof(struct vstor_packet));
+	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+
+	vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT;
+	FILL_VMSTOR_REVISION(vstor_packet->version.revision);
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+
+	memset(vstor_packet, 0, sizeof(struct vstor_packet));
+	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+	vstor_packet->storage_channel_properties.port_number =
+					stor_device->port_number;
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+	stor_device->path_id = vstor_packet->storage_channel_properties.path_id;
+	stor_device->target_id
+		= vstor_packet->storage_channel_properties.target_id;
+
+	memset(vstor_packet, 0, sizeof(struct vstor_packet));
+	vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+
+cleanup:
+	put_stor_device(device);
+	return ret;
+}
+
+static void storvsc_on_io_completion(struct hv_device *device,
+				  struct vstor_packet *vstor_packet,
+				  struct hv_storvsc_request *request)
+{
+	struct storvsc_device *stor_device;
+	struct vstor_packet *stor_pkt;
+
+	stor_device = (struct storvsc_device *)device->ext;
+
+	stor_pkt = &request->vstor_packet;
+
+
+	/* Copy over the status...etc */
+	stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status;
+	stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status;
+	stor_pkt->vm_srb.sense_info_length =
+	vstor_packet->vm_srb.sense_info_length;
+
+	if (vstor_packet->vm_srb.scsi_status != 0 ||
+		vstor_packet->vm_srb.srb_status != 1){
+		DPRINT_WARN(STORVSC,
+			    "cmd 0x%x scsi status 0x%x srb status 0x%x\n",
+			    stor_pkt->vm_srb.cdb[0],
+			    vstor_packet->vm_srb.scsi_status,
+			    vstor_packet->vm_srb.srb_status);
+	}
+
+	if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) {
+		/* CHECK_CONDITION */
+		if (vstor_packet->vm_srb.srb_status & 0x80) {
+			/* autosense data available */
+			DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data "
+				    "valid - len %d\n", request,
+				    vstor_packet->vm_srb.sense_info_length);
+
+			memcpy(request->sense_buffer,
+			       vstor_packet->vm_srb.sense_data,
+			       vstor_packet->vm_srb.sense_info_length);
+
+		}
+	}
+
+	stor_pkt->vm_srb.data_transfer_length =
+	vstor_packet->vm_srb.data_transfer_length;
+
+	request->on_io_completion(request);
+
+	if (atomic_dec_and_test(&stor_device->num_outstanding_req) &&
+		stor_device->drain_notify)
+		wake_up(&stor_device->waiting_to_drain);
+
+
+}
+
+static void storvsc_on_receive(struct hv_device *device,
+			     struct vstor_packet *vstor_packet,
+			     struct hv_storvsc_request *request)
+{
+	switch (vstor_packet->operation) {
+	case VSTOR_OPERATION_COMPLETE_IO:
+		storvsc_on_io_completion(device, vstor_packet, request);
+		break;
+	case VSTOR_OPERATION_REMOVE_DEVICE:
+
+	default:
+		break;
+	}
+}
+
+static void storvsc_on_channel_callback(void *context)
+{
+	struct hv_device *device = (struct hv_device *)context;
+	struct storvsc_device *stor_device;
+	u32 bytes_recvd;
+	u64 request_id;
+	unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)];
+	struct hv_storvsc_request *request;
+	int ret;
+
+
+	stor_device = get_in_stor_device(device);
+	if (!stor_device)
+		return;
+
+	do {
+		ret = vmbus_recvpacket(device->channel, packet,
+				       ALIGN(sizeof(struct vstor_packet), 8),
+				       &bytes_recvd, &request_id);
+		if (ret == 0 && bytes_recvd > 0) {
+
+			request = (struct hv_storvsc_request *)
+					(unsigned long)request_id;
+
+			if ((request == &stor_device->init_request) ||
+			    (request == &stor_device->reset_request)) {
+
+				memcpy(&request->vstor_packet, packet,
+				       sizeof(struct vstor_packet));
+				complete(&request->wait_event);
+			} else {
+				storvsc_on_receive(device,
+						(struct vstor_packet *)packet,
+						request);
+			}
+		} else {
+			break;
+		}
+	} while (1);
+
+	put_stor_device(device);
+	return;
+}
+
+static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
+{
+	struct vmstorage_channel_properties props;
+	int ret;
+
+	memset(&props, 0, sizeof(struct vmstorage_channel_properties));
+
+	/* Open the channel */
+	ret = vmbus_open(device->channel,
+			 ring_size,
+			 ring_size,
+			 (void *)&props,
+			 sizeof(struct vmstorage_channel_properties),
+			 storvsc_on_channel_callback, device);
+
+	if (ret != 0)
+		return ret;
+
+	ret = storvsc_channel_init(device);
+
+	return ret;
+}
+
+int storvsc_dev_add(struct hv_device *device,
+					void *additional_info)
+{
+	struct storvsc_device *stor_device;
+	struct storvsc_device_info *device_info;
+	int ret = 0;
+
+	device_info = (struct storvsc_device_info *)additional_info;
+	stor_device = alloc_stor_device(device);
+	if (!stor_device)
+		return -ENOMEM;
+
+	/* Save the channel properties to our storvsc channel */
+
+	/*
+	 * If we support more than 1 scsi channel, we need to set the
+	 * port number here to the scsi channel but how do we get the
+	 * scsi channel prior to the bus scan.
+	 *
+	 * The host does not support this.
+	 */
+
+	stor_device->port_number = device_info->port_number;
+	/* Send it back up */
+	ret = storvsc_connect_to_vsp(device, device_info->ring_buffer_size);
+	if (ret) {
+		kfree(stor_device);
+		return ret;
+	}
+	device_info->path_id = stor_device->path_id;
+	device_info->target_id = stor_device->target_id;
+
+	return ret;
+}
+
+int storvsc_dev_remove(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	unsigned long flags;
+
+	/*
+	 * Since we currently hold a reference on the stor
+	 * device, it is safe to dereference the ext
+	 * pointer.
+	 */
+	stor_device = (struct storvsc_device *)device->ext;
+
+	stor_device->destroy = true;
+
+	/*
+	 * At this point, all outbound traffic should be disable. We
+	 * only allow inbound traffic (responses) to proceed so that
+	 * outstanding requests can be completed.
+	 */
+
+	storvsc_wait_to_drain(stor_device);
+
+	spin_lock_irqsave(&device->ext_lock, flags);
+	stor_device->ref_count = 0;
+	device->ext = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
+
+	/* Close the channel */
+	vmbus_close(device->channel);
+
+	kfree(stor_device);
+	return 0;
+}
+
+int storvsc_do_io(struct hv_device *device,
+			      struct hv_storvsc_request *request)
+{
+	struct storvsc_device *stor_device;
+	struct vstor_packet *vstor_packet;
+	int ret = 0;
+
+	vstor_packet = &request->vstor_packet;
+	stor_device = get_out_stor_device(device);
+
+	if (!stor_device)
+		return -ENODEV;
+
+
+	request->device  = device;
+
+
+	vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
+
+	vstor_packet->vm_srb.length = sizeof(struct vmscsi_request);
+
+
+	vstor_packet->vm_srb.sense_info_length = SENSE_BUFFER_SIZE;
+
+
+	vstor_packet->vm_srb.data_transfer_length =
+	request->data_buffer.len;
+
+	vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB;
+
+	if (request->data_buffer.len) {
+		ret = vmbus_sendpacket_multipagebuffer(device->channel,
+				&request->data_buffer,
+				vstor_packet,
+				sizeof(struct vstor_packet),
+				(unsigned long)request);
+	} else {
+		ret =
+		vmbus_sendpacket(device->channel, vstor_packet,
+		       sizeof(struct vstor_packet),
+		       (unsigned long)request,
+		       VM_PKT_DATA_INBAND,
+		       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	}
+
+	if (ret != 0)
+		return ret;
+
+	atomic_inc(&stor_device->num_outstanding_req);
+
+	put_stor_device(device);
+	return ret;
+}
+
+/*
+ * The channel properties uniquely specify how the device is to be
+ * presented to the guest. Map this information for use by the block
+ * driver. For Linux guests on Hyper-V, we emulate a scsi HBA in the guest
+ * (storvsc_drv) and so scsi devices in the guest  are handled by
+ * native upper level Linux drivers. Consequently, Hyper-V
+ * block driver, while being a generic block driver, presently does not
+ * deal with anything other than devices that would need to be presented
+ * to the guest as an IDE disk.
+ *
+ * This function maps the channel properties as embedded in the input
+ * parameter device_info onto information necessary to register the
+ * corresponding block device.
+ *
+ * Currently, there is no way to stop the emulation of the block device
+ * on the host side. And so, to prevent the native IDE drivers in Linux
+ * from taking over these devices (to be managedby Hyper-V block
+ * driver), we will take over if need be the major of the IDE controllers.
+ *
+ */
+
+int storvsc_get_major_info(struct storvsc_device_info *device_info,
+			    struct storvsc_major_info *major_info)
+{
+	static bool ide0_registered;
+	static bool ide1_registered;
+
+	/*
+	 * For now we only support IDE disks.
+	 */
+	major_info->devname = "ide";
+	major_info->diskname = "hd";
+
+	if (device_info->path_id) {
+		major_info->major = 22;
+		if (!ide1_registered) {
+			major_info->do_register = true;
+			ide1_registered = true;
+		} else
+			major_info->do_register = false;
+
+		if (device_info->target_id)
+			major_info->index = 3;
+		else
+			major_info->index = 2;
+
+		return 0;
+	} else {
+		major_info->major = 3;
+		if (!ide0_registered) {
+			major_info->do_register = true;
+			ide0_registered = true;
+		} else
+			major_info->do_register = false;
+
+		if (device_info->target_id)
+			major_info->index = 1;
+		else
+			major_info->index = 0;
+
+		return 0;
+	}
+
+	return -ENODEV;
+}
 static const char *driver_name = "storvsc";
 
 struct hv_host_device {
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 33/40] Staging: hv: storvsc: Cleanup storvsc_drv.c after adding the contents of storvsc.c
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Now, cleanup storvsc_drv.c after adding the contents of storvsc.c

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |  105 +++-----------------------------------
 1 files changed, 7 insertions(+), 98 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index f460741..0702dc0 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -19,8 +19,15 @@
  *   Hank Janssen  <hjanssen@microsoft.com>
  *   K. Y. Srinivasan <kys@microsoft.com>
  */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/string.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/blkdev.h>
@@ -41,39 +48,6 @@ static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
 module_param(storvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
 
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *   K. Y. Srinivasan <kys@microsoft.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/completion.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#include "hyperv.h"
-#include "hyperv_storage.h"
-
 
 static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 {
@@ -504,71 +478,6 @@ int storvsc_do_io(struct hv_device *device,
 	return ret;
 }
 
-/*
- * The channel properties uniquely specify how the device is to be
- * presented to the guest. Map this information for use by the block
- * driver. For Linux guests on Hyper-V, we emulate a scsi HBA in the guest
- * (storvsc_drv) and so scsi devices in the guest  are handled by
- * native upper level Linux drivers. Consequently, Hyper-V
- * block driver, while being a generic block driver, presently does not
- * deal with anything other than devices that would need to be presented
- * to the guest as an IDE disk.
- *
- * This function maps the channel properties as embedded in the input
- * parameter device_info onto information necessary to register the
- * corresponding block device.
- *
- * Currently, there is no way to stop the emulation of the block device
- * on the host side. And so, to prevent the native IDE drivers in Linux
- * from taking over these devices (to be managedby Hyper-V block
- * driver), we will take over if need be the major of the IDE controllers.
- *
- */
-
-int storvsc_get_major_info(struct storvsc_device_info *device_info,
-			    struct storvsc_major_info *major_info)
-{
-	static bool ide0_registered;
-	static bool ide1_registered;
-
-	/*
-	 * For now we only support IDE disks.
-	 */
-	major_info->devname = "ide";
-	major_info->diskname = "hd";
-
-	if (device_info->path_id) {
-		major_info->major = 22;
-		if (!ide1_registered) {
-			major_info->do_register = true;
-			ide1_registered = true;
-		} else
-			major_info->do_register = false;
-
-		if (device_info->target_id)
-			major_info->index = 3;
-		else
-			major_info->index = 2;
-
-		return 0;
-	} else {
-		major_info->major = 3;
-		if (!ide0_registered) {
-			major_info->do_register = true;
-			ide0_registered = true;
-		} else
-			major_info->do_register = false;
-
-		if (device_info->target_id)
-			major_info->index = 1;
-		else
-			major_info->index = 0;
-
-		return 0;
-	}
-
-	return -ENODEV;
-}
 static const char *driver_name = "storvsc";
 
 struct hv_host_device {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 33/40] Staging: hv: storvsc: Cleanup storvsc_drv.c after adding the contents of storvsc.c
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Now, cleanup storvsc_drv.c after adding the contents of storvsc.c

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |  105 +++-----------------------------------
 1 files changed, 7 insertions(+), 98 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index f460741..0702dc0 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -19,8 +19,15 @@
  *   Hank Janssen  <hjanssen@microsoft.com>
  *   K. Y. Srinivasan <kys@microsoft.com>
  */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/string.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/blkdev.h>
@@ -41,39 +48,6 @@ static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
 module_param(storvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
 
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *   K. Y. Srinivasan <kys@microsoft.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/completion.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#include "hyperv.h"
-#include "hyperv_storage.h"
-
 
 static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 {
@@ -504,71 +478,6 @@ int storvsc_do_io(struct hv_device *device,
 	return ret;
 }
 
-/*
- * The channel properties uniquely specify how the device is to be
- * presented to the guest. Map this information for use by the block
- * driver. For Linux guests on Hyper-V, we emulate a scsi HBA in the guest
- * (storvsc_drv) and so scsi devices in the guest  are handled by
- * native upper level Linux drivers. Consequently, Hyper-V
- * block driver, while being a generic block driver, presently does not
- * deal with anything other than devices that would need to be presented
- * to the guest as an IDE disk.
- *
- * This function maps the channel properties as embedded in the input
- * parameter device_info onto information necessary to register the
- * corresponding block device.
- *
- * Currently, there is no way to stop the emulation of the block device
- * on the host side. And so, to prevent the native IDE drivers in Linux
- * from taking over these devices (to be managedby Hyper-V block
- * driver), we will take over if need be the major of the IDE controllers.
- *
- */
-
-int storvsc_get_major_info(struct storvsc_device_info *device_info,
-			    struct storvsc_major_info *major_info)
-{
-	static bool ide0_registered;
-	static bool ide1_registered;
-
-	/*
-	 * For now we only support IDE disks.
-	 */
-	major_info->devname = "ide";
-	major_info->diskname = "hd";
-
-	if (device_info->path_id) {
-		major_info->major = 22;
-		if (!ide1_registered) {
-			major_info->do_register = true;
-			ide1_registered = true;
-		} else
-			major_info->do_register = false;
-
-		if (device_info->target_id)
-			major_info->index = 3;
-		else
-			major_info->index = 2;
-
-		return 0;
-	} else {
-		major_info->major = 3;
-		if (!ide0_registered) {
-			major_info->do_register = true;
-			ide0_registered = true;
-		} else
-			major_info->do_register = false;
-
-		if (device_info->target_id)
-			major_info->index = 1;
-		else
-			major_info->index = 0;
-
-		return 0;
-	}
-
-	return -ENODEV;
-}
 static const char *driver_name = "storvsc";
 
 struct hv_host_device {
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup storvsc_drv.c.n


Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |  355 -----------------------------------
 drivers/staging/hv/storvsc_drv.c    |  314 ++++++++++++++++++++++++++++++-
 2 files changed, 313 insertions(+), 356 deletions(-)
 delete mode 100644 drivers/staging/hv/hyperv_storage.h

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
deleted file mode 100644
index 865ede1..0000000
--- a/drivers/staging/hv/hyperv_storage.h
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- *
- * Copyright (c) 2011, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *   K. Y. Srinivasan <kys@microsoft.com>
- *
- */
-
-#ifndef _HYPERV_STORAGE_H
-#define _HYPERV_STORAGE_H
-
-/*
- * We want to manage the IDE devices using standard Linux SCSI drivers
- * using the storvsc driver.
- * Define special channels to support this.
- */
-
-#define HV_MAX_IDE_DEVICES	4
-#define HV_IDE_BASE_CHANNEL	10
-#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
-#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
-#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
-#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)
-
-
-/* vstorage.w revision number.  This is used in the case of a version match, */
-/* to alert the user that structure sizes may be mismatched even though the */
-/* protocol versions match. */
-
-
-#define REVISION_STRING(REVISION_) #REVISION_
-#define FILL_VMSTOR_REVISION(RESULT_LVALUE_)				\
-	do {								\
-		char *revision_string					\
-			= REVISION_STRING($Rev : 6 $) + 6;		\
-		RESULT_LVALUE_ = 0;					\
-		while (*revision_string >= '0'				\
-			&& *revision_string <= '9') {			\
-			RESULT_LVALUE_ *= 10;				\
-			RESULT_LVALUE_ += *revision_string - '0';	\
-			revision_string++;				\
-		}							\
-	} while (0)
-
-/* Major/minor macros.  Minor version is in LSB, meaning that earlier flat */
-/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */
-#define VMSTOR_PROTOCOL_MAJOR(VERSION_)		(((VERSION_) >> 8) & 0xff)
-#define VMSTOR_PROTOCOL_MINOR(VERSION_)		(((VERSION_))      & 0xff)
-#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_)	((((MAJOR_) & 0xff) << 8) | \
-						 (((MINOR_) & 0xff)))
-#define VMSTOR_INVALID_PROTOCOL_VERSION		(-1)
-
-/* Version history: */
-/* V1 Beta                    0.1 */
-/* V1 RC < 2008/1/31          1.0 */
-/* V1 RC > 2008/1/31          2.0 */
-#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0)
-
-
-
-
-/*  This will get replaced with the max transfer length that is possible on */
-/*  the host adapter. */
-/*  The max transfer length will be published when we offer a vmbus channel. */
-#define MAX_TRANSFER_LENGTH	0x40000
-#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) +	\
-			sizeof(struct vstor_packet) +		\
-			sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE)))
-
-
-/*  Packet structure describing virtual storage requests. */
-enum vstor_packet_operation {
-	VSTOR_OPERATION_COMPLETE_IO		= 1,
-	VSTOR_OPERATION_REMOVE_DEVICE		= 2,
-	VSTOR_OPERATION_EXECUTE_SRB		= 3,
-	VSTOR_OPERATION_RESET_LUN		= 4,
-	VSTOR_OPERATION_RESET_ADAPTER		= 5,
-	VSTOR_OPERATION_RESET_BUS		= 6,
-	VSTOR_OPERATION_BEGIN_INITIALIZATION	= 7,
-	VSTOR_OPERATION_END_INITIALIZATION	= 8,
-	VSTOR_OPERATION_QUERY_PROTOCOL_VERSION	= 9,
-	VSTOR_OPERATION_QUERY_PROPERTIES	= 10,
-	VSTOR_OPERATION_MAXIMUM			= 10
-};
-
-/*
- * Platform neutral description of a scsi request -
- * this remains the same across the write regardless of 32/64 bit
- * note: it's patterned off the SCSI_PASS_THROUGH structure
- */
-#define CDB16GENERIC_LENGTH			0x10
-
-#ifndef SENSE_BUFFER_SIZE
-#define SENSE_BUFFER_SIZE			0x12
-#endif
-
-#define MAX_DATA_BUF_LEN_WITH_PADDING		0x14
-
-struct vmscsi_request {
-	unsigned short length;
-	unsigned char srb_status;
-	unsigned char scsi_status;
-
-	unsigned char port_number;
-	unsigned char path_id;
-	unsigned char target_id;
-	unsigned char lun;
-
-	unsigned char cdb_length;
-	unsigned char sense_info_length;
-	unsigned char data_in;
-	unsigned char reserved;
-
-	unsigned int data_transfer_length;
-
-	union {
-		unsigned char cdb[CDB16GENERIC_LENGTH];
-		unsigned char sense_data[SENSE_BUFFER_SIZE];
-		unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
-	};
-} __attribute((packed));
-
-
-/*
- * This structure is sent during the intialization phase to get the different
- * properties of the channel.
- */
-struct vmstorage_channel_properties {
-	unsigned short protocol_version;
-	unsigned char path_id;
-	unsigned char target_id;
-
-	/* Note: port number is only really known on the client side */
-	unsigned int port_number;
-	unsigned int flags;
-	unsigned int max_transfer_bytes;
-
-	/*  This id is unique for each channel and will correspond with */
-	/*  vendor specific data in the inquirydata */
-	unsigned long long unique_id;
-} __packed;
-
-/*  This structure is sent during the storage protocol negotiations. */
-struct vmstorage_protocol_version {
-	/* Major (MSW) and minor (LSW) version numbers. */
-	unsigned short major_minor;
-
-	/*
-	 * Revision number is auto-incremented whenever this file is changed
-	 * (See FILL_VMSTOR_REVISION macro above).  Mismatch does not
-	 * definitely indicate incompatibility--but it does indicate mismatched
-	 * builds.
-	 */
-	unsigned short revision;
-} __packed;
-
-/* Channel Property Flags */
-#define STORAGE_CHANNEL_REMOVABLE_FLAG		0x1
-#define STORAGE_CHANNEL_EMULATED_IDE_FLAG	0x2
-
-struct vstor_packet {
-	/* Requested operation type */
-	enum vstor_packet_operation operation;
-
-	/*  Flags - see below for values */
-	unsigned int flags;
-
-	/* Status of the request returned from the server side. */
-	unsigned int status;
-
-	/* Data payload area */
-	union {
-		/*
-		 * Structure used to forward SCSI commands from the
-		 * client to the server.
-		 */
-		struct vmscsi_request vm_srb;
-
-		/* Structure used to query channel properties. */
-		struct vmstorage_channel_properties storage_channel_properties;
-
-		/* Used during version negotiations. */
-		struct vmstorage_protocol_version version;
-	};
-} __packed;
-
-/* Packet flags */
-/*
- * This flag indicates that the server should send back a completion for this
- * packet.
- */
-#define REQUEST_COMPLETION_FLAG	0x1
-
-/*  This is the set of flags that the vsc can set in any packets it sends */
-#define VSC_LEGAL_FLAGS		(REQUEST_COMPLETION_FLAG)
-
-
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include "hyperv_storage.h"
-#include "hyperv.h"
-
-/* Defines */
-#define STORVSC_RING_BUFFER_SIZE			(20*PAGE_SIZE)
-#define BLKVSC_RING_BUFFER_SIZE				(20*PAGE_SIZE)
-
-#define STORVSC_MAX_IO_REQUESTS				128
-
-/*
- * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
- * reality, the path/target is not used (ie always set to 0) so our
- * scsi host adapter essentially has 1 bus with 1 target that contains
- * up to 256 luns.
- */
-#define STORVSC_MAX_LUNS_PER_TARGET			64
-#define STORVSC_MAX_TARGETS				1
-#define STORVSC_MAX_CHANNELS				1
-
-struct hv_storvsc_request;
-
-/* Matches Windows-end */
-enum storvsc_request_type {
-	WRITE_TYPE,
-	READ_TYPE,
-	UNKNOWN_TYPE,
-};
-
-
-struct hv_storvsc_request {
-	struct hv_storvsc_request *request;
-	struct hv_device *device;
-
-	/* Synchronize the request/response if needed */
-	struct completion wait_event;
-
-	unsigned char *sense_buffer;
-	void *context;
-	void (*on_io_completion)(struct hv_storvsc_request *request);
-	struct hv_multipage_buffer data_buffer;
-
-	struct vstor_packet vstor_packet;
-};
-
-
-struct storvsc_device_info {
-	u32 ring_buffer_size;
-	unsigned int port_number;
-	unsigned char path_id;
-	unsigned char target_id;
-};
-
-struct storvsc_major_info {
-	int major;
-	int index;
-	bool do_register;
-	char *devname;
-	char *diskname;
-};
-
-/* A storvsc device is a device object that contains a vmbus channel */
-struct storvsc_device {
-	struct hv_device *device;
-
-	/* 0 indicates the device is being destroyed */
-	int	 ref_count;
-	bool	 destroy;
-	bool	 drain_notify;
-	bool	 hba_owner;
-	atomic_t num_outstanding_req;
-
-	wait_queue_head_t waiting_to_drain;
-
-	/*
-	 * Each unique Port/Path/Target represents 1 channel ie scsi
-	 * controller. In reality, the pathid, targetid is always 0
-	 * and the port is set by us
-	 */
-	unsigned int port_number;
-	unsigned char path_id;
-	unsigned char target_id;
-
-	/* Used for vsc/vsp channel reset process */
-	struct hv_storvsc_request init_request;
-	struct hv_storvsc_request reset_request;
-};
-
-
-static inline struct storvsc_device *get_out_stor_device(
-					struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	unsigned long flags;
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && (stor_device->ref_count) &&
-		!stor_device->destroy)
-		stor_device->ref_count++;
-	else
-		stor_device = NULL;
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-
-	return stor_device;
-}
-
-
-static inline void put_stor_device(struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	unsigned long flags;
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	stor_device = (struct storvsc_device *)device->ext;
-
-	stor_device->ref_count--;
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-}
-
-static inline void storvsc_wait_to_drain(struct storvsc_device *dev)
-{
-	dev->drain_notify = true;
-	wait_event(dev->waiting_to_drain,
-		   atomic_read(&dev->num_outstanding_req) == 0);
-	dev->drain_notify = false;
-}
-
-/* Interface */
-
-int storvsc_dev_add(struct hv_device *device,
-				void *additional_info);
-int storvsc_dev_remove(struct hv_device *device);
-
-int storvsc_do_io(struct hv_device *device,
-				struct hv_storvsc_request *request);
-
-int storvsc_get_major_info(struct storvsc_device_info *device_info,
-				struct storvsc_major_info *major_info);
-
-#endif /* _HYPERV_STORAGE_H */
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 0702dc0..f54f013 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -21,6 +21,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/wait.h>
 #include <linux/sched.h>
 #include <linux/completion.h>
 #include <linux/string.h>
@@ -41,7 +42,318 @@
 #include <scsi/scsi_dbg.h>
 
 #include "hyperv.h"
-#include "hyperv_storage.h"
+
+
+/*
+ * We want to manage the IDE devices using standard Linux SCSI drivers
+ * using the storvsc driver.
+ * Define special channels to support this.
+ */
+
+#define HV_MAX_IDE_DEVICES	4
+#define HV_IDE_BASE_CHANNEL	10
+#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
+#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
+#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
+#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)
+
+
+/* vstorage.w revision number.  This is used in the case of a version match, */
+/* to alert the user that structure sizes may be mismatched even though the */
+/* protocol versions match. */
+
+
+#define REVISION_STRING(REVISION_) #REVISION_
+#define FILL_VMSTOR_REVISION(RESULT_LVALUE_)				\
+	do {								\
+		char *revision_string					\
+			= REVISION_STRING($Rev : 6 $) + 6;		\
+		RESULT_LVALUE_ = 0;					\
+		while (*revision_string >= '0'				\
+			&& *revision_string <= '9') {			\
+			RESULT_LVALUE_ *= 10;				\
+			RESULT_LVALUE_ += *revision_string - '0';	\
+			revision_string++;				\
+		}							\
+	} while (0)
+
+/* Major/minor macros.  Minor version is in LSB, meaning that earlier flat */
+/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */
+#define VMSTOR_PROTOCOL_MAJOR(VERSION_)		(((VERSION_) >> 8) & 0xff)
+#define VMSTOR_PROTOCOL_MINOR(VERSION_)		(((VERSION_))      & 0xff)
+#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_)	((((MAJOR_) & 0xff) << 8) | \
+						 (((MINOR_) & 0xff)))
+#define VMSTOR_INVALID_PROTOCOL_VERSION		(-1)
+
+/* Version history: */
+/* V1 Beta                    0.1 */
+/* V1 RC < 2008/1/31          1.0 */
+/* V1 RC > 2008/1/31          2.0 */
+#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0)
+
+
+
+
+/*  This will get replaced with the max transfer length that is possible on */
+/*  the host adapter. */
+/*  The max transfer length will be published when we offer a vmbus channel. */
+#define MAX_TRANSFER_LENGTH	0x40000
+#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) +	\
+			sizeof(struct vstor_packet) +		\
+			sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE)))
+
+
+/*  Packet structure describing virtual storage requests. */
+enum vstor_packet_operation {
+	VSTOR_OPERATION_COMPLETE_IO		= 1,
+	VSTOR_OPERATION_REMOVE_DEVICE		= 2,
+	VSTOR_OPERATION_EXECUTE_SRB		= 3,
+	VSTOR_OPERATION_RESET_LUN		= 4,
+	VSTOR_OPERATION_RESET_ADAPTER		= 5,
+	VSTOR_OPERATION_RESET_BUS		= 6,
+	VSTOR_OPERATION_BEGIN_INITIALIZATION	= 7,
+	VSTOR_OPERATION_END_INITIALIZATION	= 8,
+	VSTOR_OPERATION_QUERY_PROTOCOL_VERSION	= 9,
+	VSTOR_OPERATION_QUERY_PROPERTIES	= 10,
+	VSTOR_OPERATION_MAXIMUM			= 10
+};
+
+/*
+ * Platform neutral description of a scsi request -
+ * this remains the same across the write regardless of 32/64 bit
+ * note: it's patterned off the SCSI_PASS_THROUGH structure
+ */
+#define CDB16GENERIC_LENGTH			0x10
+
+#ifndef SENSE_BUFFER_SIZE
+#define SENSE_BUFFER_SIZE			0x12
+#endif
+
+#define MAX_DATA_BUF_LEN_WITH_PADDING		0x14
+
+struct vmscsi_request {
+	unsigned short length;
+	unsigned char srb_status;
+	unsigned char scsi_status;
+
+	unsigned char port_number;
+	unsigned char path_id;
+	unsigned char target_id;
+	unsigned char lun;
+
+	unsigned char cdb_length;
+	unsigned char sense_info_length;
+	unsigned char data_in;
+	unsigned char reserved;
+
+	unsigned int data_transfer_length;
+
+	union {
+		unsigned char cdb[CDB16GENERIC_LENGTH];
+		unsigned char sense_data[SENSE_BUFFER_SIZE];
+		unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
+	};
+} __attribute((packed));
+
+
+/*
+ * This structure is sent during the intialization phase to get the different
+ * properties of the channel.
+ */
+struct vmstorage_channel_properties {
+	unsigned short protocol_version;
+	unsigned char path_id;
+	unsigned char target_id;
+
+	/* Note: port number is only really known on the client side */
+	unsigned int port_number;
+	unsigned int flags;
+	unsigned int max_transfer_bytes;
+
+	/*  This id is unique for each channel and will correspond with */
+	/*  vendor specific data in the inquirydata */
+	unsigned long long unique_id;
+} __packed;
+
+/*  This structure is sent during the storage protocol negotiations. */
+struct vmstorage_protocol_version {
+	/* Major (MSW) and minor (LSW) version numbers. */
+	unsigned short major_minor;
+
+	/*
+	 * Revision number is auto-incremented whenever this file is changed
+	 * (See FILL_VMSTOR_REVISION macro above).  Mismatch does not
+	 * definitely indicate incompatibility--but it does indicate mismatched
+	 * builds.
+	 */
+	unsigned short revision;
+} __packed;
+
+/* Channel Property Flags */
+#define STORAGE_CHANNEL_REMOVABLE_FLAG		0x1
+#define STORAGE_CHANNEL_EMULATED_IDE_FLAG	0x2
+
+struct vstor_packet {
+	/* Requested operation type */
+	enum vstor_packet_operation operation;
+
+	/*  Flags - see below for values */
+	unsigned int flags;
+
+	/* Status of the request returned from the server side. */
+	unsigned int status;
+
+	/* Data payload area */
+	union {
+		/*
+		 * Structure used to forward SCSI commands from the
+		 * client to the server.
+		 */
+		struct vmscsi_request vm_srb;
+
+		/* Structure used to query channel properties. */
+		struct vmstorage_channel_properties storage_channel_properties;
+
+		/* Used during version negotiations. */
+		struct vmstorage_protocol_version version;
+	};
+} __packed;
+
+/* Packet flags */
+/*
+ * This flag indicates that the server should send back a completion for this
+ * packet.
+ */
+#define REQUEST_COMPLETION_FLAG	0x1
+
+/*  This is the set of flags that the vsc can set in any packets it sends */
+#define VSC_LEGAL_FLAGS		(REQUEST_COMPLETION_FLAG)
+
+
+/* Defines */
+#define STORVSC_RING_BUFFER_SIZE			(20*PAGE_SIZE)
+#define BLKVSC_RING_BUFFER_SIZE				(20*PAGE_SIZE)
+
+#define STORVSC_MAX_IO_REQUESTS				128
+
+/*
+ * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
+ * reality, the path/target is not used (ie always set to 0) so our
+ * scsi host adapter essentially has 1 bus with 1 target that contains
+ * up to 256 luns.
+ */
+#define STORVSC_MAX_LUNS_PER_TARGET			64
+#define STORVSC_MAX_TARGETS				1
+#define STORVSC_MAX_CHANNELS				1
+
+struct hv_storvsc_request;
+
+/* Matches Windows-end */
+enum storvsc_request_type {
+	WRITE_TYPE,
+	READ_TYPE,
+	UNKNOWN_TYPE,
+};
+
+
+struct hv_storvsc_request {
+	struct hv_storvsc_request *request;
+	struct hv_device *device;
+
+	/* Synchronize the request/response if needed */
+	struct completion wait_event;
+
+	unsigned char *sense_buffer;
+	void *context;
+	void (*on_io_completion)(struct hv_storvsc_request *request);
+	struct hv_multipage_buffer data_buffer;
+
+	struct vstor_packet vstor_packet;
+};
+
+
+struct storvsc_device_info {
+	u32 ring_buffer_size;
+	unsigned int port_number;
+	unsigned char path_id;
+	unsigned char target_id;
+};
+
+struct storvsc_major_info {
+	int major;
+	int index;
+	bool do_register;
+	char *devname;
+	char *diskname;
+};
+
+/* A storvsc device is a device object that contains a vmbus channel */
+struct storvsc_device {
+	struct hv_device *device;
+
+	/* 0 indicates the device is being destroyed */
+	int	 ref_count;
+	bool	 destroy;
+	bool	 drain_notify;
+	bool	 hba_owner;
+	atomic_t num_outstanding_req;
+
+	wait_queue_head_t waiting_to_drain;
+
+	/*
+	 * Each unique Port/Path/Target represents 1 channel ie scsi
+	 * controller. In reality, the pathid, targetid is always 0
+	 * and the port is set by us
+	 */
+	unsigned int port_number;
+	unsigned char path_id;
+	unsigned char target_id;
+
+	/* Used for vsc/vsp channel reset process */
+	struct hv_storvsc_request init_request;
+	struct hv_storvsc_request reset_request;
+};
+
+
+static inline struct storvsc_device *get_out_stor_device(
+					struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device->ext_lock, flags);
+	stor_device = (struct storvsc_device *)device->ext;
+	if (stor_device && (stor_device->ref_count) &&
+		!stor_device->destroy)
+		stor_device->ref_count++;
+	else
+		stor_device = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
+
+	return stor_device;
+}
+
+
+static inline void put_stor_device(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device->ext_lock, flags);
+	stor_device = (struct storvsc_device *)device->ext;
+
+	stor_device->ref_count--;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
+}
+
+static inline void storvsc_wait_to_drain(struct storvsc_device *dev)
+{
+	dev->drain_notify = true;
+	wait_event(dev->waiting_to_drain,
+		   atomic_read(&dev->num_outstanding_req) == 0);
+	dev->drain_notify = false;
+}
+
 
 static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup storvsc_drv.c.n


Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/hyperv_storage.h |  355 -----------------------------------
 drivers/staging/hv/storvsc_drv.c    |  314 ++++++++++++++++++++++++++++++-
 2 files changed, 313 insertions(+), 356 deletions(-)
 delete mode 100644 drivers/staging/hv/hyperv_storage.h

diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
deleted file mode 100644
index 865ede1..0000000
--- a/drivers/staging/hv/hyperv_storage.h
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- *
- * Copyright (c) 2011, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *   K. Y. Srinivasan <kys@microsoft.com>
- *
- */
-
-#ifndef _HYPERV_STORAGE_H
-#define _HYPERV_STORAGE_H
-
-/*
- * We want to manage the IDE devices using standard Linux SCSI drivers
- * using the storvsc driver.
- * Define special channels to support this.
- */
-
-#define HV_MAX_IDE_DEVICES	4
-#define HV_IDE_BASE_CHANNEL	10
-#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
-#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
-#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
-#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)
-
-
-/* vstorage.w revision number.  This is used in the case of a version match, */
-/* to alert the user that structure sizes may be mismatched even though the */
-/* protocol versions match. */
-
-
-#define REVISION_STRING(REVISION_) #REVISION_
-#define FILL_VMSTOR_REVISION(RESULT_LVALUE_)				\
-	do {								\
-		char *revision_string					\
-			= REVISION_STRING($Rev : 6 $) + 6;		\
-		RESULT_LVALUE_ = 0;					\
-		while (*revision_string >= '0'				\
-			&& *revision_string <= '9') {			\
-			RESULT_LVALUE_ *= 10;				\
-			RESULT_LVALUE_ += *revision_string - '0';	\
-			revision_string++;				\
-		}							\
-	} while (0)
-
-/* Major/minor macros.  Minor version is in LSB, meaning that earlier flat */
-/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */
-#define VMSTOR_PROTOCOL_MAJOR(VERSION_)		(((VERSION_) >> 8) & 0xff)
-#define VMSTOR_PROTOCOL_MINOR(VERSION_)		(((VERSION_))      & 0xff)
-#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_)	((((MAJOR_) & 0xff) << 8) | \
-						 (((MINOR_) & 0xff)))
-#define VMSTOR_INVALID_PROTOCOL_VERSION		(-1)
-
-/* Version history: */
-/* V1 Beta                    0.1 */
-/* V1 RC < 2008/1/31          1.0 */
-/* V1 RC > 2008/1/31          2.0 */
-#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0)
-
-
-
-
-/*  This will get replaced with the max transfer length that is possible on */
-/*  the host adapter. */
-/*  The max transfer length will be published when we offer a vmbus channel. */
-#define MAX_TRANSFER_LENGTH	0x40000
-#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) +	\
-			sizeof(struct vstor_packet) +		\
-			sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE)))
-
-
-/*  Packet structure describing virtual storage requests. */
-enum vstor_packet_operation {
-	VSTOR_OPERATION_COMPLETE_IO		= 1,
-	VSTOR_OPERATION_REMOVE_DEVICE		= 2,
-	VSTOR_OPERATION_EXECUTE_SRB		= 3,
-	VSTOR_OPERATION_RESET_LUN		= 4,
-	VSTOR_OPERATION_RESET_ADAPTER		= 5,
-	VSTOR_OPERATION_RESET_BUS		= 6,
-	VSTOR_OPERATION_BEGIN_INITIALIZATION	= 7,
-	VSTOR_OPERATION_END_INITIALIZATION	= 8,
-	VSTOR_OPERATION_QUERY_PROTOCOL_VERSION	= 9,
-	VSTOR_OPERATION_QUERY_PROPERTIES	= 10,
-	VSTOR_OPERATION_MAXIMUM			= 10
-};
-
-/*
- * Platform neutral description of a scsi request -
- * this remains the same across the write regardless of 32/64 bit
- * note: it's patterned off the SCSI_PASS_THROUGH structure
- */
-#define CDB16GENERIC_LENGTH			0x10
-
-#ifndef SENSE_BUFFER_SIZE
-#define SENSE_BUFFER_SIZE			0x12
-#endif
-
-#define MAX_DATA_BUF_LEN_WITH_PADDING		0x14
-
-struct vmscsi_request {
-	unsigned short length;
-	unsigned char srb_status;
-	unsigned char scsi_status;
-
-	unsigned char port_number;
-	unsigned char path_id;
-	unsigned char target_id;
-	unsigned char lun;
-
-	unsigned char cdb_length;
-	unsigned char sense_info_length;
-	unsigned char data_in;
-	unsigned char reserved;
-
-	unsigned int data_transfer_length;
-
-	union {
-		unsigned char cdb[CDB16GENERIC_LENGTH];
-		unsigned char sense_data[SENSE_BUFFER_SIZE];
-		unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
-	};
-} __attribute((packed));
-
-
-/*
- * This structure is sent during the intialization phase to get the different
- * properties of the channel.
- */
-struct vmstorage_channel_properties {
-	unsigned short protocol_version;
-	unsigned char path_id;
-	unsigned char target_id;
-
-	/* Note: port number is only really known on the client side */
-	unsigned int port_number;
-	unsigned int flags;
-	unsigned int max_transfer_bytes;
-
-	/*  This id is unique for each channel and will correspond with */
-	/*  vendor specific data in the inquirydata */
-	unsigned long long unique_id;
-} __packed;
-
-/*  This structure is sent during the storage protocol negotiations. */
-struct vmstorage_protocol_version {
-	/* Major (MSW) and minor (LSW) version numbers. */
-	unsigned short major_minor;
-
-	/*
-	 * Revision number is auto-incremented whenever this file is changed
-	 * (See FILL_VMSTOR_REVISION macro above).  Mismatch does not
-	 * definitely indicate incompatibility--but it does indicate mismatched
-	 * builds.
-	 */
-	unsigned short revision;
-} __packed;
-
-/* Channel Property Flags */
-#define STORAGE_CHANNEL_REMOVABLE_FLAG		0x1
-#define STORAGE_CHANNEL_EMULATED_IDE_FLAG	0x2
-
-struct vstor_packet {
-	/* Requested operation type */
-	enum vstor_packet_operation operation;
-
-	/*  Flags - see below for values */
-	unsigned int flags;
-
-	/* Status of the request returned from the server side. */
-	unsigned int status;
-
-	/* Data payload area */
-	union {
-		/*
-		 * Structure used to forward SCSI commands from the
-		 * client to the server.
-		 */
-		struct vmscsi_request vm_srb;
-
-		/* Structure used to query channel properties. */
-		struct vmstorage_channel_properties storage_channel_properties;
-
-		/* Used during version negotiations. */
-		struct vmstorage_protocol_version version;
-	};
-} __packed;
-
-/* Packet flags */
-/*
- * This flag indicates that the server should send back a completion for this
- * packet.
- */
-#define REQUEST_COMPLETION_FLAG	0x1
-
-/*  This is the set of flags that the vsc can set in any packets it sends */
-#define VSC_LEGAL_FLAGS		(REQUEST_COMPLETION_FLAG)
-
-
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include "hyperv_storage.h"
-#include "hyperv.h"
-
-/* Defines */
-#define STORVSC_RING_BUFFER_SIZE			(20*PAGE_SIZE)
-#define BLKVSC_RING_BUFFER_SIZE				(20*PAGE_SIZE)
-
-#define STORVSC_MAX_IO_REQUESTS				128
-
-/*
- * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
- * reality, the path/target is not used (ie always set to 0) so our
- * scsi host adapter essentially has 1 bus with 1 target that contains
- * up to 256 luns.
- */
-#define STORVSC_MAX_LUNS_PER_TARGET			64
-#define STORVSC_MAX_TARGETS				1
-#define STORVSC_MAX_CHANNELS				1
-
-struct hv_storvsc_request;
-
-/* Matches Windows-end */
-enum storvsc_request_type {
-	WRITE_TYPE,
-	READ_TYPE,
-	UNKNOWN_TYPE,
-};
-
-
-struct hv_storvsc_request {
-	struct hv_storvsc_request *request;
-	struct hv_device *device;
-
-	/* Synchronize the request/response if needed */
-	struct completion wait_event;
-
-	unsigned char *sense_buffer;
-	void *context;
-	void (*on_io_completion)(struct hv_storvsc_request *request);
-	struct hv_multipage_buffer data_buffer;
-
-	struct vstor_packet vstor_packet;
-};
-
-
-struct storvsc_device_info {
-	u32 ring_buffer_size;
-	unsigned int port_number;
-	unsigned char path_id;
-	unsigned char target_id;
-};
-
-struct storvsc_major_info {
-	int major;
-	int index;
-	bool do_register;
-	char *devname;
-	char *diskname;
-};
-
-/* A storvsc device is a device object that contains a vmbus channel */
-struct storvsc_device {
-	struct hv_device *device;
-
-	/* 0 indicates the device is being destroyed */
-	int	 ref_count;
-	bool	 destroy;
-	bool	 drain_notify;
-	bool	 hba_owner;
-	atomic_t num_outstanding_req;
-
-	wait_queue_head_t waiting_to_drain;
-
-	/*
-	 * Each unique Port/Path/Target represents 1 channel ie scsi
-	 * controller. In reality, the pathid, targetid is always 0
-	 * and the port is set by us
-	 */
-	unsigned int port_number;
-	unsigned char path_id;
-	unsigned char target_id;
-
-	/* Used for vsc/vsp channel reset process */
-	struct hv_storvsc_request init_request;
-	struct hv_storvsc_request reset_request;
-};
-
-
-static inline struct storvsc_device *get_out_stor_device(
-					struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	unsigned long flags;
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	stor_device = (struct storvsc_device *)device->ext;
-	if (stor_device && (stor_device->ref_count) &&
-		!stor_device->destroy)
-		stor_device->ref_count++;
-	else
-		stor_device = NULL;
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-
-	return stor_device;
-}
-
-
-static inline void put_stor_device(struct hv_device *device)
-{
-	struct storvsc_device *stor_device;
-	unsigned long flags;
-
-	spin_lock_irqsave(&device->ext_lock, flags);
-	stor_device = (struct storvsc_device *)device->ext;
-
-	stor_device->ref_count--;
-	spin_unlock_irqrestore(&device->ext_lock, flags);
-}
-
-static inline void storvsc_wait_to_drain(struct storvsc_device *dev)
-{
-	dev->drain_notify = true;
-	wait_event(dev->waiting_to_drain,
-		   atomic_read(&dev->num_outstanding_req) == 0);
-	dev->drain_notify = false;
-}
-
-/* Interface */
-
-int storvsc_dev_add(struct hv_device *device,
-				void *additional_info);
-int storvsc_dev_remove(struct hv_device *device);
-
-int storvsc_do_io(struct hv_device *device,
-				struct hv_storvsc_request *request);
-
-int storvsc_get_major_info(struct storvsc_device_info *device_info,
-				struct storvsc_major_info *major_info);
-
-#endif /* _HYPERV_STORAGE_H */
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 0702dc0..f54f013 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -21,6 +21,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/wait.h>
 #include <linux/sched.h>
 #include <linux/completion.h>
 #include <linux/string.h>
@@ -41,7 +42,318 @@
 #include <scsi/scsi_dbg.h>
 
 #include "hyperv.h"
-#include "hyperv_storage.h"
+
+
+/*
+ * We want to manage the IDE devices using standard Linux SCSI drivers
+ * using the storvsc driver.
+ * Define special channels to support this.
+ */
+
+#define HV_MAX_IDE_DEVICES	4
+#define HV_IDE_BASE_CHANNEL	10
+#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
+#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
+#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
+#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)
+
+
+/* vstorage.w revision number.  This is used in the case of a version match, */
+/* to alert the user that structure sizes may be mismatched even though the */
+/* protocol versions match. */
+
+
+#define REVISION_STRING(REVISION_) #REVISION_
+#define FILL_VMSTOR_REVISION(RESULT_LVALUE_)				\
+	do {								\
+		char *revision_string					\
+			= REVISION_STRING($Rev : 6 $) + 6;		\
+		RESULT_LVALUE_ = 0;					\
+		while (*revision_string >= '0'				\
+			&& *revision_string <= '9') {			\
+			RESULT_LVALUE_ *= 10;				\
+			RESULT_LVALUE_ += *revision_string - '0';	\
+			revision_string++;				\
+		}							\
+	} while (0)
+
+/* Major/minor macros.  Minor version is in LSB, meaning that earlier flat */
+/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */
+#define VMSTOR_PROTOCOL_MAJOR(VERSION_)		(((VERSION_) >> 8) & 0xff)
+#define VMSTOR_PROTOCOL_MINOR(VERSION_)		(((VERSION_))      & 0xff)
+#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_)	((((MAJOR_) & 0xff) << 8) | \
+						 (((MINOR_) & 0xff)))
+#define VMSTOR_INVALID_PROTOCOL_VERSION		(-1)
+
+/* Version history: */
+/* V1 Beta                    0.1 */
+/* V1 RC < 2008/1/31          1.0 */
+/* V1 RC > 2008/1/31          2.0 */
+#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0)
+
+
+
+
+/*  This will get replaced with the max transfer length that is possible on */
+/*  the host adapter. */
+/*  The max transfer length will be published when we offer a vmbus channel. */
+#define MAX_TRANSFER_LENGTH	0x40000
+#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) +	\
+			sizeof(struct vstor_packet) +		\
+			sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE)))
+
+
+/*  Packet structure describing virtual storage requests. */
+enum vstor_packet_operation {
+	VSTOR_OPERATION_COMPLETE_IO		= 1,
+	VSTOR_OPERATION_REMOVE_DEVICE		= 2,
+	VSTOR_OPERATION_EXECUTE_SRB		= 3,
+	VSTOR_OPERATION_RESET_LUN		= 4,
+	VSTOR_OPERATION_RESET_ADAPTER		= 5,
+	VSTOR_OPERATION_RESET_BUS		= 6,
+	VSTOR_OPERATION_BEGIN_INITIALIZATION	= 7,
+	VSTOR_OPERATION_END_INITIALIZATION	= 8,
+	VSTOR_OPERATION_QUERY_PROTOCOL_VERSION	= 9,
+	VSTOR_OPERATION_QUERY_PROPERTIES	= 10,
+	VSTOR_OPERATION_MAXIMUM			= 10
+};
+
+/*
+ * Platform neutral description of a scsi request -
+ * this remains the same across the write regardless of 32/64 bit
+ * note: it's patterned off the SCSI_PASS_THROUGH structure
+ */
+#define CDB16GENERIC_LENGTH			0x10
+
+#ifndef SENSE_BUFFER_SIZE
+#define SENSE_BUFFER_SIZE			0x12
+#endif
+
+#define MAX_DATA_BUF_LEN_WITH_PADDING		0x14
+
+struct vmscsi_request {
+	unsigned short length;
+	unsigned char srb_status;
+	unsigned char scsi_status;
+
+	unsigned char port_number;
+	unsigned char path_id;
+	unsigned char target_id;
+	unsigned char lun;
+
+	unsigned char cdb_length;
+	unsigned char sense_info_length;
+	unsigned char data_in;
+	unsigned char reserved;
+
+	unsigned int data_transfer_length;
+
+	union {
+		unsigned char cdb[CDB16GENERIC_LENGTH];
+		unsigned char sense_data[SENSE_BUFFER_SIZE];
+		unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
+	};
+} __attribute((packed));
+
+
+/*
+ * This structure is sent during the intialization phase to get the different
+ * properties of the channel.
+ */
+struct vmstorage_channel_properties {
+	unsigned short protocol_version;
+	unsigned char path_id;
+	unsigned char target_id;
+
+	/* Note: port number is only really known on the client side */
+	unsigned int port_number;
+	unsigned int flags;
+	unsigned int max_transfer_bytes;
+
+	/*  This id is unique for each channel and will correspond with */
+	/*  vendor specific data in the inquirydata */
+	unsigned long long unique_id;
+} __packed;
+
+/*  This structure is sent during the storage protocol negotiations. */
+struct vmstorage_protocol_version {
+	/* Major (MSW) and minor (LSW) version numbers. */
+	unsigned short major_minor;
+
+	/*
+	 * Revision number is auto-incremented whenever this file is changed
+	 * (See FILL_VMSTOR_REVISION macro above).  Mismatch does not
+	 * definitely indicate incompatibility--but it does indicate mismatched
+	 * builds.
+	 */
+	unsigned short revision;
+} __packed;
+
+/* Channel Property Flags */
+#define STORAGE_CHANNEL_REMOVABLE_FLAG		0x1
+#define STORAGE_CHANNEL_EMULATED_IDE_FLAG	0x2
+
+struct vstor_packet {
+	/* Requested operation type */
+	enum vstor_packet_operation operation;
+
+	/*  Flags - see below for values */
+	unsigned int flags;
+
+	/* Status of the request returned from the server side. */
+	unsigned int status;
+
+	/* Data payload area */
+	union {
+		/*
+		 * Structure used to forward SCSI commands from the
+		 * client to the server.
+		 */
+		struct vmscsi_request vm_srb;
+
+		/* Structure used to query channel properties. */
+		struct vmstorage_channel_properties storage_channel_properties;
+
+		/* Used during version negotiations. */
+		struct vmstorage_protocol_version version;
+	};
+} __packed;
+
+/* Packet flags */
+/*
+ * This flag indicates that the server should send back a completion for this
+ * packet.
+ */
+#define REQUEST_COMPLETION_FLAG	0x1
+
+/*  This is the set of flags that the vsc can set in any packets it sends */
+#define VSC_LEGAL_FLAGS		(REQUEST_COMPLETION_FLAG)
+
+
+/* Defines */
+#define STORVSC_RING_BUFFER_SIZE			(20*PAGE_SIZE)
+#define BLKVSC_RING_BUFFER_SIZE				(20*PAGE_SIZE)
+
+#define STORVSC_MAX_IO_REQUESTS				128
+
+/*
+ * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
+ * reality, the path/target is not used (ie always set to 0) so our
+ * scsi host adapter essentially has 1 bus with 1 target that contains
+ * up to 256 luns.
+ */
+#define STORVSC_MAX_LUNS_PER_TARGET			64
+#define STORVSC_MAX_TARGETS				1
+#define STORVSC_MAX_CHANNELS				1
+
+struct hv_storvsc_request;
+
+/* Matches Windows-end */
+enum storvsc_request_type {
+	WRITE_TYPE,
+	READ_TYPE,
+	UNKNOWN_TYPE,
+};
+
+
+struct hv_storvsc_request {
+	struct hv_storvsc_request *request;
+	struct hv_device *device;
+
+	/* Synchronize the request/response if needed */
+	struct completion wait_event;
+
+	unsigned char *sense_buffer;
+	void *context;
+	void (*on_io_completion)(struct hv_storvsc_request *request);
+	struct hv_multipage_buffer data_buffer;
+
+	struct vstor_packet vstor_packet;
+};
+
+
+struct storvsc_device_info {
+	u32 ring_buffer_size;
+	unsigned int port_number;
+	unsigned char path_id;
+	unsigned char target_id;
+};
+
+struct storvsc_major_info {
+	int major;
+	int index;
+	bool do_register;
+	char *devname;
+	char *diskname;
+};
+
+/* A storvsc device is a device object that contains a vmbus channel */
+struct storvsc_device {
+	struct hv_device *device;
+
+	/* 0 indicates the device is being destroyed */
+	int	 ref_count;
+	bool	 destroy;
+	bool	 drain_notify;
+	bool	 hba_owner;
+	atomic_t num_outstanding_req;
+
+	wait_queue_head_t waiting_to_drain;
+
+	/*
+	 * Each unique Port/Path/Target represents 1 channel ie scsi
+	 * controller. In reality, the pathid, targetid is always 0
+	 * and the port is set by us
+	 */
+	unsigned int port_number;
+	unsigned char path_id;
+	unsigned char target_id;
+
+	/* Used for vsc/vsp channel reset process */
+	struct hv_storvsc_request init_request;
+	struct hv_storvsc_request reset_request;
+};
+
+
+static inline struct storvsc_device *get_out_stor_device(
+					struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device->ext_lock, flags);
+	stor_device = (struct storvsc_device *)device->ext;
+	if (stor_device && (stor_device->ref_count) &&
+		!stor_device->destroy)
+		stor_device->ref_count++;
+	else
+		stor_device = NULL;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
+
+	return stor_device;
+}
+
+
+static inline void put_stor_device(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device->ext_lock, flags);
+	stor_device = (struct storvsc_device *)device->ext;
+
+	stor_device->ref_count--;
+	spin_unlock_irqrestore(&device->ext_lock, flags);
+}
+
+static inline void storvsc_wait_to_drain(struct storvsc_device *dev)
+{
+	dev->drain_notify = true;
+	wait_event(dev->waiting_to_drain,
+		   atomic_read(&dev->num_outstanding_req) == 0);
+	dev->drain_notify = false;
+}
+
 
 static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 35/40] Staging: hv: storvsc: Make storvsc_dev_add() a static function
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Make storvsc_dev_add() a static function.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index f54f013..4a3e4b3 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -667,7 +667,7 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
 	return ret;
 }
 
-int storvsc_dev_add(struct hv_device *device,
+static int storvsc_dev_add(struct hv_device *device,
 					void *additional_info)
 {
 	struct storvsc_device *stor_device;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 35/40] Staging: hv: storvsc: Make storvsc_dev_add() a static function
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Make storvsc_dev_add() a static function.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index f54f013..4a3e4b3 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -667,7 +667,7 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
 	return ret;
 }
 
-int storvsc_dev_add(struct hv_device *device,
+static int storvsc_dev_add(struct hv_device *device,
 					void *additional_info)
 {
 	struct storvsc_device *stor_device;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 36/40] Staging: hv: storvsc: Make storvsc_dev_remove() a static function
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Make storvsc_dev_remove() a static function.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 4a3e4b3..f513503 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -702,7 +702,7 @@ static int storvsc_dev_add(struct hv_device *device,
 	return ret;
 }
 
-int storvsc_dev_remove(struct hv_device *device)
+static int storvsc_dev_remove(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
 	unsigned long flags;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 36/40] Staging: hv: storvsc: Make storvsc_dev_remove() a static function
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Make storvsc_dev_remove() a static function.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 4a3e4b3..f513503 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -702,7 +702,7 @@ static int storvsc_dev_add(struct hv_device *device,
 	return ret;
 }
 
-int storvsc_dev_remove(struct hv_device *device)
+static int storvsc_dev_remove(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
 	unsigned long flags;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 37/40] Staging: hv: storvsc: Make storvsc_do_io() a static function
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

Make storvsc_do_io() a static function.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index f513503..42689d3 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -736,7 +736,7 @@ static int storvsc_dev_remove(struct hv_device *device)
 	return 0;
 }
 
-int storvsc_do_io(struct hv_device *device,
+static int storvsc_do_io(struct hv_device *device,
 			      struct hv_storvsc_request *request)
 {
 	struct storvsc_device *stor_device;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 37/40] Staging: hv: storvsc: Make storvsc_do_io() a static function
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

Make storvsc_do_io() a static function.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index f513503..42689d3 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -736,7 +736,7 @@ static int storvsc_dev_remove(struct hv_device *device)
 	return 0;
 }
 
-int storvsc_do_io(struct hv_device *device,
+static int storvsc_do_io(struct hv_device *device,
 			      struct hv_storvsc_request *request)
 {
 	struct storvsc_device *stor_device;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 38/40] Staging: hv: storvsc: Fixup srb_status for INQUIRY and MODE_SENSE
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

The current handler on the Windows Host does not correctly handle
INQUIRY and MODE_SENSE commands with some options. Fixup srb_status
in these cases since the failure is not fatal.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 42689d3..0785947 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -542,6 +542,18 @@ static void storvsc_on_io_completion(struct hv_device *device,
 
 	stor_pkt = &request->vstor_packet;
 
+	/*
+	 * The current SCSI handling on the host side does
+	 * not correctly handle:
+	 * INQUIRY command with page code parameter set to 0x80
+	 * MODE_SENSE command with cmd[2] == 0x1c
+	 *
+	 * Setup srb status so this won't be fatal.
+	 */
+
+	if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
+	   (stor_pkt->vm_srb.cdb[0] == MODE_SENSE))
+		vstor_packet->vm_srb.srb_status = 0;
 
 	/* Copy over the status...etc */
 	stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 38/40] Staging: hv: storvsc: Fixup srb_status for INQUIRY and MODE_SENSE
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

The current handler on the Windows Host does not correctly handle
INQUIRY and MODE_SENSE commands with some options. Fixup srb_status
in these cases since the failure is not fatal.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 42689d3..0785947 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -542,6 +542,18 @@ static void storvsc_on_io_completion(struct hv_device *device,
 
 	stor_pkt = &request->vstor_packet;
 
+	/*
+	 * The current SCSI handling on the host side does
+	 * not correctly handle:
+	 * INQUIRY command with page code parameter set to 0x80
+	 * MODE_SENSE command with cmd[2] == 0x1c
+	 *
+	 * Setup srb status so this won't be fatal.
+	 */
+
+	if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
+	   (stor_pkt->vm_srb.cdb[0] == MODE_SENSE))
+		vstor_packet->vm_srb.srb_status = 0;
 
 	/* Copy over the status...etc */
 	stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 39/40] Staging: hv: storvsc: In case of scsi errors offline the device
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

When we do get fatal errors from the host, offline the device since the
host has already tried all possible recovery actions.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 0785947..cc4b128 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -1251,7 +1251,15 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
 		}
 	}
 
-	scmnd->result = vm_srb->scsi_status;
+	/*
+	 * If there is an error; offline the device since all
+	 * error recovery strategies would have already been
+	 * deployed on the host side.
+	 */
+	if (vm_srb->srb_status == 0x4)
+		scmnd->result = DID_TARGET_FAILURE << 16;
+	else
+		scmnd->result = vm_srb->scsi_status;
 
 	if (scmnd->result) {
 		if (scsi_normalize_sense(scmnd->sense_buffer,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 39/40] Staging: hv: storvsc: In case of scsi errors offline the device
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

When we do get fatal errors from the host, offline the device since the
host has already tried all possible recovery actions.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 0785947..cc4b128 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -1251,7 +1251,15 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
 		}
 	}
 
-	scmnd->result = vm_srb->scsi_status;
+	/*
+	 * If there is an error; offline the device since all
+	 * error recovery strategies would have already been
+	 * deployed on the host side.
+	 */
+	if (vm_srb->srb_status == 0x4)
+		scmnd->result = DID_TARGET_FAILURE << 16;
+	else
+		scmnd->result = vm_srb->scsi_status;
 
 	if (scmnd->result) {
 		if (scsi_normalize_sense(scmnd->sense_buffer,
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 40/40] Staging: hv: storvsc: No need to copy from bounce buffer in case of failure
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  2011-06-29 14:39     ` K. Y. Srinivasan
                       ` (38 subsequent siblings)
  39 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization
  Cc: K. Y. Srinivasan, Haiyang Zhang, Abhishek Kane, Hank Janssen

In case we are not able to submit an I/O, there is no need to copy
from the bounce buffers; get of the code to copy.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   10 +---------
 1 files changed, 1 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index cc4b128..e2cdd7b 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -1421,17 +1421,9 @@ retry_request:
 	if (ret == -EAGAIN) {
 		/* no more space */
 
-		if (cmd_request->bounce_sgl_count) {
-			/*
-			 * FIXME: We can optimize on writes by just skipping
-			 * this
-			 */
-			copy_from_bounce_buffer(scsi_sglist(scmnd),
-						cmd_request->bounce_sgl,
-						scsi_sg_count(scmnd));
+		if (cmd_request->bounce_sgl_count)
 			destroy_bounce_buffer(cmd_request->bounce_sgl,
 					      cmd_request->bounce_sgl_count);
-		}
 
 		kmem_cache_free(host_dev->request_pool, cmd_request);
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 122+ messages in thread

* [PATCH 40/40] Staging: hv: storvsc: No need to copy from bounce buffer in case of failure
@ 2011-06-29 14:39     ` K. Y. Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: K. Y. Srinivasan @ 2011-06-29 14:39 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang, Abhishek Kane

In case we are not able to submit an I/O, there is no need to copy
from the bounce buffers; get of the code to copy.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
 drivers/staging/hv/storvsc_drv.c |   10 +---------
 1 files changed, 1 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index cc4b128..e2cdd7b 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -1421,17 +1421,9 @@ retry_request:
 	if (ret == -EAGAIN) {
 		/* no more space */
 
-		if (cmd_request->bounce_sgl_count) {
-			/*
-			 * FIXME: We can optimize on writes by just skipping
-			 * this
-			 */
-			copy_from_bounce_buffer(scsi_sglist(scmnd),
-						cmd_request->bounce_sgl,
-						scsi_sg_count(scmnd));
+		if (cmd_request->bounce_sgl_count)
 			destroy_bounce_buffer(cmd_request->bounce_sgl,
 					      cmd_request->bounce_sgl_count);
-		}
 
 		kmem_cache_free(host_dev->request_pool, cmd_request);
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 122+ messages in thread

* Re: [PATCH 00/40] Staging: hv: Driver cleanup
  2011-06-29 14:38 [PATCH 00/40] Staging: hv: Driver cleanup K. Y. Srinivasan
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
@ 2011-06-30 19:33 ` Christoph Hellwig
  2011-06-30 23:28   ` KY Srinivasan
  2011-06-30 23:32     ` KY Srinivasan
  1 sibling, 2 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-06-30 19:33 UTC (permalink / raw)
  To: K. Y. Srinivasan; +Cc: gregkh, linux-kernel, devel, virtualization

On Wed, Jun 29, 2011 at 07:38:21AM -0700, K. Y. Srinivasan wrote:
> Further cleanup of the hv drivers:
> 
> 	1) Cleanup the reference counting mess for both stor and net devices.

I really don't understand the need for reference counting on the storage
side, especially now that you only have a SCSI driver.  The SCSI
midlayer does proper counting on it's objects (Scsi_Host, scsi_device,
scsi_cmnd), so you'll get that for free given that SCSI drivers just
piggyback on the midlayer lifetime rules.

For now your patches should probably go in as-is, but mid-term you
should be able to completely remove that code on the storage side.


^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 23/40] Staging: hv: storvsc: Introduce code to manage IDE devices using storvsc HBA
  2011-06-29 14:39     ` K. Y. Srinivasan
  (?)
@ 2011-06-30 19:38     ` Christoph Hellwig
  2011-06-30 21:38         ` KY Srinivasan
  -1 siblings, 1 reply; 122+ messages in thread
From: Christoph Hellwig @ 2011-06-30 19:38 UTC (permalink / raw)
  To: K. Y. Srinivasan
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane, Hank Janssen

> +/*
> + * We want to manage the IDE devices using standard Linux SCSI drivers
> + * using the storvsc driver.
> + * Define special channels to support this.
> + */
> +
> +#define HV_MAX_IDE_DEVICES	4
> +#define HV_IDE_BASE_CHANNEL	10
> +#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
> +#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
> +#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
> +#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)

This at last needs a good explanation of why these devices are called
IDE if they actually aren't.  I know you've explained the reason to me
before, but it should also be in the code.

The HV_IDE1_DEVn defines don't seem to useful to me.  They are just
used in one place, and doing an opencoded HV_IDE_BASE_CHANNEL +
channel_nr would seem a lot easier to understand to me.

> +static struct  Scsi_Host *storvsc_host;
> +
> +/*
> + * State to manage IDE devices that register with the storvsc driver.
> + *
> + */
> +static struct hv_device *ide_devices[HV_MAX_IDE_DEVICES];
> +
> +static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
> +{
> +	*target =
> +	dev->dev_instance.data[5] << 8 | dev->dev_instance.data[4];
> +
> +	*path =
> +	dev->dev_instance.data[3] << 24 | dev->dev_instance.data[2] << 16 |
> +	dev->dev_instance.data[1] << 8  | dev->dev_instance.data[0];

Pretty odd formatting, I'd rather do it as:

	*target =
		dev->dev_instance.data[5] << 8 |
		dev->dev_instance.data[4];

but more importanly what does path actually stand for here?  Opencoding
this into the caller and adding proper comments explaining the scheme
might be more readable.

> @@ -469,7 +517,6 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
>  	unsigned int sg_count = 0;
>  	struct vmscsi_request *vm_srb;
>  
> -
>  	/* If retrying, no need to prep the cmd */
>  	if (scmnd->host_scribble) {
>  
> @@ -707,7 +754,6 @@ static int storvsc_probe(struct hv_device *device)
>  		scsi_host_put(host);
>  		return -ENODEV;
>  	}
> -
>  	scsi_scan_host(host);
>  	return ret;

Completely unrelated whitespace changes.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
  2011-06-29 14:39     ` K. Y. Srinivasan
@ 2011-06-30 19:40       ` Christoph Hellwig
  -1 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-06-30 19:40 UTC (permalink / raw)
  To: K. Y. Srinivasan
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane, Hank Janssen

On Wed, Jun 29, 2011 at 07:39:21AM -0700, K. Y. Srinivasan wrote:
> We use the channel number to distinguish an IDE device managed by the
> storvsc driver from scsi devices. Add code to get the correct
> device pointer based on the channel number.
> 
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
> Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
> ---
>  drivers/staging/hv/storvsc_drv.c |   10 ++++++++++
>  1 files changed, 10 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
> index cf659d7..fcc3f5d 100644
> --- a/drivers/staging/hv/storvsc_drv.c
> +++ b/drivers/staging/hv/storvsc_drv.c
> @@ -517,6 +517,16 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
>  	unsigned int sg_count = 0;
>  	struct vmscsi_request *vm_srb;
>  
> +	if (scmnd->device->channel >= HV_IDE_BASE_CHANNEL) {
> +		int channel = scmnd->device->channel;
> +
> +		/*
> +		 * This is an IDE device; get the right dev.
> +		 */
> +
> +		dev = ide_devices[channel - HV_IDE_BASE_CHANNEL];
> +	}

So instead of playing games about getting the right hv_device here,
why don't you register one scsi host for each IDE device? libata
does the same for real ATA devices.


^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
@ 2011-06-30 19:40       ` Christoph Hellwig
  0 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-06-30 19:40 UTC (permalink / raw)
  To: K. Y. Srinivasan
  Cc: Abhishek Kane, Haiyang Zhang, gregkh, linux-kernel,
	virtualization, devel

On Wed, Jun 29, 2011 at 07:39:21AM -0700, K. Y. Srinivasan wrote:
> We use the channel number to distinguish an IDE device managed by the
> storvsc driver from scsi devices. Add code to get the correct
> device pointer based on the channel number.
> 
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
> Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
> ---
>  drivers/staging/hv/storvsc_drv.c |   10 ++++++++++
>  1 files changed, 10 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
> index cf659d7..fcc3f5d 100644
> --- a/drivers/staging/hv/storvsc_drv.c
> +++ b/drivers/staging/hv/storvsc_drv.c
> @@ -517,6 +517,16 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
>  	unsigned int sg_count = 0;
>  	struct vmscsi_request *vm_srb;
>  
> +	if (scmnd->device->channel >= HV_IDE_BASE_CHANNEL) {
> +		int channel = scmnd->device->channel;
> +
> +		/*
> +		 * This is an IDE device; get the right dev.
> +		 */
> +
> +		dev = ide_devices[channel - HV_IDE_BASE_CHANNEL];
> +	}

So instead of playing games about getting the right hv_device here,
why don't you register one scsi host for each IDE device? libata
does the same for real ATA devices.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 25/40] Staging: hv: storvsc: Add state to manage the lifecycle of emulated HBA
  2011-06-29 14:39     ` K. Y. Srinivasan
  (?)
@ 2011-06-30 19:44     ` Christoph Hellwig
  -1 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-06-30 19:44 UTC (permalink / raw)
  To: K. Y. Srinivasan
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane, Hank Janssen

I think all this would be a lot simpler if you simply used one scsi
host per ide device as mentioned before.

Also it would be nice if you could sent patches 23 to 28 as one patch
in the next round, as that allows reviewing the whole IDE related code
in one go, which is useful given that it's all interwinded.


^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
  2011-06-29 14:39     ` K. Y. Srinivasan
  (?)
@ 2011-06-30 19:45     ` Christoph Hellwig
  2011-06-30 20:13         ` KY Srinivasan
  -1 siblings, 1 reply; 122+ messages in thread
From: Christoph Hellwig @ 2011-06-30 19:45 UTC (permalink / raw)
  To: K. Y. Srinivasan
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane, Hank Janssen

On Wed, Jun 29, 2011 at 07:39:31AM -0700, K. Y. Srinivasan wrote:
> Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup storvsc_drv.c.n

I'd at least leave the first half of the header that defines the
protocol around. 

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 35/40] Staging: hv: storvsc: Make storvsc_dev_add() a static function
  2011-06-29 14:39     ` K. Y. Srinivasan
  (?)
@ 2011-06-30 19:45     ` Christoph Hellwig
  -1 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-06-30 19:45 UTC (permalink / raw)
  To: K. Y. Srinivasan
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane, Hank Janssen

On Wed, Jun 29, 2011 at 07:39:32AM -0700, K. Y. Srinivasan wrote:
> Make storvsc_dev_add() a static function.

Making all pending functions static should be fine in a single patch.


^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 38/40] Staging: hv: storvsc: Fixup srb_status for INQUIRY and MODE_SENSE
  2011-06-29 14:39     ` K. Y. Srinivasan
  (?)
@ 2011-06-30 19:47     ` Christoph Hellwig
  2011-06-30 19:59         ` KY Srinivasan
  -1 siblings, 1 reply; 122+ messages in thread
From: Christoph Hellwig @ 2011-06-30 19:47 UTC (permalink / raw)
  To: K. Y. Srinivasan
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane, Hank Janssen

On Wed, Jun 29, 2011 at 07:39:35AM -0700, K. Y. Srinivasan wrote:
> The current handler on the Windows Host does not correctly handle
> INQUIRY and MODE_SENSE commands with some options. Fixup srb_status
> in these cases since the failure is not fatal.

> +	/*
> +	 * The current SCSI handling on the host side does
> +	 * not correctly handle:
> +	 * INQUIRY command with page code parameter set to 0x80
> +	 * MODE_SENSE command with cmd[2] == 0x1c
> +	 *
> +	 * Setup srb status so this won't be fatal.
> +	 */
> +
> +	if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
> +	   (stor_pkt->vm_srb.cdb[0] == MODE_SENSE))
> +		vstor_packet->vm_srb.srb_status = 0;

Given that the srb_status is only used for debug printks I don't
quite see the point.  If people explicitly turn on debugging they
should see that these commands fail, shouldn't they?


^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 38/40] Staging: hv: storvsc: Fixup srb_status for INQUIRY and MODE_SENSE
  2011-06-30 19:47     ` Christoph Hellwig
@ 2011-06-30 19:59         ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 19:59 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:48 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 38/40] Staging: hv: storvsc: Fixup srb_status for INQUIRY and
> MODE_SENSE
> 
> On Wed, Jun 29, 2011 at 07:39:35AM -0700, K. Y. Srinivasan wrote:
> > The current handler on the Windows Host does not correctly handle
> > INQUIRY and MODE_SENSE commands with some options. Fixup srb_status
> > in these cases since the failure is not fatal.
> 
> > +	/*
> > +	 * The current SCSI handling on the host side does
> > +	 * not correctly handle:
> > +	 * INQUIRY command with page code parameter set to 0x80
> > +	 * MODE_SENSE command with cmd[2] == 0x1c
> > +	 *
> > +	 * Setup srb status so this won't be fatal.
> > +	 */
> > +
> > +	if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
> > +	   (stor_pkt->vm_srb.cdb[0] == MODE_SENSE))
> > +		vstor_packet->vm_srb.srb_status = 0;
> 
> Given that the srb_status is only used for debug printks I don't
> quite see the point.  If people explicitly turn on debugging they
> should see that these commands fail, shouldn't they?
> 
The reason I did this was so that  I could key off  on real failures indicated by
srb_status == 0x4 to off-line the device.

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 38/40] Staging: hv: storvsc: Fixup srb_status for INQUIRY and MODE_SENSE
@ 2011-06-30 19:59         ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 19:59 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:48 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 38/40] Staging: hv: storvsc: Fixup srb_status for INQUIRY and
> MODE_SENSE
> 
> On Wed, Jun 29, 2011 at 07:39:35AM -0700, K. Y. Srinivasan wrote:
> > The current handler on the Windows Host does not correctly handle
> > INQUIRY and MODE_SENSE commands with some options. Fixup srb_status
> > in these cases since the failure is not fatal.
> 
> > +	/*
> > +	 * The current SCSI handling on the host side does
> > +	 * not correctly handle:
> > +	 * INQUIRY command with page code parameter set to 0x80
> > +	 * MODE_SENSE command with cmd[2] == 0x1c
> > +	 *
> > +	 * Setup srb status so this won't be fatal.
> > +	 */
> > +
> > +	if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
> > +	   (stor_pkt->vm_srb.cdb[0] == MODE_SENSE))
> > +		vstor_packet->vm_srb.srb_status = 0;
> 
> Given that the srb_status is only used for debug printks I don't
> quite see the point.  If people explicitly turn on debugging they
> should see that these commands fail, shouldn't they?
> 
The reason I did this was so that  I could key off  on real failures indicated by
srb_status == 0x4 to off-line the device.

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
  2011-06-30 19:45     ` Christoph Hellwig
@ 2011-06-30 20:13         ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 20:13 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:46 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of
> hyperv_storage.h to storvsc_drv.c
> 
> On Wed, Jun 29, 2011 at 07:39:31AM -0700, K. Y. Srinivasan wrote:
> > Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup
> storvsc_drv.c.n
> 
> I'd at least leave the first half of the header that defines the
> protocol around.

I only got rid of the block comment at the start of hyperv_storage.h
and consolidated the include files. Nothing of substance was deleted.

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
@ 2011-06-30 20:13         ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 20:13 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Abhishek Kane (Mindtree Consulting PVT LTD),
	Haiyang Zhang, gregkh, linux-kernel, virtualization, devel



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:46 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of
> hyperv_storage.h to storvsc_drv.c
> 
> On Wed, Jun 29, 2011 at 07:39:31AM -0700, K. Y. Srinivasan wrote:
> > Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup
> storvsc_drv.c.n
> 
> I'd at least leave the first half of the header that defines the
> protocol around.

I only got rid of the block comment at the start of hyperv_storage.h
and consolidated the include files. Nothing of substance was deleted.

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
  2011-06-30 19:40       ` Christoph Hellwig
@ 2011-06-30 21:15         ` KY Srinivasan
  -1 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 21:15 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:41 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
> 
> On Wed, Jun 29, 2011 at 07:39:21AM -0700, K. Y. Srinivasan wrote:
> > We use the channel number to distinguish an IDE device managed by the
> > storvsc driver from scsi devices. Add code to get the correct
> > device pointer based on the channel number.
> >
> > Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> > Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> > Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
> > Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
> > ---
> >  drivers/staging/hv/storvsc_drv.c |   10 ++++++++++
> >  1 files changed, 10 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
> > index cf659d7..fcc3f5d 100644
> > --- a/drivers/staging/hv/storvsc_drv.c
> > +++ b/drivers/staging/hv/storvsc_drv.c
> > @@ -517,6 +517,16 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd
> *scmnd,
> >  	unsigned int sg_count = 0;
> >  	struct vmscsi_request *vm_srb;
> >
> > +	if (scmnd->device->channel >= HV_IDE_BASE_CHANNEL) {
> > +		int channel = scmnd->device->channel;
> > +
> > +		/*
> > +		 * This is an IDE device; get the right dev.
> > +		 */
> > +
> > +		dev = ide_devices[channel - HV_IDE_BASE_CHANNEL];
> > +	}
> 
> So instead of playing games about getting the right hv_device here,
> why don't you register one scsi host for each IDE device? libata
> does the same for real ATA devices.
> 
That is what I did initially. Then looking at the way we  were handling scsi devices
where each scsi controller configured for the guest results in an emulated HBA
(scsi host) in the guest and all the block devices under a given controller are
handled through this one host, I decided to mimic a similar structure  - one
scsi host for all the block devices configured as an IDE device.

I can go back to my earlier implementation with one host per disk.

Regards,

K. Y 

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
@ 2011-06-30 21:15         ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 21:15 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:41 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
> 
> On Wed, Jun 29, 2011 at 07:39:21AM -0700, K. Y. Srinivasan wrote:
> > We use the channel number to distinguish an IDE device managed by the
> > storvsc driver from scsi devices. Add code to get the correct
> > device pointer based on the channel number.
> >
> > Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> > Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> > Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
> > Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
> > ---
> >  drivers/staging/hv/storvsc_drv.c |   10 ++++++++++
> >  1 files changed, 10 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
> > index cf659d7..fcc3f5d 100644
> > --- a/drivers/staging/hv/storvsc_drv.c
> > +++ b/drivers/staging/hv/storvsc_drv.c
> > @@ -517,6 +517,16 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd
> *scmnd,
> >  	unsigned int sg_count = 0;
> >  	struct vmscsi_request *vm_srb;
> >
> > +	if (scmnd->device->channel >= HV_IDE_BASE_CHANNEL) {
> > +		int channel = scmnd->device->channel;
> > +
> > +		/*
> > +		 * This is an IDE device; get the right dev.
> > +		 */
> > +
> > +		dev = ide_devices[channel - HV_IDE_BASE_CHANNEL];
> > +	}
> 
> So instead of playing games about getting the right hv_device here,
> why don't you register one scsi host for each IDE device? libata
> does the same for real ATA devices.
> 
That is what I did initially. Then looking at the way we  were handling scsi devices
where each scsi controller configured for the guest results in an emulated HBA
(scsi host) in the guest and all the block devices under a given controller are
handled through this one host, I decided to mimic a similar structure  - one
scsi host for all the block devices configured as an IDE device.

I can go back to my earlier implementation with one host per disk.

Regards,

K. Y 

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 23/40] Staging: hv: storvsc: Introduce code to manage IDE devices using storvsc HBA
  2011-06-30 19:38     ` Christoph Hellwig
@ 2011-06-30 21:38         ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 21:38 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:39 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 23/40] Staging: hv: storvsc: Introduce code to manage IDE
> devices using storvsc HBA
> 
> > +/*
> > + * We want to manage the IDE devices using standard Linux SCSI drivers
> > + * using the storvsc driver.
> > + * Define special channels to support this.
> > + */
> > +
> > +#define HV_MAX_IDE_DEVICES	4
> > +#define HV_IDE_BASE_CHANNEL	10
> > +#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
> > +#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
> > +#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
> > +#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)
> 
> This at last needs a good explanation of why these devices are called
> IDE if they actually aren't.  I know you've explained the reason to me
> before, but it should also be in the code.

These devices are configured as IDE devices for the guest. The current
emulator supports 2 IDE controllers for a total of potentially 4 devices.
I did this to support all these 4 devices under one scsi host and used the
channel information to get at the correct device in the I/O path.
So, if you go to a model with one host per device, this would not be required.
 
> 
> The HV_IDE1_DEVn defines don't seem to useful to me.  They are just
> used in one place, and doing an opencoded HV_IDE_BASE_CHANNEL +
> channel_nr would seem a lot easier to understand to me.
> 
> > +static struct  Scsi_Host *storvsc_host;
> > +
> > +/*
> > + * State to manage IDE devices that register with the storvsc driver.
> > + *
> > + */
> > +static struct hv_device *ide_devices[HV_MAX_IDE_DEVICES];
> > +
> > +static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
> > +{
> > +	*target =
> > +	dev->dev_instance.data[5] << 8 | dev->dev_instance.data[4];
> > +
> > +	*path =
> > +	dev->dev_instance.data[3] << 24 | dev->dev_instance.data[2] << 16 |
> > +	dev->dev_instance.data[1] << 8  | dev->dev_instance.data[0];
> 
> Pretty odd formatting, I'd rather do it as:
> 
> 	*target =
> 		dev->dev_instance.data[5] << 8 |
> 		dev->dev_instance.data[4];
> 
> but more importanly what does path actually stand for here?  Opencoding
> this into the caller and adding proper comments explaining the scheme
> might be more readable.

In the blkvsc driver, the path/target info was used to properly identify the 
device - (a) the device was under the first or second IDE controller and (b)
whether it is the first or second device under the controller. 

Regards,

K. Y

.



^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 23/40] Staging: hv: storvsc: Introduce code to manage IDE devices using storvsc HBA
@ 2011-06-30 21:38         ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 21:38 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:39 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 23/40] Staging: hv: storvsc: Introduce code to manage IDE
> devices using storvsc HBA
> 
> > +/*
> > + * We want to manage the IDE devices using standard Linux SCSI drivers
> > + * using the storvsc driver.
> > + * Define special channels to support this.
> > + */
> > +
> > +#define HV_MAX_IDE_DEVICES	4
> > +#define HV_IDE_BASE_CHANNEL	10
> > +#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
> > +#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
> > +#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
> > +#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)
> 
> This at last needs a good explanation of why these devices are called
> IDE if they actually aren't.  I know you've explained the reason to me
> before, but it should also be in the code.

These devices are configured as IDE devices for the guest. The current
emulator supports 2 IDE controllers for a total of potentially 4 devices.
I did this to support all these 4 devices under one scsi host and used the
channel information to get at the correct device in the I/O path.
So, if you go to a model with one host per device, this would not be required.
 
> 
> The HV_IDE1_DEVn defines don't seem to useful to me.  They are just
> used in one place, and doing an opencoded HV_IDE_BASE_CHANNEL +
> channel_nr would seem a lot easier to understand to me.
> 
> > +static struct  Scsi_Host *storvsc_host;
> > +
> > +/*
> > + * State to manage IDE devices that register with the storvsc driver.
> > + *
> > + */
> > +static struct hv_device *ide_devices[HV_MAX_IDE_DEVICES];
> > +
> > +static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
> > +{
> > +	*target =
> > +	dev->dev_instance.data[5] << 8 | dev->dev_instance.data[4];
> > +
> > +	*path =
> > +	dev->dev_instance.data[3] << 24 | dev->dev_instance.data[2] << 16 |
> > +	dev->dev_instance.data[1] << 8  | dev->dev_instance.data[0];
> 
> Pretty odd formatting, I'd rather do it as:
> 
> 	*target =
> 		dev->dev_instance.data[5] << 8 |
> 		dev->dev_instance.data[4];
> 
> but more importanly what does path actually stand for here?  Opencoding
> this into the caller and adding proper comments explaining the scheme
> might be more readable.

In the blkvsc driver, the path/target info was used to properly identify the 
device - (a) the device was under the first or second IDE controller and (b)
whether it is the first or second device under the controller. 

Regards,

K. Y

.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 00/40] Staging: hv: Driver cleanup
  2011-06-30 19:33 ` [PATCH 00/40] Staging: hv: Driver cleanup Christoph Hellwig
@ 2011-06-30 23:28   ` KY Srinivasan
  2011-07-01  8:21     ` Christoph Hellwig
  2011-06-30 23:32     ` KY Srinivasan
  1 sibling, 1 reply; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 23:28 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: gregkh, linux-kernel, devel, virtualization



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:34 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org
> Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> 
> On Wed, Jun 29, 2011 at 07:38:21AM -0700, K. Y. Srinivasan wrote:
> > Further cleanup of the hv drivers:
> >
> > 	1) Cleanup the reference counting mess for both stor and net devices.
> 
> I really don't understand the need for reference counting on the storage
> side, especially now that you only have a SCSI driver.  The SCSI
> midlayer does proper counting on it's objects (Scsi_Host, scsi_device,
> scsi_cmnd), so you'll get that for free given that SCSI drivers just
> piggyback on the midlayer lifetime rules.

The reference counting allows us to properly deal with messages coming back from the host
to the guest with a racing remove of the device. I am told these messages could potentially be
not a response to a message sent from the guest.

> 
> For now your patches should probably go in as-is, but mid-term you
> should be able to completely remove that code on the storage side.
> 

Thanks. Sure, we will always try to simplify the code.

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 00/40] Staging: hv: Driver cleanup
  2011-06-30 19:33 ` [PATCH 00/40] Staging: hv: Driver cleanup Christoph Hellwig
@ 2011-06-30 23:32     ` KY Srinivasan
  2011-06-30 23:32     ` KY Srinivasan
  1 sibling, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 23:32 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: gregkh, linux-kernel, devel, virtualization


> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:34 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org
> Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> 
> On Wed, Jun 29, 2011 at 07:38:21AM -0700, K. Y. Srinivasan wrote:
> > Further cleanup of the hv drivers:
> >
> > 	1) Cleanup the reference counting mess for both stor and net devices.
> 
> I really don't understand the need for reference counting on the storage
> side, especially now that you only have a SCSI driver.  The SCSI
> midlayer does proper counting on it's objects (Scsi_Host, scsi_device,
> scsi_cmnd), so you'll get that for free given that SCSI drivers just
> piggyback on the midlayer lifetime rules.
> 
> For now your patches should probably go in as-is, but mid-term you
> should be able to completely remove that code on the storage side.
> 

Greg,

I am thinking of  going back to my original implementation where I had one scsi host
per IDE device. This will certainly simply the code. Let me know what you think. If you
agree with this approach, please drop this patch-set, I will send you a new set of patches.

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 00/40] Staging: hv: Driver cleanup
@ 2011-06-30 23:32     ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-06-30 23:32 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: devel, gregkh, linux-kernel, virtualization


> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Thursday, June 30, 2011 3:34 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org
> Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> 
> On Wed, Jun 29, 2011 at 07:38:21AM -0700, K. Y. Srinivasan wrote:
> > Further cleanup of the hv drivers:
> >
> > 	1) Cleanup the reference counting mess for both stor and net devices.
> 
> I really don't understand the need for reference counting on the storage
> side, especially now that you only have a SCSI driver.  The SCSI
> midlayer does proper counting on it's objects (Scsi_Host, scsi_device,
> scsi_cmnd), so you'll get that for free given that SCSI drivers just
> piggyback on the midlayer lifetime rules.
> 
> For now your patches should probably go in as-is, but mid-term you
> should be able to completely remove that code on the storage side.
> 

Greg,

I am thinking of  going back to my original implementation where I had one scsi host
per IDE device. This will certainly simply the code. Let me know what you think. If you
agree with this approach, please drop this patch-set, I will send you a new set of patches.

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 00/40] Staging: hv: Driver cleanup
  2011-06-30 23:32     ` KY Srinivasan
  (?)
@ 2011-06-30 23:48     ` Stephen Hemminger
  2011-07-01  0:19       ` KY Srinivasan
  -1 siblings, 1 reply; 122+ messages in thread
From: Stephen Hemminger @ 2011-06-30 23:48 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, devel, gregkh, linux-kernel, virtualization

On Thu, 30 Jun 2011 23:32:34 +0000
KY Srinivasan <kys@microsoft.com> wrote:

> 
> > -----Original Message-----
> > From: Christoph Hellwig [mailto:hch@infradead.org]
> > Sent: Thursday, June 30, 2011 3:34 PM
> > To: KY Srinivasan
> > Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> > devel@linuxdriverproject.org; virtualization@lists.osdl.org
> > Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> > 
> > On Wed, Jun 29, 2011 at 07:38:21AM -0700, K. Y. Srinivasan wrote:
> > > Further cleanup of the hv drivers:
> > >
> > > 	1) Cleanup the reference counting mess for both stor and net devices.
> > 
> > I really don't understand the need for reference counting on the storage
> > side, especially now that you only have a SCSI driver.  The SCSI
> > midlayer does proper counting on it's objects (Scsi_Host, scsi_device,
> > scsi_cmnd), so you'll get that for free given that SCSI drivers just
> > piggyback on the midlayer lifetime rules.
> > 
> > For now your patches should probably go in as-is, but mid-term you
> > should be able to completely remove that code on the storage side.
> > 
> 
> Greg,
> 
> I am thinking of  going back to my original implementation where I had one scsi host
> per IDE device. This will certainly simply the code. Let me know what you think. If you
> agree with this approach, please drop this patch-set, I will send you a new set of patches.

I think there ref counting on network devices is also unneeded
as long as the unregister logic handles RCU correctly. The network layer
calls the driver unregister routine after all packets are gone.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 00/40] Staging: hv: Driver cleanup
  2011-06-30 23:48     ` Stephen Hemminger
@ 2011-07-01  0:19       ` KY Srinivasan
  2011-07-01  4:45         ` Stephen Hemminger
  0 siblings, 1 reply; 122+ messages in thread
From: KY Srinivasan @ 2011-07-01  0:19 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Christoph Hellwig, devel, gregkh, linux-kernel, virtualization



> -----Original Message-----
> From: Stephen Hemminger [mailto:shemminger@vyatta.com]
> Sent: Thursday, June 30, 2011 7:48 PM
> To: KY Srinivasan
> Cc: Christoph Hellwig; devel@linuxdriverproject.org; gregkh@suse.de; linux-
> kernel@vger.kernel.org; virtualization@lists.osdl.org
> Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> 
> On Thu, 30 Jun 2011 23:32:34 +0000
> KY Srinivasan <kys@microsoft.com> wrote:
> 
> >
> > > -----Original Message-----
> > > From: Christoph Hellwig [mailto:hch@infradead.org]
> > > Sent: Thursday, June 30, 2011 3:34 PM
> > > To: KY Srinivasan
> > > Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> > > devel@linuxdriverproject.org; virtualization@lists.osdl.org
> > > Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> > >
> > > On Wed, Jun 29, 2011 at 07:38:21AM -0700, K. Y. Srinivasan wrote:
> > > > Further cleanup of the hv drivers:
> > > >
> > > > 	1) Cleanup the reference counting mess for both stor and net devices.
> > >
> > > I really don't understand the need for reference counting on the storage
> > > side, especially now that you only have a SCSI driver.  The SCSI
> > > midlayer does proper counting on it's objects (Scsi_Host, scsi_device,
> > > scsi_cmnd), so you'll get that for free given that SCSI drivers just
> > > piggyback on the midlayer lifetime rules.
> > >
> > > For now your patches should probably go in as-is, but mid-term you
> > > should be able to completely remove that code on the storage side.
> > >
> >
> > Greg,
> >
> > I am thinking of  going back to my original implementation where I had one scsi
> host
> > per IDE device. This will certainly simply the code. Let me know what you think.
> If you
> > agree with this approach, please drop this patch-set, I will send you a new set
> of patches.
> 
> I think there ref counting on network devices is also unneeded
> as long as the unregister logic handles RCU correctly. The network layer
> calls the driver unregister routine after all packets are gone.
On the networking side, what about incoming packets that may be racing
with the device destruction. The current ref counting scheme deals with
that case.

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 00/40] Staging: hv: Driver cleanup
  2011-07-01  0:19       ` KY Srinivasan
@ 2011-07-01  4:45         ` Stephen Hemminger
  2011-07-01 13:25           ` KY Srinivasan
  0 siblings, 1 reply; 122+ messages in thread
From: Stephen Hemminger @ 2011-07-01  4:45 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, devel, gregkh, linux-kernel, virtualization

On Fri, 1 Jul 2011 00:19:38 +0000
KY Srinivasan <kys@microsoft.com> wrote:

> 
> 
> > -----Original Message-----
> > From: Stephen Hemminger [mailto:shemminger@vyatta.com]
> > Sent: Thursday, June 30, 2011 7:48 PM
> > To: KY Srinivasan
> > Cc: Christoph Hellwig; devel@linuxdriverproject.org; gregkh@suse.de; linux-
> > kernel@vger.kernel.org; virtualization@lists.osdl.org
> > Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> > 
> > On Thu, 30 Jun 2011 23:32:34 +0000
> > KY Srinivasan <kys@microsoft.com> wrote:
> > 
> > >
> > > > -----Original Message-----
> > > > From: Christoph Hellwig [mailto:hch@infradead.org]
> > > > Sent: Thursday, June 30, 2011 3:34 PM
> > > > To: KY Srinivasan
> > > > Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> > > > devel@linuxdriverproject.org; virtualization@lists.osdl.org
> > > > Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> > > >
> > > > On Wed, Jun 29, 2011 at 07:38:21AM -0700, K. Y. Srinivasan wrote:
> > > > > Further cleanup of the hv drivers:
> > > > >
> > > > > 	1) Cleanup the reference counting mess for both stor and net devices.
> > > >
> > > > I really don't understand the need for reference counting on the storage
> > > > side, especially now that you only have a SCSI driver.  The SCSI
> > > > midlayer does proper counting on it's objects (Scsi_Host, scsi_device,
> > > > scsi_cmnd), so you'll get that for free given that SCSI drivers just
> > > > piggyback on the midlayer lifetime rules.
> > > >
> > > > For now your patches should probably go in as-is, but mid-term you
> > > > should be able to completely remove that code on the storage side.
> > > >
> > >
> > > Greg,
> > >
> > > I am thinking of  going back to my original implementation where I had one scsi
> > host
> > > per IDE device. This will certainly simply the code. Let me know what you think.
> > If you
> > > agree with this approach, please drop this patch-set, I will send you a new set
> > of patches.
> > 
> > I think there ref counting on network devices is also unneeded
> > as long as the unregister logic handles RCU correctly. The network layer
> > calls the driver unregister routine after all packets are gone.
> On the networking side, what about incoming packets that may be racing
> with the device destruction. The current ref counting scheme deals with
> that case.

Not sure how HV driver tells hypervisor to stop sending packets. But the
destructor is not called until after all other CPU's are done processing
packets from that device.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 38/40] Staging: hv: storvsc: Fixup srb_status for INQUIRY and MODE_SENSE
  2011-06-30 19:59         ` KY Srinivasan
@ 2011-07-01  8:00           ` Christoph Hellwig
  -1 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01  8:00 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Thu, Jun 30, 2011 at 07:59:28PM +0000, KY Srinivasan wrote:
> The reason I did this was so that  I could key off  on real failures indicated by
> srb_status == 0x4 to off-line the device.

Ok.  Please document what your doing in detail in the code, though.


^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 38/40] Staging: hv: storvsc: Fixup srb_status for INQUIRY and MODE_SENSE
@ 2011-07-01  8:00           ` Christoph Hellwig
  0 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01  8:00 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Thu, Jun 30, 2011 at 07:59:28PM +0000, KY Srinivasan wrote:
> The reason I did this was so that  I could key off  on real failures indicated by
> srb_status == 0x4 to off-line the device.

Ok.  Please document what your doing in detail in the code, though.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
  2011-06-30 20:13         ` KY Srinivasan
@ 2011-07-01  8:16           ` Christoph Hellwig
  -1 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01  8:16 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Thu, Jun 30, 2011 at 08:13:51PM +0000, KY Srinivasan wrote:
> > > Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup
> > storvsc_drv.c.n
> > 
> > I'd at least leave the first half of the header that defines the
> > protocol around.
> 
> I only got rid of the block comment at the start of hyperv_storage.h
> and consolidated the include files. Nothing of substance was deleted.

I meant to say keeping a separate header file for the protocol defintion
might be a good idea.  That way it is kept separate from the
implementation details


^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
@ 2011-07-01  8:16           ` Christoph Hellwig
  0 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01  8:16 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Thu, Jun 30, 2011 at 08:13:51PM +0000, KY Srinivasan wrote:
> > > Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup
> > storvsc_drv.c.n
> > 
> > I'd at least leave the first half of the header that defines the
> > protocol around.
> 
> I only got rid of the block comment at the start of hyperv_storage.h
> and consolidated the include files. Nothing of substance was deleted.

I meant to say keeping a separate header file for the protocol defintion
might be a good idea.  That way it is kept separate from the
implementation details

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
  2011-06-30 21:15         ` KY Srinivasan
@ 2011-07-01  8:17           ` Christoph Hellwig
  -1 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01  8:17 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Thu, Jun 30, 2011 at 09:15:54PM +0000, KY Srinivasan wrote:
> That is what I did initially. Then looking at the way we  were handling scsi devices
> where each scsi controller configured for the guest results in an emulated HBA
> (scsi host) in the guest and all the block devices under a given controller are
> handled through this one host, I decided to mimic a similar structure  - one
> scsi host for all the block devices configured as an IDE device.
> 
> I can go back to my earlier implementation with one host per disk.

Was there any downside you noticed from using one host per emulated
disk? 

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
@ 2011-07-01  8:17           ` Christoph Hellwig
  0 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01  8:17 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Abhishek Kane (Mindtree Consulting PVT LTD),
	Haiyang Zhang, gregkh, linux-kernel, Christoph Hellwig,
	virtualization, devel

On Thu, Jun 30, 2011 at 09:15:54PM +0000, KY Srinivasan wrote:
> That is what I did initially. Then looking at the way we  were handling scsi devices
> where each scsi controller configured for the guest results in an emulated HBA
> (scsi host) in the guest and all the block devices under a given controller are
> handled through this one host, I decided to mimic a similar structure  - one
> scsi host for all the block devices configured as an IDE device.
> 
> I can go back to my earlier implementation with one host per disk.

Was there any downside you noticed from using one host per emulated
disk? 

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 23/40] Staging: hv: storvsc: Introduce code to manage IDE devices using storvsc HBA
  2011-06-30 21:38         ` KY Srinivasan
@ 2011-07-01  8:19           ` Christoph Hellwig
  -1 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01  8:19 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Thu, Jun 30, 2011 at 09:38:34PM +0000, KY Srinivasan wrote:
> > > +#define HV_MAX_IDE_DEVICES	4
> > > +#define HV_IDE_BASE_CHANNEL	10
> > > +#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
> > > +#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
> > > +#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
> > > +#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)
> > 
> > This at last needs a good explanation of why these devices are called
> > IDE if they actually aren't.  I know you've explained the reason to me
> > before, but it should also be in the code.
> 
> These devices are configured as IDE devices for the guest. The current
> emulator supports 2 IDE controllers for a total of potentially 4 devices.
> I did this to support all these 4 devices under one scsi host and used the
> channel information to get at the correct device in the I/O path.
> So, if you go to a model with one host per device, this would not be required.

Either way the driver should have a nice comment somewhere explaining
why you have disks that are named IDE but handled spoken to using SCSI
with explicit discovery.

> > but more importanly what does path actually stand for here?  Opencoding
> > this into the caller and adding proper comments explaining the scheme
> > might be more readable.
> 
> In the blkvsc driver, the path/target info was used to properly identify the 
> device - (a) the device was under the first or second IDE controller and (b)
> whether it is the first or second device under the controller. 

Yeah, that's what I got from reading the code.  What confuses me is the
"path" terminology which doesn't really map to any normal nomenclature.


^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 23/40] Staging: hv: storvsc: Introduce code to manage IDE devices using storvsc HBA
@ 2011-07-01  8:19           ` Christoph Hellwig
  0 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01  8:19 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Thu, Jun 30, 2011 at 09:38:34PM +0000, KY Srinivasan wrote:
> > > +#define HV_MAX_IDE_DEVICES	4
> > > +#define HV_IDE_BASE_CHANNEL	10
> > > +#define HV_IDE0_DEV1		HV_IDE_BASE_CHANNEL
> > > +#define HV_IDE0_DEV2		(HV_IDE_BASE_CHANNEL + 1)
> > > +#define HV_IDE1_DEV1		(HV_IDE_BASE_CHANNEL + 2)
> > > +#define HV_IDE1_DEV2		(HV_IDE_BASE_CHANNEL + 3)
> > 
> > This at last needs a good explanation of why these devices are called
> > IDE if they actually aren't.  I know you've explained the reason to me
> > before, but it should also be in the code.
> 
> These devices are configured as IDE devices for the guest. The current
> emulator supports 2 IDE controllers for a total of potentially 4 devices.
> I did this to support all these 4 devices under one scsi host and used the
> channel information to get at the correct device in the I/O path.
> So, if you go to a model with one host per device, this would not be required.

Either way the driver should have a nice comment somewhere explaining
why you have disks that are named IDE but handled spoken to using SCSI
with explicit discovery.

> > but more importanly what does path actually stand for here?  Opencoding
> > this into the caller and adding proper comments explaining the scheme
> > might be more readable.
> 
> In the blkvsc driver, the path/target info was used to properly identify the 
> device - (a) the device was under the first or second IDE controller and (b)
> whether it is the first or second device under the controller. 

Yeah, that's what I got from reading the code.  What confuses me is the
"path" terminology which doesn't really map to any normal nomenclature.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 00/40] Staging: hv: Driver cleanup
  2011-06-30 23:28   ` KY Srinivasan
@ 2011-07-01  8:21     ` Christoph Hellwig
  2011-07-01 13:31       ` KY Srinivasan
  0 siblings, 1 reply; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01  8:21 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization

On Thu, Jun 30, 2011 at 11:28:27PM +0000, KY Srinivasan wrote:
> > On Wed, Jun 29, 2011 at 07:38:21AM -0700, K. Y. Srinivasan wrote:
> > > Further cleanup of the hv drivers:
> > >
> > > 	1) Cleanup the reference counting mess for both stor and net devices.
> > 
> > I really don't understand the need for reference counting on the storage
> > side, especially now that you only have a SCSI driver.  The SCSI
> > midlayer does proper counting on it's objects (Scsi_Host, scsi_device,
> > scsi_cmnd), so you'll get that for free given that SCSI drivers just
> > piggyback on the midlayer lifetime rules.
> 
> The reference counting allows us to properly deal with messages coming back from the host
> to the guest with a racing remove of the device. I am told these messages could potentially be
> not a response to a message sent from the guest.

To deal with that the scsi subsystem has a two stage teardown for the
SCSI host.  First you call scsi_remove_host, at which point no new I/O
to it can be started.  After that you can wait for all outstanding
messages, and finally you do a scsi_host_put to drop the long-term
reference to it, and eventually free it.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
  2011-07-01  8:16           ` Christoph Hellwig
@ 2011-07-01 12:48             ` KY Srinivasan
  -1 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-07-01 12:48 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Friday, July 01, 2011 4:16 AM
> To: KY Srinivasan
> Cc: Christoph Hellwig; gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of
> hyperv_storage.h to storvsc_drv.c
> 
> On Thu, Jun 30, 2011 at 08:13:51PM +0000, KY Srinivasan wrote:
> > > > Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup
> > > storvsc_drv.c.n
> > >
> > > I'd at least leave the first half of the header that defines the
> > > protocol around.
> >
> > I only got rid of the block comment at the start of hyperv_storage.h
> > and consolidated the include files. Nothing of substance was deleted.
> 
> I meant to say keeping a separate header file for the protocol defintion
> might be a good idea.  That way it is kept separate from the
> implementation details
> 
Ok; I get it. Although, a while ago as I was cleaning up the header files
In preparation to exiting staging, Greg had indicated that each driver
should, if possible be a single file. I merged the relevant files to comply
with that directive. 

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
@ 2011-07-01 12:48             ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-07-01 12:48 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Friday, July 01, 2011 4:16 AM
> To: KY Srinivasan
> Cc: Christoph Hellwig; gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of
> hyperv_storage.h to storvsc_drv.c
> 
> On Thu, Jun 30, 2011 at 08:13:51PM +0000, KY Srinivasan wrote:
> > > > Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup
> > > storvsc_drv.c.n
> > >
> > > I'd at least leave the first half of the header that defines the
> > > protocol around.
> >
> > I only got rid of the block comment at the start of hyperv_storage.h
> > and consolidated the include files. Nothing of substance was deleted.
> 
> I meant to say keeping a separate header file for the protocol defintion
> might be a good idea.  That way it is kept separate from the
> implementation details
> 
Ok; I get it. Although, a while ago as I was cleaning up the header files
In preparation to exiting staging, Greg had indicated that each driver
should, if possible be a single file. I merged the relevant files to comply
with that directive. 

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
  2011-07-01  8:17           ` Christoph Hellwig
@ 2011-07-01 13:01             ` KY Srinivasan
  -1 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-07-01 13:01 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Friday, July 01, 2011 4:17 AM
> To: KY Srinivasan
> Cc: Christoph Hellwig; gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
> 
> On Thu, Jun 30, 2011 at 09:15:54PM +0000, KY Srinivasan wrote:
> > That is what I did initially. Then looking at the way we  were handling scsi
> devices
> > where each scsi controller configured for the guest results in an emulated HBA
> > (scsi host) in the guest and all the block devices under a given controller are
> > handled through this one host, I decided to mimic a similar structure  - one
> > scsi host for all the block devices configured as an IDE device.
> >
> > I can go back to my earlier implementation with one host per disk.
> 
> Was there any downside you noticed from using one host per emulated
> disk?
Nothing I could see from whatever testing I did. However, the guest will have
Scsi hosts that the user did not configure. This is certainly the case in both 
approaches - just the numbers are different!

K. Y 

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
@ 2011-07-01 13:01             ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-07-01 13:01 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Friday, July 01, 2011 4:17 AM
> To: KY Srinivasan
> Cc: Christoph Hellwig; gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> Subject: Re: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
> 
> On Thu, Jun 30, 2011 at 09:15:54PM +0000, KY Srinivasan wrote:
> > That is what I did initially. Then looking at the way we  were handling scsi
> devices
> > where each scsi controller configured for the guest results in an emulated HBA
> > (scsi host) in the guest and all the block devices under a given controller are
> > handled through this one host, I decided to mimic a similar structure  - one
> > scsi host for all the block devices configured as an IDE device.
> >
> > I can go back to my earlier implementation with one host per disk.
> 
> Was there any downside you noticed from using one host per emulated
> disk?
Nothing I could see from whatever testing I did. However, the guest will have
Scsi hosts that the user did not configure. This is certainly the case in both 
approaches - just the numbers are different!

K. Y 

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 00/40] Staging: hv: Driver cleanup
  2011-07-01  4:45         ` Stephen Hemminger
@ 2011-07-01 13:25           ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-07-01 13:25 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Christoph Hellwig, devel, gregkh, linux-kernel, virtualization



> -----Original Message-----
> From: Stephen Hemminger [mailto:shemminger@vyatta.com]
> Sent: Friday, July 01, 2011 12:45 AM
> To: KY Srinivasan
> Cc: Christoph Hellwig; devel@linuxdriverproject.org; gregkh@suse.de; linux-
> kernel@vger.kernel.org; virtualization@lists.osdl.org
> Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> 
> On Fri, 1 Jul 2011 00:19:38 +0000
> KY Srinivasan <kys@microsoft.com> wrote:
> 
> >
> >
> > > -----Original Message-----
> > > From: Stephen Hemminger [mailto:shemminger@vyatta.com]
> > > Sent: Thursday, June 30, 2011 7:48 PM
> > > To: KY Srinivasan
> > > Cc: Christoph Hellwig; devel@linuxdriverproject.org; gregkh@suse.de; linux-
> > > kernel@vger.kernel.org; virtualization@lists.osdl.org
> > > Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> > >
> > > On Thu, 30 Jun 2011 23:32:34 +0000
> > > KY Srinivasan <kys@microsoft.com> wrote:
> > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Christoph Hellwig [mailto:hch@infradead.org]
> > > > > Sent: Thursday, June 30, 2011 3:34 PM
> > > > > To: KY Srinivasan
> > > > > Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> > > > > devel@linuxdriverproject.org; virtualization@lists.osdl.org
> > > > > Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> > > > >
> > > > > On Wed, Jun 29, 2011 at 07:38:21AM -0700, K. Y. Srinivasan wrote:
> > > > > > Further cleanup of the hv drivers:
> > > > > >
> > > > > > 	1) Cleanup the reference counting mess for both stor and net
> devices.
> > > > >
> > > > > I really don't understand the need for reference counting on the storage
> > > > > side, especially now that you only have a SCSI driver.  The SCSI
> > > > > midlayer does proper counting on it's objects (Scsi_Host, scsi_device,
> > > > > scsi_cmnd), so you'll get that for free given that SCSI drivers just
> > > > > piggyback on the midlayer lifetime rules.
> > > > >
> > > > > For now your patches should probably go in as-is, but mid-term you
> > > > > should be able to completely remove that code on the storage side.
> > > > >
> > > >
> > > > Greg,
> > > >
> > > > I am thinking of  going back to my original implementation where I had one
> scsi
> > > host
> > > > per IDE device. This will certainly simply the code. Let me know what you
> think.
> > > If you
> > > > agree with this approach, please drop this patch-set, I will send you a new
> set
> > > of patches.
> > >
> > > I think there ref counting on network devices is also unneeded
> > > as long as the unregister logic handles RCU correctly. The network layer
> > > calls the driver unregister routine after all packets are gone.
> > On the networking side, what about incoming packets that may be racing
> > with the device destruction. The current ref counting scheme deals with
> > that case.
> 
> Not sure how HV driver tells hypervisor to stop sending packets. But the
> destructor is not called until after all other CPU's are done processing
> packets from that device.

The issue I was concerned is one where, on packet reception, we need
to de-reference the ext field in the struct hv_device (this is the pointer
to the net device and this could happen concurrently with the guest
trying to shut-down the device. In the current code we deal with this
condition.

Regards,

K. Y  

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
  2011-07-01 13:01             ` KY Srinivasan
@ 2011-07-01 13:27               ` Christoph Hellwig
  -1 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01 13:27 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Fri, Jul 01, 2011 at 01:01:43PM +0000, KY Srinivasan wrote:
> Nothing I could see from whatever testing I did. However, the guest will have
> Scsi hosts that the user did not configure. This is certainly the case in both 
> approaches - just the numbers are different!

If the IDE drivers were real IDE ones you'd also have one Scsi_Host for
each of the as that's how libata handles in.  In a way you're much
closer to real ATA than with the previous block driver.  If your host
side support the ATA passthrough SCSI cdbs you'll even be able to
pass taskfiles to them and use tools like hdparm in the guest.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device
@ 2011-07-01 13:27               ` Christoph Hellwig
  0 siblings, 0 replies; 122+ messages in thread
From: Christoph Hellwig @ 2011-07-01 13:27 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Fri, Jul 01, 2011 at 01:01:43PM +0000, KY Srinivasan wrote:
> Nothing I could see from whatever testing I did. However, the guest will have
> Scsi hosts that the user did not configure. This is certainly the case in both 
> approaches - just the numbers are different!

If the IDE drivers were real IDE ones you'd also have one Scsi_Host for
each of the as that's how libata handles in.  In a way you're much
closer to real ATA than with the previous block driver.  If your host
side support the ATA passthrough SCSI cdbs you'll even be able to
pass taskfiles to them and use tools like hdparm in the guest.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 00/40] Staging: hv: Driver cleanup
  2011-07-01  8:21     ` Christoph Hellwig
@ 2011-07-01 13:31       ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-07-01 13:31 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: gregkh, linux-kernel, devel, virtualization



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: Friday, July 01, 2011 4:22 AM
> To: KY Srinivasan
> Cc: Christoph Hellwig; gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org
> Subject: Re: [PATCH 00/40] Staging: hv: Driver cleanup
> 
> On Thu, Jun 30, 2011 at 11:28:27PM +0000, KY Srinivasan wrote:
> > > On Wed, Jun 29, 2011 at 07:38:21AM -0700, K. Y. Srinivasan wrote:
> > > > Further cleanup of the hv drivers:
> > > >
> > > > 	1) Cleanup the reference counting mess for both stor and net devices.
> > >
> > > I really don't understand the need for reference counting on the storage
> > > side, especially now that you only have a SCSI driver.  The SCSI
> > > midlayer does proper counting on it's objects (Scsi_Host, scsi_device,
> > > scsi_cmnd), so you'll get that for free given that SCSI drivers just
> > > piggyback on the midlayer lifetime rules.
> >
> > The reference counting allows us to properly deal with messages coming back
> from the host
> > to the guest with a racing remove of the device. I am told these messages could
> potentially be
> > not a response to a message sent from the guest.
> 
> To deal with that the scsi subsystem has a two stage teardown for the
> SCSI host.  First you call scsi_remove_host, at which point no new I/O
> to it can be started.  After that you can wait for all outstanding
> messages, and finally you do a scsi_host_put to drop the long-term
> reference to it, and eventually free it.

That is what I have currently implemented both on the stor as well
as the net side with regards to the device specific objects hanging off of
struct hv_device (the ext field). If it is ok with you, I want to do what you
had suggested earlier. Keep the patches as they are with regards to 
reference counting for now. We can always simplify the code later.

Regards,

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
  2011-07-01 12:48             ` KY Srinivasan
@ 2011-07-05 16:12               ` Greg KH
  -1 siblings, 0 replies; 122+ messages in thread
From: Greg KH @ 2011-07-05 16:12 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Fri, Jul 01, 2011 at 12:48:44PM +0000, KY Srinivasan wrote:
> 
> 
> > -----Original Message-----
> > From: Christoph Hellwig [mailto:hch@infradead.org]
> > Sent: Friday, July 01, 2011 4:16 AM
> > To: KY Srinivasan
> > Cc: Christoph Hellwig; gregkh@suse.de; linux-kernel@vger.kernel.org;
> > devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> > Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> > Subject: Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of
> > hyperv_storage.h to storvsc_drv.c
> > 
> > On Thu, Jun 30, 2011 at 08:13:51PM +0000, KY Srinivasan wrote:
> > > > > Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup
> > > > storvsc_drv.c.n
> > > >
> > > > I'd at least leave the first half of the header that defines the
> > > > protocol around.
> > >
> > > I only got rid of the block comment at the start of hyperv_storage.h
> > > and consolidated the include files. Nothing of substance was deleted.
> > 
> > I meant to say keeping a separate header file for the protocol defintion
> > might be a good idea.  That way it is kept separate from the
> > implementation details
> > 
> Ok; I get it. Although, a while ago as I was cleaning up the header files
> In preparation to exiting staging, Greg had indicated that each driver
> should, if possible be a single file. I merged the relevant files to comply
> with that directive. 

Well, do what makes sense.


^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c
@ 2011-07-05 16:12               ` Greg KH
  0 siblings, 0 replies; 122+ messages in thread
From: Greg KH @ 2011-07-05 16:12 UTC (permalink / raw)
  To: KY Srinivasan
  Cc: Christoph Hellwig, gregkh, linux-kernel, devel, virtualization,
	Haiyang Zhang, Abhishek Kane (Mindtree Consulting PVT LTD),
	Hank Janssen

On Fri, Jul 01, 2011 at 12:48:44PM +0000, KY Srinivasan wrote:
> 
> 
> > -----Original Message-----
> > From: Christoph Hellwig [mailto:hch@infradead.org]
> > Sent: Friday, July 01, 2011 4:16 AM
> > To: KY Srinivasan
> > Cc: Christoph Hellwig; gregkh@suse.de; linux-kernel@vger.kernel.org;
> > devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> > Abhishek Kane (Mindtree Consulting PVT LTD); Hank Janssen
> > Subject: Re: [PATCH 34/40] Staging: hv: storvsc: Add the contents of
> > hyperv_storage.h to storvsc_drv.c
> > 
> > On Thu, Jun 30, 2011 at 08:13:51PM +0000, KY Srinivasan wrote:
> > > > > Add the contents of hyperv_storage.h to storvsc_drv.c and cleanup
> > > > storvsc_drv.c.n
> > > >
> > > > I'd at least leave the first half of the header that defines the
> > > > protocol around.
> > >
> > > I only got rid of the block comment at the start of hyperv_storage.h
> > > and consolidated the include files. Nothing of substance was deleted.
> > 
> > I meant to say keeping a separate header file for the protocol defintion
> > might be a good idea.  That way it is kept separate from the
> > implementation details
> > 
> Ok; I get it. Although, a while ago as I was cleaning up the header files
> In preparation to exiting staging, Greg had indicated that each driver
> should, if possible be a single file. I merged the relevant files to comply
> with that directive. 

Well, do what makes sense.

^ permalink raw reply	[flat|nested] 122+ messages in thread

* Re: [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device
  2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
                     ` (38 preceding siblings ...)
  2011-06-29 14:39     ` K. Y. Srinivasan
@ 2011-07-05 16:14   ` Greg KH
  2011-07-05 16:43       ` KY Srinivasan
  39 siblings, 1 reply; 122+ messages in thread
From: Greg KH @ 2011-07-05 16:14 UTC (permalink / raw)
  To: K. Y. Srinivasan
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane

On Wed, Jun 29, 2011 at 07:38:58AM -0700, K. Y. Srinivasan wrote:
> On entry into storvsc_on_io_completion() we have already acquired a reference
> on the stor_device; there is no need to acquire an additional reference here.
> 
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
> Signed-off-by: Hank Janssen <hjanssen@microsoft.com>

This series doesn't apply anymore, care to redo it?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device
  2011-07-05 16:14   ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device Greg KH
@ 2011-07-05 16:43       ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-07-05 16:43 UTC (permalink / raw)
  To: Greg KH
  Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang,
	Abhishek Kane (Mindtree Consulting PVT LTD)



> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Tuesday, July 05, 2011 12:14 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD)
> Subject: Re: [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary
> reference on stor_device
> 
> On Wed, Jun 29, 2011 at 07:38:58AM -0700, K. Y. Srinivasan wrote:
> > On entry into storvsc_on_io_completion() we have already acquired a
> reference
> > on the stor_device; there is no need to acquire an additional reference here.
> >
> > Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> > Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> > Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
> > Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
> 
> This series doesn't apply anymore, care to redo it?

Will do. 

K. Y


^ permalink raw reply	[flat|nested] 122+ messages in thread

* RE: [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device
@ 2011-07-05 16:43       ` KY Srinivasan
  0 siblings, 0 replies; 122+ messages in thread
From: KY Srinivasan @ 2011-07-05 16:43 UTC (permalink / raw)
  To: Greg KH
  Cc: Abhishek Kane (Mindtree Consulting PVT LTD),
	Haiyang Zhang, gregkh, linux-kernel, virtualization, devel



> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Tuesday, July 05, 2011 12:14 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang;
> Abhishek Kane (Mindtree Consulting PVT LTD)
> Subject: Re: [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary
> reference on stor_device
> 
> On Wed, Jun 29, 2011 at 07:38:58AM -0700, K. Y. Srinivasan wrote:
> > On entry into storvsc_on_io_completion() we have already acquired a
> reference
> > on the stor_device; there is no need to acquire an additional reference here.
> >
> > Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> > Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> > Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
> > Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
> 
> This series doesn't apply anymore, care to redo it?

Will do. 

K. Y

^ permalink raw reply	[flat|nested] 122+ messages in thread

end of thread, other threads:[~2011-07-05 16:43 UTC | newest]

Thread overview: 122+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-29 14:38 [PATCH 00/40] Staging: hv: Driver cleanup K. Y. Srinivasan
2011-06-29 14:38 ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device K. Y. Srinivasan
2011-06-29 14:38   ` [PATCH 02/40] Staging: hv: storvsc: Rename must_get_stor_device() K. Y. Srinivasan
2011-06-29 14:38     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 03/40] Staging: hv: storvsc: Rename get_stor_device() K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 04/40] Staging: hv: storvsc: Cleanup alloc_stor_device() K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 05/40] Staging: hv: storvsc: Introduce state to manage the lifecycle of stor device K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 06/40] Staging: hv: vmbus: Introduce a lock to protect the ext field in hv_device K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 07/40] Staging: hv: storvsc: Use the newly introduced lock in accessing ext field K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 08/40] Staging: hv: storvsc: Prevent outgoing traffic when stor dev is destroyed K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 09/40] Staging: hv: storvsc: Get rid of release_stor_device() by inlining the code K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 10/40] Staging: hv: storvsc: Get rid of final_release_stor_device() by inlining code K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 11/40] Staging: hv: storvsc: Leverage the spinlock to manage ref_cnt K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 12/40] Staging: hv: storvsc: Further cleanup reference counting of stor_device K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 13/40] Staging: hv: netvsc: Introduce code to properly manage outstanding sends K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 14/40] Staging: hv: netvsc: Inline the code for free_net_device() K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 15/40] Staging: hv: netvsc: Cleanup alloc_net_device() K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 16/40] Staging: hv: netvsc: Introduce state to manage the lifecycle of net device K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 17/40] Staging: hv: netvsc: Use the newly introduced lock in accessing ext field K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 18/40] Staging: hv: netvsc: Prevent outgoing traffic when netvsc dev is destroyed K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 19/40] Staging: hv: netvsc: Get rid of release_outbound_net_device() by inlining the code K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 20/40] Staging: hv: netvsc: Get rid of release_inbound_net_device() " K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 21/40] Staging: hv: netvsc: Leverage the spinlock to manage ref_cnt K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 22/40] Staging: hv: netvsc: Further cleanup reference counting of netvsc_device K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 23/40] Staging: hv: storvsc: Introduce code to manage IDE devices using storvsc HBA K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-30 19:38     ` Christoph Hellwig
2011-06-30 21:38       ` KY Srinivasan
2011-06-30 21:38         ` KY Srinivasan
2011-07-01  8:19         ` Christoph Hellwig
2011-07-01  8:19           ` Christoph Hellwig
2011-06-29 14:39   ` [PATCH 24/40] Staging: hv: storvsc: On I/O get the correct IDE device K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-30 19:40     ` Christoph Hellwig
2011-06-30 19:40       ` Christoph Hellwig
2011-06-30 21:15       ` KY Srinivasan
2011-06-30 21:15         ` KY Srinivasan
2011-07-01  8:17         ` Christoph Hellwig
2011-07-01  8:17           ` Christoph Hellwig
2011-07-01 13:01           ` KY Srinivasan
2011-07-01 13:01             ` KY Srinivasan
2011-07-01 13:27             ` Christoph Hellwig
2011-07-01 13:27               ` Christoph Hellwig
2011-06-29 14:39   ` [PATCH 25/40] Staging: hv: storvsc: Add state to manage the lifecycle of emulated HBA K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-30 19:44     ` Christoph Hellwig
2011-06-29 14:39   ` [PATCH 26/40] Staging: hv: storvsc: Handle probing IDE devices K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 27/40] Staging: hv: storvsc: Handle IDE devices correctly in storvsc_remove() K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 28/40] Staging: hv: storvsc: Handle IDE devices using the storvsc driver K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 29/40] Staging: hv: storvsc: Optimize bounce buffer handling for the "write" case K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 30/40] Staging: hv: storvsc: Optimize the bounce buffer handling in the "read" case K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 31/40] Staging: hv: storvsc: Get rid of blkvsc_drv.c as this code is not used K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 32/40] Staging: hv: storvsc: Include storvsc.c in storvsc_drv.c K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 33/40] Staging: hv: storvsc: Cleanup storvsc_drv.c after adding the contents of storvsc.c K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 34/40] Staging: hv: storvsc: Add the contents of hyperv_storage.h to storvsc_drv.c K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-30 19:45     ` Christoph Hellwig
2011-06-30 20:13       ` KY Srinivasan
2011-06-30 20:13         ` KY Srinivasan
2011-07-01  8:16         ` Christoph Hellwig
2011-07-01  8:16           ` Christoph Hellwig
2011-07-01 12:48           ` KY Srinivasan
2011-07-01 12:48             ` KY Srinivasan
2011-07-05 16:12             ` Greg KH
2011-07-05 16:12               ` Greg KH
2011-06-29 14:39   ` [PATCH 35/40] Staging: hv: storvsc: Make storvsc_dev_add() a static function K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-30 19:45     ` Christoph Hellwig
2011-06-29 14:39   ` [PATCH 36/40] Staging: hv: storvsc: Make storvsc_dev_remove() " K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 37/40] Staging: hv: storvsc: Make storvsc_do_io() " K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 38/40] Staging: hv: storvsc: Fixup srb_status for INQUIRY and MODE_SENSE K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-30 19:47     ` Christoph Hellwig
2011-06-30 19:59       ` KY Srinivasan
2011-06-30 19:59         ` KY Srinivasan
2011-07-01  8:00         ` Christoph Hellwig
2011-07-01  8:00           ` Christoph Hellwig
2011-06-29 14:39   ` [PATCH 39/40] Staging: hv: storvsc: In case of scsi errors offline the device K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-06-29 14:39   ` [PATCH 40/40] Staging: hv: storvsc: No need to copy from bounce buffer in case of failure K. Y. Srinivasan
2011-06-29 14:39     ` K. Y. Srinivasan
2011-07-05 16:14   ` [PATCH 01/40] Staging: hv: storvsc: Do not aquire an unnecessary reference on stor_device Greg KH
2011-07-05 16:43     ` KY Srinivasan
2011-07-05 16:43       ` KY Srinivasan
2011-06-30 19:33 ` [PATCH 00/40] Staging: hv: Driver cleanup Christoph Hellwig
2011-06-30 23:28   ` KY Srinivasan
2011-07-01  8:21     ` Christoph Hellwig
2011-07-01 13:31       ` KY Srinivasan
2011-06-30 23:32   ` KY Srinivasan
2011-06-30 23:32     ` KY Srinivasan
2011-06-30 23:48     ` Stephen Hemminger
2011-07-01  0:19       ` KY Srinivasan
2011-07-01  4:45         ` Stephen Hemminger
2011-07-01 13:25           ` KY Srinivasan

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.