[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 0 of 3] xl and hotplug: Introduce and use shutdown and reboot xm compatibility options



On Thu, 2012-09-27 at 21:11 +0100, Sander Eikelenboom wrote:
> Tuesday, September 25, 2012, 5:29:09 PM, you wrote:
> 
> > On Tue, 2012-09-25 at 16:11 +0100, Sander Eikelenboom wrote:
> 
> >> The only relative simple implementation i thought of was direct
> >> shutting down all, and when the -w parameter was set, just loop and
> >> wait on events until the only running domain is domain-0.
> >> Although this exactly does what has to be done, it somehow sounds a
> >> bit dirty.
> 
> > I think you can allocate an array of libxl_evenable_domain_death*, of
> > nr_doms in size and then as you shutdown each domain call
> > libxl_evenable_domain_death for it too.
> 
> > Then you loop waiting for destroy events, calling
> > libxl_evdisable_domain_death as each domain dies, while counting back
> > from nr_doms until 0. When it reaches 0 everything you asked for has
> > been shutdown.
> 
> > Or something like that, I've not actually implemented it ;-)
> 
> > Ian.
> 
> It's time to call defeat, without proper C skills it seems a bit too
> hard to figure it out.

That's ok, I'll add it to my TODO to pickup where you left off (unless
someone beats me to it).

Thanks for taking it this far! FWIW you seemed to be pretty close.

> Can't seem to get the hang of how to keep a reference to
> libxl_evgen_domain_death and use it to check if the domid of the event
> is the same as that from a domain we are waiting to shutdown.
> The rest of the code doesn't give me much pointers since all commands
> seem to operate on a single domid at once.
> 
> The concoction below leads to:
> xl_cmdimpl.c: In function Ãshutdown_domainÃ:
> xl_cmdimpl.c:2766: error: dereferencing pointer to incomplete type

In case you are interested this is because the libxl_evgen_domain_death
type is opaque to users of libxl so constructs like
domains_wait_shutdown[i]->domid are not possible.

The answer is to use the 3rd argument to libxl_evenable_domain_death
(the one of type libxl_ev_user) to pass a "closure", this value is
returned in the event's "for_user" field. The application can use this
to store data specific to this particular event -- in this case it would
probably be sufficient to just pass the domid here but in principal one
could pass a pointer to any datastructure.

Thanks again,
Ian.

> 
> 
> --------------------------- tools/libxl/xl_cmdimpl.c 
> ---------------------------
> index 1627cac..b900811 100644
> @@ -2684,67 +2684,98 @@ static void destroy_domain(uint32_t domid)
>      }
>      rc = libxl_domain_destroy(ctx, domid, 0);
>      if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n",rc); exit(-1); }
>  }
>  
> -static void shutdown_domain(uint32_t domid, int wait_for_it,
> -                            int fallback_trigger)
> +static int shutdown_domain(const libxl_dominfo *dominfo, int nb_domain,
> +                            int wait_for_it, int fallback_trigger)
>  {
> -    int rc;
> -    libxl_event *event;
> +    int i, rc, nb_shutdown_pending;
> +    int ret = 0;
> +    libxl_evgen_domain_death *domains_wait_shutdown[nb_domain];
> +       
> +    for (i = 0; i < nb_domain; i++) {
> +        uint32_t domid = dominfo[i].domid;
> +        if(!libxl_domid_valid_guest(domid))
> +            continue;
>  
> -    rc=libxl_domain_shutdown(ctx, domid);
> -    if (rc == ERROR_NOPARAVIRT) {
> -        if (fallback_trigger) {
> -            fprintf(stderr, "PV control interface not available:"
> -                    " sending ACPI power button event.\n");
> -            rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_POWER, 0);
> -        } else {
> -            fprintf(stderr, "PV control interface not available:"
> -                    " external graceful shutdown not possible.\n");
> -            fprintf(stderr, "Use \"-F\" to fallback to ACPI power event.\n");
> +        rc = libxl_domain_shutdown(ctx, domid);
> +
> +        if (rc == ERROR_NOPARAVIRT) {
> +            if (fallback_trigger) {
> +                fprintf(stderr, "PV control interface not available:"
> +                        " sending ACPI power button event.\n");
> +                rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_POWER, 0);
> +            } else {
> +                fprintf(stderr, "PV control interface not available:"
> +                        " external graceful shutdown not possible.\n");
> +                fprintf(stderr,
> +                    "Use \"-F\" to fallback to ACPI power event.\n");
> +            }
> +        }
> +        
> +        if (rc) {
> +            fprintf(stderr,"shutdown of domain %d failed (rc=%d)\n", domid, 
> rc);
> +            ret = -1;
> +            continue;
> +        }
> +
> +        if (wait_for_it) {
> +            rc = libxl_evenable_domain_death(ctx, domid, 0, 
> &domains_wait_shutdown[i]);
> +            if (rc) {
> +                fprintf(stderr,"wait for death of domain %d failed"
> +                    " (evgen, rc=%d)\n", domid, rc);
> +                ret = -1;
> +            } else {
> +                nb_shutdown_pending++;
> +            } 
>          }
> -    }
> -    if (rc) {
> -        fprintf(stderr,"shutdown failed (rc=%d)\n",rc);exit(-1);
>      }
>  
>      if (wait_for_it) {
> -        libxl_evgen_domain_death *deathw;
> +        while (nb_shutdown_pending > 0) {
> +            libxl_event *event;
> +            rc = libxl_event_wait(ctx, &event, LIBXL_EVENTMASK_ALL, 0,0);
> +            if (rc) {
> +                LOG("Failed to get event (rc=%d)", rc);
> +                return -1;
> +            }
>  
> -        rc = libxl_evenable_domain_death(ctx, domid, 0, &deathw);
> -        if (rc) {
> -            fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
> -            exit(-1);
> -        }
> +            uint32_t event_domid = event->domid;
> +            switch (event->type) {
>  
> -        for (;;) {
> -            rc = domain_wait_event(domid, &event);
> -            if (rc) exit(-1);
> +                case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
> +                    LOG("Domain %d has been destroyed", event_domid);
> +                    break;
>  
> -            switch (event->type) {
> +                case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
> +                    LOG("Domain %d has been shut down, reason code %d %x",
> +                        event_domid,
> +                        event->u.domain_shutdown.shutdown_reason,
> +                        event->u.domain_shutdown.shutdown_reason);
> +                    break;
>  
> -            case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
> -                LOG("Domain %d has been destroyed", domid);
> -                goto done;
> +                default:
> +                    continue;
> +                    break;
> +            }
>  
> -            case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
> -                LOG("Domain %d has been shut down, reason code %d %x", domid,
> -                    event->u.domain_shutdown.shutdown_reason,
> -                    event->u.domain_shutdown.shutdown_reason);
> -                goto done;
> +            for (i = 0; i < nb_domain; i++) {
> +                if (!domains_wait_shutdown[i])
> +                    continue;
>  
> -            default:
> -                LOG("Unexpected event type %d", event->type);
> -                break;
> +                if (domains_wait_shutdown[i]->domid == event_domid){
> +                    libxl_evdisable_domain_death(ctx, 
> domains_wait_shutdown[i]);
> +                    domains_wait_shutdown[i] = NULL;
> +                    nb_shutdown_pending--;
> +                }
>              }
>              libxl_event_free(ctx, event);
>          }
> -    done:
> -        libxl_event_free(ctx, event);
> -        libxl_evdisable_domain_death(ctx, deathw);
>      }
> +
> +    return ret;
>  }
>  
>  static void reboot_domain(uint32_t domid, int fallback_trigger)
>  {
>      int rc;
> @@ -3674,29 +3705,82 @@ int main_destroy(int argc, char **argv)
>      return 0;
>  }
>  
>  int main_shutdown(int argc, char **argv)
>  {
> +    libxl_dominfo dominfo_buf;
> +    libxl_dominfo *dominfo, *dominfo_free = NULL;
> +    int nb_domain, rc;
>      int opt;
> +    int option_index = 0;
> +    int all = 0;
>      int wait_for_it = 0;
>      int fallback_trigger = 0;
> +    static struct option long_options[] = {
> +        {"all", 0, 0, 'a'},
> +        {"wait", 0, 0, 'w'},
> +        {0, 0, 0, 0}
> +    };
>  
> -    while ((opt = def_getopt(argc, argv, "wF", "shutdown", 1)) != -1) {
> +    while ((opt = getopt_long(argc, argv, "awF", long_options, 
> &option_index)) != -1) {
>          switch (opt) {
>          case 0: case 2:
>              return opt;
> +        case 'a':
> +            all = 1;
> +            break;
>          case 'w':
>              wait_for_it = 1;
>              break;
>          case 'F':
>              fallback_trigger = 1;
>              break;
>          }
>      }
>  
> -    shutdown_domain(find_domain(argv[optind]), wait_for_it, 
> fallback_trigger);
> -    return 0;
> +    if (!argv[optind] && !all) {
> +        fprintf(stderr, "You must specify -a or a valid domain id.\n\n");
> +        return opt;
> +    }
> +
> +    if (all) {
> +        dominfo = libxl_list_domain(ctx, &nb_domain);
> +        if (!dominfo) {
> +            fprintf(stderr, "libxl_domain_infolist failed.\n");
> +            return -1;
> +        }
> +        dominfo_free = dominfo;
> +    } else {
> +        uint32_t domid = find_domain(argv[optind]);
> +        if (domid == 0) {
> +            fprintf(stderr, "Error: Domain-0 can't be shutdown by this 
> command\n");
> +            return -1;
> +        }
> +
> +        rc = libxl_domain_info(ctx, &dominfo_buf, domid);
> +
> +        if (rc == ERROR_INVAL) {
> +            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
> +                argv[optind]);
> +            return -rc;
> +        }
> +        if (rc) {
> +            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
> +            return -rc;
> +        }
> +        dominfo = &dominfo_buf;
> +        nb_domain = 1;
> +    }
> +
> +    rc = shutdown_domain(dominfo, nb_domain, wait_for_it, fallback_trigger);
> +
> +    if (dominfo_free)
> +        libxl_dominfo_list_free(dominfo_free, nb_domain);
> +    else
> +        libxl_dominfo_dispose(dominfo);
> +
> +    return -rc;
>  }
>  
>  int main_reboot(int argc, char **argv)
>  {
>      int opt;
> 
> 
> 
> 



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.