# HG changeset patch
# User emellor@xxxxxxxxxxxxxxxxxxxxxx
# Node ID d2b957902c6b48fb675ffbde5a46f6d8946c4372
# Parent 64d9190320012e88270a4bbbd418feecb81ede42
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@xxxxxxxxxxxxx>
diff -r 64d919032001 -r d2b957902c6b
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Thu Nov 24
15:57:45 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Thu Nov 24
19:53:09 2005
@@ -117,6 +117,8 @@
info->shadow[i].req.id = i+1;
info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+ info->users = 0;
+
/* Front end dir is a number, which is used as the id. */
info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
dev->data = info;
@@ -265,6 +267,7 @@
XenbusState backend_state)
{
struct blkfront_info *info = dev->data;
+ struct block_device *bd;
DPRINTK("blkfront:backend_changed.\n");
@@ -281,7 +284,18 @@
break;
case XenbusStateClosing:
- blkfront_closing(dev);
+ bd = bdget(info->dev);
+ if (bd == NULL)
+ xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
+
+ down(&bd->bd_sem);
+ if (info->users > 0)
+ xenbus_dev_error(dev, -EBUSY,
+ "Device in use; refusing to close");
+ else
+ blkfront_closing(dev);
+ up(&bd->bd_sem);
+ bdput(bd);
break;
}
}
@@ -414,12 +428,26 @@
int blkif_open(struct inode *inode, struct file *filep)
{
+ struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
+ info->users++;
return 0;
}
int blkif_release(struct inode *inode, struct file *filep)
{
+ struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
+ 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;
+ XenbusState state = xenbus_read_driver_state(dev->otherend);
+
+ if (state == XenbusStateClosing)
+ blkfront_closing(dev);
+ }
return 0;
}
diff -r 64d919032001 -r d2b957902c6b
linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Nov 24 15:57:45 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Nov 24 19:53:09 2005
@@ -127,6 +127,12 @@
struct gnttab_free_callback callback;
struct blk_shadow shadow[BLK_RING_SIZE];
unsigned long shadow_free;
+
+ /**
+ * The number of people holding this device open. We won't allow a
+ * hot-unplug unless this is 0.
+ */
+ int users;
};
extern spinlock_t blkif_io_lock;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|