* 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 diff -r 1bbb4a55cfe3 -r 87be4d8c53a4 drivers/block/xen-blkfront.c --- a/drivers/block/xen-blkfront.c Fri Apr 30 14:58:59 2010 -0700 +++ b/drivers/block/xen-blkfront.c Fri Apr 30 14:58:59 2010 -0700 @@ -534,6 +534,39 @@ 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 @@ } /** - * 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, @@ -1075,8 +1065,11 @@ 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; @@ -1127,11 +1120,13 @@ 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); + } } return 0; }