blktap: Automatically start tapdisk-ioemu on demand
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.
Signed-off-by Kevin Wolf <[email protected]>
tools/blktap/drivers/blktapctrl.c +67 -16
@@ -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
@@ -235,7 +235,7 @@ static disk_info_t ioemu_disk = {DISK_TYPE_IOEMU ,"ioemu disk" ,"ioemu" , -0 , +1 , #ifdef TAPDISKNULL #endif
tools/ioemu/Makefile +1 -1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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