Пример #1
0
/* Get qemu to change buffers. */
static void qemu_flip_buffer(int domid, int next_active)
{
    char digit = '0' + next_active;
    unsigned int len;
    char *active_str, **watch;
    struct timeval tv;
    fd_set fdset;

    /* Tell qemu that we want it to start writing log-dirty bits to the
     * other buffer */
    if (!xs_write(xs, XBT_NULL, qemu_next_active_path, &digit, 1))
        errx(1, "can't write next-active to store path (%s)\n", 
             qemu_next_active_path);

    /* Wait a while for qemu to signal that it has switched to the new 
     * active buffer */
 read_again: 
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    FD_ZERO(&fdset);
    FD_SET(xs_fileno(xs), &fdset);
    if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1)
        errx(1, "timed out waiting for qemu to switch buffers\n");
    watch = xs_read_watch(xs, &len);
    free(watch);
    
    active_str = xs_read(xs, XBT_NULL, qemu_active_path, &len);
    if (active_str == NULL || active_str[0] - '0' != next_active) 
        /* Watch fired but value is not yet right */
        goto read_again;
}
Пример #2
0
static int get_pty_fd(struct xs_handle *xs, char *path, int seconds)
/* Check for a pty in xenstore, open it and return its fd.
 * Assumes there is already a watch set in the store for this path. */
{
	struct timeval tv;
	fd_set watch_fdset;
	int xs_fd = xs_fileno(xs), pty_fd = -1;
	int start, now;
	unsigned int len = 0;
	char *pty_path, **watch_paths;;

	start = now = time(NULL);
	do {
		tv.tv_usec = 0;
		tv.tv_sec = (start + seconds) - now;
		FD_ZERO(&watch_fdset);
		FD_SET(xs_fd, &watch_fdset);
		if (select(xs_fd + 1, &watch_fdset, NULL, NULL, &tv)) {
			/* Read the watch to drain the buffer */
			watch_paths = xs_read_watch(xs, &len);
			free(watch_paths);
			/* We only watch for one thing, so no need to 
			 * disambiguate: just read the pty path */
			pty_path = xs_read(xs, XBT_NULL, path, &len);
			if (pty_path != NULL) {
				pty_fd = open(pty_path, O_RDWR | O_NOCTTY);
				if (pty_fd == -1) 
					err(errno, "Could not open tty `%s'", 
					    pty_path);
				free(pty_path);
			}
		}
	} while (pty_fd == -1 && (now = time(NULL)) < start + seconds);
	return pty_fd;
}
Пример #3
0
/* Register a QEMU graphical console, and key/mouse handler,
 * connecting up their events to the frontend */
static int xenfb_register_console(struct xenfb *xenfb) {
	/* Register our keyboard & mouse handlers */
	qemu_add_kbd_event_handler(xenfb_key_event, xenfb);
	qemu_add_mouse_event_handler(xenfb_mouse_event, xenfb,
  				     xenfb->abs_pointer_wanted,
  				     "Xen PVFB Mouse");
  
  	/* Tell QEMU to allocate a graphical console */
	graphic_console_init(xenfb->ds,
			     xenfb_update,
			     xenfb_invalidate,
			     xenfb_screen_dump,
			     xenfb);
        if (xenfb->ds->dpy_resize_shared)
            dpy_resize_shared(xenfb->ds, xenfb->width, xenfb->height, xenfb->depth, xenfb->row_stride, xenfb->pixels + xenfb->offset);
        else
            dpy_resize(xenfb->ds, xenfb->width, xenfb->height);

	if (qemu_set_fd_handler2(xc_evtchn_fd(xenfb->evt_xch), NULL, xenfb_dispatch_channel, NULL, xenfb) < 0)
	        return -1;
	if (qemu_set_fd_handler2(xs_fileno(xenfb->xsh), NULL, xenfb_dispatch_store, NULL, xenfb) < 0)
		return -1;

        fprintf(stderr, "Xen Framebuffer registered\n");
        return 0;
}
Пример #4
0
static int get_pty_fd(struct xs_handle *xs, char *path, int seconds)
/* Check for a pty in xenstore, open it and return its fd.
 * Assumes there is already a watch set in the store for this path. */
{
	struct timeval tv;
	fd_set watch_fdset;
	int xs_fd = xs_fileno(xs), pty_fd = -1;
	int start, now;
	unsigned int len = 0;
	char *pty_path, **watch_paths;

	start = now = time(NULL);
	do {
		tv.tv_usec = 0;
		tv.tv_sec = (start + seconds) - now;
		FD_ZERO(&watch_fdset);
		FD_SET(xs_fd, &watch_fdset);
		if (select(xs_fd + 1, &watch_fdset, NULL, NULL, &tv)) {
			/* Read the watch to drain the buffer */
			watch_paths = xs_read_watch(xs, &len);
			free(watch_paths);
			/* We only watch for one thing, so no need to 
			 * disambiguate: just read the pty path */
			pty_path = xs_read(xs, XBT_NULL, path, &len);
			if (pty_path != NULL) {
				if (access(pty_path, R_OK|W_OK) != 0)
					continue;
				pty_fd = open(pty_path, O_RDWR | O_NOCTTY);
				if (pty_fd == -1) 
					err(errno, "Could not open tty `%s'", 
					    pty_path);
				free(pty_path);
			}
		}
	} while (pty_fd == -1 && (now = time(NULL)) < start + seconds);

#ifdef __sun__
	if (pty_fd != -1) {
		struct termios term;

		/*
		 * The pty may come from either xend (with pygrub) or
		 * xenconsoled.  It may have tty semantics set up, or not.
		 * While it isn't strictly necessary to have those
		 * semantics here, it is good to have a consistent
		 * state that is the same as under Linux.
		 *
		 * If tcgetattr fails, they have not been set up,
		 * so go ahead and set them up now, by pushing the
		 * ptem and ldterm streams modules.
		 */
		if (tcgetattr(pty_fd, &term) < 0) {
			ioctl(pty_fd, I_PUSH, "ptem");
			ioctl(pty_fd, I_PUSH, "ldterm");
		}
	}
#endif

	return pty_fd;
}
Пример #5
0
static int wait_for_backend_state_change() {
    char keybuf[128];
    int my_domid;
    unsigned int len;

    int backend_state;
    int seconds;
    char *buf, **vec;
    int ret;

    int xs_fd;
    struct timeval tv;
	fd_set watch_fdset;
    int start, now;

    backend_state = STATE_UNDEFINED;
    xs_fd = xs_fileno(xsh);
    start = now = time(NULL);

    my_domid = atoi(xs_read(xsh, 0, "domid", &len));
    snprintf(keybuf, sizeof(keybuf), "/local/domain/0/backend/audio/%d/%d/state", my_domid, device_id);

    /*XXX: hardcoded */
    seconds = 10;
	do {
		tv.tv_usec = 0;
		tv.tv_sec = (start + seconds) - now;
		FD_ZERO(&watch_fdset);
		FD_SET(xs_fd, &watch_fdset);
        ret=select(xs_fd + 1, &watch_fdset, NULL, NULL, &tv);

        if (ret==-1)
            /* error */
            return -1;
        else if (ret) {

			/* Read the watch to drain the buffer */
			vec = xs_read_watch(xsh, &len);

            buf = xs_read(xsh, XBT_NULL, vec[0], &len);
            if (buf == 0) {
                /* usually means that the backend isn't there yet */
                continue;
            };
            backend_state = atoi(buf);

            free(buf);
            free(vec);
		}
        /* else: timeout */
	} while (backend_state == STATE_UNDEFINED && \
            (now = time(NULL)) < start + seconds);

    return backend_state;
}
Пример #6
0
char* clickos_read_handler(int domid, char *elem, char *attr)
{
	char *ctrlpath = NULL, *elempath = NULL;
	char *rpath = NULL, *wpath = NULL;
	char *value;
	int err;
	unsigned int len = 0;
	struct pollfd fds[1];

	if (!xs) {
		xenstore_init(domid);
	}

	asprintf(&ctrlpath, "/local/domain/%d/clickos/0/control", domid);
	asprintf(&elempath, "/local/domain/%d/clickos/0/elements", domid);
	asprintf(&wpath, "%s/read/%s/%s", ctrlpath, elem, attr);
	asprintf(&rpath, "%s/%s/%s", elempath, elem, attr);

	th = xs_transaction_start(xs);
	xenstore_write(wpath, " ");
	xs_transaction_end(xs, th, 0);

	err = xs_watch(xs, rpath, "lock");
	if (!err) {
		printf("Error setting a watch\n");
		return NULL;
	}

	fds[0].fd = xs_fileno(xs);
	fds[0].events = (POLLIN);
	while (len <= 0) {
	   if (poll(fds, 1, 1000) <= 0) {
		   continue;
	   }

retry_wh:
	   th = xs_transaction_start(xs);
	   //value = xenstore_read(rpath);
	   value = xs_read(xs, XBT_NULL, rpath, &len);
	   //printf("read: len %d value %s\n", len, value);
	   if (!xs_transaction_end(xs, th, 0)) {
			if (errno == EAGAIN)
				goto retry_wh;
	   }
	   usleep(5000);
	}

	err = xs_unwatch(xs, rpath, "lock");
	th = xs_transaction_start(xs);
	xs_write(xs, th, rpath, "", 0);
	err = xs_transaction_end(xs, th, 0);
	return value;
}
Пример #7
0
/* Register a watch against a backend device, and setup
 * QEMU event loop to poll the xenstore FD for notification */
static int xenfb_wait_for_backend(struct xenfb_device *dev, IOHandler *handler)
{
	fprintf(stderr, "Doing backend watch on %s\n", dev->nodename);
	if (!xs_watch(dev->xenfb->xsh, dev->nodename, "")) {
		fprintf(stderr, "Watch for dev failed\n");
		return -1;
	}

	if (qemu_set_fd_handler2(xs_fileno(dev->xenfb->xsh), NULL, handler, NULL, dev) < 0)
		return -1;

	return 0;
}
Пример #8
0
/* returns -1 on error or death, 0 if domain is running, 1 if suspended */
static int check_shutdown(checkpoint_state* s) {
    unsigned int count;
    int xsfd;
    char **vec;
    char buf[16];
    xc_dominfo_t info;

    xsfd = xs_fileno(s->xsh);

    /* loop on watch if it fires for another domain */
    while (1) {
	if (pollfd(s, xsfd) < 0)
	    return -1;

	vec = xs_read_watch(s->xsh, &count);
	if (s->watching_shutdown == 1) {
	    s->watching_shutdown = 2;
	    return 0;
	}
	if (!vec) {
	    fprintf(stderr, "empty watch fired\n");
	    continue;
	}
	snprintf(buf, sizeof(buf), "%d", s->domid);
	if (!strcmp(vec[XS_WATCH_TOKEN], buf))
	    break;
    }

    if (xc_domain_getinfo(s->xch, s->domid, 1, &info) != 1
	|| info.domid != s->domid) {
	snprintf(errbuf, sizeof(errbuf),
		 "error getting info for domain %u", s->domid);
	s->errstr = errbuf;
	return -1;
    }
    if (!info.shutdown) {
	snprintf(errbuf, sizeof(errbuf),
		 "domain %u not shut down", s->domid);
	s->errstr = errbuf;
	return 0;
    }

    if (info.shutdown_reason != SHUTDOWN_suspend)
	return -1;

    return 1;
}
Пример #9
0
static int xenpaging_wait_for_event_or_timeout(struct xenpaging *paging)
{
    xc_interface *xch = paging->xc_handle;
    xc_evtchn *xce = paging->vm_event.xce_handle;
    char **vec, *val;
    unsigned int num;
    struct pollfd fd[2];
    int port;
    int rc;
    int timeout;

    /* Wait for event channel and xenstore */
    fd[0].fd = xc_evtchn_fd(xce);
    fd[0].events = POLLIN | POLLERR;
    fd[1].fd = xs_fileno(paging->xs_handle);
    fd[1].events = POLLIN | POLLERR;

    /* No timeout while page-out is still in progress */
    timeout = paging->use_poll_timeout ? 100 : 0;
    rc = poll(fd, 2, timeout);
    if ( rc < 0 )
    {
        if (errno == EINTR)
            return 0;

        PERROR("Poll exited with an error");
        return -1;
    }

    /* First check for guest shutdown */
    if ( rc && fd[1].revents & POLLIN )
    {
        DPRINTF("Got event from xenstore\n");
        vec = xs_read_watch(paging->xs_handle, &num);
        if ( vec )
        {
            DPRINTF("path '%s' token '%s'\n", vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]);
            if ( strcmp(vec[XS_WATCH_TOKEN], watch_token) == 0 )
            {
                /* If our guest disappeared, set interrupt flag and fall through */
                if ( xs_is_domain_introduced(paging->xs_handle, paging->vm_event.domain_id) == false )
                {
                    xs_unwatch(paging->xs_handle, "@releaseDomain", watch_token);
                    interrupted = SIGQUIT;
                    /* No further poll result processing */
                    rc = 0;
                }
            }
            else if ( strcmp(vec[XS_WATCH_PATH], watch_target_tot_pages) == 0 )
            {
                int ret, target_tot_pages;
                val = xs_read(paging->xs_handle, XBT_NULL, vec[XS_WATCH_PATH], NULL);
                if ( val )
                {
                    ret = sscanf(val, "%d", &target_tot_pages);
                    if ( ret > 0 )
                    {
                        /* KiB to pages */
                        target_tot_pages >>= 2;
                        if ( target_tot_pages < 0 || target_tot_pages > paging->max_pages )
                            target_tot_pages = paging->max_pages;
                        paging->target_tot_pages = target_tot_pages;
                        /* Disable poll() delay while new target is not yet reached */
                        paging->use_poll_timeout = 0;
                        DPRINTF("new target_tot_pages %d\n", target_tot_pages);
                    }
                    free(val);
                }
            }
Пример #10
0
int main(int argc, char **argv)
{
	struct termios attr;
	int domid;
	char *sopt = "h";
	int ch;
	int opt_ind=0;
	struct option lopt[] = {
		{ "help",    0, 0, 'h' },
		{ 0 },

	};
	char *path;
	int spty, xsfd;
	struct xs_handle *xs;
	char *end;

	while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
		switch(ch) {
		case 'h':
			usage(argv[0]);
			exit(0);
			break;
		}
	}
	
	if ((argc - optind) != 1) {
		fprintf(stderr, "Invalid number of arguments\n");
		fprintf(stderr, "Try `%s --help' for more information.\n", 
			argv[0]);
		exit(EINVAL);
	}
	
	domid = strtol(argv[optind], &end, 10);
	if (end && *end) {
		fprintf(stderr, "Invalid DOMID `%s'\n", argv[optind]);
		fprintf(stderr, "Try `%s --help' for more information.\n",
			argv[0]);
		exit(EINVAL);
	}

	xs = xs_daemon_open();
	if (xs == NULL) {
		err(errno, "Could not contact XenStore");
	}

	signal(SIGTERM, sighandler);

	path = xs_get_domain_path(xs, domid);
	if (path == NULL)
		err(errno, "xs_get_domain_path()");
	path = realloc(path, strlen(path) + strlen("/console/tty") + 1);
	if (path == NULL)
		err(ENOMEM, "realloc");
	strcat(path, "/console/tty");

	/* FIXME consoled currently does not assume domain-0 doesn't have a
	   console which is good when we break domain-0 up.  To keep us
	   user friendly, we'll bail out here since no data will ever show
	   up on domain-0. */
	if (domid == 0) {
		fprintf(stderr, "Can't specify Domain-0\n");
		exit(EINVAL);
	}

	/* Set a watch on this domain's console pty */
	if (!xs_watch(xs, path, ""))
		err(errno, "Can't set watch for console pty");
	xsfd = xs_fileno(xs);

	/* Wait a little bit for tty to appear.  There is a race
	   condition that occurs after xend creates a domain.  This code
	   might be running before consoled has noticed the new domain
	   and setup a pty for it. */ 
        spty = get_pty_fd(xs, path, 5);
	if (spty == -1) {
		err(errno, "Could not read tty from store");
	}

	init_term(spty, &attr);
	init_term(STDIN_FILENO, &attr);
	console_loop(spty, xs, path);
	restore_term(STDIN_FILENO, &attr);

	free(path);
	return 0;
 }
Пример #11
0
int main(int argc, char **argv)
{
	sigset_t sigmask;
	struct pollfd pollfds[NPFD_COUNT];
	int npollfds;
	int k;
	int64_t wait_ms;
	struct paging_data pd0;
	struct paging_data pd1;
	bool recheck_time;
	int init_pass = 0;

	/*
	 * if running interactively, output initially to the terminal,
	 * otherwise to syslog right away
	 */
	if (isatty(fileno(stderr)))
	{
		log_fp = stderr;
		log_syslog = false;
	}
	else
	{
		log_fp = NULL;
		log_syslog = true;
	}

	if (log_syslog)
		openlog(progname, LOG_CONS | LOG_PID, LOG_DAEMON);

	/* parse arguments */
	handle_cmdline(argc, argv);

	if (run_as_daemon)
		daemonize();

	debug_msg(1, "debug level set to %d", debug_level);

	// page_size = sysconf(_SC_PAGESIZE);
	// if (page_size <= 0)
	//	fatal_msg("unable to get system page size");

	/*
	 * Block signals so that they aren't handled according to their
	 * default dispositions
	 */
	sigemptyset(&sigmask);
	sigaddset(&sigmask, SIGHUP);
	sigaddset(&sigmask, SIGTERM);
        if (sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0)
		fatal_perror("sigprocmask");

	/*
	 * Receive signals on file descriptors
	 */
	sigemptyset(&sigmask);
	sigaddset(&sigmask, SIGHUP);
	fd_sighup = signalfd(-1, &sigmask, 0);
	if (fd_sighup < 0)
		fatal_perror("signalfd(SIGHUP)");

	sigemptyset(&sigmask);
	sigaddset(&sigmask, SIGTERM);
	fd_sigterm = signalfd(-1, &sigmask, 0);
	if (fd_sigterm < 0)
		fatal_perror("signalfd(SIGTERM)");

	/* select clock to use */
	select_clk_id();

	/* verify we are running under a hypervisor */
	verify_hypervisor();

	pollfds[NPFD_SIGTERM].fd = fd_sigterm;
	pollfds[NPFD_SIGTERM].events = POLLIN|POLLPRI;

	pollfds[NPFD_SIGHUP].fd = fd_sighup;
	pollfds[NPFD_SIGHUP].events = POLLIN|POLLPRI;

	/* keep xs poll fd last in the array */
	pollfds[NPFD_XS].fd = -1;
	pollfds[NPFD_XS].events = POLLIN|POLLPRI;

	/* initialize xenstore structure */
	initialize_xs(pollfds);
	pollfds[NPFD_XS].fd = xs_fileno(xs);

	get_paging_data(&pd0);

        for (;;)
	{
		try_subscribe_membalance_settings();

		/* calculate sleep time till next sample point */
		if (initialized_xs)
		{
			wait_ms = timespec_diff_ms(pd0.ts, getnow()) + interval * MSEC_PER_SEC;
		}
		else
		{
			/* if xs not initialzied, keep retrying */
			wait_ms = interval * MSEC_PER_SEC;
			if (++init_pass > 30)
				wait_ms *= 2;
		}

		if (wait_ms >= tolerance_ms)
		{
			for (k = 0;  k < countof(pollfds);  k++)
				pollfds[k].revents = 0;

			/* if settings need to be updated, retry in 1 sec or sooner */
			if (need_update_membalance_settings)
				wait_ms = min(wait_ms, MSEC_PER_SEC);

			/* include xs in the poll only if has initialized xs */
			npollfds = countof(pollfds);
			if (!initialized_xs)
				npollfds--;

			if (poll(pollfds, npollfds, wait_ms) < 0)
			{
				if (errno == EINTR)
					continue;
				fatal_perror("poll");
			}

			recheck_time = false;

			handle_signals(pollfds, &recheck_time);

			if (!initialized_xs)
			{
				/* try to initialzie xs */
				initialize_xs(NULL);
				/* if successful, start monitoring page map-in rate */
				if (initialized_xs)
					get_paging_data(&pd0);
				continue;
			}

			if (pollfds[NPFD_XS].revents & (POLLIN|POLLPRI))
			{
				/* a watched value in xenstore has been changed */
				handle_xs_watch();
				recheck_time = true;
			}

			if (need_update_membalance_settings)
				update_membalance_settings();

			if (recheck_time)
			{
				/* go sleep again if wait interval has not expired yet */
				if (timespec_diff_ms(getnow(), pd0.ts) < interval * MSEC_PER_SEC - tolerance_ms)
					continue;
			}
		}

		if (!initialized_xs)
		{
			/* try to initialzie xs */
			initialize_xs(NULL);
			/* if successful, start monitoring page map-in rate */
			if (initialized_xs)
				get_paging_data(&pd0);
			continue;
		}

		/* process sample and set it as the new "previous" one */
		get_paging_data(&pd1);
		process_sample(&pd1, &pd0);
		pd0 = pd1;
	}

	/* close connection to xenstore */
	shutdown_xs();

	return EXIT_SUCCESS;
}
Пример #12
0
bool XenDomainWatcher::waitForDomainsOrTimeout( std::list<DomainInfo> &domains, int ms )
{
	struct pollfd fd;
	bool ret = false;

	fd.revents = 0;
	fd.fd = xs_fileno( xsh_ );
	fd.events = POLLIN | POLLERR;

	int rc = poll( &fd, 1, ms );

	domains.clear();

	if ( rc == 0 )
		return false; // timeout

	if ( fd.revents & POLLIN ) {

		unsigned int num;
		char **vec = xs_read_watch( xsh_, &num );

		if ( vec && introduceToken_ == vec[XS_WATCH_TOKEN] ) {

			int domid = 1;
			xc_dominfo_t dominfo;
			int err = -1;

			while ( ( err = xc_domain_getinfo( xci_, domid, 1, &dominfo ) ) == 1 ) {
				domid = dominfo.domid + 1;

				if ( xs_is_domain_introduced( xsh_, dominfo.domid ) ) {

					// New domain
					if ( domIds_.find( dominfo.domid ) == domIds_.end() ) {

						domIds_.insert( dominfo.domid );

						std::stringstream ss;
						ss << "/local/domain/" << dominfo.domid << "/name";

						std::string path = ss.str();

						errno = 0;
						char *name = static_cast<char *>(
						        xs_read_timeout( xsh_, XBT_NULL, path.c_str(), NULL, 1 ) );

						if ( !name && errno && logHelper_ )
							logHelper_->error( std::string( "xs_read() error reading " ) +
							                   ss.str() + ": " + strerror( errno ) );

						if ( name ) { // domain running or new domain w name set

							ss.str( "" );
							ss << "/local/domain/" << dominfo.domid << "/console/tty";
							path = ss.str();

							DomainInfo domain;

							errno = 0;
							void *console = xs_read_timeout( xsh_, XBT_NULL, path.c_str(),
							                                 NULL, 1 );

							if ( !console && errno && logHelper_ )
								logHelper_->error(
								        std::string( "xs_read() error reading " ) +
								        ss.str() + ": " + strerror( errno ) );

							if ( console ) {
								free( console );
								domain.isAlreadyRunning = true;
							}
							else {
								domain.isAlreadyRunning = false;
							}

							domain.name = name;
							free( name );

							domains.push_back( domain );
							ret = true;
						}
						else { // new domain, name not yet set
							ss.str( "" );
							ss << "dom" << dominfo.domid;
							xs_watch( xsh_, path.c_str(), ss.str().c_str() );
						}
					}
				}
			}

			if ( err == -1 && ( errno == EACCES || errno == EPERM ) )
				throw Exception( "access denied for xc_domain_getinfo()" );
		}

		if ( vec && releaseToken_ == vec[XS_WATCH_TOKEN] ) {

			int domid = 1;
			xc_dominfo_t dominfo;

			while ( xc_domain_getinfo( xci_, domid, 1, &dominfo ) == 1 ) {
				domid = dominfo.domid + 1;

				if ( !xs_is_domain_introduced( xsh_, dominfo.domid ) )
					domIds_.erase( dominfo.domid );
			}
		}

		if ( vec && !strncmp( vec[XS_WATCH_TOKEN], "dom", 3 ) ) {

			int domid = 1;
			if ( sscanf( vec[XS_WATCH_TOKEN], "dom%u", &domid ) == 1 ) {

				char *name = static_cast<char *>(
				        xs_read_timeout( xsh_, XBT_NULL, vec[XS_WATCH_PATH], NULL, 1 ) );

				if ( name ) {
					DomainInfo domain;
					domain.isAlreadyRunning = false;
					domain.name = name;
					free( name );

					domains.push_back( domain );
					xs_unwatch( xsh_, vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN] );

					ret = true;
				}
			}
		}

		free( vec );
	}

	return ret;
}
Пример #13
0
int xenstore_fd(void)
{
    if (xsh)
        return xs_fileno(xsh);
    return -1;
}
Пример #14
0
int
main (int argc, char **argv)
{
  int i;
  struct xs_handle *xs;
  xs_transaction_t th;
  char *path;
  int fd;
  fd_set set;
  int er;
  char **vec;
  unsigned int num_strings;
  char * buf;
  unsigned int len;
  char *program;
  char **arguments;
  int arguments_count;
  pid_t pid;
  int j;
  char *last_value = NULL;
  int status;

  program_name = argv[0];

  i = decode_switches (argc, argv);
  
  if (argc - i < 1)
    usage(1);
  
  path = argv[i++];
  if (argc - i > 0)
  {
    program = argv[i++];
    arguments_count = argc - i;
    
    arguments = malloc(sizeof(char*) * (argc - i + 2));
    arguments[0] = program;
    for (j=0; j<arguments_count; j++)
      arguments[j + 1] = argv[i + j];
    arguments[j + 1] = NULL;
  } else
  {
    program = NULL;
    arguments = NULL;
    arguments_count = 0;
  }
  
  if (want_verbose) {
    printf("Path: %s\n", path);
    if (program)
    {
      printf("Program: %s", program);
      for (i=1; i<arguments_count + 1; i++)
        printf(" %s", arguments[i]);
      printf("\n");
    }
  }
  
  /* Get a connection to the daemon */
  xs = xs_daemon_open();
  if ( xs == NULL ) xs = xs_domain_open();
  if ( xs == NULL ) {
    error("Unable to connect to XenStore");
    exit(1);
  }

  /* Create a watch on /local/domain/0/mynode. */
  er = xs_watch(xs, path, "token");
  if ( er == 0 ) {
    error("Unable to create watch");
    exit(1);
  }

  /* We are notified of read availability on the watch via the
   * file descriptor.
   */
  fd = xs_fileno(xs);
  while (1)
  {
    FD_ZERO(&set);
    FD_SET(fd, &set);
    /* Poll for data. */
    if ( select(fd + 1, &set, NULL, NULL, NULL) > 0
         && FD_ISSET(fd, &set))
    {
      /* num_strings will be set to the number of elements in vec
       * (typically, 2 - the watched path and the token) */
      vec = xs_read_watch(xs, &num_strings);
      if ( !vec ) {
        error("Unable to read watch");
        continue;
      }
      if (want_verbose)
        printf("Path changed: %s\n", vec[XS_WATCH_PATH]);
      /* Prepare a transaction and do a read. */
      th = xs_transaction_start(xs);
      buf = xs_read(xs, th, vec[XS_WATCH_PATH], &len);
      xs_transaction_end(xs, th, false);
      if (buf)
      {
        if (last_value && strcmp(buf, last_value) == 0) {
          if (want_verbose)
            printf("Value did not change\n");
          continue;
        }
      
        if (want_verbose)
          printf("New value: %s\n", buf);
          
        if (program) {
          pid = fork();
          if (pid == 0) {
            setenv("XENSTORE_WATCH_PATH", vec[XS_WATCH_PATH], 1);
            setenv("XENSTORE_WATCH_VALUE", buf, 1);
            for (i=0; arguments[i]; i++) {
              if (strcmp(arguments[i], "%v") == 0)
                arguments[i] = buf;
              else if (strcmp(arguments[i], "%p") == 0)
                arguments[i] = vec[XS_WATCH_PATH];
            }
            execvp(program, arguments);
            error("Unable to start program");
            exit(1);
          } else {
            waitpid(pid, &status, 0);
          }
        } else {
          if (!want_verbose)
            printf("%s\n", buf);
        }
        
        if (last_value)
          free(last_value);
        last_value = buf;
      }
    }
  }
  /* Cleanup */
  close(fd);
  xs_daemon_close(xs);
  free(path);

  exit(0);
}
Пример #15
0
int main(int argc, char *argv[])
{
    char *devname;
    tapdev_info_t *ctlinfo;
    int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0;
    struct xs_handle *h;
    struct pollfd  pfd[NUM_POLL_FDS];
    pid_t process;
    char buf[128];

    __init_blkif();
    snprintf(buf, sizeof(buf), "BLKTAPCTRL[%d]", getpid());
    openlog(buf, LOG_CONS|LOG_ODELAY, LOG_DAEMON);
    if (daemon(0,0)) {
        DPRINTF("daemon failed (%d)\n", errno);
        goto open_failed;
    }

    print_drivers();
    init_driver_list();
    init_rng();

    register_new_blkif_hook(blktapctrl_new_blkif);
    register_new_devmap_hook(map_new_blktapctrl);
    register_new_unmap_hook(unmap_blktapctrl);

    ctlfd = blktap_interface_open();
    if (ctlfd < 0) {
        DPRINTF("couldn't open blktap interface\n");
        goto open_failed;
    }

#ifdef MEMSHR
    memshr_daemon_initialize();
#endif

retry:
    /* Set up store connection and watch. */
    h = xs_daemon_open();
    if (h == NULL) {
        DPRINTF("xs_daemon_open failed -- "
                "is xenstore running?\n");
        if (count < MAX_ATTEMPTS) {
            count++;
            sleep(2);
            goto retry;
        } else goto open_failed;
    }

    ret = setup_probe_watch(h);
    if (ret != 0) {
        DPRINTF("Failed adding device probewatch\n");
        xs_daemon_close(h);
        goto open_failed;
    }

    ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );

    process = getpid();
    write_pidfile(process);
    ret = ioctl(ctlfd, BLKTAP_IOCTL_SENDPID, process );

    /*Static pollhooks*/
    pfd_count = 0;
    tap_pfd = pfd_count++;
    pfd[tap_pfd].fd = ctlfd;
    pfd[tap_pfd].events = POLLIN;

    store_pfd = pfd_count++;
    pfd[store_pfd].fd = xs_fileno(h);
    pfd[store_pfd].events = POLLIN;

    while (run) {
        timeout = 1000; /*Milliseconds*/
        ret = poll(pfd, pfd_count, timeout);

        if (ret > 0) {
            if (pfd[store_pfd].revents) {
                ret = xs_fire_next_watch(h);
            }
        }
    }

    xs_daemon_close(h);
    ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH );
    close(ctlfd);
    closelog();

    return 0;

open_failed:
    DPRINTF("Unable to start blktapctrl\n");
    closelog();
    return -1;
}
Пример #16
0
int xenbus_get_watch_fd(void)
{
    assert(xsh != NULL);
    assert(xs_watch(xsh, WATCH_NODE, "conn-watch"));
    return xs_fileno(xsh); 
}
Пример #17
0
int main(int argc, char **argv)
{
	struct termios attr;
	int domid;
	char *sopt = "hn:";
	int ch;
	unsigned int num = 0;
	int opt_ind=0;
	struct option lopt[] = {
		{ "type",     1, 0, 't' },
		{ "num",     1, 0, 'n' },
		{ "help",    0, 0, 'h' },
		{ 0 },

	};
	char *dom_path = NULL, *path = NULL;
	int spty, xsfd;
	struct xs_handle *xs;
	char *end;
	console_type type = CONSOLE_INVAL;

	while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
		switch(ch) {
		case 'h':
			usage(argv[0]);
			exit(0);
			break;
		case 'n':
			num = atoi(optarg);
			break;
		case 't':
			if (!strcmp(optarg, "serial"))
				type = CONSOLE_SERIAL;
			else if (!strcmp(optarg, "pv"))
				type = CONSOLE_PV;
			else {
				fprintf(stderr, "Invalid type argument\n");
				fprintf(stderr, "Console types supported are: serial, pv\n");
				exit(EINVAL);
			}
			break;
		default:
			fprintf(stderr, "Invalid argument\n");
			fprintf(stderr, "Try `%s --help' for more information.\n", 
					argv[0]);
			exit(EINVAL);
		}
	}

	if (optind >= argc) {
		fprintf(stderr, "DOMID should be specified\n");
		fprintf(stderr, "Try `%s --help' for more information.\n",
			argv[0]);
		exit(EINVAL);
	}
	domid = strtol(argv[optind], &end, 10);
	if (end && *end) {
		fprintf(stderr, "Invalid DOMID `%s'\n", argv[optind]);
		fprintf(stderr, "Try `%s --help' for more information.\n",
			argv[0]);
		exit(EINVAL);
	}

	xs = xs_daemon_open();
	if (xs == NULL) {
		err(errno, "Could not contact XenStore");
	}

	signal(SIGTERM, sighandler);

	dom_path = xs_get_domain_path(xs, domid);
	if (dom_path == NULL)
		err(errno, "xs_get_domain_path()");
	if (type == CONSOLE_INVAL) {
		xc_dominfo_t xcinfo;
		xc_interface *xc_handle = xc_interface_open(0,0,0);
		if (xc_handle == NULL)
			err(errno, "Could not open xc interface");
		xc_domain_getinfo(xc_handle, domid, 1, &xcinfo);
		/* default to pv console for pv guests and serial for hvm guests */
		if (xcinfo.hvm)
			type = CONSOLE_SERIAL;
		else
			type = CONSOLE_PV;
		xc_interface_close(xc_handle);
	}
	path = malloc(strlen(dom_path) + strlen("/device/console/0/tty") + 5);
	if (path == NULL)
		err(ENOMEM, "malloc");
	if (type == CONSOLE_SERIAL)
		snprintf(path, strlen(dom_path) + strlen("/serial/0/tty") + 5, "%s/serial/%d/tty", dom_path, num);
	else {
		if (num == 0)
			snprintf(path, strlen(dom_path) + strlen("/console/tty") + 1, "%s/console/tty", dom_path);
		else
			snprintf(path, strlen(dom_path) + strlen("/device/console/%d/tty") + 5, "%s/device/console/%d/tty", dom_path, num);
	}

	/* FIXME consoled currently does not assume domain-0 doesn't have a
	   console which is good when we break domain-0 up.  To keep us
	   user friendly, we'll bail out here since no data will ever show
	   up on domain-0. */
	if (domid == 0) {
		fprintf(stderr, "Can't specify Domain-0\n");
		exit(EINVAL);
	}

	/* Set a watch on this domain's console pty */
	if (!xs_watch(xs, path, ""))
		err(errno, "Can't set watch for console pty");
	xsfd = xs_fileno(xs);

	/* Wait a little bit for tty to appear.  There is a race
	   condition that occurs after xend creates a domain.  This code
	   might be running before consoled has noticed the new domain
	   and setup a pty for it. */ 
        spty = get_pty_fd(xs, path, 5);
	if (spty == -1) {
		err(errno, "Could not read tty from store");
	}

	init_term(spty, &attr);
	init_term(STDIN_FILENO, &attr);
	console_loop(spty, xs, path);
	restore_term(STDIN_FILENO, &attr);

	free(path);
	free(dom_path);
	return 0;
 }
Пример #18
0
static int console_loop(int fd, struct xs_handle *xs, char *pty_path)
{
	int ret, xs_fd = xs_fileno(xs), max_fd;

	do {
		fd_set fds;

		FD_ZERO(&fds);
		FD_SET(STDIN_FILENO, &fds);
		max_fd = STDIN_FILENO;
		FD_SET(xs_fd, &fds);
		if (xs_fd > max_fd) max_fd = xs_fd;
		if (fd != -1) FD_SET(fd, &fds);
		if (fd > max_fd) max_fd = fd;

		ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
		if (ret == -1) {
			if (errno == EINTR || errno == EAGAIN) {
				continue;
			}
			return -1;
		}

		if (FD_ISSET(xs_fileno(xs), &fds)) {
			int newfd = get_pty_fd(xs, pty_path, 0);
			if (fd != -1)
				close(fd);
                        if (newfd == -1) 
				/* Console PTY has become invalid */
				return 0;
			fd = newfd;
			continue;
		}

		if (FD_ISSET(STDIN_FILENO, &fds)) {
			ssize_t len;
			char msg[60];

			len = read(STDIN_FILENO, msg, sizeof(msg));
			if (len == 1 && msg[0] == ESCAPE_CHARACTER) {
				return 0;
			} 

			if (len == 0 || len == -1) {
				if (len == -1 &&
				    (errno == EINTR || errno == EAGAIN)) {
					continue;
				}
				return -1;
			}

			if (!write_sync(fd, msg, len)) {
				close(fd);
				fd = -1;
				continue;
			}
		}

		if (fd != -1 && FD_ISSET(fd, &fds)) {
			ssize_t len;
			char msg[512];

			len = read(fd, msg, sizeof(msg));
			if (len == 0 || len == -1) {
				if (len == -1 &&
				    (errno == EINTR || errno == EAGAIN)) {
					continue;
				}
				close(fd);
				fd = -1;
				continue;
			}

			if (!write_sync(STDOUT_FILENO, msg, len)) {
				perror("write() failed");
				return -1;
			}
		}
	} while (received_signal == 0);

	return 0;
}
Пример #19
0
main(
int argc, char **argv)
{

	vxt_db_start_arg_t         start_db_args;
	struct xs_handle *xs;
	char    token;
	char   **vec;
	char   *tail;
	int    ret;
	int    parse_result;
	int    num;
	int    domid;
	int    auth_dev;
	fd_set set;
	int    fd;
	char   target_uuid[MAX_VXT_UUID] = " ";
	int is_provision = 0;

	if (daemon(0, 0) < 0) {
		perror("daemon");
	}

	auth_dev = open(VXT_AUTH_DEVICE_NAME, O_RDWR);
	if(auth_dev < 0) {
		printf("main: Failed to open the Vxt authorization" 
		       " database device\n");
	}

	/*
	 * Start the database if it hasn't already been 
	 * started
	 */
	
	strncpy(start_db_args.db_file_name,
	        VXT_DB_DEFAULT_FILE_NAME, VXT_DB_NAME_MAX);
	
	ioctl(auth_dev, VXT_AUTH_DB_START, (void *)(long)&start_db_args);


	/* printf("The domain device %s\n", xs_domain_dev()); */
	xs = xs_domain_open();
	if (!xs) {
		perror("xs_domain_open failure");
		exit(1);
	}

	ret = xs_watch(xs,  "/vm", "vxtToken");
	if (ret == 0) {
		perror("xs_watch failed\n");
		exit(1);
	}

	fd = xs_fileno(xs);

	while (1) {

		FD_ZERO(&set);
		FD_SET(fd, &set);

		/* 
		 * Poll for data 
		 * printf("Poll for data, 0x%x\n", fd);
		 */
		if ((ret = select(fd+1, &set, NULL, NULL, NULL)) >= 0) {
			/* printf("Watch point triggered ret = 0x%x\n", ret); */
			vec = xs_read_watch(xs, &num);
			printf("\n after read watch ");
			if (!vec) error();

			parse_result =
			   xsd_vm_name(vec[XS_WATCH_PATH], target_uuid);

			if (parse_result == 1) {
				char **list;
			  	char path[64];
				int  entry_cnt;
				int  i;
				/*
				 * get a list of all the domain ids, 
				 * then check the name of each one
				 * to find the id for the specified domain
				 */
				list = xs_directory(xs, XBT_NULL,
				                    "/local/domain",
				                    &entry_cnt);
				for (i = (entry_cnt-1); i > 0; i--) {
					char *rec_uuid;
					sprintf(path,
					        "/local/domain/%s/vm",
						list[i]);
					rec_uuid = xs_read(xs, XBT_NULL,
					                   path, NULL);
					if ( rec_uuid == NULL ) {
						continue;
					}
					if (strcmp(&(rec_uuid[4]),
					           target_uuid) == 0) {
						free(rec_uuid);
						domid = atoi(list[i]);
						break;
					}
					free(rec_uuid);
				}
				free(list);
				if (i == 0) {
					free(vec);
					continue;
				}
	

				xsd_write_auth_record(auth_dev, target_uuid);
				/* 
				printf("main: call vxt_auth_db on uuid = %s\n",
				       target_uuid);
				*/

				xsd_provision_controller(xs, domid);
				is_provision = 1;
				update_vm_state(target_uuid, is_provision);

			} else if (parse_result == 2) {
				/* treating this case as deprovision */
				is_provision = 0;
				update_vm_state(target_uuid, is_provision);
			} else {
				/* target_uuid is undefined
				 * don't call update_vm_state
				 */
			}
			free(vec);
		} else {
			break;
		}
	}

	printf("returned from xs_watch, xenstore exited\n");

}
Пример #20
0
/**
 * xenStoreOpen:
 * @conn: pointer to the connection block
 * @name: URL for the target, NULL for local
 * @flags: combination of virDrvOpenFlag(s)
 *
 * Connects to the Xen hypervisor.
 *
 * Returns 0 or -1 in case of error.
 */
int
xenStoreOpen(virConnectPtr conn,
             virConnectAuthPtr auth ATTRIBUTE_UNUSED,
             unsigned int flags)
{
    xenUnifiedPrivatePtr priv = conn->privateData;

    virCheckFlags(VIR_CONNECT_RO, -1);

    if (flags & VIR_CONNECT_RO)
        priv->xshandle = xs_daemon_open_readonly();
    else
        priv->xshandle = xs_daemon_open();

    if (priv->xshandle == NULL) {
        /*
         * not being able to connect via the socket as an unprivileged
         * user is rather normal, this should fallback to the proxy (or
         * remote) mechanism.
         */
        if (xenHavePrivilege()) {
            virReportError(VIR_ERR_NO_XEN,
                           "%s", _("failed to connect to Xen Store"));
        }
        return -1;
    }

    /* Init activeDomainList */
    if (VIR_ALLOC(priv->activeDomainList) < 0)
        return -1;

    /* Init watch list before filling in domInfoList,
       so we can know if it is the first time through
       when the callback fires */
    if (VIR_ALLOC(priv->xsWatchList) < 0)
        return -1;

    /* This will get called once at start */
    if (xenStoreAddWatch(conn, "@releaseDomain",
                         "releaseDomain", xenStoreDomainReleased, priv) < 0)
    {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("adding watch @releaseDomain"));
        return -1;
    }

    /* The initial call of this will fill domInfoList */
    if (xenStoreAddWatch(conn, "@introduceDomain",
                         "introduceDomain", xenStoreDomainIntroduced, priv) < 0)
    {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("adding watch @introduceDomain"));
        return -1;
    }

    /* Add an event handle */
    if ((priv->xsWatch = virEventAddHandle(xs_fileno(priv->xshandle),
                                           VIR_EVENT_HANDLE_READABLE,
                                           xenStoreWatchEvent,
                                           conn,
                                           NULL)) < 0)
        VIR_DEBUG("Failed to add event handle, disabling events");

    return 0;
}