[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] 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. Signed-off-by: Kevin Wolf <kwolf@xxxxxxx> diff -r 08e010c3f251 tools/blktap/drivers/blktapctrl.c --- a/tools/blktap/drivers/blktapctrl.c Tue Apr 15 16:39:00 2008 +0100 +++ b/tools/blktap/drivers/blktapctrl.c Tue Apr 22 15:20:09 2008 +0200 @@ -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)) diff -r 08e010c3f251 tools/blktap/drivers/tapdisk.h --- a/tools/blktap/drivers/tapdisk.h Tue Apr 15 16:39:00 2008 +0100 +++ b/tools/blktap/drivers/tapdisk.h Tue Apr 22 15:20:09 2008 +0200 @@ -235,7 +235,7 @@ static disk_info_t ioemu_disk = { DISK_TYPE_IOEMU, "ioemu disk", "ioemu", - 0, + 1, #ifdef TAPDISK NULL #endif diff -r 08e010c3f251 tools/ioemu/Makefile --- a/tools/ioemu/Makefile Tue Apr 15 16:39:00 2008 +0100 +++ b/tools/ioemu/Makefile Tue Apr 22 15:20:09 2008 +0200 @@ -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 \ diff -r 08e010c3f251 tools/ioemu/hw/xen_blktap.c --- a/tools/ioemu/hw/xen_blktap.c Tue Apr 15 16:39:00 2008 +0100 +++ b/tools/ioemu/hw/xen_blktap.c Tue Apr 22 15:20:09 2008 +0200 @@ -581,17 +581,13 @@ static void handle_blktap_ctrlmsg(void* */ static int open_ctrl_socket(char *devname) { - int ret; int ipc_fd; if (mkdir(BLKTAP_CTRL_DIR, 0755) == 0) DPRINTF("Created %s directory\n", BLKTAP_CTRL_DIR); - ret = mkfifo(devname,S_IRWXU|S_IRWXG|S_IRWXO); - if ( (ret != 0) && (errno != EEXIST) ) { - DPRINTF("ERROR: pipe failed (%d)\n", errno); + if (access(devname, R_OK | W_OK)) return -1; - } ipc_fd = open(devname,O_RDWR|O_NONBLOCK); @@ -601,42 +597,6 @@ static int open_ctrl_socket(char *devnam } return ipc_fd; -} - -/** - * Unmaps all disks and closes their pipes - */ -void shutdown_blktap(void) -{ - fd_list_entry_t *ptr; - struct td_state *s; - char *devname; - - DPRINTF("Shutdown blktap\n"); - - /* Unmap all disks */ - ptr = fd_start; - while (ptr != NULL) { - s = ptr->s; - unmap_disk(s); - close(ptr->tap_fd); - ptr = ptr->next; - } - - /* Delete control pipes */ - if (asprintf(&devname, BLKTAP_CTRL_DIR "/qemu-read-%d", domid) >= 0) { - DPRINTF("Delete %s\n", devname); - if (unlink(devname)) - DPRINTF("Could not delete: %s\n", strerror(errno)); - free(devname); - } - - if (asprintf(&devname, BLKTAP_CTRL_DIR "/qemu-write-%d", domid) >= 0) { - DPRINTF("Delete %s\n", devname); - if (unlink(devname)) - DPRINTF("Could not delete: %s\n", strerror(errno)); - free(devname); - } } /** @@ -679,8 +639,5 @@ int init_blktap(void) /* Attach a handler to the read pipe (called from qemu main loop) */ qemu_set_fd_handler2(read_fd, NULL, &handle_blktap_ctrlmsg, NULL, NULL); - /* Register handler to clean up when the domain is destroyed */ - atexit(&shutdown_blktap); - return 0; } diff -r 08e010c3f251 tools/ioemu/tapdisk-ioemu.c --- a/tools/ioemu/tapdisk-ioemu.c Tue Apr 15 16:39:00 2008 +0100 +++ b/tools/ioemu/tapdisk-ioemu.c Tue Apr 22 15:20:09 2008 +0200 @@ -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; } diff -r 08e010c3f251 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Tue Apr 15 16:39:00 2008 +0100 +++ b/tools/ioemu/vl.c Tue Apr 22 15:20:09 2008 +0200 @@ -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); diff -r 08e010c3f251 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Tue Apr 15 16:39:00 2008 +0100 +++ b/tools/python/xen/xend/XendDomainInfo.py Tue Apr 22 15:20:09 2008 +0200 @@ -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] diff -r 08e010c3f251 tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Tue Apr 15 16:39:00 2008 +0100 +++ b/tools/python/xen/xend/image.py Tue Apr 22 15:20:09 2008 +0200 @@ -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 Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |