Commit 67de49c1 authored by K. Y. Srinivasan's avatar K. Y. Srinivasan Committed by Greg Kroah-Hartman
Browse files

Staging: hv: blkvsc_drv: Fix some locking issues



Additional lock related cleanup. Properly serialize access to
state even for command related operations.

Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: default avatarAbhishek Kane <v-abkane@microsoft.com>
Signed-off-by: default avatarHank Janssen <hjanssen@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 6b73e4c0
Loading
Loading
Loading
Loading
+15 −16
Original line number Diff line number Diff line
@@ -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;