1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

a major share modes reorganisation.

The shares modes code is now split into separate files. The shared
memory implementation is in locking_shm.c. The slow implementation is
in locking_slow.c

It is all controlled by a struct share_ops structure that has function
pointers to the implementation of all the functions needed by a share
modes implementation. An initialisation function sets up this
structure. This will make adding new implementations easy and clean.

This also allowed me to get rid of the ugly code in smbstatus. Now
status.c links to the locking code and calls methods in share_ops.

I also renamed some things and generally organised things in a much
cleaner fashion. Defines and structures specific to each
implementation have been moved to the appropriate file and out of
smb.h.
(This used to be commit 65ab9adaa0)
This commit is contained in:
Andrew Tridgell 1997-10-20 08:46:00 +00:00
parent f4b4b3e6e3
commit 3e670e4057
8 changed files with 1929 additions and 1762 deletions

View File

@ -305,22 +305,25 @@ int lp_minor_announce_version(void);
BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset);
BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode);
BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode);
BOOL start_share_mode_mgmt(void);
BOOL stop_share_mode_mgmt(void);
BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok);
BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token);
int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
min_share_mode_entry **old_shares);
void del_share_mode(share_lock_token token, int fnum);
BOOL set_share_mode(share_lock_token token, int fnum, uint16 port, uint16 op_type);
BOOL remove_share_oplock(int fnum, share_lock_token token);
BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok);
BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token);
int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
min_share_mode_entry **old_shares);
void del_share_mode(share_lock_token token, int fnum);
BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type);
BOOL remove_share_oplock(int fnum, share_lock_token token);
BOOL locking_init(void);
BOOL locking_end(void);
BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok);
BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token);
int get_share_modes(int cnum, int token, uint32 dev, uint32 inode,
share_mode_entry **shares);
void del_share_mode(int token, int fnum);
BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type);
BOOL remove_share_oplock(int fnum, int token);
int share_mode_forall(void (*fn)(share_mode_entry *, char *));
void share_status(FILE *f);
/*The following definitions come from locking_shm.c */
struct share_ops *locking_shm_init(void);
/*The following definitions come from locking_slow.c */
struct share_ops *locking_slow_init(void);
/*The following definitions come from lsaparse.c */
@ -778,7 +781,7 @@ BOOL check_name(char *name,int cnum);
void sync_file(int fnum);
void close_file(int fnum, BOOL normal_close);
BOOL check_file_sharing(int cnum,char *fname);
int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname,
int check_share_mode( share_mode_entry *share, int deny_mode, char *fname,
BOOL fcbopen, int *flags);
void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
int mode,int oplock_request, int *Access,int *action);
@ -791,7 +794,7 @@ int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line);
int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line);
int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line);
BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval);
BOOL request_oplock_break(min_share_mode_entry *share_entry,
BOOL request_oplock_break(share_mode_entry *share_entry,
uint32 dev, uint32 inode);
BOOL snum_used(int snum);
BOOL reload_services(BOOL test);

View File

@ -1195,29 +1195,6 @@ struct interface
struct in_addr nmask;
};
/* share mode record pointed to in shared memory hash bucket */
typedef struct
{
smb_shm_offset_t next_offset; /* offset of next record in chain from hash bucket */
int locking_version;
int32 st_dev;
int32 st_ino;
int num_share_mode_entries;
smb_shm_offset_t share_mode_entries; /* Chain of share mode entries for this file */
char file_name[1];
} share_mode_record;
/* share mode entry pointed to by share_mode_record struct */
typedef struct
{
smb_shm_offset_t next_share_mode_entry;
int pid;
uint16 op_port;
uint16 op_type;
int share_mode;
struct timeval time;
} share_mode_entry;
/* struct returned by get_share_modes */
typedef struct
{
@ -1226,14 +1203,26 @@ typedef struct
uint16 op_type;
int share_mode;
struct timeval time;
} min_share_mode_entry;
} share_mode_entry;
/* Token returned by lock_share_entry (actually ignored by FAST_SHARE_MODES code) */
typedef int share_lock_token;
/* Conversion to hash entry index from device and inode numbers. */
#define HASH_ENTRY(dev,ino) ((( (uint32)(dev) )* ( (uint32)(ino) )) % lp_shmem_hash_size())
/* each implementation of the share mode code needs
to support the following operations */
struct share_ops {
BOOL (*stop_mgmt)(void);
BOOL (*lock_entry)(int , uint32 , uint32 , int *);
BOOL (*unlock_entry)(int , uint32 , uint32 , int );
BOOL (*get_entries)(int , int , uint32 , uint32 , share_mode_entry **);
void (*del_entry)(int , int );
BOOL (*set_entry)(int , int , uint16 , uint16 );
BOOL (*remove_oplock)(int , int);
int (*forall)(void (*)(share_mode_entry *, char *));
void (*status)(FILE *);
};
/* this is used for smbstatus */
struct connect_record
{
@ -1252,34 +1241,6 @@ struct connect_record
#define LOCKING_VERSION 4
#endif /* LOCKING_VERSION */
#if !defined(FAST_SHARE_MODES)
/*
* Defines for slow share modes.
*/
/*
* Locking file header lengths & offsets.
*/
#define SMF_VERSION_OFFSET 0
#define SMF_NUM_ENTRIES_OFFSET 4
#define SMF_FILENAME_LEN_OFFSET 8
#define SMF_HEADER_LENGTH 10
#define SMF_ENTRY_LENGTH 20
/*
* Share mode record offsets.
*/
#define SME_SEC_OFFSET 0
#define SME_USEC_OFFSET 4
#define SME_SHAREMODE_OFFSET 8
#define SME_PID_OFFSET 12
#define SME_PORT_OFFSET 16
#define SME_OPLOCK_TYPE_OFFSET 18
#endif /* FAST_SHARE_MODES */
/* these are useful macros for checking validity of handles */
#define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < MAX_OPEN_FILES))
#define OPEN_FNUM(fnum) (VALID_FNUM(fnum) && Files[fnum].open)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,739 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
shared memory locking implementation
Copyright (C) Andrew Tridgell 1992-1997
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 02139, 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)
*/
#ifdef FAST_SHARE_MODES
#include "includes.h"
extern int DEBUGLEVEL;
extern connection_struct Connections[];
extern files_struct Files[];
/* share mode record pointed to in shared memory hash bucket */
typedef struct
{
smb_shm_offset_t next_offset; /* offset of next record in chain from hash bucket */
int locking_version;
int32 st_dev;
int32 st_ino;
int num_share_mode_entries;
smb_shm_offset_t share_mode_entries; /* Chain of share mode entries for this file */
char file_name[1];
} share_mode_record;
/* share mode entry pointed to by share_mode_record struct */
typedef struct
{
smb_shm_offset_t next_share_mode_entry;
share_mode_entry e;
} shm_share_mode_entry;
/*******************************************************************
deinitialize the shared memory for share_mode management
******************************************************************/
static BOOL shm_stop_share_mode_mgmt(void)
{
return smb_shm_close();
}
/*******************************************************************
lock a hash bucket entry in shared memory for share_mode management
******************************************************************/
static BOOL shm_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok)
{
return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode));
}
/*******************************************************************
unlock a hash bucket entry in shared memory for share_mode management
******************************************************************/
static BOOL shm_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token)
{
return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode));
}
/*******************************************************************
get all share mode entries in shared memory for a dev/inode pair.
********************************************************************/
static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode,
share_mode_entry **old_shares)
{
smb_shm_offset_t *mode_array;
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;
if(hash_entry > lp_shmem_hash_size() )
{
DEBUG(0,
("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \
(max = %d)\n",
hash_entry, lp_shmem_hash_size() ));
return 0;
}
mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
if(mode_array[hash_entry] == NULL_OFFSET)
{
DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry));
return 0;
}
file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
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 *)smb_shm_offset2addr(
file_scanner_p->next_offset);
}
}
if(!found)
{
DEBUG(5,("get_share_modes (FAST_SHARE_MODES): no entry for \
file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry));
return (0);
}
if(file_scanner_p->locking_version != LOCKING_VERSION)
{
DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \
record due to old locking version %d for file dev = %d, inode = %d in hash \
bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry));
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;
smb_shm_free(smb_shm_addr2offset(file_scanner_p));
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)
{
DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n"));
return 0;
}
}
num_entries_copied = 0;
entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr(
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;
int share_mode = entry_scanner_p->e.share_mode;
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;
entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr(
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*)
smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
}
/* 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)
{
DEBUG(0,("PANIC ERROR:get_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
dev, inode, hash_entry));
return 0;
}
DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \
it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \
bucket %d (number of entries now = %d)\n",
pid, share_mode, dev, inode, hash_entry,
file_scanner_p->num_share_mode_entries));
smb_shm_free(smb_shm_addr2offset(delete_entry_p));
}
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++;
DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \
record mode 0x%X pid=%d\n", entry_scanner_p->e.share_mode, entry_scanner_p->e.pid));
entry_prev_p = entry_scanner_p;
entry_scanner_p = (shm_share_mode_entry *)
smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
}
}
/* If no valid share mode entries were found then this record shouldn't exist ! */
if(num_entries_copied == 0)
{
DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
hash bucket %d has a share mode record but no entries - deleting\n",
dev, inode, hash_entry));
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;
smb_shm_free(smb_shm_addr2offset(file_scanner_p));
}
DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
hash bucket %d returning %d entries\n", dev, inode, hash_entry, num_entries_copied));
return(num_entries_copied);
}
/*******************************************************************
del the share mode of a file.
********************************************************************/
static void shm_del_share_mode(int token, int fnum)
{
uint32 dev, inode;
smb_shm_offset_t *mode_array;
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();
dev = Files[fnum].fd_ptr->dev;
inode = Files[fnum].fd_ptr->inode;
hash_entry = HASH_ENTRY(dev, inode);
if(hash_entry > lp_shmem_hash_size() )
{
DEBUG(0,
("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
(max = %d)\n",
hash_entry, lp_shmem_hash_size() ));
return;
}
mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
if(mode_array[hash_entry] == NULL_OFFSET)
{
DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n",
hash_entry));
return;
}
file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
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 *)
smb_shm_offset2addr(file_scanner_p->next_offset);
}
}
if(!found)
{
DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \
inode %d in hash bucket %d\n", dev, inode, hash_entry));
return;
}
if(file_scanner_p->locking_version != LOCKING_VERSION)
{
DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \
record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
file_scanner_p->locking_version, dev, inode, hash_entry ));
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;
smb_shm_free(smb_shm_addr2offset(file_scanner_p));
return;
}
found = False;
entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr(
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,
&Files[fnum].open_time,sizeof(struct timeval)) == 0) )
{
found = True;
break;
}
else
{
entry_prev_p = entry_scanner_p;
entry_scanner_p = (shm_share_mode_entry *)
smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
}
}
if (found)
{
/* Decrement the number of entries in the record. */
file_scanner_p->num_share_mode_entries -= 1;
DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \
Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n",
dev, inode, hash_entry, file_scanner_p->num_share_mode_entries));
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;
smb_shm_free(smb_shm_addr2offset(entry_scanner_p));
/* PARANOIA TEST */
if(file_scanner_p->num_share_mode_entries < 0)
{
DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
dev, inode, hash_entry));
return;
}
/* If we deleted the last share mode entry then remove the share mode record. */
if(file_scanner_p->num_share_mode_entries == 0)
{
DEBUG(2,("del_share_modes (FAST_SHARE_MODES): num entries = 0, deleting share_mode \
record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
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;
smb_shm_free(smb_shm_addr2offset(file_scanner_p));
}
}
else
{
DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \
dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
}
}
/*******************************************************************
set the share mode of a file. Return False on fail, True on success.
********************************************************************/
static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type)
{
files_struct *fs_p = &Files[fnum];
int32 dev, inode;
smb_shm_offset_t *mode_array;
unsigned int hash_entry;
share_mode_record *file_scanner_p;
share_mode_record *file_prev_p;
shm_share_mode_entry *new_entry_p;
smb_shm_offset_t new_entry_offset;
BOOL found = False;
dev = fs_p->fd_ptr->dev;
inode = fs_p->fd_ptr->inode;
hash_entry = HASH_ENTRY(dev, inode);
if(hash_entry > lp_shmem_hash_size() )
{
DEBUG(0,
("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
(max = %d)\n",
hash_entry, lp_shmem_hash_size() ));
return False;
}
mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
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 *)
smb_shm_offset2addr(file_scanner_p->next_offset);
}
}
if(!found)
{
/* We must create a share_mode_record */
share_mode_record *new_mode_p = NULL;
smb_shm_offset_t new_offset = smb_shm_alloc( sizeof(share_mode_record) +
strlen(fs_p->name) + 1);
if(new_offset == NULL_OFFSET)
{
DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n"));
return False;
}
new_mode_p = smb_shm_offset2addr(new_offset);
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;
new_mode_p->share_mode_entries = NULL_OFFSET;
strcpy(new_mode_p->file_name, fs_p->name);
/* 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;
DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share record for %s (dev %d \
inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry));
}
/* Now create the share mode entry */
new_entry_offset = smb_shm_alloc( sizeof(shm_share_mode_entry));
if(new_entry_offset == NULL_OFFSET)
{
smb_shm_offset_t delete_offset = mode_array[hash_entry];
DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n"));
/* Unlink the damaged record */
mode_array[hash_entry] = file_scanner_p->next_offset;
/* And delete it */
smb_shm_free( delete_offset );
return False;
}
new_entry_p = smb_shm_offset2addr(new_entry_offset);
new_entry_p->e.pid = getpid();
new_entry_p->e.share_mode = fs_p->share_mode;
new_entry_p->e.op_port = port;
new_entry_p->e.op_type = op_type;
memcpy( (char *)&new_entry_p->e.time, (char *)&fs_p->open_time, sizeof(struct timeval));
/* 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)
{
DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
dev, inode, hash_entry));
return False;
}
/* Increment the share_mode_entries counter */
file_scanner_p->num_share_mode_entries += 1;
DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \
0x%X pid=%d (num_entries now = %d)\n",fs_p->name, fs_p->share_mode, new_entry_p->e.pid,
file_scanner_p->num_share_mode_entries));
return(True);
}
/*******************************************************************
Remove an oplock port and mode entry from a share mode.
********************************************************************/
static BOOL shm_remove_share_oplock(int fnum, int token)
{
uint32 dev, inode;
smb_shm_offset_t *mode_array;
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();
dev = Files[fnum].fd_ptr->dev;
inode = Files[fnum].fd_ptr->inode;
hash_entry = HASH_ENTRY(dev, inode);
if(hash_entry > lp_shmem_hash_size() )
{
DEBUG(0,
("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash_entry %d too large \
(max = %d)\n",
hash_entry, lp_shmem_hash_size() ));
return False;
}
mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
if(mode_array[hash_entry] == NULL_OFFSET)
{
DEBUG(0,("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash bucket %d empty\n",
hash_entry));
return False;
}
file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
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 *)
smb_shm_offset2addr(file_scanner_p->next_offset);
}
}
if(!found)
{
DEBUG(0,("ERROR:remove_share_oplock (FAST_SHARE_MODES): no entry found for dev %d, \
inode %d in hash bucket %d\n", dev, inode, hash_entry));
return False;
}
if(file_scanner_p->locking_version != LOCKING_VERSION)
{
DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): Deleting old share mode \
record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
file_scanner_p->locking_version, dev, inode, hash_entry ));
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;
smb_shm_free(smb_shm_addr2offset(file_scanner_p));
return False;
}
found = False;
entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr(
file_scanner_p->share_mode_entries);
entry_prev_p = entry_scanner_p;
while(entry_scanner_p)
{
if( (pid == entry_scanner_p->e.pid) &&
(entry_scanner_p->e.share_mode == Files[fnum].share_mode) &&
(memcmp(&entry_scanner_p->e.time,
&Files[fnum].open_time,sizeof(struct timeval)) == 0) )
{
/* Delete the oplock info. */
entry_scanner_p->e.op_port = 0;
entry_scanner_p->e.op_type = 0;
found = True;
break;
}
else
{
entry_prev_p = entry_scanner_p;
entry_scanner_p = (shm_share_mode_entry *)
smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
}
}
if(!found)
{
DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): No oplock granted share \
mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
return False;
}
return True;
}
/*******************************************************************
call the specified function on each entry under management by the
share ode system
********************************************************************/
static int shm_share_forall(void (*fn)(share_mode_entry *, char *))
{
int i, count=0;
smb_shm_offset_t *mode_array;
share_mode_record *file_scanner_p;
mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
for( i = 0; i < lp_shmem_hash_size(); i++) {
smb_shm_lock_hash_entry(i);
if(mode_array[i] == NULL_OFFSET) {
smb_shm_unlock_hash_entry(i);
continue;
}
file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[i]);
while((file_scanner_p != 0) &&
(file_scanner_p->num_share_mode_entries != 0)) {
shm_share_mode_entry *entry_scanner_p =
(shm_share_mode_entry *)
smb_shm_offset2addr(file_scanner_p->share_mode_entries);
while(entry_scanner_p != 0) {
fn(&entry_scanner_p->e,
file_scanner_p->file_name);
entry_scanner_p =
(shm_share_mode_entry *)
smb_shm_offset2addr(
entry_scanner_p->next_share_mode_entry);
count++;
} /* end while entry_scanner_p */
file_scanner_p = (share_mode_record *)
smb_shm_offset2addr(file_scanner_p->next_offset);
} /* end while file_scanner_p */
smb_shm_unlock_hash_entry(i);
} /* 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;
smb_shm_get_usage(&bytes_free, &bytes_used, &bytes_overhead);
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
******************************************************************/
struct share_ops *locking_shm_init(void)
{
pstring shmem_file_name;
pstrcpy(shmem_file_name,lp_lockdir());
if (!directory_exist(shmem_file_name,NULL))
mkdir(shmem_file_name,0755);
trim_string(shmem_file_name,"","/");
if (!*shmem_file_name) return(False);
strcat(shmem_file_name, "/SHARE_MEM_FILE");
if (smb_shm_open(shmem_file_name, lp_shmem_size()))
return &share_ops;
return NULL;
}
#else
int locking_shm_dummy_procedure(void)
{return 0;}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -3422,7 +3422,7 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
(num_ulocks == 0) && (num_locks == 0) &&
(CVAL(inbuf,smb_vwv0) == 0xFF))
{
share_lock_token token;
int token;
files_struct *fsp = &Files[fnum];
uint32 dev = fsp->fd_ptr->dev;
uint32 inode = fsp->fd_ptr->inode;

View File

@ -1373,7 +1373,7 @@ void close_file(int fnum, BOOL normal_close)
int cnum = fs_p->cnum;
uint32 dev = fs_p->fd_ptr->dev;
uint32 inode = fs_p->fd_ptr->inode;
share_lock_token token;
int token;
invalidate_read_prediction(fs_p->fd_ptr->fd);
fs_p->open = False;
@ -1477,10 +1477,10 @@ BOOL check_file_sharing(int cnum,char *fname)
{
int i;
int ret = False;
min_share_mode_entry *old_shares = 0;
share_mode_entry *old_shares = 0;
int num_share_modes;
struct stat sbuf;
share_lock_token token;
int token;
int pid = getpid();
uint32 dev, inode;
@ -1509,7 +1509,7 @@ BOOL check_file_sharing(int cnum,char *fname)
broke_oplock = False;
for(i = 0; i < num_share_modes; i++)
{
min_share_mode_entry *share_entry = &old_shares[i];
share_mode_entry *share_entry = &old_shares[i];
/*
* Break oplocks before checking share modes. See comment in
@ -1571,8 +1571,8 @@ free_and_exit:
Helper for open_file_shared.
Truncate a file after checking locking; close file if locked.
**************************************************************************/
static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
BOOL *share_locked)
static void truncate_unless_locked(int fnum, int cnum, int token,
BOOL *share_locked)
{
if (Files[fnum].can_write){
if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
@ -1596,7 +1596,7 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
/****************************************************************************
check if we can open a file with a share mode
****************************************************************************/
int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname,
int check_share_mode( share_mode_entry *share, int deny_mode, char *fname,
BOOL fcbopen, int *flags)
{
int old_open_mode = share->share_mode &0xF;
@ -1648,7 +1648,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
BOOL file_existed = file_exist(fname,&sbuf);
BOOL share_locked = False;
BOOL fcbopen = False;
share_lock_token token;
int token;
uint32 dev = 0;
uint32 inode = 0;
int num_share_modes = 0;
@ -1724,7 +1724,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
if (lp_share_modes(SNUM(cnum)))
{
int i;
min_share_mode_entry *old_shares = 0;
share_mode_entry *old_shares = 0;
if (file_existed)
{
@ -1749,7 +1749,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
broke_oplock = False;
for(i = 0; i < num_share_modes; i++)
{
min_share_mode_entry *share_entry = &old_shares[i];
share_mode_entry *share_entry = &old_shares[i];
/*
* By observation of NetBench, oplocks are broken *before* share
@ -2794,7 +2794,7 @@ Send an oplock break message to another smbd process. If the oplock is held
by the local smbd then call the oplock break function directly.
****************************************************************************/
BOOL request_oplock_break(min_share_mode_entry *share_entry,
BOOL request_oplock_break(share_mode_entry *share_entry,
uint32 dev, uint32 inode)
{
char op_break_msg[OPLOCK_BREAK_MSG_LEN];
@ -4177,9 +4177,7 @@ void exit_server(char *reason)
#endif
}
#ifdef FAST_SHARE_MODES
stop_share_mode_mgmt();
#endif /* FAST_SHARE_MODES */
locking_end();
DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
exit(0);
@ -5012,10 +5010,8 @@ static void usage(char *pname)
if (!open_sockets(is_daemon,port))
exit(1);
#ifdef FAST_SHARE_MODES
if (!start_share_mode_mgmt())
if (!locking_init())
exit(1);
#endif /* FAST_SHARE_MODES */
/* possibly reload the services file. */
reload_services(True);

View File

@ -53,80 +53,52 @@ int Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */
int Ucrit_MaxPid=0; /* added by OH */
unsigned int Ucrit_IsActive = 0; /* added by OH */
#ifndef FAST_SHARE_MODES
static char *read_share_file(int fd, char *fname, char *progname)
/* we need these because we link to locking*.o */
void become_root(BOOL save_dir) {}
void unbecome_root(BOOL restore_dir) {}
connection_struct Connections[MAX_CONNECTIONS];
files_struct Files[MAX_OPEN_FILES];
static void print_share_mode(share_mode_entry *e, char *fname)
{
struct stat sb;
char *buf;
int size;
static int count;
if (count==0) {
printf("Locked files:\n");
printf("Pid DenyMode R/W Oplock Name\n");
printf("--------------------------------------------------\n");
}
count++;
if(fstat(fd, &sb) != 0)
{
printf("%s: ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
progname, fname, strerror(errno));
return 0;
}
printf("%-5d ",e->pid);
switch ((e->share_mode>>4)&0xF) {
case DENY_NONE: printf("DENY_NONE "); break;
case DENY_ALL: printf("DENY_ALL "); break;
case DENY_DOS: printf("DENY_DOS "); break;
case DENY_READ: printf("DENY_READ "); break;
case DENY_WRITE:printf("DENY_WRITE "); break;
}
switch (e->share_mode&0xF) {
case 0: printf("RDONLY "); break;
case 1: printf("WRONLY "); break;
case 2: printf("RDWR "); break;
}
if(sb.st_size == 0)
{
return 0;
}
if((e->op_type &
(EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) ==
(EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
printf("EXCLUSIVE+BATCH ");
else if (e->op_type & EXCLUSIVE_OPLOCK)
printf("EXCLUSIVE ");
else if (e->op_type & BATCH_OPLOCK)
printf("BATCH ");
else
printf("NONE ");
/* Allocate space for the file */
if((buf = (char *)malloc(sb.st_size)) == NULL)
{
printf("%s: read_share_file: malloc for file size %d fail !\n",
progname, (int)sb.st_size);
return 0;
}
if(lseek(fd, 0, SEEK_SET) != 0)
{
printf("%s: ERROR: read_share_file: Failed to reset position to 0 \
for share file %s (%s)\n", progname, fname, strerror(errno));
if(buf)
free(buf);
return 0;
}
if (read(fd,buf,sb.st_size) != sb.st_size)
{
printf("%s: ERROR: read_share_file: Failed to read share file %s (%s)\n",
progname, fname, strerror(errno));
if(buf)
free(buf);
return 0;
}
if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) {
printf("%s: ERROR: read_share_file: share file %s has incorrect \
locking version (was %d, should be %d).\n",fname,
progname, IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION);
if(buf)
free(buf);
return 0;
}
/* Sanity check for file contents */
size = sb.st_size;
size -= SMF_HEADER_LENGTH; /* Remove the header */
/* Remove the filename component. */
size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
/* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
if((size % SMF_ENTRY_LENGTH) != 0)
{
printf("%s: ERROR: read_share_file: share file %s is an incorrect length.\n",
progname, fname);
if(buf)
free(buf);
return 0;
}
return buf;
printf(" %s %s",fname,asctime(LocalTime((time_t *)&e->time.tv_sec)));
}
#endif /* FAST_SHARE_MODES */
int main(int argc, char *argv[])
{
@ -136,20 +108,8 @@ locking version (was %d, should be %d).\n",fname,
static pstring servicesf = CONFIGFILE;
extern char *optarg;
int verbose = 0, brief =0;
BOOL firstopen=True;
BOOL processes_only=False;
int last_pid=0;
#ifdef FAST_SHARE_MODES
pstring shmem_file_name;
share_mode_record *file_scanner_p;
smb_shm_offset_t *mode_array;
int bytes_free, bytes_used, bytes_overhead, bytes_total;
#else /* FAST_SHARE_MODES */
void *dir;
char *s;
#endif /* FAST_SHARE_MODES */
int oplock_type;
int i;
struct session_record *ptr;
@ -302,191 +262,16 @@ locking version (was %d, should be %d).\n",fname,
printf("\n");
#ifdef FAST_SHARE_MODES
/*******************************************************************
initialize the shared memory for share_mode management
******************************************************************/
strcpy(shmem_file_name,lp_lockdir());
trim_string(shmem_file_name,"","/");
if (!*shmem_file_name) exit(-1);
strcat(shmem_file_name, "/SHARE_MEM_FILE");
if(!smb_shm_open(shmem_file_name, lp_shmem_size())) exit(-1);
mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
if(mode_array == NULL)
{
printf("%s: base of shared memory hash array == 0! Exiting.\n", argv[0]);
smb_shm_close();
exit(-1);
}
locking_init();
for( i = 0; i < lp_shmem_hash_size(); i++)
{
smb_shm_lock_hash_entry(i);
if(mode_array[i] == NULL_OFFSET)
{
smb_shm_unlock_hash_entry(i);
continue;
}
file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[i]);
while((file_scanner_p != 0) && (file_scanner_p->num_share_mode_entries != 0))
{
share_mode_entry *entry_scanner_p =
(share_mode_entry *)smb_shm_offset2addr(
file_scanner_p->share_mode_entries);
while(entry_scanner_p != 0)
{
struct timeval t;
int pid = entry_scanner_p->pid;
int mode = entry_scanner_p->share_mode;
t.tv_sec = entry_scanner_p->time.tv_sec;
t.tv_usec = entry_scanner_p->time.tv_usec;
strcpy(fname, file_scanner_p->file_name);
oplock_type = entry_scanner_p->op_type;
#else /* FAST_SHARE_MODES */
/* For slow share modes go through all the files in
the share mode directory and read the entries in
each.
*/
dir = opendir(lp_lockdir());
if (!dir)
{
printf("%s: Unable to open lock directory %s.\n", argv[0], lp_lockdir());
return(0);
}
while ((s=readdirname(dir))) {
char *buf;
char *base;
int fd;
pstring lname;
uint32 dev,inode;
if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue;
strcpy(lname,lp_lockdir());
trim_string(lname,NULL,"/");
strcat(lname,"/");
strcat(lname,s);
fd = open(lname,O_RDWR,0);
if (fd < 0)
{
printf("%s: Unable to open share file %s.\n", argv[0], lname);
continue;
}
/* Lock the share mode file while we read it. */
if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
{
printf("%s: Unable to lock open share file %s.\n", argv[0], lname);
close(fd);
continue;
}
if(( buf = read_share_file( fd, lname, argv[0] )) == NULL)
{
close(fd);
continue;
}
strcpy( fname, &buf[10]);
close(fd);
base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++)
{
char *p = base + (i*SMF_ENTRY_LENGTH);
struct timeval t;
int pid = IVAL(p,SME_PID_OFFSET);
int mode = IVAL(p,SME_SHAREMODE_OFFSET);
t.tv_sec = IVAL(p,SME_SEC_OFFSET);
t.tv_usec = IVAL(p,SME_USEC_OFFSET);
oplock_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
#endif /* FAST_SHARE_MODES */
fname[sizeof(fname)-1] = 0;
if (firstopen) {
firstopen=False;
printf("Locked files:\n");
printf("Pid DenyMode R/W Oplock Name\n");
printf("--------------------------------------------------\n");
}
printf("%-5d ",pid);
switch ((mode>>4)&0xF)
{
case DENY_NONE: printf("DENY_NONE "); break;
case DENY_ALL: printf("DENY_ALL "); break;
case DENY_DOS: printf("DENY_DOS "); break;
case DENY_READ: printf("DENY_READ "); break;
case DENY_WRITE:printf("DENY_WRITE "); break;
}
switch (mode&0xF)
{
case 0: printf("RDONLY "); break;
case 1: printf("WRONLY "); break;
case 2: printf("RDWR "); break;
}
if((oplock_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
printf("EXCLUSIVE+BATCH ");
else if (oplock_type & EXCLUSIVE_OPLOCK)
printf("EXCLUSIVE ");
else if (oplock_type & BATCH_OPLOCK)
printf("BATCH ");
else
printf("NONE ");
printf(" %s %s",fname,asctime(LocalTime((time_t *)&t.tv_sec)));
#ifdef FAST_SHARE_MODES
entry_scanner_p = (share_mode_entry *)smb_shm_offset2addr(
entry_scanner_p->next_share_mode_entry);
} /* end while entry_scanner_p */
file_scanner_p = (share_mode_record *)smb_shm_offset2addr(
file_scanner_p->next_offset);
} /* end while file_scanner_p */
smb_shm_unlock_hash_entry(i);
} /* end for */
smb_shm_get_usage(&bytes_free, &bytes_used, &bytes_overhead);
bytes_total = bytes_free + bytes_used + bytes_overhead;
/*******************************************************************
deinitialize the shared memory for share_mode management
******************************************************************/
smb_shm_close();
#else /* FAST_SHARE_MODES */
} /* end for i */
if(buf)
free(buf);
base = 0;
} /* end while */
closedir(dir);
#endif /* FAST_SHARE_MODES */
if (firstopen)
if (share_mode_forall(print_share_mode) <= 0)
printf("No locked files\n");
#ifdef FAST_SHARE_MODES
printf("\nShare mode memory usage (bytes):\n");
printf(" %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);
#endif /* FAST_SHARE_MODES */
printf("\n");
share_status(stdout);
locking_end();
return (0);
}