|
|
|
@ -3,6 +3,23 @@
|
|
|
|
|
Implementation of Delicate Device Locking Protocol level A.
|
|
|
|
|
Copyright (C) 2007 Thomas Schmitt <scdbackup@gmx.net>
|
|
|
|
|
Provided under any of the following licenses: GPL, LGPL, BSD. Choose one.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Compile as test program:
|
|
|
|
|
|
|
|
|
|
cc -g -Wall \
|
|
|
|
|
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \
|
|
|
|
|
-DDDLPA_C_STANDALONE -o ddlpa ddlpa.c
|
|
|
|
|
|
|
|
|
|
The system macros are needed for 8-bit off_t and for open flag O_LARGEFILE
|
|
|
|
|
which are not absolutely necessary but explicitely take into respect that
|
|
|
|
|
our devices can offer more than 2 GB of addressable data.
|
|
|
|
|
|
|
|
|
|
Run test program:
|
|
|
|
|
|
|
|
|
|
./ddlpa /dev/sr0 15
|
|
|
|
|
./ddlpa 0,0,0 15
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
@ -91,7 +108,7 @@ static int ddlpa_std_by_rdev(struct ddlpa_lock *o)
|
|
|
|
|
|
|
|
|
|
if (ddlpa_debug_mode)
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"DDLPA_DEBUG: ddlpa_std_by_rdev(\"%s\") = \"%s\"\n",
|
|
|
|
|
"DDLPA_DEBUG: ddlpa_std_by_rdev(\"%s\") = \"%s\"\n",
|
|
|
|
|
o->path, o->std_path);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
@ -143,20 +160,32 @@ static int ddlpa_fcntl_lock(struct ddlpa_lock *o, int fd, int l_type)
|
|
|
|
|
static int ddlpa_occupy(struct ddlpa_lock *o, char *path, int *fd,
|
|
|
|
|
int no_o_excl)
|
|
|
|
|
{
|
|
|
|
|
int ret, o_flags = O_RDWR | O_NDELAY;
|
|
|
|
|
int ret, o_flags, o_rw, l_type;
|
|
|
|
|
char *o_rwtext;
|
|
|
|
|
|
|
|
|
|
o_flags = o->o_flags | O_NDELAY;
|
|
|
|
|
if(!no_o_excl)
|
|
|
|
|
o_flags |= O_EXCL;
|
|
|
|
|
o_rw = (o_flags) & (O_RDONLY | O_WRONLY | O_RDWR);
|
|
|
|
|
o_rwtext = (o_rw == O_RDONLY ? "O_RDONLY" :
|
|
|
|
|
(o_rw == O_WRONLY ? "O_WRONLY" :
|
|
|
|
|
(o_rw == O_RDWR ? "O_RDWR " : "O_?rw-mode?")));
|
|
|
|
|
|
|
|
|
|
*fd = open(path, o_flags);
|
|
|
|
|
if (*fd == -1) {
|
|
|
|
|
o->errmsg = malloc(strlen(path)+160);
|
|
|
|
|
if (o->errmsg)
|
|
|
|
|
sprintf(o->errmsg,
|
|
|
|
|
"Failed to open O_RDWR | O_NDELAY %s: '%s'",
|
|
|
|
|
(no_o_excl ? "" : "| O_EXCL "), path);
|
|
|
|
|
"Failed to open %s | O_NDELAY %s: '%s'",
|
|
|
|
|
o_rwtext,
|
|
|
|
|
(o_flags & O_EXCL ? "| O_EXCL " : ""), path);
|
|
|
|
|
return (errno ? errno : EBUSY);
|
|
|
|
|
}
|
|
|
|
|
ret = ddlpa_fcntl_lock(o, *fd, F_WRLCK);
|
|
|
|
|
if (o_rw == O_RDWR || o_rw == O_WRONLY)
|
|
|
|
|
l_type = F_WRLCK;
|
|
|
|
|
else
|
|
|
|
|
l_type = F_RDLCK;
|
|
|
|
|
ret = ddlpa_fcntl_lock(o, *fd, l_type);
|
|
|
|
|
if (ret) {
|
|
|
|
|
o->errmsg = malloc(strlen(path)+160);
|
|
|
|
|
if (o->errmsg)
|
|
|
|
@ -167,7 +196,8 @@ static int ddlpa_occupy(struct ddlpa_lock *o, char *path, int *fd,
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
if (ddlpa_debug_mode)
|
|
|
|
|
fprintf(stderr, "DDLPA_DEBUG: ddlpa_occupy() %s: '%s'\n",
|
|
|
|
|
fprintf(stderr, "DDLPA_DEBUG: ddlpa_occupy() %s %s: '%s'\n",
|
|
|
|
|
o_rwtext,
|
|
|
|
|
(no_o_excl ? " " : "O_EXCL "), path);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -270,7 +300,7 @@ static int ddlpa_collect_siblings(struct ddlpa_lock *o)
|
|
|
|
|
|
|
|
|
|
if (ddlpa_debug_mode)
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"DDLPA_DEBUG: ddlpa_collect_siblings() found \"%s\"\n",
|
|
|
|
|
"DDLPA_DEBUG: ddlpa_collect_siblings() found \"%s\"\n",
|
|
|
|
|
try_path);
|
|
|
|
|
|
|
|
|
|
(o->num_siblings)++;
|
|
|
|
@ -315,7 +345,7 @@ static int ddlpa_std_by_btl(struct ddlpa_lock *o)
|
|
|
|
|
|
|
|
|
|
if (ddlpa_debug_mode)
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"DDLPA_DEBUG: ddlpa_std_by_rdev(%d,%d,%d) = \"%s\"\n",
|
|
|
|
|
"DDLPA_DEBUG: ddlpa_std_by_btl(%d,%d,%d) = \"%s\"\n",
|
|
|
|
|
t_bus, t_id, t_lun, o->std_path);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
@ -490,6 +520,14 @@ usage:;
|
|
|
|
|
if (duration < 0)
|
|
|
|
|
goto usage;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* For our purpose, only O_RDWR is a suitable access mode.
|
|
|
|
|
But in order to allow experiments, o_flags are freely adjustable.
|
|
|
|
|
|
|
|
|
|
Warning: Do _not_ set an own O_EXCL flag with the following calls !
|
|
|
|
|
|
|
|
|
|
(This freedom to fail may get removed in a final version.)
|
|
|
|
|
*/
|
|
|
|
|
if (my_path[0] != '/' && my_path[0] != '.' &&
|
|
|
|
|
strchr(my_path, ',') != NULL) {
|
|
|
|
|
/*
|
|
|
|
@ -497,15 +535,17 @@ usage:;
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
sscanf(my_path, "%d,%d,%d", &bus, &target, &lun);
|
|
|
|
|
ret = ddlpa_lock_btl(bus, target, lun, O_RDWR, 0, &lck,
|
|
|
|
|
&errmsg);
|
|
|
|
|
ret = ddlpa_lock_btl(bus, target, lun, O_RDWR | O_LARGEFILE,
|
|
|
|
|
0, &lck, &errmsg);
|
|
|
|
|
} else {
|
|
|
|
|
/*
|
|
|
|
|
This substitutes for:
|
|
|
|
|
fd = open(my_path, O_RDWR | O_EXCL);
|
|
|
|
|
fd = open(my_path, O_RDWR | O_EXCL | O_LARGEFILE);
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
ret = ddlpa_lock_path(my_path, O_RDWR, 0, &lck, &errmsg);
|
|
|
|
|
ret = ddlpa_lock_path(my_path, O_RDWR | O_LARGEFILE,
|
|
|
|
|
0, &lck, &errmsg);
|
|
|
|
|
}
|
|
|
|
|
if (ret) {
|
|
|
|
|
fprintf(stderr, "Cannot exclusively open '%s'\n", my_path);
|
|
|
|
|