From d9e6bde437d7d5317c2d3887e26046232265c0ed Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Wed, 21 Sep 2011 13:34:21 +0000 Subject: [PATCH] Improved and documented workaround for udev --- README | 15 +++++++++ cdrskin/README | 16 ++++++++++ cdrskin/cdrskin_timestamp.h | 2 +- libburn/sg-linux.c | 64 +++++++++++++++++++++++++++++++------ 4 files changed, 86 insertions(+), 11 deletions(-) diff --git a/README b/README index fa53120..818500c 100644 --- a/README +++ b/README @@ -92,6 +92,21 @@ Make sure to re-compile all source files after running ./configure make install +Linux only: + +libburn tries to avoid a collision with udev's drive examination by waiting +0.1 seconds before opening the device file for a longer time, after udev +might have been alarmed by drive scanning activities. +The waiting time can be set at ./configure time with microsecond granularity. +E.g. 2 seconds: + CFLAGS="$CFLAGS -DLibburn_udev_wait_useC=2000000" + ./configure ...options... +Closing and re-opening can be disabled by zero waiting time: + CFLAGS="$CFLAGS -DLibburn_udev_wait_useC=0" +Alternatively, libburn can try to be nice by opening the device file, +closing it immediately, waiting, and only then opening it for real: + CFLAGS="$CFLAGS -DLibburn_udev_extra_open_cyclE" + ------------------------------------------------------------------------------ An important part of the project, libisofs, is hosted in a bzr repository at diff --git a/cdrskin/README b/cdrskin/README index 2ba65d2..d80ec8a 100644 --- a/cdrskin/README +++ b/cdrskin/README @@ -438,6 +438,22 @@ It will not read startup files, will abort on option dev_translation= , will not have a fifo buffer, and will not be able to put out help texts or debugging messages. + +Linux only: + +libburn tries to avoid a collision with udev's drive examination by waiting +0.1 seconds before opening the device file for a longer time, after udev +might have been alarmed by drive scanning activities. +The waiting time can be set at ./configure time with microsecond granularity. +E.g. 2 seconds: + CFLAGS="$CFLAGS -DLibburn_udev_wait_useC=2000000" + ./configure ...options... +Closing and re-opening can be disabled by zero waiting time: + CFLAGS="$CFLAGS -DLibburn_udev_wait_useC=0" +Alternatively, libburn can try to be nice by opening the device file, +closing it immediately, waiting, and only then opening it for real: + CFLAGS="$CFLAGS -DLibburn_udev_extra_open_cyclE" + ------------------------------------------------------------------------------ System Dependend Drive Permission Examples diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index d37f320..74143b3 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2011.09.20.132438" +#define Cdrskin_timestamP "2011.09.21.133344" diff --git a/libburn/sg-linux.c b/libburn/sg-linux.c index d01370a..61556f0 100644 --- a/libburn/sg-linux.c +++ b/libburn/sg-linux.c @@ -1531,6 +1531,33 @@ int sg_grab(struct burn_drive *d) relase of drive. Unclear why not the official error return value -1 of open(2) war used. */ if(! burn_drive_is_open(d)) { + char msg[120]; + +#ifndef Libburn_udev_wait_useC +#define Libburn_udev_wait_useC 100000 +#endif + +#ifndef Libburn_udev_extra_open_cyclE + + if (Libburn_udev_wait_useC > 0) { + /* ts B10921 : workaround for udev which might get + a kernel event from open() and might + remove links if it cannot inspect the + drive. This waiting period shall allow udev + to act after it was woken up by the drive scan + activities. + */ + sprintf(msg, + "To avoid collision with udev: Waiting %lu usec before grabbing", + (unsigned long) Libburn_udev_wait_useC); + libdax_msgs_submit(libdax_messenger, -1, 0x00000002, + LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + usleep(Libburn_udev_wait_useC); + } + +#endif /* Libburn_udev_extra_open_cyclE */ + try_open:; /* ts A60821 @@ -1553,21 +1580,34 @@ try_open:; fd = open(d->devname, open_mode); os_errno = errno; - if (fd >= 0) { - /* ts B10920 : workaround for udev which might get - a kernel event from open() and might - remove links if it cannot inspect the - drive. - */ + +#ifdef Libburn_udev_extra_open_cyclE + + /* ts B10920 : workaround for udev which might get + a kernel event from open() and might + remove links if it cannot inspect the + drive. + ts B10921 : this is more obtrusive than above waiting + before open(). The drive scan already has + opened and closed the drive several times. + So it seems to be merely about giving an + opportunity to udev, before long term grabbing + happens. + */ + if (fd >= 0 && Libburn_udev_wait_useC > 0) { + close(fd); + sprintf(msg, + "To avoid collision with udev: Waiting %lu usec before re-opening", + (unsigned long) Libburn_udev_wait_useC); libdax_msgs_submit(libdax_messenger, -1, 0x00000002, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, - "Waiting 2 seconds to avoid collision with udev", - 0, 0); - close(fd); - usleep(2000000); + msg, 0, 0); + usleep(Libburn_udev_wait_useC); fd = open(d->devname, open_mode); os_errno = errno; } +#endif /* Libburn_udev_extra_open_cyclE */ + if (fd >= 0) { sg_fcntl_lock(&fd, d->devname, F_WRLCK, 1); if (fd < 0) @@ -1591,6 +1631,10 @@ try_open:; drive_is_in_use:; tries++; if (tries < max_tries) { + libdax_msgs_submit(libdax_messenger, -1, 0x00000002, + LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, + "Drive is in use. Waiting 2 seconds before re-try", + 0, 0); usleep(2000000); goto try_open; }