summaryrefslogtreecommitdiffstats
path: root/drivers/block/xen-blkfront.c
diff options
context:
space:
mode:
authorDaniel Stodden <daniel.stodden@citrix.com>2010-08-07 18:33:17 +0200
committerJens Axboe <jaxboe@fusionio.com>2010-08-07 18:38:43 +0200
commita66b5aebb7dc9e695dcb4b528906fd398b63f3d9 (patch)
tree684df2ec45c83f1dc267803f4fdf4ac684bf30d0 /drivers/block/xen-blkfront.c
parentblkfront: Fix gendisk leak (diff)
downloadlinux-a66b5aebb7dc9e695dcb4b528906fd398b63f3d9.tar.xz
linux-a66b5aebb7dc9e695dcb4b528906fd398b63f3d9.zip
blkfront: Clean up vbd release
* Current blkfront_closing is rather a xlvbd_release_gendisk. Renamed in preparation of later patches (need the name again). * Removed the misleading comment -- this only applied to the backend switch handler, and the queue is already flushed btw. * Break out the xenbus call, callers know better when to switch frontend state. Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'drivers/block/xen-blkfront.c')
-rw-r--r--drivers/block/xen-blkfront.c91
1 files changed, 43 insertions, 48 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 62d32959095d..d4cb7fd82b4c 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -534,6 +534,39 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
return err;
}
+static void xlvbd_release_gendisk(struct blkfront_info *info)
+{
+ unsigned int minor, nr_minors;
+ unsigned long flags;
+
+ if (info->rq == NULL)
+ return;
+
+ spin_lock_irqsave(&blkif_io_lock, flags);
+
+ /* No more blkif_request(). */
+ blk_stop_queue(info->rq);
+
+ /* No more gnttab callback work. */
+ gnttab_cancel_free_callback(&info->callback);
+ spin_unlock_irqrestore(&blkif_io_lock, flags);
+
+ /* Flush gnttab callback work. Must be done with no locks held. */
+ flush_scheduled_work();
+
+ del_gendisk(info->gd);
+
+ minor = info->gd->first_minor;
+ nr_minors = info->gd->minors;
+ xlbd_release_minors(minor, nr_minors);
+
+ blk_cleanup_queue(info->rq);
+ info->rq = NULL;
+
+ put_disk(info->gd);
+ info->gd = NULL;
+}
+
static void kick_pending_request_queues(struct blkfront_info *info)
{
if (!RING_FULL(&info->ring)) {
@@ -995,49 +1028,6 @@ static void blkfront_connect(struct blkfront_info *info)
}
/**
- * Handle the change of state of the backend to Closing. We must delete our
- * device-layer structures now, to ensure that writes are flushed through to
- * the backend. Once is this done, we can switch to Closed in
- * acknowledgement.
- */
-static void blkfront_closing(struct blkfront_info *info)
-{
- unsigned int minor, nr_minors;
- unsigned long flags;
-
-
- if (info->rq == NULL)
- goto out;
-
- spin_lock_irqsave(&blkif_io_lock, flags);
-
- /* No more blkif_request(). */
- blk_stop_queue(info->rq);
-
- /* No more gnttab callback work. */
- gnttab_cancel_free_callback(&info->callback);
- spin_unlock_irqrestore(&blkif_io_lock, flags);
-
- /* Flush gnttab callback work. Must be done with no locks held. */
- flush_scheduled_work();
-
- minor = info->gd->first_minor;
- nr_minors = info->gd->minors;
- del_gendisk(info->gd);
- xlbd_release_minors(minor, nr_minors);
-
- blk_cleanup_queue(info->rq);
- info->rq = NULL;
-
- put_disk(info->gd);
- info->gd = NULL;
-
- out:
- if (info->xbdev)
- xenbus_frontend_closed(info->xbdev);
-}
-
-/**
* Callback received when the backend's state changes.
*/
static void blkback_changed(struct xenbus_device *dev,
@@ -1073,8 +1063,11 @@ static void blkback_changed(struct xenbus_device *dev,
if (info->users > 0)
xenbus_dev_error(dev, -EBUSY,
"Device in use; refusing to close");
- else
- blkfront_closing(info);
+ else {
+ xlvbd_release_gendisk(info);
+ xenbus_frontend_closed(info->xbdev);
+ }
+
mutex_unlock(&bd->bd_mutex);
bdput(bd);
break;
@@ -1130,11 +1123,13 @@ static int blkif_release(struct gendisk *disk, fmode_t mode)
struct xenbus_device *dev = info->xbdev;
if (!dev) {
- blkfront_closing(info);
+ xlvbd_release_gendisk(info);
kfree(info);
} else if (xenbus_read_driver_state(dev->otherend)
- == XenbusStateClosing && info->is_ready)
- blkfront_closing(info);
+ == XenbusStateClosing && info->is_ready) {
+ xlvbd_release_gendisk(info);
+ xenbus_frontend_closed(dev);
+ }
}
unlock_kernel();
return 0;