[libvirt] [PATCH] Xen Events Updated

Daniel P. Berrange berrange at redhat.com
Wed Nov 12 14:44:50 UTC 2008


On Tue, Nov 11, 2008 at 01:34:29PM -0500, Ben Guthro wrote:
> This version of the Xen-Events patch goes a step further 
> than the last version, and now emits the following domain events:
> 
> STARTED
> STOPPED
> ADDED
> REMOVED
> 
> This is accomplished by monitoring /etc/xen, and taking advantage
> of what seemed to be dormant code in the XM driver. By re-enabling
> the "config cache", we can properly track domains when files come,
> and go into this directory.

This isn't quite correct. The /etc/xen directory & thus xm_internal.c
driver is only used for Xen < 3.0.4, where there was no XenD management
of inactive domains. For Xen >= 3.0.4, we let XenD itself manage
all inactive domains, so /etc/xen should not be used. XenD keeps its
persistent configs in /var/lib/xen/xend/domains.

So for this inotify magic, we shouldn't be looking at /etc/xen, and
instead watch /var/lib/xen/xend/domains. THis is actually nice & easy
because the files in the directry are named according to the UUID,
so we don't even need to read the file contents in that scenario.

> +static void
> +xenInotifyEvent(int fd,
> +                int events ATTRIBUTE_UNUSED,
> +                void *data)
> +{
> +    char buf[1024];
> +    char fname[1024];
> +    struct inotify_event *e;
> +    int got;
> +    char *tmp, *name;
> +    virConnectPtr conn = (virConnectPtr) data;
> +    xenUnifiedPrivatePtr priv = NULL;
> +    virDomainPtr dom = NULL;
> +
> +    DEBUG0("got inotify event");
> +
> +    if( conn && conn->privateData ) {
> +        priv = conn->privateData;
> +    } else {
> +        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
> +                           "%s", _("conn, or private data is NULL"));
> +        return;
> +    }
> +
> +reread:
> +    got = read(fd, buf, sizeof(buf));
> +    if (got == -1) {
> +        if (errno == EINTR)
> +            goto reread;
> +        return;
> +    }
> +
> +    tmp = buf;
> +    while (got) {
> +        if (got < sizeof(struct inotify_event))
> +            return; /* bad */
> +
> +        e = (struct inotify_event *)tmp;
> +        tmp += sizeof(struct inotify_event);
> +        got -= sizeof(struct inotify_event);
> +
> +        if (got < e->len)
> +            return;
> +
> +        tmp += e->len;
> +        got -= e->len;
> +
> +        name = (char *)&(e->name);
> +
> +        snprintf(fname, 1024, "%s/%s", xenXMGetConfigDir(), name);
> +
> +        if (e->mask & IN_DELETE) {
> +            if (!(dom = xenInotifyConfigLookupCache(conn, fname))) {
> +                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
> +                           "%s", _("looking up dom"));
> +                continue;
> +            }
> +
> +            xenUnifiedDomainEventDispatch(conn->privateData,
> +                                          dom, VIR_DOMAIN_EVENT_REMOVED);
> +
> +            if (xenXMConfigCacheRefresh (conn) < 0) {
> +                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
> +                                   "%s", _("Error refreshing config cache"));
> +                return;
> +            }
> +        } else if (e->mask & IN_MODIFY) {
> +            /* if we track IN_CREATED we get 2 added events */
> +            if (xenXMConfigCacheRefresh (conn) < 0) {
> +                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
> +                                   "%s", _("Error refreshing config cache"));
> +                return;
> +            }

If we've activated inotify, then we should not call xenXMConfigCacheRefresh()
since that iterates over every file in the directory. Since we know the new
or old filenames, we can just populate / remove the individual file. 

This will require re-factoring xenXMConfigCacheRefresh() slightly. It currently
has all its useful logic inside its while() loop. We should break the body of
xenXMConfigCacheRefresh() out into a separate method which just able to process
a single new file, eg

  xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename);

And also add a new 

  xenXMConfigCacheRemoveFile(virConnectPtr conn,	const char *filename);

to just remove the old file from the cache.

When activating inotify we can call xenXMConfigCacheRefresh() once to get
the initial list of domains, and then disable various calls to it in all
the public APIs in xm_internal.h, and rely on the inotify code to keep it
up2date.


Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list