aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Stodden <daniel.stodden@citrix.com>2010-04-30 18:01:22 -0400
committerJens Axboe <jaxboe@fusionio.com>2010-08-07 12:45:27 -0400
commitfa1bd3591a669b92b635dbdb11d1a32a5630821b (patch)
tree41309de6425e854420b26bdcfd94accaf52c3cee
parent7fd152f4b6ae4f3cf89e4b7a0383cc3c470772fc (diff)
blkfront: Lock blockfront_info during xbdev removal
Same approach as blkfront_closing: * Grab the bdev safely, holding the info mutex. * Zap xbdev safely, holding the info mutex. * Try bdev removal safely, holding bd_mutex. Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
-rw-r--r--drivers/block/xen-blkfront.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 49862993f31e..715de7d8ce01 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -1093,18 +1093,47 @@ static void blkback_changed(struct xenbus_device *dev,
1093 } 1093 }
1094} 1094}
1095 1095
1096static int blkfront_remove(struct xenbus_device *dev) 1096static int blkfront_remove(struct xenbus_device *xbdev)
1097{ 1097{
1098 struct blkfront_info *info = dev_get_drvdata(&dev->dev); 1098 struct blkfront_info *info = dev_get_drvdata(&xbdev->dev);
1099 struct block_device *bdev = NULL;
1100 struct gendisk *disk;
1099 1101
1100 dev_dbg(&dev->dev, "blkfront_remove: %s removed\n", dev->nodename); 1102 dev_dbg(&xbdev->dev, "%s removed", xbdev->nodename);
1101 1103
1102 blkif_free(info, 0); 1104 blkif_free(info, 0);
1103 1105
1104 if(info->users == 0) 1106 mutex_lock(&info->mutex);
1107
1108 disk = info->gd;
1109 if (disk)
1110 bdev = bdget_disk(disk, 0);
1111
1112 info->xbdev = NULL;
1113 mutex_unlock(&info->mutex);
1114
1115 if (!bdev) {
1116 kfree(info);
1117 return 0;
1118 }
1119
1120 /*
1121 * The xbdev was removed before we reached the Closed
1122 * state. See if it's safe to remove the disk. If the bdev
1123 * isn't closed yet, we let release take care of it.
1124 */
1125
1126 mutex_lock(&bdev->bd_mutex);
1127 info = disk->private_data;
1128
1129 if (info && !info->users) {
1130 xlvbd_release_gendisk(info);
1131 disk->private_data = NULL;
1105 kfree(info); 1132 kfree(info);
1106 else 1133 }
1107 info->xbdev = NULL; 1134
1135 mutex_unlock(&bdev->bd_mutex);
1136 bdput(bdev);
1108 1137
1109 return 0; 1138 return 0;
1110} 1139}