diff options
Diffstat (limited to 'source3/locking/locking_shm.c')
-rw-r--r-- | source3/locking/locking_shm.c | 739 |
1 files changed, 739 insertions, 0 deletions
diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c new file mode 100644 index 0000000000..99d981ed20 --- /dev/null +++ b/source3/locking/locking_shm.c @@ -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 + + + |