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

Re: [Xen-devel] [PATCH v1 03/10] libxl: store a copy of vanilla domain configuration when creating domain



Wei Liu writes ("[PATCH v1 03/10] libxl: store a copy of vanilla domain 
configuration when creating domain"):
> This patch utilises new "libxl-json" file and stores a copy of user
> supplied domain configuration in JSON form. This copy will be used as
> template.
> 
> There're two save operations in total. The template config is first
> saved right after the domain gets its UUID and domain id. Then after the
> domain creation succeeds, the relevant bits touched by libxl are
> synchronised to the stored config.

I think there is a potential race with domain destruction here:

    Task 1                                 Task 2
    Creating the domain                    Trying to shut down

      actually create domain
                                             observe domid
                                             start domain destruction
                                             delete all userdata
                                             destroy domain
      store the userdata
        *** forbidden state created: userdata exists but domain doesn't
        *** userdata has been leaked
      [ would now bomb out ]

This race actually exists in libxl_userdata_store so it is my fault.
Sorry!

I think this should be fixed as follows:

  * domain destruction should take a lock across deleting the
    userdata and destroying the domain in Xen

  * libxl_userdata_store should take take the lock,
    check domain exists, store userdata, unlock lock.

This would be a separate lock to the one you introduce, I think.
Your lock covers a lot of xenstore processing.  But perhaps we can
reuse some of the fcntl and lockfile massaging stuff.


> +    /* At this point we've got domid and UUID, store configuration */
> +    ret = libxl__set_domain_configuration(gc, domid, &d_config_saved);

This libxl__set_domain_configuration is the only thing which creates
the libxl-json userdata ?  If so I think there is no 

> +    libxl_domain_config_dispose(&d_config_saved);
> +    if (ret) {

Please use the idempotent error-handling style.  This dispose needs to
be in the `error_out' section.  You will need to call _init at the top
of the function.  I think there's a separate success exit path in this
function so I think you do need two calls to dispose.

> +static void update_domain_config(libxl__gc *gc,
> +                                 libxl_domain_config *dst,
> +                                 const libxl_domain_config *src)
> +{

I think it would be a good idea to move this domain configuration
update stuff into a file of its own rather than interleaving it with
the (supposedly chronologically-ordered) domain creation logic.

> +    /* update network interface information */
> +    int i;
> +
> +    for (i = 0; i < src->num_nics; i++)
> +        libxl__update_config_nic(gc, &dst->nics[i], &src->nics[i]);

Does creating the config early, and then updating it, not mean that
there will be a window during domain creation when configuration
exists but lacks these updates ?

I think that might be a (theoretically application-visible) bug.

> +/* update the saved domain configuration with a callback function,
> + * which is responsible to pull in useful fields from src.
> + */
> +typedef void (update_callback)(libxl__gc *, libxl_domain_config *,
> +                               const libxl_domain_config *);

libxl coding style has no ` ' before the `*'.

> +static int libxl__update_domain_configuration(libxl__gc *gc,
> +                                              uint32_t domid,
> +                                              update_callback callback,
> +                                              const libxl_domain_config *src)
...
> +    libxl_domain_config_init(&d_config_saved);
> +
> +    rc = libxl__get_domain_configuration(gc, domid, &d_config_saved);
> +
> +    if (rc) {

Spurious blank line.

> +        LOG(ERROR, "cannot get domain configuration: %d", rc);

Doesn't libxl__get_domain_configuration log a message already ?  I
think so, in which case it's probably not ideal to log again.

To help with (a) not spewing lots of messages for a single error and
(b) writing code uncluttered by unnecessary logging calls, it can be
helpful to mention in the doc comments for functions whether they log
failures.

If they do you can replace this whole block with a one-line
       if (rc) goto out;

> +    callback(gc, &d_config_saved, src);

Callback should probably have the ability to fail.

> +    rc = libxl__set_domain_configuration(gc, domid, &d_config_saved);
> +
> +    if (rc)
> +        LOG(ERROR, "cannot set domain configuration: %d", rc);

1. Spurious blank line.  2. See above re logging.   3. This falling
through into the end of the function is unpleasant - please make
things regular.

The end of most functions should have something like:
       rc = 0;
    out:

> +    libxl_domain_config_dispose(&d_config_saved);
> +
> +out:
> +    return rc;

This seems to leak d_config_saved on error paths.

> @@ -1354,6 +1424,12 @@ static void domcreate_complete(libxl__egc *egc,
>      if (!rc && d_config->b_info.exec_ssidref)
>          rc = xc_flask_relabel_domain(CTX->xch, dcs->guest_domid, 
> d_config->b_info.exec_ssidref);
>  
> +    if (!rc) {
> +        rc = libxl__update_domain_configuration(gc, dcs->guest_domid,
> +                                                update_domain_config,
> +                                                d_config);
> +    }

Oh dear.  I see this function already has a mad error handling style
which you are following.  I won't ask you to fix it.

> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index e9d93ac..72d21ad 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -3240,6 +3240,20 @@ int libxl__lock_domain_configuration(libxl__gc *gc, 
> uint32_t domid,
>  int libxl__unlock_domain_configuration(libxl__gc *gc, uint32_t domid,
>                                         int *fd_lock);
>  
> +static inline void libxl__update_config_nic(libxl__gc *gc,
> +                                            libxl_device_nic *dst,
> +                                            libxl_device_nic *src)
> +{
> +    libxl_mac_copy(CTX, &dst->mac, &src->mac);
> +}

Nice that this is so short...

Thanks,
Ian.

_______________________________________________
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®.