Disabled but did not discarded failed attempt to lock against growisofs

This commit is contained in:
Thomas Schmitt 2006-09-27 11:57:28 +00:00
parent 927352c609
commit 886b8d1f81
6 changed files with 261 additions and 29 deletions

View File

@ -1359,7 +1359,7 @@ int Cdrpreskin_queue_msgs(struct CdrpreskiN *o, int flag)
if(o->verbosity>=Cdrskin_verbose_debuG)
Cdrpreskin_set_severities(o,"DEBUG","NEVER",0);
else
Cdrpreskin_set_severities(o,"NOTE","NEVER",0);
Cdrpreskin_set_severities(o,"SORRY","NEVER",0);
queueing= 1;
return(1);
}

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2006.09.27.082057"
#define Cdrskin_timestamP "2006.09.27.115919"

View File

@ -37,7 +37,7 @@ void burn_drive_free(struct burn_drive *d)
return;
/* ts A60822 : close open fds before forgetting them */
if (burn_drive_is_open(d))
sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0);
sg_close_drive(d);
free((void *) d->idata);
free((void *) d->mdata);
free((void *) d->toc_entry);
@ -248,6 +248,18 @@ struct burn_drive *burn_drive_register(struct burn_drive *d)
}
/* unregister most recently registered drive */
int burn_drive_unregister(struct burn_drive *d)
{
if(d->global_index != drivetop)
return 0;
burn_drive_free(d);
drivetop--;
return 1;
}
void burn_drive_release(struct burn_drive *d, int le)
{
if (d->released)
@ -711,7 +723,6 @@ int burn_drive_is_enumerable_adr(char *adr)
return sg_is_enumerable_adr(adr);
}
/* ts A60922 ticket 33 */
/* Try to find an enumerated address with the given stat.st_rdev number */
int burn_drive_resolve_link(char *path, char adr[])

View File

@ -292,7 +292,10 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020001 (SORRY,LOW) = Cannot open busy device
0x00020002 (SORRY,HIGH) = Encountered error when closing drive
0x00020003 (FATAL,HIGH) = Could not grab drive
0x00020004 (NOTE,HIGH) = Opened O_EXCL scsi sibling
0x00020005 (FATAL,HIGH) = Failed to open device
0x00020006 (FATAL,HIGH) = Too many scsi siblings
0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings
------------------------------------------------------------------------------

View File

@ -89,6 +89,28 @@ int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
}
/* ts A60924 */
int sg_handle_busy_device(char *fname, int os_errno)
{
char msg[4096];
/* ts A60814 : i saw no way to do this more nicely */
if (burn_sg_open_abort_busy) {
fprintf(stderr,
"\nlibburn: FATAL : Application triggered abort on busy device '%s'\n",
fname);
assert("drive busy" == "non fatal");
}
/* ts A60924 : now reporting to libdax_msgs */
sprintf(msg, "Cannot open busy device '%s'", fname);
libdax_msgs_submit(libdax_messenger, -1, 0x00020001,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_LOW,
msg, os_errno, 0);
return 1;
}
/* ts A60922 ticket 33 */
/** Returns the next index number and the next enumerated drive address.
@param idx An opaque number handle. Make no own theories about it.
@ -146,25 +168,144 @@ int sg_is_enumerable_adr(char *adr)
}
/* ts A60924 */
int sg_handle_busy_device(char *fname, int os_errno)
/* ts A60926 */
int sg_release_siblings(int sibling_fds[], int *sibling_count)
{
char msg[4096];
int i;
char msg[81];
/* ts A60814 : i saw no way to do this more nicely */
if (burn_sg_open_abort_busy) {
fprintf(stderr,
"\nlibburn: FATAL : Application triggered abort on busy device '%s'\n",
fname);
assert("drive busy" == "non fatal");
for(i= 0; i < *sibling_count; i++)
sg_close_drive_fd(NULL, -1, &(sibling_fds[i]), 0);
if(*sibling_count > 0) {
sprintf(msg, "Closed %d O_EXCL scsi siblings", *sibling_count);
libdax_msgs_submit(libdax_messenger, -1, 0x00020007,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, msg, 0,0);
}
*sibling_count = 0;
return 1;
}
/* ts A60924 : now reporting to libdax_msgs */
sprintf(msg, "Cannot open busy device '%s'", fname);
libdax_msgs_submit(libdax_messenger, -1, 0x00020001,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_LOW,
msg, os_errno, 0);
return 1;
/* ts A60926 */
int sg_open_drive_fd(char *fname, int scan_mode)
{
int open_mode = O_RDWR, fd;
char msg[81];
/* ts A60813
O_EXCL with block devices is an unpublished feature
of Linux kernels. Possibly introduced 2002.
Mentioned in "The Linux SCSI Generic (sg) HOWTO" */
if(burn_sg_open_o_excl)
open_mode |= O_EXCL;
/* ts A60813
O_NONBLOCK was already hardcoded in ata_ but not in sg_.
There must be some reason for this. So O_NONBLOCK is
default mode for both now. Disable on own risk. */
if(burn_sg_open_o_nonblock)
open_mode |= O_NONBLOCK;
/* <<< debugging
fprintf(stderr,
"\nlibburn: experimental: o_excl= %d , o_nonblock= %d, abort_on_busy= %d\n",
burn_sg_open_o_excl,burn_sg_open_o_nonblock,burn_sg_open_abort_busy);
fprintf(stderr,
"libburn: experimental: O_EXCL= %d , O_NONBLOCK= %d\n",
!!(open_mode&O_EXCL),!!(open_mode&O_NONBLOCK));
*/
fd = open(fname, open_mode);
if (fd == -1) {
/* <<< debugging
fprintf(stderr,
"\nlibburn: experimental: fname= %s , errno= %d\n",
fname,errno);
*/
if (errno == EBUSY) {
sg_handle_busy_device(fname, errno);
return -1;
}
if (scan_mode)
return -1;
sprintf(msg, "Failed to open device '%s'",fname);
libdax_msgs_submit(libdax_messenger, -1, 0x00020005,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, errno, 0);
return -1;
}
return fd;
}
/* ts A60926 */
int sg_open_scsi_siblings(char *path, int driveno,
int sibling_fds[], int *sibling_count,
int host_no, int channel_no, int id_no, int lun_no)
{
int tld, i, ret, fd;
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
char msg[161], fname[81];
static char tldev[][81]= {"/dev/sr%d", "/dev/scd%d", "/dev/st%d", ""};
if(host_no < 0 || id_no < 0 || channel_no < 0 || lun_no < 0)
return(2);
if(*sibling_count > 0)
sg_release_siblings(sibling_fds, sibling_count);
for (tld = 0; tldev[tld][0] != 0; tld++) {
for (i = 0; i < 32; i++) {
sprintf(fname, tldev[tld], i);
ret = sg_obtain_scsi_adr(fname, &i_host_no,
&i_channel_no, &i_target_no, &i_lun_no);
if (ret <= 0)
continue;
if (i_host_no != host_no || i_channel_no != channel_no)
continue;
if (i_target_no != id_no || i_lun_no != lun_no)
continue;
fd = sg_open_drive_fd(fname, 0);
if (fd < 0)
goto failed;
if (*sibling_count>=LIBBURN_SG_MAX_SIBLINGS) {
sprintf(msg, "Too many scsi siblings of '%s'",
path);
libdax_msgs_submit(libdax_messenger,
driveno, 0x00020006,
LIBDAX_MSGS_SEV_FATAL,
LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
goto failed;
}
sprintf(msg, "Opened O_EXCL scsi sibling '%s' of '%s'",
fname, path);
libdax_msgs_submit(libdax_messenger, driveno,
0x00020004,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
sibling_fds[*sibling_count] = fd;
(*sibling_count)++;
}
}
return(1);
failed:;
sg_release_siblings(sibling_fds, sibling_count);
return 0;
}
/* ts A60926 */
int sg_close_drive(struct burn_drive *d)
{
int ret;
if (!burn_drive_is_open(d))
return 0;
sg_release_siblings(d->sibling_fds, &(d->sibling_count));
ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0);
return ret;
}
void ata_enumerate(void)
@ -173,6 +314,9 @@ void ata_enumerate(void)
int i, fd;
char fname[10];
#ifdef No_sg_open_drive_fD
/* ts A60813 */
int open_mode = O_RDWR;
@ -189,6 +333,9 @@ void ata_enumerate(void)
if(burn_sg_open_o_nonblock)
open_mode |= O_NONBLOCK;
#endif /* No_sg_open_drive_fD */
for (i = 0; i < 26; i++) {
sprintf(fname, "/dev/hd%c", 'a' + i);
/* open O_RDWR so we don't think read only drives are
@ -197,6 +344,8 @@ void ata_enumerate(void)
/* ts A51221 */
if (burn_drive_is_banned(fname))
continue;
#ifdef No_sg_open_drive_fD
fd = open(fname, open_mode);
if (fd == -1) {
/* <<< debugging
@ -208,6 +357,12 @@ void ata_enumerate(void)
sg_handle_busy_device(fname, errno);
continue;
}
#else
fd = sg_open_drive_fd(fname, 1);
if (fd == -1)
continue;
#endif /* ! No_sg_open_drive_fD */
/* found a drive */
ioctl(fd, HDIO_GET_IDENTITY, &tm);
@ -232,9 +387,12 @@ void ata_enumerate(void)
void sg_enumerate(void)
{
struct sg_scsi_id sid;
int i, fd;
int i, fd, sibling_fds[LIBBURN_SG_MAX_SIBLINGS], sibling_count= 0, ret;
char fname[10];
#ifdef No_sg_open_drive_fD
/* ts A60813 */
int open_mode = O_RDWR;
@ -261,6 +419,9 @@ void sg_enumerate(void)
*/
#endif /* No_sg_open_drive_fD */
for (i = 0; i < 32; i++) {
sprintf(fname, "/dev/sg%d", i);
/* open RDWR so we don't accidentally think read only drives
@ -269,6 +430,9 @@ void sg_enumerate(void)
/* ts A51221 */
if (burn_drive_is_banned(fname))
continue;
#ifdef No_sg_open_drive_fD
fd = open(fname, open_mode);
if (fd == -1) {
@ -281,6 +445,14 @@ void sg_enumerate(void)
sg_handle_busy_device(fname, errno);
continue;
}
#else
fd = sg_open_drive_fd(fname, 1);
if (fd == -1)
continue;
#endif /* ! No_sg_open_drive_fD */
/* found a drive */
ioctl(fd, SG_GET_SCSI_ID, &sid);
if (sg_close_drive_fd(fname, -1, &fd,
@ -288,6 +460,21 @@ void sg_enumerate(void)
continue;
if (sid.scsi_type != TYPE_ROM)
continue;
/* ts A60927 : trying to do locking with growisofs */
if(burn_sg_open_o_excl>1) {
ret = sg_open_scsi_siblings(
fname, -1, sibling_fds, &sibling_count,
sid.host_no, sid.channel,
sid.scsi_id, sid.lun);
if (ret<=0) {
sg_handle_busy_device(fname, 0);
continue;
}
/* the final occupation will be done in sg_grab() */
sg_release_siblings(sibling_fds, &sibling_count);
}
enumerate_common(fname, sid.host_no, sid.channel,
sid.scsi_id, sid.lun);
}
@ -296,6 +483,7 @@ void sg_enumerate(void)
static void enumerate_common(char *fname, int host_no, int channel_no,
int target_no, int lun_no)
{
int i;
struct burn_drive *t;
struct burn_drive out;
@ -307,6 +495,9 @@ static void enumerate_common(char *fname, int host_no, int channel_no,
out.devname = burn_strdup(fname);
out.fd = -1337;
out.sibling_count = 0;
for(i= 0; i<LIBBURN_SG_MAX_SIBLINGS; i++)
out.sibling_fds[i] = -1337;
out.grab = sg_grab;
out.release = sg_release;
@ -355,6 +546,7 @@ static void enumerate_common(char *fname, int host_no, int channel_no,
t->released = 1;
} else {
burn_print(2, "unable to grab new located drive\n");
burn_drive_unregister(t);
}
/* ts A60821
@ -373,7 +565,7 @@ static void enumerate_common(char *fname, int host_no, int channel_no,
*/
int sg_grab(struct burn_drive *d)
{
int fd, count, os_errno= 0;
int fd, count, os_errno= 0, ret;
/* ts A60813 */
int open_mode = O_RDWR;
@ -409,6 +601,17 @@ int sg_grab(struct burn_drive *d)
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_grab ----------- opening");
/* ts A60926 */
if(burn_sg_open_o_excl>1) {
fd = -1;
ret = sg_open_scsi_siblings(d->devname,
d->global_index,d->sibling_fds,
&(d->sibling_count),
d->host, d->channel, d->id, d->lun);
if(ret <= 0)
goto drive_is_in_use;
}
fd = open(d->devname, open_mode);
os_errno = errno;
} else
@ -420,19 +623,27 @@ int sg_grab(struct burn_drive *d)
/* ts A60814:
according to my experiments this test would work now ! */
/* ts A60926 : this was disabled */
/* Tests with growisofs on kernel 2.4.21 yielded that this
does not help against blocking on busy drives.
*/
/* <<< the old dummy */
/* er = ioctl(fd, SG_GET_ACCESS_COUNT, &count);*/
count = 1;
if (1 == count) {
d->fd = fd;
fcntl(fd, F_SETOWN, getpid());
d->released = 0;
return 1;
}
drive_is_in_use:;
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Could not grab drive - already in use", 0, 0);
sg_close_drive_fd(d->devname, d->global_index, &fd, 0);
sg_close_drive(d);
d->fd = -1337;
return 0;
}
@ -462,7 +673,7 @@ int sg_release(struct burn_drive *d)
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_release ----------- closing");
sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0);
sg_close_drive(d);
return 0;
}

View File

@ -18,6 +18,13 @@ int sg_is_enumerable_adr(char *adr);
int sg_obtain_scsi_adr(char *path, int *host_no, int *channel_no,
int *target_no, int *lun_no);
/* ts A60926 : ticket 33 ++ */
int sg_open_scsi_siblings(char *fname, int driveno,
int sibling_fds[], int *sibling_count,
int host_no, int channel_no, int id_no, int lun_no);
int sg_release_siblings(int sibling_fds[], int *sibling_count);
int sg_close_drive(struct burn_drive *d);
void sg_enumerate(void);
void ata_enumerate(void);
int sg_grab(struct burn_drive *);