Skip to contentSkip to conversation

Ad I/O suspend/resume to blktap

PATCH New Ben Guthro 1 participant 1 message Aug 27, 2007 Xen hypervisor interface

lore
Share & tools
lore

Ben Guthro

author
#0 lore raw

PATCH 1/1 Ad I/O suspend/resume to blktap

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
drivers/xen/blktap/blktap.c +58 -0
diff -r 8341d8acbd7c drivers/xen/blktap/blktap.c
@@ -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)
drivers/xen/blktap/common.h +1 -0
diff -r 8341d8acbd7c drivers/xen/blktap/common.h
@@ -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__ */
drivers/xen/blktap/xenbus.c +4 -1
diff -r 8341d8acbd7c drivers/xen/blktap/xenbus.c
@@ -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
[email protected]
http://lists.xensource.com/xen-devel