# HG changeset patch # User Daniel Stodden # Date 1272506749 25200 # Node ID a781d46d987f8f8a9308412ba50bad4654a3d97c # Parent b324514f8f83ef0d8c7991e2c995400937c540ac 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 diff -r b324514f8f83 -r a781d46d987f drivers/block/xen-blkfront.c --- a/drivers/block/xen-blkfront.c Wed Apr 28 19:05:49 2010 -0700 +++ b/drivers/block/xen-blkfront.c Wed Apr 28 19:05:49 2010 -0700 @@ -1075,18 +1075,41 @@ } } -static int blkfront_remove(struct xenbus_device *dev) +static int blkfront_remove(struct xenbus_device *xbdev) { - struct blkfront_info *info = dev_get_drvdata(&dev->dev); + struct blkfront_info *info = dev_get_drvdata(&xbdev->dev); + struct block_device *bdev = NULL; - dev_dbg(&dev->dev, "blkfront_remove: %s removed\n", dev->nodename); + dev_dbg(&xbdev->dev, "%s removed", xbdev->nodename); blkif_free(info, 0); - if(info->users == 0) + mutex_lock(&info->mutex); + + if (info->gd) + bdev = bdget_disk(info->gd, 0); + + info->xbdev = NULL; + mutex_unlock(&info->mutex); + + if (!bdev) + return 0; + + /* + * The xbdev was removed before we reached the Closed + * state. See if it's safe to remove the disk. If the bdev + * isn't closed yet, then release will take care of it. + */ + + mutex_lock(&bdev->bd_mutex); + + if (!info->users) { + xlvbd_release_gendisk(info); kfree(info); - else - info->xbdev = NULL; + } + + mutex_unlock(&bdev->bd_mutex); + bdput(bdev); return 0; }