diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/xen-blkfront.c | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 763a315712cc..49862993f31e 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -1142,31 +1142,48 @@ static int blkif_open(struct block_device *bdev, fmode_t mode) | |||
1142 | if (!err) | 1142 | if (!err) |
1143 | ++info->users; | 1143 | ++info->users; |
1144 | 1144 | ||
1145 | unlock_kernel(); | ||
1146 | out: | 1145 | out: |
1146 | unlock_kernel(); | ||
1147 | return err; | 1147 | return err; |
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | static int blkif_release(struct gendisk *disk, fmode_t mode) | 1150 | static int blkif_release(struct gendisk *disk, fmode_t mode) |
1151 | { | 1151 | { |
1152 | struct blkfront_info *info = disk->private_data; | 1152 | struct blkfront_info *info = disk->private_data; |
1153 | struct block_device *bdev; | ||
1154 | struct xenbus_device *xbdev; | ||
1155 | |||
1153 | lock_kernel(); | 1156 | lock_kernel(); |
1154 | info->users--; | 1157 | if (--info->users) |
1155 | if (info->users == 0) { | 1158 | goto out; |
1156 | /* Check whether we have been instructed to close. We will | 1159 | |
1157 | have ignored this request initially, as the device was | 1160 | bdev = bdget_disk(disk, 0); |
1158 | still mounted. */ | 1161 | bdput(bdev); |
1159 | struct xenbus_device *dev = info->xbdev; | 1162 | |
1160 | 1163 | /* | |
1161 | if (!dev) { | 1164 | * Check if we have been instructed to close. We will have |
1162 | xlvbd_release_gendisk(info); | 1165 | * deferred this request, because the bdev was still open. |
1163 | kfree(info); | 1166 | */ |
1164 | } else if (xenbus_read_driver_state(dev->otherend) | 1167 | |
1165 | == XenbusStateClosing && info->is_ready) { | 1168 | mutex_lock(&info->mutex); |
1166 | xlvbd_release_gendisk(info); | 1169 | xbdev = info->xbdev; |
1167 | xenbus_frontend_closed(dev); | 1170 | |
1168 | } | 1171 | if (xbdev && xbdev->state == XenbusStateClosing) { |
1172 | /* pending switch to state closed */ | ||
1173 | xlvbd_release_gendisk(info); | ||
1174 | xenbus_frontend_closed(info->xbdev); | ||
1175 | } | ||
1176 | |||
1177 | mutex_unlock(&info->mutex); | ||
1178 | |||
1179 | if (!xbdev) { | ||
1180 | /* sudden device removal */ | ||
1181 | xlvbd_release_gendisk(info); | ||
1182 | disk->private_data = NULL; | ||
1183 | kfree(info); | ||
1169 | } | 1184 | } |
1185 | |||
1186 | out: | ||
1170 | unlock_kernel(); | 1187 | unlock_kernel(); |
1171 | return 0; | 1188 | return 0; |
1172 | } | 1189 | } |