From e535a57118c6fefb5db5b44e97bfb5ec2e521575 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 --- libburn/trunk/README | 15 ++++++ libburn/trunk/cdrskin/README | 16 ++++++ libburn/trunk/cdrskin/cdrskin_timestamp.h | 2 +- libburn/trunk/libburn/sg-linux.c | 64 +++++++++++++++++++---- 4 files changed, 86 insertions(+), 11 deletions(-) diff --git a/libburn/trunk/README b/libburn/trunk/README index fa53120b..818500cf 100644 --- a/libburn/trunk/README +++ b/libburn/trunk/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/libburn/trunk/cdrskin/README b/libburn/trunk/cdrskin/README index 2ba65d21..d80ec8aa 100644 --- a/libburn/trunk/cdrskin/README +++ b/libburn/trunk/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/libburn/trunk/cdrskin/cdrskin_timestamp.h b/libburn/trunk/cdrskin/cdrskin_timestamp.h index d37f320e..74143b3a 100644 --- a/libburn/trunk/cdrskin/cdrskin_timestamp.h +++ b/libburn/trunk/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2011.09.20.132438" +#define Cdrskin_timestamP "2011.09.21.133344" diff --git a/libburn/trunk/libburn/sg-linux.c b/libburn/trunk/libburn/sg-linux.c index d01370a7..61556f07 100644 --- a/libburn/trunk/libburn/sg-linux.c +++ b/libburn/trunk/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; }