Cleaned up scsi sibling management, sketched grafting of DDLP

This commit is contained in:
Thomas Schmitt 2007-04-09 10:54:17 +00:00
parent 1a054b54c9
commit 4bc8e4caea
5 changed files with 74 additions and 47 deletions

View File

@ -753,8 +753,8 @@ Device file family /dev/hdX on kernel >= 2.6 is not affected by this setting.
.TP
.BI \--drive_scsi_exclusive
Linux specific:
Try to exclusively reserve device files /dev/srN, /dev/scdM, /dev/stK of drive.
this would be helpful to protect against collisions with program growisofs.
Try to exclusively reserve device files /dev/srN, /dev/scdM, /dev/sgK of drives.
This would be helpful to protect against collisions with program growisofs.
Regrettably on Linux kernel 2.4 with ide-scsi emulation this seems not to
work. Wether it becomes helpful with new Linux systems has to be evaluated.
.TP

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2007.04.04.184341"
#define Cdrskin_timestamP "2007.04.09.105543"

View File

@ -52,6 +52,10 @@ SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
typedef int burn_drive_enumerator_t;
/* Parameters for sibling list. See sibling_fds, sibling_fnames */
#define BURN_OS_SG_MAX_SIBLINGS 5
#define BURN_OS_SG_MAX_NAMELEN 16
/* The list of operating system dependent elements in struct burn_drive.
Usually they are initialized in sg-*.c:enumerate_common().
*/
@ -60,5 +64,7 @@ int fd; \
\
/* ts A60926 : trying to lock against growisofs /dev/srN, /dev/scdN */ \
int sibling_count; \
int sibling_fds[LIBBURN_SG_MAX_SIBLINGS];
int sibling_fds[BURN_OS_SG_MAX_SIBLINGS]; \
/* ts A70409 : DDLP */ \
char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN];

View File

@ -75,11 +75,10 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
#include <scsi/sg.h>
#include <scsi/scsi.h>
/* ts A61211 : to recognize CD devices on /dev/sr* */
/* ts A61211 : to eventually recognize CD devices on /dev/sr* */
#include <linux/cdrom.h>
/* ts A61211 : preparing for exploration of recent Linux ATA adventures */
/** PORTING : Device file families for bus scanning and drive access.
Both device families must support the following ioctls:
SG_IO,
@ -169,7 +168,6 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no);
/* >>> ts A61115 : this needs mending. A Linux aspect shows up in cdrskin. */
/* ts A60813 : storage objects are in libburn/init.c
wether to use O_EXCL with open(2) of devices
wether to use fcntl(,F_SETLK,) after open(2) of devices
@ -197,14 +195,22 @@ int mmc_function_spy(char * text);
/* This installs the device file family if one was chosen explicitely
by burn_preset_device_open()
*/
void sg_select_device_family(void)
static void sg_select_device_family(void)
{
/* >>> ??? do we need a mutex here ? */
/* >>> (It might be concurrent but is supposed to have always
the same effect. Any race condition should be harmless.) */
if (linux_sg_auto_family) {
if (burn_sg_use_family == 1)
strcpy(linux_sg_device_family, "/dev/sr%d");
else if (burn_sg_use_family == 2)
strcpy(linux_sg_device_family, "/dev/scd%d");
else if (burn_sg_use_family == 3)
strcpy(linux_sg_device_family, "/dev/st%d");
else if (burn_sg_use_family == 4)
strcpy(linux_sg_device_family, "/dev/sg%d");
else if (linux_sg_auto_family) {
int use_sr_family = 0;
struct utsname buf;
@ -217,15 +223,6 @@ void sg_select_device_family(void)
strcpy(linux_sg_device_family, "/dev/sg%d");
linux_sg_auto_family = 0;
}
if (burn_sg_use_family == 1)
strcpy(linux_sg_device_family, "/dev/sr%d");
else if (burn_sg_use_family == 2)
strcpy(linux_sg_device_family, "/dev/scd%d");
else if (burn_sg_use_family == 3)
strcpy(linux_sg_device_family, "/dev/st%d");
else if (burn_sg_use_family == 4)
strcpy(linux_sg_device_family, "/dev/sg%d");
}
@ -279,16 +276,14 @@ static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
return(0);
ret = close(*fd);
*fd = -1337;
if(ret != -1)
if(ret != -1) {
/* ts A70409 : DDLP */
/* >>> release single lock on fname */
return 1;
}
os_errno= errno;
if (fname != NULL)
sprintf(msg, "Encountered error when closing drive '%s'",
fname);
else
sprintf(msg, "Encountered error when closing drive");
sprintf(msg, "Encountered error when closing drive '%s'", fname);
if (sorry)
sevno = LIBDAX_MSGS_SEV_SORRY;
libdax_msgs_submit(libdax_messenger, driveno, 0x00020002,
@ -298,13 +293,11 @@ static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
/* ts A70401 :
In http://lkml.org/lkml/2007/3/31/187 , Alan Cox demands usage of
SG_IO on block devices and of fcntl rather than O_EXCL.
fcntl() has the unappealing property to work only after open().
So libburn will by default use open(O_EXCL) first and afterwards
as second assertion will use fcntl(F_SETLK).
as second assertion will use fcntl(F_SETLK). One lock more should not harm.
*/
int sg_fcntl_lock(int *fd, char *fd_name)
static int sg_fcntl_lock(int *fd, char *fd_name)
{
struct flock lockthing;
char msg[81];
@ -329,6 +322,10 @@ int sg_fcntl_lock(int *fd, char *fd_name)
msg, errno, 0);
close(*fd);
*fd = -1;
/* ts A70409 : DDLP */
/* >>> release single lock on fd_name */
return(0);
}
return 1;
@ -341,6 +338,9 @@ static int sg_open_drive_fd(char *fname, int scan_mode)
int open_mode = O_RDWR, fd;
char msg[81];
/* ts A70409 : DDLP */
/* >>> obtain single lock on fname */
/* ts A60813 - A60927
O_EXCL with devices is a non-POSIX feature
of Linux kernels. Possibly introduced 2002.
@ -389,13 +389,15 @@ static int sg_open_drive_fd(char *fname, int scan_mode)
/* ts A60926 */
static int sg_release_siblings(int sibling_fds[], int *sibling_count)
static int sg_release_siblings(int sibling_fds[],
char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN],
int *sibling_count)
{
int i;
char msg[81];
for(i= 0; i < *sibling_count; i++)
sg_close_drive_fd(NULL, -1, &(sibling_fds[i]), 0);
sg_close_drive_fd(sibling_fnames[i], -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,
@ -413,7 +415,8 @@ static int sg_close_drive(struct burn_drive *d)
if (!burn_drive_is_open(d))
return 0;
sg_release_siblings(d->sibling_fds, &(d->sibling_count));
sg_release_siblings(d->sibling_fds, d->sibling_fnames,
&(d->sibling_count));
ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0);
return ret;
}
@ -421,15 +424,19 @@ static int sg_close_drive(struct burn_drive *d)
/* ts A60926 */
static int sg_open_scsi_siblings(char *path, int driveno,
int sibling_fds[], int *sibling_count,
int sibling_fds[],
char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN],
int *sibling_count,
int host_no, int channel_no, int id_no, int lun_no)
{
int tld, i, ret, fd, i_bus_no = -1;
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
char msg[161], fname[81];
struct stat stbuf;
dev_t last_rdev;
static char tldev[][81]= {"/dev/sr%d", "/dev/scd%d", "/dev/st%d",
"/dev/sg%d", ""};
static char tldev[][81]= {"/dev/sr%d", "/dev/scd%d", "/dev/sg%d", ""};
/* ts A70609: removed "/dev/st%d" */
sg_select_device_family();
if (linux_sg_device_family[0] == 0)
@ -438,13 +445,18 @@ static int sg_open_scsi_siblings(char *path, int driveno,
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);
sg_release_siblings(sibling_fds, sibling_fnames,
sibling_count);
for (tld = 0; tldev[tld][0] != 0; tld++) {
if (strcmp(tldev[tld], linux_sg_device_family)==0)
continue;
for (i = 0; i < 32; i++) {
sprintf(fname, tldev[tld], i);
if(stat(fname, &stbuf) != -1)
continue;
if (*sibling_count > 0 && last_rdev == stbuf.st_rdev)
continue;
ret = sg_obtain_scsi_adr(fname, &i_bus_no, &i_host_no,
&i_channel_no, &i_target_no, &i_lun_no);
if (ret <= 0)
@ -458,7 +470,7 @@ static int sg_open_scsi_siblings(char *path, int driveno,
if (fd < 0)
goto failed;
if (*sibling_count>=LIBBURN_SG_MAX_SIBLINGS) {
if (*sibling_count>=BURN_OS_SG_MAX_SIBLINGS) {
sprintf(msg, "Too many scsi siblings of '%s'",
path);
libdax_msgs_submit(libdax_messenger,
@ -474,12 +486,14 @@ static int sg_open_scsi_siblings(char *path, int driveno,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
sibling_fds[*sibling_count] = fd;
strcpy(sibling_fnames[*sibling_count], fname);
(*sibling_count)++;
last_rdev= stbuf.st_rdev;
}
}
return 1;
failed:;
sg_release_siblings(sibling_fds, sibling_count);
sg_release_siblings(sibling_fds, sibling_fnames, sibling_count);
return 0;
}
@ -557,10 +571,11 @@ static void ata_enumerate(void)
static void sg_enumerate(void)
{
struct sg_scsi_id sid;
int i, fd, sibling_fds[LIBBURN_SG_MAX_SIBLINGS], sibling_count= 0, ret;
int i, fd, sibling_fds[BURN_OS_SG_MAX_SIBLINGS], sibling_count= 0, ret;
int sid_ret = 0;
int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
char fname[10];
char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN];
sg_select_device_family();
@ -673,7 +688,8 @@ static void sg_enumerate(void)
/* 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,
fname, -1, sibling_fds, sibling_fnames,
&sibling_count,
sid.host_no, sid.channel,
sid.scsi_id, sid.lun);
if (ret<=0) {
@ -683,7 +699,8 @@ static void sg_enumerate(void)
continue;
}
/* the final occupation will be done in sg_grab() */
sg_release_siblings(sibling_fds, &sibling_count);
sg_release_siblings(sibling_fds, sibling_fnames,
&sibling_count);
}
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
if(bus_no == -1)
@ -737,7 +754,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* Adapter specific handles and data */
out.fd = -1337;
out.sibling_count = 0;
for(i= 0; i<LIBBURN_SG_MAX_SIBLINGS; i++)
for(i= 0; i<BURN_OS_SG_MAX_SIBLINGS; i++)
out.sibling_fds[i] = -1337;
/* PORTING: ---------------- end of non portable part ------------ */
@ -901,12 +918,15 @@ int sg_grab(struct burn_drive *d)
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_grab ----------- opening");
/* ts A70409 : DDLP */
/* >>> obtain single lock on d->devname */
/* 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->sibling_fnames,&(d->sibling_count),
d->host, d->channel, d->id, d->lun);
if(ret <= 0)
goto drive_is_in_use;
@ -1141,6 +1161,9 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
&& path[7] >= 'a' && path[7] <= 'z' && path[8] == 0)
return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */
/* ts A70409 : DDLP */
/* >>> obtain single lock on path */
fd = open(path, O_RDONLY | O_NONBLOCK);
if(fd < 0)
return 0;

View File

@ -117,8 +117,6 @@ struct burn_format_descr {
};
#define LIBBURN_SG_MAX_SIBLINGS 16
/** Gets initialized in enumerate_common() and burn_drive_register() */
struct burn_drive
{