Skip to contentSkip to conversation

blktap: Automatically start tapdisk-ioemu on demand

PATCH New Kevin Wolf 1 participant 1 message Apr 22, 2008

lore
Share & tools
lore

Kevin Wolf

author
#0 lore raw

PATCH 1/1 blktap: Automatically start tapdisk-ioemu on demand

When a domain wants to use a tap:ioemu disk but has no device model, start a tapdisk-ioemu instance as provider. Also, move the creation and removal of communication pipes to xend so that qemu-dm doesn't need the unwanted SIGHUP handler anymore.

tools/blktap/drivers/blktapctrl.c +67 -16
diff -r 08e010c3f251 tools/blktap/drivers/blktapctrl.c
@@ -474,9 +474,8 @@ static int read_msg(int fd, int msgtype,
 
 }
 
-int launch_tapdisk(char *wrctldev, char *rdctldev)
-{
-	char *argv[] = { "tapdisk", wrctldev, rdctldev, NULL };
+static int launch_tapdisk_provider(char **argv)
+{
 	pid_t child;
 	
 	if ((child = fork()) < 0)
@@ -490,7 +489,9 @@ int launch_tapdisk(char *wrctldev, char 
 			    i != STDERR_FILENO)
 				close(i);
 
-		execvp("tapdisk", argv);
+		execvp(argv[0], argv);
+		DPRINTF("execvp failed: %d (%s)\n", errno, strerror(errno));
+		DPRINTF("PATH = %s\n", getenv("PATH"));
 		_exit(1);
 	} else {
 		pid_t got;
@@ -498,28 +499,78 @@ int launch_tapdisk(char *wrctldev, char 
 			got = waitpid(child, NULL, 0);
 		} while (got != child);
 	}
+	return child;
+}
+
+static int launch_tapdisk(char *wrctldev, char *rdctldev)
+{
+	char *argv[] = { "tapdisk", wrctldev, rdctldev, NULL };
+
+	if (launch_tapdisk_provider(argv) < 0)
+		return -1;
+
 	return 0;
 }
 
-/* Connect to qemu-dm */
-static int connect_qemu(blkif_t *blkif)
+static int launch_tapdisk_ioemu(void)
+{
+	char *argv[] = { "tapdisk-ioemu", NULL };
+	return launch_tapdisk_provider(argv);
+}
+
+/* 
+ * Connect to an ioemu based disk provider (qemu-dm or tapdisk-ioemu)
+ *
+ * If the domain has a device model, connect to qemu-dm through the
+ * domain specific pipe. Otherwise use a single tapdisk-ioemu instance
+ * which is represented by domid 0 and provides access for Dom0 and
+ * all DomUs without device model.
+ */
+static int connect_qemu(blkif_t *blkif, int domid)
 {
 	char *rdctldev, *wrctldev;
-	
-	if (asprintf(&rdctldev, BLKTAP_CTRL_DIR "/qemu-read-%d", 
-			blkif->domid) < 0)
-		return -1;
-
-	if (asprintf(&wrctldev, BLKTAP_CTRL_DIR "/qemu-write-%d", 
-			blkif->domid) < 0) {
+
+	static int tapdisk_ioemu_pid = 0;
+	static int dom0_readfd = 0;
+	static int dom0_writefd = 0;
+	
+	if (asprintf(&rdctldev, BLKTAP_CTRL_DIR "/qemu-read-%d", domid) < 0)
+		return -1;
+
+	if (asprintf(&wrctldev, BLKTAP_CTRL_DIR "/qemu-write-%d", domid) < 0) {
 		free(rdctldev);
 		return -1;
 	}
 
 	DPRINTF("Using qemu blktap pipe: %s\n", rdctldev);
 	
-	blkif->fds[READ] = open_ctrl_socket(wrctldev);
-	blkif->fds[WRITE] = open_ctrl_socket(rdctldev);
+	if (domid == 0) {
+		/*
+		 * tapdisk-ioemu exits as soon as the last image is 
+		 * disconnected. Check if it is still running.
+		 */
+		if (tapdisk_ioemu_pid == 0 || kill(tapdisk_ioemu_pid, 0)) {
+			/* No device model and tapdisk-ioemu doesn't run yet */
+			DPRINTF("Launching tapdisk-ioemu\n");
+			tapdisk_ioemu_pid = launch_tapdisk_ioemu();
+			
+			dom0_readfd = open_ctrl_socket(wrctldev);
+			dom0_writefd = open_ctrl_socket(rdctldev);
+		}
+
+		DPRINTF("Using tapdisk-ioemu connection\n");
+		blkif->fds[READ] = dom0_readfd;
+		blkif->fds[WRITE] = dom0_writefd;
+	} else if (access(rdctldev, R_OK | W_OK) == 0) {
+		/* Use existing pipe to the device model */
+		DPRINTF("Using qemu-dm connection\n");
+		blkif->fds[READ] = open_ctrl_socket(wrctldev);
+		blkif->fds[WRITE] = open_ctrl_socket(rdctldev);
+	} else {
+		/* No device model => try with tapdisk-ioemu */
+		DPRINTF("No device model\n");
+		connect_qemu(blkif, 0);
+	}
 	
 	free(rdctldev);
 	free(wrctldev);
@@ -599,7 +650,7 @@ int blktapctrl_new_blkif(blkif_t *blkif)
 
 		if (!exist) {
 			if (type == DISK_TYPE_IOEMU) {
-				if (connect_qemu(blkif))
+				if (connect_qemu(blkif, blkif->domid))
 					goto fail;
 			} else {
 				if (connect_tapdisk(blkif, minor))
tools/blktap/drivers/tapdisk.h +1 -1
diff -r 08e010c3f251 tools/blktap/drivers/tapdisk.h
@@ -235,7 +235,7 @@ static disk_info_t ioemu_disk = {
 	DISK_TYPE_IOEMU,
 	"ioemu disk",
 	"ioemu",
-	0,
+	1,
 #ifdef TAPDISK
 	NULL
 #endif
tools/ioemu/Makefile +1 -1
diff -r 08e010c3f251 tools/ioemu/Makefile
@@ -87,7 +87,7 @@ endif
 
 install: all $(if $(BUILD_DOCS),install-doc)
 	mkdir -p "$(DESTDIR)$(bindir)"
-	$(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(prefix)/sbin"
+	$(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(SBINDIR)"
 #	mkdir -p "$(DESTDIR)$(datadir)"
 #	for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
 #		video.x openbios-sparc32 linux_boot.bin pxe-ne2k_pci.bin \
tools/ioemu/hw/xen_blktap.c +1 -44

68 lines not on this page · raw message

tools/ioemu/tapdisk-ioemu.c +14 -0
diff -r 08e010c3f251 tools/ioemu/tapdisk-ioemu.c
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <stdint.h>
 #include <signal.h>
+#include <unistd.h>
 #include <sys/time.h>
 
 #include <assert.h>
@@ -15,6 +16,8 @@ extern void bdrv_init(void);
 
 extern void *qemu_mallocz(size_t size);
 extern void qemu_free(void *ptr);
+
+extern void *fd_start;
 
 int domid = 0;
 FILE* logfile;
@@ -95,12 +98,17 @@ int main(void)
     int max_fd;
     fd_set rfds;
     struct timeval tv;
+    void *old_fd_start = NULL;
 
     logfile = stderr;
     
     bdrv_init();
     qemu_aio_init();
     init_blktap();
+
+    /* Daemonize */
+    if (fork() != 0)
+    	exit(0);
    
     /* 
      * Main loop: Pass events to the corrsponding handlers and check for
@@ -137,6 +145,12 @@ int main(void)
             } else 
                 pioh = &ioh->next;
         }
+
+        /* Exit when the last image has been closed */
+        if (old_fd_start != NULL && fd_start == NULL)
+            exit(0);
+
+        old_fd_start = fd_start;
     }
     return 0;
 }
tools/ioemu/vl.c +1 -7
diff -r 08e010c3f251 tools/ioemu/vl.c
@@ -6276,12 +6276,6 @@ void qemu_system_powerdown_request(void)
     powerdown_requested = 1;
     if (cpu_single_env)
         cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
-}
-
-static void qemu_sighup_handler(int signal)
-{
-    fprintf(stderr, "Received SIGHUP, terminating.\n");
-    exit(0);
 }
 
 void main_loop_wait(int timeout)
@@ -7979,7 +7973,7 @@ int main(int argc, char **argv)
 
 #ifndef CONFIG_STUBDOM
     /* Unblock SIGTERM and SIGHUP, which may have been blocked by the caller */
-    signal(SIGHUP, qemu_sighup_handler);
+    signal(SIGHUP, SIG_DFL);
     sigemptyset(&set);
     sigaddset(&set, SIGTERM);
     sigaddset(&set, SIGHUP);
tools/python/xen/xend/XendDomainInfo.py +3 -0
diff -r 08e010c3f251 tools/python/xen/xend/XendDomainInfo.py
@@ -1837,6 +1837,9 @@ class XendDomainInfo:
 
         @raise: VmError for invalid devices
         """
+        if self.image:
+            self.image.prepareEnvironment()
+
         ordered_refs = self.info.ordered_device_refs()
         for dev_uuid in ordered_refs:
             devclass, config = self.info['devices'][dev_uuid]
tools/python/xen/xend/image.py +30 -0
diff -r 08e010c3f251 tools/python/xen/xend/image.py
@@ -184,6 +184,30 @@ class ImageHandler:
     def buildDomain(self):
         """Build the domain. Define in subclass."""
         raise NotImplementedError()
+
+    def prepareEnvironment(self):
+        """Prepare the environment for the execution of the domain. This
+        method is called before any devices are set up."""
+        
+        domid = self.vm.getDomid()
+	
+        # Delete left-over pipes
+        try:
+            os.unlink('/var/run/tap/qemu-read-%d' % domid)
+            os.unlink('/var/run/tap/qemu-write-%d' % domid)
+        except:
+            pass
+
+        # No device model, don't create pipes
+        if self.device_model is None:
+            return
+
+        # If we use a device model, the pipes for communication between
+        # blktapctrl and ioemu must be present before the devices are 
+        # created (blktapctrl must access them for new block devices)
+        os.mkfifo('/var/run/tap/qemu-read-%d' % domid, 0600)
+        os.mkfifo('/var/run/tap/qemu-write-%d' % domid, 0600)
+        
 
     # Return a list of cmd line args to the device models based on the
     # xm config file
@@ -411,6 +435,12 @@ class ImageHandler:
             self.pid = None
             state = xstransact.Remove("/local/domain/0/device-model/%i"
                                       % self.vm.getDomid())
+            
+            try:
+                os.unlink('/var/run/tap/qemu-read-%d' % self.vm.getDomid())
+                os.unlink('/var/run/tap/qemu-write-%d' % self.vm.getDomid())
+            except:
+                pass
 
 
 class LinuxImageHandler(ImageHandler):

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel