From 392a840799f83ac8fadd051ac6663106712ad35d Mon Sep 17 00:00:00 2001 From: Daniel Stodden Date: Sat, 7 Aug 2010 18:45:12 +0200 Subject: [PATCH] --- yaml --- r: 208286 b: refs/heads/master c: 7fd152f4b6ae4f3cf89e4b7a0383cc3c470772fc h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/block/xen-blkfront.c | 49 ++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/[refs] b/[refs] index 6c8edf338461..c49e7938e353 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 139617437aff1f0d3b57c2d7cc60e60efc8fe6c3 +refs/heads/master: 7fd152f4b6ae4f3cf89e4b7a0383cc3c470772fc diff --git a/trunk/drivers/block/xen-blkfront.c b/trunk/drivers/block/xen-blkfront.c index 763a315712cc..49862993f31e 100644 --- a/trunk/drivers/block/xen-blkfront.c +++ b/trunk/drivers/block/xen-blkfront.c @@ -1142,31 +1142,48 @@ static int blkif_open(struct block_device *bdev, fmode_t mode) if (!err) ++info->users; - unlock_kernel(); out: + unlock_kernel(); return err; } static int blkif_release(struct gendisk *disk, fmode_t mode) { struct blkfront_info *info = disk->private_data; + struct block_device *bdev; + struct xenbus_device *xbdev; + lock_kernel(); - info->users--; - if (info->users == 0) { - /* Check whether we have been instructed to close. We will - have ignored this request initially, as the device was - still mounted. */ - struct xenbus_device *dev = info->xbdev; - - if (!dev) { - xlvbd_release_gendisk(info); - kfree(info); - } else if (xenbus_read_driver_state(dev->otherend) - == XenbusStateClosing && info->is_ready) { - xlvbd_release_gendisk(info); - xenbus_frontend_closed(dev); - } + if (--info->users) + goto out; + + bdev = bdget_disk(disk, 0); + bdput(bdev); + + /* + * Check if we have been instructed to close. We will have + * deferred this request, because the bdev was still open. + */ + + mutex_lock(&info->mutex); + xbdev = info->xbdev; + + if (xbdev && xbdev->state == XenbusStateClosing) { + /* pending switch to state closed */ + xlvbd_release_gendisk(info); + xenbus_frontend_closed(info->xbdev); + } + + mutex_unlock(&info->mutex); + + if (!xbdev) { + /* sudden device removal */ + xlvbd_release_gendisk(info); + disk->private_data = NULL; + kfree(info); } + +out: unlock_kernel(); return 0; }