[libvirt] [PATCH]: Give /dev/disk/by-{id,path} a chance to exist

Jim Meyering jim at meyering.net
Wed Nov 26 09:31:52 UTC 2008


Chris Lalancette <clalance at redhat.com> wrote:
...
> on-demand by udev.  It's basically a race between udev creating the directory
> and libvirt scanning the directory.
>      The following patch just adds a retry to the code above so that if it
> doesn't exist when we first get there, we give it time to come into being.  If
> it still hasn't shown up 5 seconds after we started, we give up and throw the error.
...
> -    if ((dh = opendir(pool->def->target.path)) == NULL) {
> +    dh = NULL;

not needed?

> +    opentries = 0;
> +    while (opentries < 50) {
> +        if ((dh = opendir(pool->def->target.path)) != NULL)
> +            break;

Hi Chris,

Nice one.  Must have been er,.. fun to track down.
The patch looks fine, but how about making it so that it retries
only for a missing final (ENOENT) or intermediate (ENOTDIR)
component.  We'd rather not have it retry due to OOM or lack of
permission, e.g.,

    dh = opendir(pool->def->target.path);
    if (dh != NULL || (errno != ENOENT && errno != ENOTDIR))
        break;

but that has so many 'not's that you might prefer to write it this way:

        if (! (dh == NULL && (errno == ENOENT || errno == ENOTDIR)))
            break;

You can save a two lines by using a for loop.
It's nice to put a name on the constant, e.g.,

    enum { WAIT_FOR_UDEV_SECS = 5 };

(and enum is better than #define, because it's usable in a debugger)

    for (open_tries = 0; open_tries < WAIT_FOR_UDEV_SECS * 10; open_tries++) {
        dh = opendir(pool->def->target.path);
        /* Stop if opendir succeeds, or if it fails for any
           reason other than a missing file name component.  */
        if (dh != NULL || (errno != ENOENT && errno != ENOTDIR))
            break;
        usleep(100 * 1000);
    }

Why "open_tries"?
Because I first read "opentries" as "op" "entries" ;-)




More information about the libvir-list mailing list