Staging: hv: blkvsc_drv: Fix some locking issues
authorK. Y. Srinivasan <kys@microsoft.com>
Tue, 10 May 2011 14:53:49 +0000 (07:53 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 11 May 2011 20:38:50 +0000 (13:38 -0700)
Additional lock related cleanup. Properly serialize access to
state even for command related operations.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/hv/blkvsc_drv.c

index 74d51bb78701b3d58c289af0e8e8db785fc33272..8a577bc849e56ad395a7d04e225fd13c861ccfad 100644 (file)
@@ -331,10 +331,14 @@ static void blkvsc_cmd_completion(struct hv_storvsc_request *request)
                        (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,
@@ -354,6 +358,7 @@ static int blkvsc_do_operation(struct block_device_context *blkdev,
        unsigned char device_type;
        struct scsi_sense_hdr sense_hdr;
        struct vmscsi_request *vm_srb;
+       unsigned long flags;
 
        int ret = 0;
 
@@ -407,7 +412,9 @@ static int blkvsc_do_operation(struct block_device_context *blkdev,
                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);
 
@@ -555,6 +562,8 @@ static int blkvsc_remove(struct hv_device *dev)
 
        blk_stop_queue(blkdev->gd->queue);
 
+       blkvsc_cancel_pending_reqs(blkdev);
+
        spin_unlock_irqrestore(&blkdev->lock, flags);
 
        while (blkdev->num_outstanding_reqs) {
@@ -563,13 +572,8 @@ static int blkvsc_remove(struct hv_device *dev)
                udelay(100);
        }
 
-       blkvsc_do_operation(blkdev, DO_FLUSH);
-
-       spin_lock_irqsave(&blkdev->lock, flags);
 
-       blkvsc_cancel_pending_reqs(blkdev);
-
-       spin_unlock_irqrestore(&blkdev->lock, flags);
+       blkvsc_do_operation(blkdev, DO_FLUSH);
 
        blk_cleanup_queue(blkdev->gd->queue);
 
@@ -597,6 +601,8 @@ static void blkvsc_shutdown(struct hv_device *dev)
 
        blk_stop_queue(blkdev->gd->queue);
 
+       blkvsc_cancel_pending_reqs(blkdev);
+
        spin_unlock_irqrestore(&blkdev->lock, flags);
 
        while (blkdev->num_outstanding_reqs) {
@@ -605,13 +611,9 @@ static void blkvsc_shutdown(struct hv_device *dev)
                udelay(100);
        }
 
-       blkvsc_do_operation(blkdev, DO_FLUSH);
 
-       spin_lock_irqsave(&blkdev->lock, flags);
-
-       blkvsc_cancel_pending_reqs(blkdev);
+       blkvsc_do_operation(blkdev, DO_FLUSH);
 
-       spin_unlock_irqrestore(&blkdev->lock, flags);
 }
 
 static int blkvsc_release(struct gendisk *disk, fmode_t mode)
@@ -619,16 +621,14 @@ 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 == 1) {
-               spin_unlock_irqrestore(&blkdev->lock, flags);
                blkvsc_do_operation(blkdev, DO_FLUSH);
-               spin_lock_irqsave(&blkdev->lock, flags);
        }
 
+       spin_lock_irqsave(&blkdev->lock, flags);
        blkdev->users--;
-
        spin_unlock_irqrestore(&blkdev->lock, flags);
+
        return 0;
 }
 
@@ -943,7 +943,6 @@ static int blkvsc_probe(struct hv_device *dev)
        struct storvsc_major_info major_info;
        int ret = 0;
 
-
        blkdev = kzalloc(sizeof(struct block_device_context), GFP_KERNEL);
        if (!blkdev) {
                ret = -ENOMEM;