blktap: Make the device destruction path synchronous.
diff -r 69301010e4cf -r 6a74cabb7220 drivers/xen/blktap/control.c
--- a/drivers/xen/blktap/control.c Wed Jun 02 19:45:25 2010 -0700
+++ b/drivers/xen/blktap/control.c Wed Jun 02 19:45:25 2010 -0700
@@ -163,46 +163,29 @@
blktap_control_destroy_device(struct blktap *tap)
{
int err;
- unsigned long inuse;
if (!tap)
return 0;
set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse);
- for (;;) {
- inuse = tap->dev_inuse;
- err = blktap_device_destroy(tap);
- if (err)
- goto wait;
+ err = blktap_device_destroy(tap);
+ if (err)
+ return err;
- inuse = tap->dev_inuse;
- err = blktap_ring_destroy(tap);
- if (err)
- goto wait;
+ err = blktap_sysfs_destroy(tap);
+ if (err)
+ return err;
- inuse = tap->dev_inuse;
- err = blktap_sysfs_destroy(tap);
- if (err)
- goto wait;
-
- break;
-
- wait:
- BTDBG("inuse: 0x%lx, dev_inuse: 0x%lx\n",
- inuse, tap->dev_inuse);
- if (wait_event_interruptible(tap->wq, tap->dev_inuse != inuse))
- break;
- }
+ err = blktap_ring_destroy(tap);
+ if (err)
+ return err;
clear_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse);
+ clear_bit(BLKTAP_CONTROL, &tap->dev_inuse);
+ wake_up(&tap->wq);
- if (tap->dev_inuse == (1UL << BLKTAP_CONTROL)) {
- err = 0;
- clear_bit(BLKTAP_CONTROL, &tap->dev_inuse);
- }
-
- return err;
+ return 0;
}
static int __init
diff -r 69301010e4cf -r 6a74cabb7220 drivers/xen/blktap/device.c
--- a/drivers/xen/blktap/device.c Wed Jun 02 19:45:25 2010 -0700
+++ b/drivers/xen/blktap/device.c Wed Jun 02 19:45:25 2010 -0700
@@ -65,7 +65,7 @@
dev->users--;
if (test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
- blktap_device_destroy(tap);
+ blktap_control_destroy_device(tap);
return 0;
}
@@ -306,7 +306,6 @@
unsigned long kvaddr;
usr_idx = request->usr_idx;
- down_write(&tap->ring.vma->vm_mm->mmap_sem);
for (i = 0; i < request->nr_pages; i++) {
kvaddr = request_to_kaddr(request, i);
@@ -324,13 +323,17 @@
}
}
- blktap_device_fast_flush(tap, request);
- up_write(&tap->ring.vma->vm_mm->mmap_sem);
+ if (blktap_active(tap)) {
+ down_write(&tap->ring.vma->vm_mm->mmap_sem);
+ blktap_device_fast_flush(tap, request);
+ up_write(&tap->ring.vma->vm_mm->mmap_sem);
+ }
}
/*
* called if the tapdisk process dies unexpectedly.
* fail and release any pending requests and disable queue.
+ * may be called from non-tapdisk context.
*/
void
blktap_device_fail_pending_requests(struct blktap *tap)
@@ -933,8 +936,11 @@
BTINFO("destroy device %d users %d\n", tap->minor, dev->users);
- if (dev->users)
+ if (dev->users) {
+ blktap_device_fail_pending_requests(tap);
+ blktap_device_restart(tap);
return -EBUSY;
+ }
spin_lock_irq(&dev->lock);
/* No more blktap_device_do_request(). */
@@ -952,8 +958,6 @@
blk_cleanup_queue(gd->queue);
put_disk(gd);
- wake_up(&tap->wq);
-
return 0;
}
diff -r 69301010e4cf -r 6a74cabb7220 drivers/xen/blktap/ring.c
--- a/drivers/xen/blktap/ring.c Wed Jun 02 19:45:25 2010 -0700
+++ b/drivers/xen/blktap/ring.c Wed Jun 02 19:45:25 2010 -0700
@@ -161,24 +161,12 @@
struct blktap *tap = vma_to_blktap(vma);
struct blktap_ring *ring = &tap->ring;
- blktap_device_fail_pending_requests(tap); /* fail pending requests */
- blktap_device_restart(tap); /* fail deferred requests */
+ BTINFO("unmapping ring %d\n", tap->minor);
+ zap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, NULL);
+ clear_bit(BLKTAP_RING_VMA, &tap->dev_inuse);
+ ring->vma = NULL;
- zap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, NULL);
-
- kfree(ring->foreign_map.map);
- ring->foreign_map.map = NULL;
-
- /* Free the ring page. */
- ClearPageReserved(virt_to_page(ring->ring.sring));
- free_page((unsigned long)ring->ring.sring);
-
- BTINFO("unmapping ring %d\n", tap->minor);
- ring->ring.sring = NULL;
- ring->vma = NULL;
- clear_bit(BLKTAP_RING_VMA, &tap->dev_inuse);
-
- wake_up(&tap->wq);
+ blktap_control_destroy_device(tap);
}
static struct vm_operations_struct blktap_ring_vm_operations = {
@@ -206,6 +194,9 @@
if (!test_bit(BLKTAP_CONTROL, &tap->dev_inuse))
return -ENODEV;
+ if (test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
+ return -EBUSY;
+
/* Only one process can access ring at a time */
if (test_and_set_bit(BLKTAP_RING_FD, &tap->dev_inuse))
return -EBUSY;
@@ -224,7 +215,9 @@
BTINFO("freeing device %d\n", tap->minor);
clear_bit(BLKTAP_RING_FD, &tap->dev_inuse);
filp->private_data = NULL;
- wake_up(&tap->wq);
+
+ blktap_control_destroy_device(tap);
+
return 0;
}
diff -r 69301010e4cf -r 6a74cabb7220 drivers/xen/blktap/sysfs.c
--- a/drivers/xen/blktap/sysfs.c Wed Jun 02 19:45:25 2010 -0700
+++ b/drivers/xen/blktap/sysfs.c Wed Jun 02 19:45:25 2010 -0700
@@ -96,7 +96,6 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
- int err;
struct blktap *tap = (struct blktap *)dev_get_drvdata(dev);
if (!tap->ring.dev)
@@ -105,9 +104,13 @@
if (test_and_set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
return -EBUSY;
- err = blktap_control_destroy_device(tap);
+ BTDBG("sending tapdisk close message\n");
+ tap->ring.ring.sring->pad[0] = BLKTAP2_RING_MESSAGE_CLOSE;
+ blktap_ring_kick_user(tap);
+ wait_event_interruptible(tap->wq,
+ !test_bit(BLKTAP_CONTROL, &tap->dev_inuse));
- return (err ? : size);
+ return 0;
}
CLASS_DEVICE_ATTR(remove, S_IWUSR, NULL, blktap_sysfs_remove_device);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|