On Tue, 2017-06-20 at 17:03 +0200, Erik Skultety wrote: > Since we have a number of places where we workaround timing issues > with > devices, attributes (files in general) not being available at the > time > of processing them by calling usleep in a loop for a fixed number of > tries, we could as well have a utility function that would do that. > Therefore we won't have to duplicate this ugly workaround even more. > > This is a prerequisite for > https://bugzilla.redhat.com/show_bug.cgi?id=1463285. > > Signed-off-by: Erik Skultety <eskultet@xxxxxxxxxx> > --- > src/libvirt_private.syms | 1 + > src/util/virfile.c | 36 ++++++++++++++++++++++++++++++++++++ > src/util/virfile.h | 2 ++ > 3 files changed, 39 insertions(+) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index c1e9471c5..53878a30f 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1698,6 +1698,7 @@ virFileStripSuffix; > virFileTouch; > virFileUnlock; > virFileUpdatePerm; > +virFileWaitForAccess; > virFileWrapperFdClose; > virFileWrapperFdFree; > virFileWrapperFdNew; > diff --git a/src/util/virfile.c b/src/util/virfile.c > index 6bbcc3d15..0b1a91699 100644 > --- a/src/util/virfile.c > +++ b/src/util/virfile.c > @@ -4164,3 +4164,39 @@ virFileReadValueString(char **value, const > char *format, ...) > VIR_FREE(str); > return ret; > } > + > + > +/** > + * virFileWaitForAccess: > + * @path: absolute path to a sysfs attribute (can be a symlink) > + * @ms: how long to wait (in milliseconds) > + * @tries: how many times should we try to wait for @path to become > accessible > + * > + * Checks the existence of @path. In case the file defined by @path > + * doesn't exist, we wait for it to appear in 100ms (for up to > @tries times). > + * > + * Returns 0 on success, -1 on error (ENOENT is fine here). > + */ > +int > +virFileWaitForAccess(const char *path, size_t ms, size_t tries) > +{ > + errno = 0; > + > + /* wait for @path to be accessible in @ms milliseconds, up to > @tries */ > + while (tries-- > 0 && !virFileExists(path)) { > + if (errno != ENOENT) { > + virReportSystemError(errno, "%s", path); > + return -1; > + } else if (tries == 10) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to access '%s' after %zu > tries"), > + path, tries); > + return -1; > + } else { > + VIR_DEBUG("Failed to access '%s', re-try in %zu ms", > path, ms); > + usleep(ms * 1000); > + } > + } > + > + return 0; > +} Just FYI, there's another way to address it by calling udevadm settle before and after "touching" a block device, libguestfs is using this approach and it works very well: https://github.com/libguestfs/libguestfs/search?utf8=%E2%9C%93&q=udev_s ettle&type= > diff --git a/src/util/virfile.h b/src/util/virfile.h > index 57ceb8072..42630ebb5 100644 > --- a/src/util/virfile.h > +++ b/src/util/virfile.h > @@ -347,6 +347,8 @@ int virFileReadValueScaledInt(unsigned long long > *value, const char *format, ... > int virFileReadValueString(char **value, const char *format, ...) > ATTRIBUTE_FMT_PRINTF(2, 3); > > +int virFileWaitForAccess(const char *path, size_t ms, size_t tries); > + > > int virFileInData(int fd, > int *inData, -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list