This patch adds I/O suspend / resume functionality to blktap.
When suspending ...
I/O requests and ignored
inflight I/Os are completed (up to the 5 min timeout)
the suspend() call is synchronous (with a 5 min timeout)
tapdisk associated with the vdisk is shot down (SIGHUP)
internal I/O "scheduler" thread is cancelled
When resuming ...
blktap is directed to process I/O requests once again.
tapdisk is resurected via blktapcntrl and a xenstore watch
internal I/O "scheduler" thread is created
Signed-off-by: Ben Guthro
Signed-off-by: Josh Nicholas <jnicholas@xxxxxxxxxxxxxxx>
diff -r 8341d8acbd7c drivers/xen/blktap/blktap.c
--- a/drivers/xen/blktap/blktap.c Thu Aug 02 10:38:33 2007 -0400
+++ b/drivers/xen/blktap/blktap.c Thu Aug 02 10:38:33 2007 -0400
@@ -52,6 +52,7 @@
#include <linux/major.h>
#include <linux/gfp.h>
#include <linux/poll.h>
+#include <linux/delay.h>
#include <asm/tlbflush.h>
#define MAX_TAP_DEV 256 /*the maximum number of tapdisk ring devices */
@@ -550,6 +551,63 @@ void signal_tapdisk(int idx)
info->blkif = NULL;
return;
+}
+
+int ensure_tapdisk_shutdown(blkif_t *blkif)
+{
+ int err;
+ tap_blkif_t *info;
+ unsigned int cntr;
+
+ info = tapfds[blkif->dev_num];
+ if (info == NULL) {
+ WPRINTK("%s() tapdisk info is missing for %d\n", __FUNCTION__,
(int)blkif->domid);
+ return -EINVAL;
+ }
+
+ if (info->pid < 1)
+ return 0;
+
+#define kTAPDISK_SIGHUP_TIMEOUT_IN_SECS 10
+#define kTAPDISK_SIGKILL_TIMEOUT_IN_SECS 8
+
+ err = kill_proc(info->pid, SIGHUP, 1);
+ if (err && (err != -ESRCH) && find_task_by_pid(info->pid)) {
+ WPRINTK("%s() SIGHUP to %u failed (%d) - attempting SIGKILL\n",
__FUNCTION__, (unsigned int)info->pid, err);
+ err = kill_proc(info->pid, SIGKILL, 1);
+ if (err && find_task_by_pid(info->pid)) {
+ WPRINTK("%s() SIGKILL to %u failed (%d) - abandoning
!?!\n", __FUNCTION__, (unsigned int)info->pid, err);
+ return err;
+ }
+ }
+
+ DPRINTK("tapdisk %u signaled for %d - now waiting\n", (unsigned
int)info->pid, (int)blkif->domid);
+
+ for (cntr=0;cntr<kTAPDISK_SIGHUP_TIMEOUT_IN_SECS;++cntr) {
+ msleep(1000);
+ if (!find_task_by_pid(info->pid)) {
+ DPRINTK("tapdisk %u for %d done [h:%u]\n", (unsigned
int)info->pid, (int)blkif->domid, cntr);
+ return 0;
+ }
+ }
+
+ DPRINTK("tapdisk %u SIGHUP failed for %d - now SIGKILLing\n", (unsigned
int)info->pid, (int)blkif->domid);
+
+ for (cntr=0;cntr<kTAPDISK_SIGKILL_TIMEOUT_IN_SECS;++cntr) {
+ err = kill_proc(info->pid, SIGKILL, 1);
+ msleep(1000);
+ if (!find_task_by_pid(info->pid)) {
+ DPRINTK("tapdisk %u for %d done [k:%u]\n", (unsigned
int)info->pid, (int)blkif->domid, cntr);
+ return 0;
+ }
+ if (err) {
+ WPRINTK("%s() SIGKILL to %u failed (%d) - abandoning
!?!\n", __FUNCTION__, (unsigned int)info->pid, err);
+ return err;
+ }
+ }
+
+ WPRINTK("%s() tapdisk %u SIGKILLing failed for %d - abandoning !?!\n",
__FUNCTION__, (unsigned int)info->pid, (int)blkif->domid);
+ return -EAGAIN;
}
static int blktap_open(struct inode *inode, struct file *filp)
diff -r 8341d8acbd7c drivers/xen/blktap/common.h
--- a/drivers/xen/blktap/common.h Thu Aug 02 10:38:33 2007 -0400
+++ b/drivers/xen/blktap/common.h Thu Aug 02 10:38:33 2007 -0400
@@ -117,5 +117,6 @@ int tap_blkif_schedule(void *arg);
int dom_to_devid(domid_t domid, int xenbus_id, blkif_t *blkif);
void signal_tapdisk(int idx);
+int ensure_tapdisk_shutdown(blkif_t *blkif);
#endif /* __BLKIF__BACKEND__COMMON_H__ */
diff -r 8341d8acbd7c drivers/xen/blktap/xenbus.c
--- a/drivers/xen/blktap/xenbus.c Thu Aug 02 10:38:33 2007 -0400
+++ b/drivers/xen/blktap/xenbus.c Thu Aug 02 10:38:33 2007 -0400
@@ -178,9 +178,12 @@ static int blktap_remove(struct xenbus_d
be->backend_watch.node = NULL;
}
if (be->blkif) {
- if (be->blkif->xenblkd)
+ if (be->blkif->xenblkd) {
kthread_stop(be->blkif->xenblkd);
+ be->blkif->xenblkd = NULL;
+ }
signal_tapdisk(be->blkif->dev_num);
+ ensure_tapdisk_shutdown(be->blkif);
tap_blkif_free(be->blkif);
be->blkif = NULL;
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|