ia64/xen-unstable

changeset 8043:d2b957902c6b

Added a count of the number of users of this block device, and refuse to close
down the frontend until that number becomes 0. There are no reasonable
semantics for hot-unplugging a block device beneath a mounted filesystem, and
this solution ensures that the guest is not crashed nor the filesystem corruptedby the actions of the administrator.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Thu Nov 24 19:53:09 2005 +0000 (2005-11-24)
parents 64d919032001
children d1e1d6493d1d
files linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Thu Nov 24 15:57:45 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Thu Nov 24 19:53:09 2005 +0000
     1.3 @@ -117,6 +117,8 @@ static int blkfront_probe(struct xenbus_
     1.4  		info->shadow[i].req.id = i+1;
     1.5  	info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
     1.6  
     1.7 +	info->users = 0;
     1.8 +
     1.9  	/* Front end dir is a number, which is used as the id. */
    1.10  	info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
    1.11  	dev->data = info;
    1.12 @@ -265,6 +267,7 @@ static void backend_changed(struct xenbu
    1.13  			    XenbusState backend_state)
    1.14  {
    1.15  	struct blkfront_info *info = dev->data;
    1.16 +	struct block_device *bd;
    1.17  
    1.18  	DPRINTK("blkfront:backend_changed.\n");
    1.19  
    1.20 @@ -281,7 +284,18 @@ static void backend_changed(struct xenbu
    1.21  		break;
    1.22  
    1.23  	case XenbusStateClosing:
    1.24 -		blkfront_closing(dev);
    1.25 +		bd = bdget(info->dev);
    1.26 +		if (bd == NULL)
    1.27 +			xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
    1.28 +
    1.29 +		down(&bd->bd_sem);
    1.30 +		if (info->users > 0)
    1.31 +			xenbus_dev_error(dev, -EBUSY,
    1.32 +					 "Device in use; refusing to close");
    1.33 +		else
    1.34 +			blkfront_closing(dev);
    1.35 +		up(&bd->bd_sem);
    1.36 +		bdput(bd);
    1.37  		break;
    1.38  	}
    1.39  }
    1.40 @@ -414,12 +428,26 @@ static void blkif_restart_queue_callback
    1.41  
    1.42  int blkif_open(struct inode *inode, struct file *filep)
    1.43  {
    1.44 +	struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
    1.45 +	info->users++;
    1.46  	return 0;
    1.47  }
    1.48  
    1.49  
    1.50  int blkif_release(struct inode *inode, struct file *filep)
    1.51  {
    1.52 +	struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
    1.53 +	info->users--;
    1.54 +	if (info->users == 0) {
    1.55 +		/* Check whether we have been instructed to close.  We will
    1.56 +		   have ignored this request initially, as the device was
    1.57 +		   still mounted. */
    1.58 +		struct xenbus_device * dev = info->xbdev;
    1.59 +		XenbusState state = xenbus_read_driver_state(dev->otherend);
    1.60 +
    1.61 +		if (state == XenbusStateClosing)
    1.62 +			blkfront_closing(dev);
    1.63 +	}
    1.64  	return 0;
    1.65  }
    1.66  
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h	Thu Nov 24 15:57:45 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h	Thu Nov 24 19:53:09 2005 +0000
     2.3 @@ -127,6 +127,12 @@ struct blkfront_info
     2.4  	struct gnttab_free_callback callback;
     2.5  	struct blk_shadow shadow[BLK_RING_SIZE];
     2.6  	unsigned long shadow_free;
     2.7 +
     2.8 +	/**
     2.9 +	 * The number of people holding this device open.  We won't allow a
    2.10 +	 * hot-unplug unless this is 0.
    2.11 +	 */
    2.12 +	int users;
    2.13  };
    2.14  
    2.15  extern spinlock_t blkif_io_lock;