1997-10-20 12:46:00 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
shared memory locking implementation
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
1997-10-20 12:46:00 +04: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 .
Revision History :
12 aug 96 : Erik . Devriendt @ te6 . siemens . be
added support for shared memory implementation of share mode locking
May 1997. Jeremy Allison ( jallison @ whistle . com ) . Modified share mode
locking to deal with multiple share modes per open file .
September 1997. Jeremy Allison ( jallison @ whistle . com ) . Added oplock
support .
October 1997 - split into separate file ( tridge )
*/
1998-07-29 07:08:05 +04:00
# include "includes.h"
1997-10-20 12:46:00 +04:00
# ifdef FAST_SHARE_MODES
extern int DEBUGLEVEL ;
1997-10-28 17:19:54 +03:00
static struct shmem_ops * shmops ;
1997-10-20 12:46:00 +04:00
/* share mode record pointed to in shared memory hash bucket */
typedef struct
{
1997-10-22 15:15:14 +04:00
int next_offset ; /* offset of next record in chain from hash bucket */
1997-10-20 12:46:00 +04:00
int locking_version ;
1998-09-01 00:20:54 +04:00
SMB_DEV_T st_dev ;
SMB_INO_T st_ino ;
1997-10-20 12:46:00 +04:00
int num_share_mode_entries ;
1997-10-22 15:15:14 +04:00
int share_mode_entries ; /* Chain of share mode entries for this file */
1997-10-20 12:46:00 +04:00
char file_name [ 1 ] ;
} share_mode_record ;
/* share mode entry pointed to by share_mode_record struct */
typedef struct
{
1997-10-22 15:15:14 +04:00
int next_share_mode_entry ;
1997-10-20 12:46:00 +04:00
share_mode_entry e ;
} shm_share_mode_entry ;
1997-10-27 17:27:17 +03:00
static int read_only ;
1997-10-20 12:46:00 +04:00
1997-10-28 17:40:31 +03:00
/* Conversion to hash entry index from device and inode numbers. */
1998-09-01 00:20:54 +04:00
# define HASH_ENTRY(dev,ino) ((unsigned int)(((dev) ^ (ino)) % shmops->hash_size()))
1997-10-28 17:40:31 +03:00
1997-10-20 12:46:00 +04:00
/*******************************************************************
deinitialize the shared memory for share_mode management
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL shm_stop_share_mode_mgmt ( void )
{
1997-12-04 10:41:48 +03:00
return shmops - > shm_close ( ) ;
1997-10-20 12:46:00 +04:00
}
/*******************************************************************
lock a hash bucket entry in shared memory for share_mode management
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static BOOL shm_lock_share_entry ( connection_struct * conn ,
1998-09-01 00:20:54 +04:00
SMB_DEV_T dev , SMB_INO_T inode , int * ptok )
1997-10-20 12:46:00 +04:00
{
1998-08-14 21:38:29 +04:00
return shmops - > lock_hash_entry ( HASH_ENTRY ( dev , inode ) ) ;
1997-10-20 12:46:00 +04:00
}
/*******************************************************************
unlock a hash bucket entry in shared memory for share_mode management
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static BOOL shm_unlock_share_entry ( connection_struct * conn ,
1998-09-01 00:20:54 +04:00
SMB_DEV_T dev , SMB_INO_T inode , int token )
1997-10-20 12:46:00 +04:00
{
1997-10-28 17:19:54 +03:00
return shmops - > unlock_hash_entry ( HASH_ENTRY ( dev , inode ) ) ;
1997-10-20 12:46:00 +04:00
}
/*******************************************************************
get all share mode entries in shared memory for a dev / inode pair .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int shm_get_share_modes ( connection_struct * conn ,
1998-09-01 00:20:54 +04:00
int token , SMB_DEV_T dev , SMB_INO_T inode ,
1997-10-20 12:46:00 +04:00
share_mode_entry * * old_shares )
{
1997-10-22 15:15:14 +04:00
int * mode_array ;
1997-10-20 12:46:00 +04:00
unsigned int hash_entry = HASH_ENTRY ( dev , inode ) ;
share_mode_record * file_scanner_p ;
share_mode_record * file_prev_p ;
shm_share_mode_entry * entry_scanner_p ;
shm_share_mode_entry * entry_prev_p ;
int num_entries ;
int num_entries_copied ;
BOOL found = False ;
share_mode_entry * share_array = ( share_mode_entry * ) 0 ;
* old_shares = 0 ;
1997-10-28 17:19:54 +03:00
mode_array = ( int * ) shmops - > offset2addr ( shmops - > get_userdef_off ( ) ) ;
1997-10-20 12:46:00 +04:00
1997-11-01 10:33:55 +03:00
if ( mode_array [ hash_entry ] = = 0 )
1997-10-20 12:46:00 +04:00
{
1997-11-01 10:33:55 +03:00
DEBUG ( 5 , ( " get_share_modes hash bucket %d empty \n " , hash_entry ) ) ;
1997-10-20 12:46:00 +04:00
return 0 ;
}
1997-10-28 17:19:54 +03:00
file_scanner_p = ( share_mode_record * ) shmops - > offset2addr ( mode_array [ hash_entry ] ) ;
1997-10-20 12:46:00 +04:00
file_prev_p = file_scanner_p ;
while ( file_scanner_p )
{
if ( ( file_scanner_p - > st_dev = = dev ) & & ( file_scanner_p - > st_ino = = inode ) )
{
found = True ;
break ;
}
else
{
file_prev_p = file_scanner_p ;
1997-10-28 17:19:54 +03:00
file_scanner_p = ( share_mode_record * ) shmops - > offset2addr (
1997-10-20 12:46:00 +04:00
file_scanner_p - > next_offset ) ;
}
}
if ( ! found )
{
1998-09-05 00:53:58 +04:00
DEBUG ( 5 , ( " get_share_modes no entry for file dev = %x ino = %.0f \n " ,
( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
return ( 0 ) ;
}
if ( file_scanner_p - > locking_version ! = LOCKING_VERSION )
{
1998-09-05 00:53:58 +04:00
DEBUG ( 0 , ( " ERROR: get_share_modes Deleting old share mode v1 %d dev=%x ino=%.0f \n " ,
file_scanner_p - > locking_version , ( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
if ( file_prev_p = = file_scanner_p )
mode_array [ hash_entry ] = file_scanner_p - > next_offset ;
else
file_prev_p - > next_offset = file_scanner_p - > next_offset ;
1997-12-04 10:41:48 +03:00
shmops - > shm_free ( shmops - > addr2offset ( file_scanner_p ) ) ;
1997-10-20 12:46:00 +04:00
return ( 0 ) ;
}
/* Allocate the old_shares array */
num_entries = file_scanner_p - > num_share_mode_entries ;
if ( num_entries )
{
* old_shares = share_array = ( share_mode_entry * )
malloc ( num_entries * sizeof ( share_mode_entry ) ) ;
if ( * old_shares = = 0 )
{
1997-11-01 10:33:55 +03:00
DEBUG ( 0 , ( " get_share_modes: malloc fail! \n " ) ) ;
1997-10-20 12:46:00 +04:00
return 0 ;
}
}
num_entries_copied = 0 ;
1997-10-28 17:19:54 +03:00
entry_scanner_p = ( shm_share_mode_entry * ) shmops - > offset2addr (
1997-10-20 12:46:00 +04:00
file_scanner_p - > share_mode_entries ) ;
entry_prev_p = entry_scanner_p ;
while ( entry_scanner_p )
{
int pid = entry_scanner_p - > e . pid ;
if ( pid & & ! process_exists ( pid ) )
{
/* Delete this share mode entry */
shm_share_mode_entry * delete_entry_p = entry_scanner_p ;
if ( entry_prev_p = = entry_scanner_p )
{
/* We are at start of list */
file_scanner_p - > share_mode_entries = entry_scanner_p - > next_share_mode_entry ;
1997-10-28 17:19:54 +03:00
entry_scanner_p = ( shm_share_mode_entry * ) shmops - > offset2addr (
1997-10-20 12:46:00 +04:00
file_scanner_p - > share_mode_entries ) ;
entry_prev_p = entry_scanner_p ;
}
else
{
entry_prev_p - > next_share_mode_entry = entry_scanner_p - > next_share_mode_entry ;
entry_scanner_p = ( shm_share_mode_entry * )
1997-10-28 17:19:54 +03:00
shmops - > offset2addr ( entry_scanner_p - > next_share_mode_entry ) ;
1997-10-20 12:46:00 +04:00
}
/* Decrement the number of share mode entries on this share mode record */
file_scanner_p - > num_share_mode_entries - = 1 ;
/* PARANOIA TEST */
if ( file_scanner_p - > num_share_mode_entries < 0 )
{
1998-09-05 00:53:58 +04:00
DEBUG ( 0 , ( " PANIC ERROR: get_share_mode: entries=%d dev=%x ino=%.0f \n " ,
file_scanner_p - > num_share_mode_entries , ( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
return 0 ;
}
1997-11-01 10:33:55 +03:00
DEBUG ( 0 , ( " get_share_modes: process %d no longer exists \n " , pid ) ) ;
1997-10-20 12:46:00 +04:00
1997-12-04 10:41:48 +03:00
shmops - > shm_free ( shmops - > addr2offset ( delete_entry_p ) ) ;
1997-10-20 12:46:00 +04:00
}
else
{
/* This is a valid share mode entry and the process that
created it still exists . Copy it into the output array .
*/
share_array [ num_entries_copied ] . pid = entry_scanner_p - > e . pid ;
share_array [ num_entries_copied ] . share_mode = entry_scanner_p - > e . share_mode ;
share_array [ num_entries_copied ] . op_port = entry_scanner_p - > e . op_port ;
share_array [ num_entries_copied ] . op_type = entry_scanner_p - > e . op_type ;
memcpy ( & share_array [ num_entries_copied ] . time , & entry_scanner_p - > e . time ,
sizeof ( struct timeval ) ) ;
num_entries_copied + + ;
1997-11-01 10:33:55 +03:00
DEBUG ( 5 , ( " get_share_modes Read share mode 0x%X pid=%d \n " ,
entry_scanner_p - > e . share_mode , entry_scanner_p - > e . pid ) ) ;
1997-10-20 12:46:00 +04:00
entry_prev_p = entry_scanner_p ;
entry_scanner_p = ( shm_share_mode_entry * )
1997-10-28 17:19:54 +03:00
shmops - > offset2addr ( entry_scanner_p - > next_share_mode_entry ) ;
1997-10-20 12:46:00 +04:00
}
}
/* If no valid share mode entries were found then this record shouldn't exist ! */
if ( num_entries_copied = = 0 )
{
1998-09-05 00:53:58 +04:00
DEBUG ( 0 , ( " get_share_modes: file with dev %x inode %.0f empty \n " ,
( unsigned int ) dev , ( double ) inode ) ) ;
1998-09-11 05:24:30 +04:00
1997-10-20 12:46:00 +04:00
if ( * old_shares )
free ( ( char * ) * old_shares ) ;
* old_shares = 0 ;
if ( file_prev_p = = file_scanner_p )
mode_array [ hash_entry ] = file_scanner_p - > next_offset ;
else
file_prev_p - > next_offset = file_scanner_p - > next_offset ;
1997-12-04 10:41:48 +03:00
shmops - > shm_free ( shmops - > addr2offset ( file_scanner_p ) ) ;
1997-10-20 12:46:00 +04:00
}
1998-09-05 00:53:58 +04:00
DEBUG ( 5 , ( " get_share_modes: file with dev %x inode %.0f -> %d entries \n " ,
( unsigned int ) dev , ( double ) inode , num_entries_copied ) ) ;
1997-10-20 12:46:00 +04:00
return ( num_entries_copied ) ;
}
/*******************************************************************
del the share mode of a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-15 11:27:34 +04:00
static void shm_del_share_mode ( int token , files_struct * fsp )
1997-10-20 12:46:00 +04:00
{
1998-09-01 00:20:54 +04:00
SMB_DEV_T dev ;
SMB_INO_T inode ;
1997-10-22 15:15:14 +04:00
int * mode_array ;
1997-10-20 12:46:00 +04:00
unsigned int hash_entry ;
share_mode_record * file_scanner_p ;
share_mode_record * file_prev_p ;
shm_share_mode_entry * entry_scanner_p ;
shm_share_mode_entry * entry_prev_p ;
BOOL found = False ;
int pid = getpid ( ) ;
1998-08-15 11:27:34 +04:00
dev = fsp - > fd_ptr - > dev ;
inode = fsp - > fd_ptr - > inode ;
1997-10-20 12:46:00 +04:00
hash_entry = HASH_ENTRY ( dev , inode ) ;
1997-10-28 17:19:54 +03:00
mode_array = ( int * ) shmops - > offset2addr ( shmops - > get_userdef_off ( ) ) ;
1997-10-20 12:46:00 +04:00
1997-11-01 10:33:55 +03:00
if ( mode_array [ hash_entry ] = = 0 )
1997-10-20 12:46:00 +04:00
{
1997-11-01 10:33:55 +03:00
DEBUG ( 0 , ( " PANIC ERROR:del_share_mode hash bucket %d empty \n " ,
1997-10-20 12:46:00 +04:00
hash_entry ) ) ;
return ;
}
1997-10-28 17:19:54 +03:00
file_scanner_p = ( share_mode_record * ) shmops - > offset2addr ( mode_array [ hash_entry ] ) ;
1997-10-20 12:46:00 +04:00
file_prev_p = file_scanner_p ;
while ( file_scanner_p )
{
if ( ( file_scanner_p - > st_dev = = dev ) & & ( file_scanner_p - > st_ino = = inode ) )
{
found = True ;
break ;
}
else
{
file_prev_p = file_scanner_p ;
file_scanner_p = ( share_mode_record * )
1997-10-28 17:19:54 +03:00
shmops - > offset2addr ( file_scanner_p - > next_offset ) ;
1997-10-20 12:46:00 +04:00
}
}
if ( ! found )
{
1998-09-05 00:53:58 +04:00
DEBUG ( 0 , ( " ERROR: del_share_mode no entry for dev %x inode %.0f \n " ,
( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
return ;
}
if ( file_scanner_p - > locking_version ! = LOCKING_VERSION )
{
1998-09-05 00:53:58 +04:00
DEBUG ( 0 , ( " ERROR: del_share_modes Deleting old share mode v1 %d dev=%x ino=%.0f \n " ,
file_scanner_p - > locking_version , ( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
if ( file_prev_p = = file_scanner_p )
mode_array [ hash_entry ] = file_scanner_p - > next_offset ;
else
file_prev_p - > next_offset = file_scanner_p - > next_offset ;
1997-12-04 10:41:48 +03:00
shmops - > shm_free ( shmops - > addr2offset ( file_scanner_p ) ) ;
1997-10-20 12:46:00 +04:00
return ;
}
found = False ;
1997-10-28 17:19:54 +03:00
entry_scanner_p = ( shm_share_mode_entry * ) shmops - > offset2addr (
1997-10-20 12:46:00 +04:00
file_scanner_p - > share_mode_entries ) ;
entry_prev_p = entry_scanner_p ;
while ( entry_scanner_p )
{
if ( ( pid = = entry_scanner_p - > e . pid ) & &
( memcmp ( & entry_scanner_p - > e . time ,
1998-08-15 11:27:34 +04:00
& fsp - > open_time , sizeof ( struct timeval ) ) = = 0 ) )
1997-10-20 12:46:00 +04:00
{
found = True ;
break ;
}
else
{
entry_prev_p = entry_scanner_p ;
entry_scanner_p = ( shm_share_mode_entry * )
1997-10-28 17:19:54 +03:00
shmops - > offset2addr ( entry_scanner_p - > next_share_mode_entry ) ;
1997-10-20 12:46:00 +04:00
}
}
if ( found )
{
/* Decrement the number of entries in the record. */
file_scanner_p - > num_share_mode_entries - = 1 ;
1998-09-05 00:53:58 +04:00
DEBUG ( 2 , ( " del_share_modes Deleting share mode entry dev=%x ino=%.0f \n " ,
( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
if ( entry_prev_p = = entry_scanner_p )
/* We are at start of list */
file_scanner_p - > share_mode_entries = entry_scanner_p - > next_share_mode_entry ;
else
entry_prev_p - > next_share_mode_entry = entry_scanner_p - > next_share_mode_entry ;
1997-12-04 10:41:48 +03:00
shmops - > shm_free ( shmops - > addr2offset ( entry_scanner_p ) ) ;
1997-10-20 12:46:00 +04:00
/* PARANOIA TEST */
if ( file_scanner_p - > num_share_mode_entries < 0 )
{
1997-11-01 10:33:55 +03:00
DEBUG ( 0 , ( " PANIC ERROR:del_share_mode num_share_mode_entries=%d \n " ,
file_scanner_p - > num_share_mode_entries ) ) ;
1997-10-20 12:46:00 +04:00
return ;
}
/* If we deleted the last share mode entry then remove the share mode record. */
if ( file_scanner_p - > num_share_mode_entries = = 0 )
{
1998-09-05 00:53:58 +04:00
DEBUG ( 2 , ( " del_share_modes num entries = 0, deleting share_mode dev=%x ino=%.0f \n " ,
( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
if ( file_prev_p = = file_scanner_p )
mode_array [ hash_entry ] = file_scanner_p - > next_offset ;
else
file_prev_p - > next_offset = file_scanner_p - > next_offset ;
1997-12-04 10:41:48 +03:00
shmops - > shm_free ( shmops - > addr2offset ( file_scanner_p ) ) ;
1997-10-20 12:46:00 +04:00
}
}
else
{
1998-09-05 00:53:58 +04:00
DEBUG ( 0 , ( " ERROR: del_share_modes No share mode dev=%x ino=%.0f \n " ,
( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
}
}
/*******************************************************************
set the share mode of a file . Return False on fail , True on success .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-15 11:27:34 +04:00
static BOOL shm_set_share_mode ( int token , files_struct * fsp , uint16 port , uint16 op_type )
1997-10-20 12:46:00 +04:00
{
1998-09-01 00:20:54 +04:00
SMB_DEV_T dev ;
SMB_INO_T inode ;
1997-10-22 15:15:14 +04:00
int * mode_array ;
1997-10-20 12:46:00 +04:00
unsigned int hash_entry ;
share_mode_record * file_scanner_p ;
shm_share_mode_entry * new_entry_p ;
1997-10-22 15:15:14 +04:00
int new_entry_offset ;
1997-10-20 12:46:00 +04:00
BOOL found = False ;
1998-08-15 11:27:34 +04:00
dev = fsp - > fd_ptr - > dev ;
inode = fsp - > fd_ptr - > inode ;
1997-10-20 12:46:00 +04:00
hash_entry = HASH_ENTRY ( dev , inode ) ;
1997-10-28 17:19:54 +03:00
mode_array = ( int * ) shmops - > offset2addr ( shmops - > get_userdef_off ( ) ) ;
1997-10-20 12:46:00 +04:00
1997-10-28 17:19:54 +03:00
file_scanner_p = ( share_mode_record * ) shmops - > offset2addr ( mode_array [ hash_entry ] ) ;
1997-10-20 12:46:00 +04:00
while ( file_scanner_p )
{
if ( ( file_scanner_p - > st_dev = = dev ) & & ( file_scanner_p - > st_ino = = inode ) )
{
found = True ;
break ;
}
else
{
file_scanner_p = ( share_mode_record * )
1997-10-28 17:19:54 +03:00
shmops - > offset2addr ( file_scanner_p - > next_offset ) ;
1997-10-20 12:46:00 +04:00
}
}
if ( ! found )
{
/* We must create a share_mode_record */
share_mode_record * new_mode_p = NULL ;
1997-12-04 10:41:48 +03:00
int new_offset = shmops - > shm_alloc ( sizeof ( share_mode_record ) +
1998-08-15 11:27:34 +04:00
strlen ( fsp - > fsp_name ) + 1 ) ;
1997-11-01 10:33:55 +03:00
if ( new_offset = = 0 ) {
1997-12-04 10:41:48 +03:00
DEBUG ( 0 , ( " ERROR:set_share_mode shmops->shm_alloc fail! \n " ) ) ;
1997-11-01 10:33:55 +03:00
return False ;
1997-10-20 12:46:00 +04:00
}
1997-10-28 17:19:54 +03:00
new_mode_p = shmops - > offset2addr ( new_offset ) ;
1997-10-20 12:46:00 +04:00
new_mode_p - > locking_version = LOCKING_VERSION ;
new_mode_p - > st_dev = dev ;
new_mode_p - > st_ino = inode ;
new_mode_p - > num_share_mode_entries = 0 ;
1997-11-01 10:33:55 +03:00
new_mode_p - > share_mode_entries = 0 ;
1998-08-15 11:27:34 +04:00
pstrcpy ( new_mode_p - > file_name , fsp - > fsp_name ) ;
1997-10-20 12:46:00 +04:00
/* Chain onto the start of the hash chain (in the hope we will be used first). */
new_mode_p - > next_offset = mode_array [ hash_entry ] ;
mode_array [ hash_entry ] = new_offset ;
file_scanner_p = new_mode_p ;
1998-09-05 00:53:58 +04:00
DEBUG ( 3 , ( " set_share_mode: Created share record for %s (dev %x inode %.0f) \n " ,
fsp - > fsp_name , ( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
}
/* Now create the share mode entry */
1997-12-04 10:41:48 +03:00
new_entry_offset = shmops - > shm_alloc ( sizeof ( shm_share_mode_entry ) ) ;
1997-11-01 10:33:55 +03:00
if ( new_entry_offset = = 0 ) {
int delete_offset = mode_array [ hash_entry ] ;
1997-12-04 10:41:48 +03:00
DEBUG ( 0 , ( " ERROR:set_share_mode: shmops->shm_alloc fail 1! \n " ) ) ;
1997-11-01 10:33:55 +03:00
/* Unlink the damaged record */
mode_array [ hash_entry ] = file_scanner_p - > next_offset ;
/* And delete it */
1997-12-04 10:41:48 +03:00
shmops - > shm_free ( delete_offset ) ;
1997-11-01 10:33:55 +03:00
return False ;
1997-10-20 12:46:00 +04:00
}
1997-10-28 17:19:54 +03:00
new_entry_p = shmops - > offset2addr ( new_entry_offset ) ;
1997-10-20 12:46:00 +04:00
new_entry_p - > e . pid = getpid ( ) ;
1998-08-15 11:27:34 +04:00
new_entry_p - > e . share_mode = fsp - > share_mode ;
1997-10-20 12:46:00 +04:00
new_entry_p - > e . op_port = port ;
new_entry_p - > e . op_type = op_type ;
1998-08-15 11:27:34 +04:00
memcpy ( ( char * ) & new_entry_p - > e . time , ( char * ) & fsp - > open_time , sizeof ( struct timeval ) ) ;
1997-10-20 12:46:00 +04:00
/* Chain onto the share_mode_record */
new_entry_p - > next_share_mode_entry = file_scanner_p - > share_mode_entries ;
file_scanner_p - > share_mode_entries = new_entry_offset ;
/* PARANOIA TEST */
if ( file_scanner_p - > num_share_mode_entries < 0 )
{
1997-11-01 10:33:55 +03:00
DEBUG ( 0 , ( " PANIC ERROR:set_share_mode num_share_mode_entries=%d \n " ,
file_scanner_p - > num_share_mode_entries ) ) ;
1997-10-20 12:46:00 +04:00
return False ;
}
/* Increment the share_mode_entries counter */
file_scanner_p - > num_share_mode_entries + = 1 ;
1997-11-01 10:33:55 +03:00
DEBUG ( 3 , ( " set_share_mode: Created share entry for %s with mode 0x%X pid=%d \n " ,
1998-08-15 11:27:34 +04:00
fsp - > fsp_name , fsp - > share_mode , new_entry_p - > e . pid ) ) ;
1997-10-20 12:46:00 +04:00
return ( True ) ;
}
/*******************************************************************
Remove an oplock port and mode entry from a share mode .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-15 11:27:34 +04:00
static BOOL shm_remove_share_oplock ( files_struct * fsp , int token )
1997-10-20 12:46:00 +04:00
{
1998-09-01 00:20:54 +04:00
SMB_DEV_T dev ;
SMB_INO_T inode ;
1997-10-22 15:15:14 +04:00
int * mode_array ;
1997-10-20 12:46:00 +04:00
unsigned int hash_entry ;
share_mode_record * file_scanner_p ;
share_mode_record * file_prev_p ;
shm_share_mode_entry * entry_scanner_p ;
BOOL found = False ;
int pid = getpid ( ) ;
1998-08-15 11:27:34 +04:00
dev = fsp - > fd_ptr - > dev ;
inode = fsp - > fd_ptr - > inode ;
1997-10-20 12:46:00 +04:00
hash_entry = HASH_ENTRY ( dev , inode ) ;
1997-10-28 17:19:54 +03:00
mode_array = ( int * ) shmops - > offset2addr ( shmops - > get_userdef_off ( ) ) ;
1997-10-20 12:46:00 +04:00
1997-11-01 10:33:55 +03:00
if ( mode_array [ hash_entry ] = = 0 )
1997-10-20 12:46:00 +04:00
{
1997-11-01 10:33:55 +03:00
DEBUG ( 0 , ( " PANIC ERROR:remove_share_oplock: hash bucket %d empty \n " ,
1997-10-20 12:46:00 +04:00
hash_entry ) ) ;
return False ;
}
1997-10-28 17:19:54 +03:00
file_scanner_p = ( share_mode_record * ) shmops - > offset2addr ( mode_array [ hash_entry ] ) ;
1997-10-20 12:46:00 +04:00
file_prev_p = file_scanner_p ;
while ( file_scanner_p )
{
if ( ( file_scanner_p - > st_dev = = dev ) & & ( file_scanner_p - > st_ino = = inode ) )
{
found = True ;
break ;
}
else
{
file_prev_p = file_scanner_p ;
file_scanner_p = ( share_mode_record * )
1997-10-28 17:19:54 +03:00
shmops - > offset2addr ( file_scanner_p - > next_offset ) ;
1997-10-20 12:46:00 +04:00
}
}
if ( ! found )
{
1998-09-05 00:53:58 +04:00
DEBUG ( 0 , ( " ERROR:remove_share_oplock: no entry found for dev=%x ino=%.0f \n " ,
( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
return False ;
}
if ( file_scanner_p - > locking_version ! = LOCKING_VERSION )
{
1998-09-05 00:53:58 +04:00
DEBUG ( 0 , ( " ERROR: remove_share_oplock: Deleting old share mode v1=%d dev=%x ino=%.0f \n " ,
file_scanner_p - > locking_version , ( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
if ( file_prev_p = = file_scanner_p )
mode_array [ hash_entry ] = file_scanner_p - > next_offset ;
else
file_prev_p - > next_offset = file_scanner_p - > next_offset ;
1997-12-04 10:41:48 +03:00
shmops - > shm_free ( shmops - > addr2offset ( file_scanner_p ) ) ;
1997-10-20 12:46:00 +04:00
return False ;
}
found = False ;
1997-10-28 17:19:54 +03:00
entry_scanner_p = ( shm_share_mode_entry * ) shmops - > offset2addr (
1997-10-20 12:46:00 +04:00
file_scanner_p - > share_mode_entries ) ;
while ( entry_scanner_p )
{
if ( ( pid = = entry_scanner_p - > e . pid ) & &
1998-08-15 11:27:34 +04:00
( entry_scanner_p - > e . share_mode = = fsp - > share_mode ) & &
1997-10-20 12:46:00 +04:00
( memcmp ( & entry_scanner_p - > e . time ,
1998-08-15 11:27:34 +04:00
& fsp - > open_time , sizeof ( struct timeval ) ) = = 0 ) )
1997-10-20 12:46:00 +04:00
{
/* Delete the oplock info. */
entry_scanner_p - > e . op_port = 0 ;
entry_scanner_p - > e . op_type = 0 ;
found = True ;
break ;
}
else
{
entry_scanner_p = ( shm_share_mode_entry * )
1997-10-28 17:19:54 +03:00
shmops - > offset2addr ( entry_scanner_p - > next_share_mode_entry ) ;
1997-10-20 12:46:00 +04:00
}
}
if ( ! found )
{
1998-09-05 00:53:58 +04:00
DEBUG ( 0 , ( " ERROR: remove_share_oplock: No oplock granted. dev=%x ino=%.0f \n " ,
( unsigned int ) dev , ( double ) inode ) ) ;
1997-10-20 12:46:00 +04:00
return False ;
}
return True ;
}
/*******************************************************************
call the specified function on each entry under management by the
1997-10-20 22:52:04 +04:00
share mode system
1997-10-20 12:46:00 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int shm_share_forall ( void ( * fn ) ( share_mode_entry * , char * ) )
{
int i , count = 0 ;
1997-10-22 15:15:14 +04:00
int * mode_array ;
1997-10-20 12:46:00 +04:00
share_mode_record * file_scanner_p ;
1997-10-28 17:19:54 +03:00
mode_array = ( int * ) shmops - > offset2addr ( shmops - > get_userdef_off ( ) ) ;
1997-10-20 12:46:00 +04:00
1997-10-29 04:59:54 +03:00
for ( i = 0 ; i < shmops - > hash_size ( ) ; i + + ) {
1997-10-28 17:19:54 +03:00
shmops - > lock_hash_entry ( i ) ;
1997-11-01 10:33:55 +03:00
if ( mode_array [ i ] = = 0 ) {
1997-10-28 17:19:54 +03:00
shmops - > unlock_hash_entry ( i ) ;
1997-10-20 12:46:00 +04:00
continue ;
}
1997-10-28 17:19:54 +03:00
file_scanner_p = ( share_mode_record * ) shmops - > offset2addr ( mode_array [ i ] ) ;
1997-10-20 12:46:00 +04:00
while ( ( file_scanner_p ! = 0 ) & &
( file_scanner_p - > num_share_mode_entries ! = 0 ) ) {
shm_share_mode_entry * entry_scanner_p =
( shm_share_mode_entry * )
1997-10-28 17:19:54 +03:00
shmops - > offset2addr ( file_scanner_p - > share_mode_entries ) ;
1997-10-20 12:46:00 +04:00
while ( entry_scanner_p ! = 0 ) {
1997-11-29 16:35:09 +03:00
if ( process_exists ( entry_scanner_p - > e . pid ) ) {
fn ( & entry_scanner_p - > e ,
file_scanner_p - > file_name ) ;
count + + ;
}
1997-10-20 12:46:00 +04:00
entry_scanner_p =
( shm_share_mode_entry * )
1997-10-28 17:19:54 +03:00
shmops - > offset2addr (
1997-10-20 12:46:00 +04:00
entry_scanner_p - > next_share_mode_entry ) ;
} /* end while entry_scanner_p */
file_scanner_p = ( share_mode_record * )
1997-10-28 17:19:54 +03:00
shmops - > offset2addr ( file_scanner_p - > next_offset ) ;
1997-10-20 12:46:00 +04:00
} /* end while file_scanner_p */
1997-10-28 17:19:54 +03:00
shmops - > unlock_hash_entry ( i ) ;
1997-10-20 12:46:00 +04:00
} /* end for */
return count ;
}
/*******************************************************************
dump the state of the system
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void shm_share_status ( FILE * f )
{
int bytes_free , bytes_used , bytes_overhead , bytes_total ;
1997-10-28 17:19:54 +03:00
shmops - > get_usage ( & bytes_free , & bytes_used , & bytes_overhead ) ;
1997-10-20 12:46:00 +04:00
bytes_total = bytes_free + bytes_used + bytes_overhead ;
fprintf ( f , " Share mode memory usage (bytes): \n " ) ;
fprintf ( f , " %d(%d%%) free + %d(%d%%) used + %d(%d%%) overhead = %d(100%%) total \n " ,
bytes_free , ( bytes_free * 100 ) / bytes_total ,
bytes_used , ( bytes_used * 100 ) / bytes_total ,
bytes_overhead , ( bytes_overhead * 100 ) / bytes_total ,
bytes_total ) ;
}
static struct share_ops share_ops = {
shm_stop_share_mode_mgmt ,
shm_lock_share_entry ,
shm_unlock_share_entry ,
shm_get_share_modes ,
shm_del_share_mode ,
shm_set_share_mode ,
shm_remove_share_oplock ,
shm_share_forall ,
shm_share_status ,
} ;
/*******************************************************************
initialize the shared memory for share_mode management
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-27 17:27:17 +03:00
struct share_ops * locking_shm_init ( int ronly )
1997-10-20 12:46:00 +04:00
{
1997-10-27 17:27:17 +03:00
read_only = ronly ;
1997-10-28 17:19:54 +03:00
1998-07-29 07:08:05 +04:00
# ifdef HAVE_SYSV_IPC
1997-10-29 04:59:54 +03:00
shmops = sysv_shm_open ( read_only ) ;
1997-10-28 17:19:54 +03:00
if ( shmops ) return & share_ops ;
# endif
1998-07-29 07:08:05 +04:00
# ifdef HAVE_SHARED_MMAP
1997-10-29 04:59:54 +03:00
shmops = smb_shm_open ( read_only ) ;
1997-10-28 17:19:54 +03:00
if ( shmops ) return & share_ops ;
1998-07-29 07:08:05 +04:00
# endif
1997-10-28 17:19:54 +03:00
1997-10-20 12:46:00 +04:00
return NULL ;
}
# else
int locking_shm_dummy_procedure ( void )
{ return 0 ; }
1998-07-29 07:08:05 +04:00
# endif /* FAST_SHARE_MODES */