|
[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
On Thu, Jul 24, 2014 at 07:52:46PM +0100, Ian Jackson wrote:
> 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!
>
No worries. I can fix this.
> 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.
>
Why do we need a second lock? The one I introduced in previous patch is
used to serialise access to user data. Isn't that just what we want in
this case?
>
> > + /* 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
>
-EPARSE. :-(
> > + 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.
>
Will fix this.
> > +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.
>
No problem.
> > + /* 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.
>
Yes, there's such windows.
Ian C suggested I add lock during creation, which I think should fix
this problem.
> > +/* 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 `*'.
>
Ack.
> > +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.
>
Fixed.
> > + 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.
>
Yes. I agree.
> 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.
>
I guess you mean I should write
if (callback(XXX))
This of course can be done.
> > + 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.
>
Will fix this.
> > @@ -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.
>
Luckily it's very short at the moment.
Wei.
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |