2000-01-13 15:09:36 +03:00
/*
Unix SMB / Netbios implementation .
Version 3.0
byte range locking code
2000-04-26 00:30:58 +04:00
Updated to handle range splits / merges .
Copyright ( C ) Andrew Tridgell 1992 - 2000
Copyright ( C ) Jeremy Allison 1992 - 2000
2000-01-13 15:09:36 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2000-04-26 00:30:58 +04:00
/* This module implements a tdb based byte range locking service,
2000-01-13 15:09:36 +03:00
replacing the fcntl ( ) based byte range locking previously
used . This allows us to provide the same semantics as NT */
# include "includes.h"
2001-08-27 12:19:43 +04:00
# define ZERO_ZERO 0
2000-04-26 00:30:58 +04:00
/* This contains elements that differentiate locks. The smbpid is a
2000-01-13 15:09:36 +03:00
client supplied pid , and is essentially the locking context for
this client */
2000-04-26 00:30:58 +04:00
2000-01-13 15:09:36 +03:00
struct lock_context {
uint16 smbpid ;
uint16 tid ;
pid_t pid ;
} ;
2000-04-26 00:30:58 +04:00
/* The data in brlock records is an unsorted linear array of these
2000-01-13 15:09:36 +03:00
records . It is unnecessary to store the count as tdb provides the
size of the record */
2000-04-26 00:30:58 +04:00
2000-01-13 15:09:36 +03:00
struct lock_struct {
struct lock_context context ;
br_off start ;
br_off size ;
2000-01-14 07:32:57 +03:00
int fnum ;
2000-01-14 11:01:44 +03:00
enum brl_type lock_type ;
2000-01-13 15:09:36 +03:00
} ;
2000-04-26 00:30:58 +04:00
/* The key used in the brlock database. */
2000-01-13 15:09:36 +03:00
struct lock_key {
SMB_DEV_T device ;
SMB_INO_T inode ;
} ;
2000-04-26 00:30:58 +04:00
/* The open brlock.tdb database. */
2000-01-13 15:09:36 +03:00
2000-04-26 00:30:58 +04:00
static TDB_CONTEXT * tdb ;
2000-01-13 15:09:36 +03:00
2000-05-10 04:05:27 +04:00
/****************************************************************************
Create a locking key - ensuring zero filled for pad purposes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static TDB_DATA locking_key ( SMB_DEV_T dev , SMB_INO_T inode )
{
static struct lock_key key ;
TDB_DATA kbuf ;
memset ( & key , ' \0 ' , sizeof ( key ) ) ;
key . device = dev ;
key . inode = inode ;
kbuf . dptr = ( char * ) & key ;
kbuf . dsize = sizeof ( key ) ;
return kbuf ;
}
2000-01-13 15:09:36 +03:00
/****************************************************************************
2000-04-26 00:30:58 +04:00
See if two locking contexts are equal .
2000-01-13 15:09:36 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-26 00:30:58 +04:00
2000-01-13 15:09:36 +03:00
static BOOL brl_same_context ( struct lock_context * ctx1 ,
struct lock_context * ctx2 )
{
return ( ctx1 - > pid = = ctx2 - > pid ) & &
( ctx1 - > smbpid = = ctx2 - > smbpid ) & &
( ctx1 - > tid = = ctx2 - > tid ) ;
}
/****************************************************************************
2000-04-26 00:30:58 +04:00
See if lock2 can be added when lock1 is in place .
2000-01-13 15:09:36 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-26 00:30:58 +04:00
2000-01-13 15:09:36 +03:00
static BOOL brl_conflict ( struct lock_struct * lck1 ,
struct lock_struct * lck2 )
2001-08-25 01:09:38 +04:00
{
if ( lck1 - > lock_type = = READ_LOCK & & lck2 - > lock_type = = READ_LOCK ) {
return False ;
}
if ( brl_same_context ( & lck1 - > context , & lck2 - > context ) & &
lck2 - > lock_type = = READ_LOCK & & lck1 - > fnum = = lck2 - > fnum ) {
return False ;
}
if ( lck1 - > start > = ( lck2 - > start + lck2 - > size ) | |
lck2 - > start > = ( lck1 - > start + lck1 - > size ) ) {
return False ;
}
return True ;
}
2001-08-27 12:19:43 +04:00
# if ZERO_ZERO
static BOOL brl_conflict1 ( struct lock_struct * lck1 ,
struct lock_struct * lck2 )
{
if ( lck1 - > lock_type = = READ_LOCK & & lck2 - > lock_type = = READ_LOCK ) {
return False ;
}
if ( brl_same_context ( & lck1 - > context , & lck2 - > context ) & &
lck2 - > lock_type = = READ_LOCK & & lck1 - > fnum = = lck2 - > fnum ) {
return False ;
}
if ( lck2 - > start = = 0 & & lck2 - > size = = 0 & & lck1 - > size ! = 0 ) {
return True ;
}
if ( lck1 - > start > = ( lck2 - > start + lck2 - > size ) | |
lck2 - > start > = ( lck1 - > start + lck1 - > size ) ) {
return False ;
}
return True ;
}
# endif
2001-08-25 01:09:38 +04:00
/****************************************************************************
Check to see if this lock conflicts , but ignore our own locks on the
same fnum only .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL brl_conflict_other ( struct lock_struct * lck1 , struct lock_struct * lck2 )
2000-01-13 15:09:36 +03:00
{
2000-01-14 11:01:44 +03:00
if ( lck1 - > lock_type = = READ_LOCK & & lck2 - > lock_type = = READ_LOCK )
return False ;
2000-01-13 15:09:36 +03:00
if ( brl_same_context ( & lck1 - > context , & lck2 - > context ) & &
2001-08-25 01:09:38 +04:00
lck1 - > fnum = = lck2 - > fnum )
return False ;
2000-01-13 15:09:36 +03:00
if ( lck1 - > start > = ( lck2 - > start + lck2 - > size ) | |
lck2 - > start > = ( lck1 - > start + lck1 - > size ) ) return False ;
return True ;
}
/****************************************************************************
2001-05-23 00:35:48 +04:00
Delete a record if it is for a dead process , if check_self is true , then
delete any records belonging to this pid also ( there shouldn ' t be any ) .
2000-01-13 15:09:36 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-05-23 00:35:48 +04:00
2000-05-03 18:29:05 +04:00
static int delete_fn ( TDB_CONTEXT * ttdb , TDB_DATA kbuf , TDB_DATA dbuf , void * state )
{
struct lock_struct * locks ;
int count , i ;
2001-05-23 00:35:48 +04:00
BOOL check_self = * ( BOOL * ) state ;
pid_t mypid = sys_getpid ( ) ;
2000-05-03 18:29:05 +04:00
2000-12-06 03:05:15 +03:00
tdb_chainlock ( tdb , kbuf ) ;
2000-05-03 18:29:05 +04:00
locks = ( struct lock_struct * ) dbuf . dptr ;
count = dbuf . dsize / sizeof ( * locks ) ;
for ( i = 0 ; i < count ; i + + ) {
struct lock_struct * lock = & locks [ i ] ;
2001-05-23 00:35:48 +04:00
/* If check_self is true we want to remove our own records. */
if ( check_self & & ( mypid = = lock - > context . pid ) ) {
DEBUG ( 0 , ( " brlock : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists ! \n " ,
( unsigned int ) lock - > context . pid ) ) ;
} else if ( process_exists ( lock - > context . pid ) ) {
DEBUG ( 10 , ( " brlock : delete_fn. pid %u exists. \n " , ( unsigned int ) lock - > context . pid ) ) ;
continue ;
}
DEBUG ( 10 , ( " brlock : delete_fn. Deleting record for process %u \n " ,
( unsigned int ) lock - > context . pid ) ) ;
2000-05-03 18:29:05 +04:00
if ( count > 1 & & i < count - 1 ) {
memmove ( & locks [ i ] , & locks [ i + 1 ] ,
sizeof ( * locks ) * ( ( count - 1 ) - i ) ) ;
}
count - - ;
i - - ;
}
2000-04-26 00:30:58 +04:00
2000-05-03 18:29:05 +04:00
if ( count = = 0 ) {
tdb_delete ( tdb , kbuf ) ;
} else if ( count < ( dbuf . dsize / sizeof ( * locks ) ) ) {
2000-05-04 00:33:25 +04:00
dbuf . dsize = count * sizeof ( * locks ) ;
2000-05-03 18:29:05 +04:00
tdb_store ( tdb , kbuf , dbuf , TDB_REPLACE ) ;
}
2000-12-06 03:05:15 +03:00
tdb_chainunlock ( tdb , kbuf ) ;
2000-05-03 18:29:05 +04:00
return 0 ;
}
/****************************************************************************
Open up the brlock . tdb database .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-05-23 00:35:48 +04:00
2000-01-16 14:14:44 +03:00
void brl_init ( int read_only )
2000-01-13 15:09:36 +03:00
{
2001-05-23 00:35:48 +04:00
BOOL check_self = False ;
if ( tdb )
return ;
2001-09-07 02:08:19 +04:00
tdb = tdb_open_log ( lock_path ( " brlock.tdb " ) , 0 , TDB_DEFAULT | ( read_only ? 0x0 : TDB_CLEAR_IF_FIRST ) ,
2000-06-13 19:46:15 +04:00
read_only ? O_RDONLY : ( O_RDWR | O_CREAT ) , 0644 ) ;
2000-01-13 15:09:36 +03:00
if ( ! tdb ) {
DEBUG ( 0 , ( " Failed to open byte range locking database \n " ) ) ;
2000-05-03 18:29:05 +04:00
return ;
}
/* delete any dead locks */
2001-05-23 00:35:48 +04:00
if ( ! read_only )
tdb_traverse ( tdb , delete_fn , & check_self ) ;
2000-01-13 15:09:36 +03:00
}
2001-05-23 00:35:48 +04:00
/****************************************************************************
Close down the brlock . tdb database .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void brl_shutdown ( int read_only )
{
BOOL check_self = True ;
2001-05-23 22:33:45 +04:00
if ( ! tdb )
2001-05-23 00:35:48 +04:00
return ;
/* delete any dead locks */
if ( ! read_only )
tdb_traverse ( tdb , delete_fn , & check_self ) ;
tdb_close ( tdb ) ;
}
2000-01-13 15:09:36 +03:00
2001-08-27 12:19:43 +04:00
# if ZERO_ZERO
/****************************************************************************
compare two locks for sorting
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int lock_compare ( struct lock_struct * lck1 ,
struct lock_struct * lck2 )
{
if ( lck1 - > start ! = lck2 - > start ) return ( lck1 - > start - lck2 - > start ) ;
if ( lck2 - > size ! = lck1 - > size ) {
return ( ( int ) lck1 - > size - ( int ) lck2 - > size ) ;
}
return 0 ;
}
# endif
2000-01-13 15:09:36 +03:00
/****************************************************************************
2000-04-26 00:30:58 +04:00
Lock a range of bytes .
2000-01-13 15:09:36 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-26 00:30:58 +04:00
2001-09-06 05:19:35 +04:00
NTSTATUS brl_lock ( SMB_DEV_T dev , SMB_INO_T ino , int fnum ,
uint16 smbpid , pid_t pid , uint16 tid ,
br_off start , br_off size ,
enum brl_type lock_type )
2000-01-13 15:09:36 +03:00
{
TDB_DATA kbuf , dbuf ;
int count , i ;
struct lock_struct lock , * locks ;
2001-08-12 21:30:01 +04:00
char * tp ;
2001-09-06 05:19:35 +04:00
NTSTATUS status = NT_STATUS_OK ;
2000-01-13 15:09:36 +03:00
2000-05-10 04:05:27 +04:00
kbuf = locking_key ( dev , ino ) ;
2000-01-13 15:09:36 +03:00
dbuf . dptr = NULL ;
2001-08-27 12:19:43 +04:00
# if !ZERO_ZERO
2001-08-25 01:09:38 +04:00
if ( start = = 0 & & size = = 0 ) {
2001-08-27 12:19:43 +04:00
DEBUG ( 0 , ( " client sent 0/0 lock - please report this \n " ) ) ;
2001-09-06 05:19:35 +04:00
return NT_STATUS_INVALID_PARAMETER ;
2001-08-25 01:09:38 +04:00
}
# endif
2000-12-06 03:05:15 +03:00
tdb_chainlock ( tdb , kbuf ) ;
2000-01-13 15:09:36 +03:00
dbuf = tdb_fetch ( tdb , kbuf ) ;
lock . context . smbpid = smbpid ;
lock . context . pid = pid ;
lock . context . tid = tid ;
lock . start = start ;
lock . size = size ;
2000-01-14 07:32:57 +03:00
lock . fnum = fnum ;
2000-01-13 15:09:36 +03:00
lock . lock_type = lock_type ;
if ( dbuf . dptr ) {
/* there are existing locks - make sure they don't conflict */
locks = ( struct lock_struct * ) dbuf . dptr ;
count = dbuf . dsize / sizeof ( * locks ) ;
for ( i = 0 ; i < count ; i + + ) {
if ( brl_conflict ( & locks [ i ] , & lock ) ) {
2001-09-06 05:19:35 +04:00
status = NT_STATUS_LOCK_NOT_GRANTED ;
2000-01-13 15:09:36 +03:00
goto fail ;
}
2001-08-27 12:19:43 +04:00
# if ZERO_ZERO
if ( lock . start = = 0 & & lock . size = = 0 & &
locks [ i ] . size = = 0 ) {
break ;
}
# endif
2000-01-13 15:09:36 +03:00
}
}
/* no conflicts - add it to the list of locks */
2001-08-12 21:30:01 +04:00
tp = Realloc ( dbuf . dptr , dbuf . dsize + sizeof ( * locks ) ) ;
2001-09-06 05:19:35 +04:00
if ( ! tp ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
} else {
dbuf . dptr = tp ;
}
2000-01-13 15:09:36 +03:00
memcpy ( dbuf . dptr + dbuf . dsize , & lock , sizeof ( lock ) ) ;
dbuf . dsize + = sizeof ( lock ) ;
2001-08-27 12:19:43 +04:00
# if ZERO_ZERO
/* sort the lock list */
qsort ( dbuf . dptr , dbuf . dsize / sizeof ( lock ) , sizeof ( lock ) , lock_compare ) ;
# endif
2000-01-13 15:09:36 +03:00
tdb_store ( tdb , kbuf , dbuf , TDB_REPLACE ) ;
2001-09-17 08:16:35 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2000-12-06 03:05:15 +03:00
tdb_chainunlock ( tdb , kbuf ) ;
2001-09-06 05:19:35 +04:00
return NT_STATUS_OK ;
2000-01-13 15:09:36 +03:00
fail :
2001-09-17 08:16:35 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2000-12-06 03:05:15 +03:00
tdb_chainunlock ( tdb , kbuf ) ;
2001-09-06 05:19:35 +04:00
return status ;
2000-01-13 15:09:36 +03:00
}
/****************************************************************************
2000-04-26 00:30:58 +04:00
Unlock a range of bytes .
2000-01-13 15:09:36 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-26 00:30:58 +04:00
2000-01-14 07:32:57 +03:00
BOOL brl_unlock ( SMB_DEV_T dev , SMB_INO_T ino , int fnum ,
2000-01-13 15:09:36 +03:00
uint16 smbpid , pid_t pid , uint16 tid ,
br_off start , br_off size )
{
TDB_DATA kbuf , dbuf ;
int count , i ;
struct lock_struct * locks ;
struct lock_context context ;
2000-05-10 04:05:27 +04:00
kbuf = locking_key ( dev , ino ) ;
2000-01-13 15:09:36 +03:00
dbuf . dptr = NULL ;
2000-12-06 03:05:15 +03:00
tdb_chainlock ( tdb , kbuf ) ;
2000-01-13 15:09:36 +03:00
dbuf = tdb_fetch ( tdb , kbuf ) ;
2000-04-28 02:23:04 +04:00
if ( ! dbuf . dptr ) {
2000-04-29 00:54:23 +04:00
DEBUG ( 10 , ( " brl_unlock: tdb_fetch failed ! \n " ) ) ;
2000-04-28 02:23:04 +04:00
goto fail ;
}
2000-01-13 15:09:36 +03:00
context . smbpid = smbpid ;
context . pid = pid ;
context . tid = tid ;
/* there are existing locks - find a match */
locks = ( struct lock_struct * ) dbuf . dptr ;
count = dbuf . dsize / sizeof ( * locks ) ;
2000-04-26 00:30:58 +04:00
2001-08-27 12:19:43 +04:00
# if ZERO_ZERO
2001-08-25 01:09:38 +04:00
for ( i = 0 ; i < count ; i + + ) {
2000-04-26 00:30:58 +04:00
struct lock_struct * lock = & locks [ i ] ;
2001-08-25 01:09:38 +04:00
if ( lock - > lock_type = = WRITE_LOCK & &
brl_same_context ( & lock - > context , & context ) & &
lock - > fnum = = fnum & &
lock - > start = = start & &
lock - > size = = size ) {
/* found it - delete it */
if ( count = = 1 ) {
tdb_delete ( tdb , kbuf ) ;
} else {
if ( i < count - 1 ) {
memmove ( & locks [ i ] , & locks [ i + 1 ] ,
sizeof ( * locks ) * ( ( count - 1 ) - i ) ) ;
}
dbuf . dsize - = sizeof ( * locks ) ;
tdb_store ( tdb , kbuf , dbuf , TDB_REPLACE ) ;
}
2000-04-28 02:23:04 +04:00
2001-09-17 08:16:35 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2001-08-25 01:09:38 +04:00
tdb_chainunlock ( tdb , kbuf ) ;
return True ;
2000-04-28 02:23:04 +04:00
}
2001-08-25 01:09:38 +04:00
}
2001-08-27 12:19:43 +04:00
# endif
2001-08-25 01:09:38 +04:00
locks = ( struct lock_struct * ) dbuf . dptr ;
count = dbuf . dsize / sizeof ( * locks ) ;
for ( i = 0 ; i < count ; i + + ) {
struct lock_struct * lock = & locks [ i ] ;
2000-04-28 02:23:04 +04:00
2000-04-26 00:30:58 +04:00
if ( brl_same_context ( & lock - > context , & context ) & &
lock - > fnum = = fnum & &
lock - > start = = start & &
lock - > size = = size ) {
2000-01-13 15:09:36 +03:00
/* found it - delete it */
if ( count = = 1 ) {
tdb_delete ( tdb , kbuf ) ;
} else {
if ( i < count - 1 ) {
memmove ( & locks [ i ] , & locks [ i + 1 ] ,
sizeof ( * locks ) * ( ( count - 1 ) - i ) ) ;
}
dbuf . dsize - = sizeof ( * locks ) ;
tdb_store ( tdb , kbuf , dbuf , TDB_REPLACE ) ;
}
2001-09-17 08:16:35 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2000-12-06 03:05:15 +03:00
tdb_chainunlock ( tdb , kbuf ) ;
2000-01-13 15:09:36 +03:00
return True ;
}
}
/* we didn't find it */
fail :
2001-09-17 08:16:35 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2000-12-06 03:05:15 +03:00
tdb_chainunlock ( tdb , kbuf ) ;
2000-01-13 15:09:36 +03:00
return False ;
}
2001-06-30 05:59:48 +04:00
2000-01-13 15:09:36 +03:00
/****************************************************************************
2000-04-26 00:30:58 +04:00
Test if we could add a lock if we wanted to .
2000-01-13 15:09:36 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-26 00:30:58 +04:00
2000-05-06 00:50:22 +04:00
BOOL brl_locktest ( SMB_DEV_T dev , SMB_INO_T ino , int fnum ,
2000-01-13 15:09:36 +03:00
uint16 smbpid , pid_t pid , uint16 tid ,
br_off start , br_off size ,
2001-06-30 05:59:48 +04:00
enum brl_type lock_type , int check_self )
2000-01-13 15:09:36 +03:00
{
TDB_DATA kbuf , dbuf ;
int count , i ;
struct lock_struct lock , * locks ;
2000-05-10 04:05:27 +04:00
kbuf = locking_key ( dev , ino ) ;
2000-01-13 15:09:36 +03:00
dbuf . dptr = NULL ;
2000-12-06 03:05:15 +03:00
tdb_chainlock ( tdb , kbuf ) ;
2000-01-13 15:09:36 +03:00
dbuf = tdb_fetch ( tdb , kbuf ) ;
lock . context . smbpid = smbpid ;
lock . context . pid = pid ;
lock . context . tid = tid ;
lock . start = start ;
lock . size = size ;
2000-05-06 00:50:22 +04:00
lock . fnum = fnum ;
2000-01-13 15:09:36 +03:00
lock . lock_type = lock_type ;
if ( dbuf . dptr ) {
/* there are existing locks - make sure they don't conflict */
locks = ( struct lock_struct * ) dbuf . dptr ;
count = dbuf . dsize / sizeof ( * locks ) ;
for ( i = 0 ; i < count ; i + + ) {
2001-06-30 05:59:48 +04:00
if ( check_self ) {
if ( brl_conflict ( & locks [ i ] , & lock ) )
goto fail ;
} else {
/*
* Our own locks don ' t conflict .
*/
if ( brl_conflict_other ( & locks [ i ] , & lock ) )
goto fail ;
2000-01-13 15:09:36 +03:00
}
}
}
/* no conflicts - we could have added it */
2001-09-17 08:16:35 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2000-12-06 03:05:15 +03:00
tdb_chainunlock ( tdb , kbuf ) ;
2000-01-13 15:09:36 +03:00
return True ;
fail :
2001-09-17 08:16:35 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2000-12-06 03:05:15 +03:00
tdb_chainunlock ( tdb , kbuf ) ;
2000-01-13 15:09:36 +03:00
return False ;
}
2000-01-14 07:32:57 +03:00
/****************************************************************************
2000-04-26 00:30:58 +04:00
Remove any locks associated with a open file .
2000-01-14 07:32:57 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-26 00:30:58 +04:00
2000-01-14 07:32:57 +03:00
void brl_close ( SMB_DEV_T dev , SMB_INO_T ino , pid_t pid , int tid , int fnum )
{
TDB_DATA kbuf , dbuf ;
2000-05-03 18:29:05 +04:00
int count , i , dcount = 0 ;
2000-01-14 07:32:57 +03:00
struct lock_struct * locks ;
2000-05-10 04:05:27 +04:00
kbuf = locking_key ( dev , ino ) ;
2000-01-14 07:32:57 +03:00
dbuf . dptr = NULL ;
2000-12-06 03:05:15 +03:00
tdb_chainlock ( tdb , kbuf ) ;
2000-01-14 07:32:57 +03:00
dbuf = tdb_fetch ( tdb , kbuf ) ;
if ( ! dbuf . dptr ) goto fail ;
/* there are existing locks - remove any for this fnum */
locks = ( struct lock_struct * ) dbuf . dptr ;
count = dbuf . dsize / sizeof ( * locks ) ;
for ( i = 0 ; i < count ; i + + ) {
2000-04-26 00:30:58 +04:00
struct lock_struct * lock = & locks [ i ] ;
if ( lock - > context . tid = = tid & &
lock - > context . pid = = pid & &
lock - > fnum = = fnum ) {
2000-01-14 07:32:57 +03:00
/* found it - delete it */
if ( count > 1 & & i < count - 1 ) {
memmove ( & locks [ i ] , & locks [ i + 1 ] ,
sizeof ( * locks ) * ( ( count - 1 ) - i ) ) ;
}
count - - ;
i - - ;
2000-05-03 18:29:05 +04:00
dcount + + ;
2000-01-14 07:32:57 +03:00
}
}
if ( count = = 0 ) {
tdb_delete ( tdb , kbuf ) ;
} else if ( count < ( dbuf . dsize / sizeof ( * locks ) ) ) {
2000-05-03 18:29:05 +04:00
dbuf . dsize - = dcount * sizeof ( * locks ) ;
2000-01-14 07:32:57 +03:00
tdb_store ( tdb , kbuf , dbuf , TDB_REPLACE ) ;
}
/* we didn't find it */
fail :
2001-09-17 08:16:35 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2000-12-06 03:05:15 +03:00
tdb_chainunlock ( tdb , kbuf ) ;
2000-01-14 07:32:57 +03:00
}
2000-01-16 14:14:44 +03:00
/****************************************************************************
2000-04-26 00:30:58 +04:00
Traverse the whole database with this function , calling traverse_callback
on each lock .
2000-01-16 14:14:44 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-26 00:30:58 +04:00
1) added void* state argument to tdb_traverse. guess what! there were
two places i found where it was appropriate to _use_ that third argument,
in locking.c and brlock.c! there was a static traverse_function and
i removed the static variable, typecast it to a void*, passed it to
tdb_traverse and re-cast it back to the traverse_function inside the
tdb_traverse function. this makes the use of tdb_traverse() reentrant,
which is never going to happen, i know, i just don't like to see
statics lying about when there's no need for them.
as i had to do in samba-tng, all uses of tdb_traverse modified to take
the new void* state argument.
2) disabled rpcclient: referring people to use SAMBA_TNG rpcclient.
i don't know how the other samba team members would react if i deleted
rpcclient from cvs main. damn, that code's so old, it's unreal.
20 rpcclient commands, instead of about 70 in SAMBA_TNG.
(This used to be commit 49d7f0afbc1c5425d53019e234d54ddf205c8e9a)
2000-02-04 07:59:31 +03:00
static int traverse_fn ( TDB_CONTEXT * ttdb , TDB_DATA kbuf , TDB_DATA dbuf , void * state )
2000-01-16 14:14:44 +03:00
{
struct lock_struct * locks ;
struct lock_key * key ;
int i ;
1) added void* state argument to tdb_traverse. guess what! there were
two places i found where it was appropriate to _use_ that third argument,
in locking.c and brlock.c! there was a static traverse_function and
i removed the static variable, typecast it to a void*, passed it to
tdb_traverse and re-cast it back to the traverse_function inside the
tdb_traverse function. this makes the use of tdb_traverse() reentrant,
which is never going to happen, i know, i just don't like to see
statics lying about when there's no need for them.
as i had to do in samba-tng, all uses of tdb_traverse modified to take
the new void* state argument.
2) disabled rpcclient: referring people to use SAMBA_TNG rpcclient.
i don't know how the other samba team members would react if i deleted
rpcclient from cvs main. damn, that code's so old, it's unreal.
20 rpcclient commands, instead of about 70 in SAMBA_TNG.
(This used to be commit 49d7f0afbc1c5425d53019e234d54ddf205c8e9a)
2000-02-04 07:59:31 +03:00
BRLOCK_FN ( traverse_callback ) = ( BRLOCK_FN_CAST ( ) ) state ;
2000-01-16 14:14:44 +03:00
locks = ( struct lock_struct * ) dbuf . dptr ;
key = ( struct lock_key * ) kbuf . dptr ;
for ( i = 0 ; i < dbuf . dsize / sizeof ( * locks ) ; i + + ) {
traverse_callback ( key - > device , key - > inode ,
locks [ i ] . context . pid ,
locks [ i ] . lock_type ,
locks [ i ] . start ,
locks [ i ] . size ) ;
}
return 0 ;
}
/*******************************************************************
2000-04-26 00:30:58 +04:00
Call the specified function on each lock in the database .
2000-01-16 14:14:44 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-26 00:30:58 +04:00
1) added void* state argument to tdb_traverse. guess what! there were
two places i found where it was appropriate to _use_ that third argument,
in locking.c and brlock.c! there was a static traverse_function and
i removed the static variable, typecast it to a void*, passed it to
tdb_traverse and re-cast it back to the traverse_function inside the
tdb_traverse function. this makes the use of tdb_traverse() reentrant,
which is never going to happen, i know, i just don't like to see
statics lying about when there's no need for them.
as i had to do in samba-tng, all uses of tdb_traverse modified to take
the new void* state argument.
2) disabled rpcclient: referring people to use SAMBA_TNG rpcclient.
i don't know how the other samba team members would react if i deleted
rpcclient from cvs main. damn, that code's so old, it's unreal.
20 rpcclient commands, instead of about 70 in SAMBA_TNG.
(This used to be commit 49d7f0afbc1c5425d53019e234d54ddf205c8e9a)
2000-02-04 07:59:31 +03:00
int brl_forall ( BRLOCK_FN ( fn ) )
2000-01-16 14:14:44 +03:00
{
if ( ! tdb ) return 0 ;
2000-11-18 02:10:56 +03:00
return tdb_traverse ( tdb , traverse_fn , ( void * ) fn ) ;
2000-01-16 14:14:44 +03:00
}