From 0e8fd3398771da2f016d72830179507f3edda51b Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sat, 4 May 1996 07:50:46 +0000 Subject: Initial version imported to CVS (This used to be commit 291551d80711daab7b7581720bcd9a08d6096517) --- source3/locking/locking.c | 330 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 source3/locking/locking.c (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c new file mode 100644 index 0000000000..6ff3ab5d12 --- /dev/null +++ b/source3/locking/locking.c @@ -0,0 +1,330 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Locking functions + Copyright (C) Andrew Tridgell 1992-1995 + + 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. +*/ + +#include "includes.h" +#include "loadparm.h" +extern int DEBUGLEVEL; +extern connection_struct Connections[]; +extern files_struct Files[]; + +pstring share_del_pending=""; + + +/**************************************************************************** + utility function called to see if a file region is locked +****************************************************************************/ +BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset) +{ + int snum = SNUM(cnum); + + if (count == 0) + return(False); + + if (!lp_locking(snum) || !lp_strict_locking(snum)) + return(False); + + return(fcntl_lock(Files[fnum].fd,F_GETLK,offset,count, + (Files[fnum].can_write?F_WRLCK:F_RDLCK))); +} + + +/**************************************************************************** + utility function called by locking requests +****************************************************************************/ +BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode) +{ + BOOL ok = False; + + if (!lp_locking(SNUM(cnum))) + return(True); + + if (count == 0) { + *eclass = ERRDOS; + *ecode = ERRnoaccess; + return False; + } + + if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum)) + ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count, + (Files[fnum].can_write?F_WRLCK:F_RDLCK)); + + if (!ok) { + *eclass = ERRDOS; + *ecode = ERRlock; + return False; + } + return True; /* Got lock */ +} + + +/**************************************************************************** + utility function called by unlocking requests +****************************************************************************/ +BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode) +{ + BOOL ok = False; + + if (!lp_locking(SNUM(cnum))) + return(True); + + if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum)) + ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count,F_UNLCK); + + if (!ok) { + *eclass = ERRDOS; + *ecode = ERRlock; + return False; + } + return True; /* Did unlock */ +} + +/******************************************************************* + name a share file + ******************************************************************/ +static BOOL share_name(int cnum,struct stat *st,char *name) +{ + strcpy(name,lp_lockdir()); + standard_sub(cnum,name); + trim_string(name,"","/"); + if (!*name) return(False); + name += strlen(name); + + sprintf(name,"/share.%d.%d",(int)st->st_dev,(int)st->st_ino); + return(True); +} + +/******************************************************************* + use the fnum to get the share file name + ******************************************************************/ +static BOOL share_name_fnum(int fnum,char *name) +{ + struct stat st; + if (fstat(Files[fnum].fd,&st) != 0) return(False); + return(share_name(Files[fnum].cnum,&st,name)); +} + + +/******************************************************************* + get the share mode of a file using the fnum + ******************************************************************/ +int get_share_mode_by_fnum(int cnum,int fnum,int *pid) +{ + struct stat sbuf; + if (fstat(Files[fnum].fd,&sbuf) == -1) return(0); + return(get_share_mode(cnum,&sbuf,pid)); +} + +/******************************************************************* + get the share mode of a file using the files name + ******************************************************************/ +int get_share_mode_byname(int cnum,char *fname,int *pid) +{ + struct stat sbuf; + if (stat(fname,&sbuf) == -1) return(0); + return(get_share_mode(cnum,&sbuf,pid)); +} + + +/******************************************************************* +get the share mode of a file +********************************************************************/ +int get_share_mode(int cnum,struct stat *sbuf,int *pid) +{ + pstring fname; + int fd2; + char buf[16]; + int ret; + time_t t; + + *pid = 0; + + if (!share_name(cnum,sbuf,fname)) return(0); + + fd2 = open(fname,O_RDONLY,0); + if (fd2 < 0) return(0); + + if (read(fd2,buf,16) != 16) { + close(fd2); + unlink(fname); + return(0); + } + close(fd2); + + t = IVAL(buf,0); + ret = IVAL(buf,4); + *pid = IVAL(buf,8); + + if (IVAL(buf,12) != LOCKING_VERSION) { + if (!unlink(fname)) DEBUG(2,("Deleted old locking file %s",fname)); + *pid = 0; + return(0); + } + + if (*pid && !process_exists(*pid)) { + ret=0; + *pid = 0; + } + + if (! *pid) unlink(fname); /* XXXXX race, race */ + + if (*pid) + DEBUG(5,("Read share file %s mode 0x%X pid=%d\n",fname,ret,*pid)); + + return(ret); +} + + +/******************************************************************* +del the share mode of a file, if we set it last +********************************************************************/ +void del_share_mode(int fnum) +{ + pstring fname; + int fd2; + char buf[16]; + time_t t=0; + int pid=0; + BOOL del = False; + + if (!share_name_fnum(fnum,fname)) return; + + fd2 = open(fname,O_RDONLY,0); + if (fd2 < 0) return; + if (read(fd2,buf,16) != 16) + del = True; + close(fd2); + + if (!del) { + t = IVAL(buf,0); + pid = IVAL(buf,8); + } + + if (!del) + if (IVAL(buf,12) != LOCKING_VERSION || !pid || !process_exists(pid)) + del = True; + + if (!del && t == Files[fnum].open_time && pid==(int)getpid()) + del = True; + + if (del) { + if (!unlink(fname)) + DEBUG(2,("Deleted share file %s\n",fname)); + else { + DEBUG(3,("Pending delete share file %s\n",fname)); + if (*share_del_pending) DEBUG(0,("Share del clash!\n")); + strcpy(share_del_pending,fname); + } + } +} + + +/******************************************************************* +set the share mode of a file +********************************************************************/ +BOOL set_share_mode(int fnum,int mode) +{ + pstring fname; + int fd2; + char buf[16]; + int pid = (int)getpid(); + + if (!share_name_fnum(fnum,fname)) return(False); + + { + int old_umask = umask(0); + fd2 = open(fname,O_WRONLY|O_CREAT|O_TRUNC,0644); + umask(old_umask); + } + if (fd2 < 0) { + DEBUG(2,("Failed to create share file %s\n",fname)); + return(False); + } + + SIVAL(buf,0,Files[fnum].open_time); + SIVAL(buf,4,mode); + SIVAL(buf,8,pid); + SIVAL(buf,12,LOCKING_VERSION); + + if (write(fd2,buf,16) != 16) { + close(fd2); + unlink(fname); + return(False); + } + + write(fd2,Files[fnum].name,strlen(Files[fnum].name)+1); + + close(fd2); + + DEBUG(3,("Created share file %s with mode 0x%X pid=%d\n",fname,mode,pid)); + + return(True); +} + + +/******************************************************************* +cleanup any stale share files +********************************************************************/ +void clean_share_files(void) +{ + char *lockdir = lp_lockdir(); + void *dir; + char *s; + + if (!*lockdir) return; + + dir = opendir(lockdir); + if (!dir) return; + + while ((s=readdirname(dir))) { + char buf[16]; + int pid; + int fd; + pstring lname; + int dev,inode; + + if (sscanf(s,"share.%d.%d",&dev,&inode)!=2) continue; + + strcpy(lname,lp_lockdir()); + trim_string(lname,NULL,"/"); + strcat(lname,"/"); + strcat(lname,s); + + fd = open(lname,O_RDONLY,0); + if (fd < 0) continue; + + if (read(fd,buf,16) != 16) { + close(fd); + if (!unlink(lname)) + printf("Deleted corrupt share file %s\n",s); + continue; + } + close(fd); + + pid = IVAL(buf,8); + + if (IVAL(buf,12) != LOCKING_VERSION || !process_exists(pid)) { + if (!unlink(lname)) + printf("Deleted stale share file %s\n",s); + } + } + + closedir(dir); +} -- cgit From de411c701ed79c02875807dc60ef035d8d08334d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Jun 1996 03:39:58 +0000 Subject: moved some more locking routines to locking.c, and moved replacement routines for broken OSes from util.c to replace.c. (This used to be commit 3ee9d45426a9b3b584d1ffb9f81af26790a83b4c) --- source3/locking/locking.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 6ff3ab5d12..9ece771266 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -28,6 +28,137 @@ extern files_struct Files[]; pstring share_del_pending=""; +/**************************************************************************** +routine to do file locking +****************************************************************************/ +BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type) +{ +#if HAVE_FCNTL_LOCK + struct flock lock; + int ret; + +#if 1 + uint32 mask = 0xC0000000; + + /* make sure the count is reasonable, we might kill the lockd otherwise */ + count &= ~mask; + + /* the offset is often strange - remove 2 of its bits if either of + the top two bits are set. Shift the top ones by two bits. This + still allows OLE2 apps to operate, but should stop lockd from + dieing */ + if ((offset & mask) != 0) + offset = (offset & ~mask) | ((offset & mask) >> 2); +#else + unsigned long mask = ((unsigned)1<<31); + + /* interpret negative counts as large numbers */ + if (count < 0) + count &= ~mask; + + /* no negative offsets */ + offset &= ~mask; + + /* count + offset must be in range */ + while ((offset < 0 || (offset + count < 0)) && mask) + { + offset &= ~mask; + mask = mask >> 1; + } +#endif + + + DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type)); + + lock.l_type = type; + lock.l_whence = SEEK_SET; + lock.l_start = (int)offset; + lock.l_len = (int)count; + lock.l_pid = 0; + + errno = 0; + + ret = fcntl(fd,op,&lock); + + if (errno != 0) + DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno))); + + /* a lock query */ + if (op == F_GETLK) + { + if ((ret != -1) && + (lock.l_type != F_UNLCK) && + (lock.l_pid != 0) && + (lock.l_pid != getpid())) + { + DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid)); + return(True); + } + + /* it must be not locked or locked by me */ + return(False); + } + + /* a lock set or unset */ + if (ret == -1) + { + DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n", + offset,count,op,type,strerror(errno))); + + /* perhaps it doesn't support this sort of locking?? */ + if (errno == EINVAL) + { + DEBUG(3,("locking not supported? returning True\n")); + return(True); + } + + return(False); + } + + /* everything went OK */ + DEBUG(5,("Lock call successful\n")); + + return(True); +#else + return(False); +#endif +} + +/******************************************************************* +lock a file - returning a open file descriptor or -1 on failure +The timeout is in seconds. 0 means no timeout +********************************************************************/ +int file_lock(char *name,int timeout) +{ + int fd = open(name,O_RDWR|O_CREAT,0666); + time_t t=0; + if (fd < 0) return(-1); + +#if HAVE_FCNTL_LOCK + if (timeout) t = time(NULL); + while (!timeout || (time(NULL)-t < timeout)) { + if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd); + msleep(LOCK_RETRY_TIMEOUT); + } + return(-1); +#else + return(fd); +#endif +} + +/******************************************************************* +unlock a file locked by file_lock +********************************************************************/ +void file_unlock(int fd) +{ + if (fd<0) return; +#if HAVE_FCNTL_LOCK + fcntl_lock(fd,F_SETLK,0,1,F_UNLCK); +#endif + close(fd); +} + + /**************************************************************************** utility function called to see if a file region is locked ****************************************************************************/ -- cgit From 7e3b4a1c0df1434eb3d02f93c736ce065f9898d8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Jun 1996 04:38:24 +0000 Subject: got rid of a lot of redundent header files as we now globally generate prototypes automatically using "make proto". This is much less prone to error than the old method of manually adding prototypes (This used to be commit b551dc98f7cc194a5fc2e67a4ebae7fd67a01bbc) --- source3/locking/locking.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 9ece771266..e81e1125e8 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -20,7 +20,6 @@ */ #include "includes.h" -#include "loadparm.h" extern int DEBUGLEVEL; extern connection_struct Connections[]; extern files_struct Files[]; -- cgit From dc38599c5a01211f20b9685dd440df82cd25c5cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Jun 1996 12:23:54 +0000 Subject: - change date as a demo for john - modified plp printing parser to work on my system (This used to be commit 9408f91e1b9a2482af96afe9df08e0a5fba60cdb) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e81e1125e8..78661d6970 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Locking functions - Copyright (C) Andrew Tridgell 1992-1995 + Copyright (C) Andrew Tridgell 1992-1996 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 -- cgit From ebc96b7309dbce110ae63bcb91dd8ad5a2cadbbf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 14 Aug 1996 15:02:28 +0000 Subject: changed "unsigned long" to "uint32" in several places (for IP addresses) to keep 64 bit machines happy. (This used to be commit b4aaec504ae66dc6a0f05d12529100cb62d47afd) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 78661d6970..8f76ce43da 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -49,7 +49,7 @@ BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type) if ((offset & mask) != 0) offset = (offset & ~mask) | ((offset & mask) >> 2); #else - unsigned long mask = ((unsigned)1<<31); + uint32 mask = ((unsigned)1<<31); /* interpret negative counts as large numbers */ if (count < 0) -- cgit From 47673b32ed4a907b380b70d5f4f366ba8be301d2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 Aug 1996 15:11:34 +0000 Subject: - added FAST_SHARE_MODES code - added some named pipe code from Jim (This used to be commit c94866e9e44ea1eb72da06bc65ef1c032ae8e0c9) --- source3/locking/locking.c | 246 +++++++++++++++- source3/locking/shmem.c | 722 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 967 insertions(+), 1 deletion(-) create mode 100644 source3/locking/shmem.c (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8f76ce43da..60428f2e98 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -17,6 +17,11 @@ 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 */ #include "includes.h" @@ -226,6 +231,34 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * return True; /* Did unlock */ } +#ifdef FAST_SHARE_MODES +/******************************************************************* + initialize the shared memory for share_mode management + ******************************************************************/ +BOOL start_share_mode_mgmt(void) +{ + pstring shmem_file_name; + + strcpy(shmem_file_name,lp_lockdir()); + trim_string(shmem_file_name,"","/"); + if (!*shmem_file_name) return(False); + strcat(shmem_file_name, "/SHARE_MEM_FILE"); + return shm_open(shmem_file_name, SHMEM_SIZE); +} + + +/******************************************************************* + deinitialize the shared memory for share_mode management + ******************************************************************/ +BOOL stop_share_mode_mgmt(void) +{ + return shm_close(); +} + +#else + +/* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */ + /******************************************************************* name a share file ******************************************************************/ @@ -251,6 +284,7 @@ static BOOL share_name_fnum(int fnum,char *name) return(share_name(Files[fnum].cnum,&st,name)); } +#endif /******************************************************************* get the share mode of a file using the fnum @@ -278,6 +312,78 @@ get the share mode of a file ********************************************************************/ int get_share_mode(int cnum,struct stat *sbuf,int *pid) { +#ifdef FAST_SHARE_MODES + share_mode_record *scanner_p; + share_mode_record *prev_p; + int ret; + BOOL found = False; + + *pid = 0; + + if(!shm_lock()) return (0); + + scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off()); + prev_p = scanner_p; + while(scanner_p) + { + if( (scanner_p->st_dev == sbuf->st_dev) && (scanner_p->st_ino == sbuf->st_ino) ) + { + found = True; + break; + } + else + { + prev_p = scanner_p ; + scanner_p = (share_mode_record *)shm_offset2addr(scanner_p->next_offset); + } + } + + if(!found) + { + shm_unlock(); + return (0); + } + + if(scanner_p->locking_version != LOCKING_VERSION) + { + DEBUG(2,("Deleting old share mode record due to old locking version %d",scanner_p->locking_version)); + if(prev_p == scanner_p) + shm_set_userdef_off(scanner_p->next_offset); + else + prev_p->next_offset = scanner_p->next_offset; + shm_free(shm_addr2offset(scanner_p)); + *pid = 0; + + shm_unlock(); + return (0); + } + + *pid = scanner_p->pid; + ret = scanner_p->share_mode; + + if (*pid && !process_exists(*pid)) + { + ret = 0; + *pid = 0; + } + + if (! *pid) + { + if(prev_p == scanner_p) + shm_set_userdef_off(scanner_p->next_offset); + else + prev_p->next_offset = scanner_p->next_offset; + shm_free(shm_addr2offset(scanner_p)); + } + + if (*pid) + DEBUG(5,("Read share mode record mode 0x%X pid=%d\n",ret,*pid)); + + if(!shm_unlock()) return (0); + + return(ret); + +#else pstring fname; int fd2; char buf[16]; @@ -319,6 +425,7 @@ int get_share_mode(int cnum,struct stat *sbuf,int *pid) DEBUG(5,("Read share file %s mode 0x%X pid=%d\n",fname,ret,*pid)); return(ret); +#endif } @@ -327,6 +434,67 @@ del the share mode of a file, if we set it last ********************************************************************/ void del_share_mode(int fnum) { +#ifdef FAST_SHARE_MODES + struct stat st; + time_t t=0; + int pid=0; + BOOL del = False; + share_mode_record *scanner_p; + share_mode_record *prev_p; + BOOL found = False; + + + + if (fstat(Files[fnum].fd,&st) != 0) return; + + if (!shm_lock()) return; + + scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off()); + prev_p = scanner_p; + while(scanner_p) + { + if( (scanner_p->st_dev == st.st_dev) && (scanner_p->st_ino == st.st_ino) ) + { + found = True; + break; + } + else + { + prev_p = scanner_p ; + scanner_p = (share_mode_record *)shm_offset2addr(scanner_p->next_offset); + } + } + + if(!found) + { + shm_unlock(); + return; + } + + t = scanner_p->time; + pid = scanner_p->pid; + + if( (scanner_p->locking_version != LOCKING_VERSION) || !pid || !process_exists(pid)) + del = True; + + if (!del && t == Files[fnum].open_time && pid==(int)getpid()) + del = True; + + if (del) + { + DEBUG(2,("Deleting share mode record\n")); + if(prev_p == scanner_p) + shm_set_userdef_off(scanner_p->next_offset); + else + prev_p->next_offset = scanner_p->next_offset; + shm_free(shm_addr2offset(scanner_p)); + + } + + shm_unlock(); + return; + +#else pstring fname; int fd2; char buf[16]; @@ -363,6 +531,7 @@ void del_share_mode(int fnum) strcpy(share_del_pending,fname); } } +#endif } @@ -371,6 +540,36 @@ set the share mode of a file ********************************************************************/ BOOL set_share_mode(int fnum,int mode) { +#ifdef FAST_SHARE_MODES + int pid = (int)getpid(); + struct stat st; + shm_offset_t new_off; + share_mode_record *new_p; + + + if (fstat(Files[fnum].fd,&st) != 0) return(False); + + if (!shm_lock()) return (False); + new_off = shm_alloc(sizeof(share_mode_record) + strlen(Files[fnum].name) ); + if (new_off == NULL_OFFSET) return (False); + new_p = (share_mode_record *)shm_offset2addr(new_off); + new_p->locking_version = LOCKING_VERSION; + new_p->share_mode = mode; + new_p->time = Files[fnum].open_time; + new_p->pid = pid; + new_p->st_dev = st.st_dev; + new_p->st_ino = st.st_ino; + strcpy(new_p->file_name,Files[fnum].name); + new_p->next_offset = shm_get_userdef_off(); + shm_set_userdef_off(new_off); + + + DEBUG(3,("Created share record for %s with mode 0x%X pid=%d\n",Files[fnum].name,mode,pid)); + + if (!shm_unlock()) return (False); + return(True); + +#else pstring fname; int fd2; char buf[16]; @@ -406,14 +605,58 @@ BOOL set_share_mode(int fnum,int mode) DEBUG(3,("Created share file %s with mode 0x%X pid=%d\n",fname,mode,pid)); return(True); +#endif } /******************************************************************* cleanup any stale share files ********************************************************************/ -void clean_share_files(void) +void clean_share_modes(void) { +#ifdef USE_SHMEM + share_mode_record *scanner_p; + share_mode_record *prev_p; + int pid; + + if (!shm_lock()) return; + + scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off()); + prev_p = scanner_p; + while(scanner_p) + { + pid = scanner_p->pid; + + if( (scanner_p->locking_version != LOCKING_VERSION) || !process_exists(pid)) + { + DEBUG(2,("Deleting stale share mode record")); + if(prev_p == scanner_p) + { + shm_set_userdef_off(scanner_p->next_offset); + shm_free(shm_addr2offset(scanner_p)); + scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off()); + prev_p = scanner_p; + } + else + { + prev_p->next_offset = scanner_p->next_offset; + shm_free(shm_addr2offset(scanner_p)); + scanner_p = (share_mode_record *)shm_offset2addr(prev_p->next_offset); + } + + } + else + { + prev_p = scanner_p ; + scanner_p = (share_mode_record *)shm_offset2addr(scanner_p->next_offset); + } + } + + + shm_unlock(); + return; + +#else char *lockdir = lp_lockdir(); void *dir; char *s; @@ -457,4 +700,5 @@ void clean_share_files(void) } closedir(dir); +#endif } diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c new file mode 100644 index 0000000000..3a308d07ba --- /dev/null +++ b/source3/locking/shmem.c @@ -0,0 +1,722 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Shared memory functions + Copyright (C) Erik Devriendt 1996 + + 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. + +*/ + +#ifdef FAST_SHARE_MODES + + +#include "includes.h" + +extern int DEBUGLEVEL; + + +#define SHM_MAGIC 0x53484100 +/* = "SHM" in hex */ + +#define SHM_VERSION 1 + +/* WARNING : offsets are used because mmap() does not guarantee that all processes have the + shared memory mapped to the same address */ + +struct ShmHeader +{ + int shm_magic; + int shm_version; + int total_size; /* in bytes */ + BOOL consistent; + shm_offset_t first_free_off; + shm_offset_t userdef_off; /* a userdefined offset. can be used to store root of tree or list */ + struct { /* a cell is a range of bytes of sizeof(struct ShmBlockDesc) size */ + int cells_free; + int cells_used; + int cells_system; /* number of cells used as allocated block descriptors */ + } statistics; +}; + +#define SHM_NOT_FREE_OFF (-1) +struct ShmBlockDesc +{ + shm_offset_t next; /* offset of next block in the free list or SHM_NOT_FREE_OFF when block in use */ + int size; /* user size in BlockDescSize units */ +}; + +#define EOList_Addr (struct ShmBlockDesc *)( 0 ) +#define EOList_Off (NULL_OFFSET) + +#define CellSize sizeof(struct ShmBlockDesc) + +/* HeaderSize aligned on 8 byte boundary */ +#define AlignedHeaderSize ((sizeof(struct ShmHeader)+7) & ~7) + +static int shm_fd = -1; +static pstring shm_processreg_name = ""; + +static struct ShmHeader *shm_header_p = (struct ShmHeader *)0; +static int shm_times_locked = 0; + +static BOOL shm_register_process(char *processreg_file, pid_t pid, BOOL *other_processes) +{ + int old_umask; + int shm_processes_fd = -1; + int nb_read; + pid_t other_pid; + int free_slot = -1; + int erased_slot; + + + old_umask = umask(0); + shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0666); + umask(old_umask); + if ( shm_processes_fd < 0 ) + { + DEBUG(0,("ERROR shm_register_process : processreg_file open failed with code %d\n",errno)); + return False; + } + + *other_processes = False; + + while ((nb_read = read(shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) + { + if(other_pid) + { + if(process_exists(other_pid)) + *other_processes = True; + else + { + /* erase old pid */ + DEBUG(2,("shm_register_process : erasing stale record for pid %d\n",other_pid)); + other_pid = (pid_t)0; + erased_slot = lseek(shm_processes_fd, -sizeof(other_pid), SEEK_CUR); + write(shm_processes_fd, &other_pid, sizeof(other_pid)); + if(free_slot < 0) + free_slot = erased_slot; + } + } + else + if(free_slot < 0) + free_slot = lseek(shm_processes_fd, -sizeof(other_pid), SEEK_CUR); + } + if (nb_read < 0) + { + DEBUG(0,("ERROR shm_register_process : processreg_file read failed with code %d\n",errno)); + close(shm_processes_fd); + return False; + } + + if(free_slot < 0) + free_slot = lseek(shm_processes_fd, 0, SEEK_END); + + DEBUG(2,("shm_register_process : writing record for pid %d at offset %d\n",pid,free_slot)); + lseek(shm_processes_fd, free_slot, SEEK_SET); + if(write(shm_processes_fd, &pid, sizeof(pid)) < 0) + { + DEBUG(0,("ERROR shm_register_process : processreg_file write failed with code %d\n",errno)); + close(shm_processes_fd); + return False; + } + + close(shm_processes_fd); + + return True; +} + +static BOOL shm_unregister_process(char *processreg_file, pid_t pid) +{ + int old_umask; + int shm_processes_fd = -1; + int nb_read; + pid_t other_pid; + int erased_slot; + BOOL found = False; + + + old_umask = umask(0); + shm_processes_fd = open(processreg_file, O_RDWR); + umask(old_umask); + if ( shm_processes_fd < 0 ) + { + DEBUG(0,("ERROR shm_unregister_process : processreg_file open failed with code %d\n",errno)); + return False; + } + + while ((nb_read = read(shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) + { + if(other_pid == pid) + { + /* erase pid */ + DEBUG(2,("shm_unregister_process : erasing record for pid %d\n",other_pid)); + other_pid = (pid_t)0; + erased_slot = lseek(shm_processes_fd, -sizeof(other_pid), SEEK_CUR); + if(write(shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) + { + DEBUG(0,("ERROR shm_unregister_process : processreg_file write failed with code %d\n",errno)); + close(shm_processes_fd); + return False; + } + + found = True; + break; + } + } + if (nb_read < 0) + { + DEBUG(0,("ERROR shm_unregister_process : processreg_file read failed with code %d\n",errno)); + close(shm_processes_fd); + return False; + } + + if(!found) + { + DEBUG(0,("ERROR shm_unregister_process : couldn't find pid %d in file %s\n",pid,processreg_file)); + close(shm_processes_fd); + return False; + } + + + close(shm_processes_fd); + + return True; +} + + +static BOOL shm_validate_header(int size) +{ + if( !shm_header_p ) + { + /* not mapped yet */ + DEBUG(0,("ERROR shm_validate_header : shmem not mapped\n")); + return False; + } + + if(shm_header_p->shm_magic != SHM_MAGIC) + { + DEBUG(0,("ERROR shm_validate_header : bad magic\n")); + return False; + } + if(shm_header_p->shm_version != SHM_VERSION) + { + DEBUG(0,("ERROR shm_validate_header : bad version %X\n",shm_header_p->shm_version)); + return False; + } + + if(shm_header_p->total_size != size) + { + DEBUG(0,("ERROR shm_validate_header : shmem size mismatch (old = %d, new = %d)\n",shm_header_p->total_size,size)); + return False; + } + + if(!shm_header_p->consistent) + { + DEBUG(0,("ERROR shm_validate_header : shmem not consistent\n")); + return False; + } + return True; +} + +static BOOL shm_initialize(int size) +{ + struct ShmBlockDesc * first_free_block_p; + + DEBUG(2,("shm_initialize : initializing shmem file of size %d\n",size)); + + if( !shm_header_p ) + { + /* not mapped yet */ + DEBUG(0,("ERROR shm_initialize : shmem not mapped\n")); + return False; + } + + shm_header_p->shm_magic = SHM_MAGIC; + shm_header_p->shm_version = SHM_VERSION; + shm_header_p->total_size = size; + shm_header_p->first_free_off = AlignedHeaderSize; + shm_header_p->userdef_off = NULL_OFFSET; + + first_free_block_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); + first_free_block_p->next = EOList_Off; + first_free_block_p->size = ( size - AlignedHeaderSize - CellSize ) / CellSize ; + + shm_header_p->statistics.cells_free = first_free_block_p->size; + shm_header_p->statistics.cells_used = 0; + shm_header_p->statistics.cells_system = 1; + + shm_header_p->consistent = True; + + return True; +} + +static void shm_solve_neighbors(struct ShmBlockDesc *head_p ) +{ + struct ShmBlockDesc *next_p; + + /* Check if head_p and head_p->next are neighbors and if so join them */ + if ( head_p == EOList_Addr ) return ; + if ( head_p->next == EOList_Off ) return ; + + next_p = (struct ShmBlockDesc *)shm_offset2addr(head_p->next); + if ( ( head_p + head_p->size + 1 ) == next_p) + { + head_p->size += next_p->size +1 ; /* adapt size */ + head_p->next = next_p->next ; /* link out */ + + shm_header_p->statistics.cells_free += 1; + shm_header_p->statistics.cells_system -= 1; + } +} + + + +BOOL shm_open( char *file_name, int size) +{ + int filesize; + BOOL created_new = False; + BOOL other_processes = True; + int old_umask; + + DEBUG(2,("shm_open : using shmem file %s to be of size %d\n",file_name,size)); + + old_umask = umask(0); + shm_fd = open(file_name, O_RDWR | O_CREAT, 0666); + umask(old_umask); + if ( shm_fd < 0 ) + { + DEBUG(0,("ERROR shm_open : open failed with code %d\n",errno)); + return False; + } + + if (!shm_lock()) + { + DEBUG(0,("ERROR shm_open : can't do shm_lock\n")); + return False; + } + + if( (filesize = lseek(shm_fd, 0, SEEK_END)) < 0) + { + DEBUG(0,("ERROR shm_open : lseek failed with code %d\n",errno)); + shm_unlock(); + close(shm_fd); + return False; + } + + /* return the file offset to 0 to save on later seeks */ + lseek(shm_fd,0,SEEK_SET); + + if (filesize == 0) + { + /* we just created a new one */ + created_new = True; + } + + /* to find out if some other process is already mapping the file, + we use a registration file containing the processids of the file mapping processes + */ + + /* construct processreg file name */ + strcpy(shm_processreg_name, file_name); + strcat(shm_processreg_name, ".processes"); + + if (! shm_register_process(shm_processreg_name, getpid(), &other_processes)) + { + shm_unlock(); + close(shm_fd); + return False; + } + + if (created_new || !other_processes) + { + /* we just created a new one, or are the first opener, lets set it size */ + if( ftruncate(shm_fd, size) <0) + { + DEBUG(0,("ERROR shm_open : ftruncate failed with code %d\n",errno)); + shm_unregister_process(shm_processreg_name, getpid()); + shm_unlock(); + close(shm_fd); + return False; + } + + /* paranoia */ + lseek(shm_fd,0,SEEK_SET); + + filesize = size; + } + + if (size != filesize ) + { + /* the existing file has a different size and we are not the first opener. + Since another process is still using it, we will use the file size */ + DEBUG(0,("WARNING shm_open : filesize (%d) != expected size (%d), using filesize\n",filesize,size)); + size = filesize; + } + + shm_header_p = (struct ShmHeader *)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, shm_fd, 0); + /* WARNING, shm_header_p can be different for different processes mapping the same file ! */ + if (shm_header_p == (struct ShmHeader *)(-1)) + { + DEBUG(0,("ERROR shm_open : mmap failed with code %d\n",errno)); + shm_unregister_process(shm_processreg_name, getpid()); + shm_unlock(); + close(shm_fd); + return False; + } + + + if (created_new || !other_processes) + { + shm_initialize(size); + } + else if (!shm_validate_header(size) ) + { + /* existing file is corrupt, samba admin should remove it by hand */ + DEBUG(0,("ERROR shm_open : corrupt shared mem file, remove it manually\n")); + munmap((caddr_t)shm_header_p, size); + shm_unregister_process(shm_processreg_name, getpid()); + shm_unlock(); + close(shm_fd); + return False; + } + + shm_unlock(); + return True; + +} + + +BOOL shm_close( void ) +{ + + DEBUG(2,("shm_close\n")); + if(shm_times_locked > 0) + DEBUG(0,("WARNING shm_close : shmem was still locked %d times\n",shm_times_locked));; + if ( munmap((caddr_t)shm_header_p, shm_header_p->total_size) < 0) + { + DEBUG(0,("ERROR shm_close : munmap failed with code %d\n",errno)); + } + + shm_lock(); + shm_unregister_process(shm_processreg_name, getpid()); + shm_unlock(); + + close(shm_fd); + + shm_fd = -1; + shm_processreg_name[0] = '\0'; + + shm_header_p = (struct ShmHeader *)0; + shm_times_locked = 0; + + return True; +} + +shm_offset_t shm_alloc(int size) +{ + unsigned num_cells ; + struct ShmBlockDesc *scanner_p; + struct ShmBlockDesc *prev_p; + struct ShmBlockDesc *new_p; + shm_offset_t result_offset; + + + if( !shm_header_p ) + { + /* not mapped yet */ + DEBUG(0,("ERROR shm_alloc : shmem not mapped\n")); + return NULL_OFFSET; + } + + if( !shm_header_p->consistent) + { + DEBUG(0,("ERROR shm_alloc : shmem not consistent\n")); + return NULL_OFFSET; + } + + + /* calculate the number of cells */ + num_cells = (size + CellSize -1) / CellSize; + + /* set start of scan */ + prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); + scanner_p = prev_p ; + + /* scan the free list to find a matching free space */ + while ( ( scanner_p != EOList_Addr ) && ( scanner_p->size < num_cells ) ) + { + prev_p = scanner_p; + scanner_p = (struct ShmBlockDesc *)shm_offset2addr(scanner_p->next); + } + + /* at this point scanner point to a block header or to the end of the list */ + if ( scanner_p == EOList_Addr ) + { + DEBUG(0,("ERROR shm_alloc : alloc of %d bytes failed, no free space found\n",size)); + return (NULL_OFFSET); + } + + /* going to modify shared mem */ + shm_header_p->consistent = False; + + /* if we found a good one : scanner == the good one */ + if ( scanner_p->size <= num_cells + 2 ) + { + /* there is no use in making a new one, it will be too small anyway + * we will link out scanner + */ + if ( prev_p == scanner_p ) + { + shm_header_p->first_free_off = scanner_p->next ; + } + else + { + prev_p->next = scanner_p->next ; + } + shm_header_p->statistics.cells_free -= scanner_p->size; + shm_header_p->statistics.cells_used += scanner_p->size; + } + else + { + /* Make a new one */ + new_p = scanner_p + 1 + num_cells; + new_p->size = scanner_p->size - num_cells - 1; + new_p->next = scanner_p->next; + scanner_p->size = num_cells; + scanner_p->next = shm_addr2offset(new_p); + + if ( prev_p != scanner_p ) + { + prev_p->next = shm_addr2offset(new_p) ; + } + else + { + shm_header_p->first_free_off = shm_addr2offset(new_p) ; + } + shm_header_p->statistics.cells_free -= num_cells+1; + shm_header_p->statistics.cells_used += num_cells; + shm_header_p->statistics.cells_system += 1; + } + + result_offset = shm_addr2offset( &(scanner_p[1]) ); + scanner_p->next = SHM_NOT_FREE_OFF ; + + /* end modification of shared mem */ + shm_header_p->consistent = True; + + DEBUG(2,("shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); + + return ( result_offset ); +} + + + +BOOL shm_free(shm_offset_t offset) +{ + struct ShmBlockDesc *header_p ; /* pointer to header of block to free */ + struct ShmBlockDesc *scanner_p ; /* used to scan the list */ + struct ShmBlockDesc *prev_p ; /* holds previous in the list */ + + if( !shm_header_p ) + { + /* not mapped yet */ + DEBUG(0,("ERROR shm_free : shmem not mapped\n")); + return False; + } + + if( !shm_header_p->consistent) + { + DEBUG(0,("ERROR shm_free : shmem not consistent\n")); + return False; + } + + header_p = ( (struct ShmBlockDesc *)shm_offset2addr(offset) - 1); /* make pointer to header of block */ + + if (header_p->next != SHM_NOT_FREE_OFF) + { + DEBUG(0,("ERROR shm_free : bad offset (%d)\n",offset)); + return False; + } + + /* find a place in the free_list to put the header in */ + + /* set scanner and previous pointer to start of list */ + prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); + scanner_p = prev_p ; + + while ( ( scanner_p != EOList_Addr) && (scanner_p < header_p) ) /* while we didn't scan past its position */ + { + prev_p = scanner_p ; + scanner_p = (struct ShmBlockDesc *)shm_offset2addr(scanner_p->next); + } + + shm_header_p->consistent = False; + + DEBUG(2,("shm_free : freeing %d bytes at offset %d\n",header_p->size*CellSize,offset)); + + if ( scanner_p == prev_p ) + { + shm_header_p->statistics.cells_free += header_p->size; + shm_header_p->statistics.cells_used -= header_p->size; + + /* we must free it at the beginning of the list */ + shm_header_p->first_free_off = shm_addr2offset(header_p); /* set the free_list_pointer to this block_header */ + + /* scanner is the one that was first in the list */ + header_p->next = shm_addr2offset(scanner_p); + shm_solve_neighbors( header_p ); /* if neighbors then link them */ + + shm_header_p->consistent = True; + return True; + } + else + { + shm_header_p->statistics.cells_free += header_p->size; + shm_header_p->statistics.cells_used -= header_p->size; + + prev_p->next = shm_addr2offset(header_p); + header_p->next = shm_addr2offset(scanner_p); + shm_solve_neighbors(header_p) ; + shm_solve_neighbors(prev_p) ; + + shm_header_p->consistent = True; + return True; + } +} + +shm_offset_t shm_get_userdef_off(void) +{ + if (!shm_header_p) + return NULL_OFFSET; + else + return shm_header_p->userdef_off; +} + +BOOL shm_set_userdef_off(shm_offset_t userdef_off) +{ + if (!shm_header_p) + return False; + else + shm_header_p->userdef_off = userdef_off; + return True; +} + +void * shm_offset2addr(shm_offset_t offset) +{ + if (offset == NULL_OFFSET ) + return (void *)(0); + + if (!shm_header_p) + return (void *)(0); + + return (void *)((char *)shm_header_p + offset ); +} + +shm_offset_t shm_addr2offset(void *addr) +{ + if (!addr) + return NULL_OFFSET; + + if (!shm_header_p) + return NULL_OFFSET; + + return (shm_offset_t)((char *)addr - (char *)shm_header_p); +} + +BOOL shm_lock(void) +{ + if (shm_fd < 0) + { + DEBUG(0,("ERROR shm_lock : bad shm_fd (%d)\n",shm_fd)); + return False; + } + + shm_times_locked++; + + if(shm_times_locked > 1) + { + DEBUG(2,("shm_lock : locked %d times\n",shm_times_locked)); + return True; + } + + if (lockf(shm_fd, F_LOCK, 0) < 0) + { + DEBUG(0,("ERROR shm_lock : lockf failed with code %d\n",errno)); + shm_times_locked--; + return False; + } + + return True; + +} + + + +BOOL shm_unlock(void) +{ + if (shm_fd < 0) + { + DEBUG(0,("ERROR shm_unlock : bad shm_fd (%d)\n",shm_fd)); + return False; + } + + if(shm_times_locked == 0) + { + DEBUG(0,("ERROR shm_unlock : shmem not locked\n",shm_fd)); + return False; + } + + shm_times_locked--; + + if(shm_times_locked > 0) + { + DEBUG(2,("shm_unlock : still locked %d times\n",shm_times_locked)); + return True; + } + + if (lockf(shm_fd, F_ULOCK, 0) < 0) + { + DEBUG(0,("ERROR shm_unlock : lockf failed with code %d\n",errno)); + shm_times_locked++; + return False; + } + + return True; + +} + + +BOOL shm_get_usage(int *bytes_free, + int *bytes_used, + int *bytes_overhead) +{ + if( !shm_header_p ) + { + /* not mapped yet */ + DEBUG(0,("ERROR shm_free : shmem not mapped\n")); + return False; + } + *bytes_free = shm_header_p->statistics.cells_free * CellSize; + *bytes_used = shm_header_p->statistics.cells_used * CellSize; + *bytes_overhead = shm_header_p->statistics.cells_system * CellSize + AlignedHeaderSize; + + return True; +} + +#else /* FAST_SHARE_MODES */ + int shmem_dummy_procedure(void) +{return 0;} +#endif -- cgit From efb8113d00a4513c1115640004c0905465d3b673 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 17 Aug 1996 14:27:12 +0000 Subject: - made FAST_SHARE_MODES standard for Linux - you can now press enter after a password prompt with "smbclient -L hostname" and it will use a blank username and password, the same as if you used -U% - changed the wins.dat store code to not go via a string variable (just use fprintf instead) - removed a "unsigned long" that luke put back in, changing it to uint32 to keep 64 bit machines happy. Naughtly luke! - allow guest non-connnected print queue listings so ms client 3 can work (This used to be commit 917160dee69bbc198985b6f3232ca2dcda809d8a) --- source3/locking/locking.c | 8 ++++---- source3/locking/shmem.c | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 60428f2e98..966bb2253b 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -231,7 +231,7 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * return True; /* Did unlock */ } -#ifdef FAST_SHARE_MODES +#if FAST_SHARE_MODES /******************************************************************* initialize the shared memory for share_mode management ******************************************************************/ @@ -312,7 +312,7 @@ get the share mode of a file ********************************************************************/ int get_share_mode(int cnum,struct stat *sbuf,int *pid) { -#ifdef FAST_SHARE_MODES +#if FAST_SHARE_MODES share_mode_record *scanner_p; share_mode_record *prev_p; int ret; @@ -434,7 +434,7 @@ del the share mode of a file, if we set it last ********************************************************************/ void del_share_mode(int fnum) { -#ifdef FAST_SHARE_MODES +#if FAST_SHARE_MODES struct stat st; time_t t=0; int pid=0; @@ -540,7 +540,7 @@ set the share mode of a file ********************************************************************/ BOOL set_share_mode(int fnum,int mode) { -#ifdef FAST_SHARE_MODES +#if FAST_SHARE_MODES int pid = (int)getpid(); struct stat st; shm_offset_t new_off; diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 3a308d07ba..f68059afa2 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -20,10 +20,11 @@ */ -#ifdef FAST_SHARE_MODES +#include "includes.h" -#include "includes.h" +#if FAST_SHARE_MODES + extern int DEBUGLEVEL; -- cgit From 0c33046a0aa0461a5e932dd7b0b6e38ab9708867 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 19 Aug 1996 11:17:29 +0000 Subject: - added "netbios name" option in smb.conf to make controlling the name that samba uses possible - added "socket address" option to allow virtual SMB servers (on systems with IP aliasing line Linux) - disabled FAST_SHARE_MODES by default in Linux as older Linux boxes can't do shared writeable mappings. We really need autoconf ... - added new option types in loadparm so a string type can be specified ot be uppercase only, this is used for the workgroup and netbios name options - auto-create the lock directory if it doesn't exist in shared mem startup - get rid of announce_backup() - change a few comments in nmbd code - rewrote the chaining code completely. Hopefully it will handle any depth chains now. - added LPRng support (This used to be commit e9eac6cd49c352349580ddb13d720cb201aecc48) --- source3/locking/locking.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 966bb2253b..04f4a4b197 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -240,6 +240,8 @@ BOOL start_share_mode_mgmt(void) pstring shmem_file_name; strcpy(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"); -- cgit From e23f2b9cef8428bda51b413642d9720ba5c590d5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 4 Oct 1996 09:31:07 +0000 Subject: - changed the umask handling. We now set the umask to 0 and explicitly set the mode on all created files. I think this is a better policy. - change the debug levels on some items - fix a charset handling bug which affected foreign and extended charset users - no longer switch back to the original directory when idle, instead switch to / as the original directory may not be readable by ordinary users. - fix some bugs where the create mode of files was not being explicitly set (it was relying on the umask and using fopen). Not a big bug as it only affected obscure commands like the messaging ops. - got rid of the lock code in the lpq cache as its no longer needed - rewrote smbrun to be faster and to remove the security hole. We now don't actually need a external smbrun binary, its all done by smbd. - add a more explicit warning about uids and gids of -1 or 65535 (This used to be commit 5aa735c940ccdb6acae5f28449d484181c912e49) --- source3/locking/shmem.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index f68059afa2..e17cf1aa8d 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -75,17 +75,13 @@ static int shm_times_locked = 0; static BOOL shm_register_process(char *processreg_file, pid_t pid, BOOL *other_processes) { - int old_umask; int shm_processes_fd = -1; int nb_read; pid_t other_pid; int free_slot = -1; - int erased_slot; - + int erased_slot; - old_umask = umask(0); shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0666); - umask(old_umask); if ( shm_processes_fd < 0 ) { DEBUG(0,("ERROR shm_register_process : processreg_file open failed with code %d\n",errno)); -- cgit From 75e3bbc651187754fa7b0c9fb5df921c31738d65 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 10 Dec 1996 17:53:00 +0000 Subject: Moved fcntl locking code into util.c to allow it to be called from nmbd code. jra@cygnus.com (This used to be commit d718f4fd30423fea957b14e141289739506656cb) --- source3/locking/locking.c | 131 ---------------------------------------------- 1 file changed, 131 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 04f4a4b197..dde9477e23 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -32,137 +32,6 @@ extern files_struct Files[]; pstring share_del_pending=""; -/**************************************************************************** -routine to do file locking -****************************************************************************/ -BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type) -{ -#if HAVE_FCNTL_LOCK - struct flock lock; - int ret; - -#if 1 - uint32 mask = 0xC0000000; - - /* make sure the count is reasonable, we might kill the lockd otherwise */ - count &= ~mask; - - /* the offset is often strange - remove 2 of its bits if either of - the top two bits are set. Shift the top ones by two bits. This - still allows OLE2 apps to operate, but should stop lockd from - dieing */ - if ((offset & mask) != 0) - offset = (offset & ~mask) | ((offset & mask) >> 2); -#else - uint32 mask = ((unsigned)1<<31); - - /* interpret negative counts as large numbers */ - if (count < 0) - count &= ~mask; - - /* no negative offsets */ - offset &= ~mask; - - /* count + offset must be in range */ - while ((offset < 0 || (offset + count < 0)) && mask) - { - offset &= ~mask; - mask = mask >> 1; - } -#endif - - - DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type)); - - lock.l_type = type; - lock.l_whence = SEEK_SET; - lock.l_start = (int)offset; - lock.l_len = (int)count; - lock.l_pid = 0; - - errno = 0; - - ret = fcntl(fd,op,&lock); - - if (errno != 0) - DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno))); - - /* a lock query */ - if (op == F_GETLK) - { - if ((ret != -1) && - (lock.l_type != F_UNLCK) && - (lock.l_pid != 0) && - (lock.l_pid != getpid())) - { - DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid)); - return(True); - } - - /* it must be not locked or locked by me */ - return(False); - } - - /* a lock set or unset */ - if (ret == -1) - { - DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n", - offset,count,op,type,strerror(errno))); - - /* perhaps it doesn't support this sort of locking?? */ - if (errno == EINVAL) - { - DEBUG(3,("locking not supported? returning True\n")); - return(True); - } - - return(False); - } - - /* everything went OK */ - DEBUG(5,("Lock call successful\n")); - - return(True); -#else - return(False); -#endif -} - -/******************************************************************* -lock a file - returning a open file descriptor or -1 on failure -The timeout is in seconds. 0 means no timeout -********************************************************************/ -int file_lock(char *name,int timeout) -{ - int fd = open(name,O_RDWR|O_CREAT,0666); - time_t t=0; - if (fd < 0) return(-1); - -#if HAVE_FCNTL_LOCK - if (timeout) t = time(NULL); - while (!timeout || (time(NULL)-t < timeout)) { - if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd); - msleep(LOCK_RETRY_TIMEOUT); - } - return(-1); -#else - return(fd); -#endif -} - -/******************************************************************* -unlock a file locked by file_lock -********************************************************************/ -void file_unlock(int fd) -{ - if (fd<0) return; -#if HAVE_FCNTL_LOCK - fcntl_lock(fd,F_SETLK,0,1,F_UNLCK); -#endif - close(fd); -} - - /**************************************************************************** utility function called to see if a file region is locked ****************************************************************************/ -- cgit From 8bc7d6bebd4fcf8c95cb6d58da14404a5e46de91 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 9 Jan 1997 18:02:17 +0000 Subject: Makefile: Changes to split Solaris into Solaris2.3 and previous, and 2.4 and after from Paul Eggert. Makefile: Added AMIGA changes from Rask Ingemann Lambertsen . charset.c: Patch for Western European Languages from Josef Hinteregger charset.h: Patch for Western European Languages from Josef Hinteregger clitar.c: Patch to re-sync after read fail from (lost contributor name, sorry). includes.h: Patch for AMIGA from Rask Ingemann Lambertsen includes.h: Patch for SunOS atexit by Jeremy (jra@cygnus.com) interface.c: Patch for AMIGA from Rask Ingemann Lambertsen kanji.h: Patch for Western European Languages from Josef Hinteregger locking.c: Patch to fix file locking from Jeremy (jra@cygnus.com) locking.c: Patch to add granularity of lock files to usec by Jeremy (jra@cygnus.com) pipes.c: Patch to fix file locking from Jeremy (jra@cygnus.com) proto.h: Patch to fix file locking from Jeremy (jra@cygnus.com) reply.c: Patch to fix file locking from Jeremy (jra@cygnus.com) server.c: Patch to fix file locking from Jeremy (jra@cygnus.com) server.c: Patch for FAST_SHARE_MODE fix from (lost contributor name, sorry). smb.h: Patch to fix file locking from Jeremy (jra@cygnus.com) smb.h: Patch to add granularity of lock files to usec by Jeremy (jra@cygnus.com) status.c: Patch to fix file locking from Jeremy (jra@cygnus.com) statuc.c: Patch to add granularity of lock files to usec by Jeremy (jra@cygnus.com) system.c: Patch for Western European Languages from Josef Hinteregger trans2.c: Patch to fix file locking from Jeremy (jra@cygnus.com) trans2.c: Patch to fix volume name reported to Win95 from Jeremy (jra@cygnus.com) util.c: Patch for Western European Languages from Josef Hinteregger util.c: Patch to fix client_name from continuously returning UNKNOWN (from various contributors). version.h: Update to 1.9.16p10. (This used to be commit 03d28fa32eb094affa33133ebe2602fdb70f6361) --- source3/locking/locking.c | 64 ++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 29 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index dde9477e23..d94cc9c35f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -45,7 +45,7 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset) if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - return(fcntl_lock(Files[fnum].fd,F_GETLK,offset,count, + return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count, (Files[fnum].can_write?F_WRLCK:F_RDLCK))); } @@ -67,7 +67,7 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ec } if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum)) - ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count, + ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count, (Files[fnum].can_write?F_WRLCK:F_RDLCK)); if (!ok) { @@ -90,7 +90,7 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * return(True); if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum)) - ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count,F_UNLCK); + ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); if (!ok) { *eclass = ERRDOS; @@ -151,7 +151,7 @@ static BOOL share_name(int cnum,struct stat *st,char *name) static BOOL share_name_fnum(int fnum,char *name) { struct stat st; - if (fstat(Files[fnum].fd,&st) != 0) return(False); + if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return(False); return(share_name(Files[fnum].cnum,&st,name)); } @@ -163,7 +163,7 @@ static BOOL share_name_fnum(int fnum,char *name) int get_share_mode_by_fnum(int cnum,int fnum,int *pid) { struct stat sbuf; - if (fstat(Files[fnum].fd,&sbuf) == -1) return(0); + if (fstat(Files[fnum].fd_ptr->fd,&sbuf) == -1) return(0); return(get_share_mode(cnum,&sbuf,pid)); } @@ -257,9 +257,9 @@ int get_share_mode(int cnum,struct stat *sbuf,int *pid) #else pstring fname; int fd2; - char buf[16]; + char buf[20]; int ret; - time_t t; + struct timeval t; *pid = 0; @@ -268,18 +268,20 @@ int get_share_mode(int cnum,struct stat *sbuf,int *pid) fd2 = open(fname,O_RDONLY,0); if (fd2 < 0) return(0); - if (read(fd2,buf,16) != 16) { + if (read(fd2,buf,20) != 20) { + DEBUG(2,("Failed to read share file %s\n",fname)); close(fd2); unlink(fname); return(0); } close(fd2); - t = IVAL(buf,0); - ret = IVAL(buf,4); - *pid = IVAL(buf,8); + t.tv_sec = IVAL(buf,4); + t.tv_usec = IVAL(buf,8); + ret = IVAL(buf,12); + *pid = IVAL(buf,16); - if (IVAL(buf,12) != LOCKING_VERSION) { + if (IVAL(buf,0) != LOCKING_VERSION) { if (!unlink(fname)) DEBUG(2,("Deleted old locking file %s",fname)); *pid = 0; return(0); @@ -368,29 +370,31 @@ void del_share_mode(int fnum) #else pstring fname; int fd2; - char buf[16]; - time_t t=0; + char buf[20]; + struct timeval t; int pid=0; BOOL del = False; + t.tv_sec = t.tv_usec = 0; if (!share_name_fnum(fnum,fname)) return; fd2 = open(fname,O_RDONLY,0); if (fd2 < 0) return; - if (read(fd2,buf,16) != 16) + if (read(fd2,buf,20) != 20) del = True; close(fd2); if (!del) { - t = IVAL(buf,0); - pid = IVAL(buf,8); + t.tv_sec = IVAL(buf,4); + t.tv_usec = IVAL(buf,8); + pid = IVAL(buf,16); } if (!del) - if (IVAL(buf,12) != LOCKING_VERSION || !pid || !process_exists(pid)) + if (IVAL(buf,0) != LOCKING_VERSION || !pid || !process_exists(pid)) del = True; - if (!del && t == Files[fnum].open_time && pid==(int)getpid()) + if (!del && (memcmp(&t,&Files[fnum].open_time,sizeof(t)) == 0) && (pid==(int)getpid())) del = True; if (del) { @@ -443,7 +447,7 @@ BOOL set_share_mode(int fnum,int mode) #else pstring fname; int fd2; - char buf[16]; + char buf[20]; int pid = (int)getpid(); if (!share_name_fnum(fnum,fname)) return(False); @@ -458,12 +462,14 @@ BOOL set_share_mode(int fnum,int mode) return(False); } - SIVAL(buf,0,Files[fnum].open_time); - SIVAL(buf,4,mode); - SIVAL(buf,8,pid); - SIVAL(buf,12,LOCKING_VERSION); + SIVAL(buf,0,LOCKING_VERSION); + SIVAL(buf,4,Files[fnum].open_time.tv_sec); + SIVAL(buf,8,Files[fnum].open_time.tv_usec); + SIVAL(buf,12,mode); + SIVAL(buf,16,pid); - if (write(fd2,buf,16) != 16) { + if (write(fd2,buf,20) != 20) { + DEBUG(2,("Failed to write share file %s\n",fname)); close(fd2); unlink(fname); return(False); @@ -538,7 +544,7 @@ void clean_share_modes(void) if (!dir) return; while ((s=readdirname(dir))) { - char buf[16]; + char buf[20]; int pid; int fd; pstring lname; @@ -554,7 +560,7 @@ void clean_share_modes(void) fd = open(lname,O_RDONLY,0); if (fd < 0) continue; - if (read(fd,buf,16) != 16) { + if (read(fd,buf,20) != 20) { close(fd); if (!unlink(lname)) printf("Deleted corrupt share file %s\n",s); @@ -562,9 +568,9 @@ void clean_share_modes(void) } close(fd); - pid = IVAL(buf,8); + pid = IVAL(buf,16); - if (IVAL(buf,12) != LOCKING_VERSION || !process_exists(pid)) { + if (IVAL(buf,0) != LOCKING_VERSION || !process_exists(pid)) { if (!unlink(lname)) printf("Deleted stale share file %s\n",s); } -- cgit From 869f24e0b1915ec8d3e14f8850417474200e687e Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 15 Jan 1997 01:53:25 +0000 Subject: locking.c proto.h shmem.c smb.h status.c : Changed shm_ prefixes to smb_shm_ prefixes as shm_ is a POSIX.4 prefix. Updated fd code in FAST_SHARE_MODE code to work with new fd indirection. quotas.c: Fixed #ifdef not on position zero. Jeremy. (jra@cygnus.com). (This used to be commit c9a9d56642cc34369a42f48a28116e466240d303) --- source3/locking/locking.c | 87 ++++----- source3/locking/shmem.c | 458 +++++++++++++++++++++++----------------------- 2 files changed, 274 insertions(+), 271 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d94cc9c35f..ce96aa01cf 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -114,7 +114,7 @@ BOOL start_share_mode_mgmt(void) trim_string(shmem_file_name,"","/"); if (!*shmem_file_name) return(False); strcat(shmem_file_name, "/SHARE_MEM_FILE"); - return shm_open(shmem_file_name, SHMEM_SIZE); + return smb_shm_open(shmem_file_name, SHMEM_SIZE); } @@ -123,7 +123,7 @@ BOOL start_share_mode_mgmt(void) ******************************************************************/ BOOL stop_share_mode_mgmt(void) { - return shm_close(); + return smb_shm_close(); } #else @@ -191,9 +191,9 @@ int get_share_mode(int cnum,struct stat *sbuf,int *pid) *pid = 0; - if(!shm_lock()) return (0); + if(!smb_shm_lock()) return (0); - scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off()); + scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off()); prev_p = scanner_p; while(scanner_p) { @@ -205,13 +205,13 @@ int get_share_mode(int cnum,struct stat *sbuf,int *pid) else { prev_p = scanner_p ; - scanner_p = (share_mode_record *)shm_offset2addr(scanner_p->next_offset); + scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset); } } if(!found) { - shm_unlock(); + smb_shm_unlock(); return (0); } @@ -219,13 +219,13 @@ int get_share_mode(int cnum,struct stat *sbuf,int *pid) { DEBUG(2,("Deleting old share mode record due to old locking version %d",scanner_p->locking_version)); if(prev_p == scanner_p) - shm_set_userdef_off(scanner_p->next_offset); + smb_shm_set_userdef_off(scanner_p->next_offset); else prev_p->next_offset = scanner_p->next_offset; - shm_free(shm_addr2offset(scanner_p)); + smb_shm_free(smb_shm_addr2offset(scanner_p)); *pid = 0; - shm_unlock(); + smb_shm_unlock(); return (0); } @@ -241,16 +241,16 @@ int get_share_mode(int cnum,struct stat *sbuf,int *pid) if (! *pid) { if(prev_p == scanner_p) - shm_set_userdef_off(scanner_p->next_offset); + smb_shm_set_userdef_off(scanner_p->next_offset); else prev_p->next_offset = scanner_p->next_offset; - shm_free(shm_addr2offset(scanner_p)); + smb_shm_free(smb_shm_addr2offset(scanner_p)); } if (*pid) DEBUG(5,("Read share mode record mode 0x%X pid=%d\n",ret,*pid)); - if(!shm_unlock()) return (0); + if(!smb_shm_unlock()) return (0); return(ret); @@ -309,20 +309,20 @@ void del_share_mode(int fnum) { #if FAST_SHARE_MODES struct stat st; - time_t t=0; + struct timeval t; int pid=0; BOOL del = False; share_mode_record *scanner_p; share_mode_record *prev_p; BOOL found = False; + t.tv_sec = t.tv_usec = 0; + if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return; - if (fstat(Files[fnum].fd,&st) != 0) return; - - if (!shm_lock()) return; + if (!smb_shm_lock()) return; - scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off()); + scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off()); prev_p = scanner_p; while(scanner_p) { @@ -334,37 +334,39 @@ void del_share_mode(int fnum) else { prev_p = scanner_p ; - scanner_p = (share_mode_record *)shm_offset2addr(scanner_p->next_offset); + scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset); } } if(!found) { - shm_unlock(); + smb_shm_unlock(); return; } - t = scanner_p->time; + t.tv_sec = scanner_p->time.tv_sec; + t.tv_usec = scanner_p->time.tv_usec; pid = scanner_p->pid; if( (scanner_p->locking_version != LOCKING_VERSION) || !pid || !process_exists(pid)) del = True; - if (!del && t == Files[fnum].open_time && pid==(int)getpid()) + if (!del && (memcmp(&t,&Files[fnum].open_time,sizeof(t)) == 0) + && pid==(int)getpid()) del = True; if (del) { DEBUG(2,("Deleting share mode record\n")); if(prev_p == scanner_p) - shm_set_userdef_off(scanner_p->next_offset); + smb_shm_set_userdef_off(scanner_p->next_offset); else prev_p->next_offset = scanner_p->next_offset; - shm_free(shm_addr2offset(scanner_p)); + smb_shm_free(smb_shm_addr2offset(scanner_p)); } - shm_unlock(); + smb_shm_unlock(); return; #else @@ -418,30 +420,31 @@ BOOL set_share_mode(int fnum,int mode) #if FAST_SHARE_MODES int pid = (int)getpid(); struct stat st; - shm_offset_t new_off; + smb_shm_offset_t new_off; share_mode_record *new_p; - if (fstat(Files[fnum].fd,&st) != 0) return(False); + if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return(False); - if (!shm_lock()) return (False); - new_off = shm_alloc(sizeof(share_mode_record) + strlen(Files[fnum].name) ); + if (!smb_shm_lock()) return (False); + new_off = smb_shm_alloc(sizeof(share_mode_record) + strlen(Files[fnum].name) ); if (new_off == NULL_OFFSET) return (False); - new_p = (share_mode_record *)shm_offset2addr(new_off); + new_p = (share_mode_record *)smb_shm_offset2addr(new_off); new_p->locking_version = LOCKING_VERSION; new_p->share_mode = mode; - new_p->time = Files[fnum].open_time; + new_p->time.tv_sec = Files[fnum].open_time.tv_sec; + new_p->time.tv_usec = Files[fnum].open_time.tv_usec; new_p->pid = pid; new_p->st_dev = st.st_dev; new_p->st_ino = st.st_ino; strcpy(new_p->file_name,Files[fnum].name); - new_p->next_offset = shm_get_userdef_off(); - shm_set_userdef_off(new_off); + new_p->next_offset = smb_shm_get_userdef_off(); + smb_shm_set_userdef_off(new_off); DEBUG(3,("Created share record for %s with mode 0x%X pid=%d\n",Files[fnum].name,mode,pid)); - if (!shm_unlock()) return (False); + if (!smb_shm_unlock()) return (False); return(True); #else @@ -496,9 +499,9 @@ void clean_share_modes(void) share_mode_record *prev_p; int pid; - if (!shm_lock()) return; + if (!smb_shm_lock()) return; - scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off()); + scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off()); prev_p = scanner_p; while(scanner_p) { @@ -509,28 +512,28 @@ void clean_share_modes(void) DEBUG(2,("Deleting stale share mode record")); if(prev_p == scanner_p) { - shm_set_userdef_off(scanner_p->next_offset); - shm_free(shm_addr2offset(scanner_p)); - scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off()); + smb_shm_set_userdef_off(scanner_p->next_offset); + smb_shm_free(smb_shm_addr2offset(scanner_p)); + scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off()); prev_p = scanner_p; } else { prev_p->next_offset = scanner_p->next_offset; - shm_free(shm_addr2offset(scanner_p)); - scanner_p = (share_mode_record *)shm_offset2addr(prev_p->next_offset); + smb_shm_free(smb_shm_addr2offset(scanner_p)); + scanner_p = (share_mode_record *)smb_shm_offset2addr(prev_p->next_offset); } } else { prev_p = scanner_p ; - scanner_p = (share_mode_record *)shm_offset2addr(scanner_p->next_offset); + scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset); } } - shm_unlock(); + smb_shm_unlock(); return; #else diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index e17cf1aa8d..9f7b985e67 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -29,68 +29,68 @@ extern int DEBUGLEVEL; -#define SHM_MAGIC 0x53484100 +#define SMB_SHM_MAGIC 0x53484100 /* = "SHM" in hex */ -#define SHM_VERSION 1 +#define SMB_SHM_VERSION 1 /* WARNING : offsets are used because mmap() does not guarantee that all processes have the shared memory mapped to the same address */ -struct ShmHeader +struct SmbShmHeader { - int shm_magic; - int shm_version; + int smb_shm_magic; + int smb_shm_version; int total_size; /* in bytes */ BOOL consistent; - shm_offset_t first_free_off; - shm_offset_t userdef_off; /* a userdefined offset. can be used to store root of tree or list */ - struct { /* a cell is a range of bytes of sizeof(struct ShmBlockDesc) size */ + smb_shm_offset_t first_free_off; + smb_shm_offset_t userdef_off; /* a userdefined offset. can be used to store root of tree or list */ + struct { /* a cell is a range of bytes of sizeof(struct SmbShmBlockDesc) size */ int cells_free; int cells_used; int cells_system; /* number of cells used as allocated block descriptors */ } statistics; }; -#define SHM_NOT_FREE_OFF (-1) -struct ShmBlockDesc +#define SMB_SHM_NOT_FREE_OFF (-1) +struct SmbShmBlockDesc { - shm_offset_t next; /* offset of next block in the free list or SHM_NOT_FREE_OFF when block in use */ + smb_shm_offset_t next; /* offset of next block in the free list or SMB_SHM_NOT_FREE_OFF when block in use */ int size; /* user size in BlockDescSize units */ }; -#define EOList_Addr (struct ShmBlockDesc *)( 0 ) +#define EOList_Addr (struct SmbShmBlockDesc *)( 0 ) #define EOList_Off (NULL_OFFSET) -#define CellSize sizeof(struct ShmBlockDesc) +#define CellSize sizeof(struct SmbShmBlockDesc) /* HeaderSize aligned on 8 byte boundary */ -#define AlignedHeaderSize ((sizeof(struct ShmHeader)+7) & ~7) +#define AlignedHeaderSize ((sizeof(struct SmbShmHeader)+7) & ~7) -static int shm_fd = -1; -static pstring shm_processreg_name = ""; +static int smb_shm_fd = -1; +static pstring smb_shm_processreg_name = ""; -static struct ShmHeader *shm_header_p = (struct ShmHeader *)0; -static int shm_times_locked = 0; +static struct SmbShmHeader *smb_shm_header_p = (struct SmbShmHeader *)0; +static int smb_shm_times_locked = 0; -static BOOL shm_register_process(char *processreg_file, pid_t pid, BOOL *other_processes) +static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *other_processes) { - int shm_processes_fd = -1; + int smb_shm_processes_fd = -1; int nb_read; pid_t other_pid; int free_slot = -1; int erased_slot; - shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0666); - if ( shm_processes_fd < 0 ) + smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0666); + if ( smb_shm_processes_fd < 0 ) { - DEBUG(0,("ERROR shm_register_process : processreg_file open failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_register_process : processreg_file open failed with code %d\n",errno)); return False; } *other_processes = False; - while ((nb_read = read(shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) + while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) { if(other_pid) { @@ -99,46 +99,46 @@ static BOOL shm_register_process(char *processreg_file, pid_t pid, BOOL *other_p else { /* erase old pid */ - DEBUG(2,("shm_register_process : erasing stale record for pid %d\n",other_pid)); + DEBUG(2,("smb_shm_register_process : erasing stale record for pid %d\n",other_pid)); other_pid = (pid_t)0; - erased_slot = lseek(shm_processes_fd, -sizeof(other_pid), SEEK_CUR); - write(shm_processes_fd, &other_pid, sizeof(other_pid)); + erased_slot = lseek(smb_shm_processes_fd, -sizeof(other_pid), SEEK_CUR); + write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)); if(free_slot < 0) free_slot = erased_slot; } } else if(free_slot < 0) - free_slot = lseek(shm_processes_fd, -sizeof(other_pid), SEEK_CUR); + free_slot = lseek(smb_shm_processes_fd, -sizeof(other_pid), SEEK_CUR); } if (nb_read < 0) { - DEBUG(0,("ERROR shm_register_process : processreg_file read failed with code %d\n",errno)); - close(shm_processes_fd); + DEBUG(0,("ERROR smb_shm_register_process : processreg_file read failed with code %d\n",errno)); + close(smb_shm_processes_fd); return False; } if(free_slot < 0) - free_slot = lseek(shm_processes_fd, 0, SEEK_END); + free_slot = lseek(smb_shm_processes_fd, 0, SEEK_END); - DEBUG(2,("shm_register_process : writing record for pid %d at offset %d\n",pid,free_slot)); - lseek(shm_processes_fd, free_slot, SEEK_SET); - if(write(shm_processes_fd, &pid, sizeof(pid)) < 0) + DEBUG(2,("smb_shm_register_process : writing record for pid %d at offset %d\n",pid,free_slot)); + lseek(smb_shm_processes_fd, free_slot, SEEK_SET); + if(write(smb_shm_processes_fd, &pid, sizeof(pid)) < 0) { - DEBUG(0,("ERROR shm_register_process : processreg_file write failed with code %d\n",errno)); - close(shm_processes_fd); + DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %d\n",errno)); + close(smb_shm_processes_fd); return False; } - close(shm_processes_fd); + close(smb_shm_processes_fd); return True; } -static BOOL shm_unregister_process(char *processreg_file, pid_t pid) +static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) { int old_umask; - int shm_processes_fd = -1; + int smb_shm_processes_fd = -1; int nb_read; pid_t other_pid; int erased_slot; @@ -146,26 +146,26 @@ static BOOL shm_unregister_process(char *processreg_file, pid_t pid) old_umask = umask(0); - shm_processes_fd = open(processreg_file, O_RDWR); + smb_shm_processes_fd = open(processreg_file, O_RDWR); umask(old_umask); - if ( shm_processes_fd < 0 ) + if ( smb_shm_processes_fd < 0 ) { - DEBUG(0,("ERROR shm_unregister_process : processreg_file open failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file open failed with code %d\n",errno)); return False; } - while ((nb_read = read(shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) + while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) { if(other_pid == pid) { /* erase pid */ - DEBUG(2,("shm_unregister_process : erasing record for pid %d\n",other_pid)); + DEBUG(2,("smb_shm_unregister_process : erasing record for pid %d\n",other_pid)); other_pid = (pid_t)0; - erased_slot = lseek(shm_processes_fd, -sizeof(other_pid), SEEK_CUR); - if(write(shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) + erased_slot = lseek(smb_shm_processes_fd, -sizeof(other_pid), SEEK_CUR); + if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) { - DEBUG(0,("ERROR shm_unregister_process : processreg_file write failed with code %d\n",errno)); - close(shm_processes_fd); + DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %d\n",errno)); + close(smb_shm_processes_fd); return False; } @@ -175,146 +175,146 @@ static BOOL shm_unregister_process(char *processreg_file, pid_t pid) } if (nb_read < 0) { - DEBUG(0,("ERROR shm_unregister_process : processreg_file read failed with code %d\n",errno)); - close(shm_processes_fd); + DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file read failed with code %d\n",errno)); + close(smb_shm_processes_fd); return False; } if(!found) { - DEBUG(0,("ERROR shm_unregister_process : couldn't find pid %d in file %s\n",pid,processreg_file)); - close(shm_processes_fd); + DEBUG(0,("ERROR smb_shm_unregister_process : couldn't find pid %d in file %s\n",pid,processreg_file)); + close(smb_shm_processes_fd); return False; } - close(shm_processes_fd); + close(smb_shm_processes_fd); return True; } -static BOOL shm_validate_header(int size) +static BOOL smb_shm_validate_header(int size) { - if( !shm_header_p ) + if( !smb_shm_header_p ) { /* not mapped yet */ - DEBUG(0,("ERROR shm_validate_header : shmem not mapped\n")); + DEBUG(0,("ERROR smb_shm_validate_header : shmem not mapped\n")); return False; } - if(shm_header_p->shm_magic != SHM_MAGIC) + if(smb_shm_header_p->smb_shm_magic != SMB_SHM_MAGIC) { - DEBUG(0,("ERROR shm_validate_header : bad magic\n")); + DEBUG(0,("ERROR smb_shm_validate_header : bad magic\n")); return False; } - if(shm_header_p->shm_version != SHM_VERSION) + if(smb_shm_header_p->smb_shm_version != SMB_SHM_VERSION) { - DEBUG(0,("ERROR shm_validate_header : bad version %X\n",shm_header_p->shm_version)); + DEBUG(0,("ERROR smb_shm_validate_header : bad version %X\n",smb_shm_header_p->smb_shm_version)); return False; } - if(shm_header_p->total_size != size) + if(smb_shm_header_p->total_size != size) { - DEBUG(0,("ERROR shm_validate_header : shmem size mismatch (old = %d, new = %d)\n",shm_header_p->total_size,size)); + DEBUG(0,("ERROR smb_shm_validate_header : shmem size mismatch (old = %d, new = %d)\n",smb_shm_header_p->total_size,size)); return False; } - if(!shm_header_p->consistent) + if(!smb_shm_header_p->consistent) { - DEBUG(0,("ERROR shm_validate_header : shmem not consistent\n")); + DEBUG(0,("ERROR smb_shm_validate_header : shmem not consistent\n")); return False; } return True; } -static BOOL shm_initialize(int size) +static BOOL smb_shm_initialize(int size) { - struct ShmBlockDesc * first_free_block_p; + struct SmbShmBlockDesc * first_free_block_p; - DEBUG(2,("shm_initialize : initializing shmem file of size %d\n",size)); + DEBUG(2,("smb_shm_initialize : initializing shmem file of size %d\n",size)); - if( !shm_header_p ) + if( !smb_shm_header_p ) { /* not mapped yet */ - DEBUG(0,("ERROR shm_initialize : shmem not mapped\n")); + DEBUG(0,("ERROR smb_shm_initialize : shmem not mapped\n")); return False; } - shm_header_p->shm_magic = SHM_MAGIC; - shm_header_p->shm_version = SHM_VERSION; - shm_header_p->total_size = size; - shm_header_p->first_free_off = AlignedHeaderSize; - shm_header_p->userdef_off = NULL_OFFSET; + smb_shm_header_p->smb_shm_magic = SMB_SHM_MAGIC; + smb_shm_header_p->smb_shm_version = SMB_SHM_VERSION; + smb_shm_header_p->total_size = size; + smb_shm_header_p->first_free_off = AlignedHeaderSize; + smb_shm_header_p->userdef_off = NULL_OFFSET; - first_free_block_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); + first_free_block_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); first_free_block_p->next = EOList_Off; first_free_block_p->size = ( size - AlignedHeaderSize - CellSize ) / CellSize ; - shm_header_p->statistics.cells_free = first_free_block_p->size; - shm_header_p->statistics.cells_used = 0; - shm_header_p->statistics.cells_system = 1; + smb_shm_header_p->statistics.cells_free = first_free_block_p->size; + smb_shm_header_p->statistics.cells_used = 0; + smb_shm_header_p->statistics.cells_system = 1; - shm_header_p->consistent = True; + smb_shm_header_p->consistent = True; return True; } -static void shm_solve_neighbors(struct ShmBlockDesc *head_p ) +static void smb_shm_solve_neighbors(struct SmbShmBlockDesc *head_p ) { - struct ShmBlockDesc *next_p; + struct SmbShmBlockDesc *next_p; /* Check if head_p and head_p->next are neighbors and if so join them */ if ( head_p == EOList_Addr ) return ; if ( head_p->next == EOList_Off ) return ; - next_p = (struct ShmBlockDesc *)shm_offset2addr(head_p->next); + next_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(head_p->next); if ( ( head_p + head_p->size + 1 ) == next_p) { head_p->size += next_p->size +1 ; /* adapt size */ head_p->next = next_p->next ; /* link out */ - shm_header_p->statistics.cells_free += 1; - shm_header_p->statistics.cells_system -= 1; + smb_shm_header_p->statistics.cells_free += 1; + smb_shm_header_p->statistics.cells_system -= 1; } } -BOOL shm_open( char *file_name, int size) +BOOL smb_shm_open( char *file_name, int size) { int filesize; BOOL created_new = False; BOOL other_processes = True; int old_umask; - DEBUG(2,("shm_open : using shmem file %s to be of size %d\n",file_name,size)); + DEBUG(2,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); old_umask = umask(0); - shm_fd = open(file_name, O_RDWR | O_CREAT, 0666); + smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0666); umask(old_umask); - if ( shm_fd < 0 ) + if ( smb_shm_fd < 0 ) { - DEBUG(0,("ERROR shm_open : open failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_open : open failed with code %d\n",errno)); return False; } - if (!shm_lock()) + if (!smb_shm_lock()) { - DEBUG(0,("ERROR shm_open : can't do shm_lock\n")); + DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_lock\n")); return False; } - if( (filesize = lseek(shm_fd, 0, SEEK_END)) < 0) + if( (filesize = lseek(smb_shm_fd, 0, SEEK_END)) < 0) { - DEBUG(0,("ERROR shm_open : lseek failed with code %d\n",errno)); - shm_unlock(); - close(shm_fd); + DEBUG(0,("ERROR smb_shm_open : lseek failed with code %d\n",errno)); + smb_shm_unlock(); + close(smb_shm_fd); return False; } /* return the file offset to 0 to save on later seeks */ - lseek(shm_fd,0,SEEK_SET); + lseek(smb_shm_fd,0,SEEK_SET); if (filesize == 0) { @@ -327,30 +327,30 @@ BOOL shm_open( char *file_name, int size) */ /* construct processreg file name */ - strcpy(shm_processreg_name, file_name); - strcat(shm_processreg_name, ".processes"); + strcpy(smb_shm_processreg_name, file_name); + strcat(smb_shm_processreg_name, ".processes"); - if (! shm_register_process(shm_processreg_name, getpid(), &other_processes)) + if (! smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes)) { - shm_unlock(); - close(shm_fd); + smb_shm_unlock(); + close(smb_shm_fd); return False; } if (created_new || !other_processes) { /* we just created a new one, or are the first opener, lets set it size */ - if( ftruncate(shm_fd, size) <0) + if( ftruncate(smb_shm_fd, size) <0) { - DEBUG(0,("ERROR shm_open : ftruncate failed with code %d\n",errno)); - shm_unregister_process(shm_processreg_name, getpid()); - shm_unlock(); - close(shm_fd); + DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %d\n",errno)); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); + smb_shm_unlock(); + close(smb_shm_fd); return False; } /* paranoia */ - lseek(shm_fd,0,SEEK_SET); + lseek(smb_shm_fd,0,SEEK_SET); filesize = size; } @@ -359,88 +359,88 @@ BOOL shm_open( char *file_name, int size) { /* the existing file has a different size and we are not the first opener. Since another process is still using it, we will use the file size */ - DEBUG(0,("WARNING shm_open : filesize (%d) != expected size (%d), using filesize\n",filesize,size)); + DEBUG(0,("WARNING smb_shm_open : filesize (%d) != expected size (%d), using filesize\n",filesize,size)); size = filesize; } - shm_header_p = (struct ShmHeader *)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, shm_fd, 0); - /* WARNING, shm_header_p can be different for different processes mapping the same file ! */ - if (shm_header_p == (struct ShmHeader *)(-1)) + smb_shm_header_p = (struct SmbShmHeader *)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, smb_shm_fd, 0); + /* WARNING, smb_shm_header_p can be different for different processes mapping the same file ! */ + if (smb_shm_header_p == (struct SmbShmHeader *)(-1)) { - DEBUG(0,("ERROR shm_open : mmap failed with code %d\n",errno)); - shm_unregister_process(shm_processreg_name, getpid()); - shm_unlock(); - close(shm_fd); + DEBUG(0,("ERROR smb_shm_open : mmap failed with code %d\n",errno)); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); + smb_shm_unlock(); + close(smb_shm_fd); return False; } if (created_new || !other_processes) { - shm_initialize(size); + smb_shm_initialize(size); } - else if (!shm_validate_header(size) ) + else if (!smb_shm_validate_header(size) ) { /* existing file is corrupt, samba admin should remove it by hand */ - DEBUG(0,("ERROR shm_open : corrupt shared mem file, remove it manually\n")); - munmap((caddr_t)shm_header_p, size); - shm_unregister_process(shm_processreg_name, getpid()); - shm_unlock(); - close(shm_fd); + DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n")); + munmap((caddr_t)smb_shm_header_p, size); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); + smb_shm_unlock(); + close(smb_shm_fd); return False; } - shm_unlock(); + smb_shm_unlock(); return True; } -BOOL shm_close( void ) +BOOL smb_shm_close( void ) { - DEBUG(2,("shm_close\n")); - if(shm_times_locked > 0) - DEBUG(0,("WARNING shm_close : shmem was still locked %d times\n",shm_times_locked));; - if ( munmap((caddr_t)shm_header_p, shm_header_p->total_size) < 0) + DEBUG(2,("smb_shm_close\n")); + if(smb_shm_times_locked > 0) + DEBUG(0,("WARNING smb_shm_close : shmem was still locked %d times\n",smb_shm_times_locked));; + if ( munmap((caddr_t)smb_shm_header_p, smb_shm_header_p->total_size) < 0) { - DEBUG(0,("ERROR shm_close : munmap failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_close : munmap failed with code %d\n",errno)); } - shm_lock(); - shm_unregister_process(shm_processreg_name, getpid()); - shm_unlock(); + smb_shm_lock(); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); + smb_shm_unlock(); - close(shm_fd); + close(smb_shm_fd); - shm_fd = -1; - shm_processreg_name[0] = '\0'; + smb_shm_fd = -1; + smb_shm_processreg_name[0] = '\0'; - shm_header_p = (struct ShmHeader *)0; - shm_times_locked = 0; + smb_shm_header_p = (struct SmbShmHeader *)0; + smb_shm_times_locked = 0; return True; } -shm_offset_t shm_alloc(int size) +smb_shm_offset_t smb_shm_alloc(int size) { unsigned num_cells ; - struct ShmBlockDesc *scanner_p; - struct ShmBlockDesc *prev_p; - struct ShmBlockDesc *new_p; - shm_offset_t result_offset; + struct SmbShmBlockDesc *scanner_p; + struct SmbShmBlockDesc *prev_p; + struct SmbShmBlockDesc *new_p; + smb_shm_offset_t result_offset; - if( !shm_header_p ) + if( !smb_shm_header_p ) { /* not mapped yet */ - DEBUG(0,("ERROR shm_alloc : shmem not mapped\n")); + DEBUG(0,("ERROR smb_shm_alloc : shmem not mapped\n")); return NULL_OFFSET; } - if( !shm_header_p->consistent) + if( !smb_shm_header_p->consistent) { - DEBUG(0,("ERROR shm_alloc : shmem not consistent\n")); + DEBUG(0,("ERROR smb_shm_alloc : shmem not consistent\n")); return NULL_OFFSET; } @@ -449,25 +449,25 @@ shm_offset_t shm_alloc(int size) num_cells = (size + CellSize -1) / CellSize; /* set start of scan */ - prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); + prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); scanner_p = prev_p ; /* scan the free list to find a matching free space */ while ( ( scanner_p != EOList_Addr ) && ( scanner_p->size < num_cells ) ) { prev_p = scanner_p; - scanner_p = (struct ShmBlockDesc *)shm_offset2addr(scanner_p->next); + scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next); } /* at this point scanner point to a block header or to the end of the list */ if ( scanner_p == EOList_Addr ) { - DEBUG(0,("ERROR shm_alloc : alloc of %d bytes failed, no free space found\n",size)); + DEBUG(0,("ERROR smb_shm_alloc : alloc of %d bytes failed, no free space found\n",size)); return (NULL_OFFSET); } /* going to modify shared mem */ - shm_header_p->consistent = False; + smb_shm_header_p->consistent = False; /* if we found a good one : scanner == the good one */ if ( scanner_p->size <= num_cells + 2 ) @@ -477,14 +477,14 @@ shm_offset_t shm_alloc(int size) */ if ( prev_p == scanner_p ) { - shm_header_p->first_free_off = scanner_p->next ; + smb_shm_header_p->first_free_off = scanner_p->next ; } else { prev_p->next = scanner_p->next ; } - shm_header_p->statistics.cells_free -= scanner_p->size; - shm_header_p->statistics.cells_used += scanner_p->size; + smb_shm_header_p->statistics.cells_free -= scanner_p->size; + smb_shm_header_p->statistics.cells_used += scanner_p->size; } else { @@ -493,166 +493,166 @@ shm_offset_t shm_alloc(int size) new_p->size = scanner_p->size - num_cells - 1; new_p->next = scanner_p->next; scanner_p->size = num_cells; - scanner_p->next = shm_addr2offset(new_p); + scanner_p->next = smb_shm_addr2offset(new_p); if ( prev_p != scanner_p ) { - prev_p->next = shm_addr2offset(new_p) ; + prev_p->next = smb_shm_addr2offset(new_p) ; } else { - shm_header_p->first_free_off = shm_addr2offset(new_p) ; + smb_shm_header_p->first_free_off = smb_shm_addr2offset(new_p) ; } - shm_header_p->statistics.cells_free -= num_cells+1; - shm_header_p->statistics.cells_used += num_cells; - shm_header_p->statistics.cells_system += 1; + smb_shm_header_p->statistics.cells_free -= num_cells+1; + smb_shm_header_p->statistics.cells_used += num_cells; + smb_shm_header_p->statistics.cells_system += 1; } - result_offset = shm_addr2offset( &(scanner_p[1]) ); - scanner_p->next = SHM_NOT_FREE_OFF ; + result_offset = smb_shm_addr2offset( &(scanner_p[1]) ); + scanner_p->next = SMB_SHM_NOT_FREE_OFF ; /* end modification of shared mem */ - shm_header_p->consistent = True; + smb_shm_header_p->consistent = True; - DEBUG(2,("shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); + DEBUG(2,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); return ( result_offset ); } -BOOL shm_free(shm_offset_t offset) +BOOL smb_shm_free(smb_shm_offset_t offset) { - struct ShmBlockDesc *header_p ; /* pointer to header of block to free */ - struct ShmBlockDesc *scanner_p ; /* used to scan the list */ - struct ShmBlockDesc *prev_p ; /* holds previous in the list */ + struct SmbShmBlockDesc *header_p ; /* pointer to header of block to free */ + struct SmbShmBlockDesc *scanner_p ; /* used to scan the list */ + struct SmbShmBlockDesc *prev_p ; /* holds previous in the list */ - if( !shm_header_p ) + if( !smb_shm_header_p ) { /* not mapped yet */ - DEBUG(0,("ERROR shm_free : shmem not mapped\n")); + DEBUG(0,("ERROR smb_shm_free : shmem not mapped\n")); return False; } - if( !shm_header_p->consistent) + if( !smb_shm_header_p->consistent) { - DEBUG(0,("ERROR shm_free : shmem not consistent\n")); + DEBUG(0,("ERROR smb_shm_free : shmem not consistent\n")); return False; } - header_p = ( (struct ShmBlockDesc *)shm_offset2addr(offset) - 1); /* make pointer to header of block */ + header_p = ( (struct SmbShmBlockDesc *)smb_shm_offset2addr(offset) - 1); /* make pointer to header of block */ - if (header_p->next != SHM_NOT_FREE_OFF) + if (header_p->next != SMB_SHM_NOT_FREE_OFF) { - DEBUG(0,("ERROR shm_free : bad offset (%d)\n",offset)); + DEBUG(0,("ERROR smb_shm_free : bad offset (%d)\n",offset)); return False; } /* find a place in the free_list to put the header in */ /* set scanner and previous pointer to start of list */ - prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); + prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); scanner_p = prev_p ; while ( ( scanner_p != EOList_Addr) && (scanner_p < header_p) ) /* while we didn't scan past its position */ { prev_p = scanner_p ; - scanner_p = (struct ShmBlockDesc *)shm_offset2addr(scanner_p->next); + scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next); } - shm_header_p->consistent = False; + smb_shm_header_p->consistent = False; - DEBUG(2,("shm_free : freeing %d bytes at offset %d\n",header_p->size*CellSize,offset)); + DEBUG(2,("smb_shm_free : freeing %d bytes at offset %d\n",header_p->size*CellSize,offset)); if ( scanner_p == prev_p ) { - shm_header_p->statistics.cells_free += header_p->size; - shm_header_p->statistics.cells_used -= header_p->size; + smb_shm_header_p->statistics.cells_free += header_p->size; + smb_shm_header_p->statistics.cells_used -= header_p->size; /* we must free it at the beginning of the list */ - shm_header_p->first_free_off = shm_addr2offset(header_p); /* set the free_list_pointer to this block_header */ + smb_shm_header_p->first_free_off = smb_shm_addr2offset(header_p); /* set the free_list_pointer to this block_header */ /* scanner is the one that was first in the list */ - header_p->next = shm_addr2offset(scanner_p); - shm_solve_neighbors( header_p ); /* if neighbors then link them */ + header_p->next = smb_shm_addr2offset(scanner_p); + smb_shm_solve_neighbors( header_p ); /* if neighbors then link them */ - shm_header_p->consistent = True; + smb_shm_header_p->consistent = True; return True; } else { - shm_header_p->statistics.cells_free += header_p->size; - shm_header_p->statistics.cells_used -= header_p->size; + smb_shm_header_p->statistics.cells_free += header_p->size; + smb_shm_header_p->statistics.cells_used -= header_p->size; - prev_p->next = shm_addr2offset(header_p); - header_p->next = shm_addr2offset(scanner_p); - shm_solve_neighbors(header_p) ; - shm_solve_neighbors(prev_p) ; + prev_p->next = smb_shm_addr2offset(header_p); + header_p->next = smb_shm_addr2offset(scanner_p); + smb_shm_solve_neighbors(header_p) ; + smb_shm_solve_neighbors(prev_p) ; - shm_header_p->consistent = True; + smb_shm_header_p->consistent = True; return True; } } -shm_offset_t shm_get_userdef_off(void) +smb_shm_offset_t smb_shm_get_userdef_off(void) { - if (!shm_header_p) + if (!smb_shm_header_p) return NULL_OFFSET; else - return shm_header_p->userdef_off; + return smb_shm_header_p->userdef_off; } -BOOL shm_set_userdef_off(shm_offset_t userdef_off) +BOOL smb_shm_set_userdef_off(smb_shm_offset_t userdef_off) { - if (!shm_header_p) + if (!smb_shm_header_p) return False; else - shm_header_p->userdef_off = userdef_off; + smb_shm_header_p->userdef_off = userdef_off; return True; } -void * shm_offset2addr(shm_offset_t offset) +void * smb_shm_offset2addr(smb_shm_offset_t offset) { if (offset == NULL_OFFSET ) return (void *)(0); - if (!shm_header_p) + if (!smb_shm_header_p) return (void *)(0); - return (void *)((char *)shm_header_p + offset ); + return (void *)((char *)smb_shm_header_p + offset ); } -shm_offset_t shm_addr2offset(void *addr) +smb_shm_offset_t smb_shm_addr2offset(void *addr) { if (!addr) return NULL_OFFSET; - if (!shm_header_p) + if (!smb_shm_header_p) return NULL_OFFSET; - return (shm_offset_t)((char *)addr - (char *)shm_header_p); + return (smb_shm_offset_t)((char *)addr - (char *)smb_shm_header_p); } -BOOL shm_lock(void) +BOOL smb_shm_lock(void) { - if (shm_fd < 0) + if (smb_shm_fd < 0) { - DEBUG(0,("ERROR shm_lock : bad shm_fd (%d)\n",shm_fd)); + DEBUG(0,("ERROR smb_shm_lock : bad smb_shm_fd (%d)\n",smb_shm_fd)); return False; } - shm_times_locked++; + smb_shm_times_locked++; - if(shm_times_locked > 1) + if(smb_shm_times_locked > 1) { - DEBUG(2,("shm_lock : locked %d times\n",shm_times_locked)); + DEBUG(2,("smb_shm_lock : locked %d times\n",smb_shm_times_locked)); return True; } - if (lockf(shm_fd, F_LOCK, 0) < 0) + if (lockf(smb_shm_fd, F_LOCK, 0) < 0) { - DEBUG(0,("ERROR shm_lock : lockf failed with code %d\n",errno)); - shm_times_locked--; + DEBUG(0,("ERROR smb_shm_lock : lockf failed with code %d\n",errno)); + smb_shm_times_locked--; return False; } @@ -662,32 +662,32 @@ BOOL shm_lock(void) -BOOL shm_unlock(void) +BOOL smb_shm_unlock(void) { - if (shm_fd < 0) + if (smb_shm_fd < 0) { - DEBUG(0,("ERROR shm_unlock : bad shm_fd (%d)\n",shm_fd)); + DEBUG(0,("ERROR smb_shm_unlock : bad smb_shm_fd (%d)\n",smb_shm_fd)); return False; } - if(shm_times_locked == 0) + if(smb_shm_times_locked == 0) { - DEBUG(0,("ERROR shm_unlock : shmem not locked\n",shm_fd)); + DEBUG(0,("ERROR smb_shm_unlock : shmem not locked\n",smb_shm_fd)); return False; } - shm_times_locked--; + smb_shm_times_locked--; - if(shm_times_locked > 0) + if(smb_shm_times_locked > 0) { - DEBUG(2,("shm_unlock : still locked %d times\n",shm_times_locked)); + DEBUG(2,("smb_shm_unlock : still locked %d times\n",smb_shm_times_locked)); return True; } - if (lockf(shm_fd, F_ULOCK, 0) < 0) + if (lockf(smb_shm_fd, F_ULOCK, 0) < 0) { - DEBUG(0,("ERROR shm_unlock : lockf failed with code %d\n",errno)); - shm_times_locked++; + DEBUG(0,("ERROR smb_shm_unlock : lockf failed with code %d\n",errno)); + smb_shm_times_locked++; return False; } @@ -696,19 +696,19 @@ BOOL shm_unlock(void) } -BOOL shm_get_usage(int *bytes_free, +BOOL smb_shm_get_usage(int *bytes_free, int *bytes_used, int *bytes_overhead) { - if( !shm_header_p ) + if( !smb_shm_header_p ) { /* not mapped yet */ - DEBUG(0,("ERROR shm_free : shmem not mapped\n")); + DEBUG(0,("ERROR smb_shm_free : shmem not mapped\n")); return False; } - *bytes_free = shm_header_p->statistics.cells_free * CellSize; - *bytes_used = shm_header_p->statistics.cells_used * CellSize; - *bytes_overhead = shm_header_p->statistics.cells_system * CellSize + AlignedHeaderSize; + *bytes_free = smb_shm_header_p->statistics.cells_free * CellSize; + *bytes_used = smb_shm_header_p->statistics.cells_used * CellSize; + *bytes_overhead = smb_shm_header_p->statistics.cells_system * CellSize + AlignedHeaderSize; return True; } -- cgit From 0f1f0ceb9519368188f695e18e2341ccfd1b2d15 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 8 May 1997 01:14:17 +0000 Subject: 'The mother of all checkins' :-). Jeremy Allison (jallison@whistle.com) Wed May 7 1997: Update for 1.9.17alpha1 release - 'browsefix release' designed to make browsing across subnets work. byteorder.h: Updated copyright to 1997. charcnv.c: Updated copyright to 1997. charset.c Updated copyright to 1997. charset.h Updated copyright to 1997. client.c Updated copyright to 1997. clientutil.c Updated copyright to 1997. dir.c Updated copyright to 1997. fault.c Updated copyright to 1997. includes.h Updated copyright to 1997. interface.c Updated copyright to 1997. ipc.c Updated copyright to 1997. kanji.c Updated copyright to 1997. kanji.h Updated copyright to 1997. loadparm.c Updated copyright to 1997. locking.c Updated copyright to 1997. mangle.c Updated copyright to 1997. message.c Updated copyright to 1997. nameannounce.c Made use of WINS subnet explicit. Added reset_announce_timer() so announcement can be made immediately when we become a master. Expanded code to do sync with dmb. namebrowse.c Removed redundent checks for AM_MASTER in sync code. Made use of WINS subnet explicit. namedbname.c Made use of WINS subnet explicit. namedbresp.c Made use of WINS subnet explicit. namedbserver.c Made use of WINS subnet explicit. namedbsubnet.c Explicitly add workgroup to WINS subnet when we become a dmb. Made use of WINS subnet explicit. namedbwork.c Made use of WINS subnet explicit. Removed redundent check_work_servertype() function. nameelect.c Explicitly add workgroup to WINS subnet when we become a master browser. Made use of WINS subnet explicit. namelogon.c Updated copyright to 1997. namepacket.c Updated copyright to 1997. namequery.c Updated copyright to 1997. nameresp.c Made use of WINS subnet explicit. Made nmbd fail if configured as master browser and one exists already. nameserv.c Made use of WINS subnet explicit. Remove redundent logon server and domain master code. nameserv.h Add emumerate subnet macros. nameservreply.c Made use of WINS subnet explicit. nameservresp.c Updated copyright to 1997. namework.c Made use of WINS subnet explicit. Updated code to add sync browser entries to add subnet parameter. nmbd.c Added sanity check for misconfigured nmbd. nmblib.c Updated copyright to 1997. nmblookup.c Updated copyright to 1997. nmbsync.c Removed redundent AM_ANY_MASTER check. params.c Updated copyright to 1997. password.c Updated copyright to 1997. pipes.c Updated copyright to 1997. predict.c Updated copyright to 1997. printing.c Updated copyright to 1997. proto.h Changed protos for new nmbd code. quotas.c Updated copyright to 1997. replace.c Updated copyright to 1997. reply.c Updated copyright to 1997. server.c Updated copyright to 1997. shmem.c Updated copyright to 1997. smb.h Updated copyright to 1997. smbencrypt.c Updated copyright to 1997. smbpasswd.c Updated copyright to 1997. smbrun.c Updated copyright to 1997. status.c Updated copyright to 1997. system.c Updated copyright to 1997. testparm.c Updated copyright to 1997. testprns.c Updated copyright to 1997. time.c Updated copyright to 1997. trans2.c Updated copyright to 1997. trans2.h Updated copyright to 1997. uid.c Updated copyright to 1997. username.c Updated copyright to 1997. util.c Updated copyright to 1997. version.h Changed to 1.9.17alpha1. (This used to be commit cf23a155a1315f50d488794a2caf88402bf3e3e6) --- source3/locking/locking.c | 2 +- source3/locking/shmem.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index ce96aa01cf..7c23e5b3ca 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Locking functions - Copyright (C) Andrew Tridgell 1992-1996 + 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 diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 9f7b985e67..2c02982d04 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Shared memory functions - Copyright (C) Erik Devriendt 1996 + Copyright (C) Erik Devriendt 1996-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 -- cgit From aa864415c5183c948fe9ae221023d40265c38013 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 20 May 1997 00:32:51 +0000 Subject: dir.c: Fixed double slash issue. includes.h: Changed to ifdef FAST_SHARE_MODES. ipc.c: Changed lp_workgroup() to myworkgroup. loadparm.c: Added new shared mem parameters. Added Luke's fix. locking.c: Rewrite to do share modes better (both fast and slow modes). nameannounce.c: Changed lp_workgroup() to myworkgroup. Added Luke's fix. nameconf.c: Changed lp_workgroup() to myworkgroup. namedbname.c: Improved debug. namedbserver.c: Changed lp_workgroup() to myworkgroup. namedbsubnet.c: Added Luke's fix - rewritten somewhat. namedbwork.c: Changed lp_workgroup() to myworkgroup. nameelect.c: Added Luke's fix - rewritten somewhat. nameresp.c: Stoped shadowing global. nameserv.c: Added Luke's fix - Improved debug. nameservreply.c: Improved debug. namework.c: Changed lp_workgroup() to myworkgroup. nmbd.c: Added Luke's fix - Changed lp_workgroup() to myworkgroup. pipes.c: Changed lp_workgroup() to myworkgroup. proto.h: Added Luke's fix, added smb_shm_ proto's. reply.c: Changed lp_workgroup() to myworkgroup. server.c: Rewrite to do share modes better (both fast and slow modes). shmem.c: Rewrite to do share modes better (both fast and slow modes). smb.h: Rewrite to do share modes better (both fast and slow modes). status.c: Rewrite to do share modes better (both fast and slow modes). trans2.c: Fixed double slash issue. util.c: Tidied up, created myworkgroup. Jeremy Allison (jallison@whistle.com). (This used to be commit 2a1711eaaf08bb6776770cd3c96b3010f431a677) --- source3/locking/locking.c | 1323 +++++++++++++++++++++++++++++++++------------ source3/locking/shmem.c | 261 ++++++--- 2 files changed, 1184 insertions(+), 400 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 7c23e5b3ca..e63e347a26 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -22,6 +22,9 @@ 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. */ #include "includes.h" @@ -29,9 +32,6 @@ extern int DEBUGLEVEL; extern connection_struct Connections[]; extern files_struct Files[]; -pstring share_del_pending=""; - - /**************************************************************************** utility function called to see if a file region is locked ****************************************************************************/ @@ -100,7 +100,7 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * return True; /* Did unlock */ } -#if FAST_SHARE_MODES +#ifdef FAST_SHARE_MODES /******************************************************************* initialize the shared memory for share_mode management ******************************************************************/ @@ -114,7 +114,7 @@ BOOL start_share_mode_mgmt(void) trim_string(shmem_file_name,"","/"); if (!*shmem_file_name) return(False); strcat(shmem_file_name, "/SHARE_MEM_FILE"); - return smb_shm_open(shmem_file_name, SHMEM_SIZE); + return smb_shm_open(shmem_file_name, lp_shmem_size()); } @@ -126,459 +126,1118 @@ BOOL stop_share_mode_mgmt(void) return smb_shm_close(); } -#else - -/* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */ - -/******************************************************************* - name a share file - ******************************************************************/ -static BOOL share_name(int cnum,struct stat *st,char *name) -{ - strcpy(name,lp_lockdir()); - standard_sub(cnum,name); - trim_string(name,"","/"); - if (!*name) return(False); - name += strlen(name); - - sprintf(name,"/share.%d.%d",(int)st->st_dev,(int)st->st_ino); - return(True); -} - /******************************************************************* - use the fnum to get the share file name + lock a hash bucket entry in shared memory for share_mode management ******************************************************************/ -static BOOL share_name_fnum(int fnum,char *name) +BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok) { - struct stat st; - if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return(False); - return(share_name(Files[fnum].cnum,&st,name)); + return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode)); } -#endif - /******************************************************************* - get the share mode of a file using the fnum + unlock a hash bucket entry in shared memory for share_mode management ******************************************************************/ -int get_share_mode_by_fnum(int cnum,int fnum,int *pid) +BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token) { - struct stat sbuf; - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) == -1) return(0); - return(get_share_mode(cnum,&sbuf,pid)); + return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode)); } /******************************************************************* - get the share mode of a file using the files name - ******************************************************************/ -int get_share_mode_byname(int cnum,char *fname,int *pid) -{ - struct stat sbuf; - if (stat(fname,&sbuf) == -1) return(0); - return(get_share_mode(cnum,&sbuf,pid)); -} - - -/******************************************************************* -get the share mode of a file +get all share mode entries in shared memory for a dev/inode pair. ********************************************************************/ -int get_share_mode(int cnum,struct stat *sbuf,int *pid) +int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, + min_share_mode_entry **old_shares) { -#if FAST_SHARE_MODES - share_mode_record *scanner_p; - share_mode_record *prev_p; - int ret; + 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; + share_mode_entry *entry_scanner_p; + share_mode_entry *entry_prev_p; + int num_entries; + int num_entries_copied; BOOL found = False; + min_share_mode_entry *share_array = (min_share_mode_entry *)0; - *pid = 0; + *old_shares = 0; - if(!smb_shm_lock()) return (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() )); + abort(); + } - scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - prev_p = scanner_p; - while(scanner_p) + mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + + if(mode_array[hash_entry] == NULL_OFFSET) { - if( (scanner_p->st_dev == sbuf->st_dev) && (scanner_p->st_ino == sbuf->st_ino) ) + 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 { - prev_p = scanner_p ; - scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset); + file_prev_p = file_scanner_p ; + file_scanner_p = (share_mode_record *)smb_shm_offset2addr( + file_scanner_p->next_offset); } } if(!found) { - smb_shm_unlock(); + 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(scanner_p->locking_version != LOCKING_VERSION) + if(file_scanner_p->locking_version != LOCKING_VERSION) { - DEBUG(2,("Deleting old share mode record due to old locking version %d",scanner_p->locking_version)); - if(prev_p == scanner_p) - smb_shm_set_userdef_off(scanner_p->next_offset); + 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",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 - prev_p->next_offset = scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(scanner_p)); - *pid = 0; - - smb_shm_unlock(); + file_prev_p->next_offset = file_scanner_p->next_offset; + smb_shm_free(smb_shm_addr2offset(file_scanner_p)); return (0); } - - *pid = scanner_p->pid; - ret = scanner_p->share_mode; - if (*pid && !process_exists(*pid)) + /* Allocate the old_shares array */ + num_entries = file_scanner_p->num_share_mode_entries; + if(num_entries) { - ret = 0; - *pid = 0; + *old_shares = share_array = (min_share_mode_entry *) + malloc(num_entries * sizeof(min_share_mode_entry)); + if(*old_shares == 0) + { + DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n")); + return 0; + } } + + num_entries_copied = 0; - if (! *pid) + entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr( + file_scanner_p->share_mode_entries); + entry_prev_p = entry_scanner_p; + while(entry_scanner_p) { - if(prev_p == scanner_p) - smb_shm_set_userdef_off(scanner_p->next_offset); - else - prev_p->next_offset = scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(scanner_p)); + int pid = entry_scanner_p->pid; + + if (pid && !process_exists(pid)) + { + /* Delete this share mode entry */ + 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; + entry_scanner_p = (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 = (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)); + abort(); + } + + 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 (number of entries now = %d)\n", + pid, entry_scanner_p->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->pid; + share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode; + memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->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->share_mode, entry_scanner_p->pid)); + entry_prev_p = entry_scanner_p; + entry_scanner_p = (share_mode_entry *) + smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); + } } - if (*pid) - DEBUG(5,("Read share mode record mode 0x%X pid=%d\n",ret,*pid)); + /* 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)); + } - if(!smb_shm_unlock()) return (0); - - return(ret); - -#else - pstring fname; - int fd2; - char buf[20]; - int ret; - struct timeval t; + 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); +} - *pid = 0; +/******************************************************************* +del the share mode of a file. +********************************************************************/ +void del_share_mode(share_lock_token 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; + share_mode_entry *entry_scanner_p; + share_mode_entry *entry_prev_p; + BOOL found = False; + int pid = getpid(); - if (!share_name(cnum,sbuf,fname)) return(0); + dev = Files[fnum].fd_ptr->dev; + inode = Files[fnum].fd_ptr->inode; - fd2 = open(fname,O_RDONLY,0); - if (fd2 < 0) return(0); + hash_entry = HASH_ENTRY(dev, inode); - if (read(fd2,buf,20) != 20) { - DEBUG(2,("Failed to read share file %s\n",fname)); - close(fd2); - unlink(fname); - return(0); + 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() )); + abort(); } - close(fd2); - t.tv_sec = IVAL(buf,4); - t.tv_usec = IVAL(buf,8); - ret = IVAL(buf,12); - *pid = IVAL(buf,16); + 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)); + abort(); + } - if (IVAL(buf,0) != LOCKING_VERSION) { - if (!unlink(fname)) DEBUG(2,("Deleted old locking file %s",fname)); - *pid = 0; - return(0); - } + file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); + file_prev_p = file_scanner_p; - if (*pid && !process_exists(*pid)) { - ret=0; - *pid = 0; + 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; } - if (! *pid) unlink(fname); /* XXXXX race, race */ + found = False; + entry_scanner_p = (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->pid) && + (memcmp(&entry_scanner_p->time, + &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) + { + found = True; + break; + } + else + { + entry_prev_p = entry_scanner_p; + entry_scanner_p = (share_mode_entry *) + smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); + } + } - if (*pid) - DEBUG(5,("Read share file %s mode 0x%X pid=%d\n",fname,ret,*pid)); + 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)); + abort(); + } - return(ret); -#endif + /* 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)); + } } - /******************************************************************* -del the share mode of a file, if we set it last +set the share mode of a file. Return False on fail, True on success. ********************************************************************/ -void del_share_mode(int fnum) +BOOL set_share_mode(share_lock_token token, int fnum) { -#if FAST_SHARE_MODES - struct stat st; - struct timeval t; - int pid=0; - BOOL del = False; - share_mode_record *scanner_p; - share_mode_record *prev_p; + 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; + share_mode_entry *new_entry_p; + smb_shm_offset_t new_entry_offset; BOOL found = False; - t.tv_sec = t.tv_usec = 0; - - if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return; - - if (!smb_shm_lock()) return; + 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() )); + abort(); + } + + 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; - scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - prev_p = scanner_p; - while(scanner_p) + while(file_scanner_p) { - if( (scanner_p->st_dev == st.st_dev) && (scanner_p->st_ino == st.st_ino) ) + if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) { - found = True; - break; + found = True; + break; } else { - prev_p = scanner_p ; - scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset); + file_prev_p = file_scanner_p ; + file_scanner_p = (share_mode_record *) + smb_shm_offset2addr(file_scanner_p->next_offset); } } - + if(!found) { - smb_shm_unlock(); - return; + /* 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(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; } - - t.tv_sec = scanner_p->time.tv_sec; - t.tv_usec = scanner_p->time.tv_usec; - pid = scanner_p->pid; - - if( (scanner_p->locking_version != LOCKING_VERSION) || !pid || !process_exists(pid)) - del = True; - if (!del && (memcmp(&t,&Files[fnum].open_time,sizeof(t)) == 0) - && pid==(int)getpid()) - del = True; + new_entry_p = smb_shm_offset2addr(new_entry_offset); - if (del) + new_entry_p->pid = getpid(); + new_entry_p->share_mode = fs_p->share_mode; + memcpy( (char *)&new_entry_p->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(2,("Deleting share mode record\n")); - if(prev_p == scanner_p) - smb_shm_set_userdef_off(scanner_p->next_offset); - else - prev_p->next_offset = scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(scanner_p)); - + 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)); + abort(); } - smb_shm_unlock(); - return; + /* 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->pid, + file_scanner_p->num_share_mode_entries)); + + return(True); +} + +#else /* FAST_SHARE_MODES */ + +/* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */ -#else +/******************************************************************* + name a share file + ******************************************************************/ +static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) +{ + strcpy(name,lp_lockdir()); + standard_sub(cnum,name); + trim_string(name,"","/"); + if (!*name) return(False); + name += strlen(name); + + sprintf(name,"/share.%u.%u",dev,inode); + return(True); +} + +/******************************************************************* + lock a share mode file. + ******************************************************************/ +BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok) +{ pstring fname; - int fd2; - char buf[20]; - struct timeval t; - int pid=0; - BOOL del = False; - - t.tv_sec = t.tv_usec = 0; - if (!share_name_fnum(fnum,fname)) return; - - fd2 = open(fname,O_RDONLY,0); - if (fd2 < 0) return; - if (read(fd2,buf,20) != 20) - del = True; - close(fd2); - - if (!del) { - t.tv_sec = IVAL(buf,4); - t.tv_usec = IVAL(buf,8); - pid = IVAL(buf,16); - } - - if (!del) - if (IVAL(buf,0) != LOCKING_VERSION || !pid || !process_exists(pid)) - del = True; - - if (!del && (memcmp(&t,&Files[fnum].open_time,sizeof(t)) == 0) && (pid==(int)getpid())) - del = True; - - if (del) { - if (!unlink(fname)) - DEBUG(2,("Deleted share file %s\n",fname)); - else { - DEBUG(3,("Pending delete share file %s\n",fname)); - if (*share_del_pending) DEBUG(0,("Share del clash!\n")); - strcpy(share_del_pending,fname); + int fd; + + *ptok = (share_lock_token)-1; + + if(!share_name(cnum, dev, inode, fname)) + return False; + + { + int old_umask; + unbecome_user(); + old_umask = umask(0); +#ifdef SECURE_SHARE_MODES + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); +#else /* SECURE_SHARE_MODES */ + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0644); +#endif /* SECURE_SHARE_MODES */ + umask(old_umask); + if(!become_user(cnum,Connections[cnum].vuid)) + { + DEBUG(0,("lock_share_entry: Can't become connected user!\n")); + close(fd); + return False; + } + /* We need to change directory back to the connection root. */ + if (ChDir(Connections[cnum].connectpath) != 0) + { + DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n", + Connections[cnum].connectpath, strerror(errno))); + close(fd); + return False; } } -#endif + + /* At this point we have an open fd to the share mode file. + Lock the first byte exclusively to signify a lock. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) + { + DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n", + strerror(errno))); + close(fd); + return False; + } + + *ptok = (share_lock_token)fd; + return True; } - /******************************************************************* -set the share mode of a file + unlock a share mode file. + ******************************************************************/ +BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token) +{ + int fd = (int)token; + int ret = True; + + /* token is the fd of the open share mode file. */ + /* Unlock the first byte. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False) + { + DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", + strerror(errno))); + ret = False; + } + + close((int)token); + return ret; +} + +/******************************************************************* +Force a share file to be deleted. ********************************************************************/ -BOOL set_share_mode(int fnum,int mode) + +static int delete_share_file( int cnum, char *fname ) { -#if FAST_SHARE_MODES - int pid = (int)getpid(); - struct stat st; - smb_shm_offset_t new_off; - share_mode_record *new_p; + unbecome_user(); + if(unlink(fname) != 0) + { + DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", + fname, strerror(errno))); + } + + DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); + + if(!become_user(cnum,Connections[cnum].vuid)) + { + DEBUG(0,("delete_share_file: Can't become connected user!\n")); + return -1; + } + /* We need to change directory back to the connection root. */ + if (ChDir(Connections[cnum].connectpath) != 0) + { + DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n", + Connections[cnum].connectpath, strerror(errno))); + return -1; + } + return 0; +} + +/******************************************************************* +Read a share file into a buffer. +********************************************************************/ + +static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file) +{ + struct stat sb; + char *buf; + int size; + + *out = 0; + *p_new_file = False; + + if(fstat(fd, &sb) != 0) + { + DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", + fname, strerror(errno))); + return -1; + } + + if(sb.st_size == 0) + { + *p_new_file = True; + return 0; + } + + /* Allocate space for the file */ + if((buf = (char *)malloc(sb.st_size)) == NULL) + { + DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size)); + return -1; + } + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \ +for share file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return -1; + } - if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return(False); + if (read(fd,buf,sb.st_size) != sb.st_size) + { + DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n", + fname, strerror(errno))); + if(buf) + free(buf); + return -1; + } - if (!smb_shm_lock()) return (False); - new_off = smb_shm_alloc(sizeof(share_mode_record) + strlen(Files[fnum].name) ); - if (new_off == NULL_OFFSET) return (False); - new_p = (share_mode_record *)smb_shm_offset2addr(new_off); - new_p->locking_version = LOCKING_VERSION; - new_p->share_mode = mode; - new_p->time.tv_sec = Files[fnum].open_time.tv_sec; - new_p->time.tv_usec = Files[fnum].open_time.tv_usec; - new_p->pid = pid; - new_p->st_dev = st.st_dev; - new_p->st_ino = st.st_ino; - strcpy(new_p->file_name,Files[fnum].name); - new_p->next_offset = smb_shm_get_userdef_off(); - smb_shm_set_userdef_off(new_off); - - - DEBUG(3,("Created share record for %s with mode 0x%X pid=%d\n",Files[fnum].name,mode,pid)); - - if (!smb_shm_unlock()) return (False); - return(True); + if (IVAL(buf,0) != LOCKING_VERSION) { + DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ +locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION)); + if(buf) + free(buf); + delete_share_file(cnum, fname); + return -1; + } + + /* Sanity check for file contents */ + size = sb.st_size; + size -= 10; /* Remove the header */ + + /* Remove the filename component. */ + size -= SVAL(buf, 8); + + /* The remaining size must be a multiple of 16 - error if not. */ + if((size % 16) != 0) + { + DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \ +deleting it.\n", fname)); + if(buf) + free(buf); + delete_share_file(cnum, fname); + return -1; + } -#else + *out = buf; + return 0; +} + +/******************************************************************* +get all share mode entries in a share file for a dev/inode pair. +********************************************************************/ +int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, + min_share_mode_entry **old_shares) +{ + int fd = (int)token; pstring fname; - int fd2; - char buf[20]; - int pid = (int)getpid(); + int i; + int num_entries; + int num_entries_copied; + int newsize; + min_share_mode_entry *share_array; + char *buf = 0; + char *base = 0; + BOOL new_file; + + *old_shares = 0; + + /* Read the share file header - this is of the form: + 0 - locking version. + 4 - number of share mode entries. + 8 - 2 byte name length + [n bytes] file name (zero terminated). - if (!share_name_fnum(fnum,fname)) return(False); + Followed by share mode entries of the form : + 0 - tv_sec + 4 - tv_usec + 8 - share_mode + 12 - pid + + */ + + share_name(cnum, dev, inode, fname); + + if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0) { - int old_umask = umask(0); - fd2 = open(fname,O_WRONLY|O_CREAT|O_TRUNC,0644); - umask(old_umask); + DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n", + fname)); + return 0; } - if (fd2 < 0) { - DEBUG(2,("Failed to create share file %s\n",fname)); - return(False); + + if(new_file == True) + return 0; + + num_entries = IVAL(buf,4); + + DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n", + fname, num_entries)); + + /* PARANOIA TEST */ + if(num_entries < 0) + { + DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ +for share file %d\n", num_entries, fname)); + abort(); } - SIVAL(buf,0,LOCKING_VERSION); - SIVAL(buf,4,Files[fnum].open_time.tv_sec); - SIVAL(buf,8,Files[fnum].open_time.tv_usec); - SIVAL(buf,12,mode); - SIVAL(buf,16,pid); + if(num_entries) + { + *old_shares = share_array = (min_share_mode_entry *) + malloc(num_entries * sizeof(min_share_mode_entry)); + if(*old_shares == 0) + { + DEBUG(0,("get_share_modes: malloc fail !\n")); + return 0; + } + } + else + { + /* No entries - just delete the file. */ + DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n", + fname)); + if(buf) + free(buf); + delete_share_file(cnum, fname); + return 0; + } - if (write(fd2,buf,20) != 20) { - DEBUG(2,("Failed to write share file %s\n",fname)); - close(fd2); - unlink(fname); - return(False); + num_entries_copied = 0; + base = buf + 10 + SVAL(buf,8); + + for( i = 0; i < num_entries; i++) + { + int pid; + char *p = base + (i*16); + + pid = IVAL(p,12); + + if(!process_exists(pid)) + { + DEBUG(0,("get_share_modes: process %d no longer exists and \ +it left a share mode entry with mode 0x%X in share file %s\n", + pid, IVAL(p,8), fname)); + continue; + } + share_array[num_entries_copied].time.tv_sec = IVAL(p,0); + share_array[num_entries_copied].time.tv_usec = IVAL(p,4); + share_array[num_entries_copied].share_mode = IVAL(p,8); + share_array[num_entries_copied].pid = pid; + + num_entries_copied++; } - write(fd2,Files[fnum].name,strlen(Files[fnum].name)+1); + if(num_entries_copied == 0) + { + /* Delete the whole file. */ + DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n", + fname)); + if(*old_shares) + free((char *)old_shares); + if(buf) + free(buf); + delete_share_file(cnum, fname); + return 0; + } - close(fd2); + /* If we deleted some entries we need to re-write the whole number of + share mode entries back into the file. */ - DEBUG(3,("Created share file %s with mode 0x%X pid=%d\n",fname,mode,pid)); + if(num_entries_copied != num_entries) + { + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ +position 0 for share mode file %s (%s)\n", fname, strerror(errno))); + if(*old_shares) + free((char *)old_shares); + if(buf) + free(buf); + return 0; + } - return(True); -#endif + SIVAL(buf, 4, num_entries_copied); + for( i = 0; i < num_entries_copied; i++) + { + char *p = base + (i*16); + + SIVAL(p,12,share_array[i].pid); + SIVAL(p,8,share_array[i].share_mode); + SIVAL(p,0,share_array[i].time.tv_sec); + SIVAL(p,4,share_array[i].time.tv_usec); + } + + newsize = (base - buf) + (16*num_entries_copied); + if(write(fd, buf, newsize) != newsize) + { + DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ +mode file %s (%s)\n", fname, strerror(errno))); + if(*old_shares) + free((char *)old_shares); + if(buf) + free(buf); + return 0; + } + /* Now truncate the file at this point. */ + if(ftruncate(fd, newsize)!= 0) + { + DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ +mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); + if(*old_shares) + free((char *)old_shares); + if(buf) + free(buf); + return 0; + } + } + + if(buf) + free(buf); + + DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname, + num_entries_copied)); + + return num_entries_copied; } - /******************************************************************* -cleanup any stale share files +del a share mode from a share mode file. ********************************************************************/ -void clean_share_modes(void) +void del_share_mode(share_lock_token token, int fnum) { -#ifdef USE_SHMEM - share_mode_record *scanner_p; - share_mode_record *prev_p; + pstring fname; + int fd = (int)token; + char *buf = 0; + char *base = 0; + int num_entries; + int newsize; + int i; + files_struct *fs_p = &Files[fnum]; int pid; - - if (!smb_shm_lock()) return; - - scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - prev_p = scanner_p; - while(scanner_p) + BOOL deleted = False; + BOOL new_file; + + share_name(fs_p->cnum, fs_p->fd_ptr->dev, + fs_p->fd_ptr->inode, fname); + + if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) { - pid = scanner_p->pid; - - if( (scanner_p->locking_version != LOCKING_VERSION) || !process_exists(pid)) - { - DEBUG(2,("Deleting stale share mode record")); - if(prev_p == scanner_p) - { - smb_shm_set_userdef_off(scanner_p->next_offset); - smb_shm_free(smb_shm_addr2offset(scanner_p)); - scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - prev_p = scanner_p; - } - else - { - prev_p->next_offset = scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(scanner_p)); - scanner_p = (share_mode_record *)smb_shm_offset2addr(prev_p->next_offset); - } - - } - else - { - prev_p = scanner_p ; - scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset); - } + DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", + fname)); + return; } - - smb_shm_unlock(); - return; - -#else - char *lockdir = lp_lockdir(); - void *dir; - char *s; + if(new_file == True) + { + DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", + fname)); + delete_share_file(fs_p->cnum, fname); + return; + } - if (!*lockdir) return; + num_entries = IVAL(buf,4); - dir = opendir(lockdir); - if (!dir) return; + DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n", + fname, num_entries)); - while ((s=readdirname(dir))) { - char buf[20]; - int pid; - int fd; - pstring lname; - int dev,inode; + /* PARANOIA TEST */ + if(num_entries < 0) + { + DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ +for share file %d\n", num_entries, fname)); + abort(); + } - if (sscanf(s,"share.%d.%d",&dev,&inode)!=2) continue; + if(num_entries == 0) + { + /* No entries - just delete the file. */ + DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n", + fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return; + } - strcpy(lname,lp_lockdir()); - trim_string(lname,NULL,"/"); - strcat(lname,"/"); - strcat(lname,s); + pid = getpid(); - fd = open(lname,O_RDONLY,0); - if (fd < 0) continue; + /* Go through the entries looking for the particular one + we have set - delete it. + */ - if (read(fd,buf,20) != 20) { - close(fd); - if (!unlink(lname)) - printf("Deleted corrupt share file %s\n",s); + base = buf + 10 + SVAL(buf,8); + + for(i = 0; i < num_entries; i++) + { + char *p = base + (i*16); + + if((IVAL(p,0) != fs_p->open_time.tv_sec) || (IVAL(p,4) != fs_p->open_time.tv_usec) || + (IVAL(p,8) != fs_p->share_mode) || (IVAL(p,12) != pid)) continue; + + DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", + i, num_entries, fname)); + + /* Remove this entry. */ + if(i != num_entries - 1) + memcpy(p, p + 16, (num_entries - i - 1)*16); + + deleted = True; + break; + } + + if(!deleted) + { + DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname)); + if(buf) + free(buf); + return; + } + + num_entries--; + SIVAL(buf,4, num_entries); + + if(num_entries == 0) + { + /* Deleted the last entry - remove the file. */ + DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n", + fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum,fname); + return; + } + + /* Re-write the file - and truncate it at the correct point. */ + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ +position 0 for share mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return; } - close(fd); - pid = IVAL(buf,16); + newsize = (base - buf) + (16*num_entries); + if(write(fd, buf, newsize) != newsize) + { + DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ +mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return; + } + /* Now truncate the file at this point. */ + if(ftruncate(fd, newsize) != 0) + { + DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ +mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); + if(buf) + free(buf); + return; + } +} + +/******************************************************************* +set the share mode of a file +********************************************************************/ +BOOL set_share_mode(share_lock_token token,int fnum) +{ + files_struct *fs_p = &Files[fnum]; + pstring fname; + int fd = (int)token; + int pid = (int)getpid(); + struct stat sb; + char *buf; + int num_entries; + int header_size; + char *p; + + share_name(fs_p->cnum, fs_p->fd_ptr->dev, + fs_p->fd_ptr->inode, fname); + + if(fstat(fd, &sb) != 0) + { + DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", + fname)); + return False; + } - if (IVAL(buf,0) != LOCKING_VERSION || !process_exists(pid)) { - if (!unlink(lname)) - printf("Deleted stale share file %s\n",s); + /* Sanity check for file contents (if it's not a new share file). */ + if(sb.st_size != 0) + { + int size = sb.st_size; + + /* Allocate space for the file plus one extra entry */ + if((buf = (char *)malloc(sb.st_size + 16)) == NULL) + { + DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", sb.st_size + 16)); + return False; + } + + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: set_share_mode: Failed to reset position \ +to 0 for share file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; } + + if (read(fd,buf,sb.st_size) != sb.st_size) + { + DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n", + fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + if (IVAL(buf,0) != LOCKING_VERSION) + { + DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ +locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return False; + } + + size -= (10 + SVAL(buf, 8)); /* Remove the header */ + + /* The remaining size must be a multiple of 16 - error if not. */ + if((size % 16) != 0) + { + DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \ +deleting it.\n", fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return False; + } + } + else + { + /* New file - just use a single_entry. */ + if((buf = (char *)malloc(10 + strlen(fs_p->name) + 1 + 16)) == NULL) + { + DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); + return False; + } + SIVAL(buf,0,LOCKING_VERSION); + SIVAL(buf,4,0); + SSVAL(buf,8,strlen(fs_p->name) + 1); + strcpy(buf + 10, fs_p->name); + } + + num_entries = IVAL(buf,4); + header_size = 10 + SVAL(buf,8); + p = buf + header_size + (num_entries * 16); + SIVAL(p,0,fs_p->open_time.tv_sec); + SIVAL(p,4,fs_p->open_time.tv_usec); + SIVAL(p,8,fs_p->share_mode); + SIVAL(p,12,pid); + + num_entries++; + + SIVAL(buf,4,num_entries); + + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \ +0 for share file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + if (write(fd,buf,header_size + (num_entries*16)) != (header_size + (num_entries*16))) + { + DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ +deleting it (%s).\n",fname, strerror(errno))); + delete_share_file(fs_p->cnum, fname); + if(buf) + free(buf); + return False; + } + + /* Now truncate the file at this point - just for safety. */ + if(ftruncate(fd, header_size + (16*num_entries))!= 0) + { + DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ +mode file %s to size %d (%s)\n", fname, header_size + (16*num_entries), strerror(errno))); + if(buf) + free(buf); + return False; + } + + if(buf) + free(buf); + + DEBUG(3,("set_share_mode: Created share file %s with \ +mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid)); - closedir(dir); -#endif + return True; } +#endif /* FAST_SHARE_MODES */ diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 2c02982d04..9d4e62bdd7 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -23,7 +23,7 @@ #include "includes.h" -#if FAST_SHARE_MODES +#ifdef FAST_SHARE_MODES extern int DEBUGLEVEL; @@ -32,7 +32,7 @@ extern int DEBUGLEVEL; #define SMB_SHM_MAGIC 0x53484100 /* = "SHM" in hex */ -#define SMB_SHM_VERSION 1 +#define SMB_SHM_VERSION 2 /* WARNING : offsets are used because mmap() does not guarantee that all processes have the shared memory mapped to the same address */ @@ -73,15 +73,109 @@ static pstring smb_shm_processreg_name = ""; static struct SmbShmHeader *smb_shm_header_p = (struct SmbShmHeader *)0; static int smb_shm_times_locked = 0; +static BOOL smb_shm_initialize_called = False; + +static BOOL smb_shm_global_lock(void) +{ + if (smb_shm_fd < 0) + { + DEBUG(0,("ERROR smb_shm_global_lock : bad smb_shm_fd (%d)\n",smb_shm_fd)); + return False; + } + + smb_shm_times_locked++; + + if(smb_shm_times_locked > 1) + { + DEBUG(2,("smb_shm_global_lock : locked %d times\n",smb_shm_times_locked)); + return True; + } + + /* Do an exclusive wait lock on the first byte of the file */ + if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_WRLCK) == False) + { + DEBUG(0,("ERROR smb_shm_global_lock : fcntl_lock failed with code %d\n",errno)); + smb_shm_times_locked--; + return False; + } + + return True; + +} + +static BOOL smb_shm_global_unlock(void) +{ + if (smb_shm_fd < 0) + { + DEBUG(0,("ERROR smb_shm_global_unlock : bad smb_shm_fd (%d)\n",smb_shm_fd)); + return False; + } + + if(smb_shm_times_locked == 0) + { + DEBUG(0,("ERROR smb_shm_global_unlock : shmem not locked\n",smb_shm_fd)); + return False; + } + + smb_shm_times_locked--; + + if(smb_shm_times_locked > 0) + { + DEBUG(2,("smb_shm_global_unlock : still locked %d times\n",smb_shm_times_locked)); + return True; + } + + /* Do a wait unlock on the first byte of the file */ + if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_UNLCK) == False) + { + DEBUG(0,("ERROR smb_shm_global_unlock : fcntl_lock failed with code %d\n",errno)); + smb_shm_times_locked++; + return False; + } + + return True; + +} + +/* + * Function to create the hash table for the share mode entries. Called + * when smb shared memory is global locked. + */ + +BOOL smb_shm_create_hash_table( unsigned int size ) +{ + size *= sizeof(smb_shm_offset_t); + + smb_shm_global_lock(); + smb_shm_header_p->userdef_off = smb_shm_alloc( size ); + + if(smb_shm_header_p->userdef_off == NULL_OFFSET) + { + DEBUG(0,("smb_shm_create_hash_table: Failed to create hash table of size %d\n",size)); + smb_shm_global_unlock(); + return False; + } + + /* Clear hash buckets. */ + memset( smb_shm_offset2addr(smb_shm_header_p->userdef_off), '\0', size); + smb_shm_global_unlock(); + return True; +} + static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *other_processes) { int smb_shm_processes_fd = -1; int nb_read; pid_t other_pid; + int seek_back = -sizeof(other_pid); int free_slot = -1; int erased_slot; +#ifndef SECURE_SHARE_MODES smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0666); +#else /* SECURE_SHARE_MODES */ + smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0600); +#endif /* SECURE_SHARE_MODES */ if ( smb_shm_processes_fd < 0 ) { DEBUG(0,("ERROR smb_shm_register_process : processreg_file open failed with code %d\n",errno)); @@ -99,9 +193,10 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth else { /* erase old pid */ - DEBUG(2,("smb_shm_register_process : erasing stale record for pid %d\n",other_pid)); + DEBUG(2,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %d)\n", + other_pid, seek_back)); other_pid = (pid_t)0; - erased_slot = lseek(smb_shm_processes_fd, -sizeof(other_pid), SEEK_CUR); + erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)); if(free_slot < 0) free_slot = erased_slot; @@ -109,7 +204,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth } else if(free_slot < 0) - free_slot = lseek(smb_shm_processes_fd, -sizeof(other_pid), SEEK_CUR); + free_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); } if (nb_read < 0) { @@ -141,6 +236,7 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) int smb_shm_processes_fd = -1; int nb_read; pid_t other_pid; + int seek_back = -sizeof(other_pid); int erased_slot; BOOL found = False; @@ -156,12 +252,14 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) { + DEBUG(2,("smb_shm_unregister_process : read record for pid %d\n",other_pid)); if(other_pid == pid) { /* erase pid */ - DEBUG(2,("smb_shm_unregister_process : erasing record for pid %d\n",other_pid)); + DEBUG(2,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %d)\n", + other_pid, seek_back)); other_pid = (pid_t)0; - erased_slot = lseek(smb_shm_processes_fd, -sizeof(other_pid), SEEK_CUR); + erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) { DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %d\n",errno)); @@ -257,6 +355,8 @@ static BOOL smb_shm_initialize(int size) smb_shm_header_p->consistent = True; + smb_shm_initialize_called = True; + return True; } @@ -291,7 +391,11 @@ BOOL smb_shm_open( char *file_name, int size) DEBUG(2,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); old_umask = umask(0); +#ifndef SECURE_SHARE_MODES smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0666); +#else /* SECURE_SHARE_MODES */ + smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0600); +#endif /* SECURE_SHARE_MODE */ umask(old_umask); if ( smb_shm_fd < 0 ) { @@ -299,16 +403,16 @@ BOOL smb_shm_open( char *file_name, int size) return False; } - if (!smb_shm_lock()) + if (!smb_shm_global_lock()) { - DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_lock\n")); + DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n")); return False; } if( (filesize = lseek(smb_shm_fd, 0, SEEK_END)) < 0) { DEBUG(0,("ERROR smb_shm_open : lseek failed with code %d\n",errno)); - smb_shm_unlock(); + smb_shm_global_unlock(); close(smb_shm_fd); return False; } @@ -332,7 +436,7 @@ BOOL smb_shm_open( char *file_name, int size) if (! smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes)) { - smb_shm_unlock(); + smb_shm_global_unlock(); close(smb_shm_fd); return False; } @@ -344,7 +448,7 @@ BOOL smb_shm_open( char *file_name, int size) { DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %d\n",errno)); smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_unlock(); + smb_shm_global_unlock(); close(smb_shm_fd); return False; } @@ -369,7 +473,7 @@ BOOL smb_shm_open( char *file_name, int size) { DEBUG(0,("ERROR smb_shm_open : mmap failed with code %d\n",errno)); smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_unlock(); + smb_shm_global_unlock(); close(smb_shm_fd); return False; } @@ -378,6 +482,8 @@ BOOL smb_shm_open( char *file_name, int size) if (created_new || !other_processes) { smb_shm_initialize(size); + /* Create the hash buckets for the share file entries. */ + smb_shm_create_hash_table( lp_shmem_hash_size() ); } else if (!smb_shm_validate_header(size) ) { @@ -385,12 +491,12 @@ BOOL smb_shm_open( char *file_name, int size) DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n")); munmap((caddr_t)smb_shm_header_p, size); smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_unlock(); + smb_shm_global_unlock(); close(smb_shm_fd); return False; } - smb_shm_unlock(); + smb_shm_global_unlock(); return True; } @@ -399,17 +505,22 @@ BOOL smb_shm_open( char *file_name, int size) BOOL smb_shm_close( void ) { + if(smb_shm_initialize_called == False) + return True; + DEBUG(2,("smb_shm_close\n")); if(smb_shm_times_locked > 0) DEBUG(0,("WARNING smb_shm_close : shmem was still locked %d times\n",smb_shm_times_locked));; - if ( munmap((caddr_t)smb_shm_header_p, smb_shm_header_p->total_size) < 0) + if ((smb_shm_header_p != NULL) && + (munmap((caddr_t)smb_shm_header_p, smb_shm_header_p->total_size) < 0)) { DEBUG(0,("ERROR smb_shm_close : munmap failed with code %d\n",errno)); } - smb_shm_lock(); + smb_shm_global_lock(); + DEBUG(2,("calling smb_shm_unregister_process(%s, %d)\n", smb_shm_processreg_name, getpid())); smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_unlock(); + smb_shm_global_unlock(); close(smb_shm_fd); @@ -438,9 +549,12 @@ smb_shm_offset_t smb_shm_alloc(int size) return NULL_OFFSET; } + smb_shm_global_lock(); + if( !smb_shm_header_p->consistent) { DEBUG(0,("ERROR smb_shm_alloc : shmem not consistent\n")); + smb_shm_global_unlock(); return NULL_OFFSET; } @@ -463,6 +577,7 @@ smb_shm_offset_t smb_shm_alloc(int size) if ( scanner_p == EOList_Addr ) { DEBUG(0,("ERROR smb_shm_alloc : alloc of %d bytes failed, no free space found\n",size)); + smb_shm_global_unlock(); return (NULL_OFFSET); } @@ -516,6 +631,7 @@ smb_shm_offset_t smb_shm_alloc(int size) DEBUG(2,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); + smb_shm_global_unlock(); return ( result_offset ); } @@ -534,9 +650,12 @@ BOOL smb_shm_free(smb_shm_offset_t offset) return False; } + smb_shm_global_lock(); + if( !smb_shm_header_p->consistent) { DEBUG(0,("ERROR smb_shm_free : shmem not consistent\n")); + smb_shm_global_unlock(); return False; } @@ -545,6 +664,7 @@ BOOL smb_shm_free(smb_shm_offset_t offset) if (header_p->next != SMB_SHM_NOT_FREE_OFF) { DEBUG(0,("ERROR smb_shm_free : bad offset (%d)\n",offset)); + smb_shm_global_unlock(); return False; } @@ -577,6 +697,7 @@ BOOL smb_shm_free(smb_shm_offset_t offset) smb_shm_solve_neighbors( header_p ); /* if neighbors then link them */ smb_shm_header_p->consistent = True; + smb_shm_global_unlock(); return True; } else @@ -590,6 +711,7 @@ BOOL smb_shm_free(smb_shm_offset_t offset) smb_shm_solve_neighbors(prev_p) ; smb_shm_header_p->consistent = True; + smb_shm_global_unlock(); return True; } } @@ -633,68 +755,71 @@ smb_shm_offset_t smb_shm_addr2offset(void *addr) return (smb_shm_offset_t)((char *)addr - (char *)smb_shm_header_p); } -BOOL smb_shm_lock(void) +/******************************************************************* + Lock a particular hash bucket entry. + ******************************************************************/ + +BOOL smb_shm_lock_hash_entry( unsigned int entry) { - if (smb_shm_fd < 0) - { - DEBUG(0,("ERROR smb_shm_lock : bad smb_shm_fd (%d)\n",smb_shm_fd)); + int start = (smb_shm_header_p->userdef_off + (entry * sizeof(smb_shm_offset_t))); + + if (smb_shm_fd < 0) + { + DEBUG(0,("ERROR smb_shm_lock_hash_entry : bad smb_shm_fd (%d)\n",smb_shm_fd)); return False; - } - - smb_shm_times_locked++; - - if(smb_shm_times_locked > 1) - { - DEBUG(2,("smb_shm_lock : locked %d times\n",smb_shm_times_locked)); - return True; - } - - if (lockf(smb_shm_fd, F_LOCK, 0) < 0) - { - DEBUG(0,("ERROR smb_shm_lock : lockf failed with code %d\n",errno)); - smb_shm_times_locked--; + } + + if(entry >= lp_shmem_hash_size()) + { + DEBUG(0,("ERROR smb_shm_lock_hash_entry : hash entry size too big (%d)\n", entry)); return False; - } - - return True; - + } + + /* Do an exclusive wait lock on the 4 byte region mapping into this entry */ + if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_WRLCK) == False) + { + DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %d\n",errno)); + return False; + } + + DEBUG(9,("smb_shm_lock_hash_entry: locked hash bucket %d\n", entry)); + return True; } +/******************************************************************* + Unlock a particular hash bucket entry. + ******************************************************************/ - -BOOL smb_shm_unlock(void) +BOOL smb_shm_unlock_hash_entry( unsigned int entry ) { - if (smb_shm_fd < 0) - { - DEBUG(0,("ERROR smb_shm_unlock : bad smb_shm_fd (%d)\n",smb_shm_fd)); + int start = (smb_shm_header_p->userdef_off + (entry * sizeof(smb_shm_offset_t))); + + if (smb_shm_fd < 0) + { + DEBUG(0,("ERROR smb_shm_unlock_hash_entry : bad smb_shm_fd (%d)\n",smb_shm_fd)); return False; - } + } - if(smb_shm_times_locked == 0) - { - DEBUG(0,("ERROR smb_shm_unlock : shmem not locked\n",smb_shm_fd)); + if(entry >= lp_shmem_hash_size()) + { + DEBUG(0,("ERROR smb_shm_unlock_hash_entry : hash entry size too big (%d)\n", entry)); return False; - } - - smb_shm_times_locked--; - - if(smb_shm_times_locked > 0) - { - DEBUG(2,("smb_shm_unlock : still locked %d times\n",smb_shm_times_locked)); - return True; - } - - if (lockf(smb_shm_fd, F_ULOCK, 0) < 0) - { - DEBUG(0,("ERROR smb_shm_unlock : lockf failed with code %d\n",errno)); - smb_shm_times_locked++; + } + + /* Do a wait lock on the 4 byte region mapping into this entry */ + if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_UNLCK) == False) + { + DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %d\n",errno)); return False; - } - - return True; - + } + + DEBUG(9,("smb_shm_unlock_hash_entry: unlocked hash bucket %d\n", entry)); + return True; } +/******************************************************************* + Gather statistics on shared memory usage. + ******************************************************************/ BOOL smb_shm_get_usage(int *bytes_free, int *bytes_used, @@ -716,4 +841,4 @@ BOOL smb_shm_get_usage(int *bytes_free, #else /* FAST_SHARE_MODES */ int shmem_dummy_procedure(void) {return 0;} -#endif +#endif /* FAST_SHARE_MODES */ -- cgit From ccf4314fe73fb035f6941f00ce952ba3a308c2da Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 27 May 1997 20:28:45 +0000 Subject: loadparm.c: Ensure printer services cannot be read only and don't use share mode locking. locking.c: Changed aborts to returns so not so drastic on PANIC errors. proto.h: Removed definition of open_file as this is now never externally called. reply.c: Changed reply_mknew, reply_ctemp, reply_printopen to go through open_file_shared. server.c: Modified open_file_shared to be more robust and be useful for printer & temp files. Removed truncate option from open_file (now all truncates are done in open_file_shared). util.c: Added EAGAIN to errors checked in open_socket_out(). version.h: Updated to 1.9.17alpha2. jallison@whistle.com (This used to be commit d8471909b79fd591be2b789485b65d2e636d4745) --- source3/locking/locking.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e63e347a26..2c392e924d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -167,7 +167,7 @@ int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \ (max = %d)\n", hash_entry, lp_shmem_hash_size() )); - abort(); + return 0; } mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); @@ -265,7 +265,7 @@ bucket %d",file_scanner_p->locking_version, dev, inode, hash_entry)); 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)); - abort(); + return 0; } DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \ @@ -344,7 +344,7 @@ void del_share_mode(share_lock_token token, int fnum) ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \ (max = %d)\n", hash_entry, lp_shmem_hash_size() )); - abort(); + return; } mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); @@ -353,7 +353,7 @@ void del_share_mode(share_lock_token token, int fnum) { DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry)); - abort(); + return; } file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); @@ -436,7 +436,7 @@ Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries no 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)); - abort(); + return; } /* If we deleted the last share mode entry then remove the share mode record. */ @@ -483,7 +483,7 @@ BOOL set_share_mode(share_lock_token token, int fnum) ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \ (max = %d)\n", hash_entry, lp_shmem_hash_size() )); - abort(); + return False; } mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); @@ -564,7 +564,7 @@ inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry)); 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)); - abort(); + return False; } /* Increment the share_mode_entries counter */ @@ -838,7 +838,7 @@ int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, { DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ for share file %d\n", num_entries, fname)); - abort(); + return 0; } if(num_entries) @@ -1005,7 +1005,7 @@ void del_share_mode(share_lock_token token, int fnum) { DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ for share file %d\n", num_entries, fname)); - abort(); + return; } if(num_entries == 0) -- cgit From 9e37076f2b8514a010008db44def4355e52379c2 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 27 Jun 1997 00:26:59 +0000 Subject: shmem.c: Changed debug to higher level uid.c: Stop smbrun from deleting device files. util.c: Added EAGAIN to known error list. Jeremy (jallison@whistle.com) (This used to be commit c07db8d8e7e4a421501a08efe999e9ccd7337855) --- source3/locking/shmem.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 9d4e62bdd7..f3f84ec8c3 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -87,7 +87,7 @@ static BOOL smb_shm_global_lock(void) if(smb_shm_times_locked > 1) { - DEBUG(2,("smb_shm_global_lock : locked %d times\n",smb_shm_times_locked)); + DEBUG(5,("smb_shm_global_lock : locked %d times\n",smb_shm_times_locked)); return True; } @@ -121,7 +121,7 @@ static BOOL smb_shm_global_unlock(void) if(smb_shm_times_locked > 0) { - DEBUG(2,("smb_shm_global_unlock : still locked %d times\n",smb_shm_times_locked)); + DEBUG(5,("smb_shm_global_unlock : still locked %d times\n",smb_shm_times_locked)); return True; } @@ -193,7 +193,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth else { /* erase old pid */ - DEBUG(2,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %d)\n", + DEBUG(5,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %d)\n", other_pid, seek_back)); other_pid = (pid_t)0; erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); @@ -216,7 +216,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth if(free_slot < 0) free_slot = lseek(smb_shm_processes_fd, 0, SEEK_END); - DEBUG(2,("smb_shm_register_process : writing record for pid %d at offset %d\n",pid,free_slot)); + DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %d\n",pid,free_slot)); lseek(smb_shm_processes_fd, free_slot, SEEK_SET); if(write(smb_shm_processes_fd, &pid, sizeof(pid)) < 0) { @@ -252,11 +252,11 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) { - DEBUG(2,("smb_shm_unregister_process : read record for pid %d\n",other_pid)); + DEBUG(5,("smb_shm_unregister_process : read record for pid %d\n",other_pid)); if(other_pid == pid) { /* erase pid */ - DEBUG(2,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %d)\n", + DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %d)\n", other_pid, seek_back)); other_pid = (pid_t)0; erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); @@ -330,7 +330,7 @@ static BOOL smb_shm_initialize(int size) { struct SmbShmBlockDesc * first_free_block_p; - DEBUG(2,("smb_shm_initialize : initializing shmem file of size %d\n",size)); + DEBUG(5,("smb_shm_initialize : initializing shmem file of size %d\n",size)); if( !smb_shm_header_p ) { @@ -388,7 +388,7 @@ BOOL smb_shm_open( char *file_name, int size) BOOL other_processes = True; int old_umask; - DEBUG(2,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); + DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); old_umask = umask(0); #ifndef SECURE_SHARE_MODES @@ -508,7 +508,7 @@ BOOL smb_shm_close( void ) if(smb_shm_initialize_called == False) return True; - DEBUG(2,("smb_shm_close\n")); + DEBUG(5,("smb_shm_close\n")); if(smb_shm_times_locked > 0) DEBUG(0,("WARNING smb_shm_close : shmem was still locked %d times\n",smb_shm_times_locked));; if ((smb_shm_header_p != NULL) && @@ -518,7 +518,7 @@ BOOL smb_shm_close( void ) } smb_shm_global_lock(); - DEBUG(2,("calling smb_shm_unregister_process(%s, %d)\n", smb_shm_processreg_name, getpid())); + DEBUG(5,("calling smb_shm_unregister_process(%s, %d)\n", smb_shm_processreg_name, getpid())); smb_shm_unregister_process(smb_shm_processreg_name, getpid()); smb_shm_global_unlock(); @@ -629,7 +629,7 @@ smb_shm_offset_t smb_shm_alloc(int size) /* end modification of shared mem */ smb_shm_header_p->consistent = True; - DEBUG(2,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); + DEBUG(6,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); smb_shm_global_unlock(); return ( result_offset ); @@ -682,7 +682,7 @@ BOOL smb_shm_free(smb_shm_offset_t offset) smb_shm_header_p->consistent = False; - DEBUG(2,("smb_shm_free : freeing %d bytes at offset %d\n",header_p->size*CellSize,offset)); + DEBUG(6,("smb_shm_free : freeing %d bytes at offset %d\n",header_p->size*CellSize,offset)); if ( scanner_p == prev_p ) { -- cgit From fb1429c1970bc123e191f0cb7cc764faf4b86998 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 1 Jul 1997 01:19:13 +0000 Subject: client.c: New print queue query code from Jeff C. Foster " ipc.c: Added code for returning restricted lists of servers. loadparm.c: Changed default for force create mode to 000. Changed default maxmux to 50 to comply with NT. locking.c: Fixed silly crash bug with slow share mode code. nameannounce.c: Added code for returning restricted lists of servers. namedbserver.c: Added code for returning restricted lists of servers. nameelect.c: Added code for returning restricted lists of servers. namework.c: Added code for returning restricted lists of servers. nmbsync.c: Added code for returning restricted lists of servers. server.c: Added quota fix Albrecht Gebhardt smb.h: Added define for COPYBUF_SIZE. system.c: Rename across filesystems Patch from Warren Birnbaum util.c: Minor fix for warning. (This used to be commit 1c6e433caa22813a699c9766847886eb59755f8b) --- source3/locking/locking.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 2c392e924d..64dc207cb7 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -893,7 +893,8 @@ it left a share mode entry with mode 0x%X in share file %s\n", DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n", fname)); if(*old_shares) - free((char *)old_shares); + free((char *)*old_shares); + *old_shares = 0; if(buf) free(buf); delete_share_file(cnum, fname); @@ -910,7 +911,8 @@ it left a share mode entry with mode 0x%X in share file %s\n", DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); if(*old_shares) - free((char *)old_shares); + free((char *)*old_shares); + *old_shares = 0; if(buf) free(buf); return 0; @@ -933,7 +935,8 @@ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ mode file %s (%s)\n", fname, strerror(errno))); if(*old_shares) - free((char *)old_shares); + free((char *)*old_shares); + *old_shares = 0; if(buf) free(buf); return 0; @@ -944,7 +947,8 @@ mode file %s (%s)\n", fname, strerror(errno))); DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); if(*old_shares) - free((char *)old_shares); + free((char *)*old_shares); + *old_shares = 0; if(buf) free(buf); return 0; -- cgit From 6835bd679c414a7d19a50cd6e99a53801cf4475e Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 15 Jul 1997 17:47:43 +0000 Subject: Fix silly crash bug in FAST_SHARE_MODES (same bug as was in SLOW_SHARE_MODES - duh !). Jeremy (jallison@whistle.com) (This used to be commit d38ac4f3a2fb47d3e2ca7d5f788130064502c6eb) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 64dc207cb7..f579a75a0b 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -301,7 +301,7 @@ record mode 0x%X pid=%d\n", entry_scanner_p->share_mode, entry_scanner_p->pid)); hash bucket %d has a share mode record but no entries - deleting\n", dev, inode, hash_entry)); if(*old_shares) - free((char *)old_shares); + free((char *)*old_shares); *old_shares = 0; if(file_prev_p == file_scanner_p) -- cgit From 15ae50ca5203bc4c04567e400ba041a4d1757b2b Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 24 Jul 1997 17:25:11 +0000 Subject: Makefile: Added UNIXWARE 2.x with shadow passwords from fja@extratech.com client.c: Made prompt appear at debug level 0. Fixed strcasecmp redefinition. Caused client to use set_blocking rather than making fcntl calls itself. dir.c: Removed redundent snum parameters. includes.h: Added SCO fixes. loadparm.c: Made default 'files to hide' a null string. nmbd.c: Removed O_NONBLOCK from pid file open for platforms that dont have it. proto.h: Changed snum to cnum where needed. Changed is_xx_path to is_in_path (now called via MACRO). quotas.c: Swapped setuid/seteuid calls when restoring uid. reply.c: Removed redundent snum parameters. server.c: Changed snum to cnum where needed. Setup new veto_list, hide_list namelists. Added standard_sub changes from Stefaan A Eeckels and Paul Rippin shmem.c: Changed cast for sizeof to be int before negating. smb.h: Added new veto_list, hide_list entries to connections. Added IS_PRINT, IS_HIDDEN_PATH, IS_VETO_PATH macros. trans2.c: Removed redundent snum parameters. util.c: Added standard_sub_basic changes from Stefaan A Eeckels and Paul Rippin Fixed up veto/hidden path processing so the paths are pres-parsed and checked for wildcards (for speed). Jeremy (jallison@whistle.com) (This used to be commit 9afa36f7874cfd527aa6ef1e7965c1d35d46ab1f) --- source3/locking/shmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index f3f84ec8c3..fcd9f3ad0d 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -167,7 +167,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth int smb_shm_processes_fd = -1; int nb_read; pid_t other_pid; - int seek_back = -sizeof(other_pid); + int seek_back = -((int)sizeof(other_pid)); int free_slot = -1; int erased_slot; @@ -236,7 +236,7 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) int smb_shm_processes_fd = -1; int nb_read; pid_t other_pid; - int seek_back = -sizeof(other_pid); + int seek_back = -((int)sizeof(other_pid)); int erased_slot; BOOL found = False; -- cgit From 22e4d4e9d44577593d53ad84e77c9c078774d2e9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Aug 1997 02:22:44 +0000 Subject: added a new type to mkproto.awk so it can handle shmem.c in general if you add a new type that is returned by a non-static function then just add it to the list of known types in mkproto.awk (This used to be commit 1d4ce07435f3d6dac41a2616a044bcd441dbaced) --- source3/locking/shmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index fcd9f3ad0d..fc8dfbb9f3 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -733,7 +733,7 @@ BOOL smb_shm_set_userdef_off(smb_shm_offset_t userdef_off) return True; } -void * smb_shm_offset2addr(smb_shm_offset_t offset) +void *smb_shm_offset2addr(smb_shm_offset_t offset) { if (offset == NULL_OFFSET ) return (void *)(0); -- cgit From 30416c0b8a0f54f6cc1179c2e00860eaf5f58401 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Sep 1997 20:17:32 +0000 Subject: charcnv.c client.c clitar.c kanji.c kanji.h loadparm.c mangle.c smb.h util.c: Big merge to allow KANJI support to be in the main binary without explicitly compiling with it. locking.c: Fix for smbstatus not being able to read files. namepacket.c: Removed unneccesary debug statement. trans2.c: Added Luke's proposed fix (ifdefed out until further testing). nmblookup.c: Fixed bug where query fails and status is done on bogus IP. Jeremy (jallison@whistle.com) (This used to be commit 9196255022ae8c51b527412747b324819bea2c13) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f579a75a0b..760d21a05d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -616,7 +616,7 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok #ifdef SECURE_SHARE_MODES fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); #else /* SECURE_SHARE_MODES */ - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0644); + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); #endif /* SECURE_SHARE_MODES */ umask(old_umask); if(!become_user(cnum,Connections[cnum].vuid)) -- cgit From 552818e60eff4a87ece94f98c33424c93354bf6c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Sep 1997 05:43:37 +0000 Subject: - change a lot of occurances of errno to use strerror(errno). We can't assume all our users are programmers :-) - automatically create the smbpasswd file if it doesn't exist when running smbpasswd. (This used to be commit 1d2361bd2dec35bce029699f54c6a61fa739fa4b) --- source3/locking/shmem.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index fc8dfbb9f3..bbb11f215a 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -94,7 +94,7 @@ static BOOL smb_shm_global_lock(void) /* Do an exclusive wait lock on the first byte of the file */ if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_WRLCK) == False) { - DEBUG(0,("ERROR smb_shm_global_lock : fcntl_lock failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_global_lock : fcntl_lock failed with code %s\n",strerror(errno))); smb_shm_times_locked--; return False; } @@ -128,7 +128,7 @@ static BOOL smb_shm_global_unlock(void) /* Do a wait unlock on the first byte of the file */ if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_UNLCK) == False) { - DEBUG(0,("ERROR smb_shm_global_unlock : fcntl_lock failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_global_unlock : fcntl_lock failed with code %s\n",strerror(errno))); smb_shm_times_locked++; return False; } @@ -178,7 +178,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth #endif /* SECURE_SHARE_MODES */ if ( smb_shm_processes_fd < 0 ) { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file open failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_register_process : processreg_file open failed with code %s\n",strerror(errno))); return False; } @@ -208,7 +208,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth } if (nb_read < 0) { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file read failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_register_process : processreg_file read failed with code %s\n",strerror(errno))); close(smb_shm_processes_fd); return False; } @@ -220,7 +220,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth lseek(smb_shm_processes_fd, free_slot, SEEK_SET); if(write(smb_shm_processes_fd, &pid, sizeof(pid)) < 0) { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %s\n",strerror(errno))); close(smb_shm_processes_fd); return False; } @@ -246,7 +246,7 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) umask(old_umask); if ( smb_shm_processes_fd < 0 ) { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file open failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file open failed with code %s\n",strerror(errno))); return False; } @@ -262,7 +262,7 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %s\n",strerror(errno))); close(smb_shm_processes_fd); return False; } @@ -273,7 +273,7 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) } if (nb_read < 0) { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file read failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file read failed with code %s\n",strerror(errno))); close(smb_shm_processes_fd); return False; } @@ -399,7 +399,7 @@ BOOL smb_shm_open( char *file_name, int size) umask(old_umask); if ( smb_shm_fd < 0 ) { - DEBUG(0,("ERROR smb_shm_open : open failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_open : open failed with code %s\n",strerror(errno))); return False; } @@ -411,7 +411,7 @@ BOOL smb_shm_open( char *file_name, int size) if( (filesize = lseek(smb_shm_fd, 0, SEEK_END)) < 0) { - DEBUG(0,("ERROR smb_shm_open : lseek failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_open : lseek failed with code %s\n",strerror(errno))); smb_shm_global_unlock(); close(smb_shm_fd); return False; @@ -446,7 +446,7 @@ BOOL smb_shm_open( char *file_name, int size) /* we just created a new one, or are the first opener, lets set it size */ if( ftruncate(smb_shm_fd, size) <0) { - DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %s\n",strerror(errno))); smb_shm_unregister_process(smb_shm_processreg_name, getpid()); smb_shm_global_unlock(); close(smb_shm_fd); @@ -471,7 +471,7 @@ BOOL smb_shm_open( char *file_name, int size) /* WARNING, smb_shm_header_p can be different for different processes mapping the same file ! */ if (smb_shm_header_p == (struct SmbShmHeader *)(-1)) { - DEBUG(0,("ERROR smb_shm_open : mmap failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_open : mmap failed with code %s\n",strerror(errno))); smb_shm_unregister_process(smb_shm_processreg_name, getpid()); smb_shm_global_unlock(); close(smb_shm_fd); @@ -514,7 +514,7 @@ BOOL smb_shm_close( void ) if ((smb_shm_header_p != NULL) && (munmap((caddr_t)smb_shm_header_p, smb_shm_header_p->total_size) < 0)) { - DEBUG(0,("ERROR smb_shm_close : munmap failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_close : munmap failed with code %s\n",strerror(errno))); } smb_shm_global_lock(); @@ -778,7 +778,7 @@ BOOL smb_shm_lock_hash_entry( unsigned int entry) /* Do an exclusive wait lock on the 4 byte region mapping into this entry */ if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_WRLCK) == False) { - DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno))); return False; } @@ -809,7 +809,7 @@ BOOL smb_shm_unlock_hash_entry( unsigned int entry ) /* Do a wait lock on the 4 byte region mapping into this entry */ if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_UNLCK) == False) { - DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %d\n",errno)); + DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno))); return False; } -- cgit From 6dd6b1383c0ed10c0897dea44f247befc15b03cc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 25 Sep 1997 00:25:44 +0000 Subject: Makefile: Removed earlier errors. includes.h: Added INADDR_LOOPBACK define. locking.c: More code to support oplocks. proto.h: Updated. server.c: More code to support oplocks. Moved processing of an SMB out of process() into a separate function so it is easier to call from an oplock break. smb.h: Added oplock fields. Jeremy (jallison@whistle.com) (This used to be commit f46dbaf08eb8e06a7545d2c19dce9e2dda9dcc78) --- source3/locking/locking.c | 271 +++++++++++++++++++++++++--------------------- 1 file changed, 147 insertions(+), 124 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 760d21a05d..7604676394 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -46,7 +46,7 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset) return(False); return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count, - (Files[fnum].can_write?F_WRLCK:F_RDLCK))); + (Files[fnum].can_write?F_WRLCK:F_RDLCK))); } @@ -68,7 +68,7 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ec if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum)) ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count, - (Files[fnum].can_write?F_WRLCK:F_RDLCK)); + (Files[fnum].can_write?F_WRLCK:F_RDLCK)); if (!ok) { *eclass = ERRDOS; @@ -182,37 +182,37 @@ int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, 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( (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 \ + 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); + return (0); } if(file_scanner_p->locking_version != LOCKING_VERSION) { - DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \ + 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",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); + 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 */ @@ -283,6 +283,9 @@ bucket (number of entries now = %d)\n", */ share_array[num_entries_copied].pid = entry_scanner_p->pid; share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode; +#ifdef USE_OPLOCKS + share_array[num_entries_copied].op_port = entry_scanner_p->op_port; +#endif /* USE_OPLOCKS */ memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time, sizeof(struct timeval)); num_entries_copied++; @@ -361,17 +364,17 @@ void del_share_mode(share_lock_token token, int fnum) 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( (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) @@ -383,20 +386,20 @@ inode %d in hash bucket %d\n", dev, inode, hash_entry)); if(file_scanner_p->locking_version != LOCKING_VERSION) { - DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \ + 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; + 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 = (share_mode_entry*)smb_shm_offset2addr( - file_scanner_p->share_mode_entries); + file_scanner_p->share_mode_entries); entry_prev_p = entry_scanner_p; while(entry_scanner_p) { @@ -441,15 +444,15 @@ for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries /* 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; + mode_array[hash_entry] = file_scanner_p->next_offset; else - file_prev_p->next_offset = file_scanner_p->next_offset; + file_prev_p->next_offset = file_scanner_p->next_offset; smb_shm_free(smb_shm_addr2offset(file_scanner_p)); - } + } } else { @@ -461,7 +464,7 @@ 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. ********************************************************************/ -BOOL set_share_mode(share_lock_token token, int fnum) +BOOL set_share_mode(share_lock_token token, int fnum, uint16 port) { files_struct *fs_p = &Files[fnum]; int32 dev, inode; @@ -493,17 +496,17 @@ BOOL set_share_mode(share_lock_token token, int fnum) 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( (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) @@ -552,6 +555,9 @@ inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry)); new_entry_p->pid = getpid(); new_entry_p->share_mode = fs_p->share_mode; +#ifdef USE_OPLOCKS + new_entry_p->op_port = port; +#endif /* USE_OPLOCKS */ memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval)); /* Chain onto the share_mode_record */ @@ -751,9 +757,10 @@ for share file %s (%s)\n", fname, strerror(errno))); return -1; } - if (IVAL(buf,0) != LOCKING_VERSION) { + if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION)); +locking version (was %d, should be %d).\n",fname, + IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); if(buf) free(buf); delete_share_file(cnum, fname); @@ -762,13 +769,13 @@ locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION)) /* Sanity check for file contents */ size = sb.st_size; - size -= 10; /* Remove the header */ + size -= SMF_HEADER_LENGTH; /* Remove the header */ /* Remove the filename component. */ - size -= SVAL(buf, 8); + size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET); - /* The remaining size must be a multiple of 16 - error if not. */ - if((size % 16) != 0) + /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ + if((size % SMF_ENTRY_LENGTH) != 0) { DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \ deleting it.\n", fname)); @@ -813,7 +820,7 @@ int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, 4 - tv_usec 8 - share_mode 12 - pid - + 16 - oplock port (if oplocks in use) - 2 bytes. */ share_name(cnum, dev, inode, fname); @@ -828,7 +835,7 @@ int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, if(new_file == True) return 0; - num_entries = IVAL(buf,4); + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n", fname, num_entries)); @@ -863,26 +870,29 @@ for share file %d\n", num_entries, fname)); } num_entries_copied = 0; - base = buf + 10 + SVAL(buf,8); + base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); for( i = 0; i < num_entries; i++) { int pid; - char *p = base + (i*16); + char *p = base + (i*SMF_ENTRY_LENGTH); - pid = IVAL(p,12); + pid = IVAL(p,SME_PID_OFFSET); if(!process_exists(pid)) { DEBUG(0,("get_share_modes: process %d no longer exists and \ it left a share mode entry with mode 0x%X in share file %s\n", - pid, IVAL(p,8), fname)); + pid, IVAL(p,SME_SHAREMODE_OFFSET), fname)); continue; } - share_array[num_entries_copied].time.tv_sec = IVAL(p,0); - share_array[num_entries_copied].time.tv_usec = IVAL(p,4); - share_array[num_entries_copied].share_mode = IVAL(p,8); + share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET); + share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); + share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); share_array[num_entries_copied].pid = pid; +#ifdef USE_OPLOCKS + share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); +#endif /* USE_OPLOCKS */ num_entries_copied++; } @@ -918,18 +928,21 @@ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); return 0; } - SIVAL(buf, 4, num_entries_copied); + SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied); for( i = 0; i < num_entries_copied; i++) { - char *p = base + (i*16); - - SIVAL(p,12,share_array[i].pid); - SIVAL(p,8,share_array[i].share_mode); - SIVAL(p,0,share_array[i].time.tv_sec); - SIVAL(p,4,share_array[i].time.tv_usec); + char *p = base + (i*SMF_ENTRY_LENGTH); + + SIVAL(p,SME_PID_OFFSET,share_array[i].pid); + SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); + SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); + SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); +#ifdef USE_OPLOCKS + SIVAL(p,SME_PORT_OFFSET,share_array[i].op_port); +#endif /* USE_OPLOCKS */ } - newsize = (base - buf) + (16*num_entries_copied); + newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); if(write(fd, buf, newsize) != newsize) { DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ @@ -999,7 +1012,7 @@ void del_share_mode(share_lock_token token, int fnum) return; } - num_entries = IVAL(buf,4); + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n", fname, num_entries)); @@ -1029,14 +1042,16 @@ for share file %d\n", num_entries, fname)); we have set - delete it. */ - base = buf + 10 + SVAL(buf,8); + base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); for(i = 0; i < num_entries; i++) { - char *p = base + (i*16); + char *p = base + (i*SMF_ENTRY_LENGTH); - if((IVAL(p,0) != fs_p->open_time.tv_sec) || (IVAL(p,4) != fs_p->open_time.tv_usec) || - (IVAL(p,8) != fs_p->share_mode) || (IVAL(p,12) != pid)) + if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || + (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || + (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || + (IVAL(p,SME_PID_OFFSET) != pid)) continue; DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", @@ -1044,7 +1059,7 @@ for share file %d\n", num_entries, fname)); /* Remove this entry. */ if(i != num_entries - 1) - memcpy(p, p + 16, (num_entries - i - 1)*16); + memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH); deleted = True; break; @@ -1059,7 +1074,7 @@ for share file %d\n", num_entries, fname)); } num_entries--; - SIVAL(buf,4, num_entries); + SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries); if(num_entries == 0) { @@ -1074,23 +1089,23 @@ for share file %d\n", num_entries, fname)); /* Re-write the file - and truncate it at the correct point. */ if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ + { + DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } + if(buf) + free(buf); + return; + } - newsize = (base - buf) + (16*num_entries); + newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ + { + DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } + if(buf) + free(buf); + return; + } /* Now truncate the file at this point. */ if(ftruncate(fd, newsize) != 0) { @@ -1105,7 +1120,7 @@ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); /******************************************************************* set the share mode of a file ********************************************************************/ -BOOL set_share_mode(share_lock_token token,int fnum) +BOOL set_share_mode(share_lock_token token,int fnum, uint16 port) { files_struct *fs_p = &Files[fnum]; pstring fname; @@ -1133,9 +1148,10 @@ BOOL set_share_mode(share_lock_token token,int fnum) int size = sb.st_size; /* Allocate space for the file plus one extra entry */ - if((buf = (char *)malloc(sb.st_size + 16)) == NULL) + if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL) { - DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", sb.st_size + 16)); + DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", + sb.st_size + SMF_ENTRY_LENGTH)); return False; } @@ -1157,20 +1173,21 @@ to 0 for share file %s (%s)\n", fname, strerror(errno))); return False; } - if (IVAL(buf,0) != LOCKING_VERSION) + if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION)); +locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), + LOCKING_VERSION)); if(buf) free(buf); delete_share_file(fs_p->cnum, fname); return False; } - size -= (10 + SVAL(buf, 8)); /* Remove the header */ + size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */ - /* The remaining size must be a multiple of 16 - error if not. */ - if((size % 16) != 0) + /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ + if((size % SMF_ENTRY_LENGTH) != 0) { DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \ deleting it.\n", fname)); @@ -1184,28 +1201,32 @@ deleting it.\n", fname)); else { /* New file - just use a single_entry. */ - if((buf = (char *)malloc(10 + strlen(fs_p->name) + 1 + 16)) == NULL) + if((buf = (char *)malloc(SMF_HEADER_LENGTH + + strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL) { DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); return False; } - SIVAL(buf,0,LOCKING_VERSION); - SIVAL(buf,4,0); - SSVAL(buf,8,strlen(fs_p->name) + 1); - strcpy(buf + 10, fs_p->name); + SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); + SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); + SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1); + strcpy(buf + SMF_HEADER_LENGTH, fs_p->name); } - num_entries = IVAL(buf,4); - header_size = 10 + SVAL(buf,8); - p = buf + header_size + (num_entries * 16); - SIVAL(p,0,fs_p->open_time.tv_sec); - SIVAL(p,4,fs_p->open_time.tv_usec); - SIVAL(p,8,fs_p->share_mode); - SIVAL(p,12,pid); + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); + header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH); + SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec); + SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec); + SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode); + SIVAL(p,SME_PID_OFFSET,pid); +#ifdef USE_OPLOCKS + SSVAL(p,SME_PORT_OFFSET,port); +#endif /* USE_OPLOCKS */ num_entries++; - SIVAL(buf,4,num_entries); + SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries); if(lseek(fd, 0, SEEK_SET) != 0) { @@ -1216,7 +1237,8 @@ deleting it.\n", fname)); return False; } - if (write(fd,buf,header_size + (num_entries*16)) != (header_size + (num_entries*16))) + if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != + (header_size + (num_entries*SMF_ENTRY_LENGTH))) { DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ deleting it (%s).\n",fname, strerror(errno))); @@ -1227,10 +1249,11 @@ deleting it (%s).\n",fname, strerror(errno))); } /* Now truncate the file at this point - just for safety. */ - if(ftruncate(fd, header_size + (16*num_entries))!= 0) + if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0) { DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, header_size + (16*num_entries), strerror(errno))); +mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), + strerror(errno))); if(buf) free(buf); return False; -- cgit From cef59090bb2fd3f8a9efd1a453cb90264b891d58 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Sep 1997 18:55:29 +0000 Subject: Adding Andrews buffer overflow fixes into the main branch. Jeremy (jallison@whistle.com) (This used to be commit e7eb1f044d3101679dc7a118820ea5efe0cd837c) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 7604676394..64f24fb242 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -108,7 +108,7 @@ BOOL start_share_mode_mgmt(void) { pstring shmem_file_name; - strcpy(shmem_file_name,lp_lockdir()); + pstrcpy(shmem_file_name,lp_lockdir()); if (!directory_exist(shmem_file_name,NULL)) mkdir(shmem_file_name,0755); trim_string(shmem_file_name,"","/"); -- cgit From dff16872ca39c007d32d114af82d3ccd97f9d47a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Sep 1997 19:26:56 +0000 Subject: Syncing up current oplock work in progress. #ifdef'ed out so should have no effect on other work. Jeremy (jallison@whistle.com) (This used to be commit 7e3d4c8b21f63a06d32605d230129e36883ad08c) --- source3/locking/locking.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 64f24fb242..7aa0e7dcf9 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -285,6 +285,7 @@ bucket (number of entries now = %d)\n", share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode; #ifdef USE_OPLOCKS share_array[num_entries_copied].op_port = entry_scanner_p->op_port; + share_array[num_entries_copied].op_type = entry_scanner_p->op_type; #endif /* USE_OPLOCKS */ memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time, sizeof(struct timeval)); @@ -464,7 +465,7 @@ 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. ********************************************************************/ -BOOL set_share_mode(share_lock_token token, int fnum, uint16 port) +BOOL set_share_mode(share_lock_token token, int fnum, uint16 port, uint16 op_type) { files_struct *fs_p = &Files[fnum]; int32 dev, inode; @@ -557,6 +558,7 @@ inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry)); new_entry_p->share_mode = fs_p->share_mode; #ifdef USE_OPLOCKS new_entry_p->op_port = port; + new_entry_p->op_type = op_type; #endif /* USE_OPLOCKS */ memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval)); @@ -892,6 +894,7 @@ it left a share mode entry with mode 0x%X in share file %s\n", share_array[num_entries_copied].pid = pid; #ifdef USE_OPLOCKS share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); + share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); #endif /* USE_OPLOCKS */ num_entries_copied++; @@ -939,6 +942,7 @@ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); #ifdef USE_OPLOCKS SIVAL(p,SME_PORT_OFFSET,share_array[i].op_port); + SIVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); #endif /* USE_OPLOCKS */ } @@ -1120,7 +1124,7 @@ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); /******************************************************************* set the share mode of a file ********************************************************************/ -BOOL set_share_mode(share_lock_token token,int fnum, uint16 port) +BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type) { files_struct *fs_p = &Files[fnum]; pstring fname; @@ -1222,6 +1226,7 @@ deleting it.\n", fname)); SIVAL(p,SME_PID_OFFSET,pid); #ifdef USE_OPLOCKS SSVAL(p,SME_PORT_OFFSET,port); + SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); #endif /* USE_OPLOCKS */ num_entries++; -- cgit From 5864551aef50295addd1c8aa690a52870f70626d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Oct 1997 23:32:22 +0000 Subject: OPLOCK CHECK-IN - oplocks are now *OPERATIONAL* !!!! Yipeee. At least as far as I can check in a short time :-). local.h: Changed OPLOCK_BREAK_TIMEOUT to 30 seconds. locking.c: Big changes to delete oplocks on a share mode entry. proto.h: updated. reply.c: Added oplock break code in lockingX reply & readbraw reply. server.c: Add batch oplock code. Force server shutdown if client fails to respond to oplock break. smb.h: Fix silly slow share mode oplock define bug. status.c: Add oplock status info. Jeremy (jallison@whistle.com) (This used to be commit 4c83d37239f15f855fc10f01d7b4bf4217fb9eda) --- source3/locking/locking.c | 244 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 242 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 7aa0e7dcf9..693beb7432 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -585,6 +585,122 @@ for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries return(True); } +/******************************************************************* +Remove an oplock port and mode entry from a share mode. +********************************************************************/ +BOOL remove_share_oplock(int fnum, share_lock_token token) +{ +#ifdef USE_OPLOCKS + 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; + share_mode_entry *entry_scanner_p; + 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 = (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->pid) && + (entry_scanner_p->op_port != 0) && + (entry_scanner_p->op_type != 0) && + (memcmp(&entry_scanner_p->time, + &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) + { + /* Delete the oplock info. */ + entry_scanner_p->op_port = 0; + entry_scanner_p->op_type = 0; + found = True; + break; + } + else + { + entry_prev_p = entry_scanner_p; + entry_scanner_p = (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; +#else /* USE_OPLOCKS */ + return False; +#endif /* USE_OPLOCKS */ +} + #else /* FAST_SHARE_MODES */ /* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */ @@ -941,8 +1057,8 @@ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); #ifdef USE_OPLOCKS - SIVAL(p,SME_PORT_OFFSET,share_array[i].op_port); - SIVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); + SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); + SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); #endif /* USE_OPLOCKS */ } @@ -1272,4 +1388,128 @@ mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid)); return True; } + +/******************************************************************* +Remove an oplock port and mode entry from a share mode. +********************************************************************/ +BOOL remove_share_oplock(int fnum, share_lock_token token) +{ +#ifdef USE_OPLOCKS + pstring fname; + int fd = (int)token; + char *buf = 0; + char *base = 0; + int num_entries; + int fsize; + int i; + files_struct *fs_p = &Files[fnum]; + int pid; + BOOL found = False; + BOOL new_file; + + share_name(fs_p->cnum, fs_p->fd_ptr->dev, + fs_p->fd_ptr->inode, fname); + + if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) + { + DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n", + fname)); + return False; + } + + if(new_file == True) + { + DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \ +deleting it.\n", fname)); + delete_share_file(fs_p->cnum, fname); + return False; + } + + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); + + DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n", + fname, num_entries)); + + /* PARANOIA TEST */ + if(num_entries < 0) + { + DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \ +for share file %d\n", num_entries, fname)); + return False; + } + + if(num_entries == 0) + { + /* No entries - just delete the file. */ + DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n", + fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return False; + } + + pid = getpid(); + + /* Go through the entries looking for the particular one + we have set - remove the oplock settings on it. + */ + + base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + + for(i = 0; i < num_entries; i++) + { + char *p = base + (i*SMF_ENTRY_LENGTH); + + if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || + (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || + (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || + (IVAL(p,SME_PID_OFFSET) != pid) || + (SVAL(p,SME_PORT_OFFSET) == 0) || + (SVAL(p,SME_OPLOCK_TYPE_OFFSET) == 0)) + continue; + + DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \ +from the share file %s\n", i, num_entries, fname)); + + SSVAL(p,SME_PORT_OFFSET,0); + SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0); + found = True; + break; + } + + if(!found) + { + DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname)); + if(buf) + free(buf); + return False; + } + + /* Re-write the file - and truncate it at the correct point. */ + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \ +position 0 for share mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); + if(write(fd, buf, fsize) != fsize) + { + DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \ +mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + return True; + +#else /* USE_OPLOCKS */ + return False; +#endif /* USE_OPLOCKS */ +} #endif /* FAST_SHARE_MODES */ -- cgit From 2f7b04061e61df7dcc1029b71fe12ca4dfca5f10 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Oct 1997 20:36:06 +0000 Subject: locking.c: Fixed incorrect parameter count in debug statements. May explain solaris crashes. reply.c: Added NT specific error code. Put oplock break code in correct place in reply_lockingX. server.c: Removed unneeded error mapping stuff. Fixed race condition in oplock code. trans2.c: Added NT specific error code. util.c: Added paranoia check in interpret_addr. Some core dumps reported here. Upped fcntl debug levels. Andrew. Please check the NT specific error code handling (search for the string "/* Ugly - NT specific hack - but needed (JRA) */", this makes NT and 95 clients behave correctly here - please check your Visual Basic apps with this code. Jeremy (jallison@whistle.com). (This used to be commit 97ee4a5f69bd9cfbbc8710a1a04d80db0ee40104) --- source3/locking/locking.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 693beb7432..834f3e5658 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -206,7 +206,7 @@ file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry)); { 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",file_scanner_p->locking_version, dev, inode, hash_entry)); +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 @@ -270,7 +270,7 @@ for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries 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 (number of entries now = %d)\n", +bucket %d (number of entries now = %d)\n", pid, entry_scanner_p->share_mode, dev, inode, hash_entry, file_scanner_p->num_share_mode_entries)); @@ -316,8 +316,7 @@ hash bucket %d has a share mode record but no entries - deleting\n", } 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)); +hash bucket %d returning %d entries\n", dev, inode, hash_entry, num_entries_copied)); return(num_entries_copied); } @@ -878,8 +877,8 @@ for share file %s (%s)\n", fname, strerror(errno))); if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ locking version (was %d, should be %d).\n",fname, - IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); - if(buf) + IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); + if(buf) free(buf); delete_share_file(cnum, fname); return -1; -- cgit From c89eaa20d14c46c70980598345d7aa9394bcd854 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Oct 1997 23:45:34 +0000 Subject: Making it harder for share_mode_entries to be left with non-zero op_type fields. Paranoia code really. Jeremy (jallison@whistle.com) (This used to be commit 21ecb46f56ac0f341803d0552c981e517d0322cb) --- source3/locking/locking.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 834f3e5658..abda5d39d4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -668,8 +668,7 @@ record due to old locking version %d for file dev %d, inode %d hash bucket %d\n" while(entry_scanner_p) { if( (pid == entry_scanner_p->pid) && - (entry_scanner_p->op_port != 0) && - (entry_scanner_p->op_type != 0) && + (entry_scanner_p->share_mode == Files[fnum].share_mode) && (memcmp(&entry_scanner_p->time, &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) { @@ -1463,9 +1462,7 @@ for share file %d\n", num_entries, fname)); if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || - (IVAL(p,SME_PID_OFFSET) != pid) || - (SVAL(p,SME_PORT_OFFSET) == 0) || - (SVAL(p,SME_OPLOCK_TYPE_OFFSET) == 0)) + (IVAL(p,SME_PID_OFFSET) != pid)) continue; DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \ -- cgit From 2e92be3aaf01c574d32d1a10e1359888638b68bc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Oct 1997 17:52:25 +0000 Subject: client.c: Changed shadowed variable. locking.c: Removed USE_OPLOCKS - now the default. params.c: Removed unused variable. proto.h: Updated. reply.c: Removed USE_OPLOCKS - now the default. server.c: Removed USE_OPLOCKS - now the default. smb.h: Removed USE_OPLOCKS - now the default. smbparse.c: Changed shadowed variable. status.c: Removed USE_OPLOCKS - now the default. util.c: Removed USE_OPLOCKS - now the default. Jeremy (jallison@whistle.com) (This used to be commit b93509846d6291771787af457500eec8984ee6bd) --- source3/locking/locking.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index abda5d39d4..f29c1a6105 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -283,10 +283,8 @@ bucket %d (number of entries now = %d)\n", */ share_array[num_entries_copied].pid = entry_scanner_p->pid; share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode; -#ifdef USE_OPLOCKS share_array[num_entries_copied].op_port = entry_scanner_p->op_port; share_array[num_entries_copied].op_type = entry_scanner_p->op_type; -#endif /* USE_OPLOCKS */ memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time, sizeof(struct timeval)); num_entries_copied++; @@ -555,10 +553,8 @@ inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry)); new_entry_p->pid = getpid(); new_entry_p->share_mode = fs_p->share_mode; -#ifdef USE_OPLOCKS new_entry_p->op_port = port; new_entry_p->op_type = op_type; -#endif /* USE_OPLOCKS */ memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval)); /* Chain onto the share_mode_record */ @@ -589,7 +585,6 @@ Remove an oplock port and mode entry from a share mode. ********************************************************************/ BOOL remove_share_oplock(int fnum, share_lock_token token) { -#ifdef USE_OPLOCKS uint32 dev, inode; smb_shm_offset_t *mode_array; unsigned int hash_entry; @@ -694,9 +689,6 @@ mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_en } return True; -#else /* USE_OPLOCKS */ - return False; -#endif /* USE_OPLOCKS */ } #else /* FAST_SHARE_MODES */ @@ -1006,10 +998,8 @@ it left a share mode entry with mode 0x%X in share file %s\n", share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); share_array[num_entries_copied].pid = pid; -#ifdef USE_OPLOCKS share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); -#endif /* USE_OPLOCKS */ num_entries_copied++; } @@ -1054,10 +1044,8 @@ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); -#ifdef USE_OPLOCKS SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); -#endif /* USE_OPLOCKS */ } newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); @@ -1338,10 +1326,8 @@ deleting it.\n", fname)); SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec); SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode); SIVAL(p,SME_PID_OFFSET,pid); -#ifdef USE_OPLOCKS SSVAL(p,SME_PORT_OFFSET,port); SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); -#endif /* USE_OPLOCKS */ num_entries++; @@ -1392,7 +1378,6 @@ Remove an oplock port and mode entry from a share mode. ********************************************************************/ BOOL remove_share_oplock(int fnum, share_lock_token token) { -#ifdef USE_OPLOCKS pstring fname; int fd = (int)token; char *buf = 0; @@ -1504,8 +1489,5 @@ mode file %s (%s)\n", fname, strerror(errno))); return True; -#else /* USE_OPLOCKS */ - return False; -#endif /* USE_OPLOCKS */ } #endif /* FAST_SHARE_MODES */ -- cgit From 1f7a84bc9c343170ccf06c32d40fc2b07bff271d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Oct 1997 19:50:51 +0000 Subject: Finally ! Found & fixed crash bug with logging message when deleting invalid share mode entries. Thanks to berg@wienrg.aut.alcatel.at (Dietmar Berg) for the stack backtrace. Jeremy (jallison@whistle.com) (This used to be commit db4c2cb50e11d252ff3ba0e0973767e909dd33bd) --- source3/locking/locking.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f29c1a6105..6e321d0626 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -241,6 +241,7 @@ bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); { /* Delete this share mode entry */ share_mode_entry *delete_entry_p = entry_scanner_p; + int share_mode = entry_scanner_p->share_mode; if(entry_prev_p == entry_scanner_p) { @@ -271,7 +272,7 @@ for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries 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, entry_scanner_p->share_mode, dev, inode, hash_entry, + pid, share_mode, dev, inode, hash_entry, file_scanner_p->num_share_mode_entries)); smb_shm_free(smb_shm_addr2offset(delete_entry_p)); -- cgit From fb27bc139f8d321e50471c595b65b277ee114801 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Oct 1997 18:46:19 +0000 Subject: locking.c: Added fix for race condition in slow share mode code. lsaparse.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. pipes.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. server.c: Fixed last known oplock race condition. smb.h: Re-removed USE_OPLOCK defines - someone checked in an old version. smbparse.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. Jeremy (jallison@whistle.com) (This used to be commit 1e1366ddc5542283a37debdf830ca139bbade1b0) --- source3/locking/locking.c | 71 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 15 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 6e321d0626..639bc7be0b 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -25,6 +25,10 @@ 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. + */ #include "includes.h" @@ -726,13 +730,60 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok { int old_umask; + BOOL gotlock = False; unbecome_user(); old_umask = umask(0); + + /* + * There was a race condition in the original slow share mode code. + * A smbd could open a share mode file, and before getting + * the lock, another smbd could delete the last entry for + * the share mode file and delete the file entry from the + * directory. Thus this smbd would be left with a locked + * share mode fd attached to a file that no longer had a + * directory entry. Thus another smbd would think that + * there were no outstanding opens on the file. To fix + * this we now check we can do a stat() call on the filename + * before allowing the lock to proceed, and back out completely + * and try the open again if we cannot. + * Jeremy Allison (jallison@whistle.com). + */ + + do + { + struct stat dummy_stat; + #ifdef SECURE_SHARE_MODES - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); #else /* SECURE_SHARE_MODES */ - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); #endif /* SECURE_SHARE_MODES */ + + /* At this point we have an open fd to the share mode file. + Lock the first byte exclusively to signify a lock. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) + { + DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", + fname, strerror(errno))); + close(fd); + return False; + } + + /* + * If we cannot stat the filename, the file was deleted between + * the open and the lock call. Back out and try again. + */ + + if(stat(fname, &dummy_stat)!=0) + { + DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", + fname, strerror(errno))); + close(fd); + } + else + gotlock = True; + } while(!gotlock); + umask(old_umask); if(!become_user(cnum,Connections[cnum].vuid)) { @@ -750,18 +801,8 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok } } - /* At this point we have an open fd to the share mode file. - Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - close(fd); - return False; - } - - *ptok = (share_lock_token)fd; - return True; + *ptok = (share_lock_token)fd; + return True; } /******************************************************************* @@ -781,7 +822,7 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok ret = False; } - close((int)token); + close(fd); return ret; } -- cgit From cdd01aa4dd2660aca01db7b5c22f52a1f506896d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Oct 1997 00:16:37 +0000 Subject: Added fixes for become_user braindamage. Jeremy (jallison@whistle.com) (This used to be commit 08afa51f5c80f3da983781774378bc1646c431d7) --- source3/locking/locking.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 639bc7be0b..4af37fdc47 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -722,6 +722,7 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok { pstring fname; int fd; + ret = True; *ptok = (share_lock_token)-1; @@ -759,6 +760,14 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); #endif /* SECURE_SHARE_MODES */ + if(fd < 0) + { + DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n", + fname, strerror(errno))); + ret = False; + break; + } + /* At this point we have an open fd to the share mode file. Lock the first byte exclusively to signify a lock. */ if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) @@ -766,7 +775,8 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", fname, strerror(errno))); close(fd); - return False; + ret = False; + break; } /* @@ -784,12 +794,18 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok gotlock = True; } while(!gotlock); + /* + * We have to come here if any of the above calls fail + * as we don't want to return and leave ourselves running + * as root ! + */ + umask(old_umask); if(!become_user(cnum,Connections[cnum].vuid)) { DEBUG(0,("lock_share_entry: Can't become connected user!\n")); close(fd); - return False; + ret = False; } /* We need to change directory back to the connection root. */ if (ChDir(Connections[cnum].connectpath) != 0) @@ -797,12 +813,12 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n", Connections[cnum].connectpath, strerror(errno))); close(fd); - return False; + ret = False; } } *ptok = (share_lock_token)fd; - return True; + return ret; } /******************************************************************* -- cgit From 9f6a10d173713677a929a2ffe0bc2a7f1a2ed229 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Oct 1997 00:36:57 +0000 Subject: Broke my own rule about checking in uncompiled source :-(. Jeremy. (This used to be commit 9fd056c91196746e09f220a15171f3c97791dcce) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4af37fdc47..04c198afea 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -722,7 +722,7 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok { pstring fname; int fd; - ret = True; + int ret = True; *ptok = (share_lock_token)-1; -- cgit From 359d42c08d012b3e1c1bc6ac1071f8add706ba35 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Oct 1997 21:53:59 +0000 Subject: ipc.c: Adding Andrews become_root code to the main branch. locking.c: Adding Andrews become_root code to the main branch. pipes.c: Fixing the close_file issue. proto.h: The usual. reply.c: Move smb_pass into NTDOMAIN defined code. Fixing the close_file issue. server.c: Fixing the close_file issue. trans2.c: Fixing the close_file issue. uid.c: Adding Andrews become_root code to the main branch. Jeremy (jallison@whistle.com) (This used to be commit 16fd4337f79ce33f91050c96c4a566221c5d9126) --- source3/locking/locking.c | 45 ++++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 29 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 04c198afea..5071121bed 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -729,10 +729,12 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok if(!share_name(cnum, dev, inode, fname)) return False; + /* we need to do this as root */ + become_root(False); + { int old_umask; BOOL gotlock = False; - unbecome_user(); old_umask = umask(0); /* @@ -801,23 +803,13 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok */ umask(old_umask); - if(!become_user(cnum,Connections[cnum].vuid)) - { - DEBUG(0,("lock_share_entry: Can't become connected user!\n")); - close(fd); - ret = False; - } - /* We need to change directory back to the connection root. */ - if (ChDir(Connections[cnum].connectpath) != 0) - { - DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n", - Connections[cnum].connectpath, strerror(errno))); - close(fd); - ret = False; - } } *ptok = (share_lock_token)fd; + + /* return to our previous privilage level */ + unbecome_root(False); + return ret; } @@ -848,27 +840,22 @@ Force a share file to be deleted. static int delete_share_file( int cnum, char *fname ) { - unbecome_user(); + /* the share file could be owned by anyone, so do this as root */ + become_root(False); + if(unlink(fname) != 0) { DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", fname, strerror(errno))); + } + else + { + DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); } - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); + /* return to our previous privilage level */ + unbecome_root(False); - if(!become_user(cnum,Connections[cnum].vuid)) - { - DEBUG(0,("delete_share_file: Can't become connected user!\n")); - return -1; - } - /* We need to change directory back to the connection root. */ - if (ChDir(Connections[cnum].connectpath) != 0) - { - DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n", - Connections[cnum].connectpath, strerror(errno))); - return -1; - } return 0; } -- cgit From c336a2f08183f63031b0a08b2111669bc36a5f30 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Oct 1997 23:08:07 +0000 Subject: .cvsignore: Added make_smbcodepage interface.c: Added is_local_net(). locking.c: Added Fix for zero length share files from Gerald Werner plus a race condition fix for the fix. nameannounce.c: Made function static. namedbresp.c: extern int ClientDGRAM removed - not used. namedbserver.c: extern int ClientDGRAM removed - not used. namedbsubnet.c: Added code to make sockets per subnet. namepacket.c: Added code to read from all sockets & filter. nameresp.c: extern int ClientDGRAM removed - not used. nameserv.c: Indentation tidyup :-). nameserv.h: Added sockets to struct subnet. nameservresp.c: Improved debug message. nmbd.c: Changed to terminte on listen_for_packets exiting. nmbsync.c: extern int ClientDGRAM & ClientNMB removed - not used. proto.h: The usual. util.c: Fixed debug message. Jeremy (jallison@whistle.com) (This used to be commit 6904c2de080b2a9702800e9e4126386ced20569d) --- source3/locking/locking.c | 75 +++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 25 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 5071121bed..bbc0c0033f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -715,6 +715,31 @@ static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) return(True); } +/******************************************************************* +Force a share file to be deleted. +********************************************************************/ + +static int delete_share_file( int cnum, char *fname ) +{ + /* the share file could be owned by anyone, so do this as root */ + become_root(False); + + if(unlink(fname) != 0) + { + DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", + fname, strerror(errno))); + } + else + { + DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); + } + + /* return to our previous privilage level */ + unbecome_root(False); + + return 0; +} + /******************************************************************* lock a share mode file. ******************************************************************/ @@ -820,6 +845,31 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok { int fd = (int)token; int ret = True; + struct stat sb; + pstring fname; + + /* Fix for zero length share files from + Gerald Werner */ + + share_name(cnum, dev, inode, fname); + + /* get the share mode file size */ + if(fstat((int)token, &sb) != 0) + { + DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", + fname, strerror(errno))); + sb.st_size = 1; + ret = False; + } + + /* If the file was zero length, we must delete before + doing the unlock to avoid a race condition (see + the code in lock_share_mode_entry for details. + */ + + /* remove the share file if zero length */ + if(sb.st_size == 0) + delete_share_file(cnum, fname); /* token is the fd of the open share mode file. */ /* Unlock the first byte. */ @@ -834,31 +884,6 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok return ret; } -/******************************************************************* -Force a share file to be deleted. -********************************************************************/ - -static int delete_share_file( int cnum, char *fname ) -{ - /* the share file could be owned by anyone, so do this as root */ - become_root(False); - - if(unlink(fname) != 0) - { - DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", - fname, strerror(errno))); - } - else - { - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); - } - - /* return to our previous privilage level */ - unbecome_root(False); - - return 0; -} - /******************************************************************* Read a share file into a buffer. ********************************************************************/ -- cgit From 3e670e4057321911c6674b8abe3c0bdcd684fd09 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Oct 1997 08:46:00 +0000 Subject: 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 65ab9adaa0d356b8041ed8a507ea52117f2a284e) --- source3/locking/locking.c | 1458 ++-------------------------------------- source3/locking/locking_shm.c | 739 ++++++++++++++++++++ source3/locking/locking_slow.c | 1039 ++++++++++++++++++++++++++++ 3 files changed, 1829 insertions(+), 1407 deletions(-) create mode 100644 source3/locking/locking_shm.c create mode 100644 source3/locking/locking_slow.c (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index bbc0c0033f..c75497c6b9 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -36,6 +36,8 @@ extern int DEBUGLEVEL; extern connection_struct Connections[]; extern files_struct Files[]; +static struct share_ops *share_ops; + /**************************************************************************** utility function called to see if a file region is locked ****************************************************************************/ @@ -104,1460 +106,102 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * return True; /* Did unlock */ } -#ifdef FAST_SHARE_MODES -/******************************************************************* - initialize the shared memory for share_mode management - ******************************************************************/ -BOOL start_share_mode_mgmt(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"); - return smb_shm_open(shmem_file_name, lp_shmem_size()); -} -/******************************************************************* - deinitialize the shared memory for share_mode management - ******************************************************************/ -BOOL stop_share_mode_mgmt(void) +/**************************************************************************** + initialise the locking functions +****************************************************************************/ +BOOL locking_init(void) { - return smb_shm_close(); -} +#ifdef FAST_SHARE_MODES + share_ops = locking_shm_init(); + if (!share_ops) { + DEBUG(0,("ERROR: Failed to initialise fast share modes - trying slow code\n")); + } + if (share_ops) return True; +#endif -/******************************************************************* - lock a hash bucket entry in shared memory for share_mode management - ******************************************************************/ -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok) -{ - return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode)); + share_ops = locking_slow_init(); + if (!share_ops) { + DEBUG(0,("ERROR: Failed to initialise share modes!\n")); + return False; + } + + return True; } /******************************************************************* - unlock a hash bucket entry in shared memory for share_mode management + deinitialize the share_mode management ******************************************************************/ -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token) +BOOL locking_end(void) { - return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode)); + return share_ops->stop_mgmt(); } -/******************************************************************* -get all share mode entries in shared memory for a dev/inode pair. -********************************************************************/ -int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, - min_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; - share_mode_entry *entry_scanner_p; - share_mode_entry *entry_prev_p; - int num_entries; - int num_entries_copied; - BOOL found = False; - min_share_mode_entry *share_array = (min_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 = (min_share_mode_entry *) - malloc(num_entries * sizeof(min_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 = (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->pid; - - if (pid && !process_exists(pid)) - { - /* Delete this share mode entry */ - share_mode_entry *delete_entry_p = entry_scanner_p; - int share_mode = entry_scanner_p->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 = (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 = (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->pid; - share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode; - share_array[num_entries_copied].op_port = entry_scanner_p->op_port; - share_array[num_entries_copied].op_type = entry_scanner_p->op_type; - memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->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->share_mode, entry_scanner_p->pid)); - entry_prev_p = entry_scanner_p; - entry_scanner_p = (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. -********************************************************************/ -void del_share_mode(share_lock_token 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; - share_mode_entry *entry_scanner_p; - 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 = (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->pid) && - (memcmp(&entry_scanner_p->time, - &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) - { - found = True; - break; - } - else - { - entry_prev_p = entry_scanner_p; - entry_scanner_p = (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. -********************************************************************/ -BOOL set_share_mode(share_lock_token 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; - 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(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->pid = getpid(); - new_entry_p->share_mode = fs_p->share_mode; - new_entry_p->op_port = port; - new_entry_p->op_type = op_type; - memcpy( (char *)&new_entry_p->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->pid, - file_scanner_p->num_share_mode_entries)); - - return(True); -} - -/******************************************************************* -Remove an oplock port and mode entry from a share mode. -********************************************************************/ -BOOL remove_share_oplock(int fnum, share_lock_token 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; - share_mode_entry *entry_scanner_p; - 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 = (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->pid) && - (entry_scanner_p->share_mode == Files[fnum].share_mode) && - (memcmp(&entry_scanner_p->time, - &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) - { - /* Delete the oplock info. */ - entry_scanner_p->op_port = 0; - entry_scanner_p->op_type = 0; - found = True; - break; - } - else - { - entry_prev_p = entry_scanner_p; - entry_scanner_p = (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; -} - -#else /* FAST_SHARE_MODES */ - -/* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */ - -/******************************************************************* - name a share file + lock a hash bucket entry ******************************************************************/ -static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) -{ - strcpy(name,lp_lockdir()); - standard_sub(cnum,name); - trim_string(name,"","/"); - if (!*name) return(False); - name += strlen(name); - - sprintf(name,"/share.%u.%u",dev,inode); - return(True); -} - -/******************************************************************* -Force a share file to be deleted. -********************************************************************/ - -static int delete_share_file( int cnum, char *fname ) +BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) { - /* the share file could be owned by anyone, so do this as root */ - become_root(False); - - if(unlink(fname) != 0) - { - DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", - fname, strerror(errno))); - } - else - { - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); - } - - /* return to our previous privilage level */ - unbecome_root(False); - - return 0; + return share_ops->lock_entry(cnum, dev, inode, ptok); } /******************************************************************* - lock a share mode file. + unlock a hash bucket entry ******************************************************************/ -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok) +BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token) { - pstring fname; - int fd; - int ret = True; - - *ptok = (share_lock_token)-1; - - if(!share_name(cnum, dev, inode, fname)) - return False; - - /* we need to do this as root */ - become_root(False); - - { - int old_umask; - BOOL gotlock = False; - old_umask = umask(0); - - /* - * There was a race condition in the original slow share mode code. - * A smbd could open a share mode file, and before getting - * the lock, another smbd could delete the last entry for - * the share mode file and delete the file entry from the - * directory. Thus this smbd would be left with a locked - * share mode fd attached to a file that no longer had a - * directory entry. Thus another smbd would think that - * there were no outstanding opens on the file. To fix - * this we now check we can do a stat() call on the filename - * before allowing the lock to proceed, and back out completely - * and try the open again if we cannot. - * Jeremy Allison (jallison@whistle.com). - */ - - do - { - struct stat dummy_stat; - -#ifdef SECURE_SHARE_MODES - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); -#else /* SECURE_SHARE_MODES */ - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); -#endif /* SECURE_SHARE_MODES */ - - if(fd < 0) - { - DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n", - fname, strerror(errno))); - ret = False; - break; - } - - /* At this point we have an open fd to the share mode file. - Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", - fname, strerror(errno))); - close(fd); - ret = False; - break; - } - - /* - * If we cannot stat the filename, the file was deleted between - * the open and the lock call. Back out and try again. - */ - - if(stat(fname, &dummy_stat)!=0) - { - DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", - fname, strerror(errno))); - close(fd); - } - else - gotlock = True; - } while(!gotlock); - - /* - * We have to come here if any of the above calls fail - * as we don't want to return and leave ourselves running - * as root ! - */ - - umask(old_umask); - } - - *ptok = (share_lock_token)fd; - - /* return to our previous privilage level */ - unbecome_root(False); - - return ret; + return share_ops->unlock_entry(cnum, dev, inode, token); } /******************************************************************* - unlock a share mode file. - ******************************************************************/ -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token) +get all share mode entries for a dev/inode pair. +********************************************************************/ +int get_share_modes(int cnum, int token, uint32 dev, uint32 inode, + share_mode_entry **shares) { - int fd = (int)token; - int ret = True; - struct stat sb; - pstring fname; - - /* Fix for zero length share files from - Gerald Werner */ - - share_name(cnum, dev, inode, fname); - - /* get the share mode file size */ - if(fstat((int)token, &sb) != 0) - { - DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - sb.st_size = 1; - ret = False; - } - - /* If the file was zero length, we must delete before - doing the unlock to avoid a race condition (see - the code in lock_share_mode_entry for details. - */ - - /* remove the share file if zero length */ - if(sb.st_size == 0) - delete_share_file(cnum, fname); - - /* token is the fd of the open share mode file. */ - /* Unlock the first byte. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False) - { - DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - ret = False; - } - - close(fd); - return ret; + return share_ops->get_entries(cnum, token, dev, inode, shares); } /******************************************************************* -Read a share file into a buffer. +del the share mode of a file. ********************************************************************/ - -static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file) +void del_share_mode(int token, int fnum) { - struct stat sb; - char *buf; - int size; - - *out = 0; - *p_new_file = False; - - if(fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - return -1; - } - - if(sb.st_size == 0) - { - *p_new_file = True; - return 0; - } - - /* Allocate space for the file */ - if((buf = (char *)malloc(sb.st_size)) == NULL) - { - DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size)); - return -1; - } - - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \ -for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (read(fd,buf,sb.st_size) != sb.st_size) - { - DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { - DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, - IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(cnum, fname); - return -1; - } - - /* 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) - { - DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(cnum, fname); - return -1; - } - - *out = buf; - return 0; + share_ops->del_entry(token, fnum); } /******************************************************************* -get all share mode entries in a share file for a dev/inode pair. +set the share mode of a file. Return False on fail, True on success. ********************************************************************/ -int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, - min_share_mode_entry **old_shares) +BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type) { - int fd = (int)token; - pstring fname; - int i; - int num_entries; - int num_entries_copied; - int newsize; - min_share_mode_entry *share_array; - char *buf = 0; - char *base = 0; - BOOL new_file; - - *old_shares = 0; - - /* Read the share file header - this is of the form: - 0 - locking version. - 4 - number of share mode entries. - 8 - 2 byte name length - [n bytes] file name (zero terminated). - - Followed by share mode entries of the form : - - 0 - tv_sec - 4 - tv_usec - 8 - share_mode - 12 - pid - 16 - oplock port (if oplocks in use) - 2 bytes. - */ - - share_name(cnum, dev, inode, fname); - - if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n", - fname)); - return 0; - } - - if(new_file == True) - return 0; - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); - return 0; - } - - if(num_entries) - { - *old_shares = share_array = (min_share_mode_entry *) - malloc(num_entries * sizeof(min_share_mode_entry)); - if(*old_shares == 0) - { - DEBUG(0,("get_share_modes: malloc fail !\n")); - return 0; - } - } - else - { - /* No entries - just delete the file. */ - DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(cnum, fname); - return 0; - } - - num_entries_copied = 0; - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for( i = 0; i < num_entries; i++) - { - int pid; - char *p = base + (i*SMF_ENTRY_LENGTH); - - pid = IVAL(p,SME_PID_OFFSET); - - if(!process_exists(pid)) - { - DEBUG(0,("get_share_modes: process %d no longer exists and \ -it left a share mode entry with mode 0x%X in share file %s\n", - pid, IVAL(p,SME_SHAREMODE_OFFSET), fname)); - continue; - } - share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET); - share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); - share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - share_array[num_entries_copied].pid = pid; - share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); - share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - - num_entries_copied++; - } - - if(num_entries_copied == 0) - { - /* Delete the whole file. */ - DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n", - fname)); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - delete_share_file(cnum, fname); - return 0; - } - - /* If we deleted some entries we need to re-write the whole number of - share mode entries back into the file. */ - - if(num_entries_copied != num_entries) - { - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - - SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied); - for( i = 0; i < num_entries_copied; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - SIVAL(p,SME_PID_OFFSET,share_array[i].pid); - SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); - SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); - SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); - } - - newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - /* Now truncate the file at this point. */ - if(ftruncate(fd, newsize)!= 0) - { - DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - } - - if(buf) - free(buf); - - DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname, - num_entries_copied)); - - return num_entries_copied; + return share_ops->set_entry(token, fnum, port, op_type); } /******************************************************************* -del a share mode from a share mode file. +Remove an oplock port and mode entry from a share mode. ********************************************************************/ -void del_share_mode(share_lock_token token, int fnum) +BOOL remove_share_oplock(int fnum, int token) { - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int newsize; - int i; - files_struct *fs_p = &Files[fnum]; - int pid; - BOOL deleted = False; - BOOL new_file; - - share_name(fs_p->cnum, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); - - if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", - fname)); - return; - } - - if(new_file == True) - { - DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", - fname)); - delete_share_file(fs_p->cnum, fname); - return; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); - return; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return; - } - - pid = getpid(); - - /* Go through the entries looking for the particular one - we have set - delete it. - */ - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || - (IVAL(p,SME_PID_OFFSET) != pid)) - continue; - - DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", - i, num_entries, fname)); - - /* Remove this entry. */ - if(i != num_entries - 1) - memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH); - - deleted = True; - break; - } - - if(!deleted) - { - DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return; - } - - num_entries--; - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries); - - if(num_entries == 0) - { - /* Deleted the last entry - remove the file. */ - DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n", - fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum,fname); - return; - } + return share_ops->remove_oplock(fnum, token); +} - /* Re-write the file - and truncate it at the correct point. */ - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - /* Now truncate the file at this point. */ - if(ftruncate(fd, newsize) != 0) - { - DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(buf) - free(buf); - return; - } -} - /******************************************************************* -set the share mode of a file +call the specified function on each entry under management by the +share mode system ********************************************************************/ -BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type) +int share_mode_forall(void (*fn)(share_mode_entry *, char *)) { - files_struct *fs_p = &Files[fnum]; - pstring fname; - int fd = (int)token; - int pid = (int)getpid(); - struct stat sb; - char *buf; - int num_entries; - int header_size; - char *p; - - share_name(fs_p->cnum, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); - - if(fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", - fname)); - return False; - } - - /* Sanity check for file contents (if it's not a new share file). */ - if(sb.st_size != 0) - { - int size = sb.st_size; - - /* Allocate space for the file plus one extra entry */ - if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL) - { - DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", - sb.st_size + SMF_ENTRY_LENGTH)); - return False; - } - - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to reset position \ -to 0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (read(fd,buf,sb.st_size) != sb.st_size) - { - DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) - { - DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), - LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return False; - } - - size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */ - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 0) - { - DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return False; - } - - } - else - { - /* New file - just use a single_entry. */ - if((buf = (char *)malloc(SMF_HEADER_LENGTH + - strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL) - { - DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); - return False; - } - SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); - SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1); - strcpy(buf + SMF_HEADER_LENGTH, fs_p->name); - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH); - SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec); - SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode); - SIVAL(p,SME_PID_OFFSET,pid); - SSVAL(p,SME_PORT_OFFSET,port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); - - num_entries++; - - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries); - - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \ -0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != - (header_size + (num_entries*SMF_ENTRY_LENGTH))) - { - DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ -deleting it (%s).\n",fname, strerror(errno))); - delete_share_file(fs_p->cnum, fname); - if(buf) - free(buf); - return False; - } - - /* Now truncate the file at this point - just for safety. */ - if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0) - { - DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), - strerror(errno))); - if(buf) - free(buf); - return False; - } - - if(buf) - free(buf); - - DEBUG(3,("set_share_mode: Created share file %s with \ -mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid)); - - return True; + return share_ops->forall(fn); } /******************************************************************* -Remove an oplock port and mode entry from a share mode. +dump the state of the system ********************************************************************/ -BOOL remove_share_oplock(int fnum, share_lock_token token) +void share_status(FILE *f) { - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int fsize; - int i; - files_struct *fs_p = &Files[fnum]; - int pid; - BOOL found = False; - BOOL new_file; - - share_name(fs_p->cnum, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); - - if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n", - fname)); - return False; - } - - if(new_file == True) - { - DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \ -deleting it.\n", fname)); - delete_share_file(fs_p->cnum, fname); - return False; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); - return False; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return False; - } - - pid = getpid(); - - /* Go through the entries looking for the particular one - we have set - remove the oplock settings on it. - */ - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || - (IVAL(p,SME_PID_OFFSET) != pid)) - continue; - - DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \ -from the share file %s\n", i, num_entries, fname)); - - SSVAL(p,SME_PORT_OFFSET,0); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0); - found = True; - break; - } - - if(!found) - { - DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return False; - } - - /* Re-write the file - and truncate it at the correct point. */ - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, fsize) != fsize) - { - DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - return True; - + share_ops->status(f); } -#endif /* FAST_SHARE_MODES */ 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 + + + diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c new file mode 100644 index 0000000000..cc646c6ca6 --- /dev/null +++ b/source3/locking/locking_slow.c @@ -0,0 +1,1039 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + slow (lockfile) 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) +*/ + +#include "includes.h" +extern int DEBUGLEVEL; +extern connection_struct Connections[]; +extern files_struct Files[]; + +/* + * 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 + + +/******************************************************************* + deinitialize share_mode management + ******************************************************************/ +static BOOL slow_stop_share_mode_mgmt(void) +{ + return True; +} + + +/******************************************************************* + name a share file + ******************************************************************/ +static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) +{ + strcpy(name,lp_lockdir()); + trim_string(name,"","/"); + if (!*name) return(False); + name += strlen(name); + + sprintf(name,"/share.%u.%u",dev,inode); + return(True); +} + +/******************************************************************* +Force a share file to be deleted. +********************************************************************/ +static int delete_share_file( int cnum, char *fname ) +{ + /* the share file could be owned by anyone, so do this as root */ + become_root(False); + + if(unlink(fname) != 0) + { + DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", + fname, strerror(errno))); + } + else + { + DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); + } + + /* return to our previous privilage level */ + unbecome_root(False); + + return 0; +} + +/******************************************************************* + lock a share mode file. + ******************************************************************/ +static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) +{ + pstring fname; + int fd; + int ret = True; + + *ptok = (int)-1; + + if(!share_name(cnum, dev, inode, fname)) + return False; + + /* we need to do this as root */ + become_root(False); + + { + int old_umask; + BOOL gotlock = False; + old_umask = umask(0); + + /* + * There was a race condition in the original slow share mode code. + * A smbd could open a share mode file, and before getting + * the lock, another smbd could delete the last entry for + * the share mode file and delete the file entry from the + * directory. Thus this smbd would be left with a locked + * share mode fd attached to a file that no longer had a + * directory entry. Thus another smbd would think that + * there were no outstanding opens on the file. To fix + * this we now check we can do a stat() call on the filename + * before allowing the lock to proceed, and back out completely + * and try the open again if we cannot. + * Jeremy Allison (jallison@whistle.com). + */ + + do + { + struct stat dummy_stat; + +#ifdef SECURE_SHARE_MODES + fd = (int)open(fname,O_RDWR|O_CREAT,0600); +#else /* SECURE_SHARE_MODES */ + fd = (int)open(fname,O_RDWR|O_CREAT,0666); +#endif /* SECURE_SHARE_MODES */ + + if(fd < 0) + { + DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n", + fname, strerror(errno))); + ret = False; + break; + } + + /* At this point we have an open fd to the share mode file. + Lock the first byte exclusively to signify a lock. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) + { + DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", + fname, strerror(errno))); + close(fd); + ret = False; + break; + } + + /* + * If we cannot stat the filename, the file was deleted between + * the open and the lock call. Back out and try again. + */ + + if(stat(fname, &dummy_stat)!=0) + { + DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", + fname, strerror(errno))); + close(fd); + } + else + gotlock = True; + } while(!gotlock); + + /* + * We have to come here if any of the above calls fail + * as we don't want to return and leave ourselves running + * as root ! + */ + + umask(old_umask); + } + + *ptok = (int)fd; + + /* return to our previous privilage level */ + unbecome_root(False); + + return ret; +} + +/******************************************************************* + unlock a share mode file. + ******************************************************************/ +static BOOL slow_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token) +{ + int fd = (int)token; + int ret = True; + struct stat sb; + pstring fname; + + /* Fix for zero length share files from + Gerald Werner */ + + share_name(cnum, dev, inode, fname); + + /* get the share mode file size */ + if(fstat((int)token, &sb) != 0) + { + DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", + fname, strerror(errno))); + sb.st_size = 1; + ret = False; + } + + /* If the file was zero length, we must delete before + doing the unlock to avoid a race condition (see + the code in lock_share_mode_entry for details. + */ + + /* remove the share file if zero length */ + if(sb.st_size == 0) + delete_share_file(cnum, fname); + + /* token is the fd of the open share mode file. */ + /* Unlock the first byte. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False) + { + DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", + strerror(errno))); + ret = False; + } + + close(fd); + return ret; +} + +/******************************************************************* +Read a share file into a buffer. +********************************************************************/ +static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file) +{ + struct stat sb; + char *buf; + int size; + + *out = 0; + *p_new_file = False; + + if(fstat(fd, &sb) != 0) + { + DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", + fname, strerror(errno))); + return -1; + } + + if(sb.st_size == 0) + { + *p_new_file = True; + return 0; + } + + /* Allocate space for the file */ + if((buf = (char *)malloc(sb.st_size)) == NULL) + { + DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size)); + return -1; + } + + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \ +for share file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return -1; + } + + if (read(fd,buf,sb.st_size) != sb.st_size) + { + DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n", + fname, strerror(errno))); + if(buf) + free(buf); + return -1; + } + + if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { + DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ +locking version (was %d, should be %d).\n",fname, + IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); + if(buf) + free(buf); + delete_share_file(cnum, fname); + return -1; + } + + /* 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) + { + DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \ +deleting it.\n", fname)); + if(buf) + free(buf); + delete_share_file(cnum, fname); + return -1; + } + + *out = buf; + return 0; +} + +/******************************************************************* +get all share mode entries in a share file for a dev/inode pair. +********************************************************************/ +static int slow_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, + share_mode_entry **old_shares) +{ + int fd = (int)token; + pstring fname; + int i; + int num_entries; + int num_entries_copied; + int newsize; + share_mode_entry *share_array; + char *buf = 0; + char *base = 0; + BOOL new_file; + + *old_shares = 0; + + /* Read the share file header - this is of the form: + 0 - locking version. + 4 - number of share mode entries. + 8 - 2 byte name length + [n bytes] file name (zero terminated). + + Followed by share mode entries of the form : + + 0 - tv_sec + 4 - tv_usec + 8 - share_mode + 12 - pid + 16 - oplock port (if oplocks in use) - 2 bytes. + */ + + share_name(cnum, dev, inode, fname); + + if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0) + { + DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n", + fname)); + return 0; + } + + if(new_file == True) + return 0; + + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); + + DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n", + fname, num_entries)); + + /* PARANOIA TEST */ + if(num_entries < 0) + { + DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ +for share file %d\n", num_entries, fname)); + return 0; + } + + 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: malloc fail !\n")); + return 0; + } + } + else + { + /* No entries - just delete the file. */ + DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n", + fname)); + if(buf) + free(buf); + delete_share_file(cnum, fname); + return 0; + } + + num_entries_copied = 0; + base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + + for( i = 0; i < num_entries; i++) + { + int pid; + char *p = base + (i*SMF_ENTRY_LENGTH); + + pid = IVAL(p,SME_PID_OFFSET); + + if(!process_exists(pid)) + { + DEBUG(0,("get_share_modes: process %d no longer exists and \ +it left a share mode entry with mode 0x%X in share file %s\n", + pid, IVAL(p,SME_SHAREMODE_OFFSET), fname)); + continue; + } + share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET); + share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); + share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); + share_array[num_entries_copied].pid = pid; + share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); + share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); + + num_entries_copied++; + } + + if(num_entries_copied == 0) + { + /* Delete the whole file. */ + DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n", + fname)); + if(*old_shares) + free((char *)*old_shares); + *old_shares = 0; + if(buf) + free(buf); + delete_share_file(cnum, fname); + return 0; + } + + /* If we deleted some entries we need to re-write the whole number of + share mode entries back into the file. */ + + if(num_entries_copied != num_entries) + { + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ +position 0 for share mode file %s (%s)\n", fname, strerror(errno))); + if(*old_shares) + free((char *)*old_shares); + *old_shares = 0; + if(buf) + free(buf); + return 0; + } + + SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied); + for( i = 0; i < num_entries_copied; i++) + { + char *p = base + (i*SMF_ENTRY_LENGTH); + + SIVAL(p,SME_PID_OFFSET,share_array[i].pid); + SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); + SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); + SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); + SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); + SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); + } + + newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); + if(write(fd, buf, newsize) != newsize) + { + DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ +mode file %s (%s)\n", fname, strerror(errno))); + if(*old_shares) + free((char *)*old_shares); + *old_shares = 0; + if(buf) + free(buf); + return 0; + } + /* Now truncate the file at this point. */ + if(ftruncate(fd, newsize)!= 0) + { + DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ +mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); + if(*old_shares) + free((char *)*old_shares); + *old_shares = 0; + if(buf) + free(buf); + return 0; + } + } + + if(buf) + free(buf); + + DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname, + num_entries_copied)); + + return num_entries_copied; +} + +/******************************************************************* +del a share mode from a share mode file. +********************************************************************/ +static void slow_del_share_mode(int token, int fnum) +{ + pstring fname; + int fd = (int)token; + char *buf = 0; + char *base = 0; + int num_entries; + int newsize; + int i; + files_struct *fs_p = &Files[fnum]; + int pid; + BOOL deleted = False; + BOOL new_file; + + share_name(fs_p->cnum, fs_p->fd_ptr->dev, + fs_p->fd_ptr->inode, fname); + + if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) + { + DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", + fname)); + return; + } + + if(new_file == True) + { + DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", + fname)); + delete_share_file(fs_p->cnum, fname); + return; + } + + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); + + DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n", + fname, num_entries)); + + /* PARANOIA TEST */ + if(num_entries < 0) + { + DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ +for share file %d\n", num_entries, fname)); + return; + } + + if(num_entries == 0) + { + /* No entries - just delete the file. */ + DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n", + fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return; + } + + pid = getpid(); + + /* Go through the entries looking for the particular one + we have set - delete it. + */ + + base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + + for(i = 0; i < num_entries; i++) + { + char *p = base + (i*SMF_ENTRY_LENGTH); + + if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || + (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || + (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || + (IVAL(p,SME_PID_OFFSET) != pid)) + continue; + + DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", + i, num_entries, fname)); + + /* Remove this entry. */ + if(i != num_entries - 1) + memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH); + + deleted = True; + break; + } + + if(!deleted) + { + DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname)); + if(buf) + free(buf); + return; + } + + num_entries--; + SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries); + + if(num_entries == 0) + { + /* Deleted the last entry - remove the file. */ + DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n", + fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum,fname); + return; + } + + /* Re-write the file - and truncate it at the correct point. */ + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ +position 0 for share mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return; + } + + newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); + if(write(fd, buf, newsize) != newsize) + { + DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ +mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return; + } + /* Now truncate the file at this point. */ + if(ftruncate(fd, newsize) != 0) + { + DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ +mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); + if(buf) + free(buf); + return; + } +} + +/******************************************************************* +set the share mode of a file +********************************************************************/ +static BOOL slow_set_share_mode(int token,int fnum, uint16 port, uint16 op_type) +{ + files_struct *fs_p = &Files[fnum]; + pstring fname; + int fd = (int)token; + int pid = (int)getpid(); + struct stat sb; + char *buf; + int num_entries; + int header_size; + char *p; + + share_name(fs_p->cnum, fs_p->fd_ptr->dev, + fs_p->fd_ptr->inode, fname); + + if(fstat(fd, &sb) != 0) + { + DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", + fname)); + return False; + } + + /* Sanity check for file contents (if it's not a new share file). */ + if(sb.st_size != 0) + { + int size = sb.st_size; + + /* Allocate space for the file plus one extra entry */ + if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL) + { + DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", + sb.st_size + SMF_ENTRY_LENGTH)); + return False; + } + + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: set_share_mode: Failed to reset position \ +to 0 for share file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + if (read(fd,buf,sb.st_size) != sb.st_size) + { + DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n", + fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) + { + DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ +locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), + LOCKING_VERSION)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return False; + } + + size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */ + + /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ + if((size % SMF_ENTRY_LENGTH) != 0) + { + DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \ +deleting it.\n", fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return False; + } + + } + else + { + /* New file - just use a single_entry. */ + if((buf = (char *)malloc(SMF_HEADER_LENGTH + + strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL) + { + DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); + return False; + } + SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); + SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); + SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1); + strcpy(buf + SMF_HEADER_LENGTH, fs_p->name); + } + + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); + header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH); + SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec); + SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec); + SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode); + SIVAL(p,SME_PID_OFFSET,pid); + SSVAL(p,SME_PORT_OFFSET,port); + SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); + + num_entries++; + + SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries); + + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \ +0 for share file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != + (header_size + (num_entries*SMF_ENTRY_LENGTH))) + { + DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ +deleting it (%s).\n",fname, strerror(errno))); + delete_share_file(fs_p->cnum, fname); + if(buf) + free(buf); + return False; + } + + /* Now truncate the file at this point - just for safety. */ + if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0) + { + DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ +mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), + strerror(errno))); + if(buf) + free(buf); + return False; + } + + if(buf) + free(buf); + + DEBUG(3,("set_share_mode: Created share file %s with \ +mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid)); + + return True; +} + +/******************************************************************* +Remove an oplock port and mode entry from a share mode. +********************************************************************/ +static BOOL slow_remove_share_oplock(int fnum, int token) +{ + pstring fname; + int fd = (int)token; + char *buf = 0; + char *base = 0; + int num_entries; + int fsize; + int i; + files_struct *fs_p = &Files[fnum]; + int pid; + BOOL found = False; + BOOL new_file; + + share_name(fs_p->cnum, fs_p->fd_ptr->dev, + fs_p->fd_ptr->inode, fname); + + if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) + { + DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n", + fname)); + return False; + } + + if(new_file == True) + { + DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \ +deleting it.\n", fname)); + delete_share_file(fs_p->cnum, fname); + return False; + } + + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); + + DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n", + fname, num_entries)); + + /* PARANOIA TEST */ + if(num_entries < 0) + { + DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \ +for share file %d\n", num_entries, fname)); + return False; + } + + if(num_entries == 0) + { + /* No entries - just delete the file. */ + DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n", + fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return False; + } + + pid = getpid(); + + /* Go through the entries looking for the particular one + we have set - remove the oplock settings on it. + */ + + base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + + for(i = 0; i < num_entries; i++) + { + char *p = base + (i*SMF_ENTRY_LENGTH); + + if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || + (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || + (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || + (IVAL(p,SME_PID_OFFSET) != pid)) + continue; + + DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \ +from the share file %s\n", i, num_entries, fname)); + + SSVAL(p,SME_PORT_OFFSET,0); + SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0); + found = True; + break; + } + + if(!found) + { + DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname)); + if(buf) + free(buf); + return False; + } + + /* Re-write the file - and truncate it at the correct point. */ + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \ +position 0 for share mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); + if(write(fd, buf, fsize) != fsize) + { + DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \ +mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + return True; +} + + + +/******************************************************************* +call the specified function on each entry under management by the +share ode system +********************************************************************/ +static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) +{ + int i, count=0; + void *dir; + char *s; + share_mode_entry e; + + dir = opendir(lp_lockdir()); + if (!dir) { + return(0); + } + + while ((s=readdirname(dir))) { + char *buf; + char *base; + int fd; + pstring lname; + uint32 dev,inode; + BOOL new_file; + pstring fname; + + 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) { + continue; + } + + /* Lock the share mode file while we read it. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) { + close(fd); + continue; + } + + if(read_share_file( 0, fd, lname, &buf, &new_file)) { + 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); + e.pid = IVAL(p,SME_PID_OFFSET); + e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); + e.time.tv_sec = IVAL(p,SME_SEC_OFFSET); + e.time.tv_usec = IVAL(p,SME_USEC_OFFSET); + e.op_port = SVAL(p,SME_PORT_OFFSET); + e.pid = SVAL(p,SME_PID_OFFSET); + e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); + + fn(&e, fname); + count++; + } /* end for i */ + + if(buf) + free(buf); + base = 0; + } /* end while */ + closedir(dir); + + return count; +} + + +/******************************************************************* +dump the state of the system +********************************************************************/ +static void slow_share_status(FILE *f) +{ + +} + + +static struct share_ops share_ops = { + slow_stop_share_mode_mgmt, + slow_lock_share_entry, + slow_unlock_share_entry, + slow_get_share_modes, + slow_del_share_mode, + slow_set_share_mode, + slow_remove_share_oplock, + slow_share_forall, + slow_share_status, +}; + +/******************************************************************* + initialize the slow share_mode management + ******************************************************************/ +struct share_ops *locking_slow_init(void) +{ + if (!directory_exist(lp_lockdir(),NULL)) { + mkdir(lp_lockdir(),0755); + if (!directory_exist(lp_lockdir(),NULL)) + return NULL; + } + + return &share_ops; +} -- cgit From 79f4fb52c1ed56fd843f81b4eb0cdd2991d4d0f4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Oct 1997 18:52:04 +0000 Subject: loadparm.c: Changed 'interfaces only' parameter to 'bind interfaces only'. Added 'dos filetimes' parameter for UTIME fix. locking_shm.c: Fixed typo (sorry Andrew :-). namepacket.c: Changed lp_interfaces_only() to lp_bind_interfaces_only(). proto.h: The usual. reply.c: Made filetime calls use new file_utime call (wrapper for sys_utime). server.c: Made filetime calls use new file_utime call (wrapper for sys_utime). system.c: Added Andrew's sanity checks to times in sys_utime(). time.c: Moved set_filetime() to server.c. Made null_mtime() global. trans2.c: Made filetime calls use new file_utime call (wrapper for sys_utime). Jeremy (jallison@whistle.com) (This used to be commit 41a1d81c112a82ad2ae1b3c4ee81051f133ce1ed) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/locking/locking_shm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 99d981ed20..47074cff6b 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -636,7 +636,7 @@ mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_en /******************************************************************* call the specified function on each entry under management by the -share ode system +share mode system ********************************************************************/ static int shm_share_forall(void (*fn)(share_mode_entry *, char *)) { -- cgit From f20e6f6b261c3976b412845000b3f170f8ad6a9f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 22 Oct 1997 11:15:14 +0000 Subject: shared memory code cleanups (partly preparing for a possible sysV shared memory implementation) (This used to be commit 8d1993c71a5d5d32636f62ba9b9a9009ec74d730) --- source3/locking/locking_shm.c | 32 +++++++++++++++---------------- source3/locking/shmem.c | 44 +++++++++++++++++-------------------------- 2 files changed, 33 insertions(+), 43 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 47074cff6b..8383b687e4 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -42,19 +42,19 @@ 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 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 */ + int 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 next_share_mode_entry; share_mode_entry e; } shm_share_mode_entry; @@ -89,7 +89,7 @@ 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; + int *mode_array; unsigned int hash_entry = HASH_ENTRY(dev, inode); share_mode_record *file_scanner_p; share_mode_record *file_prev_p; @@ -111,7 +111,7 @@ static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, return 0; } - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + mode_array = (int *)smb_shm_offset2addr(smb_shm_get_userdef_off()); if(mode_array[hash_entry] == NULL_OFFSET) { @@ -267,7 +267,7 @@ 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; + int *mode_array; unsigned int hash_entry; share_mode_record *file_scanner_p; share_mode_record *file_prev_p; @@ -290,7 +290,7 @@ static void shm_del_share_mode(int token, int fnum) return; } - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + mode_array = (int *)smb_shm_offset2addr(smb_shm_get_userdef_off()); if(mode_array[hash_entry] == NULL_OFFSET) { @@ -408,12 +408,12 @@ 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; + int *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; + int new_entry_offset; BOOL found = False; dev = fs_p->fd_ptr->dev; @@ -429,7 +429,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) return False; } - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + mode_array = (int *)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; @@ -453,7 +453,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) { /* 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) + + int new_offset = smb_shm_alloc( sizeof(share_mode_record) + strlen(fs_p->name) + 1); if(new_offset == NULL_OFFSET) { @@ -482,7 +482,7 @@ inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_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]; + int 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; @@ -528,7 +528,7 @@ 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; + int *mode_array; unsigned int hash_entry; share_mode_record *file_scanner_p; share_mode_record *file_prev_p; @@ -551,7 +551,7 @@ static BOOL shm_remove_share_oplock(int fnum, int token) return False; } - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + mode_array = (int *)smb_shm_offset2addr(smb_shm_get_userdef_off()); if(mode_array[hash_entry] == NULL_OFFSET) { @@ -641,10 +641,10 @@ share mode system static int shm_share_forall(void (*fn)(share_mode_entry *, char *)) { int i, count=0; - smb_shm_offset_t *mode_array; + int *mode_array; share_mode_record *file_scanner_p; - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + mode_array = (int *)smb_shm_offset2addr(smb_shm_get_userdef_off()); for( i = 0; i < lp_shmem_hash_size(); i++) { smb_shm_lock_hash_entry(i); diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index bbb11f215a..9daca3e482 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -43,8 +43,8 @@ struct SmbShmHeader int smb_shm_version; int total_size; /* in bytes */ BOOL consistent; - smb_shm_offset_t first_free_off; - smb_shm_offset_t userdef_off; /* a userdefined offset. can be used to store root of tree or list */ + int first_free_off; + int userdef_off; /* a userdefined offset. can be used to store root of tree or list */ struct { /* a cell is a range of bytes of sizeof(struct SmbShmBlockDesc) size */ int cells_free; int cells_used; @@ -55,7 +55,7 @@ struct SmbShmHeader #define SMB_SHM_NOT_FREE_OFF (-1) struct SmbShmBlockDesc { - smb_shm_offset_t next; /* offset of next block in the free list or SMB_SHM_NOT_FREE_OFF when block in use */ + int next; /* offset of next block in the free list or SMB_SHM_NOT_FREE_OFF when block in use */ int size; /* user size in BlockDescSize units */ }; @@ -141,10 +141,9 @@ static BOOL smb_shm_global_unlock(void) * Function to create the hash table for the share mode entries. Called * when smb shared memory is global locked. */ - -BOOL smb_shm_create_hash_table( unsigned int size ) +static BOOL smb_shm_create_hash_table( unsigned int size ) { - size *= sizeof(smb_shm_offset_t); + size *= sizeof(int); smb_shm_global_lock(); smb_shm_header_p->userdef_off = smb_shm_alloc( size ); @@ -381,7 +380,7 @@ static void smb_shm_solve_neighbors(struct SmbShmBlockDesc *head_p ) -BOOL smb_shm_open( char *file_name, int size) +BOOL smb_shm_open(char *file_name, int size) { int filesize; BOOL created_new = False; @@ -533,13 +532,13 @@ BOOL smb_shm_close( void ) return True; } -smb_shm_offset_t smb_shm_alloc(int size) +int smb_shm_alloc(int size) { unsigned num_cells ; struct SmbShmBlockDesc *scanner_p; struct SmbShmBlockDesc *prev_p; struct SmbShmBlockDesc *new_p; - smb_shm_offset_t result_offset; + int result_offset; if( !smb_shm_header_p ) @@ -637,7 +636,7 @@ smb_shm_offset_t smb_shm_alloc(int size) -BOOL smb_shm_free(smb_shm_offset_t offset) +BOOL smb_shm_free(int offset) { struct SmbShmBlockDesc *header_p ; /* pointer to header of block to free */ struct SmbShmBlockDesc *scanner_p ; /* used to scan the list */ @@ -716,7 +715,7 @@ BOOL smb_shm_free(smb_shm_offset_t offset) } } -smb_shm_offset_t smb_shm_get_userdef_off(void) +int smb_shm_get_userdef_off(void) { if (!smb_shm_header_p) return NULL_OFFSET; @@ -724,16 +723,7 @@ smb_shm_offset_t smb_shm_get_userdef_off(void) return smb_shm_header_p->userdef_off; } -BOOL smb_shm_set_userdef_off(smb_shm_offset_t userdef_off) -{ - if (!smb_shm_header_p) - return False; - else - smb_shm_header_p->userdef_off = userdef_off; - return True; -} - -void *smb_shm_offset2addr(smb_shm_offset_t offset) +void *smb_shm_offset2addr(int offset) { if (offset == NULL_OFFSET ) return (void *)(0); @@ -744,7 +734,7 @@ void *smb_shm_offset2addr(smb_shm_offset_t offset) return (void *)((char *)smb_shm_header_p + offset ); } -smb_shm_offset_t smb_shm_addr2offset(void *addr) +int smb_shm_addr2offset(void *addr) { if (!addr) return NULL_OFFSET; @@ -752,7 +742,7 @@ smb_shm_offset_t smb_shm_addr2offset(void *addr) if (!smb_shm_header_p) return NULL_OFFSET; - return (smb_shm_offset_t)((char *)addr - (char *)smb_shm_header_p); + return (int)((char *)addr - (char *)smb_shm_header_p); } /******************************************************************* @@ -761,7 +751,7 @@ smb_shm_offset_t smb_shm_addr2offset(void *addr) BOOL smb_shm_lock_hash_entry( unsigned int entry) { - int start = (smb_shm_header_p->userdef_off + (entry * sizeof(smb_shm_offset_t))); + int start = (smb_shm_header_p->userdef_off + (entry * sizeof(int))); if (smb_shm_fd < 0) { @@ -776,7 +766,7 @@ BOOL smb_shm_lock_hash_entry( unsigned int entry) } /* Do an exclusive wait lock on the 4 byte region mapping into this entry */ - if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_WRLCK) == False) + if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(int), F_WRLCK) == False) { DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno))); return False; @@ -792,7 +782,7 @@ BOOL smb_shm_lock_hash_entry( unsigned int entry) BOOL smb_shm_unlock_hash_entry( unsigned int entry ) { - int start = (smb_shm_header_p->userdef_off + (entry * sizeof(smb_shm_offset_t))); + int start = (smb_shm_header_p->userdef_off + (entry * sizeof(int))); if (smb_shm_fd < 0) { @@ -807,7 +797,7 @@ BOOL smb_shm_unlock_hash_entry( unsigned int entry ) } /* Do a wait lock on the 4 byte region mapping into this entry */ - if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_UNLCK) == False) + if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(int), F_UNLCK) == False) { DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno))); return False; -- cgit From 71d648cdb431ecf984196a7e480208a94fcdf390 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Oct 1997 14:27:17 +0000 Subject: change the default file permissions on the SHARE_MEM_FILE* to 0644. smbstatus now gets only read permission on the share files and does no locking. also get rid of some unnecessary umask(0) calls. smbd always runs with umask(0) (This used to be commit c6ac10170dbba57dfebc54c50d79cb29d13bb442) --- source3/locking/locking.c | 6 ++--- source3/locking/locking_shm.c | 11 ++++++--- source3/locking/locking_slow.c | 39 +++++++++++++++++++----------- source3/locking/shmem.c | 55 ++++++++++++++++++++++++++---------------- 4 files changed, 70 insertions(+), 41 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index c75497c6b9..ae977b0f69 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -111,17 +111,17 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * /**************************************************************************** initialise the locking functions ****************************************************************************/ -BOOL locking_init(void) +BOOL locking_init(int read_only) { #ifdef FAST_SHARE_MODES - share_ops = locking_shm_init(); + share_ops = locking_shm_init(read_only); if (!share_ops) { DEBUG(0,("ERROR: Failed to initialise fast share modes - trying slow code\n")); } if (share_ops) return True; #endif - share_ops = locking_slow_init(); + share_ops = locking_slow_init(read_only); if (!share_ops) { DEBUG(0,("ERROR: Failed to initialise share modes!\n")); return False; diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 8383b687e4..410fcb9760 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -58,6 +58,7 @@ typedef struct share_mode_entry e; } shm_share_mode_entry; +static int read_only; /******************************************************************* deinitialize the shared memory for share_mode management @@ -715,17 +716,21 @@ static struct share_ops share_ops = { /******************************************************************* initialize the shared memory for share_mode management ******************************************************************/ -struct share_ops *locking_shm_init(void) +struct share_ops *locking_shm_init(int ronly) { pstring shmem_file_name; + + read_only = ronly; pstrcpy(shmem_file_name,lp_lockdir()); - if (!directory_exist(shmem_file_name,NULL)) + if (!directory_exist(shmem_file_name,NULL)) { + if (read_only) return 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())) + if (smb_shm_open(shmem_file_name, lp_shmem_size(), read_only)) return &share_ops; return NULL; } diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index cc646c6ca6..9bd6d65aa7 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -58,6 +58,14 @@ extern files_struct Files[]; #define SME_PORT_OFFSET 16 #define SME_OPLOCK_TYPE_OFFSET 18 +/* we need world read for smbstatus to function correctly */ +#ifdef SECURE_SHARE_MODES +#define SHARE_FILE_MODE 0600 +#else +#define SHARE_FILE_MODE 0644 +#endif + +static int read_only; /******************************************************************* deinitialize share_mode management @@ -87,6 +95,8 @@ Force a share file to be deleted. ********************************************************************/ static int delete_share_file( int cnum, char *fname ) { + if (read_only) return -1; + /* the share file could be owned by anyone, so do this as root */ become_root(False); @@ -120,14 +130,13 @@ static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) if(!share_name(cnum, dev, inode, fname)) return False; + if (read_only) return True; + /* we need to do this as root */ become_root(False); { - int old_umask; BOOL gotlock = False; - old_umask = umask(0); - /* * There was a race condition in the original slow share mode code. * A smbd could open a share mode file, and before getting @@ -147,11 +156,8 @@ static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) { struct stat dummy_stat; -#ifdef SECURE_SHARE_MODES - fd = (int)open(fname,O_RDWR|O_CREAT,0600); -#else /* SECURE_SHARE_MODES */ - fd = (int)open(fname,O_RDWR|O_CREAT,0666); -#endif /* SECURE_SHARE_MODES */ + fd = (int)open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT), + SHARE_FILE_MODE); if(fd < 0) { @@ -192,8 +198,6 @@ static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) * as we don't want to return and leave ourselves running * as root ! */ - - umask(old_umask); } *ptok = (int)fd; @@ -214,6 +218,8 @@ static BOOL slow_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int toke struct stat sb; pstring fname; + if (read_only) return True; + /* Fix for zero length share files from Gerald Werner */ @@ -959,13 +965,14 @@ static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) strcat(lname,"/"); strcat(lname,s); - fd = open(lname,O_RDWR,0); + fd = open(lname,read_only?O_RDONLY:O_RDWR,0); if (fd < 0) { continue; } /* Lock the share mode file while we read it. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) { + if(!read_only && + fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) { close(fd); continue; } @@ -1027,10 +1034,14 @@ static struct share_ops share_ops = { /******************************************************************* initialize the slow share_mode management ******************************************************************/ -struct share_ops *locking_slow_init(void) +struct share_ops *locking_slow_init(int ronly) { + + read_only = ronly; + if (!directory_exist(lp_lockdir(),NULL)) { - mkdir(lp_lockdir(),0755); + if (!read_only) + mkdir(lp_lockdir(),0755); if (!directory_exist(lp_lockdir(),NULL)) return NULL; } diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 9daca3e482..1f9cb8b732 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -34,6 +34,13 @@ extern int DEBUGLEVEL; #define SMB_SHM_VERSION 2 +/* we need world read for smbstatus to function correctly */ +#ifdef SECURE_SHARE_MODES +#define SHM_FILE_MODE 0600 +#else +#define SHM_FILE_MODE 0644 +#endif + /* WARNING : offsets are used because mmap() does not guarantee that all processes have the shared memory mapped to the same address */ @@ -75,6 +82,8 @@ static int smb_shm_times_locked = 0; static BOOL smb_shm_initialize_called = False; +static int read_only; + static BOOL smb_shm_global_lock(void) { if (smb_shm_fd < 0) @@ -90,6 +99,9 @@ static BOOL smb_shm_global_lock(void) DEBUG(5,("smb_shm_global_lock : locked %d times\n",smb_shm_times_locked)); return True; } + + if (read_only) + return True; /* Do an exclusive wait lock on the first byte of the file */ if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_WRLCK) == False) @@ -124,6 +136,9 @@ static BOOL smb_shm_global_unlock(void) DEBUG(5,("smb_shm_global_unlock : still locked %d times\n",smb_shm_times_locked)); return True; } + + if (read_only) + return True; /* Do a wait unlock on the first byte of the file */ if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_UNLCK) == False) @@ -170,11 +185,10 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth int free_slot = -1; int erased_slot; -#ifndef SECURE_SHARE_MODES - smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0666); -#else /* SECURE_SHARE_MODES */ - smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0600); -#endif /* SECURE_SHARE_MODES */ + smb_shm_processes_fd = open(processreg_file, + read_only?O_RDONLY:(O_RDWR|O_CREAT), + SHM_FILE_MODE); + if ( smb_shm_processes_fd < 0 ) { DEBUG(0,("ERROR smb_shm_register_process : processreg_file open failed with code %s\n",strerror(errno))); @@ -231,7 +245,6 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) { - int old_umask; int smb_shm_processes_fd = -1; int nb_read; pid_t other_pid; @@ -240,9 +253,7 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) BOOL found = False; - old_umask = umask(0); smb_shm_processes_fd = open(processreg_file, O_RDWR); - umask(old_umask); if ( smb_shm_processes_fd < 0 ) { DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file open failed with code %s\n",strerror(errno))); @@ -380,22 +391,19 @@ static void smb_shm_solve_neighbors(struct SmbShmBlockDesc *head_p ) -BOOL smb_shm_open(char *file_name, int size) +BOOL smb_shm_open(char *file_name, int size, int ronly) { int filesize; BOOL created_new = False; BOOL other_processes = True; - int old_umask; + + read_only = ronly; DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); - old_umask = umask(0); -#ifndef SECURE_SHARE_MODES - smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0666); -#else /* SECURE_SHARE_MODES */ - smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0600); -#endif /* SECURE_SHARE_MODE */ - umask(old_umask); + smb_shm_fd = open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), + SHM_FILE_MODE); + if ( smb_shm_fd < 0 ) { DEBUG(0,("ERROR smb_shm_open : open failed with code %s\n",strerror(errno))); @@ -433,14 +441,15 @@ BOOL smb_shm_open(char *file_name, int size) strcpy(smb_shm_processreg_name, file_name); strcat(smb_shm_processreg_name, ".processes"); - if (! smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes)) + if (!read_only && + !smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes)) { smb_shm_global_unlock(); close(smb_shm_fd); return False; } - if (created_new || !other_processes) + if (!read_only && (created_new || !other_processes)) { /* we just created a new one, or are the first opener, lets set it size */ if( ftruncate(smb_shm_fd, size) <0) @@ -466,7 +475,11 @@ BOOL smb_shm_open(char *file_name, int size) size = filesize; } - smb_shm_header_p = (struct SmbShmHeader *)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, smb_shm_fd, 0); + smb_shm_header_p = (struct SmbShmHeader *)mmap(NULL, size, + read_only?PROT_READ: + (PROT_READ | PROT_WRITE), + MAP_FILE | MAP_SHARED, + smb_shm_fd, 0); /* WARNING, smb_shm_header_p can be different for different processes mapping the same file ! */ if (smb_shm_header_p == (struct SmbShmHeader *)(-1)) { @@ -478,7 +491,7 @@ BOOL smb_shm_open(char *file_name, int size) } - if (created_new || !other_processes) + if (!read_only && (created_new || !other_processes)) { smb_shm_initialize(size); /* Create the hash buckets for the share file entries. */ -- cgit From c9fa24b7a8809a7963f0970cf2dd21f6804e31a4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Oct 1997 14:19:54 +0000 Subject: SYSV IPC implementation of fast share modes. It will try sysv IPC first, then if that fails it will try mmap(), then after that it will try share files. I have defined USE_SYSV_IPC for Linux, Solaris and HPUX at the moment. Probably a lot more could have it defined. In fact, the vast majority of systems support it. Need autoconf again :-) It should actually be faster than the mmap() version, and doesn't need any lock files. This means the problem of the share mem file being on a NFS drive will be gone. (This used to be commit cc8fe0f0629eea9acc39e30d8d76d5890a5b6978) --- source3/locking/locking_shm.c | 106 +++---- source3/locking/shmem.c | 531 +++++++++++++++++++----------------- source3/locking/shmem_sysv.c | 621 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 952 insertions(+), 306 deletions(-) create mode 100644 source3/locking/shmem_sysv.c (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 410fcb9760..f2ae641808 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -39,6 +39,8 @@ extern int DEBUGLEVEL; extern connection_struct Connections[]; extern files_struct Files[]; +static struct shmem_ops *shmops; + /* share mode record pointed to in shared memory hash bucket */ typedef struct { @@ -65,7 +67,7 @@ static int read_only; ******************************************************************/ static BOOL shm_stop_share_mode_mgmt(void) { - return smb_shm_close(); + return shmops->close(); } /******************************************************************* @@ -73,7 +75,7 @@ static BOOL shm_stop_share_mode_mgmt(void) ******************************************************************/ static BOOL shm_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) { - return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode)); + return shmops->lock_hash_entry(HASH_ENTRY(dev, inode)); } /******************************************************************* @@ -81,7 +83,7 @@ static BOOL shm_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) ******************************************************************/ static BOOL shm_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token) { - return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode)); + return shmops->unlock_hash_entry(HASH_ENTRY(dev, inode)); } /******************************************************************* @@ -112,7 +114,7 @@ static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, return 0; } - mode_array = (int *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); if(mode_array[hash_entry] == NULL_OFFSET) { @@ -120,7 +122,7 @@ static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, return 0; } - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); + file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]); file_prev_p = file_scanner_p; while(file_scanner_p) { @@ -132,7 +134,7 @@ static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, else { file_prev_p = file_scanner_p ; - file_scanner_p = (share_mode_record *)smb_shm_offset2addr( + file_scanner_p = (share_mode_record *)shmops->offset2addr( file_scanner_p->next_offset); } } @@ -153,7 +155,7 @@ bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); 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)); + shmops->free(shmops->addr2offset(file_scanner_p)); return (0); } @@ -172,7 +174,7 @@ bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); num_entries_copied = 0; - entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr( + entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr( file_scanner_p->share_mode_entries); entry_prev_p = entry_scanner_p; while(entry_scanner_p) @@ -189,7 +191,7 @@ bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); { /* 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( + entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr( file_scanner_p->share_mode_entries); entry_prev_p = entry_scanner_p; } @@ -197,7 +199,7 @@ bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); { 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); + shmops->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; @@ -217,7 +219,7 @@ 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)); + shmops->free(shmops->addr2offset(delete_entry_p)); } else { @@ -235,7 +237,7 @@ bucket %d (number of entries now = %d)\n", 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); + shmops->offset2addr(entry_scanner_p->next_share_mode_entry); } } @@ -253,7 +255,7 @@ hash bucket %d has a share mode record but no entries - deleting\n", 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)); + shmops->free(shmops->addr2offset(file_scanner_p)); } DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \ @@ -291,7 +293,7 @@ static void shm_del_share_mode(int token, int fnum) return; } - mode_array = (int *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); if(mode_array[hash_entry] == NULL_OFFSET) { @@ -300,7 +302,7 @@ static void shm_del_share_mode(int token, int fnum) return; } - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); + file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]); file_prev_p = file_scanner_p; while(file_scanner_p) @@ -314,7 +316,7 @@ static void shm_del_share_mode(int token, int fnum) { file_prev_p = file_scanner_p ; file_scanner_p = (share_mode_record *) - smb_shm_offset2addr(file_scanner_p->next_offset); + shmops->offset2addr(file_scanner_p->next_offset); } } @@ -334,12 +336,12 @@ record due to old locking version %d for file dev %d, inode %d hash bucket %d\n" 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)); + shmops->free(shmops->addr2offset(file_scanner_p)); return; } found = False; - entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr( + entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr( file_scanner_p->share_mode_entries); entry_prev_p = entry_scanner_p; while(entry_scanner_p) @@ -355,7 +357,7 @@ record due to old locking version %d for file dev %d, inode %d hash bucket %d\n" { entry_prev_p = entry_scanner_p; entry_scanner_p = (shm_share_mode_entry *) - smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); + shmops->offset2addr(entry_scanner_p->next_share_mode_entry); } } @@ -372,7 +374,7 @@ Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries no 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)); + shmops->free(shmops->addr2offset(entry_scanner_p)); /* PARANOIA TEST */ if(file_scanner_p->num_share_mode_entries < 0) @@ -392,7 +394,7 @@ record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); 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)); + shmops->free(shmops->addr2offset(file_scanner_p)); } } else @@ -430,9 +432,9 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) return False; } - mode_array = (int *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); + file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]); file_prev_p = file_scanner_p; while(file_scanner_p) @@ -446,7 +448,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) { file_prev_p = file_scanner_p ; file_scanner_p = (share_mode_record *) - smb_shm_offset2addr(file_scanner_p->next_offset); + shmops->offset2addr(file_scanner_p->next_offset); } } @@ -454,14 +456,14 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) { /* We must create a share_mode_record */ share_mode_record *new_mode_p = NULL; - int new_offset = smb_shm_alloc( sizeof(share_mode_record) + + int new_offset = shmops->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")); + DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): shmops->alloc fail !\n")); return False; } - new_mode_p = smb_shm_offset2addr(new_offset); + new_mode_p = shmops->offset2addr(new_offset); new_mode_p->locking_version = LOCKING_VERSION; new_mode_p->st_dev = dev; new_mode_p->st_ino = inode; @@ -480,19 +482,19 @@ 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)); + new_entry_offset = shmops->alloc( sizeof(shm_share_mode_entry)); if(new_entry_offset == NULL_OFFSET) { int delete_offset = mode_array[hash_entry]; - DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n")); + DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): shmops->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 ); + shmops->free( delete_offset ); return False; } - new_entry_p = smb_shm_offset2addr(new_entry_offset); + new_entry_p = shmops->offset2addr(new_entry_offset); new_entry_p->e.pid = getpid(); new_entry_p->e.share_mode = fs_p->share_mode; @@ -552,7 +554,7 @@ static BOOL shm_remove_share_oplock(int fnum, int token) return False; } - mode_array = (int *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); if(mode_array[hash_entry] == NULL_OFFSET) { @@ -561,7 +563,7 @@ static BOOL shm_remove_share_oplock(int fnum, int token) return False; } - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); + file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]); file_prev_p = file_scanner_p; while(file_scanner_p) @@ -575,7 +577,7 @@ static BOOL shm_remove_share_oplock(int fnum, int token) { file_prev_p = file_scanner_p ; file_scanner_p = (share_mode_record *) - smb_shm_offset2addr(file_scanner_p->next_offset); + shmops->offset2addr(file_scanner_p->next_offset); } } @@ -595,12 +597,12 @@ record due to old locking version %d for file dev %d, inode %d hash bucket %d\n" 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)); + shmops->free(shmops->addr2offset(file_scanner_p)); return False; } found = False; - entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr( + entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr( file_scanner_p->share_mode_entries); entry_prev_p = entry_scanner_p; while(entry_scanner_p) @@ -620,7 +622,7 @@ record due to old locking version %d for file dev %d, inode %d hash bucket %d\n" { entry_prev_p = entry_scanner_p; entry_scanner_p = (shm_share_mode_entry *) - smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); + shmops->offset2addr(entry_scanner_p->next_share_mode_entry); } } @@ -645,21 +647,21 @@ static int shm_share_forall(void (*fn)(share_mode_entry *, char *)) int *mode_array; share_mode_record *file_scanner_p; - mode_array = (int *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); for( i = 0; i < lp_shmem_hash_size(); i++) { - smb_shm_lock_hash_entry(i); + shmops->lock_hash_entry(i); if(mode_array[i] == NULL_OFFSET) { - smb_shm_unlock_hash_entry(i); + shmops->unlock_hash_entry(i); continue; } - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[i]); + file_scanner_p = (share_mode_record *)shmops->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); + shmops->offset2addr(file_scanner_p->share_mode_entries); while(entry_scanner_p != 0) { @@ -668,14 +670,14 @@ static int shm_share_forall(void (*fn)(share_mode_entry *, char *)) entry_scanner_p = (shm_share_mode_entry *) - smb_shm_offset2addr( + shmops->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); + shmops->offset2addr(file_scanner_p->next_offset); } /* end while file_scanner_p */ - smb_shm_unlock_hash_entry(i); + shmops->unlock_hash_entry(i); } /* end for */ return count; @@ -689,7 +691,7 @@ 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); + shmops->get_usage(&bytes_free, &bytes_used, &bytes_overhead); bytes_total = bytes_free + bytes_used + bytes_overhead; fprintf(f, "Share mode memory usage (bytes):\n"); @@ -721,7 +723,12 @@ struct share_ops *locking_shm_init(int ronly) pstring shmem_file_name; read_only = ronly; - + +#ifdef USE_SYSV_IPC + shmops = sysv_shm_open(lp_shmem_size(), read_only); + if (shmops) return &share_ops; +#endif + pstrcpy(shmem_file_name,lp_lockdir()); if (!directory_exist(shmem_file_name,NULL)) { if (read_only) return NULL; @@ -730,8 +737,9 @@ struct share_ops *locking_shm_init(int ronly) 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(), read_only)) - return &share_ops; + shmops = smb_shm_open(shmem_file_name, lp_shmem_size(), read_only); + if (shmops) return &share_ops; + return NULL; } diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 1f9cb8b732..72d7c07751 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -152,6 +152,136 @@ static BOOL smb_shm_global_unlock(void) } + +static void *smb_shm_offset2addr(int offset) +{ + if (offset == NULL_OFFSET ) + return (void *)(0); + + if (!smb_shm_header_p) + return (void *)(0); + + return (void *)((char *)smb_shm_header_p + offset ); +} + +static int smb_shm_addr2offset(void *addr) +{ + if (!addr) + return NULL_OFFSET; + + if (!smb_shm_header_p) + return NULL_OFFSET; + + return (int)((char *)addr - (char *)smb_shm_header_p); +} + + + +static int smb_shm_alloc(int size) +{ + unsigned num_cells ; + struct SmbShmBlockDesc *scanner_p; + struct SmbShmBlockDesc *prev_p; + struct SmbShmBlockDesc *new_p; + int result_offset; + + + if( !smb_shm_header_p ) + { + /* not mapped yet */ + DEBUG(0,("ERROR smb_shm_alloc : shmem not mapped\n")); + return NULL_OFFSET; + } + + smb_shm_global_lock(); + + if( !smb_shm_header_p->consistent) + { + DEBUG(0,("ERROR smb_shm_alloc : shmem not consistent\n")); + smb_shm_global_unlock(); + return NULL_OFFSET; + } + + + /* calculate the number of cells */ + num_cells = (size + CellSize -1) / CellSize; + + /* set start of scan */ + prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); + scanner_p = prev_p ; + + /* scan the free list to find a matching free space */ + while ( ( scanner_p != EOList_Addr ) && ( scanner_p->size < num_cells ) ) + { + prev_p = scanner_p; + scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next); + } + + /* at this point scanner point to a block header or to the end of the list */ + if ( scanner_p == EOList_Addr ) + { + DEBUG(0,("ERROR smb_shm_alloc : alloc of %d bytes failed, no free space found\n",size)); + smb_shm_global_unlock(); + return (NULL_OFFSET); + } + + /* going to modify shared mem */ + smb_shm_header_p->consistent = False; + + /* if we found a good one : scanner == the good one */ + if ( scanner_p->size <= num_cells + 2 ) + { + /* there is no use in making a new one, it will be too small anyway + * we will link out scanner + */ + if ( prev_p == scanner_p ) + { + smb_shm_header_p->first_free_off = scanner_p->next ; + } + else + { + prev_p->next = scanner_p->next ; + } + smb_shm_header_p->statistics.cells_free -= scanner_p->size; + smb_shm_header_p->statistics.cells_used += scanner_p->size; + } + else + { + /* Make a new one */ + new_p = scanner_p + 1 + num_cells; + new_p->size = scanner_p->size - num_cells - 1; + new_p->next = scanner_p->next; + scanner_p->size = num_cells; + scanner_p->next = smb_shm_addr2offset(new_p); + + if ( prev_p != scanner_p ) + { + prev_p->next = smb_shm_addr2offset(new_p) ; + } + else + { + smb_shm_header_p->first_free_off = smb_shm_addr2offset(new_p) ; + } + smb_shm_header_p->statistics.cells_free -= num_cells+1; + smb_shm_header_p->statistics.cells_used += num_cells; + smb_shm_header_p->statistics.cells_system += 1; + } + + result_offset = smb_shm_addr2offset( &(scanner_p[1]) ); + scanner_p->next = SMB_SHM_NOT_FREE_OFF ; + + /* end modification of shared mem */ + smb_shm_header_p->consistent = True; + + DEBUG(6,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); + + smb_shm_global_unlock(); + return ( result_offset ); +} + + + + /* * Function to create the hash table for the share mode entries. Called * when smb shared memory is global locked. @@ -391,130 +521,7 @@ static void smb_shm_solve_neighbors(struct SmbShmBlockDesc *head_p ) -BOOL smb_shm_open(char *file_name, int size, int ronly) -{ - int filesize; - BOOL created_new = False; - BOOL other_processes = True; - - read_only = ronly; - - DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); - - smb_shm_fd = open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), - SHM_FILE_MODE); - - if ( smb_shm_fd < 0 ) - { - DEBUG(0,("ERROR smb_shm_open : open failed with code %s\n",strerror(errno))); - return False; - } - - if (!smb_shm_global_lock()) - { - DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n")); - return False; - } - - if( (filesize = lseek(smb_shm_fd, 0, SEEK_END)) < 0) - { - DEBUG(0,("ERROR smb_shm_open : lseek failed with code %s\n",strerror(errno))); - smb_shm_global_unlock(); - close(smb_shm_fd); - return False; - } - - /* return the file offset to 0 to save on later seeks */ - lseek(smb_shm_fd,0,SEEK_SET); - - if (filesize == 0) - { - /* we just created a new one */ - created_new = True; - } - - /* to find out if some other process is already mapping the file, - we use a registration file containing the processids of the file mapping processes - */ - - /* construct processreg file name */ - strcpy(smb_shm_processreg_name, file_name); - strcat(smb_shm_processreg_name, ".processes"); - - if (!read_only && - !smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes)) - { - smb_shm_global_unlock(); - close(smb_shm_fd); - return False; - } - - if (!read_only && (created_new || !other_processes)) - { - /* we just created a new one, or are the first opener, lets set it size */ - if( ftruncate(smb_shm_fd, size) <0) - { - DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %s\n",strerror(errno))); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return False; - } - - /* paranoia */ - lseek(smb_shm_fd,0,SEEK_SET); - - filesize = size; - } - - if (size != filesize ) - { - /* the existing file has a different size and we are not the first opener. - Since another process is still using it, we will use the file size */ - DEBUG(0,("WARNING smb_shm_open : filesize (%d) != expected size (%d), using filesize\n",filesize,size)); - size = filesize; - } - - smb_shm_header_p = (struct SmbShmHeader *)mmap(NULL, size, - read_only?PROT_READ: - (PROT_READ | PROT_WRITE), - MAP_FILE | MAP_SHARED, - smb_shm_fd, 0); - /* WARNING, smb_shm_header_p can be different for different processes mapping the same file ! */ - if (smb_shm_header_p == (struct SmbShmHeader *)(-1)) - { - DEBUG(0,("ERROR smb_shm_open : mmap failed with code %s\n",strerror(errno))); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return False; - } - - - if (!read_only && (created_new || !other_processes)) - { - smb_shm_initialize(size); - /* Create the hash buckets for the share file entries. */ - smb_shm_create_hash_table( lp_shmem_hash_size() ); - } - else if (!smb_shm_validate_header(size) ) - { - /* existing file is corrupt, samba admin should remove it by hand */ - DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n")); - munmap((caddr_t)smb_shm_header_p, size); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return False; - } - - smb_shm_global_unlock(); - return True; - -} - - -BOOL smb_shm_close( void ) +static BOOL smb_shm_close( void ) { if(smb_shm_initialize_called == False) @@ -545,111 +552,8 @@ BOOL smb_shm_close( void ) return True; } -int smb_shm_alloc(int size) -{ - unsigned num_cells ; - struct SmbShmBlockDesc *scanner_p; - struct SmbShmBlockDesc *prev_p; - struct SmbShmBlockDesc *new_p; - int result_offset; - - - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_alloc : shmem not mapped\n")); - return NULL_OFFSET; - } - - smb_shm_global_lock(); - if( !smb_shm_header_p->consistent) - { - DEBUG(0,("ERROR smb_shm_alloc : shmem not consistent\n")); - smb_shm_global_unlock(); - return NULL_OFFSET; - } - - - /* calculate the number of cells */ - num_cells = (size + CellSize -1) / CellSize; - - /* set start of scan */ - prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); - scanner_p = prev_p ; - - /* scan the free list to find a matching free space */ - while ( ( scanner_p != EOList_Addr ) && ( scanner_p->size < num_cells ) ) - { - prev_p = scanner_p; - scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next); - } - - /* at this point scanner point to a block header or to the end of the list */ - if ( scanner_p == EOList_Addr ) - { - DEBUG(0,("ERROR smb_shm_alloc : alloc of %d bytes failed, no free space found\n",size)); - smb_shm_global_unlock(); - return (NULL_OFFSET); - } - - /* going to modify shared mem */ - smb_shm_header_p->consistent = False; - - /* if we found a good one : scanner == the good one */ - if ( scanner_p->size <= num_cells + 2 ) - { - /* there is no use in making a new one, it will be too small anyway - * we will link out scanner - */ - if ( prev_p == scanner_p ) - { - smb_shm_header_p->first_free_off = scanner_p->next ; - } - else - { - prev_p->next = scanner_p->next ; - } - smb_shm_header_p->statistics.cells_free -= scanner_p->size; - smb_shm_header_p->statistics.cells_used += scanner_p->size; - } - else - { - /* Make a new one */ - new_p = scanner_p + 1 + num_cells; - new_p->size = scanner_p->size - num_cells - 1; - new_p->next = scanner_p->next; - scanner_p->size = num_cells; - scanner_p->next = smb_shm_addr2offset(new_p); - - if ( prev_p != scanner_p ) - { - prev_p->next = smb_shm_addr2offset(new_p) ; - } - else - { - smb_shm_header_p->first_free_off = smb_shm_addr2offset(new_p) ; - } - smb_shm_header_p->statistics.cells_free -= num_cells+1; - smb_shm_header_p->statistics.cells_used += num_cells; - smb_shm_header_p->statistics.cells_system += 1; - } - - result_offset = smb_shm_addr2offset( &(scanner_p[1]) ); - scanner_p->next = SMB_SHM_NOT_FREE_OFF ; - - /* end modification of shared mem */ - smb_shm_header_p->consistent = True; - - DEBUG(6,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); - - smb_shm_global_unlock(); - return ( result_offset ); -} - - - -BOOL smb_shm_free(int offset) +static BOOL smb_shm_free(int offset) { struct SmbShmBlockDesc *header_p ; /* pointer to header of block to free */ struct SmbShmBlockDesc *scanner_p ; /* used to scan the list */ @@ -728,7 +632,7 @@ BOOL smb_shm_free(int offset) } } -int smb_shm_get_userdef_off(void) +static int smb_shm_get_userdef_off(void) { if (!smb_shm_header_p) return NULL_OFFSET; @@ -736,33 +640,10 @@ int smb_shm_get_userdef_off(void) return smb_shm_header_p->userdef_off; } -void *smb_shm_offset2addr(int offset) -{ - if (offset == NULL_OFFSET ) - return (void *)(0); - - if (!smb_shm_header_p) - return (void *)(0); - - return (void *)((char *)smb_shm_header_p + offset ); -} - -int smb_shm_addr2offset(void *addr) -{ - if (!addr) - return NULL_OFFSET; - - if (!smb_shm_header_p) - return NULL_OFFSET; - - return (int)((char *)addr - (char *)smb_shm_header_p); -} - /******************************************************************* Lock a particular hash bucket entry. ******************************************************************/ - -BOOL smb_shm_lock_hash_entry( unsigned int entry) +static BOOL smb_shm_lock_hash_entry( unsigned int entry) { int start = (smb_shm_header_p->userdef_off + (entry * sizeof(int))); @@ -792,8 +673,7 @@ BOOL smb_shm_lock_hash_entry( unsigned int entry) /******************************************************************* Unlock a particular hash bucket entry. ******************************************************************/ - -BOOL smb_shm_unlock_hash_entry( unsigned int entry ) +static BOOL smb_shm_unlock_hash_entry( unsigned int entry ) { int start = (smb_shm_header_p->userdef_off + (entry * sizeof(int))); @@ -823,8 +703,7 @@ BOOL smb_shm_unlock_hash_entry( unsigned int entry ) /******************************************************************* Gather statistics on shared memory usage. ******************************************************************/ - -BOOL smb_shm_get_usage(int *bytes_free, +static BOOL smb_shm_get_usage(int *bytes_free, int *bytes_used, int *bytes_overhead) { @@ -841,6 +720,144 @@ BOOL smb_shm_get_usage(int *bytes_free, return True; } + +static struct shmem_ops shmops = { + smb_shm_close, + smb_shm_alloc, + smb_shm_free, + smb_shm_get_userdef_off, + smb_shm_offset2addr, + smb_shm_addr2offset, + smb_shm_lock_hash_entry, + smb_shm_unlock_hash_entry, + smb_shm_get_usage, +}; + +/******************************************************************* + open the shared memory + ******************************************************************/ +struct shmem_ops *smb_shm_open(char *file_name, int size, int ronly) +{ + int filesize; + BOOL created_new = False; + BOOL other_processes = True; + + read_only = ronly; + + DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); + + smb_shm_fd = open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), + SHM_FILE_MODE); + + if ( smb_shm_fd < 0 ) + { + DEBUG(0,("ERROR smb_shm_open : open failed with code %s\n",strerror(errno))); + return NULL; + } + + if (!smb_shm_global_lock()) + { + DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n")); + return NULL; + } + + if( (filesize = lseek(smb_shm_fd, 0, SEEK_END)) < 0) + { + DEBUG(0,("ERROR smb_shm_open : lseek failed with code %s\n",strerror(errno))); + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; + } + + /* return the file offset to 0 to save on later seeks */ + lseek(smb_shm_fd,0,SEEK_SET); + + if (filesize == 0) + { + /* we just created a new one */ + created_new = True; + } + + /* to find out if some other process is already mapping the file, + we use a registration file containing the processids of the file mapping processes + */ + + /* construct processreg file name */ + strcpy(smb_shm_processreg_name, file_name); + strcat(smb_shm_processreg_name, ".processes"); + + if (!read_only && + !smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes)) + { + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; + } + + if (!read_only && (created_new || !other_processes)) + { + /* we just created a new one, or are the first opener, lets set it size */ + if( ftruncate(smb_shm_fd, size) <0) + { + DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %s\n",strerror(errno))); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; + } + + /* paranoia */ + lseek(smb_shm_fd,0,SEEK_SET); + + filesize = size; + } + + if (size != filesize ) + { + /* the existing file has a different size and we are not the first opener. + Since another process is still using it, we will use the file size */ + DEBUG(0,("WARNING smb_shm_open : filesize (%d) != expected size (%d), using filesize\n",filesize,size)); + size = filesize; + } + + smb_shm_header_p = (struct SmbShmHeader *)mmap(NULL, size, + read_only?PROT_READ: + (PROT_READ | PROT_WRITE), + MAP_FILE | MAP_SHARED, + smb_shm_fd, 0); + /* WARNING, smb_shm_header_p can be different for different processes mapping the same file ! */ + if (smb_shm_header_p == (struct SmbShmHeader *)(-1)) + { + DEBUG(0,("ERROR smb_shm_open : mmap failed with code %s\n",strerror(errno))); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; + } + + + if (!read_only && (created_new || !other_processes)) + { + smb_shm_initialize(size); + /* Create the hash buckets for the share file entries. */ + smb_shm_create_hash_table( lp_shmem_hash_size() ); + } + else if (!smb_shm_validate_header(size) ) + { + /* existing file is corrupt, samba admin should remove it by hand */ + DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n")); + munmap((caddr_t)smb_shm_header_p, size); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; + } + + smb_shm_global_unlock(); + return &shmops; +} + + #else /* FAST_SHARE_MODES */ int shmem_dummy_procedure(void) {return 0;} diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c new file mode 100644 index 0000000000..793e508c71 --- /dev/null +++ b/source3/locking/shmem_sysv.c @@ -0,0 +1,621 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Shared memory functions - SYSV IPC implementation + Copyright (C) Erik Devriendt 1996-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. + +*/ + +#include "includes.h" + + +#ifdef USE_SYSV_IPC + +extern int DEBUGLEVEL; + +#define SHMEM_KEY ((key_t)0x280267) +#define SEMAPHORE_KEY (SHMEM_KEY+2) + +#define SHM_MAGIC 0x53484100 +#define SHM_VERSION 2 + +#define IPC_PERMS ((SHM_R | SHM_W) | (SHM_R>>3) | (SHM_R>>6)) + +static int shm_id; +static int sem_id; +static int shm_size; +static int hash_size; +static int global_lock_count; + +struct ShmHeader { + int shm_magic; + int shm_version; + int total_size; /* in bytes */ + BOOL consistent; + int first_free_off; + int userdef_off; /* a userdefined offset. can be used to store + root of tree or list */ + struct { /* a cell is a range of bytes of sizeof(struct + ShmBlockDesc) size */ + int cells_free; + int cells_used; + int cells_system; /* number of cells used as allocated + block descriptors */ + } statistics; +}; + +#define SHM_NOT_FREE_OFF (-1) +struct ShmBlockDesc +{ + int next; /* offset of next block in the free list or + SHM_NOT_FREE_OFF when block in use */ + int size; /* user size in BlockDescSize units */ +}; + +#define EOList_Addr (struct ShmBlockDesc *)( 0 ) +#define EOList_Off (NULL_OFFSET) + +#define CellSize sizeof(struct ShmBlockDesc) + +/* HeaderSize aligned on 8 byte boundary */ +#define AlignedHeaderSize ((sizeof(struct ShmHeader)+7) & ~7) + +static struct ShmHeader *shm_header_p = (struct ShmHeader *)0; + +static BOOL shm_initialize_called = False; + +static int read_only; + +static BOOL sem_lock(int i) +{ + struct sembuf sb; + if (read_only) return True; + + sb.sem_num = i; + sb.sem_op = -1; + sb.sem_flg = SEM_UNDO; + + if (semop(sem_id, &sb, 1) != 0) { + DEBUG(0,("ERROR: IPC lock failed on semaphore %d\n", i)); + return False; + } + + return True; +} + +static BOOL sem_unlock(int i) +{ + struct sembuf sb; + if (read_only) return True; + + sb.sem_num = i; + sb.sem_op = 1; + sb.sem_flg = SEM_UNDO; + + if (semop(sem_id, &sb, 1) != 0) { + DEBUG(0,("ERROR: IPC unlock failed on semaphore %d\n", i)); + return False; + } + + return True; +} + +static BOOL global_lock(void) +{ + global_lock_count++; + if (global_lock_count == 1) + return sem_lock(0); + return True; +} + +static BOOL global_unlock(void) +{ + global_lock_count--; + if (global_lock_count == 0) + return sem_unlock(0); + return True; +} + +static void *shm_offset2addr(int offset) +{ + if (offset == NULL_OFFSET ) + return (void *)(0); + + if (!shm_header_p) + return (void *)(0); + + return (void *)((char *)shm_header_p + offset ); +} + +static int shm_addr2offset(void *addr) +{ + if (!addr) + return NULL_OFFSET; + + if (!shm_header_p) + return NULL_OFFSET; + + return (int)((char *)addr - (char *)shm_header_p); +} + + +static int shm_alloc(int size) +{ + unsigned num_cells ; + struct ShmBlockDesc *scanner_p; + struct ShmBlockDesc *prev_p; + struct ShmBlockDesc *new_p; + int result_offset; + + + if (!shm_header_p) { + /* not mapped yet */ + DEBUG(0,("ERROR shm_alloc : shmem not mapped\n")); + return NULL_OFFSET; + } + + global_lock(); + + if (!shm_header_p->consistent) { + DEBUG(0,("ERROR shm_alloc : shmem not consistent\n")); + global_unlock(); + return NULL_OFFSET; + } + + /* calculate the number of cells */ + num_cells = (size + CellSize -1) / CellSize; + + /* set start of scan */ + prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); + scanner_p = prev_p ; + + /* scan the free list to find a matching free space */ + while ((scanner_p != EOList_Addr) && (scanner_p->size < num_cells)) { + prev_p = scanner_p; + scanner_p = (struct ShmBlockDesc *)shm_offset2addr(scanner_p->next); + } + + /* at this point scanner point to a block header or to the end of + the list */ + if (scanner_p == EOList_Addr) { + DEBUG(0,("ERROR shm_alloc : alloc of %d bytes failed, no free space found\n",size)); + global_unlock(); + return (NULL_OFFSET); + } + + /* going to modify shared mem */ + shm_header_p->consistent = False; + + /* if we found a good one : scanner == the good one */ + if (scanner_p->size <= num_cells + 2) { + /* there is no use in making a new one, it will be too small anyway + * we will link out scanner + */ + if ( prev_p == scanner_p ) { + shm_header_p->first_free_off = scanner_p->next ; + } else { + prev_p->next = scanner_p->next ; + } + shm_header_p->statistics.cells_free -= scanner_p->size; + shm_header_p->statistics.cells_used += scanner_p->size; + } else { + /* Make a new one */ + new_p = scanner_p + 1 + num_cells; + new_p->size = scanner_p->size - num_cells - 1; + new_p->next = scanner_p->next; + scanner_p->size = num_cells; + scanner_p->next = shm_addr2offset(new_p); + + if (prev_p != scanner_p) { + prev_p->next = shm_addr2offset(new_p) ; + } else { + shm_header_p->first_free_off = shm_addr2offset(new_p); + } + shm_header_p->statistics.cells_free -= num_cells+1; + shm_header_p->statistics.cells_used += num_cells; + shm_header_p->statistics.cells_system += 1; + } + + result_offset = shm_addr2offset( &(scanner_p[1]) ); + scanner_p->next = SHM_NOT_FREE_OFF ; + + /* end modification of shared mem */ + shm_header_p->consistent = True; + + DEBUG(6,("shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); + + global_unlock(); + return result_offset; +} + + + +/* + * Function to create the hash table for the share mode entries. Called + * when smb shared memory is global locked. + */ +static BOOL shm_create_hash_table( unsigned int size ) +{ + size *= sizeof(int); + + global_lock(); + shm_header_p->userdef_off = shm_alloc( size ); + + if(shm_header_p->userdef_off == NULL_OFFSET) { + DEBUG(0,("shm_create_hash_table: Failed to create hash table of size %d\n",size)); + global_unlock(); + return False; + } + + /* Clear hash buckets. */ + memset( shm_offset2addr(shm_header_p->userdef_off), '\0', size); + global_unlock(); + return True; +} + +static BOOL shm_validate_header(int size) +{ + if( !shm_header_p ) { + /* not mapped yet */ + DEBUG(0,("ERROR shm_validate_header : shmem not mapped\n")); + return False; + } + + if(shm_header_p->shm_magic != SHM_MAGIC) { + DEBUG(0,("ERROR shm_validate_header : bad magic\n")); + return False; + } + + if(shm_header_p->shm_version != SHM_VERSION) { + DEBUG(0,("ERROR shm_validate_header : bad version %X\n",shm_header_p->shm_version)); + return False; + } + + if(shm_header_p->total_size != size) { + DEBUG(0,("ERROR shm_validate_header : shmem size mismatch (old = %d, new = %d)\n",shm_header_p->total_size,size)); + return False; + } + + if(!shm_header_p->consistent) { + DEBUG(0,("ERROR shm_validate_header : shmem not consistent\n")); + return False; + } + return True; +} + +static BOOL shm_initialize(int size) +{ + struct ShmBlockDesc * first_free_block_p; + + DEBUG(5,("shm_initialize : initializing shmem file of size %d\n",size)); + + if( !shm_header_p ) { + /* not mapped yet */ + DEBUG(0,("ERROR shm_initialize : shmem not mapped\n")); + return False; + } + + shm_header_p->shm_magic = SHM_MAGIC; + shm_header_p->shm_version = SHM_VERSION; + shm_header_p->total_size = size; + shm_header_p->first_free_off = AlignedHeaderSize; + shm_header_p->userdef_off = NULL_OFFSET; + + first_free_block_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); + first_free_block_p->next = EOList_Off; + first_free_block_p->size = ( size - AlignedHeaderSize - CellSize ) / CellSize ; + + shm_header_p->statistics.cells_free = first_free_block_p->size; + shm_header_p->statistics.cells_used = 0; + shm_header_p->statistics.cells_system = 1; + + shm_header_p->consistent = True; + + shm_initialize_called = True; + + return True; +} + +static void shm_solve_neighbors(struct ShmBlockDesc *head_p ) +{ + struct ShmBlockDesc *next_p; + + /* Check if head_p and head_p->next are neighbors and if so + join them */ + if ( head_p == EOList_Addr ) return ; + if ( head_p->next == EOList_Off ) return ; + + next_p = (struct ShmBlockDesc *)shm_offset2addr(head_p->next); + if ( ( head_p + head_p->size + 1 ) == next_p) { + head_p->size += next_p->size +1 ; /* adapt size */ + head_p->next = next_p->next ; /* link out */ + + shm_header_p->statistics.cells_free += 1; + shm_header_p->statistics.cells_system -= 1; + } +} + + + + +static BOOL shm_close( void ) +{ + return True; +} + + +static BOOL shm_free(int offset) +{ + struct ShmBlockDesc *header_p; /* pointer to header of + block to free */ + struct ShmBlockDesc *scanner_p; /* used to scan the list */ + struct ShmBlockDesc *prev_p; /* holds previous in the + list */ + + if (!shm_header_p) { + /* not mapped yet */ + DEBUG(0,("ERROR shm_free : shmem not mapped\n")); + return False; + } + + global_lock(); + + if (!shm_header_p->consistent) { + DEBUG(0,("ERROR shm_free : shmem not consistent\n")); + global_unlock(); + return False; + } + + /* make pointer to header of block */ + header_p = ((struct ShmBlockDesc *)shm_offset2addr(offset) - 1); + + if (header_p->next != SHM_NOT_FREE_OFF) { + DEBUG(0,("ERROR shm_free : bad offset (%d)\n",offset)); + global_unlock(); + return False; + } + + /* find a place in the free_list to put the header in */ + + /* set scanner and previous pointer to start of list */ + prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); + scanner_p = prev_p ; + + while ((scanner_p != EOList_Addr) && + (scanner_p < header_p)) { + /* while we didn't scan past its position */ + prev_p = scanner_p ; + scanner_p = (struct ShmBlockDesc *)shm_offset2addr(scanner_p->next); + } + + shm_header_p->consistent = False; + + DEBUG(6,("shm_free : freeing %d bytes at offset %d\n", + header_p->size*CellSize,offset)); + + if (scanner_p == prev_p) { + shm_header_p->statistics.cells_free += header_p->size; + shm_header_p->statistics.cells_used -= header_p->size; + + /* we must free it at the beginning of the list */ + shm_header_p->first_free_off = shm_addr2offset(header_p); /* set the free_list_pointer to this block_header */ + + /* scanner is the one that was first in the list */ + header_p->next = shm_addr2offset(scanner_p); + shm_solve_neighbors( header_p ); /* if neighbors then link them */ + + shm_header_p->consistent = True; + } else { + shm_header_p->statistics.cells_free += header_p->size; + shm_header_p->statistics.cells_used -= header_p->size; + + prev_p->next = shm_addr2offset(header_p); + header_p->next = shm_addr2offset(scanner_p); + shm_solve_neighbors(header_p) ; + shm_solve_neighbors(prev_p) ; + + shm_header_p->consistent = True; + } + + global_unlock(); + return True; +} + + +static int shm_get_userdef_off(void) +{ + if (!shm_header_p) + return NULL_OFFSET; + else + return shm_header_p->userdef_off; +} + +/******************************************************************* + Lock a particular hash bucket entry. + ******************************************************************/ +static BOOL shm_lock_hash_entry(unsigned int entry) +{ + DEBUG(0,("hash lock %d\n", entry)); + return sem_lock(entry+1); +} + +/******************************************************************* + Unlock a particular hash bucket entry. + ******************************************************************/ +static BOOL shm_unlock_hash_entry(unsigned int entry) +{ + DEBUG(0,("hash unlock %d\n", entry)); + return sem_unlock(entry+1); +} + + +/******************************************************************* + Gather statistics on shared memory usage. + ******************************************************************/ +static BOOL shm_get_usage(int *bytes_free, + int *bytes_used, + int *bytes_overhead) +{ + if(!shm_header_p) { + /* not mapped yet */ + DEBUG(0,("ERROR shm_free : shmem not mapped\n")); + return False; + } + + *bytes_free = shm_header_p->statistics.cells_free * CellSize; + *bytes_used = shm_header_p->statistics.cells_used * CellSize; + *bytes_overhead = shm_header_p->statistics.cells_system * CellSize + AlignedHeaderSize; + + return True; +} + +static struct shmem_ops shmops = { + shm_close, + shm_alloc, + shm_free, + shm_get_userdef_off, + shm_offset2addr, + shm_addr2offset, + shm_lock_hash_entry, + shm_unlock_hash_entry, + shm_get_usage, +}; + +/******************************************************************* + open the shared memory + ******************************************************************/ +struct shmem_ops *sysv_shm_open(int size, int ronly) +{ + BOOL created_new = False; + BOOL other_processes; + struct shmid_ds shm_ds; + struct semid_ds sem_ds; + union semun su; + int i; + + read_only = ronly; + + shm_size = size; + + DEBUG(4,("Trying sysv shmem open of size %d\n", size)); + + /* first the semaphore */ + sem_id = semget(SEMAPHORE_KEY, 0, 0); + if (sem_id == -1) { + if (read_only) return NULL; + + sem_id = semget(SEMAPHORE_KEY, lp_shmem_hash_size()+1, + IPC_CREAT | IPC_EXCL | IPC_PERMS); + + if (sem_id == -1) { + DEBUG(0,("Can't create or use semaphore %s\n", + strerror(errno))); + } + + if (sem_id != -1) { + su.val = 1; + for (i=0;i 1); + + if (!read_only && !other_processes) { + memset((char *)shm_header_p, 0, shm_size); + shm_initialize(shm_size); + shm_create_hash_table(lp_shmem_hash_size()); + DEBUG(1,("Initialised IPC area of size %d\n", shm_size)); + } else if (!shm_validate_header(shm_size)) { + /* existing file is corrupt, samba admin should remove + it by hand */ + DEBUG(0,("ERROR shm_open : corrupt IPC area - remove it!\n")); + global_unlock(); + return NULL; + } + + global_unlock(); + return &shmops; +} + + + +#else + int ipc_dummy_procedure(void) +{return 0;} +#endif -- cgit From e75de8adc6918cc16ad84d2fa32cbc185d5b7fdb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Oct 1997 14:40:31 +0000 Subject: lower the default hash size if SEMMSL isn't defined (This used to be commit 9f0be847fdbcf0f8bbd69de6cdf277ae0440bcda) --- source3/locking/locking_shm.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index f2ae641808..3abd6b25a7 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -62,6 +62,11 @@ typedef struct static int read_only; + +/* Conversion to hash entry index from device and inode numbers. */ +#define HASH_ENTRY(dev,ino) ((( (uint32)(dev) )* ( (uint32)(ino) )) % lp_shmem_hash_size()) + + /******************************************************************* deinitialize the shared memory for share_mode management ******************************************************************/ -- cgit From 9c717c285a2498b0a3bbf889551041a8aa5a9841 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Oct 1997 14:59:06 +0000 Subject: fix for broken sunos4 includes (doesn't have SHM_R) (This used to be commit 6ca96782ace2258707f49d204726a00baef9d941) --- source3/locking/shmem_sysv.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 793e508c71..36d0cca27f 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -33,7 +33,11 @@ extern int DEBUGLEVEL; #define SHM_MAGIC 0x53484100 #define SHM_VERSION 2 +#ifdef SHM_R #define IPC_PERMS ((SHM_R | SHM_W) | (SHM_R>>3) | (SHM_R>>6)) +#else +#define IPC_PERMS 0644 +#endif static int shm_id; static int sem_id; -- cgit From 4fd96fddd2b13f60c4eb13263bac2a62a2795dcc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 Oct 1997 01:59:54 +0000 Subject: clean up the hash entry code a bit. Got rid of lp_shmem_hash_size() and made it private to the 2 shmem implementations. Added new shmops->hash_size() function. Added code to handle the IPC system limits by looping decreasing the size of the resources (semaphores and shared memory) that we request until we get under the system limits, which can be quite low on some systems! Added checks that the creator of the IPC objects is root. Otherwise we would be open to a security hole where someone pre-creates the shared memory segment and attaches. (This used to be commit 6b6f624b63137d4750200e8cb4961b1402513632) --- source3/locking/locking_shm.c | 51 +++---------------------------- source3/locking/shmem.c | 48 +++++++++++++++++------------ source3/locking/shmem_sysv.c | 70 +++++++++++++++++++++++++++++++++---------- 3 files changed, 88 insertions(+), 81 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 3abd6b25a7..d299e34caa 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -64,7 +64,7 @@ static int read_only; /* Conversion to hash entry index from device and inode numbers. */ -#define HASH_ENTRY(dev,ino) ((( (uint32)(dev) )* ( (uint32)(ino) )) % lp_shmem_hash_size()) +#define HASH_ENTRY(dev,ino) ((((uint32)(dev)) * ((uint32)(ino))) % shmops->hash_size()) /******************************************************************* @@ -110,15 +110,6 @@ static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, *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 = (int *)shmops->offset2addr(shmops->get_userdef_off()); if(mode_array[hash_entry] == NULL_OFFSET) @@ -289,15 +280,6 @@ static void shm_del_share_mode(int token, int fnum) 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 = (int *)shmops->offset2addr(shmops->get_userdef_off()); if(mode_array[hash_entry] == NULL_OFFSET) @@ -428,14 +410,6 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) 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 = (int *)shmops->offset2addr(shmops->get_userdef_off()); @@ -550,15 +524,6 @@ static BOOL shm_remove_share_oplock(int fnum, int token) 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 = (int *)shmops->offset2addr(shmops->get_userdef_off()); if(mode_array[hash_entry] == NULL_OFFSET) @@ -654,7 +619,7 @@ static int shm_share_forall(void (*fn)(share_mode_entry *, char *)) mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); - for( i = 0; i < lp_shmem_hash_size(); i++) { + for( i = 0; i < shmops->hash_size(); i++) { shmops->lock_hash_entry(i); if(mode_array[i] == NULL_OFFSET) { shmops->unlock_hash_entry(i); @@ -730,19 +695,11 @@ struct share_ops *locking_shm_init(int ronly) read_only = ronly; #ifdef USE_SYSV_IPC - shmops = sysv_shm_open(lp_shmem_size(), read_only); + shmops = sysv_shm_open(read_only); if (shmops) return &share_ops; #endif - pstrcpy(shmem_file_name,lp_lockdir()); - if (!directory_exist(shmem_file_name,NULL)) { - if (read_only) return NULL; - mkdir(shmem_file_name,0755); - } - trim_string(shmem_file_name,"","/"); - if (!*shmem_file_name) return(False); - strcat(shmem_file_name, "/SHARE_MEM_FILE"); - shmops = smb_shm_open(shmem_file_name, lp_shmem_size(), read_only); + shmops = smb_shm_open(read_only); if (shmops) return &share_ops; return NULL; diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 72d7c07751..909e8dd435 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -41,6 +41,9 @@ extern int DEBUGLEVEL; #define SHM_FILE_MODE 0644 #endif +#define SHMEM_HASH_SIZE 113 + + /* WARNING : offsets are used because mmap() does not guarantee that all processes have the shared memory mapped to the same address */ @@ -653,12 +656,6 @@ static BOOL smb_shm_lock_hash_entry( unsigned int entry) return False; } - if(entry >= lp_shmem_hash_size()) - { - DEBUG(0,("ERROR smb_shm_lock_hash_entry : hash entry size too big (%d)\n", entry)); - return False; - } - /* Do an exclusive wait lock on the 4 byte region mapping into this entry */ if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(int), F_WRLCK) == False) { @@ -683,12 +680,6 @@ static BOOL smb_shm_unlock_hash_entry( unsigned int entry ) return False; } - if(entry >= lp_shmem_hash_size()) - { - DEBUG(0,("ERROR smb_shm_unlock_hash_entry : hash entry size too big (%d)\n", entry)); - return False; - } - /* Do a wait lock on the 4 byte region mapping into this entry */ if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(int), F_UNLCK) == False) { @@ -720,6 +711,13 @@ static BOOL smb_shm_get_usage(int *bytes_free, return True; } +/******************************************************************* +hash a number into a hash_entry + ******************************************************************/ +static unsigned smb_shm_hash_size(void) +{ + return SHMEM_HASH_SIZE; +} static struct shmem_ops shmops = { smb_shm_close, @@ -731,18 +729,30 @@ static struct shmem_ops shmops = { smb_shm_lock_hash_entry, smb_shm_unlock_hash_entry, smb_shm_get_usage, + smb_shm_hash_size, }; /******************************************************************* open the shared memory ******************************************************************/ -struct shmem_ops *smb_shm_open(char *file_name, int size, int ronly) +struct shmem_ops *smb_shm_open(int ronly) { - int filesize; - BOOL created_new = False; - BOOL other_processes = True; - - read_only = ronly; + pstring file_name; + int filesize; + BOOL created_new = False; + BOOL other_processes = True; + int size = lp_shmem_size(); + + read_only = ronly; + + pstrcpy(file_name,lp_lockdir()); + if (!directory_exist(file_name,NULL)) { + if (read_only) return NULL; + mkdir(file_name,0755); + } + trim_string(file_name,"","/"); + if (!*file_name) return(False); + strcat(file_name, "/SHARE_MEM_FILE"); DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); @@ -840,7 +850,7 @@ struct shmem_ops *smb_shm_open(char *file_name, int size, int ronly) { smb_shm_initialize(size); /* Create the hash buckets for the share file entries. */ - smb_shm_create_hash_table( lp_shmem_hash_size() ); + smb_shm_create_hash_table(SHMEM_HASH_SIZE); } else if (!smb_shm_validate_header(size) ) { diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 36d0cca27f..e3f40418d9 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -39,6 +39,14 @@ extern int DEBUGLEVEL; #define IPC_PERMS 0644 #endif +#ifdef SEMMSL +#define SHMEM_HASH_SIZE (SEMMSL-1) +#else +#define SHMEM_HASH_SIZE 63 +#endif + +#define MIN_SHM_SIZE 10240 + static int shm_id; static int sem_id; static int shm_size; @@ -487,6 +495,16 @@ static BOOL shm_get_usage(int *bytes_free, return True; } + +/******************************************************************* +hash a number into a hash_entry + ******************************************************************/ +static unsigned shm_hash_size(void) +{ + return hash_size; +} + + static struct shmem_ops shmops = { shm_close, shm_alloc, @@ -497,12 +515,13 @@ static struct shmem_ops shmops = { shm_lock_hash_entry, shm_unlock_hash_entry, shm_get_usage, + shm_hash_size, }; /******************************************************************* open the shared memory ******************************************************************/ -struct shmem_ops *sysv_shm_open(int size, int ronly) +struct shmem_ops *sysv_shm_open(int ronly) { BOOL created_new = False; BOOL other_processes; @@ -513,17 +532,23 @@ struct shmem_ops *sysv_shm_open(int size, int ronly) read_only = ronly; - shm_size = size; + shm_size = lp_shmem_size(); - DEBUG(4,("Trying sysv shmem open of size %d\n", size)); + DEBUG(4,("Trying sysv shmem open of size %d\n", shm_size)); /* first the semaphore */ sem_id = semget(SEMAPHORE_KEY, 0, 0); if (sem_id == -1) { if (read_only) return NULL; - sem_id = semget(SEMAPHORE_KEY, lp_shmem_hash_size()+1, - IPC_CREAT | IPC_EXCL | IPC_PERMS); + hash_size = SHMEM_HASH_SIZE; + + while (hash_size > 1) { + sem_id = semget(SEMAPHORE_KEY, hash_size+1, + IPC_CREAT | IPC_EXCL | IPC_PERMS); + if (sem_id != -1 || errno != EINVAL) break; + hash_size--; + } if (sem_id == -1) { DEBUG(0,("Can't create or use semaphore %s\n", @@ -532,7 +557,7 @@ struct shmem_ops *sysv_shm_open(int size, int ronly) if (sem_id != -1) { su.val = 1; - for (i=0;i MIN_SHM_SIZE) { + shm_id = shmget(SHMEM_KEY, shm_size, + IPC_CREAT | IPC_EXCL | IPC_PERMS); + if (shm_id != -1 || errno != EINVAL) break; + shm_size *= 0.9; + } created_new = (shm_id != -1); } @@ -592,19 +628,23 @@ struct shmem_ops *sysv_shm_open(int size, int ronly) DEBUG(0,("ERROR shm_open : can't IPC_STAT\n")); } - /* set the permissions */ if (!read_only) { - shm_ds.shm_perm.mode = IPC_PERMS; - shmctl(shm_id, IPC_SET, &shm_ds); + if (shm_ds.shm_perm.cuid != 0 || shm_ds.shm_perm.cgid != 0) { + DEBUG(0,("ERROR: root did not create the shmem\n")); + global_unlock(); + return NULL; + } } + shm_size = shm_ds.shm_segsz; + other_processes = (shm_ds.shm_nattch > 1); if (!read_only && !other_processes) { memset((char *)shm_header_p, 0, shm_size); shm_initialize(shm_size); - shm_create_hash_table(lp_shmem_hash_size()); - DEBUG(1,("Initialised IPC area of size %d\n", shm_size)); + shm_create_hash_table(hash_size); + DEBUG(3,("Initialised IPC area of size %d\n", shm_size)); } else if (!shm_validate_header(shm_size)) { /* existing file is corrupt, samba admin should remove it by hand */ -- cgit From cb6941a19390113cbe61f436e74c9d969afd00d0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 Oct 1997 02:18:08 +0000 Subject: - don't allow locking to initialise twice - check that it is initialised before de-initialising it! (This used to be commit 68ad7b91999216e5721207b5a79c3a66be7cf420) --- source3/locking/locking.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index ae977b0f69..d654d038c8 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -113,6 +113,8 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * ****************************************************************************/ BOOL locking_init(int read_only) { + if (share_ops) return True; + #ifdef FAST_SHARE_MODES share_ops = locking_shm_init(read_only); if (!share_ops) { @@ -135,7 +137,9 @@ BOOL locking_init(int read_only) ******************************************************************/ BOOL locking_end(void) { - return share_ops->stop_mgmt(); + if (share_ops) + return share_ops->stop_mgmt(); + return True; } -- cgit From 87ea4b93ecde16a4156c9c307ad477537a837ef4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 Oct 1997 02:59:22 +0000 Subject: damn. We need root privilages to do semaphore operations even if we have done the semget() as root. The problem is that become_root() and unbecome_root() are so slow! I've provided two options. The default is to set the semaphores (but _not_ the shared memory) world writeable so that a become_root() isn't needed. Otherwise you can define SECURE_SEMAPHORES and pay the performance penalty. (This used to be commit 2bbd8d2cbc5cf1901859a181bc9ec29822995e51) --- source3/locking/shmem_sysv.c | 71 +++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 28 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index e3f40418d9..8832902820 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -39,6 +39,14 @@ extern int DEBUGLEVEL; #define IPC_PERMS 0644 #endif +#ifdef SECURE_SEMAPHORES +/* secure semaphores are slow because we have to do a become_root() + on every call! */ +#define SEMAPHORE_PERMS IPC_PERMS +#else +#define SEMAPHORE_PERMS 0666 +#endif + #ifdef SEMMSL #define SHMEM_HASH_SIZE (SEMMSL-1) #else @@ -92,45 +100,49 @@ static BOOL shm_initialize_called = False; static int read_only; -static BOOL sem_lock(int i) +static BOOL sem_change(int i, int op) { +#ifdef SECURE_SEMAPHORES + extern struct current_user current_user; + int became_root=0; +#endif struct sembuf sb; + int ret; + if (read_only) return True; - - sb.sem_num = i; - sb.sem_op = -1; - sb.sem_flg = SEM_UNDO; - if (semop(sem_id, &sb, 1) != 0) { - DEBUG(0,("ERROR: IPC lock failed on semaphore %d\n", i)); - return False; +#ifdef SECURE_SEMAPHORES + if (current_user.uid != 0) { + become_root(0); + became_root = 1; } - - return True; -} - -static BOOL sem_unlock(int i) -{ - struct sembuf sb; - if (read_only) return True; +#endif sb.sem_num = i; - sb.sem_op = 1; + sb.sem_op = op; sb.sem_flg = SEM_UNDO; - if (semop(sem_id, &sb, 1) != 0) { - DEBUG(0,("ERROR: IPC unlock failed on semaphore %d\n", i)); - return False; + ret = semop(sem_id, &sb, 1); + + if (ret != 0) { + DEBUG(0,("ERROR: sem_change(%d,%d) failed (%s)\n", + i, op, strerror(errno))); } - return True; +#ifdef SECURE_SEMAPHORES + if (became_root) { + unbecome_root(0); + } +#endif + + return ret == 0; } static BOOL global_lock(void) { global_lock_count++; if (global_lock_count == 1) - return sem_lock(0); + return sem_change(0, -1); return True; } @@ -138,7 +150,7 @@ static BOOL global_unlock(void) { global_lock_count--; if (global_lock_count == 0) - return sem_unlock(0); + return sem_change(0, 1); return True; } @@ -461,8 +473,7 @@ static int shm_get_userdef_off(void) ******************************************************************/ static BOOL shm_lock_hash_entry(unsigned int entry) { - DEBUG(0,("hash lock %d\n", entry)); - return sem_lock(entry+1); + return sem_change(entry+1, -1); } /******************************************************************* @@ -470,8 +481,7 @@ static BOOL shm_lock_hash_entry(unsigned int entry) ******************************************************************/ static BOOL shm_unlock_hash_entry(unsigned int entry) { - DEBUG(0,("hash unlock %d\n", entry)); - return sem_unlock(entry+1); + return sem_change(entry+1, 1); } @@ -545,7 +555,7 @@ struct shmem_ops *sysv_shm_open(int ronly) while (hash_size > 1) { sem_id = semget(SEMAPHORE_KEY, hash_size+1, - IPC_CREAT | IPC_EXCL | IPC_PERMS); + IPC_CREAT|IPC_EXCL| SEMAPHORE_PERMS); if (sem_id != -1 || errno != EINVAL) break; hash_size--; } @@ -584,6 +594,11 @@ struct shmem_ops *sysv_shm_open(int ronly) DEBUG(0,("ERROR: root did not create the semaphore\n")); return NULL; } + + sem_ds.sem_perm.mode = SEMAPHORE_PERMS; + if (semctl(sem_id, 0, IPC_SET, su) != 0) { + DEBUG(0,("ERROR shm_open : can't IPC_SET\n")); + } } -- cgit From d5fdd84ffa78c1ce8211c2c5794b057c72bf1947 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 31 Oct 1997 02:40:55 +0000 Subject: - cleanup some warnings - redo the prototypes (This used to be commit 31dcb51e05914d49d81a3faef354aaf0ab9fa63f) --- source3/locking/locking_shm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index d299e34caa..c1e32538e1 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -690,8 +690,6 @@ static struct share_ops share_ops = { ******************************************************************/ struct share_ops *locking_shm_init(int ronly) { - pstring shmem_file_name; - read_only = ronly; #ifdef USE_SYSV_IPC -- cgit From 4400805208722e3679809a0ca53c2285e45212ca Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 31 Oct 1997 05:56:07 +0000 Subject: change from * to ^ in hashing of device/inode. Using * meant that if the device number happened to divide the number of hash buckets we would only use a small fraction of the hash buckets, which would slow things down. (This used to be commit 623ffd701f2f966875d396d8b2df74f0cf874cda) --- source3/locking/locking_shm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index c1e32538e1..dfabbac290 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -64,7 +64,7 @@ static int read_only; /* Conversion to hash entry index from device and inode numbers. */ -#define HASH_ENTRY(dev,ino) ((((uint32)(dev)) * ((uint32)(ino))) % shmops->hash_size()) +#define HASH_ENTRY(dev,ino) ((((uint32)(dev)) ^ ((uint32)(ino))) % shmops->hash_size()) /******************************************************************* -- cgit From 264b1e0e75ae63467b6fe51b339e1e5f3c4477bc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 Nov 1997 07:33:55 +0000 Subject: some locking code cleanups (This used to be commit 6d77311d6cecabafb86c02e26b30724425ef6208) --- source3/locking/locking_shm.c | 136 +++++++++---------- source3/locking/shmem.c | 20 +-- source3/locking/shmem_sysv.c | 304 +++++++++++++++++++++--------------------- 3 files changed, 222 insertions(+), 238 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index dfabbac290..45ab14d452 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -112,9 +112,9 @@ static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); - if(mode_array[hash_entry] == NULL_OFFSET) + if(mode_array[hash_entry] == 0) { - DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry)); + DEBUG(5,("get_share_modes hash bucket %d empty\n", hash_entry)); return 0; } @@ -137,16 +137,15 @@ static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, 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)); + DEBUG(5,("get_share_modes no entry for file dev = %d ino = %d\n", + dev, inode)); 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)); + DEBUG(0,("ERROR: get_share_modes Deleting old share mode v1 %d dev=%d ino=%d\n", + file_scanner_p->locking_version, dev, inode)); if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; else @@ -163,7 +162,7 @@ bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); malloc(num_entries * sizeof(share_mode_entry)); if(*old_shares == 0) { - DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n")); + DEBUG(0,("get_share_modes: malloc fail!\n")); return 0; } } @@ -181,7 +180,6 @@ bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); { /* 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) { @@ -203,17 +201,12 @@ bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); /* 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)); + DEBUG(0,("PANIC ERROR: get_share_mode: entries=%d dev=%d ino=%d\n", + file_scanner_p->num_share_mode_entries,dev, inode)); 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)); + DEBUG(0,("get_share_modes: process %d no longer exists\n", pid)); shmops->free(shmops->addr2offset(delete_entry_p)); } @@ -229,8 +222,8 @@ bucket %d (number of entries now = %d)\n", 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)); + DEBUG(5,("get_share_modes Read share 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 *) shmops->offset2addr(entry_scanner_p->next_share_mode_entry); @@ -240,9 +233,8 @@ record mode 0x%X pid=%d\n", entry_scanner_p->e.share_mode, entry_scanner_p->e.pi /* 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)); + DEBUG(0,("get_share_modes: file with dev %d inode %d empty\n", + dev, inode)); if(*old_shares) free((char *)*old_shares); *old_shares = 0; @@ -254,8 +246,8 @@ hash bucket %d has a share mode record but no entries - deleting\n", shmops->free(shmops->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)); + DEBUG(5,("get_share_modes: file with dev %d inode %d -> %d entries\n", + dev, inode, num_entries_copied)); return(num_entries_copied); } @@ -282,9 +274,9 @@ static void shm_del_share_mode(int token, int fnum) mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); - if(mode_array[hash_entry] == NULL_OFFSET) + if(mode_array[hash_entry] == 0) { - DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n", + DEBUG(0,("PANIC ERROR:del_share_mode hash bucket %d empty\n", hash_entry)); return; } @@ -309,16 +301,15 @@ static void shm_del_share_mode(int token, int fnum) 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)); + DEBUG(0,("ERROR: del_share_mode no entry for dev %d inode %d\n", + dev, inode)); 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 )); + DEBUG(0,("ERROR: del_share_modes Deleting old share mode v1 %d dev=%d ino=%d\n", + file_scanner_p->locking_version, dev, inode)); if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; else @@ -353,9 +344,8 @@ record due to old locking version %d for file dev %d, inode %d hash bucket %d\n" /* 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)); + DEBUG(2,("del_share_modes Deleting share mode entry dev=%d ino=%d\n", + dev, inode)); 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; @@ -366,17 +356,16 @@ Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries no /* 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)); + DEBUG(0,("PANIC ERROR:del_share_mode num_share_mode_entries=%d\n", + file_scanner_p->num_share_mode_entries)); 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)); + DEBUG(2,("del_share_modes num entries = 0, deleting share_mode dev=%d ino=%d\n", + dev, inode)); if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; else @@ -386,8 +375,8 @@ record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); } 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)); + DEBUG(0,("ERROR: del_share_modes No share mode dev=%d ino=%d\n", + dev, inode)); } } @@ -435,19 +424,18 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) { /* We must create a share_mode_record */ share_mode_record *new_mode_p = NULL; - int new_offset = shmops->alloc( sizeof(share_mode_record) + - strlen(fs_p->name) + 1); - if(new_offset == NULL_OFFSET) - { - DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): shmops->alloc fail !\n")); - return False; + int new_offset = shmops->alloc(sizeof(share_mode_record) + + strlen(fs_p->name) + 1); + if(new_offset == 0) { + DEBUG(0,("ERROR:set_share_mode shmops->alloc fail!\n")); + return False; } new_mode_p = shmops->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; + new_mode_p->share_mode_entries = 0; 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). */ @@ -456,21 +444,20 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) 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)); + DEBUG(3,("set_share_mode: Created share record for %s (dev %d inode %d)\n", + fs_p->name, dev, inode)); } /* Now create the share mode entry */ - new_entry_offset = shmops->alloc( sizeof(shm_share_mode_entry)); - if(new_entry_offset == NULL_OFFSET) - { - int delete_offset = mode_array[hash_entry]; - DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): shmops->alloc fail 1!\n")); - /* Unlink the damaged record */ - mode_array[hash_entry] = file_scanner_p->next_offset; - /* And delete it */ - shmops->free( delete_offset ); - return False; + new_entry_offset = shmops->alloc(sizeof(shm_share_mode_entry)); + if(new_entry_offset == 0) { + int delete_offset = mode_array[hash_entry]; + DEBUG(0,("ERROR:set_share_mode: shmops->alloc fail 1!\n")); + /* Unlink the damaged record */ + mode_array[hash_entry] = file_scanner_p->next_offset; + /* And delete it */ + shmops->free( delete_offset ); + return False; } new_entry_p = shmops->offset2addr(new_entry_offset); @@ -488,18 +475,16 @@ inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry)); /* 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)); + DEBUG(0,("PANIC ERROR:set_share_mode num_share_mode_entries=%d\n", + file_scanner_p->num_share_mode_entries)); 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)); + DEBUG(3,("set_share_mode: Created share entry for %s with mode 0x%X pid=%d\n", + fs_p->name, fs_p->share_mode, new_entry_p->e.pid)); return(True); } @@ -526,9 +511,9 @@ static BOOL shm_remove_share_oplock(int fnum, int token) mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); - if(mode_array[hash_entry] == NULL_OFFSET) + if(mode_array[hash_entry] == 0) { - DEBUG(0,("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash bucket %d empty\n", + DEBUG(0,("PANIC ERROR:remove_share_oplock: hash bucket %d empty\n", hash_entry)); return False; } @@ -553,16 +538,15 @@ static BOOL shm_remove_share_oplock(int fnum, int token) 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)); + DEBUG(0,("ERROR:remove_share_oplock: no entry found for dev=%d ino=%d\n", + dev, inode)); 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 )); + DEBUG(0,("ERROR: remove_share_oplock: Deleting old share mode v1=%d dev=%d ino=%d\n", + file_scanner_p->locking_version, dev, inode)); if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; else @@ -598,8 +582,8 @@ record due to old locking version %d for file dev %d, inode %d hash bucket %d\n" 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)); + DEBUG(0,("ERROR: remove_share_oplock: No oplock granted. dev=%d ino=%d\n", + dev, inode)); return False; } @@ -621,7 +605,7 @@ static int shm_share_forall(void (*fn)(share_mode_entry *, char *)) for( i = 0; i < shmops->hash_size(); i++) { shmops->lock_hash_entry(i); - if(mode_array[i] == NULL_OFFSET) { + if(mode_array[i] == 0) { shmops->unlock_hash_entry(i); continue; } diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 909e8dd435..864f7c298b 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -70,7 +70,7 @@ struct SmbShmBlockDesc }; #define EOList_Addr (struct SmbShmBlockDesc *)( 0 ) -#define EOList_Off (NULL_OFFSET) +#define EOList_Off 0 #define CellSize sizeof(struct SmbShmBlockDesc) @@ -158,7 +158,7 @@ static BOOL smb_shm_global_unlock(void) static void *smb_shm_offset2addr(int offset) { - if (offset == NULL_OFFSET ) + if (offset == 0 ) return (void *)(0); if (!smb_shm_header_p) @@ -170,10 +170,10 @@ static void *smb_shm_offset2addr(int offset) static int smb_shm_addr2offset(void *addr) { if (!addr) - return NULL_OFFSET; + return 0; if (!smb_shm_header_p) - return NULL_OFFSET; + return 0; return (int)((char *)addr - (char *)smb_shm_header_p); } @@ -193,7 +193,7 @@ static int smb_shm_alloc(int size) { /* not mapped yet */ DEBUG(0,("ERROR smb_shm_alloc : shmem not mapped\n")); - return NULL_OFFSET; + return 0; } smb_shm_global_lock(); @@ -202,7 +202,7 @@ static int smb_shm_alloc(int size) { DEBUG(0,("ERROR smb_shm_alloc : shmem not consistent\n")); smb_shm_global_unlock(); - return NULL_OFFSET; + return 0; } @@ -225,7 +225,7 @@ static int smb_shm_alloc(int size) { DEBUG(0,("ERROR smb_shm_alloc : alloc of %d bytes failed, no free space found\n",size)); smb_shm_global_unlock(); - return (NULL_OFFSET); + return (0); } /* going to modify shared mem */ @@ -296,7 +296,7 @@ static BOOL smb_shm_create_hash_table( unsigned int size ) smb_shm_global_lock(); smb_shm_header_p->userdef_off = smb_shm_alloc( size ); - if(smb_shm_header_p->userdef_off == NULL_OFFSET) + if(smb_shm_header_p->userdef_off == 0) { DEBUG(0,("smb_shm_create_hash_table: Failed to create hash table of size %d\n",size)); smb_shm_global_unlock(); @@ -486,7 +486,7 @@ static BOOL smb_shm_initialize(int size) smb_shm_header_p->smb_shm_version = SMB_SHM_VERSION; smb_shm_header_p->total_size = size; smb_shm_header_p->first_free_off = AlignedHeaderSize; - smb_shm_header_p->userdef_off = NULL_OFFSET; + smb_shm_header_p->userdef_off = 0; first_free_block_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); first_free_block_p->next = EOList_Off; @@ -638,7 +638,7 @@ static BOOL smb_shm_free(int offset) static int smb_shm_get_userdef_off(void) { if (!smb_shm_header_p) - return NULL_OFFSET; + return 0; else return smb_shm_header_p->userdef_off; } diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 8832902820..14ed199738 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Shared memory functions - SYSV IPC implementation - Copyright (C) Erik Devriendt 1996-1997 + Copyright (C) Andrew Tridgell 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 @@ -53,7 +53,7 @@ extern int DEBUGLEVEL; #define SHMEM_HASH_SIZE 63 #endif -#define MIN_SHM_SIZE 10240 +#define MIN_SHM_SIZE 0x1000 static int shm_id; static int sem_id; @@ -83,19 +83,18 @@ struct ShmBlockDesc { int next; /* offset of next block in the free list or SHM_NOT_FREE_OFF when block in use */ - int size; /* user size in BlockDescSize units */ + int size; /* user size in BlockDescSize units */ }; -#define EOList_Addr (struct ShmBlockDesc *)( 0 ) -#define EOList_Off (NULL_OFFSET) +#define EOList_Addr NULL +#define EOList_Off (0) #define CellSize sizeof(struct ShmBlockDesc) -/* HeaderSize aligned on 8 byte boundary */ -#define AlignedHeaderSize ((sizeof(struct ShmHeader)+7) & ~7) - -static struct ShmHeader *shm_header_p = (struct ShmHeader *)0; +/* HeaderSize aligned on a 8 byte boundary */ +#define AlignedHeaderSize ((sizeof(struct ShmHeader)+7) & ~7) +static struct ShmHeader *shm_header_p = NULL; static BOOL shm_initialize_called = False; static int read_only; @@ -156,22 +155,22 @@ static BOOL global_unlock(void) static void *shm_offset2addr(int offset) { - if (offset == NULL_OFFSET ) + if (offset == 0 ) return (void *)(0); if (!shm_header_p) return (void *)(0); - return (void *)((char *)shm_header_p + offset ); + return (void *)((char *)shm_header_p + offset); } static int shm_addr2offset(void *addr) { if (!addr) - return NULL_OFFSET; + return 0; if (!shm_header_p) - return NULL_OFFSET; + return 0; return (int)((char *)addr - (char *)shm_header_p); } @@ -189,7 +188,7 @@ static int shm_alloc(int size) if (!shm_header_p) { /* not mapped yet */ DEBUG(0,("ERROR shm_alloc : shmem not mapped\n")); - return NULL_OFFSET; + return 0; } global_lock(); @@ -197,13 +196,13 @@ static int shm_alloc(int size) if (!shm_header_p->consistent) { DEBUG(0,("ERROR shm_alloc : shmem not consistent\n")); global_unlock(); - return NULL_OFFSET; + return 0; } - /* calculate the number of cells */ - num_cells = (size + CellSize -1) / CellSize; + /* calculate the number of cells */ + num_cells = (size + (CellSize-1)) / CellSize; - /* set start of scan */ + /* set start of scan */ prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); scanner_p = prev_p ; @@ -216,144 +215,50 @@ static int shm_alloc(int size) /* at this point scanner point to a block header or to the end of the list */ if (scanner_p == EOList_Addr) { - DEBUG(0,("ERROR shm_alloc : alloc of %d bytes failed, no free space found\n",size)); + DEBUG(0,("ERROR shm_alloc : alloc of %d bytes failed\n",size)); global_unlock(); - return (NULL_OFFSET); + return (0); } /* going to modify shared mem */ shm_header_p->consistent = False; /* if we found a good one : scanner == the good one */ - if (scanner_p->size <= num_cells + 2) { - /* there is no use in making a new one, it will be too small anyway - * we will link out scanner - */ - if ( prev_p == scanner_p ) { - shm_header_p->first_free_off = scanner_p->next ; - } else { - prev_p->next = scanner_p->next ; - } - shm_header_p->statistics.cells_free -= scanner_p->size; - shm_header_p->statistics.cells_used += scanner_p->size; - } else { + if (scanner_p->size > num_cells + 2) { /* Make a new one */ new_p = scanner_p + 1 + num_cells; - new_p->size = scanner_p->size - num_cells - 1; + new_p->size = scanner_p->size - (num_cells + 1); new_p->next = scanner_p->next; scanner_p->size = num_cells; scanner_p->next = shm_addr2offset(new_p); - - if (prev_p != scanner_p) { - prev_p->next = shm_addr2offset(new_p) ; - } else { - shm_header_p->first_free_off = shm_addr2offset(new_p); - } - shm_header_p->statistics.cells_free -= num_cells+1; - shm_header_p->statistics.cells_used += num_cells; + + shm_header_p->statistics.cells_free -= 1; shm_header_p->statistics.cells_system += 1; } - result_offset = shm_addr2offset( &(scanner_p[1]) ); - scanner_p->next = SHM_NOT_FREE_OFF ; + /* take it from the free list */ + if (prev_p == scanner_p) { + shm_header_p->first_free_off = scanner_p->next; + } else { + prev_p->next = scanner_p->next; + } + shm_header_p->statistics.cells_free -= scanner_p->size; + shm_header_p->statistics.cells_used += scanner_p->size; + + result_offset = shm_addr2offset(&(scanner_p[1])); + scanner_p->next = SHM_NOT_FREE_OFF; /* end modification of shared mem */ shm_header_p->consistent = True; - - DEBUG(6,("shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); global_unlock(); + + DEBUG(6,("shm_alloc : allocated %d bytes at offset %d\n", + size,result_offset)); + return result_offset; } - - -/* - * Function to create the hash table for the share mode entries. Called - * when smb shared memory is global locked. - */ -static BOOL shm_create_hash_table( unsigned int size ) -{ - size *= sizeof(int); - - global_lock(); - shm_header_p->userdef_off = shm_alloc( size ); - - if(shm_header_p->userdef_off == NULL_OFFSET) { - DEBUG(0,("shm_create_hash_table: Failed to create hash table of size %d\n",size)); - global_unlock(); - return False; - } - - /* Clear hash buckets. */ - memset( shm_offset2addr(shm_header_p->userdef_off), '\0', size); - global_unlock(); - return True; -} - -static BOOL shm_validate_header(int size) -{ - if( !shm_header_p ) { - /* not mapped yet */ - DEBUG(0,("ERROR shm_validate_header : shmem not mapped\n")); - return False; - } - - if(shm_header_p->shm_magic != SHM_MAGIC) { - DEBUG(0,("ERROR shm_validate_header : bad magic\n")); - return False; - } - - if(shm_header_p->shm_version != SHM_VERSION) { - DEBUG(0,("ERROR shm_validate_header : bad version %X\n",shm_header_p->shm_version)); - return False; - } - - if(shm_header_p->total_size != size) { - DEBUG(0,("ERROR shm_validate_header : shmem size mismatch (old = %d, new = %d)\n",shm_header_p->total_size,size)); - return False; - } - - if(!shm_header_p->consistent) { - DEBUG(0,("ERROR shm_validate_header : shmem not consistent\n")); - return False; - } - return True; -} - -static BOOL shm_initialize(int size) -{ - struct ShmBlockDesc * first_free_block_p; - - DEBUG(5,("shm_initialize : initializing shmem file of size %d\n",size)); - - if( !shm_header_p ) { - /* not mapped yet */ - DEBUG(0,("ERROR shm_initialize : shmem not mapped\n")); - return False; - } - - shm_header_p->shm_magic = SHM_MAGIC; - shm_header_p->shm_version = SHM_VERSION; - shm_header_p->total_size = size; - shm_header_p->first_free_off = AlignedHeaderSize; - shm_header_p->userdef_off = NULL_OFFSET; - - first_free_block_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); - first_free_block_p->next = EOList_Off; - first_free_block_p->size = ( size - AlignedHeaderSize - CellSize ) / CellSize ; - - shm_header_p->statistics.cells_free = first_free_block_p->size; - shm_header_p->statistics.cells_used = 0; - shm_header_p->statistics.cells_system = 1; - - shm_header_p->consistent = True; - - shm_initialize_called = True; - - return True; -} - static void shm_solve_neighbors(struct ShmBlockDesc *head_p ) { struct ShmBlockDesc *next_p; @@ -364,9 +269,9 @@ static void shm_solve_neighbors(struct ShmBlockDesc *head_p ) if ( head_p->next == EOList_Off ) return ; next_p = (struct ShmBlockDesc *)shm_offset2addr(head_p->next); - if ( ( head_p + head_p->size + 1 ) == next_p) { - head_p->size += next_p->size +1 ; /* adapt size */ - head_p->next = next_p->next ; /* link out */ + if ((head_p + head_p->size + 1) == next_p) { + head_p->size += next_p->size + 1; /* adapt size */ + head_p->next = next_p->next; /* link out */ shm_header_p->statistics.cells_free += 1; shm_header_p->statistics.cells_system -= 1; @@ -374,21 +279,13 @@ static void shm_solve_neighbors(struct ShmBlockDesc *head_p ) } - - -static BOOL shm_close( void ) -{ - return True; -} - - static BOOL shm_free(int offset) { struct ShmBlockDesc *header_p; /* pointer to header of - block to free */ + block to free */ struct ShmBlockDesc *scanner_p; /* used to scan the list */ struct ShmBlockDesc *prev_p; /* holds previous in the - list */ + list */ if (!shm_header_p) { /* not mapped yet */ @@ -416,14 +313,16 @@ static BOOL shm_free(int offset) /* find a place in the free_list to put the header in */ /* set scanner and previous pointer to start of list */ - prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); + prev_p = (struct ShmBlockDesc *) + shm_offset2addr(shm_header_p->first_free_off); scanner_p = prev_p ; while ((scanner_p != EOList_Addr) && (scanner_p < header_p)) { /* while we didn't scan past its position */ prev_p = scanner_p ; - scanner_p = (struct ShmBlockDesc *)shm_offset2addr(scanner_p->next); + scanner_p = (struct ShmBlockDesc *) + shm_offset2addr(scanner_p->next); } shm_header_p->consistent = False; @@ -436,11 +335,12 @@ static BOOL shm_free(int offset) shm_header_p->statistics.cells_used -= header_p->size; /* we must free it at the beginning of the list */ - shm_header_p->first_free_off = shm_addr2offset(header_p); /* set the free_list_pointer to this block_header */ + shm_header_p->first_free_off = shm_addr2offset(header_p); + /* set the free_list_pointer to this block_header */ /* scanner is the one that was first in the list */ header_p->next = shm_addr2offset(scanner_p); - shm_solve_neighbors( header_p ); /* if neighbors then link them */ + shm_solve_neighbors(header_p); shm_header_p->consistent = True; } else { @@ -460,14 +360,113 @@ static BOOL shm_free(int offset) } +/* + * Function to create the hash table for the share mode entries. Called + * when smb shared memory is global locked. + */ +static BOOL shm_create_hash_table(unsigned int hash_entries) +{ + int size = hash_entries * sizeof(int); + + global_lock(); + shm_header_p->userdef_off = shm_alloc(size); + + if(shm_header_p->userdef_off == 0) { + DEBUG(0,("shm_create_hash_table: Failed to create hash table of size %d\n", + size)); + global_unlock(); + return False; + } + + /* Clear hash buckets. */ + memset(shm_offset2addr(shm_header_p->userdef_off), '\0', size); + global_unlock(); + return True; +} + + +static BOOL shm_validate_header(int size) +{ + if(!shm_header_p) { + /* not mapped yet */ + DEBUG(0,("ERROR shm_validate_header : shmem not mapped\n")); + return False; + } + + if(shm_header_p->shm_magic != SHM_MAGIC) { + DEBUG(0,("ERROR shm_validate_header : bad magic\n")); + return False; + } + + if(shm_header_p->shm_version != SHM_VERSION) { + DEBUG(0,("ERROR shm_validate_header : bad version %X\n", + shm_header_p->shm_version)); + return False; + } + + if(shm_header_p->total_size != size) { + DEBUG(0,("ERROR shmem size mismatch (old = %d, new = %d)\n", + shm_header_p->total_size,size)); + return False; + } + + if(!shm_header_p->consistent) { + DEBUG(0,("ERROR shmem not consistent\n")); + return False; + } + return True; +} + + +static BOOL shm_initialize(int size) +{ + struct ShmBlockDesc * first_free_block_p; + + DEBUG(5,("shm_initialize : initializing shmem size %d\n",size)); + + if( !shm_header_p ) { + /* not mapped yet */ + DEBUG(0,("ERROR shm_initialize : shmem not mapped\n")); + return False; + } + + shm_header_p->shm_magic = SHM_MAGIC; + shm_header_p->shm_version = SHM_VERSION; + shm_header_p->total_size = size; + shm_header_p->first_free_off = AlignedHeaderSize; + shm_header_p->userdef_off = 0; + + first_free_block_p = (struct ShmBlockDesc *) + shm_offset2addr(shm_header_p->first_free_off); + first_free_block_p->next = EOList_Off; + first_free_block_p->size = + (size - (AlignedHeaderSize+CellSize))/CellSize; + shm_header_p->statistics.cells_free = first_free_block_p->size; + shm_header_p->statistics.cells_used = 0; + shm_header_p->statistics.cells_system = 1; + + shm_header_p->consistent = True; + + shm_initialize_called = True; + + return True; +} + +static BOOL shm_close( void ) +{ + return True; +} + + static int shm_get_userdef_off(void) { if (!shm_header_p) - return NULL_OFFSET; + return 0; else return shm_header_p->userdef_off; } + /******************************************************************* Lock a particular hash bucket entry. ******************************************************************/ @@ -500,7 +499,8 @@ static BOOL shm_get_usage(int *bytes_free, *bytes_free = shm_header_p->statistics.cells_free * CellSize; *bytes_used = shm_header_p->statistics.cells_used * CellSize; - *bytes_overhead = shm_header_p->statistics.cells_system * CellSize + AlignedHeaderSize; + *bytes_overhead = shm_header_p->statistics.cells_system * CellSize + + AlignedHeaderSize; return True; } -- cgit From 92fcced605374948e2481edecaf290c5bea717d5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 Nov 1997 08:13:42 +0000 Subject: don't use SEM_UNDO because of ridiculously small undo limits on some OSes. Instead add explicit checks for dead locks at startup. (This used to be commit 79858d610c37675b9dc56a949723053ac9b67620) --- source3/locking/shmem_sysv.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 14ed199738..826de5694c 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -119,7 +119,7 @@ static BOOL sem_change(int i, int op) sb.sem_num = i; sb.sem_op = op; - sb.sem_flg = SEM_UNDO; + sb.sem_flg = 0; ret = semop(sem_id, &sb, 1); @@ -539,6 +539,7 @@ struct shmem_ops *sysv_shm_open(int ronly) struct semid_ds sem_ds; union semun su; int i; + int pid; read_only = ronly; @@ -595,6 +596,16 @@ struct shmem_ops *sysv_shm_open(int ronly) return NULL; } + if (semctl(sem_id, 0, GETVAL, su) == 0 && + !process_exists((pid=semctl(sem_id, 0, GETPID, su)))) { + DEBUG(0,("WARNING: clearing global IPC lock set by dead process %d\n", + pid)); + su.val = 1; + if (semctl(sem_id, 0, SETVAL, su) != 0) { + DEBUG(0,("ERROR: Failed to clear global lock\n")); + } + } + sem_ds.sem_perm.mode = SEMAPHORE_PERMS; if (semctl(sem_id, 0, IPC_SET, su) != 0) { DEBUG(0,("ERROR shm_open : can't IPC_SET\n")); @@ -605,6 +616,19 @@ struct shmem_ops *sysv_shm_open(int ronly) if (!global_lock()) return NULL; + + + for (i=1;i Date: Sat, 29 Nov 1997 13:35:09 +0000 Subject: don't display locks for dead processes in smbstatus (This used to be commit c7df484ef6d746fb1f5b53007ee04fa54e5f2223) --- source3/locking/locking_shm.c | 8 +++++--- source3/locking/locking_slow.c | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 45ab14d452..77ceb2573c 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -619,14 +619,16 @@ static int shm_share_forall(void (*fn)(share_mode_entry *, char *)) while(entry_scanner_p != 0) { - fn(&entry_scanner_p->e, - file_scanner_p->file_name); + if (process_exists(entry_scanner_p->e.pid)) { + fn(&entry_scanner_p->e, + file_scanner_p->file_name); + count++; + } entry_scanner_p = (shm_share_mode_entry *) shmops->offset2addr( entry_scanner_p->next_share_mode_entry); - count++; } /* end while entry_scanner_p */ file_scanner_p = (share_mode_record *) shmops->offset2addr(file_scanner_p->next_offset); diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 9bd6d65aa7..935ed09f60 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -996,8 +996,10 @@ static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) e.pid = SVAL(p,SME_PID_OFFSET); e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - fn(&e, fname); - count++; + if (process_exists(e.pid)) { + fn(&e, fname); + count++; + } } /* end for i */ if(buf) -- cgit From 28f37efd349a3199954060700b3239aed4f3c9e2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 Dec 1997 07:41:48 +0000 Subject: don't use free and alloc as structure elements (This used to be commit f7066355b00a169423b4f64f58567e19b52abc1b) --- source3/locking/locking_shm.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 77ceb2573c..2e3278d3dd 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -72,7 +72,7 @@ static int read_only; ******************************************************************/ static BOOL shm_stop_share_mode_mgmt(void) { - return shmops->close(); + return shmops->shm_close(); } /******************************************************************* @@ -150,7 +150,7 @@ static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, mode_array[hash_entry] = file_scanner_p->next_offset; else file_prev_p->next_offset = file_scanner_p->next_offset; - shmops->free(shmops->addr2offset(file_scanner_p)); + shmops->shm_free(shmops->addr2offset(file_scanner_p)); return (0); } @@ -208,7 +208,7 @@ static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, DEBUG(0,("get_share_modes: process %d no longer exists\n", pid)); - shmops->free(shmops->addr2offset(delete_entry_p)); + shmops->shm_free(shmops->addr2offset(delete_entry_p)); } else { @@ -243,7 +243,7 @@ static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, mode_array[hash_entry] = file_scanner_p->next_offset; else file_prev_p->next_offset = file_scanner_p->next_offset; - shmops->free(shmops->addr2offset(file_scanner_p)); + shmops->shm_free(shmops->addr2offset(file_scanner_p)); } DEBUG(5,("get_share_modes: file with dev %d inode %d -> %d entries\n", @@ -314,7 +314,7 @@ static void shm_del_share_mode(int token, int fnum) mode_array[hash_entry] = file_scanner_p->next_offset; else file_prev_p->next_offset = file_scanner_p->next_offset; - shmops->free(shmops->addr2offset(file_scanner_p)); + shmops->shm_free(shmops->addr2offset(file_scanner_p)); return; } @@ -351,7 +351,7 @@ static void shm_del_share_mode(int token, int fnum) 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; - shmops->free(shmops->addr2offset(entry_scanner_p)); + shmops->shm_free(shmops->addr2offset(entry_scanner_p)); /* PARANOIA TEST */ if(file_scanner_p->num_share_mode_entries < 0) @@ -370,7 +370,7 @@ static void shm_del_share_mode(int token, int fnum) mode_array[hash_entry] = file_scanner_p->next_offset; else file_prev_p->next_offset = file_scanner_p->next_offset; - shmops->free(shmops->addr2offset(file_scanner_p)); + shmops->shm_free(shmops->addr2offset(file_scanner_p)); } } else @@ -424,10 +424,10 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) { /* We must create a share_mode_record */ share_mode_record *new_mode_p = NULL; - int new_offset = shmops->alloc(sizeof(share_mode_record) + + int new_offset = shmops->shm_alloc(sizeof(share_mode_record) + strlen(fs_p->name) + 1); if(new_offset == 0) { - DEBUG(0,("ERROR:set_share_mode shmops->alloc fail!\n")); + DEBUG(0,("ERROR:set_share_mode shmops->shm_alloc fail!\n")); return False; } new_mode_p = shmops->offset2addr(new_offset); @@ -449,14 +449,14 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) } /* Now create the share mode entry */ - new_entry_offset = shmops->alloc(sizeof(shm_share_mode_entry)); + new_entry_offset = shmops->shm_alloc(sizeof(shm_share_mode_entry)); if(new_entry_offset == 0) { int delete_offset = mode_array[hash_entry]; - DEBUG(0,("ERROR:set_share_mode: shmops->alloc fail 1!\n")); + DEBUG(0,("ERROR:set_share_mode: shmops->shm_alloc fail 1!\n")); /* Unlink the damaged record */ mode_array[hash_entry] = file_scanner_p->next_offset; /* And delete it */ - shmops->free( delete_offset ); + shmops->shm_free( delete_offset ); return False; } @@ -551,7 +551,7 @@ static BOOL shm_remove_share_oplock(int fnum, int token) mode_array[hash_entry] = file_scanner_p->next_offset; else file_prev_p->next_offset = file_scanner_p->next_offset; - shmops->free(shmops->addr2offset(file_scanner_p)); + shmops->shm_free(shmops->addr2offset(file_scanner_p)); return False; } -- cgit From 637c3ed4a3a99f37e7c7a7a1015934fae5621d27 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 1997 14:06:09 +0000 Subject: - handle ENOSPC in shmem init. - be a little bit more friendly about grabbing semaphores (This used to be commit 87f88708939a3b72b26716a0d6648c4ea2d14047) --- source3/locking/shmem_sysv.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 826de5694c..665cd8e7b4 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -557,8 +557,9 @@ struct shmem_ops *sysv_shm_open(int ronly) while (hash_size > 1) { sem_id = semget(SEMAPHORE_KEY, hash_size+1, IPC_CREAT|IPC_EXCL| SEMAPHORE_PERMS); - if (sem_id != -1 || errno != EINVAL) break; - hash_size--; + if (sem_id != -1 || + (errno != EINVAL && errno != ENOSPC)) break; + hash_size -= 5; } if (sem_id == -1) { @@ -639,8 +640,9 @@ struct shmem_ops *sysv_shm_open(int ronly) while (shm_size > MIN_SHM_SIZE) { shm_id = shmget(SHMEM_KEY, shm_size, IPC_CREAT | IPC_EXCL | IPC_PERMS); - if (shm_id != -1 || errno != EINVAL) break; - shm_size *= 0.9; + if (shm_id != -1 || + (errno != EINVAL && errno != ENOSPC)) break; + shm_size *= 0.8; } created_new = (shm_id != -1); } -- cgit From 1df19ae3bc99e5afc9839a59fbcefee4297017d4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 29 Dec 1997 12:34:16 +0000 Subject: a dummy change to shmem_sysv.c to try and break CVS out of a problem with the ntdom branch (This used to be commit 213c3a4ed27cdc689e941b9a6d70e02e8b7dedd4) --- source3/locking/shmem_sysv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/locking') diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 665cd8e7b4..6b5d9b1ea6 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -39,6 +39,7 @@ extern int DEBUGLEVEL; #define IPC_PERMS 0644 #endif + #ifdef SECURE_SEMAPHORES /* secure semaphores are slow because we have to do a become_root() on every call! */ -- cgit From 55f400bd84f26027f5ec9b7fa06b22895de7557c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Jan 1998 13:27:43 +0000 Subject: This is *not* a big change (although it looks like one). This is merely updating the Copyright statements from 1997 to 1998. It's a once a year thing :-). NO OTHER CHANGES WERE MADE. Jeremy. (This used to be commit b9c16977231efb274e08856f7f3f4408dad6d96c) --- source3/locking/locking.c | 2 +- source3/locking/locking_shm.c | 2 +- source3/locking/locking_slow.c | 2 +- source3/locking/shmem.c | 2 +- source3/locking/shmem_sysv.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d654d038c8..189ac0bcfe 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Locking functions - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 2e3278d3dd..e3c65ce286 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. shared memory locking implementation - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 935ed09f60..de2bb1701c 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. slow (lockfile) locking implementation - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 864f7c298b..63d7ebd3d4 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Shared memory functions - Copyright (C) Erik Devriendt 1996-1997 + Copyright (C) Erik Devriendt 1996-1998 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 diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 6b5d9b1ea6..e415c2ebc5 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Shared memory functions - SYSV IPC implementation - Copyright (C) Andrew Tridgell 1997 + Copyright (C) Andrew Tridgell 1997-1998 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 -- cgit From 93b3c5813638d37f53717ec42feff408b8765e23 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 22 Mar 1998 01:31:50 +0000 Subject: - added a check for broken RH5 include files. With the standard RH5 includes (ie. unpatched RH5) Samba gets file corruption because of the incorrect definition of the shmid_ds structure. Updating your RH5 installation of glibc-devel fixes this. - don't try to fcntl_lock() a read-only fd in shmem.c - allow level 0 debug messages to get through in smbstatus (This used to be commit 45553771f90087a12db0153524146d42155d1d3f) --- source3/locking/shmem.c | 6 ++++++ source3/locking/shmem_sysv.c | 9 +++++++++ 2 files changed, 15 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 63d7ebd3d4..9f24076171 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -656,6 +656,9 @@ static BOOL smb_shm_lock_hash_entry( unsigned int entry) return False; } + if (read_only) + return True; + /* Do an exclusive wait lock on the 4 byte region mapping into this entry */ if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(int), F_WRLCK) == False) { @@ -679,6 +682,9 @@ static BOOL smb_shm_unlock_hash_entry( unsigned int entry ) DEBUG(0,("ERROR smb_shm_unlock_hash_entry : bad smb_shm_fd (%d)\n",smb_shm_fd)); return False; } + + if (read_only) + return True; /* Do a wait lock on the 4 byte region mapping into this entry */ if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(int), F_UNLCK) == False) diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index e415c2ebc5..b9d4594947 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -542,6 +542,15 @@ struct shmem_ops *sysv_shm_open(int ronly) int i; int pid; + + +#ifdef LINUX + if (sizeof(shm_ds) == 52) { + DEBUG(0,("WARNING: You probably have a broken set of glibc2 include files - disabling sysv shared memory\n")); + return NULL; + } +#endif + read_only = ronly; shm_size = lp_shmem_size(); -- cgit From e300c0346ff92035ff9568b55b34469193e29769 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Apr 1998 18:21:16 +0000 Subject: includes.h: Moved HPUX undefine of SEMMSL to where it actually does something. ipc.c: Added Luke's debug statement. locking_slow.c: Added FTRUNCATE_NEEDS_ROOT code for broken systems that need it (not sure what these are yet). membuffer.c ntdomain.h proto.h lib/rpc/include/rpc_dce.h lib/rpc/include/rpc_srvsvc.h lib/rpc/parse/parse_prs.c lib/rpc/parse/parse_rpc.c lib/rpc/server/srv_pipe_hnd.c lib/rpc/server/srv_util.c: Re-merge of Luke's NTDOM changes 'cos he's a lazy git with carpel tunnel syndrome :-). Jeremy. (This used to be commit 52e3966fbcf7b5fbdbc7cbe9ac0b453ab5bf3217) --- source3/locking/locking_slow.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index de2bb1701c..d6ac6efac1 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -502,8 +502,17 @@ mode file %s (%s)\n", fname, strerror(errno))); return 0; } /* Now truncate the file at this point. */ +#ifdef FTRUNCATE_NEEDS_ROOT + become_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + if(ftruncate(fd, newsize)!= 0) { + +#ifdef FTRUNCATE_NEEDS_ROOT + unbecome_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); if(*old_shares) @@ -515,6 +524,10 @@ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); } } +#ifdef FTRUNCATE_NEEDS_ROOT + unbecome_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + if(buf) free(buf); @@ -653,15 +666,29 @@ mode file %s (%s)\n", fname, strerror(errno))); free(buf); return; } + /* Now truncate the file at this point. */ +#ifdef FTRUNCATE_NEEDS_ROOT + become_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + if(ftruncate(fd, newsize) != 0) { + +#ifdef FTRUNCATE_NEEDS_ROOT + unbecome_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); if(buf) free(buf); return; } + +#ifdef FTRUNCATE_NEEDS_ROOT + unbecome_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ } /******************************************************************* @@ -795,8 +822,18 @@ deleting it (%s).\n",fname, strerror(errno))); } /* Now truncate the file at this point - just for safety. */ + +#ifdef FTRUNCATE_NEEDS_ROOT + become_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0) { + +#ifdef FTRUNCATE_NEEDS_ROOT + unbecome_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), strerror(errno))); @@ -805,6 +842,10 @@ mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entr return False; } +#ifdef FTRUNCATE_NEEDS_ROOT + unbecome_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + if(buf) free(buf); -- cgit From 3dfc0c847240ac7e12c39f4ed9c31a888949ade1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 May 1998 06:38:36 +0000 Subject: changed to use slprintf() instead of sprintf() just about everywhere. I've implemented slprintf() as a bounds checked sprintf() using mprotect() and a non-writeable page. This should prevent any sprintf based security holes. (This used to be commit ee09e9dadb69aaba5a751dd20ccc6d587d841bd6) --- source3/locking/shmem_sysv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index b9d4594947..20aea9283d 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -666,7 +666,7 @@ struct shmem_ops *sysv_shm_open(int ronly) shm_header_p = (struct ShmHeader *)shmat(shm_id, 0, read_only?SHM_RDONLY:0); - if ((int)shm_header_p == -1) { + if ((long)shm_header_p == -1) { DEBUG(0,("Can't attach to IPC area\n")); global_unlock(); return NULL; -- cgit From f888868f46a5418bac9ab528497136c152895305 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 May 1998 00:55:32 +0000 Subject: This is a security audit change of the main source. It removed all ocurrences of the following functions : sprintf strcpy strcat The replacements are slprintf, safe_strcpy and safe_strcat. It should not be possible to use code in Samba that uses sprintf, strcpy or strcat, only the safe_equivalents. Once Andrew has fixed the slprintf implementation then this code will be moved back to the 1.9.18 code stream. Jeremy. (This used to be commit 2d774454005f0b54e5684cf618da7060594dfcbb) --- source3/locking/locking_shm.c | 2 +- source3/locking/locking_slow.c | 16 +++++++++------- source3/locking/shmem.c | 6 +++--- 3 files changed, 13 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index e3c65ce286..afca567033 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -436,7 +436,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) new_mode_p->st_ino = inode; new_mode_p->num_share_mode_entries = 0; new_mode_p->share_mode_entries = 0; - strcpy(new_mode_p->file_name, fs_p->name); + pstrcpy(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]; diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index d6ac6efac1..635cd08e9a 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -81,12 +81,14 @@ static BOOL slow_stop_share_mode_mgmt(void) ******************************************************************/ static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) { - strcpy(name,lp_lockdir()); + int len; + pstrcpy(name,lp_lockdir()); trim_string(name,"","/"); if (!*name) return(False); + len = strlen(name); name += strlen(name); - sprintf(name,"/share.%u.%u",dev,inode); + slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%u",dev,inode); return(True); } @@ -784,7 +786,7 @@ deleting it.\n", fname)); SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1); - strcpy(buf + SMF_HEADER_LENGTH, fs_p->name); + pstrcpy(buf + SMF_HEADER_LENGTH, fs_p->name); } num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); @@ -1001,10 +1003,10 @@ static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue; - strcpy(lname,lp_lockdir()); + pstrcpy(lname,lp_lockdir()); trim_string(lname,NULL,"/"); - strcat(lname,"/"); - strcat(lname,s); + pstrcat(lname,"/"); + pstrcat(lname,s); fd = open(lname,read_only?O_RDONLY:O_RDWR,0); if (fd < 0) { @@ -1022,7 +1024,7 @@ static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) close(fd); continue; } - strcpy( fname, &buf[10]); + pstrcpy( fname, &buf[10]); close(fd); base = buf + SMF_HEADER_LENGTH + diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 9f24076171..21aaa9e24f 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -758,7 +758,7 @@ struct shmem_ops *smb_shm_open(int ronly) } trim_string(file_name,"","/"); if (!*file_name) return(False); - strcat(file_name, "/SHARE_MEM_FILE"); + pstrcat(file_name, "/SHARE_MEM_FILE"); DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); @@ -799,8 +799,8 @@ struct shmem_ops *smb_shm_open(int ronly) */ /* construct processreg file name */ - strcpy(smb_shm_processreg_name, file_name); - strcat(smb_shm_processreg_name, ".processes"); + pstrcpy(smb_shm_processreg_name, file_name); + pstrcat(smb_shm_processreg_name, ".processes"); if (!read_only && !smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes)) -- cgit From ee9a61841ac10d32d869a3893bc690c66f2bb1bb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 May 1998 22:11:24 +0000 Subject: includes.h: SunOS doesn't have strcasecmp, solaris versions prior to 2.6 don't have vsnprintf. locking_slow.c: slight tidy. make_smbcodepage.c: Use safe_strcpy instead of pstrcpy. nmbd_winsserver.c: Use pstrcpy instead of fstrcpy. smbmount.c: Fixed reported bug. util.c: Removed old fstrcpy/fstrcat functions. Jeremy. (This used to be commit f257d2e4bafd3944cca737699913a8d868279ca6) --- source3/locking/locking_slow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 635cd08e9a..183acd1f44 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -86,7 +86,7 @@ static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) trim_string(name,"","/"); if (!*name) return(False); len = strlen(name); - name += strlen(name); + name += len; slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%u",dev,inode); return(True); -- cgit From 88d88f5d0d23c8c849739b9441872734c0431c99 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Jun 1998 20:46:05 +0000 Subject: loadparm.c: Did it ! Changed defaults for 'case preserve' and 'short case preserve'. Also removed 'domain allow/deny' parameters. shmem_sysv.c: Added strerror code so I can see why sysV calls are failing. lib/rpc/server/srv_netlog.c: Removed code that used 'domain allow/deny' parameters - replaced with a comment so I will remember to fix this later. Jeremy. (This used to be commit 5f46c7c4b11a75f1ffbd806cde915b4bf28232db) --- source3/locking/shmem_sysv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 20aea9283d..439d89c6e0 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -658,7 +658,7 @@ struct shmem_ops *sysv_shm_open(int ronly) } if (shm_id == -1) { - DEBUG(0,("Can't create or use IPC area\n")); + DEBUG(0,("Can't create or use IPC area. Error was %s\n", strerror(errno))); global_unlock(); return NULL; } @@ -667,7 +667,7 @@ struct shmem_ops *sysv_shm_open(int ronly) shm_header_p = (struct ShmHeader *)shmat(shm_id, 0, read_only?SHM_RDONLY:0); if ((long)shm_header_p == -1) { - DEBUG(0,("Can't attach to IPC area\n")); + DEBUG(0,("Can't attach to IPC area. Error was %s\n", strerror(errno))); global_unlock(); return NULL; } @@ -676,7 +676,7 @@ struct shmem_ops *sysv_shm_open(int ronly) we use a registration file containing the processids of the file mapping processes */ if (shmctl(shm_id, IPC_STAT, &shm_ds) != 0) { - DEBUG(0,("ERROR shm_open : can't IPC_STAT\n")); + DEBUG(0,("ERROR shm_open : can't IPC_STAT. Error was %s\n", strerror(errno))); } if (!read_only) { -- cgit From 6491a956ef0b6a54b28887521f75e2f54f18a6d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Jul 1998 22:23:56 +0000 Subject: nttrans.c: More NT SMB stuff. shmem_sysv.c: Fix for shared memory problems on several systems, Second and subsequent use of shmget should use zero as the size. Fix from Veselin Terzic Jeremy. (This used to be commit 1cd94b24592ca31ffae671acfd83b0d42b212cab) --- source3/locking/shmem_sysv.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 439d89c6e0..3466930f4c 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -641,8 +641,15 @@ struct shmem_ops *sysv_shm_open(int ronly) } } - /* try to use an existing key */ - shm_id = shmget(SHMEM_KEY, shm_size, 0); + /* + * Try to use an existing key. Note that + * in order to use an existing key successfully + * size must be zero else shmget returns EINVAL. + * Thanks to Veselin Terzic + * for pointing this out. + */ + + shm_id = shmget(SHMEM_KEY, 0, 0); /* if that failed then create one */ if (shm_id == -1) { -- cgit From 06c0349c445958aebb8a4611bdb7082711585754 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Jul 1998 00:10:26 +0000 Subject: locking.c: Added lock type to is_locked() and do_lock() as the code in reply_lockingX wasn't taking account of the difference between read and write locks ! How did this ever work :-) ! reply.c: server.c: Add lock type to is_locked() and do_lock(). util.c: Also added code from klausr@ITAP.Physik.Uni-Stuttgart.De to fix problem with log files growing too large if an smbd writes less than 100 debug messages. Jeremy. (This used to be commit 80080abf772a470d5f0f4dcd4a75fb2a09a9fb2a) --- source3/locking/locking.c | 74 ++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 27 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 189ac0bcfe..d5d767d2cc 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -39,11 +39,13 @@ extern files_struct Files[]; static struct share_ops *share_ops; /**************************************************************************** - utility function called to see if a file region is locked + Utility function called to see if a file region is locked. ****************************************************************************/ -BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset) + +BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset, int lock_type) { int snum = SNUM(cnum); + files_struct *fsp = &Files[fnum]; if (count == 0) return(False); @@ -51,17 +53,22 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset) if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count, - (Files[fnum].can_write?F_WRLCK:F_RDLCK))); + if((lock_type == F_WRLCK) && !fsp->can_write) + lock_type = F_RDLCK; + + return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); } /**************************************************************************** - utility function called by locking requests + Utility function called by locking requests. ****************************************************************************/ -BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode) + +BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int lock_type, + int *eclass,uint32 *ecode) { BOOL ok = False; + files_struct *fsp = &Files[fnum]; if (!lp_locking(SNUM(cnum))) return(True); @@ -72,9 +79,12 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ec return False; } - if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum)) - ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count, - (Files[fnum].can_write?F_WRLCK:F_RDLCK)); + if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) { + if(lock_type == F_WRLCK && !fsp->can_write) + lock_type = F_RDLCK; + + ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,lock_type); + } if (!ok) { *eclass = ERRDOS; @@ -86,17 +96,19 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ec /**************************************************************************** - utility function called by unlocking requests + Utility function called by unlocking requests. ****************************************************************************/ + BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode) { BOOL ok = False; + files_struct *fsp = &Files[fnum]; if (!lp_locking(SNUM(cnum))) return(True); - if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum)) - ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); + if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) + ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); if (!ok) { *eclass = ERRDOS; @@ -109,8 +121,9 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * /**************************************************************************** - initialise the locking functions + Initialise the locking functions. ****************************************************************************/ + BOOL locking_init(int read_only) { if (share_ops) return True; @@ -133,8 +146,9 @@ BOOL locking_init(int read_only) } /******************************************************************* - deinitialize the share_mode management - ******************************************************************/ + Deinitialize the share_mode management. +******************************************************************/ + BOOL locking_end(void) { if (share_ops) @@ -144,24 +158,27 @@ BOOL locking_end(void) /******************************************************************* - lock a hash bucket entry - ******************************************************************/ + Lock a hash bucket entry. +******************************************************************/ + BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) { return share_ops->lock_entry(cnum, dev, inode, ptok); } /******************************************************************* - unlock a hash bucket entry - ******************************************************************/ + Unlock a hash bucket entry. +******************************************************************/ + BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token) { return share_ops->unlock_entry(cnum, dev, inode, token); } /******************************************************************* -get all share mode entries for a dev/inode pair. + Get all share mode entries for a dev/inode pair. ********************************************************************/ + int get_share_modes(int cnum, int token, uint32 dev, uint32 inode, share_mode_entry **shares) { @@ -169,42 +186,45 @@ int get_share_modes(int cnum, int token, uint32 dev, uint32 inode, } /******************************************************************* -del the share mode of a file. + Del the share mode of a file. ********************************************************************/ + void del_share_mode(int token, int fnum) { share_ops->del_entry(token, fnum); } /******************************************************************* -set the share mode of a file. Return False on fail, True on success. + Set the share mode of a file. Return False on fail, True on success. ********************************************************************/ + BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type) { return share_ops->set_entry(token, fnum, port, op_type); } /******************************************************************* -Remove an oplock port and mode entry from a share mode. + Remove an oplock port and mode entry from a share mode. ********************************************************************/ BOOL remove_share_oplock(int fnum, int token) { return share_ops->remove_oplock(fnum, token); } - /******************************************************************* -call the specified function on each entry under management by the -share mode system + Call the specified function on each entry under management by the + share mode system. ********************************************************************/ + int share_mode_forall(void (*fn)(share_mode_entry *, char *)) { return share_ops->forall(fn); } /******************************************************************* -dump the state of the system + Dump the state of the system. ********************************************************************/ + void share_status(FILE *f) { share_ops->status(f); -- cgit From 7abcd0521e36425bf7c3dc90929c00ed49e9ab07 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Jul 1998 18:15:31 +0000 Subject: loadparm.c: Added strict sync parameter. locking.c: Added code to deal with real open mode of file. reply.c: Added strict sync parameter. server.c: Added strict sync parameter. Fixed open modes. Jeremy. (This used to be commit ed57b603b5c9333d588e62d774ad2be67e43ffd9) --- source3/locking/locking.c | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d5d767d2cc..6aecfed6a5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -38,6 +38,35 @@ extern files_struct Files[]; static struct share_ops *share_ops; +/**************************************************************************** + Utility function to map a lock type correctly depending on the real open + mode of a file. +****************************************************************************/ + +static int map_lock_type( files_struct *fsp, int lock_type) +{ + if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) { + /* + * Many UNIX's cannot get a write lock on a file opened read-only. + * Win32 locking semantics allow this. + * Do the best we can and attempt a read-only lock. + */ + return F_RDLCK; + } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { + /* + * Ditto for read locks on write only files. + */ + return F_WRLCK; + } + + /* + * This return should be the most normal, as we attempt + * to always open files read/write. + */ + + return lock_type; +} + /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ @@ -53,10 +82,8 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset, int lock_type) if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - if((lock_type == F_WRLCK) && !fsp->can_write) - lock_type = F_RDLCK; - - return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); + return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count, + map_lock_type(fsp,lock_type))); } @@ -79,12 +106,9 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int lock_type, return False; } - if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) { - if(lock_type == F_WRLCK && !fsp->can_write) - lock_type = F_RDLCK; - - ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,lock_type); - } + if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) + ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count, + map_lock_type(fsp,lock_type)); if (!ok) { *eclass = ERRDOS; -- cgit From 83951dd37685ac8c5e45f44270d932250f785be5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Jul 1998 18:26:47 +0000 Subject: locking.c: Don't need to do map_lock_type on *testing* a lock, just on setting. Jeremy. (This used to be commit 17f68cc86cafbb04dbd9cc6ecc0aac7b911c9b70) --- source3/locking/locking.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 6aecfed6a5..f443482544 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -82,8 +82,13 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset, int lock_type) if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count, - map_lock_type(fsp,lock_type))); + /* + * Note that most UNIX's can *test* for a write lock on + * a read-only fd, just not *set* a write lock on a read-only + * fd. So we don't need to use map_lock_type here. + */ + + return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); } -- cgit From c48b3fce6be6d5d952cbcda0ddae223dda5a576f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 29 Jul 1998 00:27:23 +0000 Subject: locking.c: Print messages when we downgrade a lock. reply.c: Do the same mask expansion we do in trans2.c - needed for Win98. trans2.c: Make the mask expansion into a function call now we have to do it twice. Jeremy. (This used to be commit 7b3a9d6285cc0d1967155a68845e28c6296ecc67) --- source3/locking/locking.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f443482544..e4ca6bbb04 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -51,11 +51,13 @@ static int map_lock_type( files_struct *fsp, int lock_type) * Win32 locking semantics allow this. * Do the best we can and attempt a read-only lock. */ + DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n")); return F_RDLCK; } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { /* * Ditto for read locks on write only files. */ + DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n")); return F_WRLCK; } -- cgit From 64578c0589a3a741f81fb55c16eeb882128da00b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 Jul 1998 03:08:05 +0000 Subject: merge from the autoconf2 branch to the main branch (This used to be commit 3bda7ac417107a7b01d91805ca71c4330657ed21) --- source3/locking/locking.c | 11 ++++------ source3/locking/locking_shm.c | 9 ++++++--- source3/locking/locking_slow.c | 46 +++++++----------------------------------- source3/locking/shmem.c | 6 +++--- source3/locking/shmem_sysv.c | 11 +--------- 5 files changed, 21 insertions(+), 62 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e4ca6bbb04..e303fb5482 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -88,7 +88,7 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset, int lock_type) * Note that most UNIX's can *test* for a write lock on * a read-only fd, just not *set* a write lock on a read-only * fd. So we don't need to use map_lock_type here. - */ + */ return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); } @@ -161,13 +161,10 @@ BOOL locking_init(int read_only) #ifdef FAST_SHARE_MODES share_ops = locking_shm_init(read_only); - if (!share_ops) { - DEBUG(0,("ERROR: Failed to initialise fast share modes - trying slow code\n")); - } - if (share_ops) return True; -#endif - +#else share_ops = locking_slow_init(read_only); +#endif + if (!share_ops) { DEBUG(0,("ERROR: Failed to initialise share modes!\n")); return False; diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index afca567033..43a927e14c 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -32,9 +32,10 @@ October 1997 - split into separate file (tridge) */ +#include "includes.h" + #ifdef FAST_SHARE_MODES -#include "includes.h" extern int DEBUGLEVEL; extern connection_struct Connections[]; extern files_struct Files[]; @@ -678,13 +679,15 @@ struct share_ops *locking_shm_init(int ronly) { read_only = ronly; -#ifdef USE_SYSV_IPC +#ifdef HAVE_SYSV_IPC shmops = sysv_shm_open(read_only); if (shmops) return &share_ops; #endif +#ifdef HAVE_SHARED_MMAP shmops = smb_shm_open(read_only); if (shmops) return &share_ops; +#endif return NULL; } @@ -692,7 +695,7 @@ struct share_ops *locking_shm_init(int ronly) #else int locking_shm_dummy_procedure(void) {return 0;} -#endif +#endif /* FAST_SHARE_MODES */ diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 183acd1f44..1f8f962ac9 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -33,6 +33,9 @@ */ #include "includes.h" + +#ifndef FAST_SHARE_MODES + extern int DEBUGLEVEL; extern connection_struct Connections[]; extern files_struct Files[]; @@ -504,17 +507,8 @@ mode file %s (%s)\n", fname, strerror(errno))); return 0; } /* Now truncate the file at this point. */ -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - if(ftruncate(fd, newsize)!= 0) { - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); if(*old_shares) @@ -526,10 +520,6 @@ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); } } -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - if(buf) free(buf); @@ -670,27 +660,14 @@ mode file %s (%s)\n", fname, strerror(errno))); } /* Now truncate the file at this point. */ -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - if(ftruncate(fd, newsize) != 0) { - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); if(buf) free(buf); return; } - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ } /******************************************************************* @@ -825,17 +802,8 @@ deleting it (%s).\n",fname, strerror(errno))); /* Now truncate the file at this point - just for safety. */ -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0) { - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), strerror(errno))); @@ -844,10 +812,6 @@ mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entr return False; } -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - if(buf) free(buf); @@ -1093,3 +1057,7 @@ struct share_ops *locking_slow_init(int ronly) return &share_ops; } +#else + int locking_slow_dummy_procedure(void) +{return 0;} +#endif /* !FAST_SHARE_MODES */ diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 21aaa9e24f..48f78d2a5b 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -23,7 +23,7 @@ #include "includes.h" -#ifdef FAST_SHARE_MODES +#ifdef HAVE_SHARED_MMAP extern int DEBUGLEVEL; @@ -874,7 +874,7 @@ struct shmem_ops *smb_shm_open(int ronly) } -#else /* FAST_SHARE_MODES */ +#else /* HAVE_SHARED_MMAP */ int shmem_dummy_procedure(void) {return 0;} -#endif /* FAST_SHARE_MODES */ +#endif /* HAVE_SHARED_MMAP */ diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 3466930f4c..0809e0546f 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -23,7 +23,7 @@ #include "includes.h" -#ifdef USE_SYSV_IPC +#ifdef HAVE_SYSV_IPC extern int DEBUGLEVEL; @@ -542,15 +542,6 @@ struct shmem_ops *sysv_shm_open(int ronly) int i; int pid; - - -#ifdef LINUX - if (sizeof(shm_ds) == 52) { - DEBUG(0,("WARNING: You probably have a broken set of glibc2 include files - disabling sysv shared memory\n")); - return NULL; - } -#endif - read_only = ronly; shm_size = lp_shmem_size(); -- cgit From 7284bb5ca049a682097bb25afcf25d40f1ac5479 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Jul 1998 21:18:57 +0000 Subject: Makefile.in: Moved UBIQX stuff into UTILOBJ. loadparm.c: Added "ole locking compatibility" option (default "true"). locking.c: Changes to implement union in files_struct. locking_shm.c: Changes to implement union in files_struct. nttrans.c: Made opening a directory explicit (we have to). Added create directory code for nttrans. reply.c: Changes to implement union in files_struct. server.c: Changes to implement union in files_struct. Added create directory code. trans2.c: Changes to implement union in files_struct. smb.h: Changes to implement union in files_struct. util.c: Changed linked list code to UNIQX linked list. This will make the other lists I need to implement for ChangeNotify and blocking locks easier. Jeremy. (This used to be commit 3a5eea850bb256b39cff8ace1e4fb4e0c1f5472b) --- source3/locking/locking.c | 10 +++++----- source3/locking/locking_shm.c | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e303fb5482..1b01efd7ef 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -45,7 +45,7 @@ static struct share_ops *share_ops; static int map_lock_type( files_struct *fsp, int lock_type) { - if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) { + if((lock_type == F_WRLCK) && (fsp->f_u.fd_ptr->real_open_flags == O_RDONLY)) { /* * Many UNIX's cannot get a write lock on a file opened read-only. * Win32 locking semantics allow this. @@ -53,7 +53,7 @@ static int map_lock_type( files_struct *fsp, int lock_type) */ DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n")); return F_RDLCK; - } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { + } else if( (lock_type == F_RDLCK) && (fsp->f_u.fd_ptr->real_open_flags == O_WRONLY)) { /* * Ditto for read locks on write only files. */ @@ -90,7 +90,7 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset, int lock_type) * fd. So we don't need to use map_lock_type here. */ - return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); + return(fcntl_lock(fsp->f_u.fd_ptr->fd,F_GETLK,offset,count,lock_type)); } @@ -114,7 +114,7 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int lock_type, } if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) - ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count, + ok = fcntl_lock(fsp->f_u.fd_ptr->fd,F_SETLK,offset,count, map_lock_type(fsp,lock_type)); if (!ok) { @@ -139,7 +139,7 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * return(True); if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) - ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); + ok = fcntl_lock(fsp->f_u.fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); if (!ok) { *eclass = ERRDOS; diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 43a927e14c..95d59a8465 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -268,8 +268,8 @@ static void shm_del_share_mode(int token, int fnum) BOOL found = False; int pid = getpid(); - dev = Files[fnum].fd_ptr->dev; - inode = Files[fnum].fd_ptr->inode; + dev = Files[fnum].f_u.fd_ptr->dev; + inode = Files[fnum].f_u.fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); @@ -396,8 +396,8 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) int new_entry_offset; BOOL found = False; - dev = fs_p->fd_ptr->dev; - inode = fs_p->fd_ptr->inode; + dev = fs_p->f_u.fd_ptr->dev; + inode = fs_p->f_u.fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); @@ -505,8 +505,8 @@ static BOOL shm_remove_share_oplock(int fnum, int token) BOOL found = False; int pid = getpid(); - dev = Files[fnum].fd_ptr->dev; - inode = Files[fnum].fd_ptr->inode; + dev = Files[fnum].f_u.fd_ptr->dev; + inode = Files[fnum].f_u.fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); -- cgit From 7448091da6ee11709b8e5117ff6810515567f88a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 3 Aug 1998 19:07:55 +0000 Subject: First implementation of ChangeNotify - this version only checks for changes in the directory modify timestamps. A better version will look at the requested client flags, and create a hash that represents the current state of the directory, and check against this instead. debug.c: Added lp_timestamp_logs() function. loadparm.c: Added "change notify timeout" in seconds (default 60) - this is the scan rate for a directory. Added ""timestamp logs" boolean - default True. Turns off log timestamps (so I can read them :-). nttrans.c: ChangeNotify implementation. server.c: ChangeNotify implementation. shmem_sysv.c: Added exits on shmem errors (without them smbd can core dump if some calls fail). smb.h: Added ChangeNotify flags for future use. util.c: Tidied up typedef. Jeremy. (This used to be commit a0748c3f53974483680ebe2ea4f556ece8d7fa43) --- source3/locking/shmem_sysv.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 0809e0546f..b8b9c2cb45 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -572,7 +572,8 @@ struct shmem_ops *sysv_shm_open(int ronly) su.val = 1; for (i=0;i Date: Tue, 11 Aug 1998 23:28:35 +0000 Subject: include/smb.h: Removed dir_ptr. Not needed. locking/locking.c: First cut a blocking lock code. #ifdef'ed out for now. locking/locking_shm.c: Removed dir_ptr. Not needed. smbd/nttrans.c: More work on ChangeNotify - return is not an error and needs to be handled as a nttrans with zero params. Removed dir_ptr. Not needed. smbd/reply.c: smbd/server.c: smbd/trans2.c: Removed dir_ptr. Not needed. Hmmm. At the moment smbclient is broken - doesn't issue prompt correctly. This needs looking at. Jeremy. (This used to be commit ddfbcc05815621d3c463f92faed047f126412342) --- source3/locking/locking.c | 144 ++++++++++++++++++++++++++++++++++++++++-- source3/locking/locking_shm.c | 12 ++-- 2 files changed, 145 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 1b01efd7ef..b56d1cc7ed 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -38,6 +38,140 @@ extern files_struct Files[]; static struct share_ops *share_ops; +#if 0 /* JRATEST - blocking lock code - under development. */ + +/**************************************************************************** + This is the structure to queue to implement blocking locks. + notify. It consists of the requesting SMB and the expiry time. +*****************************************************************************/ + +typedef struct { + ubi_slNode msg_next; + time_t expire_time; + int lock_num; + char *inbuf; + int length; +} blocking_lock_record; + +static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0}; + +/**************************************************************************** + Function to push a blocking lockingX request onto the lock queue. +****************************************************************************/ + +BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num) +{ + blocking_lock_record *blr; + int fnum = GETFNUM(inbuf,smb_vwv2); + + /* + * Now queue an entry on the blocking lock queue. We setup + * the expiration time here. + */ + + if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) { + DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); + return False; + } + + if((blr->inbuf = (char *)malloc(length)) == NULL) { + DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); + free((char *)blr); + return False; + } + + memcpy(blr->inbuf, inbuf, length); + blr->length = length; + blr->lock_num = lock_num; + blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; + + ubi_slAddTail(&blocking_lock_queue, blr); + + DEBUG(3,("push_blocking_lock_request: lock request blocked with expiry time %d \ +for fnum = %d, name = %s\n", blr->expire_time, fnum, Files[fnum].name )); + + return True; +} + +/**************************************************************************** + Process the blocking lock queue. Note that this is only called as root. +*****************************************************************************/ + +void process_blocking_lock_queue(time_t t) +{ + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; + + if(blr == NULL) + return; + + /* + * Go through the queue and see if we can get any of the locks. + */ + + while(blr != NULL) { + int fnum = GETFNUM(blr->inbuf,smb_vwv2); + int cnum = SVAL(blr->inbuf,smb_tid); + files_struct *fsp = &Files[fnum]; + uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : + SVAL(blr->inbuf,smb_uid); + + if(blr->expire_time > t) { + /* + * Lock expired - throw away all previously + * obtained locks and return lock error. + */ + + blocking_lock_fail(blr); + blocking_lock_reply_error(blr); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + if(!become_user(&Connections[cnum],cnum,vuid)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", + vuid )); + /* + * Remove the entry and return an error to the client. + */ + blocking_lock_reply_error(blr); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + if(!become_service(cnum,True)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become service cnum=%d. \ +Error was %s.\n", cnum, strerror(errno) )); + /* + * Remove the entry and return an error to the client. + */ + blocking_lock_reply_error(blr); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + + /* + * Go through the remaining locks and try and obtain them. + * If we get them all then return success and delete this + * record. + */ + + if(blocking_lock_record_process(blr)) { + /* + * Success - + unbecome_user(); + /* + * Move to the next in the list. + */ + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } +#endif /* JRATEST */ + /**************************************************************************** Utility function to map a lock type correctly depending on the real open mode of a file. @@ -45,7 +179,7 @@ static struct share_ops *share_ops; static int map_lock_type( files_struct *fsp, int lock_type) { - if((lock_type == F_WRLCK) && (fsp->f_u.fd_ptr->real_open_flags == O_RDONLY)) { + if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) { /* * Many UNIX's cannot get a write lock on a file opened read-only. * Win32 locking semantics allow this. @@ -53,7 +187,7 @@ static int map_lock_type( files_struct *fsp, int lock_type) */ DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n")); return F_RDLCK; - } else if( (lock_type == F_RDLCK) && (fsp->f_u.fd_ptr->real_open_flags == O_WRONLY)) { + } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { /* * Ditto for read locks on write only files. */ @@ -90,7 +224,7 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset, int lock_type) * fd. So we don't need to use map_lock_type here. */ - return(fcntl_lock(fsp->f_u.fd_ptr->fd,F_GETLK,offset,count,lock_type)); + return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); } @@ -114,7 +248,7 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int lock_type, } if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) - ok = fcntl_lock(fsp->f_u.fd_ptr->fd,F_SETLK,offset,count, + ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count, map_lock_type(fsp,lock_type)); if (!ok) { @@ -139,7 +273,7 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * return(True); if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) - ok = fcntl_lock(fsp->f_u.fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); + ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); if (!ok) { *eclass = ERRDOS; diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 95d59a8465..43a927e14c 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -268,8 +268,8 @@ static void shm_del_share_mode(int token, int fnum) BOOL found = False; int pid = getpid(); - dev = Files[fnum].f_u.fd_ptr->dev; - inode = Files[fnum].f_u.fd_ptr->inode; + dev = Files[fnum].fd_ptr->dev; + inode = Files[fnum].fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); @@ -396,8 +396,8 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) int new_entry_offset; BOOL found = False; - dev = fs_p->f_u.fd_ptr->dev; - inode = fs_p->f_u.fd_ptr->inode; + dev = fs_p->fd_ptr->dev; + inode = fs_p->fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); @@ -505,8 +505,8 @@ static BOOL shm_remove_share_oplock(int fnum, int token) BOOL found = False; int pid = getpid(); - dev = Files[fnum].f_u.fd_ptr->dev; - inode = Files[fnum].f_u.fd_ptr->inode; + dev = Files[fnum].fd_ptr->dev; + inode = Files[fnum].fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); -- cgit From fcb5437da6a32b641260502d371494df614949d0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 12 Aug 1998 10:09:41 +0000 Subject: fixed the nested comment - Jeremy, do you want that unbecome_user() or not? (This used to be commit 638ee7d265982ca95ae7f49e2a84431bdf147c21) --- source3/locking/locking.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index b56d1cc7ed..f15c76ba6d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -163,8 +163,7 @@ Error was %s.\n", cnum, strerror(errno) )); if(blocking_lock_record_process(blr)) { /* * Success - - unbecome_user(); - /* + unbecome_user(); * Move to the next in the list. */ prev = blr; -- cgit From ce333b25dba43822b7f06b3afbd6c3cee04f357e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Aug 1998 02:10:45 +0000 Subject: More blocking lock code - still #ifdef'ed out - under development. Jeremy. (This used to be commit c9695bdf2e22c3081841f116af37340308d447aa) --- source3/locking/locking.c | 180 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 170 insertions(+), 10 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f15c76ba6d..da5cdf46dd 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -35,6 +35,7 @@ extern int DEBUGLEVEL; extern connection_struct Connections[]; extern files_struct Files[]; +extern int Client; static struct share_ops *share_ops; @@ -93,6 +94,154 @@ for fnum = %d, name = %s\n", blr->expire_time, fnum, Files[fnum].name )); return True; } +/**************************************************************************** + Return a blocking lock success SMB. +*****************************************************************************/ + +void blocking_lock_reply_success(blocking_lock_record *blr) +{ + extern int chain_size; + extern int chain_fnum; + extern char *OutBuffer; + char *outbuf = OutBuffer; + int bufsize = BUFFER_SIZE; + char *inbuf = blr->inbuf; + int fnum = GETFNUM(inbuf,smb_vwv2); + int outsize = 0; + + construct_reply_common(inbuf, outbuf); + set_message(outbuf,2,0,True); + + /* + * As this message is a lockingX call we must handle + * any following chained message correctly. + * This is normally handled in construct_reply(), + * but as that calls switch_message, we can't use + * that here and must set up the chain info manually. + */ + + chain_fnum = fnum; + chain_size = 0; + + outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); + + outsize += chain_size; + + if(outsize > 4) + smb_setlen(outbuf,outsize - 4); + + send_smb(Client,outbuf); +} + +/**************************************************************************** + Return a lock fail error. Undo all the locks we have obtained first. +*****************************************************************************/ + +void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode) +{ + extern char *OutBuffer; + char *outbuf = OutBuffer; + int bufsize = BUFFER_SIZE; + char *inbuf = blr->inbuf; + int fnum = GETFNUM(inbuf,smb_vwv2); + uint16 num_ulocks = SVAL(inbuf,smb_vwv6); + uint16 num_locks = SVAL(inbuf,smb_vwv7); + uint32 count, offset; + int cnum; + int lock_num = blr->lock_num; + char *data; + int i; + + cnum = SVAL(inbuf,smb_tid); + + data = smb_buf(inbuf) + 10*num_ulocks; + + /* + * Data now points at the beginning of the list + * of smb_lkrng structs. + */ + + for(i = blr->lock_num; i >= 0; i--) { + count = IVAL(data,SMB_LKLEN_OFFSET(i)); + offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2); + } + + construct_reply_common(inbuf, outbuf); + ERROR(eclass,ecode); + send_smb(Client,outbuf); +} + +/**************************************************************************** + Attempt to finish off getting all pending blocking locks. + Returns True if we want to be removed from the list. +*****************************************************************************/ + +BOOL blocking_lock_record_process(blocking_lock_record *blr) +{ + char *inbuf = blr->inbuf; + unsigned char locktype = CVAL(inbuf,smb_vwv3); + int fnum = GETFNUM(inbuf,smb_vwv2); + uint16 num_ulocks = SVAL(inbuf,smb_vwv6); + uint16 num_locks = SVAL(inbuf,smb_vwv7); + uint32 count, offset; + int cnum; + int lock_num = blr->lock_num; + char *data; + int eclass=0; + uint32 ecode=0; + + cnum = SVAL(inbuf,smb_tid); + + data = smb_buf(inbuf) + 10*num_ulocks; + + /* + * Data now points at the beginning of the list + * of smb_lkrng structs. + */ + + for(; blr->lock_num < num_locks; blr->lock_num++) { + count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num)); + offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num)); + if(!do_lock(fnum,cnum,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), + &eclass, &ecode)) + break; + } + + if(blr->lock_num == num_locks) { + + /* + * Success - we got all the locks. + */ + + DEBUG(3,("blocking_lock_record_process fnum=%d cnum=%d type=%d num_locks=%d\n", + fnum, cnum, (unsigned int)locktype, num_locks) ); + + blocking_lock_reply_success(blr); + return True; + + } else if((errno != EACCES) && (errno != EAGAIN)) { + + /* + * We have other than a "can't get lock" POSIX + * error. Free any locks we had and return an error. + * Return True so we get dequeued. + */ + + blocking_lock_reply_error(blr, eclass, ecode); + return True; + } + + /* + * Still can't get all the locks - keep waiting. + */ + + DEBUG(10,("blocking_lock_record_process: only got %d locks of %d needed for fnum = %d. \ +Waiting..\n", blr->lock_num, num_locks, fnum )); + + return False; +} + /**************************************************************************** Process the blocking lock queue. Note that this is only called as root. *****************************************************************************/ @@ -116,14 +265,18 @@ void process_blocking_lock_queue(time_t t) uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(blr->inbuf,smb_uid); - if(blr->expire_time > t) { + DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", + fnum, fsp->name )); + + if((blr->expire_time != -1) && (blr->expire_time > t)) { /* * Lock expired - throw away all previously * obtained locks and return lock error. */ + DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", + fnum, fsp->name )); - blocking_lock_fail(blr); - blocking_lock_reply_error(blr); + blocking_lock_reply_error(blr,ERRSRV,ERRaccess); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); continue; @@ -135,7 +288,7 @@ void process_blocking_lock_queue(time_t t) /* * Remove the entry and return an error to the client. */ - blocking_lock_reply_error(blr); + blocking_lock_reply_error(blr,ERRSRV,ERRaccess); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); continue; @@ -147,7 +300,7 @@ Error was %s.\n", cnum, strerror(errno) )); /* * Remove the entry and return an error to the client. */ - blocking_lock_reply_error(blr); + blocking_lock_reply_error(blr,ERRSRV,ERRaccess); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); unbecome_user(); @@ -156,19 +309,26 @@ Error was %s.\n", cnum, strerror(errno) )); /* * Go through the remaining locks and try and obtain them. - * If we get them all then return success and delete this - * record. + * The call returns True if all locks were obtained successfully + * and False if we still need to wait. */ if(blocking_lock_record_process(blr)) { - /* - * Success - - unbecome_user(); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + + unbecome_user(); + + /* * Move to the next in the list. */ prev = blr; blr = (blocking_lock_record *)ubi_slNext(blr); } +} #endif /* JRATEST */ /**************************************************************************** -- cgit From 3cf6cc6134960c99adb702b21394a4a607cfe30a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Aug 1998 02:02:40 +0000 Subject: Makefile.in: Changed so that make proto will work with ldap & nisplus. locking/locking.c: Made #ifdef'ed out functions static for Make proto. lib/util.c: Re-instated old mask_match code for UNIX filesystem checks only. Client calls use the new mask_match code. Changed the name of the old function to unix_mask_match. Jeremy. (This used to be commit b68e756ff57622c6c74f28031d4be964d7b1c9bc) --- source3/locking/locking.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index da5cdf46dd..c1c0659496 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -98,7 +98,7 @@ for fnum = %d, name = %s\n", blr->expire_time, fnum, Files[fnum].name )); Return a blocking lock success SMB. *****************************************************************************/ -void blocking_lock_reply_success(blocking_lock_record *blr) +static void blocking_lock_reply_success(blocking_lock_record *blr) { extern int chain_size; extern int chain_fnum; @@ -137,7 +137,7 @@ void blocking_lock_reply_success(blocking_lock_record *blr) Return a lock fail error. Undo all the locks we have obtained first. *****************************************************************************/ -void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode) +static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode) { extern char *OutBuffer; char *outbuf = OutBuffer; @@ -177,7 +177,7 @@ void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecod Returns True if we want to be removed from the list. *****************************************************************************/ -BOOL blocking_lock_record_process(blocking_lock_record *blr) +static BOOL blocking_lock_record_process(blocking_lock_record *blr) { char *inbuf = blr->inbuf; unsigned char locktype = CVAL(inbuf,smb_vwv3); -- cgit From b9623ab59e813131b1ed3f51616a46e719d59c21 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 14 Aug 1998 17:38:29 +0000 Subject: this is the bug change to using connection_struct* instead of cnum. Connections[] is now a local array in server.c I might have broken something with this change. In particular the oplock code is suspect and some .dll files aren't being oplocked when I expected them to be. I'll look at it after I've got some sleep. (This used to be commit c7ee025ead4a85b6fa44a832047b878451845fb6) --- source3/locking/locking.c | 87 +++++++++++++++++++----------------------- source3/locking/locking_shm.c | 20 +++++----- source3/locking/locking_slow.c | 78 +++++++++++++++++++------------------ source3/locking/shmem.c | 2 +- 4 files changed, 91 insertions(+), 96 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index c1c0659496..bb852b07d6 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -33,7 +33,6 @@ #include "includes.h" extern int DEBUGLEVEL; -extern connection_struct Connections[]; extern files_struct Files[]; extern int Client; @@ -147,13 +146,10 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; - int cnum; int lock_num = blr->lock_num; char *data; int i; - cnum = SVAL(inbuf,smb_tid); - data = smb_buf(inbuf) + 10*num_ulocks; /* @@ -164,7 +160,7 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int for(i = blr->lock_num; i >= 0; i--) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2); + do_unlock(fnum,conn,count,offset,&dummy1,&dummy2); } construct_reply_common(inbuf, outbuf); @@ -185,14 +181,11 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; - int cnum; int lock_num = blr->lock_num; char *data; int eclass=0; uint32 ecode=0; - cnum = SVAL(inbuf,smb_tid); - data = smb_buf(inbuf) + 10*num_ulocks; /* @@ -203,7 +196,7 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) for(; blr->lock_num < num_locks; blr->lock_num++) { count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num)); offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num)); - if(!do_lock(fnum,cnum,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), + if(!do_lock(fnum,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) break; } @@ -214,8 +207,8 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) * Success - we got all the locks. */ - DEBUG(3,("blocking_lock_record_process fnum=%d cnum=%d type=%d num_locks=%d\n", - fnum, cnum, (unsigned int)locktype, num_locks) ); + DEBUG(3,("blocking_lock_record_process fnum=%d type=%d num_locks=%d\n", + fnum, (unsigned int)locktype, num_locks) ); blocking_lock_reply_success(blr); return True; @@ -260,7 +253,6 @@ void process_blocking_lock_queue(time_t t) while(blr != NULL) { int fnum = GETFNUM(blr->inbuf,smb_vwv2); - int cnum = SVAL(blr->inbuf,smb_tid); files_struct *fsp = &Files[fnum]; uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(blr->inbuf,smb_uid); @@ -282,7 +274,7 @@ void process_blocking_lock_queue(time_t t) continue; } - if(!become_user(&Connections[cnum],cnum,vuid)) { + if(!become_user(conn,vuid)) { DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", vuid )); /* @@ -294,9 +286,8 @@ void process_blocking_lock_queue(time_t t) continue; } - if(!become_service(cnum,True)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become service cnum=%d. \ -Error was %s.\n", cnum, strerror(errno) )); + if(!become_service(conn,True)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); /* * Remove the entry and return an error to the client. */ @@ -365,39 +356,39 @@ static int map_lock_type( files_struct *fsp, int lock_type) /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ - -BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset, int lock_type) +BOOL is_locked(int fnum,connection_struct *conn, + uint32 count,uint32 offset, int lock_type) { - int snum = SNUM(cnum); - files_struct *fsp = &Files[fnum]; + int snum = SNUM(conn); + files_struct *fsp = &Files[fnum]; - if (count == 0) - return(False); + if (count == 0) + return(False); - if (!lp_locking(snum) || !lp_strict_locking(snum)) - return(False); - - /* - * Note that most UNIX's can *test* for a write lock on - * a read-only fd, just not *set* a write lock on a read-only - * fd. So we don't need to use map_lock_type here. - */ + if (!lp_locking(snum) || !lp_strict_locking(snum)) + return(False); - return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); + /* + * Note that most UNIX's can *test* for a write lock on + * a read-only fd, just not *set* a write lock on a read-only + * fd. So we don't need to use map_lock_type here. + */ + + return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); } /**************************************************************************** Utility function called by locking requests. ****************************************************************************/ - -BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int lock_type, +BOOL do_lock(int fnum,connection_struct *conn, + uint32 count,uint32 offset,int lock_type, int *eclass,uint32 *ecode) { BOOL ok = False; files_struct *fsp = &Files[fnum]; - if (!lp_locking(SNUM(cnum))) + if (!lp_locking(SNUM(conn))) return(True); if (count == 0) { @@ -406,7 +397,7 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int lock_type, return False; } - if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) + if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->conn == conn)) ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count, map_lock_type(fsp,lock_type)); @@ -422,16 +413,16 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int lock_type, /**************************************************************************** Utility function called by unlocking requests. ****************************************************************************/ - -BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode) +BOOL do_unlock(int fnum,connection_struct *conn, + uint32 count,uint32 offset,int *eclass,uint32 *ecode) { BOOL ok = False; files_struct *fsp = &Files[fnum]; - if (!lp_locking(SNUM(cnum))) + if (!lp_locking(SNUM(conn))) return(True); - if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) + if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->conn == conn)) ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); if (!ok) { @@ -481,29 +472,29 @@ BOOL locking_end(void) /******************************************************************* Lock a hash bucket entry. ******************************************************************/ - -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) +BOOL lock_share_entry(connection_struct *conn, + uint32 dev, uint32 inode, int *ptok) { - return share_ops->lock_entry(cnum, dev, inode, ptok); + return share_ops->lock_entry(conn, dev, inode, ptok); } /******************************************************************* Unlock a hash bucket entry. ******************************************************************/ - -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token) +BOOL unlock_share_entry(connection_struct *conn, + uint32 dev, uint32 inode, int token) { - return share_ops->unlock_entry(cnum, dev, inode, token); + return share_ops->unlock_entry(conn, dev, inode, token); } /******************************************************************* Get all share mode entries for a dev/inode pair. ********************************************************************/ - -int get_share_modes(int cnum, int token, uint32 dev, uint32 inode, +int get_share_modes(connection_struct *conn, + int token, uint32 dev, uint32 inode, share_mode_entry **shares) { - return share_ops->get_entries(cnum, token, dev, inode, shares); + return share_ops->get_entries(conn, token, dev, inode, shares); } /******************************************************************* diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 43a927e14c..84310d3a33 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -37,7 +37,6 @@ #ifdef FAST_SHARE_MODES extern int DEBUGLEVEL; -extern connection_struct Connections[]; extern files_struct Files[]; static struct shmem_ops *shmops; @@ -79,15 +78,17 @@ static BOOL shm_stop_share_mode_mgmt(void) /******************************************************************* 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) +static BOOL shm_lock_share_entry(connection_struct *conn, + uint32 dev, uint32 inode, int *ptok) { - return shmops->lock_hash_entry(HASH_ENTRY(dev, inode)); + return shmops->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) +static BOOL shm_unlock_share_entry(connection_struct *conn, + uint32 dev, uint32 inode, int token) { return shmops->unlock_hash_entry(HASH_ENTRY(dev, inode)); } @@ -95,7 +96,8 @@ static BOOL shm_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token /******************************************************************* 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, +static int shm_get_share_modes(connection_struct *conn, + int token, uint32 dev, uint32 inode, share_mode_entry **old_shares) { int *mode_array; @@ -426,7 +428,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) /* We must create a share_mode_record */ share_mode_record *new_mode_p = NULL; int new_offset = shmops->shm_alloc(sizeof(share_mode_record) + - strlen(fs_p->name) + 1); + strlen(fs_p->fsp_name) + 1); if(new_offset == 0) { DEBUG(0,("ERROR:set_share_mode shmops->shm_alloc fail!\n")); return False; @@ -437,7 +439,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) new_mode_p->st_ino = inode; new_mode_p->num_share_mode_entries = 0; new_mode_p->share_mode_entries = 0; - pstrcpy(new_mode_p->file_name, fs_p->name); + pstrcpy(new_mode_p->file_name, fs_p->fsp_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]; @@ -446,7 +448,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) file_scanner_p = new_mode_p; DEBUG(3,("set_share_mode: Created share record for %s (dev %d inode %d)\n", - fs_p->name, dev, inode)); + fs_p->fsp_name, dev, inode)); } /* Now create the share mode entry */ @@ -485,7 +487,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) file_scanner_p->num_share_mode_entries += 1; DEBUG(3,("set_share_mode: Created share entry for %s with mode 0x%X pid=%d\n", - fs_p->name, fs_p->share_mode, new_entry_p->e.pid)); + fs_p->fsp_name, fs_p->share_mode, new_entry_p->e.pid)); return(True); } diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 1f8f962ac9..9135ae29d2 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -37,7 +37,6 @@ #ifndef FAST_SHARE_MODES extern int DEBUGLEVEL; -extern connection_struct Connections[]; extern files_struct Files[]; /* @@ -82,23 +81,24 @@ static BOOL slow_stop_share_mode_mgmt(void) /******************************************************************* name a share file ******************************************************************/ -static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) +static BOOL share_name(connection_struct *conn, + uint32 dev, uint32 inode, char *name) { - int len; - pstrcpy(name,lp_lockdir()); - trim_string(name,"","/"); - if (!*name) return(False); - len = strlen(name); - name += len; - - slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%u",dev,inode); - return(True); + int len; + pstrcpy(name,lp_lockdir()); + trim_string(name,"","/"); + if (!*name) return(False); + len = strlen(name); + name += len; + + slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%u",dev,inode); + return(True); } /******************************************************************* Force a share file to be deleted. ********************************************************************/ -static int delete_share_file( int cnum, char *fname ) +static int delete_share_file(connection_struct *conn, char *fname ) { if (read_only) return -1; @@ -124,7 +124,8 @@ static int delete_share_file( int cnum, char *fname ) /******************************************************************* lock a share mode file. ******************************************************************/ -static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) +static BOOL slow_lock_share_entry(connection_struct *conn, + uint32 dev, uint32 inode, int *ptok) { pstring fname; int fd; @@ -132,7 +133,7 @@ static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) *ptok = (int)-1; - if(!share_name(cnum, dev, inode, fname)) + if(!share_name(conn, dev, inode, fname)) return False; if (read_only) return True; @@ -216,7 +217,8 @@ static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) /******************************************************************* unlock a share mode file. ******************************************************************/ -static BOOL slow_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token) +static BOOL slow_unlock_share_entry(connection_struct *conn, + uint32 dev, uint32 inode, int token) { int fd = (int)token; int ret = True; @@ -228,7 +230,7 @@ static BOOL slow_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int toke /* Fix for zero length share files from Gerald Werner */ - share_name(cnum, dev, inode, fname); + share_name(conn, dev, inode, fname); /* get the share mode file size */ if(fstat((int)token, &sb) != 0) @@ -246,7 +248,7 @@ static BOOL slow_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int toke /* remove the share file if zero length */ if(sb.st_size == 0) - delete_share_file(cnum, fname); + delete_share_file(conn, fname); /* token is the fd of the open share mode file. */ /* Unlock the first byte. */ @@ -264,7 +266,7 @@ static BOOL slow_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int toke /******************************************************************* Read a share file into a buffer. ********************************************************************/ -static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file) +static int read_share_file(connection_struct *conn, int fd, char *fname, char **out, BOOL *p_new_file) { struct stat sb; char *buf; @@ -317,7 +319,7 @@ locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); if(buf) free(buf); - delete_share_file(cnum, fname); + delete_share_file(conn, fname); return -1; } @@ -335,7 +337,7 @@ locking version (was %d, should be %d).\n",fname, deleting it.\n", fname)); if(buf) free(buf); - delete_share_file(cnum, fname); + delete_share_file(conn, fname); return -1; } @@ -346,7 +348,7 @@ deleting it.\n", fname)); /******************************************************************* get all share mode entries in a share file for a dev/inode pair. ********************************************************************/ -static int slow_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, +static int slow_get_share_modes(connection_struct *conn, int token, uint32 dev, uint32 inode, share_mode_entry **old_shares) { int fd = (int)token; @@ -377,9 +379,9 @@ static int slow_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, 16 - oplock port (if oplocks in use) - 2 bytes. */ - share_name(cnum, dev, inode, fname); + share_name(conn, dev, inode, fname); - if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0) + if(read_share_file( conn, fd, fname, &buf, &new_file) != 0) { DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n", fname)); @@ -419,7 +421,7 @@ for share file %d\n", num_entries, fname)); fname)); if(buf) free(buf); - delete_share_file(cnum, fname); + delete_share_file(conn, fname); return 0; } @@ -460,7 +462,7 @@ it left a share mode entry with mode 0x%X in share file %s\n", *old_shares = 0; if(buf) free(buf); - delete_share_file(cnum, fname); + delete_share_file(conn, fname); return 0; } @@ -546,10 +548,10 @@ static void slow_del_share_mode(int token, int fnum) BOOL deleted = False; BOOL new_file; - share_name(fs_p->cnum, fs_p->fd_ptr->dev, + share_name(fs_p->conn, fs_p->fd_ptr->dev, fs_p->fd_ptr->inode, fname); - if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) + if(read_share_file( fs_p->conn, fd, fname, &buf, &new_file) != 0) { DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", fname)); @@ -560,7 +562,7 @@ static void slow_del_share_mode(int token, int fnum) { DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", fname)); - delete_share_file(fs_p->cnum, fname); + delete_share_file(fs_p->conn, fname); return; } @@ -584,7 +586,7 @@ for share file %d\n", num_entries, fname)); fname)); if(buf) free(buf); - delete_share_file(fs_p->cnum, fname); + delete_share_file(fs_p->conn, fname); return; } @@ -635,7 +637,7 @@ for share file %d\n", num_entries, fname)); fname)); if(buf) free(buf); - delete_share_file(fs_p->cnum,fname); + delete_share_file(fs_p->conn,fname); return; } @@ -685,7 +687,7 @@ static BOOL slow_set_share_mode(int token,int fnum, uint16 port, uint16 op_type) int header_size; char *p; - share_name(fs_p->cnum, fs_p->fd_ptr->dev, + share_name(fs_p->conn, fs_p->fd_ptr->dev, fs_p->fd_ptr->inode, fname); if(fstat(fd, &sb) != 0) @@ -733,7 +735,7 @@ locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); if(buf) free(buf); - delete_share_file(fs_p->cnum, fname); + delete_share_file(fs_p->conn, fname); return False; } @@ -746,7 +748,7 @@ locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), deleting it.\n", fname)); if(buf) free(buf); - delete_share_file(fs_p->cnum, fname); + delete_share_file(fs_p->conn, fname); return False; } @@ -794,7 +796,7 @@ deleting it.\n", fname)); { DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ deleting it (%s).\n",fname, strerror(errno))); - delete_share_file(fs_p->cnum, fname); + delete_share_file(fs_p->conn, fname); if(buf) free(buf); return False; @@ -838,10 +840,10 @@ static BOOL slow_remove_share_oplock(int fnum, int token) BOOL found = False; BOOL new_file; - share_name(fs_p->cnum, fs_p->fd_ptr->dev, + share_name(fs_p->conn, fs_p->fd_ptr->dev, fs_p->fd_ptr->inode, fname); - if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) + if(read_share_file( fs_p->conn, fd, fname, &buf, &new_file) != 0) { DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n", fname)); @@ -852,7 +854,7 @@ static BOOL slow_remove_share_oplock(int fnum, int token) { DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \ deleting it.\n", fname)); - delete_share_file(fs_p->cnum, fname); + delete_share_file(fs_p->conn, fname); return False; } @@ -876,7 +878,7 @@ for share file %d\n", num_entries, fname)); fname)); if(buf) free(buf); - delete_share_file(fs_p->cnum, fname); + delete_share_file(fs_p->conn, fname); return False; } diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 48f78d2a5b..dd97d5c76c 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -128,7 +128,7 @@ static BOOL smb_shm_global_unlock(void) if(smb_shm_times_locked == 0) { - DEBUG(0,("ERROR smb_shm_global_unlock : shmem not locked\n",smb_shm_fd)); + DEBUG(0,("ERROR smb_shm_global_unlock : shmem not locked\n")); return False; } -- cgit From e13aeea928dd89373cfaf3916c96f853c1227884 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 15 Aug 1998 01:19:26 +0000 Subject: configure: Changes for extra headers. configure.in: Source for header changes. client/clitar.c: Fixed isXXX macros & debugs for gcc pedantic compile. include/config.h.in: Added MEMSET, BZERO, MEMORY, RPCSVC_YPCLNT, STRINGS headers. include/includes.h: Headers for the above. include/smb.h: Made SIGNAL_CAST POSIX by default void (*)(int). lib/access.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/charset.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/debug.c: Fixed signal functs. lib/kanji.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/smbrun.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/util.c: Fixed isXXX macros & debugs for gcc pedantic compile. libsmb/namequery.c: Fixed isXXX macros & debugs for gcc pedantic compile. locking/shmem.c: Fixed isXXX macros & debugs for gcc pedantic compile. locking/shmem_sysv.c: Fixed error messages in sysV stuff. nmbd/asyncdns.c: Fixed signal functs. nmbd/nmbd.c: Fixed isXXX macros & debugs for gcc pedantic compile. passdb/passdb.c: Fixed isXXX macros & debugs for gcc pedantic compile. passdb/smbpassfile.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/chgpasswd.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/ipc.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/nttrans.c: Fixed fsp code path. smbd/password.c: fixed HAVE_YP_GET_DEFAULT_DOMAIN problem. smbd/printing.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/reply.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/server.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/trans2.c: Fixed core dump bug. smbd/uid.c: Fixed isXXX macros & debugs for gcc pedantic compile. Jeremy. (This used to be commit 1b9cbcd02e575dc0a95fa589f720df30a4acc46b) --- source3/locking/shmem.c | 15 +++++++++------ source3/locking/shmem_sysv.c | 12 ++++++++++-- 2 files changed, 19 insertions(+), 8 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index dd97d5c76c..be8e22108a 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -340,7 +340,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth { /* erase old pid */ DEBUG(5,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %d)\n", - other_pid, seek_back)); + (int)other_pid, seek_back)); other_pid = (pid_t)0; erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)); @@ -362,7 +362,8 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth if(free_slot < 0) free_slot = lseek(smb_shm_processes_fd, 0, SEEK_END); - DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %d\n",pid,free_slot)); + DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %d\n", + (int)pid,free_slot)); lseek(smb_shm_processes_fd, free_slot, SEEK_SET); if(write(smb_shm_processes_fd, &pid, sizeof(pid)) < 0) { @@ -395,12 +396,12 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) { - DEBUG(5,("smb_shm_unregister_process : read record for pid %d\n",other_pid)); + DEBUG(5,("smb_shm_unregister_process : read record for pid %d\n",(int)other_pid)); if(other_pid == pid) { /* erase pid */ DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %d)\n", - other_pid, seek_back)); + (int)other_pid, seek_back)); other_pid = (pid_t)0; erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) @@ -423,7 +424,8 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) if(!found) { - DEBUG(0,("ERROR smb_shm_unregister_process : couldn't find pid %d in file %s\n",pid,processreg_file)); + DEBUG(0,("ERROR smb_shm_unregister_process : couldn't find pid %d in file %s\n", + (int)pid,processreg_file)); close(smb_shm_processes_fd); return False; } @@ -540,7 +542,8 @@ static BOOL smb_shm_close( void ) } smb_shm_global_lock(); - DEBUG(5,("calling smb_shm_unregister_process(%s, %d)\n", smb_shm_processreg_name, getpid())); + DEBUG(5,("calling smb_shm_unregister_process(%s, %d)\n", + smb_shm_processreg_name, (int)getpid())); smb_shm_unregister_process(smb_shm_processreg_name, getpid()); smb_shm_global_unlock(); diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index b8b9c2cb45..192ed32344 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -564,8 +564,9 @@ struct shmem_ops *sysv_shm_open(int ronly) } if (sem_id == -1) { - DEBUG(0,("Can't create or use semaphore %s\n", + DEBUG(0,("Can't create or use semaphore [1]. Error was %s\n", strerror(errno))); + return NULL; } if (sem_id != -1) { @@ -574,6 +575,7 @@ struct shmem_ops *sysv_shm_open(int ronly) if (semctl(sem_id, i, SETVAL, su) != 0) { DEBUG(1,("Failed to init semaphore %d. Error was %s\n", i, strerror(errno))); + return NULL; } } } @@ -582,7 +584,7 @@ struct shmem_ops *sysv_shm_open(int ronly) sem_id = semget(SEMAPHORE_KEY, 0, 0); } if (sem_id == -1) { - DEBUG(0,("Can't create or use semaphore.Error was %s\n", + DEBUG(0,("Can't create or use semaphore [2]. Error was %s\n", strerror(errno))); return NULL; } @@ -609,6 +611,7 @@ struct shmem_ops *sysv_shm_open(int ronly) if (semctl(sem_id, 0, SETVAL, su) != 0) { DEBUG(0,("ERROR: Failed to clear global lock. Error was %s\n", strerror(errno))); + return NULL; } } @@ -616,6 +619,7 @@ struct shmem_ops *sysv_shm_open(int ronly) if (semctl(sem_id, 0, IPC_SET, su) != 0) { DEBUG(0,("ERROR shmctl : can't IPC_SET. Error was %s\n", strerror(errno))); + return NULL; } } @@ -632,6 +636,8 @@ struct shmem_ops *sysv_shm_open(int ronly) if (semctl(sem_id, i, SETVAL, su) != 0) { DEBUG(0,("ERROR: Failed to clear IPC lock %d. Error was %s\n", i, strerror(errno))); + global_unlock(); + return NULL; } } } @@ -679,6 +685,8 @@ struct shmem_ops *sysv_shm_open(int ronly) mapping processes */ if (shmctl(shm_id, IPC_STAT, &shm_ds) != 0) { DEBUG(0,("ERROR shmctl : can't IPC_STAT. Error was %s\n", strerror(errno))); + global_unlock(); + return NULL; } if (!read_only) { -- cgit From 127655cc888ac40332d4e8e5b94aab03f5120aae Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 15 Aug 1998 07:27:34 +0000 Subject: this checkin gets rid of the global Files[] array and makes it local in files.c it should now be faily easy to expand the default MAX_OPEN_FILES to many thousands. (This used to be commit b088c804f98908eb02f05ab2f2e8a61691a0a582) --- source3/locking/locking.c | 56 ++++++++++++++++------------------ source3/locking/locking_shm.c | 38 +++++++++++------------ source3/locking/locking_slow.c | 68 ++++++++++++++++++++---------------------- 3 files changed, 75 insertions(+), 87 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index bb852b07d6..50c4af2265 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -33,7 +33,6 @@ #include "includes.h" extern int DEBUGLEVEL; -extern files_struct Files[]; extern int Client; static struct share_ops *share_ops; @@ -62,7 +61,7 @@ static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_qu BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num) { blocking_lock_record *blr; - int fnum = GETFNUM(inbuf,smb_vwv2); + files_struct *fsp = GETFSP(inbuf,smb_vwv2); /* * Now queue an entry on the blocking lock queue. We setup @@ -88,7 +87,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int ubi_slAddTail(&blocking_lock_queue, blr); DEBUG(3,("push_blocking_lock_request: lock request blocked with expiry time %d \ -for fnum = %d, name = %s\n", blr->expire_time, fnum, Files[fnum].name )); +for fnum = %d, name = %s\n", blr->expire_time, fsp->fnum, fsp->name )); return True; } @@ -96,16 +95,15 @@ for fnum = %d, name = %s\n", blr->expire_time, fnum, Files[fnum].name )); /**************************************************************************** Return a blocking lock success SMB. *****************************************************************************/ - static void blocking_lock_reply_success(blocking_lock_record *blr) { extern int chain_size; - extern int chain_fnum; + extern files_struct *chain_fsp; extern char *OutBuffer; char *outbuf = OutBuffer; int bufsize = BUFFER_SIZE; char *inbuf = blr->inbuf; - int fnum = GETFNUM(inbuf,smb_vwv2); + files_struct *fsp = GETFSP(inbuf,smb_vwv2); int outsize = 0; construct_reply_common(inbuf, outbuf); @@ -119,7 +117,7 @@ static void blocking_lock_reply_success(blocking_lock_record *blr) * that here and must set up the chain info manually. */ - chain_fnum = fnum; + chain_fsp = fsp; chain_size = 0; outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); @@ -142,7 +140,7 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int char *outbuf = OutBuffer; int bufsize = BUFFER_SIZE; char *inbuf = blr->inbuf; - int fnum = GETFNUM(inbuf,smb_vwv2); + files_struct *fsp = GETFSP(inbuf,smb_vwv2); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; @@ -160,7 +158,7 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int for(i = blr->lock_num; i >= 0; i--) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - do_unlock(fnum,conn,count,offset,&dummy1,&dummy2); + do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } construct_reply_common(inbuf, outbuf); @@ -177,7 +175,7 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) { char *inbuf = blr->inbuf; unsigned char locktype = CVAL(inbuf,smb_vwv3); - int fnum = GETFNUM(inbuf,smb_vwv2); + files_struct *fsp = GETFSP(inbuf,smb_vwv2); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; @@ -196,7 +194,7 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) for(; blr->lock_num < num_locks; blr->lock_num++) { count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num)); offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num)); - if(!do_lock(fnum,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), + if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) break; } @@ -208,7 +206,7 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) */ DEBUG(3,("blocking_lock_record_process fnum=%d type=%d num_locks=%d\n", - fnum, (unsigned int)locktype, num_locks) ); + fsp->fnum, (unsigned int)locktype, num_locks) ); blocking_lock_reply_success(blr); return True; @@ -230,7 +228,7 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) */ DEBUG(10,("blocking_lock_record_process: only got %d locks of %d needed for fnum = %d. \ -Waiting..\n", blr->lock_num, num_locks, fnum )); +Waiting..\n", blr->lock_num, num_locks, fsp->fnum)); return False; } @@ -252,13 +250,12 @@ void process_blocking_lock_queue(time_t t) */ while(blr != NULL) { - int fnum = GETFNUM(blr->inbuf,smb_vwv2); - files_struct *fsp = &Files[fnum]; + files_struct *fsp = GETFSP(blr->inbuf,smb_vwv2); uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(blr->inbuf,smb_uid); DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", - fnum, fsp->name )); + fsp->fnum, fsp->name )); if((blr->expire_time != -1) && (blr->expire_time > t)) { /* @@ -266,7 +263,7 @@ void process_blocking_lock_queue(time_t t) * obtained locks and return lock error. */ DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", - fnum, fsp->name )); + fsp->fnum, fsp->name )); blocking_lock_reply_error(blr,ERRSRV,ERRaccess); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); @@ -356,11 +353,10 @@ static int map_lock_type( files_struct *fsp, int lock_type) /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ -BOOL is_locked(int fnum,connection_struct *conn, +BOOL is_locked(files_struct *fsp,connection_struct *conn, uint32 count,uint32 offset, int lock_type) { int snum = SNUM(conn); - files_struct *fsp = &Files[fnum]; if (count == 0) return(False); @@ -381,12 +377,11 @@ BOOL is_locked(int fnum,connection_struct *conn, /**************************************************************************** Utility function called by locking requests. ****************************************************************************/ -BOOL do_lock(int fnum,connection_struct *conn, +BOOL do_lock(files_struct *fsp,connection_struct *conn, uint32 count,uint32 offset,int lock_type, int *eclass,uint32 *ecode) { BOOL ok = False; - files_struct *fsp = &Files[fnum]; if (!lp_locking(SNUM(conn))) return(True); @@ -397,7 +392,7 @@ BOOL do_lock(int fnum,connection_struct *conn, return False; } - if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->conn == conn)) + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count, map_lock_type(fsp,lock_type)); @@ -413,16 +408,15 @@ BOOL do_lock(int fnum,connection_struct *conn, /**************************************************************************** Utility function called by unlocking requests. ****************************************************************************/ -BOOL do_unlock(int fnum,connection_struct *conn, +BOOL do_unlock(files_struct *fsp,connection_struct *conn, uint32 count,uint32 offset,int *eclass,uint32 *ecode) { BOOL ok = False; - files_struct *fsp = &Files[fnum]; if (!lp_locking(SNUM(conn))) return(True); - if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->conn == conn)) + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); if (!ok) { @@ -501,26 +495,26 @@ int get_share_modes(connection_struct *conn, Del the share mode of a file. ********************************************************************/ -void del_share_mode(int token, int fnum) +void del_share_mode(int token, files_struct *fsp) { - share_ops->del_entry(token, fnum); + share_ops->del_entry(token, fsp); } /******************************************************************* Set the share mode of a file. Return False on fail, True on success. ********************************************************************/ -BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type) +BOOL set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type) { - return share_ops->set_entry(token, fnum, port, op_type); + return share_ops->set_entry(token, fsp, port, op_type); } /******************************************************************* Remove an oplock port and mode entry from a share mode. ********************************************************************/ -BOOL remove_share_oplock(int fnum, int token) +BOOL remove_share_oplock(files_struct *fsp, int token) { - return share_ops->remove_oplock(fnum, token); + return share_ops->remove_oplock(fsp, token); } /******************************************************************* diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 84310d3a33..cded5e628d 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -37,7 +37,6 @@ #ifdef FAST_SHARE_MODES extern int DEBUGLEVEL; -extern files_struct Files[]; static struct shmem_ops *shmops; @@ -258,7 +257,7 @@ static int shm_get_share_modes(connection_struct *conn, /******************************************************************* del the share mode of a file. ********************************************************************/ -static void shm_del_share_mode(int token, int fnum) +static void shm_del_share_mode(int token, files_struct *fsp) { uint32 dev, inode; int *mode_array; @@ -270,8 +269,8 @@ static void shm_del_share_mode(int token, int fnum) BOOL found = False; int pid = getpid(); - dev = Files[fnum].fd_ptr->dev; - inode = Files[fnum].fd_ptr->inode; + dev = fsp->fd_ptr->dev; + inode = fsp->fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); @@ -329,7 +328,7 @@ static void shm_del_share_mode(int token, int fnum) { if( (pid == entry_scanner_p->e.pid) && (memcmp(&entry_scanner_p->e.time, - &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) + &fsp->open_time,sizeof(struct timeval)) == 0) ) { found = True; break; @@ -386,9 +385,8 @@ static void shm_del_share_mode(int token, int fnum) /******************************************************************* 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) +static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type) { - files_struct *fs_p = &Files[fnum]; int32 dev, inode; int *mode_array; unsigned int hash_entry; @@ -398,8 +396,8 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) int new_entry_offset; BOOL found = False; - dev = fs_p->fd_ptr->dev; - inode = fs_p->fd_ptr->inode; + dev = fsp->fd_ptr->dev; + inode = fsp->fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); @@ -428,7 +426,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) /* We must create a share_mode_record */ share_mode_record *new_mode_p = NULL; int new_offset = shmops->shm_alloc(sizeof(share_mode_record) + - strlen(fs_p->fsp_name) + 1); + strlen(fsp->fsp_name) + 1); if(new_offset == 0) { DEBUG(0,("ERROR:set_share_mode shmops->shm_alloc fail!\n")); return False; @@ -439,7 +437,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) new_mode_p->st_ino = inode; new_mode_p->num_share_mode_entries = 0; new_mode_p->share_mode_entries = 0; - pstrcpy(new_mode_p->file_name, fs_p->fsp_name); + pstrcpy(new_mode_p->file_name, fsp->fsp_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]; @@ -448,7 +446,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) file_scanner_p = new_mode_p; DEBUG(3,("set_share_mode: Created share record for %s (dev %d inode %d)\n", - fs_p->fsp_name, dev, inode)); + fsp->fsp_name, dev, inode)); } /* Now create the share mode entry */ @@ -466,10 +464,10 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) new_entry_p = shmops->offset2addr(new_entry_offset); new_entry_p->e.pid = getpid(); - new_entry_p->e.share_mode = fs_p->share_mode; + new_entry_p->e.share_mode = fsp->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)); + memcpy( (char *)&new_entry_p->e.time, (char *)&fsp->open_time, sizeof(struct timeval)); /* Chain onto the share_mode_record */ new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries; @@ -487,7 +485,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) file_scanner_p->num_share_mode_entries += 1; DEBUG(3,("set_share_mode: Created share entry for %s with mode 0x%X pid=%d\n", - fs_p->fsp_name, fs_p->share_mode, new_entry_p->e.pid)); + fsp->fsp_name, fsp->share_mode, new_entry_p->e.pid)); return(True); } @@ -495,7 +493,7 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) /******************************************************************* Remove an oplock port and mode entry from a share mode. ********************************************************************/ -static BOOL shm_remove_share_oplock(int fnum, int token) +static BOOL shm_remove_share_oplock(files_struct *fsp, int token) { uint32 dev, inode; int *mode_array; @@ -507,8 +505,8 @@ static BOOL shm_remove_share_oplock(int fnum, int token) BOOL found = False; int pid = getpid(); - dev = Files[fnum].fd_ptr->dev; - inode = Files[fnum].fd_ptr->inode; + dev = fsp->fd_ptr->dev; + inode = fsp->fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); @@ -565,9 +563,9 @@ static BOOL shm_remove_share_oplock(int fnum, int token) while(entry_scanner_p) { if( (pid == entry_scanner_p->e.pid) && - (entry_scanner_p->e.share_mode == Files[fnum].share_mode) && + (entry_scanner_p->e.share_mode == fsp->share_mode) && (memcmp(&entry_scanner_p->e.time, - &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) + &fsp->open_time,sizeof(struct timeval)) == 0) ) { /* Delete the oplock info. */ entry_scanner_p->e.op_port = 0; diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 9135ae29d2..8b56e7599b 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -37,7 +37,6 @@ #ifndef FAST_SHARE_MODES extern int DEBUGLEVEL; -extern files_struct Files[]; /* * Locking file header lengths & offsets. @@ -534,7 +533,7 @@ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); /******************************************************************* del a share mode from a share mode file. ********************************************************************/ -static void slow_del_share_mode(int token, int fnum) +static void slow_del_share_mode(int token, files_struct *fsp) { pstring fname; int fd = (int)token; @@ -543,15 +542,14 @@ static void slow_del_share_mode(int token, int fnum) int num_entries; int newsize; int i; - files_struct *fs_p = &Files[fnum]; int pid; BOOL deleted = False; BOOL new_file; - share_name(fs_p->conn, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); + share_name(fsp->conn, fsp->fd_ptr->dev, + fsp->fd_ptr->inode, fname); - if(read_share_file( fs_p->conn, fd, fname, &buf, &new_file) != 0) + if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0) { DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", fname)); @@ -562,7 +560,7 @@ static void slow_del_share_mode(int token, int fnum) { DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", fname)); - delete_share_file(fs_p->conn, fname); + delete_share_file(fsp->conn, fname); return; } @@ -586,7 +584,7 @@ for share file %d\n", num_entries, fname)); fname)); if(buf) free(buf); - delete_share_file(fs_p->conn, fname); + delete_share_file(fsp->conn, fname); return; } @@ -602,9 +600,9 @@ for share file %d\n", num_entries, fname)); { char *p = base + (i*SMF_ENTRY_LENGTH); - if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || + if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || + (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) || + (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || (IVAL(p,SME_PID_OFFSET) != pid)) continue; @@ -637,7 +635,7 @@ for share file %d\n", num_entries, fname)); fname)); if(buf) free(buf); - delete_share_file(fs_p->conn,fname); + delete_share_file(fsp->conn,fname); return; } @@ -675,9 +673,8 @@ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); /******************************************************************* set the share mode of a file ********************************************************************/ -static BOOL slow_set_share_mode(int token,int fnum, uint16 port, uint16 op_type) +static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 op_type) { - files_struct *fs_p = &Files[fnum]; pstring fname; int fd = (int)token; int pid = (int)getpid(); @@ -687,8 +684,8 @@ static BOOL slow_set_share_mode(int token,int fnum, uint16 port, uint16 op_type) int header_size; char *p; - share_name(fs_p->conn, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); + share_name(fsp->conn, fsp->fd_ptr->dev, + fsp->fd_ptr->inode, fname); if(fstat(fd, &sb) != 0) { @@ -735,7 +732,7 @@ locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); if(buf) free(buf); - delete_share_file(fs_p->conn, fname); + delete_share_file(fsp->conn, fname); return False; } @@ -748,7 +745,7 @@ locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), deleting it.\n", fname)); if(buf) free(buf); - delete_share_file(fs_p->conn, fname); + delete_share_file(fsp->conn, fname); return False; } @@ -757,23 +754,23 @@ deleting it.\n", fname)); { /* New file - just use a single_entry. */ if((buf = (char *)malloc(SMF_HEADER_LENGTH + - strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL) + strlen(fsp->name) + 1 + SMF_ENTRY_LENGTH)) == NULL) { DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); return False; } SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); - SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1); - pstrcpy(buf + SMF_HEADER_LENGTH, fs_p->name); + SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fsp->name) + 1); + pstrcpy(buf + SMF_HEADER_LENGTH, fsp->name); } num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH); - SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec); - SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode); + SIVAL(p,SME_SEC_OFFSET,fsp->open_time.tv_sec); + SIVAL(p,SME_USEC_OFFSET,fsp->open_time.tv_usec); + SIVAL(p,SME_SHAREMODE_OFFSET,fsp->share_mode); SIVAL(p,SME_PID_OFFSET,pid); SSVAL(p,SME_PORT_OFFSET,port); SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); @@ -796,7 +793,7 @@ deleting it.\n", fname)); { DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ deleting it (%s).\n",fname, strerror(errno))); - delete_share_file(fs_p->conn, fname); + delete_share_file(fsp->conn, fname); if(buf) free(buf); return False; @@ -818,7 +815,7 @@ mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entr free(buf); DEBUG(3,("set_share_mode: Created share file %s with \ -mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid)); +mode 0x%X pid=%d\n",fname,fsp->share_mode,pid)); return True; } @@ -826,7 +823,7 @@ mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid)); /******************************************************************* Remove an oplock port and mode entry from a share mode. ********************************************************************/ -static BOOL slow_remove_share_oplock(int fnum, int token) +static BOOL slow_remove_share_oplock(files_struct *fsp, int token) { pstring fname; int fd = (int)token; @@ -835,15 +832,14 @@ static BOOL slow_remove_share_oplock(int fnum, int token) int num_entries; int fsize; int i; - files_struct *fs_p = &Files[fnum]; int pid; BOOL found = False; BOOL new_file; - share_name(fs_p->conn, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); + share_name(fsp->conn, fsp->fd_ptr->dev, + fsp->fd_ptr->inode, fname); - if(read_share_file( fs_p->conn, fd, fname, &buf, &new_file) != 0) + if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0) { DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n", fname)); @@ -854,7 +850,7 @@ static BOOL slow_remove_share_oplock(int fnum, int token) { DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \ deleting it.\n", fname)); - delete_share_file(fs_p->conn, fname); + delete_share_file(fsp->conn, fname); return False; } @@ -878,7 +874,7 @@ for share file %d\n", num_entries, fname)); fname)); if(buf) free(buf); - delete_share_file(fs_p->conn, fname); + delete_share_file(fsp->conn, fname); return False; } @@ -894,9 +890,9 @@ for share file %d\n", num_entries, fname)); { char *p = base + (i*SMF_ENTRY_LENGTH); - if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || + if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || + (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) || + (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || (IVAL(p,SME_PID_OFFSET) != pid)) continue; -- cgit From a7acf10566af549eb71e7a421397c8073d55e0f6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Aug 1998 03:04:06 +0000 Subject: server.c: fixed a bug in close_file() with the new files.c handling code bitmap.c: added bitmap hanlding code in preparation for increasing the default max open files to several thousand (This used to be commit f573a65b67e7a57586fec57845598e49b157ee0a) --- source3/locking/locking.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 50c4af2265..cdaeea6d7e 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -494,7 +494,6 @@ int get_share_modes(connection_struct *conn, /******************************************************************* Del the share mode of a file. ********************************************************************/ - void del_share_mode(int token, files_struct *fsp) { share_ops->del_entry(token, fsp); @@ -503,7 +502,6 @@ void del_share_mode(int token, files_struct *fsp) /******************************************************************* Set the share mode of a file. Return False on fail, True on success. ********************************************************************/ - BOOL set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type) { return share_ops->set_entry(token, fsp, port, op_type); -- cgit From 6daa579e0f76a9318bcac9442d7209580bb58bbc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Aug 1998 05:23:54 +0000 Subject: fixed some bugs in the locking_slow code caused by the recent changes. also fixed a couple of %s/%d bugs in locking slow that have been there for a while but are now revealed by the gcc printf argument testing. (This used to be commit 16228c185a7844a243db538aa1e5729e62a8bc4a) --- source3/locking/locking_slow.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 8b56e7599b..2017f09289 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -290,7 +290,8 @@ static int read_share_file(connection_struct *conn, int fd, char *fname, char ** /* Allocate space for the file */ if((buf = (char *)malloc(sb.st_size)) == NULL) { - DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size)); + DEBUG(0,("read_share_file: malloc for file size %d fail !\n", + (int)sb.st_size)); return -1; } @@ -399,7 +400,7 @@ static int slow_get_share_modes(connection_struct *conn, int token, uint32 dev, if(num_entries < 0) { DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); +for share file %s\n", num_entries, fname)); return 0; } @@ -573,7 +574,7 @@ static void slow_del_share_mode(int token, files_struct *fsp) if(num_entries < 0) { DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); +for share file %s\n", num_entries, fname)); return; } @@ -703,7 +704,7 @@ static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL) { DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", - sb.st_size + SMF_ENTRY_LENGTH)); + (int)(sb.st_size + SMF_ENTRY_LENGTH))); return False; } @@ -754,15 +755,15 @@ deleting it.\n", fname)); { /* New file - just use a single_entry. */ if((buf = (char *)malloc(SMF_HEADER_LENGTH + - strlen(fsp->name) + 1 + SMF_ENTRY_LENGTH)) == NULL) + strlen(fsp->fsp_name) + 1 + SMF_ENTRY_LENGTH)) == NULL) { DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); return False; } SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); - SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fsp->name) + 1); - pstrcpy(buf + SMF_HEADER_LENGTH, fsp->name); + SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fsp->fsp_name) + 1); + pstrcpy(buf + SMF_HEADER_LENGTH, fsp->fsp_name); } num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); @@ -863,7 +864,7 @@ deleting it.\n", fname)); if(num_entries < 0) { DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); +for share file %s\n", num_entries, fname)); return False; } -- cgit From 8978aae69699ccab76fdf95037948b1cc7e7c286 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 03:52:05 +0000 Subject: much cleaner chain pointer handling for both files and pipes. the chain pointer is now stored as a static and is set whenever a handle is created or extracted. This also makes the code less error prone. (This used to be commit 068a862982bea726e8d7b1b4065d510b9840a272) --- source3/locking/locking.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index cdaeea6d7e..8737a12e17 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -61,7 +61,7 @@ static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_qu BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num) { blocking_lock_record *blr; - files_struct *fsp = GETFSP(inbuf,smb_vwv2); + files_struct *fsp = file_fsp(inbuf,smb_vwv2); /* * Now queue an entry on the blocking lock queue. We setup @@ -98,12 +98,11 @@ for fnum = %d, name = %s\n", blr->expire_time, fsp->fnum, fsp->name )); static void blocking_lock_reply_success(blocking_lock_record *blr) { extern int chain_size; - extern files_struct *chain_fsp; extern char *OutBuffer; char *outbuf = OutBuffer; int bufsize = BUFFER_SIZE; char *inbuf = blr->inbuf; - files_struct *fsp = GETFSP(inbuf,smb_vwv2); + files_struct *fsp = file_fsp(inbuf,smb_vwv2); int outsize = 0; construct_reply_common(inbuf, outbuf); @@ -117,7 +116,7 @@ static void blocking_lock_reply_success(blocking_lock_record *blr) * that here and must set up the chain info manually. */ - chain_fsp = fsp; + file_set_chain(fsp); chain_size = 0; outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); @@ -140,7 +139,7 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int char *outbuf = OutBuffer; int bufsize = BUFFER_SIZE; char *inbuf = blr->inbuf; - files_struct *fsp = GETFSP(inbuf,smb_vwv2); + files_struct *fsp = file_fsp(inbuf,smb_vwv2); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; @@ -175,7 +174,7 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) { char *inbuf = blr->inbuf; unsigned char locktype = CVAL(inbuf,smb_vwv3); - files_struct *fsp = GETFSP(inbuf,smb_vwv2); + files_struct *fsp = file_fsp(inbuf,smb_vwv2); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; @@ -250,7 +249,7 @@ void process_blocking_lock_queue(time_t t) */ while(blr != NULL) { - files_struct *fsp = GETFSP(blr->inbuf,smb_vwv2); + files_struct *fsp = file_fsp(blr->inbuf,smb_vwv2); uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(blr->inbuf,smb_uid); -- cgit From 1e6837837ac402702ccadcbcfd853b8c673c783a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Aug 1998 23:39:59 +0000 Subject: smbd/nttrans.c: Fixed bug in split off pipe code. locking/locking.c: More blocking lock changes. Jeremy. (This used to be commit 2ca4fc95a4227645f1009a057d46b58508846a92) --- source3/locking/locking.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8737a12e17..873e382b46 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -116,7 +116,6 @@ static void blocking_lock_reply_success(blocking_lock_record *blr) * that here and must set up the chain info manually. */ - file_set_chain(fsp); chain_size = 0; outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); @@ -227,7 +226,7 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) */ DEBUG(10,("blocking_lock_record_process: only got %d locks of %d needed for fnum = %d. \ -Waiting..\n", blr->lock_num, num_locks, fsp->fnum)); +Waiting....\n", blr->lock_num, num_locks, fsp->fnum)); return False; } @@ -249,8 +248,17 @@ void process_blocking_lock_queue(time_t t) */ while(blr != NULL) { - files_struct *fsp = file_fsp(blr->inbuf,smb_vwv2); - uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : + files_struct *fsp = NULL; + uint16 vuid; + + /* + * Ensure we don't have any old chain_fnum values + * sitting around.... + */ + file_chain_reset(); + + fsp = file_fsp(blr->inbuf,smb_vwv2); + vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(blr->inbuf,smb_uid); DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", -- cgit From 12de4034c72ea5054d716bf848c2b16bef7a4d89 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Aug 1998 01:49:34 +0000 Subject: Makefile.in: Moved blocking lock code into smbd/blocking.c for link purposes. include/includes.h: Added nterr.h. locking/locking.c: Moved blocking lock code into smbd/blocking.c for link purposes. smbd/close.c: Added blocking lock removal to file close. smbd/filename.c: Tidied up unix_convert() so I could read it (:-) in preparation for the stat_cache code. smbd/nttrans.c: Added WRITE_ATTRIBUTES check. smbd/reply.c: Fixed multibyte char problem in wildcard mask. Jeremy. (This used to be commit 148eaba3dadb1d0bd3ac3ef53da3d9811636e89a) --- source3/locking/locking.c | 290 ---------------------------------------------- 1 file changed, 290 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 873e382b46..f5e27317b5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -33,299 +33,9 @@ #include "includes.h" extern int DEBUGLEVEL; -extern int Client; static struct share_ops *share_ops; -#if 0 /* JRATEST - blocking lock code - under development. */ - -/**************************************************************************** - This is the structure to queue to implement blocking locks. - notify. It consists of the requesting SMB and the expiry time. -*****************************************************************************/ - -typedef struct { - ubi_slNode msg_next; - time_t expire_time; - int lock_num; - char *inbuf; - int length; -} blocking_lock_record; - -static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0}; - -/**************************************************************************** - Function to push a blocking lockingX request onto the lock queue. -****************************************************************************/ - -BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num) -{ - blocking_lock_record *blr; - files_struct *fsp = file_fsp(inbuf,smb_vwv2); - - /* - * Now queue an entry on the blocking lock queue. We setup - * the expiration time here. - */ - - if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) { - DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); - return False; - } - - if((blr->inbuf = (char *)malloc(length)) == NULL) { - DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); - free((char *)blr); - return False; - } - - memcpy(blr->inbuf, inbuf, length); - blr->length = length; - blr->lock_num = lock_num; - blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; - - ubi_slAddTail(&blocking_lock_queue, blr); - - DEBUG(3,("push_blocking_lock_request: lock request blocked with expiry time %d \ -for fnum = %d, name = %s\n", blr->expire_time, fsp->fnum, fsp->name )); - - return True; -} - -/**************************************************************************** - Return a blocking lock success SMB. -*****************************************************************************/ -static void blocking_lock_reply_success(blocking_lock_record *blr) -{ - extern int chain_size; - extern char *OutBuffer; - char *outbuf = OutBuffer; - int bufsize = BUFFER_SIZE; - char *inbuf = blr->inbuf; - files_struct *fsp = file_fsp(inbuf,smb_vwv2); - int outsize = 0; - - construct_reply_common(inbuf, outbuf); - set_message(outbuf,2,0,True); - - /* - * As this message is a lockingX call we must handle - * any following chained message correctly. - * This is normally handled in construct_reply(), - * but as that calls switch_message, we can't use - * that here and must set up the chain info manually. - */ - - chain_size = 0; - - outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); - - outsize += chain_size; - - if(outsize > 4) - smb_setlen(outbuf,outsize - 4); - - send_smb(Client,outbuf); -} - -/**************************************************************************** - Return a lock fail error. Undo all the locks we have obtained first. -*****************************************************************************/ - -static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode) -{ - extern char *OutBuffer; - char *outbuf = OutBuffer; - int bufsize = BUFFER_SIZE; - char *inbuf = blr->inbuf; - files_struct *fsp = file_fsp(inbuf,smb_vwv2); - uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - uint16 num_locks = SVAL(inbuf,smb_vwv7); - uint32 count, offset; - int lock_num = blr->lock_num; - char *data; - int i; - - data = smb_buf(inbuf) + 10*num_ulocks; - - /* - * Data now points at the beginning of the list - * of smb_lkrng structs. - */ - - for(i = blr->lock_num; i >= 0; i--) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); - } - - construct_reply_common(inbuf, outbuf); - ERROR(eclass,ecode); - send_smb(Client,outbuf); -} - -/**************************************************************************** - Attempt to finish off getting all pending blocking locks. - Returns True if we want to be removed from the list. -*****************************************************************************/ - -static BOOL blocking_lock_record_process(blocking_lock_record *blr) -{ - char *inbuf = blr->inbuf; - unsigned char locktype = CVAL(inbuf,smb_vwv3); - files_struct *fsp = file_fsp(inbuf,smb_vwv2); - uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - uint16 num_locks = SVAL(inbuf,smb_vwv7); - uint32 count, offset; - int lock_num = blr->lock_num; - char *data; - int eclass=0; - uint32 ecode=0; - - data = smb_buf(inbuf) + 10*num_ulocks; - - /* - * Data now points at the beginning of the list - * of smb_lkrng structs. - */ - - for(; blr->lock_num < num_locks; blr->lock_num++) { - count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num)); - offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num)); - if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), - &eclass, &ecode)) - break; - } - - if(blr->lock_num == num_locks) { - - /* - * Success - we got all the locks. - */ - - DEBUG(3,("blocking_lock_record_process fnum=%d type=%d num_locks=%d\n", - fsp->fnum, (unsigned int)locktype, num_locks) ); - - blocking_lock_reply_success(blr); - return True; - - } else if((errno != EACCES) && (errno != EAGAIN)) { - - /* - * We have other than a "can't get lock" POSIX - * error. Free any locks we had and return an error. - * Return True so we get dequeued. - */ - - blocking_lock_reply_error(blr, eclass, ecode); - return True; - } - - /* - * Still can't get all the locks - keep waiting. - */ - - DEBUG(10,("blocking_lock_record_process: only got %d locks of %d needed for fnum = %d. \ -Waiting....\n", blr->lock_num, num_locks, fsp->fnum)); - - return False; -} - -/**************************************************************************** - Process the blocking lock queue. Note that this is only called as root. -*****************************************************************************/ - -void process_blocking_lock_queue(time_t t) -{ - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; - - if(blr == NULL) - return; - - /* - * Go through the queue and see if we can get any of the locks. - */ - - while(blr != NULL) { - files_struct *fsp = NULL; - uint16 vuid; - - /* - * Ensure we don't have any old chain_fnum values - * sitting around.... - */ - file_chain_reset(); - - fsp = file_fsp(blr->inbuf,smb_vwv2); - vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : - SVAL(blr->inbuf,smb_uid); - - DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", - fsp->fnum, fsp->name )); - - if((blr->expire_time != -1) && (blr->expire_time > t)) { - /* - * Lock expired - throw away all previously - * obtained locks and return lock error. - */ - DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", - fsp->fnum, fsp->name )); - - blocking_lock_reply_error(blr,ERRSRV,ERRaccess); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - if(!become_user(conn,vuid)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", - vuid )); - /* - * Remove the entry and return an error to the client. - */ - blocking_lock_reply_error(blr,ERRSRV,ERRaccess); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - if(!become_service(conn,True)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); - /* - * Remove the entry and return an error to the client. - */ - blocking_lock_reply_error(blr,ERRSRV,ERRaccess); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - /* - * Go through the remaining locks and try and obtain them. - * The call returns True if all locks were obtained successfully - * and False if we still need to wait. - */ - - if(blocking_lock_record_process(blr)) { - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - unbecome_user(); - - /* - * Move to the next in the list. - */ - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); - } -} -#endif /* JRATEST */ - /**************************************************************************** Utility function to map a lock type correctly depending on the real open mode of a file. -- cgit From dc76502cd8a950f6aff84ce4eedfd9d2b30d3dcc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 20 Aug 1998 19:28:37 +0000 Subject: Turning on blocking locking code. NB. Blocking lock requests that are not the head of an SMB request (ie. are part of a chain) will not be queued - this will be fixed when we move to the new chain code. In practice, this doesn't seem to cause much of a problem (in my admittedly limited testing) bug a debug level zero message will be placed in the log when this happens to help determine how real the problem is. smbd/locking.c: New debug messages. smbd/blocking.c: New blocking code - handles SMBlock, SMBlockread and SMBlockingX smbd/chgpasswd.c: Fix for master fd leak. smbd/files.c: Tidyup comment. smbd/nttrans.c: Added fnum to debug message. smbd/process.c: Made chain_reply() use construct_reply_common(). Added blocking lock queue processing into idle loop. smbd/reply.c: Added queue pushes for SMBlock, SMBlockread and SMBlockingX. Jeremy. (This used to be commit e1dd03ecda0bc6d7eaa31070c83774bb5679fd1b) --- source3/locking/locking.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f5e27317b5..4f2c9ab345 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -109,6 +109,9 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, return False; } + DEBUG(10,("do_lock: lock type %d start=%d len=%d requested for file %s\n", + lock_type, (int)offset, (int)count, fsp->fsp_name )); + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count, map_lock_type(fsp,lock_type)); @@ -133,6 +136,9 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, if (!lp_locking(SNUM(conn))) return(True); + DEBUG(10,("do_unlock: unlock start=%d len=%d requested for file %s\n", + (int)offset, (int)count, fsp->fsp_name )); + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); -- cgit From 98411c48c08f6093a0b42b46c02c6544804bf98d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Aug 1998 04:35:54 +0000 Subject: - zero shared memory before freeing it - changed the hash size to 13 (much smaller than before). This should make for more efficient shared memory usage as it will lead to less fragmentation. (This used to be commit 9c1e4c2dae6323c9a1bd74148d0b45aac61e7c0a) --- source3/locking/shmem.c | 5 ++++- source3/locking/shmem_sysv.c | 9 ++++----- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index be8e22108a..6015085fe4 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -41,7 +41,7 @@ extern int DEBUGLEVEL; #define SHM_FILE_MODE 0644 #endif -#define SHMEM_HASH_SIZE 113 +#define SHMEM_HASH_SIZE 13 /* WARNING : offsets are used because mmap() does not guarantee that all processes have the @@ -606,6 +606,9 @@ static BOOL smb_shm_free(int offset) DEBUG(6,("smb_shm_free : freeing %d bytes at offset %d\n",header_p->size*CellSize,offset)); + /* zero the area being freed - this allows us to find bugs faster */ + memset(smb_shm_offset2addr(offset), 0, header_p->size*CellSize); + if ( scanner_p == prev_p ) { smb_shm_header_p->statistics.cells_free += header_p->size; diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 192ed32344..b57116f7b8 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -48,11 +48,7 @@ extern int DEBUGLEVEL; #define SEMAPHORE_PERMS 0666 #endif -#ifdef SEMMSL -#define SHMEM_HASH_SIZE (SEMMSL-1) -#else -#define SHMEM_HASH_SIZE 63 -#endif +#define SHMEM_HASH_SIZE 13 #define MIN_SHM_SIZE 0x1000 @@ -330,6 +326,9 @@ static BOOL shm_free(int offset) DEBUG(6,("shm_free : freeing %d bytes at offset %d\n", header_p->size*CellSize,offset)); + + /* zero the area being freed - this allows us to find bugs faster */ + memset(shm_offset2addr(offset), 0, header_p->size*CellSize); if (scanner_p == prev_p) { shm_header_p->statistics.cells_free += header_p->size; -- cgit From 693480af8bb2d3e83566af9463ca427f47a879da Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Aug 1998 20:20:54 +0000 Subject: configure.in, configure: include/config.h.in: Added stropts and poll. include/smb.h: Moved old typedefs of uint8 etc. into include/includes.h where all the other defines live (changed them from typedefs to defines). Other changes : changed from using uint32 to SMB_DEV_T and SMB_INO_T in preparation for moving to size independed (ie. 64 bit clean) device and inode access. Stat call wrapper comes next :-). Jeremy. (This used to be commit 3d9ec96de5e04e83abafe9c5d980bd39eee856ea) --- source3/locking/locking.c | 6 +++--- source3/locking/locking_shm.c | 24 ++++++++++++------------ source3/locking/locking_slow.c | 16 +++++++++------- 3 files changed, 24 insertions(+), 22 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4f2c9ab345..856b7cfcf6 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -190,7 +190,7 @@ BOOL locking_end(void) Lock a hash bucket entry. ******************************************************************/ BOOL lock_share_entry(connection_struct *conn, - uint32 dev, uint32 inode, int *ptok) + SMB_DEV_T dev, SMB_INO_T inode, int *ptok) { return share_ops->lock_entry(conn, dev, inode, ptok); } @@ -199,7 +199,7 @@ BOOL lock_share_entry(connection_struct *conn, Unlock a hash bucket entry. ******************************************************************/ BOOL unlock_share_entry(connection_struct *conn, - uint32 dev, uint32 inode, int token) + SMB_DEV_T dev, SMB_INO_T inode, int token) { return share_ops->unlock_entry(conn, dev, inode, token); } @@ -208,7 +208,7 @@ BOOL unlock_share_entry(connection_struct *conn, Get all share mode entries for a dev/inode pair. ********************************************************************/ int get_share_modes(connection_struct *conn, - int token, uint32 dev, uint32 inode, + int token, SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry **shares) { return share_ops->get_entries(conn, token, dev, inode, shares); diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index cded5e628d..909bdb78e4 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -45,8 +45,8 @@ typedef struct { int next_offset; /* offset of next record in chain from hash bucket */ int locking_version; - int32 st_dev; - int32 st_ino; + SMB_DEV_T st_dev; + SMB_INO_T st_ino; int num_share_mode_entries; int share_mode_entries; /* Chain of share mode entries for this file */ char file_name[1]; @@ -63,7 +63,7 @@ static int read_only; /* Conversion to hash entry index from device and inode numbers. */ -#define HASH_ENTRY(dev,ino) ((((uint32)(dev)) ^ ((uint32)(ino))) % shmops->hash_size()) +#define HASH_ENTRY(dev,ino) ((unsigned int)(((dev) ^ (ino)) % shmops->hash_size())) /******************************************************************* @@ -78,7 +78,7 @@ static BOOL shm_stop_share_mode_mgmt(void) lock a hash bucket entry in shared memory for share_mode management ******************************************************************/ static BOOL shm_lock_share_entry(connection_struct *conn, - uint32 dev, uint32 inode, int *ptok) + SMB_DEV_T dev, SMB_INO_T inode, int *ptok) { return shmops->lock_hash_entry(HASH_ENTRY(dev, inode)); } @@ -87,7 +87,7 @@ static BOOL shm_lock_share_entry(connection_struct *conn, unlock a hash bucket entry in shared memory for share_mode management ******************************************************************/ static BOOL shm_unlock_share_entry(connection_struct *conn, - uint32 dev, uint32 inode, int token) + SMB_DEV_T dev, SMB_INO_T inode, int token) { return shmops->unlock_hash_entry(HASH_ENTRY(dev, inode)); } @@ -96,7 +96,7 @@ static BOOL shm_unlock_share_entry(connection_struct *conn, get all share mode entries in shared memory for a dev/inode pair. ********************************************************************/ static int shm_get_share_modes(connection_struct *conn, - int token, uint32 dev, uint32 inode, + int token, SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry **old_shares) { int *mode_array; @@ -259,7 +259,8 @@ del the share mode of a file. ********************************************************************/ static void shm_del_share_mode(int token, files_struct *fsp) { - uint32 dev, inode; + SMB_DEV_T dev; + SMB_INO_T inode; int *mode_array; unsigned int hash_entry; share_mode_record *file_scanner_p; @@ -387,7 +388,8 @@ set the share mode of a file. Return False on fail, True on success. ********************************************************************/ static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type) { - int32 dev, inode; + SMB_DEV_T dev; + SMB_INO_T inode; int *mode_array; unsigned int hash_entry; share_mode_record *file_scanner_p; @@ -495,7 +497,8 @@ Remove an oplock port and mode entry from a share mode. ********************************************************************/ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) { - uint32 dev, inode; + SMB_DEV_T dev; + SMB_INO_T inode; int *mode_array; unsigned int hash_entry; share_mode_record *file_scanner_p; @@ -696,6 +699,3 @@ struct share_ops *locking_shm_init(int ronly) int locking_shm_dummy_procedure(void) {return 0;} #endif /* FAST_SHARE_MODES */ - - - diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 2017f09289..0a766c9ab9 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -81,7 +81,7 @@ static BOOL slow_stop_share_mode_mgmt(void) name a share file ******************************************************************/ static BOOL share_name(connection_struct *conn, - uint32 dev, uint32 inode, char *name) + SMB_DEV_T dev, SMB_INO_T inode, char *name) { int len; pstrcpy(name,lp_lockdir()); @@ -124,7 +124,7 @@ static int delete_share_file(connection_struct *conn, char *fname ) lock a share mode file. ******************************************************************/ static BOOL slow_lock_share_entry(connection_struct *conn, - uint32 dev, uint32 inode, int *ptok) + SMB_DEV_T dev, SMB_INO_T inode, int *ptok) { pstring fname; int fd; @@ -217,9 +217,9 @@ static BOOL slow_lock_share_entry(connection_struct *conn, unlock a share mode file. ******************************************************************/ static BOOL slow_unlock_share_entry(connection_struct *conn, - uint32 dev, uint32 inode, int token) + SMB_DEV_T dev, SMB_INO_T inode, int token) { - int fd = (int)token; + int fd = token; int ret = True; struct stat sb; pstring fname; @@ -348,10 +348,11 @@ deleting it.\n", fname)); /******************************************************************* get all share mode entries in a share file for a dev/inode pair. ********************************************************************/ -static int slow_get_share_modes(connection_struct *conn, int token, uint32 dev, uint32 inode, +static int slow_get_share_modes(connection_struct *conn, int token, + SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry **old_shares) { - int fd = (int)token; + int fd = token; pstring fname; int i; int num_entries; @@ -960,7 +961,8 @@ static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) char *base; int fd; pstring lname; - uint32 dev,inode; + SMB_DEV_T dev; + SMB_INO_T inode; BOOL new_file; pstring fname; -- cgit From 18556274139cc5a00593471bd745354d98a35303 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Sep 1998 20:11:54 +0000 Subject: More abstraction of file system data types, to move to a 64 bit file interface for the NT SMB's. Created a new define, SMB_STRUCT_STAT that currently is defined to be struct stat - this wil change to a user defined type containing 64 bit info when the correct wrappers are written for 64 bit stat(), fstat() and lstat() calls. Also changed all sys_xxxx() calls that were previously just wrappers to the same call prefixed by a dos_to_unix() call into dos_xxxx() calls. This makes it explicit when a pathname translation is being done, and when it is not. Now, all sys_xxx() calls are meant to be wrappers to mask OS differences, and not silently converting filenames on the fly. Jeremy. (This used to be commit 28aa182dbffaa4ffd86047e608400de4b26e80eb) --- source3/locking/locking_slow.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 0a766c9ab9..4c2ba43cd8 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -159,7 +159,7 @@ static BOOL slow_lock_share_entry(connection_struct *conn, do { - struct stat dummy_stat; + SMB_STRUCT_STAT dummy_stat; fd = (int)open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT), SHARE_FILE_MODE); @@ -221,7 +221,7 @@ static BOOL slow_unlock_share_entry(connection_struct *conn, { int fd = token; int ret = True; - struct stat sb; + SMB_STRUCT_STAT sb; pstring fname; if (read_only) return True; @@ -267,7 +267,7 @@ Read a share file into a buffer. ********************************************************************/ static int read_share_file(connection_struct *conn, int fd, char *fname, char **out, BOOL *p_new_file) { - struct stat sb; + SMB_STRUCT_STAT sb; char *buf; int size; @@ -680,7 +680,7 @@ static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 pstring fname; int fd = (int)token; int pid = (int)getpid(); - struct stat sb; + SMB_STRUCT_STAT sb; char *buf; int num_entries; int header_size; -- cgit From 7bb86c1b132bce31a006ea9768a54db7a45fe1a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Sep 1998 18:40:31 +0000 Subject: Ok - this is the 64 bit widening check in. It changes the configure to check for stat64 and friends, and then changes much of Samba to use the data type SMB_OFF_T for file size information. stat/fstat/lstat/lseek/ftruncate have now become sys_stat etc. to hide the 64 bit calls if needed. Note that this still does not expose 64 bit functionality to the client, as the changes to the reply_xxx smb's are not yet done. This code change should make these changes possible. Still to do before full 64 bit-ness to the client: fcntl lock code. statfs code widening of dev_t and ino_t (now possible due to SMB_DEV_T and SMB_OFF_T types being in place). Let me know if wierd things happen after this check-in and I'll fix them :-). Jeremy. (This used to be commit 14500936c321d15995c963766aac67bf1f4e3824) --- source3/locking/locking_slow.c | 38 ++++++++--------- source3/locking/shmem.c | 93 +++++++++++++++++++++++++++--------------- 2 files changed, 79 insertions(+), 52 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 4c2ba43cd8..c242baec4a 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -188,7 +188,7 @@ static BOOL slow_lock_share_entry(connection_struct *conn, * the open and the lock call. Back out and try again. */ - if(stat(fname, &dummy_stat)!=0) + if(sys_stat(fname, &dummy_stat)!=0) { DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", fname, strerror(errno))); @@ -232,7 +232,7 @@ static BOOL slow_unlock_share_entry(connection_struct *conn, share_name(conn, dev, inode, fname); /* get the share mode file size */ - if(fstat((int)token, &sb) != 0) + if(sys_fstat((int)token, &sb) != 0) { DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", fname, strerror(errno))); @@ -269,12 +269,12 @@ static int read_share_file(connection_struct *conn, int fd, char *fname, char ** { SMB_STRUCT_STAT sb; char *buf; - int size; + SMB_OFF_T size; *out = 0; *p_new_file = False; - if(fstat(fd, &sb) != 0) + if(sys_fstat(fd, &sb) != 0) { DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", fname, strerror(errno))); @@ -288,14 +288,14 @@ static int read_share_file(connection_struct *conn, int fd, char *fname, char ** } /* Allocate space for the file */ - if((buf = (char *)malloc(sb.st_size)) == NULL) + if((buf = (char *)malloc((size_t)sb.st_size)) == NULL) { DEBUG(0,("read_share_file: malloc for file size %d fail !\n", (int)sb.st_size)); return -1; } - if(lseek(fd, 0, SEEK_SET) != 0) + if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) { DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \ for share file %s (%s)\n", fname, strerror(errno))); @@ -304,7 +304,7 @@ for share file %s (%s)\n", fname, strerror(errno))); return -1; } - if (read(fd,buf,sb.st_size) != sb.st_size) + if (read(fd,buf,(size_t)sb.st_size) != (size_t)sb.st_size) { DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n", fname, strerror(errno))); @@ -472,7 +472,7 @@ it left a share mode entry with mode 0x%X in share file %s\n", if(num_entries_copied != num_entries) { - if(lseek(fd, 0, SEEK_SET) != 0) + if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) { DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); @@ -510,7 +510,7 @@ mode file %s (%s)\n", fname, strerror(errno))); return 0; } /* Now truncate the file at this point. */ - if(ftruncate(fd, newsize)!= 0) + if(sys_ftruncate(fd, (SMB_OFF_T)newsize)!= 0) { DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); @@ -642,7 +642,7 @@ for share file %s\n", num_entries, fname)); } /* Re-write the file - and truncate it at the correct point. */ - if(lseek(fd, 0, SEEK_SET) != 0) + if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) { DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); @@ -662,7 +662,7 @@ mode file %s (%s)\n", fname, strerror(errno))); } /* Now truncate the file at this point. */ - if(ftruncate(fd, newsize) != 0) + if(sys_ftruncate(fd, (SMB_OFF_T)newsize) != 0) { DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); @@ -689,7 +689,7 @@ static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 share_name(fsp->conn, fsp->fd_ptr->dev, fsp->fd_ptr->inode, fname); - if(fstat(fd, &sb) != 0) + if(sys_fstat(fd, &sb) != 0) { DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", fname)); @@ -699,17 +699,17 @@ static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 /* Sanity check for file contents (if it's not a new share file). */ if(sb.st_size != 0) { - int size = sb.st_size; + SMB_OFF_T size = sb.st_size; /* Allocate space for the file plus one extra entry */ - if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL) + if((buf = (char *)malloc((size_t)(sb.st_size + SMF_ENTRY_LENGTH))) == NULL) { DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", (int)(sb.st_size + SMF_ENTRY_LENGTH))); return False; } - if(lseek(fd, 0, SEEK_SET) != 0) + if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) { DEBUG(0,("ERROR: set_share_mode: Failed to reset position \ to 0 for share file %s (%s)\n", fname, strerror(errno))); @@ -718,7 +718,7 @@ to 0 for share file %s (%s)\n", fname, strerror(errno))); return False; } - if (read(fd,buf,sb.st_size) != sb.st_size) + if (read(fd,buf,(size_t)sb.st_size) != (size_t)sb.st_size) { DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n", fname, strerror(errno))); @@ -781,7 +781,7 @@ deleting it.\n", fname)); SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries); - if(lseek(fd, 0, SEEK_SET) != 0) + if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) { DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \ 0 for share file %s (%s)\n", fname, strerror(errno))); @@ -803,7 +803,7 @@ deleting it (%s).\n",fname, strerror(errno))); /* Now truncate the file at this point - just for safety. */ - if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0) + if(sys_ftruncate(fd, (SMB_OFF_T)(header_size + (SMF_ENTRY_LENGTH*num_entries)))!= 0) { DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), @@ -916,7 +916,7 @@ from the share file %s\n", i, num_entries, fname)); } /* Re-write the file - and truncate it at the correct point. */ - if(lseek(fd, 0, SEEK_SET) != 0) + if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) { DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 6015085fe4..8a81d0efff 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -314,9 +314,9 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth int smb_shm_processes_fd = -1; int nb_read; pid_t other_pid; - int seek_back = -((int)sizeof(other_pid)); - int free_slot = -1; - int erased_slot; + SMB_OFF_T seek_back = -((SMB_OFF_T)sizeof(other_pid)); + SMB_OFF_T free_slot = -1; + SMB_OFF_T erased_slot; smb_shm_processes_fd = open(processreg_file, read_only?O_RDONLY:(O_RDWR|O_CREAT), @@ -339,10 +339,15 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth else { /* erase old pid */ +#ifdef LARGE_SMB_OFF_T + DEBUG(5,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %.0f)\n", + (int)other_pid, (double)seek_back)); +#else DEBUG(5,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %d)\n", (int)other_pid, seek_back)); +#endif other_pid = (pid_t)0; - erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); + erased_slot = sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)); if(free_slot < 0) free_slot = erased_slot; @@ -350,7 +355,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth } else if(free_slot < 0) - free_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); + free_slot = sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); } if (nb_read < 0) { @@ -360,11 +365,17 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth } if(free_slot < 0) - free_slot = lseek(smb_shm_processes_fd, 0, SEEK_END); + free_slot = sys_lseek(smb_shm_processes_fd, 0, SEEK_END); +#ifdef LARGE_SMB_OFF_T + DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %.0f\n", + (int)pid, (double)free_slot)); +#else /* LARGE_SMB_OFF_T */ DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %d\n", (int)pid,free_slot)); - lseek(smb_shm_processes_fd, free_slot, SEEK_SET); +#endif /* LARGE_SMB_OFF_T */ + + sys_lseek(smb_shm_processes_fd, free_slot, SEEK_SET); if(write(smb_shm_processes_fd, &pid, sizeof(pid)) < 0) { DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %s\n",strerror(errno))); @@ -382,8 +393,8 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) int smb_shm_processes_fd = -1; int nb_read; pid_t other_pid; - int seek_back = -((int)sizeof(other_pid)); - int erased_slot; + SMB_OFF_T seek_back = -((SMB_OFF_T)sizeof(other_pid)); + SMB_OFF_T erased_slot; BOOL found = False; @@ -399,20 +410,25 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) DEBUG(5,("smb_shm_unregister_process : read record for pid %d\n",(int)other_pid)); if(other_pid == pid) { - /* erase pid */ - DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %d)\n", + /* erase pid */ +#ifdef LARGE_SMB_OFF_T + DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %.0f)\n", + (int)other_pid, (double)seek_back)); +#else /* LARGE_SMB_OFF_T */ + DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %d)\n", (int)other_pid, seek_back)); - other_pid = (pid_t)0; - erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); - if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) - { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %s\n",strerror(errno))); - close(smb_shm_processes_fd); - return False; - } +#endif /* LARGE_SMB_OFF_T */ + other_pid = (pid_t)0; + erased_slot = sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); + if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) + { + DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %s\n",strerror(errno))); + close(smb_shm_processes_fd); + return False; + } - found = True; - break; + found = True; + break; } } if (nb_read < 0) @@ -750,10 +766,10 @@ static struct shmem_ops shmops = { struct shmem_ops *smb_shm_open(int ronly) { pstring file_name; - int filesize; + SMB_OFF_T filesize; BOOL created_new = False; BOOL other_processes = True; - int size = lp_shmem_size(); + SMB_OFF_T size = (SMB_OFF_T)lp_shmem_size(); read_only = ronly; @@ -766,7 +782,11 @@ struct shmem_ops *smb_shm_open(int ronly) if (!*file_name) return(False); pstrcat(file_name, "/SHARE_MEM_FILE"); +#ifdef LARGE_SMB_OFF_T + DEBUG(5,("smb_shm_open : using shmem file %s to be of size %.0f\n",file_name,(double)size)); +#else /* LARGE_SMB_OFF_T */ DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); +#endif /* LARGE_SMB_OFF_T */ smb_shm_fd = open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), SHM_FILE_MODE); @@ -783,7 +803,7 @@ struct shmem_ops *smb_shm_open(int ronly) return NULL; } - if( (filesize = lseek(smb_shm_fd, 0, SEEK_END)) < 0) + if( (filesize = sys_lseek(smb_shm_fd, 0, SEEK_END)) < 0) { DEBUG(0,("ERROR smb_shm_open : lseek failed with code %s\n",strerror(errno))); smb_shm_global_unlock(); @@ -792,7 +812,7 @@ struct shmem_ops *smb_shm_open(int ronly) } /* return the file offset to 0 to save on later seeks */ - lseek(smb_shm_fd,0,SEEK_SET); + sys_lseek(smb_shm_fd,0,SEEK_SET); if (filesize == 0) { @@ -819,17 +839,17 @@ struct shmem_ops *smb_shm_open(int ronly) if (!read_only && (created_new || !other_processes)) { /* we just created a new one, or are the first opener, lets set it size */ - if( ftruncate(smb_shm_fd, size) <0) + if( sys_ftruncate(smb_shm_fd, size) <0) { - DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %s\n",strerror(errno))); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; + DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %s\n",strerror(errno))); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; } /* paranoia */ - lseek(smb_shm_fd,0,SEEK_SET); + sys_lseek(smb_shm_fd,0,SEEK_SET); filesize = size; } @@ -838,7 +858,14 @@ struct shmem_ops *smb_shm_open(int ronly) { /* the existing file has a different size and we are not the first opener. Since another process is still using it, we will use the file size */ - DEBUG(0,("WARNING smb_shm_open : filesize (%d) != expected size (%d), using filesize\n",filesize,size)); +#ifdef LARGE_SMB_OFF_T + DEBUG(0,("WARNING smb_shm_open : filesize (%.0f) != expected size (%.0f), using filesize\n", + (double)filesize, (double)size)); +#else /* LARGE_SMB_OFF_T */ + DEBUG(0,("WARNING smb_shm_open : filesize (%d) != expected size (%d), using filesize\n", + filesize,size)); +#endif /* LARGE_SMB_OFF_T */ + size = filesize; } -- cgit From 623a18db4b0f46c80c29e93a0ad0a2fcbfec71dc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Sep 1998 00:23:28 +0000 Subject: More 64 bit stuff - now the fcntl locks are 64 bit clean. Nearly at the stage where I can expose the 64-bit-ness to the NT clients.... Jeremy. (This used to be commit 422f1dd45074c0e28203aca5952e57bbe56676b6) --- source3/locking/locking.c | 41 +++++++++++++++++++++++++---------------- source3/locking/locking_slow.c | 6 +++--- source3/locking/shmem.c | 8 ++++---- 3 files changed, 32 insertions(+), 23 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 856b7cfcf6..bd484a18b6 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -71,7 +71,7 @@ static int map_lock_type( files_struct *fsp, int lock_type) Utility function called to see if a file region is locked. ****************************************************************************/ BOOL is_locked(files_struct *fsp,connection_struct *conn, - uint32 count,uint32 offset, int lock_type) + SMB_OFF_T count,SMB_OFF_T offset, int lock_type) { int snum = SNUM(conn); @@ -87,7 +87,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, * fd. So we don't need to use map_lock_type here. */ - return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); + return(fcntl_lock(fsp->fd_ptr->fd,SMB_F_GETLK,offset,count,lock_type)); } @@ -95,7 +95,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, Utility function called by locking requests. ****************************************************************************/ BOOL do_lock(files_struct *fsp,connection_struct *conn, - uint32 count,uint32 offset,int lock_type, + SMB_OFF_T count,SMB_OFF_T offset,int lock_type, int *eclass,uint32 *ecode) { BOOL ok = False; @@ -109,11 +109,16 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, return False; } +#ifdef LARGE_SMB_OFF_T + DEBUG(10,("do_lock: lock type %d start=%.0f len=%.0f requested for file %s\n", + lock_type, (double)offset, (double)count, fsp->fsp_name )); +#else /* LARGE_SMB_OFF_T */ DEBUG(10,("do_lock: lock type %d start=%d len=%d requested for file %s\n", lock_type, (int)offset, (int)count, fsp->fsp_name )); +#endif /* LARGE_SMB_OFF_T */ if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count, + ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, map_lock_type(fsp,lock_type)); if (!ok) { @@ -129,18 +134,23 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, Utility function called by unlocking requests. ****************************************************************************/ BOOL do_unlock(files_struct *fsp,connection_struct *conn, - uint32 count,uint32 offset,int *eclass,uint32 *ecode) + SMB_OFF_T count,SMB_OFF_T offset,int *eclass,uint32 *ecode) { BOOL ok = False; if (!lp_locking(SNUM(conn))) return(True); +#ifdef LARGE_SMB_OFF_T + DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", + (double)offset, (double)count, fsp->fsp_name )); +#else DEBUG(10,("do_unlock: unlock start=%d len=%d requested for file %s\n", (int)offset, (int)count, fsp->fsp_name )); +#endif if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); + ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); if (!ok) { *eclass = ERRDOS; @@ -150,28 +160,27 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, return True; /* Did unlock */ } - - /**************************************************************************** Initialise the locking functions. ****************************************************************************/ BOOL locking_init(int read_only) { - if (share_ops) return True; + if (share_ops) + return True; #ifdef FAST_SHARE_MODES - share_ops = locking_shm_init(read_only); + share_ops = locking_shm_init(read_only); #else - share_ops = locking_slow_init(read_only); + share_ops = locking_slow_init(read_only); #endif - if (!share_ops) { - DEBUG(0,("ERROR: Failed to initialise share modes!\n")); - return False; - } + if (!share_ops) { + DEBUG(0,("ERROR: Failed to initialise share modes!\n")); + return False; + } - return True; + return True; } /******************************************************************* diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index c242baec4a..c9b8d2a687 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -174,7 +174,7 @@ static BOOL slow_lock_share_entry(connection_struct *conn, /* At this point we have an open fd to the share mode file. Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) + if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) { DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", fname, strerror(errno))); @@ -251,7 +251,7 @@ static BOOL slow_unlock_share_entry(connection_struct *conn, /* token is the fd of the open share mode file. */ /* Unlock the first byte. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False) + if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False) { DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", strerror(errno))); @@ -980,7 +980,7 @@ static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) /* Lock the share mode file while we read it. */ if(!read_only && - fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) { + fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) { close(fd); continue; } diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 8a81d0efff..3cdcf82f73 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -107,7 +107,7 @@ static BOOL smb_shm_global_lock(void) return True; /* Do an exclusive wait lock on the first byte of the file */ - if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_WRLCK) == False) + if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) { DEBUG(0,("ERROR smb_shm_global_lock : fcntl_lock failed with code %s\n",strerror(errno))); smb_shm_times_locked--; @@ -144,7 +144,7 @@ static BOOL smb_shm_global_unlock(void) return True; /* Do a wait unlock on the first byte of the file */ - if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_UNLCK) == False) + if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False) { DEBUG(0,("ERROR smb_shm_global_unlock : fcntl_lock failed with code %s\n",strerror(errno))); smb_shm_times_locked++; @@ -682,7 +682,7 @@ static BOOL smb_shm_lock_hash_entry( unsigned int entry) return True; /* Do an exclusive wait lock on the 4 byte region mapping into this entry */ - if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(int), F_WRLCK) == False) + if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, start, sizeof(int), F_WRLCK) == False) { DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno))); return False; @@ -709,7 +709,7 @@ static BOOL smb_shm_unlock_hash_entry( unsigned int entry ) return True; /* Do a wait lock on the 4 byte region mapping into this entry */ - if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(int), F_UNLCK) == False) + if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, start, sizeof(int), F_UNLCK) == False) { DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno))); return False; -- cgit From 83900f2b682c62f2b5620b29ecb710274990ac51 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Sep 1998 20:53:58 +0000 Subject: Modified dev_t and ino_t code to be 64 bit clean (including changes to oplock break message passing). I think that smbd/nmbd are now inode and offset size independent (at least for 32 bit and 64 bit systems). Now to expose all this new functionality to NT clients..... Jeremy. (This used to be commit 5910d07bbf45a34d3c901461f74704c029a79474) --- source3/locking/locking_shm.c | 131 ++++++++++++++++++++++++++++++++--------- source3/locking/locking_slow.c | 18 +++++- 2 files changed, 118 insertions(+), 31 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 909bdb78e4..b18b5efb2c 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -139,15 +139,26 @@ static int shm_get_share_modes(connection_struct *conn, if(!found) { - DEBUG(5,("get_share_modes no entry for file dev = %d ino = %d\n", - dev, inode)); +#ifdef LARGE_SMB_INO_T + DEBUG(5,("get_share_modes no entry for file dev = %x ino = %.0f\n", + (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(5,("get_share_modes no entry for file dev = %x ino = %lx\n", + (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ return (0); } if(file_scanner_p->locking_version != LOCKING_VERSION) { - DEBUG(0,("ERROR: get_share_modes Deleting old share mode v1 %d dev=%d ino=%d\n", - file_scanner_p->locking_version, dev, inode)); +#ifdef LARGE_SMB_INO_T + 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)); +#else /* LARGE_SMB_INO_T */ + DEBUG(0,("ERROR: get_share_modes Deleting old share mode v1 %d dev=%x ino=%lx\n", + file_scanner_p->locking_version, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ + if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; else @@ -203,8 +214,13 @@ static int shm_get_share_modes(connection_struct *conn, /* PARANOIA TEST */ if(file_scanner_p->num_share_mode_entries < 0) { - DEBUG(0,("PANIC ERROR: get_share_mode: entries=%d dev=%d ino=%d\n", - file_scanner_p->num_share_mode_entries,dev, inode)); +#ifdef LARGE_SMB_INO_T + 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)); +#else /* LARGE_SMB_INO_T */ + DEBUG(0,("PANIC ERROR: get_share_mode: entries=%d dev=%x ino=%lx\n", + file_scanner_p->num_share_mode_entries, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ return 0; } @@ -235,8 +251,13 @@ static int shm_get_share_modes(connection_struct *conn, /* If no valid share mode entries were found then this record shouldn't exist ! */ if(num_entries_copied == 0) { - DEBUG(0,("get_share_modes: file with dev %d inode %d empty\n", - dev, inode)); +#ifdef LARGE_SMB_INO_T + DEBUG(0,("get_share_modes: file with dev %x inode %.0f empty\n", + (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(0,("get_share_modes: file with dev %x inode %lx empty\n", + (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ if(*old_shares) free((char *)*old_shares); *old_shares = 0; @@ -248,8 +269,13 @@ static int shm_get_share_modes(connection_struct *conn, shmops->shm_free(shmops->addr2offset(file_scanner_p)); } - DEBUG(5,("get_share_modes: file with dev %d inode %d -> %d entries\n", - dev, inode, num_entries_copied)); +#ifdef LARGE_SMB_INO_T + DEBUG(5,("get_share_modes: file with dev %x inode %.0f -> %d entries\n", + (unsigned int)dev, (double)inode, num_entries_copied)); +#else /* LARGE_SMB_INO_T */ + DEBUG(5,("get_share_modes: file with dev %x inode %lx -> %d entries\n", + (unsigned int)dev, (unsigned long)inode, num_entries_copied)); +#endif /* LARGE_SMB_INO_T */ return(num_entries_copied); } @@ -304,15 +330,26 @@ static void shm_del_share_mode(int token, files_struct *fsp) if(!found) { - DEBUG(0,("ERROR: del_share_mode no entry for dev %d inode %d\n", - dev, inode)); +#ifdef LARGE_SMB_INO_T + DEBUG(0,("ERROR: del_share_mode no entry for dev %x inode %.0f\n", + (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(0,("ERROR: del_share_mode no entry for dev %x inode %lx\n", + (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ return; } if(file_scanner_p->locking_version != LOCKING_VERSION) { - DEBUG(0,("ERROR: del_share_modes Deleting old share mode v1 %d dev=%d ino=%d\n", - file_scanner_p->locking_version, dev, inode)); +#ifdef LARGE_SMB_INO_T + 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)); +#else /* LARGE_SMB_INO_T */ + DEBUG(0,("ERROR: del_share_modes Deleting old share mode v1 %d dev=%x ino=%lx\n", + file_scanner_p->locking_version, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ + if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; else @@ -347,8 +384,14 @@ static void shm_del_share_mode(int token, files_struct *fsp) /* Decrement the number of entries in the record. */ file_scanner_p->num_share_mode_entries -= 1; - DEBUG(2,("del_share_modes Deleting share mode entry dev=%d ino=%d\n", - dev, inode)); +#ifdef LARGE_SMB_INO_T + DEBUG(2,("del_share_modes Deleting share mode entry dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(2,("del_share_modes Deleting share mode entry dev=%x ino=%lx\n", + (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ + 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; @@ -367,8 +410,14 @@ static void shm_del_share_mode(int token, files_struct *fsp) /* 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 num entries = 0, deleting share_mode dev=%d ino=%d\n", - dev, inode)); +#ifdef LARGE_SMB_INO_T + DEBUG(2,("del_share_modes num entries = 0, deleting share_mode dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(2,("del_share_modes num entries = 0, deleting share_mode dev=%x ino=%lx\n", + (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ + if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; else @@ -378,8 +427,13 @@ static void shm_del_share_mode(int token, files_struct *fsp) } else { - DEBUG(0,("ERROR: del_share_modes No share mode dev=%d ino=%d\n", - dev, inode)); +#ifdef LARGE_SMB_INO_T + DEBUG(0,("ERROR: del_share_modes No share mode dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(0,("ERROR: del_share_modes No share mode dev=%x ino=%lx\n", + (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ } } @@ -447,8 +501,13 @@ static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 file_scanner_p = new_mode_p; - DEBUG(3,("set_share_mode: Created share record for %s (dev %d inode %d)\n", - fsp->fsp_name, dev, inode)); +#ifdef LARGE_SMB_INO_T + DEBUG(3,("set_share_mode: Created share record for %s (dev %x inode %.0f)\n", + fsp->fsp_name, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(3,("set_share_mode: Created share record for %s (dev %x inode %lx)\n", + fsp->fsp_name, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ } /* Now create the share mode entry */ @@ -542,15 +601,26 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) if(!found) { - DEBUG(0,("ERROR:remove_share_oplock: no entry found for dev=%d ino=%d\n", - dev, inode)); +#ifdef LARGE_SMB_INO_T + DEBUG(0,("ERROR:remove_share_oplock: no entry found for dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(0,("ERROR:remove_share_oplock: no entry found for dev=%x ino=%lx\n", + (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ return False; } if(file_scanner_p->locking_version != LOCKING_VERSION) { - DEBUG(0,("ERROR: remove_share_oplock: Deleting old share mode v1=%d dev=%d ino=%d\n", - file_scanner_p->locking_version, dev, inode)); +#ifdef LARGE_SMB_INO_T + 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)); +#else /* LARGE_SMB_INO_T */ + DEBUG(0,("ERROR: remove_share_oplock: Deleting old share mode v1=%d dev=%x ino=%lx\n", + file_scanner_p->locking_version, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ + if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; else @@ -586,8 +656,13 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) if(!found) { - DEBUG(0,("ERROR: remove_share_oplock: No oplock granted. dev=%d ino=%d\n", - dev, inode)); +#ifdef LARGE_SMB_INO_T + DEBUG(0,("ERROR: remove_share_oplock: No oplock granted. dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(0,("ERROR: remove_share_oplock: No oplock granted. dev=%x ino=%lx\n", + (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ return False; } diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index c9b8d2a687..fd95fd45ec 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -90,7 +90,11 @@ static BOOL share_name(connection_struct *conn, len = strlen(name); name += len; - slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%u",dev,inode); +#ifdef LARGE_SMB_INO_T + slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%.0f",(unsigned int)dev,(double)inode); +#else /* LARGE_SMB_INO_T */ + slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%lu",(unsigned int)dev,(unsigned long)inode); +#endif /* LARGE_SMB_INO_T */ return(True); } @@ -966,8 +970,16 @@ static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) BOOL new_file; pstring fname; - if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue; - +#ifdef LARGE_SMB_INO_T + double inode_ascii; + if (sscanf(s,"share.%u.%lf",&dev,&inode_ascii)!=2) continue; + inode = (SMB_INO_T)inode_ascii; +#else /* LARGE_SMB_INO_T */ + unsigned long inode_long; + if (sscanf(s,"share.%u.%lu",&dev,&inode_long)!=2) continue; + inode = (SMB_INO_T)inode_long; +#endif /* LARGE_SMB_INO_T */ + pstrcpy(lname,lp_lockdir()); trim_string(lname,NULL,"/"); pstrcat(lname,"/"); -- cgit From e9ea36e4d2270bd7d32da12ef6d6e2299641582d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Sep 1998 05:07:05 +0000 Subject: tridge the destroyer returns! prompted by the interpret_security() dead code that Jean-Francois pointed out I added a make target "finddead" that finds potentially dead (ie. unused) code. It spat out 304 function names ... I went through these are deleted many of them, making others static (finddead also reports functions that are used only in the local file). in doing this I have almost certainly deleted some useful code. I may have even prevented compilation with some compile options. I apologise. I decided it was better to get rid of this code now and add back the one or two functions that are needed than to keep all this baggage. So, if I have done a bit too much "destroying" then let me know. Keep the swearing to a minimum :) One bit I didn't do is the ubibt code. Chris, can you look at that? Heaps of unused functions there. Can they be made static? (This used to be commit 2204475c87f3024ea8fd1fbd7385b2def617a46f) --- source3/locking/shmem.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 3cdcf82f73..d8ef1d2c53 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -344,7 +344,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth (int)other_pid, (double)seek_back)); #else DEBUG(5,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %d)\n", - (int)other_pid, seek_back)); + (int)other_pid, (int)seek_back)); #endif other_pid = (pid_t)0; erased_slot = sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); @@ -372,7 +372,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth (int)pid, (double)free_slot)); #else /* LARGE_SMB_OFF_T */ DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %d\n", - (int)pid,free_slot)); + (int)pid,(int)free_slot)); #endif /* LARGE_SMB_OFF_T */ sys_lseek(smb_shm_processes_fd, free_slot, SEEK_SET); @@ -416,7 +416,7 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) (int)other_pid, (double)seek_back)); #else /* LARGE_SMB_OFF_T */ DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %d)\n", - (int)other_pid, seek_back)); + (int)other_pid, (int)seek_back)); #endif /* LARGE_SMB_OFF_T */ other_pid = (pid_t)0; erased_slot = sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); @@ -785,7 +785,8 @@ struct shmem_ops *smb_shm_open(int ronly) #ifdef LARGE_SMB_OFF_T DEBUG(5,("smb_shm_open : using shmem file %s to be of size %.0f\n",file_name,(double)size)); #else /* LARGE_SMB_OFF_T */ - DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); + DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n", + file_name,(int)size)); #endif /* LARGE_SMB_OFF_T */ smb_shm_fd = open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), @@ -863,7 +864,7 @@ struct shmem_ops *smb_shm_open(int ronly) (double)filesize, (double)size)); #else /* LARGE_SMB_OFF_T */ DEBUG(0,("WARNING smb_shm_open : filesize (%d) != expected size (%d), using filesize\n", - filesize,size)); + (int)filesize,(int)size)); #endif /* LARGE_SMB_OFF_T */ size = filesize; -- cgit From 012e575e1336fbba70174d32c26ecab9ce5523ce Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Sep 1998 05:23:29 +0000 Subject: ahh, the joy of deleting large chunks of code that someone else has painstakingly put in :) This gets rid of most of the #ifdef LARGE_SMB_INO_T ifdefs around DEBUG() statements. We just use %.0f in all cases. Makes the code a bit easier to read :) (This used to be commit 41f0069afc02169932e04ff0039bb6328eaaf04d) --- source3/locking/locking.c | 10 ---------- source3/locking/shmem.c | 25 ------------------------- 2 files changed, 35 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index bd484a18b6..f088720e0a 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -109,13 +109,8 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, return False; } -#ifdef LARGE_SMB_OFF_T DEBUG(10,("do_lock: lock type %d start=%.0f len=%.0f requested for file %s\n", lock_type, (double)offset, (double)count, fsp->fsp_name )); -#else /* LARGE_SMB_OFF_T */ - DEBUG(10,("do_lock: lock type %d start=%d len=%d requested for file %s\n", - lock_type, (int)offset, (int)count, fsp->fsp_name )); -#endif /* LARGE_SMB_OFF_T */ if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, @@ -141,13 +136,8 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, if (!lp_locking(SNUM(conn))) return(True); -#ifdef LARGE_SMB_OFF_T DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", (double)offset, (double)count, fsp->fsp_name )); -#else - DEBUG(10,("do_unlock: unlock start=%d len=%d requested for file %s\n", - (int)offset, (int)count, fsp->fsp_name )); -#endif if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index d8ef1d2c53..f1c985881b 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -339,13 +339,8 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth else { /* erase old pid */ -#ifdef LARGE_SMB_OFF_T DEBUG(5,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %.0f)\n", (int)other_pid, (double)seek_back)); -#else - DEBUG(5,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %d)\n", - (int)other_pid, (int)seek_back)); -#endif other_pid = (pid_t)0; erased_slot = sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)); @@ -367,13 +362,8 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth if(free_slot < 0) free_slot = sys_lseek(smb_shm_processes_fd, 0, SEEK_END); -#ifdef LARGE_SMB_OFF_T DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %.0f\n", (int)pid, (double)free_slot)); -#else /* LARGE_SMB_OFF_T */ - DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %d\n", - (int)pid,(int)free_slot)); -#endif /* LARGE_SMB_OFF_T */ sys_lseek(smb_shm_processes_fd, free_slot, SEEK_SET); if(write(smb_shm_processes_fd, &pid, sizeof(pid)) < 0) @@ -411,13 +401,8 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) if(other_pid == pid) { /* erase pid */ -#ifdef LARGE_SMB_OFF_T DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %.0f)\n", (int)other_pid, (double)seek_back)); -#else /* LARGE_SMB_OFF_T */ - DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %d)\n", - (int)other_pid, (int)seek_back)); -#endif /* LARGE_SMB_OFF_T */ other_pid = (pid_t)0; erased_slot = sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) @@ -782,12 +767,7 @@ struct shmem_ops *smb_shm_open(int ronly) if (!*file_name) return(False); pstrcat(file_name, "/SHARE_MEM_FILE"); -#ifdef LARGE_SMB_OFF_T DEBUG(5,("smb_shm_open : using shmem file %s to be of size %.0f\n",file_name,(double)size)); -#else /* LARGE_SMB_OFF_T */ - DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n", - file_name,(int)size)); -#endif /* LARGE_SMB_OFF_T */ smb_shm_fd = open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), SHM_FILE_MODE); @@ -859,13 +839,8 @@ struct shmem_ops *smb_shm_open(int ronly) { /* the existing file has a different size and we are not the first opener. Since another process is still using it, we will use the file size */ -#ifdef LARGE_SMB_OFF_T DEBUG(0,("WARNING smb_shm_open : filesize (%.0f) != expected size (%.0f), using filesize\n", (double)filesize, (double)size)); -#else /* LARGE_SMB_OFF_T */ - DEBUG(0,("WARNING smb_shm_open : filesize (%d) != expected size (%d), using filesize\n", - (int)filesize,(int)size)); -#endif /* LARGE_SMB_OFF_T */ size = filesize; } -- cgit From 06cc91f9a631a23dcd4902d710b89e4b7584c459 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Sep 1998 01:24:30 +0000 Subject: Added ssize_t to configure code. Got 'religion' about using size_t and ssize_t for read/write stuff as part of the code to expose 64 bits to the client. This checkin does all the 'easy' stuff - such as all the read/write/lock calls - but now comes the harder parts (open & friends) and all the file enquiry functions..... Jeremy. (This used to be commit 36544fe5476f7770bd5748574fc54be7b3ee4d4a) --- source3/locking/locking_shm.c | 71 +------------------------------------------ 1 file changed, 1 insertion(+), 70 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index b18b5efb2c..2e7d29f745 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -139,25 +139,15 @@ static int shm_get_share_modes(connection_struct *conn, if(!found) { -#ifdef LARGE_SMB_INO_T DEBUG(5,("get_share_modes no entry for file dev = %x ino = %.0f\n", (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(5,("get_share_modes no entry for file dev = %x ino = %lx\n", - (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ return (0); } if(file_scanner_p->locking_version != LOCKING_VERSION) { -#ifdef LARGE_SMB_INO_T 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)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("ERROR: get_share_modes Deleting old share mode v1 %d dev=%x ino=%lx\n", - file_scanner_p->locking_version, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; @@ -214,13 +204,8 @@ static int shm_get_share_modes(connection_struct *conn, /* PARANOIA TEST */ if(file_scanner_p->num_share_mode_entries < 0) { -#ifdef LARGE_SMB_INO_T 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)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("PANIC ERROR: get_share_mode: entries=%d dev=%x ino=%lx\n", - file_scanner_p->num_share_mode_entries, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ return 0; } @@ -251,13 +236,9 @@ static int shm_get_share_modes(connection_struct *conn, /* If no valid share mode entries were found then this record shouldn't exist ! */ if(num_entries_copied == 0) { -#ifdef LARGE_SMB_INO_T DEBUG(0,("get_share_modes: file with dev %x inode %.0f empty\n", (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("get_share_modes: file with dev %x inode %lx empty\n", - (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ + if(*old_shares) free((char *)*old_shares); *old_shares = 0; @@ -269,13 +250,8 @@ static int shm_get_share_modes(connection_struct *conn, shmops->shm_free(shmops->addr2offset(file_scanner_p)); } -#ifdef LARGE_SMB_INO_T DEBUG(5,("get_share_modes: file with dev %x inode %.0f -> %d entries\n", (unsigned int)dev, (double)inode, num_entries_copied)); -#else /* LARGE_SMB_INO_T */ - DEBUG(5,("get_share_modes: file with dev %x inode %lx -> %d entries\n", - (unsigned int)dev, (unsigned long)inode, num_entries_copied)); -#endif /* LARGE_SMB_INO_T */ return(num_entries_copied); } @@ -330,25 +306,15 @@ static void shm_del_share_mode(int token, files_struct *fsp) if(!found) { -#ifdef LARGE_SMB_INO_T DEBUG(0,("ERROR: del_share_mode no entry for dev %x inode %.0f\n", (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("ERROR: del_share_mode no entry for dev %x inode %lx\n", - (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ return; } if(file_scanner_p->locking_version != LOCKING_VERSION) { -#ifdef LARGE_SMB_INO_T 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)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("ERROR: del_share_modes Deleting old share mode v1 %d dev=%x ino=%lx\n", - file_scanner_p->locking_version, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; @@ -384,13 +350,8 @@ static void shm_del_share_mode(int token, files_struct *fsp) /* Decrement the number of entries in the record. */ file_scanner_p->num_share_mode_entries -= 1; -#ifdef LARGE_SMB_INO_T DEBUG(2,("del_share_modes Deleting share mode entry dev=%x ino=%.0f\n", (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(2,("del_share_modes Deleting share mode entry dev=%x ino=%lx\n", - (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ if(entry_prev_p == entry_scanner_p) /* We are at start of list */ @@ -410,13 +371,8 @@ static void shm_del_share_mode(int token, files_struct *fsp) /* If we deleted the last share mode entry then remove the share mode record. */ if(file_scanner_p->num_share_mode_entries == 0) { -#ifdef LARGE_SMB_INO_T DEBUG(2,("del_share_modes num entries = 0, deleting share_mode dev=%x ino=%.0f\n", (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(2,("del_share_modes num entries = 0, deleting share_mode dev=%x ino=%lx\n", - (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; @@ -427,13 +383,8 @@ static void shm_del_share_mode(int token, files_struct *fsp) } else { -#ifdef LARGE_SMB_INO_T DEBUG(0,("ERROR: del_share_modes No share mode dev=%x ino=%.0f\n", (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("ERROR: del_share_modes No share mode dev=%x ino=%lx\n", - (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ } } @@ -501,13 +452,8 @@ static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 file_scanner_p = new_mode_p; -#ifdef LARGE_SMB_INO_T DEBUG(3,("set_share_mode: Created share record for %s (dev %x inode %.0f)\n", fsp->fsp_name, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(3,("set_share_mode: Created share record for %s (dev %x inode %lx)\n", - fsp->fsp_name, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ } /* Now create the share mode entry */ @@ -601,25 +547,15 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) if(!found) { -#ifdef LARGE_SMB_INO_T DEBUG(0,("ERROR:remove_share_oplock: no entry found for dev=%x ino=%.0f\n", (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("ERROR:remove_share_oplock: no entry found for dev=%x ino=%lx\n", - (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ return False; } if(file_scanner_p->locking_version != LOCKING_VERSION) { -#ifdef LARGE_SMB_INO_T 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)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("ERROR: remove_share_oplock: Deleting old share mode v1=%d dev=%x ino=%lx\n", - file_scanner_p->locking_version, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; @@ -656,13 +592,8 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) if(!found) { -#ifdef LARGE_SMB_INO_T DEBUG(0,("ERROR: remove_share_oplock: No oplock granted. dev=%x ino=%.0f\n", (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("ERROR: remove_share_oplock: No oplock granted. dev=%x ino=%lx\n", - (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ return False; } -- cgit From e649750cb4d2d2577f0577b1d7a87ae4daf8fb6f Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Mon, 21 Sep 1998 09:07:08 +0000 Subject: major autoconf clean-up fix problems in builds with srcdir!=builddir (This used to be commit 1ffc3b807a3f80644c974b454ff5e6f68e89b546) --- source3/locking/dummy.in | 1 + 1 file changed, 1 insertion(+) create mode 100644 source3/locking/dummy.in (limited to 'source3/locking') diff --git a/source3/locking/dummy.in b/source3/locking/dummy.in new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/source3/locking/dummy.in @@ -0,0 +1 @@ + -- cgit From cf971f88ac188eec353a7fb021744b8076cc4eb7 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Mon, 28 Sep 1998 00:14:36 +0000 Subject: automated generation of .dummy files for each subdirectory; dummy.in files are no longer needed, and new directories will be taken care of automatically, at configure (or config.status --recheck) time (This used to be commit 237a8e5fe62d757c04b8207cbbee4df1470cfe4e) --- source3/locking/dummy.in | 1 - 1 file changed, 1 deletion(-) delete mode 100644 source3/locking/dummy.in (limited to 'source3/locking') diff --git a/source3/locking/dummy.in b/source3/locking/dummy.in deleted file mode 100644 index 8b13789179..0000000000 --- a/source3/locking/dummy.in +++ /dev/null @@ -1 +0,0 @@ - -- cgit From cf3a9741dc7427efb97eff09a3c197a906ce6767 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Sep 1998 21:43:48 +0000 Subject: Changes to test in configure if capabilities are enabled on a system. Changes to get Samba to compile cleanly with the IRIX compiler with the options : -fullwarn -woff 1209,1174 (the -woff options are to turn off warnings about unused function parameters and controlling loop expressions being constants). Split prototype generation as we hit a limit in IRIX nawk. Removed "." code in smbd/filename.c (yet again :-). Jeremy. (This used to be commit e0567433bd72aec17bf5a54cc292701095d25f09) --- source3/locking/locking_shm.c | 6 ------ source3/locking/shmem.c | 8 ++++++-- source3/locking/shmem_sysv.c | 5 ----- 3 files changed, 6 insertions(+), 13 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 2e7d29f745..1077cf23eb 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -398,7 +398,6 @@ static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 int *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; int new_entry_offset; BOOL found = False; @@ -411,7 +410,6 @@ static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]); - file_prev_p = file_scanner_p; while(file_scanner_p) { @@ -422,7 +420,6 @@ static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 } else { - file_prev_p = file_scanner_p ; file_scanner_p = (share_mode_record *) shmops->offset2addr(file_scanner_p->next_offset); } @@ -509,7 +506,6 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) 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(); @@ -568,7 +564,6 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) found = False; entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr( file_scanner_p->share_mode_entries); - entry_prev_p = entry_scanner_p; while(entry_scanner_p) { if( (pid == entry_scanner_p->e.pid) && @@ -584,7 +579,6 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) } else { - entry_prev_p = entry_scanner_p; entry_scanner_p = (shm_share_mode_entry *) shmops->offset2addr(entry_scanner_p->next_share_mode_entry); } diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index f1c985881b..b63db1f168 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -384,7 +384,6 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) int nb_read; pid_t other_pid; SMB_OFF_T seek_back = -((SMB_OFF_T)sizeof(other_pid)); - SMB_OFF_T erased_slot; BOOL found = False; @@ -404,7 +403,12 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %.0f)\n", (int)other_pid, (double)seek_back)); other_pid = (pid_t)0; - erased_slot = sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); + if(sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR) == -1) + { + DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file sys_lseek failed with code %s\n",strerror(errno))); + close(smb_shm_processes_fd); + return False; + } if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) { DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %s\n",strerror(errno))); diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index b57116f7b8..1dd4743df0 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -92,7 +92,6 @@ struct ShmBlockDesc #define AlignedHeaderSize ((sizeof(struct ShmHeader)+7) & ~7) static struct ShmHeader *shm_header_p = NULL; -static BOOL shm_initialize_called = False; static int read_only; @@ -447,8 +446,6 @@ static BOOL shm_initialize(int size) shm_header_p->consistent = True; - shm_initialize_called = True; - return True; } @@ -533,7 +530,6 @@ static struct shmem_ops shmops = { ******************************************************************/ struct shmem_ops *sysv_shm_open(int ronly) { - BOOL created_new = False; BOOL other_processes; struct shmid_ds shm_ds; struct semid_ds sem_ds; @@ -661,7 +657,6 @@ struct shmem_ops *sysv_shm_open(int ronly) (errno != EINVAL && errno != ENOSPC)) break; shm_size *= 0.8; } - created_new = (shm_id != -1); } if (shm_id == -1) { -- cgit From fc62d6bf368c950e1e51bc42771cce8b299df42c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 17 Oct 1998 17:41:13 +0000 Subject: Small tidyups for gcc in 'preen' mode.... Jeremy. (This used to be commit 60dc1a4a00a22088d33369588b0d5eb292cf084a) --- source3/locking/locking_slow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index fd95fd45ec..f2c2d3e9d9 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -1071,6 +1071,6 @@ struct share_ops *locking_slow_init(int ronly) return &share_ops; } #else - int locking_slow_dummy_procedure(void) -{return 0;} + int locking_slow_dummy_procedure(void); + int locking_slow_dummy_procedure(void) {return 0;} #endif /* !FAST_SHARE_MODES */ -- cgit From b8aec499dc49b1d86d9f44296e07d40232813642 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 18 Oct 1998 22:06:35 +0000 Subject: Fixed sys_lseek and seek_file calls so all returns are *checked* :-). Jeremy. (This used to be commit b8b781191dd7d28944d87eec5fa0fbef798e289b) --- source3/locking/shmem.c | 414 ++++++++++++++++++++++++++++-------------------- 1 file changed, 242 insertions(+), 172 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index b63db1f168..2a4e4de129 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -311,71 +311,113 @@ static BOOL smb_shm_create_hash_table( unsigned int size ) static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *other_processes) { - int smb_shm_processes_fd = -1; - int nb_read; - pid_t other_pid; - SMB_OFF_T seek_back = -((SMB_OFF_T)sizeof(other_pid)); - SMB_OFF_T free_slot = -1; - SMB_OFF_T erased_slot; - - smb_shm_processes_fd = open(processreg_file, - read_only?O_RDONLY:(O_RDWR|O_CREAT), - SHM_FILE_MODE); - - if ( smb_shm_processes_fd < 0 ) - { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file open failed with code %s\n",strerror(errno))); - return False; - } - - *other_processes = False; - - while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) - { - if(other_pid) + int smb_shm_processes_fd = -1; + int nb_read; + pid_t other_pid; + SMB_OFF_T seek_back = -((SMB_OFF_T)sizeof(other_pid)); + SMB_OFF_T free_slot = -1; + SMB_OFF_T erased_slot; + + smb_shm_processes_fd = open(processreg_file, + read_only?O_RDONLY:(O_RDWR|O_CREAT), + SHM_FILE_MODE); + + if ( smb_shm_processes_fd < 0 ) + { + DEBUG(0, ("ERROR smb_shm_register_process : processreg_file \ +open failed with code %s\n",strerror(errno))); + return False; + } + + *other_processes = False; + + while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) + { + if(other_pid) + { + if(process_exists(other_pid)) + *other_processes = True; + else { - if(process_exists(other_pid)) - *other_processes = True; - else - { - /* erase old pid */ - DEBUG(5,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %.0f)\n", - (int)other_pid, (double)seek_back)); - other_pid = (pid_t)0; - erased_slot = sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); - write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)); - if(free_slot < 0) - free_slot = erased_slot; - } + /* erase old pid */ + DEBUG(5,("smb_shm_register_process : erasing stale record \ +for pid %d (seek_back = %.0f)\n", (int)other_pid, (double)seek_back)); + other_pid = (pid_t)0; + if((erased_slot = sys_lseek(smb_shm_processes_fd, + seek_back, SEEK_CUR)) == -1) + { + DEBUG(0, ("ERROR smb_shm_register_process : sys_lseek failed \ +with error %s\n", strerror(errno))); + close(smb_shm_processes_fd); + return False; + } + + if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) == -1) + { + DEBUG(0, ("ERROR smb_shm_register_process : write failed \ +with error %s\n", strerror(errno))); + close(smb_shm_processes_fd); + return False; + } + + if(free_slot < 0) + free_slot = erased_slot; } - else - if(free_slot < 0) - free_slot = sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); - } - if (nb_read < 0) - { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file read failed with code %s\n",strerror(errno))); + } + else + { + if(free_slot < 0) + { + if((free_slot = sys_lseek(smb_shm_processes_fd, + seek_back, SEEK_CUR))==-1) + { + DEBUG(0, ("ERROR smb_shm_register_process : sys_lseek \ +failed with error %s\n", strerror(errno))); + close(smb_shm_processes_fd); + return False; + } + } /* end if free_slot */ + } /* end else */ + } /* end if other_pid */ + + if (nb_read < 0) + { + DEBUG(0,("ERROR smb_shm_register_process : processreg_file read \ +failed with code %s\n",strerror(errno))); + close(smb_shm_processes_fd); + return False; + } + + if(free_slot < 0) + { + if((free_slot = sys_lseek(smb_shm_processes_fd, 0, SEEK_END)) == -1) + { + DEBUG(0,("ERROR smb_shm_register_process : sys_lseek failed with code %s\n",strerror(errno))); close(smb_shm_processes_fd); return False; - } - - if(free_slot < 0) - free_slot = sys_lseek(smb_shm_processes_fd, 0, SEEK_END); + } + } - DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %.0f\n", + DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %.0f\n", (int)pid, (double)free_slot)); - sys_lseek(smb_shm_processes_fd, free_slot, SEEK_SET); - if(write(smb_shm_processes_fd, &pid, sizeof(pid)) < 0) - { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %s\n",strerror(errno))); - close(smb_shm_processes_fd); - return False; - } + if(sys_lseek(smb_shm_processes_fd, free_slot, SEEK_SET) == -1) + { + DEBUG(0,("ERROR smb_shm_register_process : sys_lseek failed with code %s\n",strerror(errno))); + close(smb_shm_processes_fd); + return False; + } - close(smb_shm_processes_fd); + if(write(smb_shm_processes_fd, &pid, sizeof(pid)) == -1) + { + DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %s\n",strerror(errno))); + close(smb_shm_processes_fd); + return False; + } - return True; + close(smb_shm_processes_fd); + + return True; } static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) @@ -754,136 +796,164 @@ static struct shmem_ops shmops = { ******************************************************************/ struct shmem_ops *smb_shm_open(int ronly) { - pstring file_name; - SMB_OFF_T filesize; - BOOL created_new = False; - BOOL other_processes = True; - SMB_OFF_T size = (SMB_OFF_T)lp_shmem_size(); - - read_only = ronly; + pstring file_name; + SMB_OFF_T filesize; + BOOL created_new = False; + BOOL other_processes = True; + SMB_OFF_T size = (SMB_OFF_T)lp_shmem_size(); - pstrcpy(file_name,lp_lockdir()); - if (!directory_exist(file_name,NULL)) { - if (read_only) return NULL; - mkdir(file_name,0755); - } - trim_string(file_name,"","/"); - if (!*file_name) return(False); - pstrcat(file_name, "/SHARE_MEM_FILE"); - - DEBUG(5,("smb_shm_open : using shmem file %s to be of size %.0f\n",file_name,(double)size)); - - smb_shm_fd = open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), - SHM_FILE_MODE); + read_only = ronly; - if ( smb_shm_fd < 0 ) - { - DEBUG(0,("ERROR smb_shm_open : open failed with code %s\n",strerror(errno))); + pstrcpy(file_name,lp_lockdir()); + if (!directory_exist(file_name,NULL)) { + if (read_only) return NULL; - } - - if (!smb_shm_global_lock()) - { - DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n")); - return NULL; - } - - if( (filesize = sys_lseek(smb_shm_fd, 0, SEEK_END)) < 0) - { - DEBUG(0,("ERROR smb_shm_open : lseek failed with code %s\n",strerror(errno))); - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; - } - - /* return the file offset to 0 to save on later seeks */ - sys_lseek(smb_shm_fd,0,SEEK_SET); - - if (filesize == 0) - { - /* we just created a new one */ - created_new = True; - } - - /* to find out if some other process is already mapping the file, - we use a registration file containing the processids of the file mapping processes - */ - - /* construct processreg file name */ - pstrcpy(smb_shm_processreg_name, file_name); - pstrcat(smb_shm_processreg_name, ".processes"); - - if (!read_only && - !smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes)) - { + mkdir(file_name,0755); + } + trim_string(file_name,"","/"); + if (!*file_name) + return(False); + pstrcat(file_name, "/SHARE_MEM_FILE"); + + DEBUG(5,("smb_shm_open : using shmem file %s to be of size %.0f\n", + file_name,(double)size)); + + smb_shm_fd = open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), + SHM_FILE_MODE); + + if ( smb_shm_fd < 0 ) + { + DEBUG(0,("ERROR smb_shm_open : open failed with code %s\n",strerror(errno))); + return NULL; + } + + if (!smb_shm_global_lock()) + { + DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n")); + return NULL; + } + + if( (filesize = sys_lseek(smb_shm_fd, 0, SEEK_END)) == -1) + { + DEBUG(0,("ERROR smb_shm_open : sys_lseek failed with code %s\n", + strerror(errno))); + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; + } + + /* + * Return the file offset to 0 to save on later seeks. + */ + if(sys_lseek(smb_shm_fd,0,SEEK_SET) == -1) + { + DEBUG(0,("ERROR smb_shm_open : sys_lseek failed with code %s\n", + strerror(errno))); + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; + } + + if (filesize == 0) + { + /* + * We just created a new one. + */ + created_new = True; + } + + /* + * To find out if some other process is already mapping the file, + * we use a registration file containing the processids of the file + * mapping processes. + */ + + /* construct processreg file name */ + pstrcpy(smb_shm_processreg_name, file_name); + pstrcat(smb_shm_processreg_name, ".processes"); + + if (!read_only && !smb_shm_register_process(smb_shm_processreg_name, + getpid(), &other_processes)) + { + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; + } + + if (!read_only && (created_new || !other_processes)) + { + /* we just created a new one, or are the first opener, lets set it size */ + if( sys_ftruncate(smb_shm_fd, size) <0) + { + DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %s\n", + strerror(errno))); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); smb_shm_global_unlock(); close(smb_shm_fd); return NULL; - } - - if (!read_only && (created_new || !other_processes)) - { - /* we just created a new one, or are the first opener, lets set it size */ - if( sys_ftruncate(smb_shm_fd, size) <0) - { - DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %s\n",strerror(errno))); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; - } - - /* paranoia */ - sys_lseek(smb_shm_fd,0,SEEK_SET); - - filesize = size; - } - - if (size != filesize ) - { - /* the existing file has a different size and we are not the first opener. - Since another process is still using it, we will use the file size */ - DEBUG(0,("WARNING smb_shm_open : filesize (%.0f) != expected size (%.0f), using filesize\n", - (double)filesize, (double)size)); + } - size = filesize; - } - - smb_shm_header_p = (struct SmbShmHeader *)mmap(NULL, size, - read_only?PROT_READ: - (PROT_READ | PROT_WRITE), - MAP_FILE | MAP_SHARED, - smb_shm_fd, 0); - /* WARNING, smb_shm_header_p can be different for different processes mapping the same file ! */ - if (smb_shm_header_p == (struct SmbShmHeader *)(-1)) - { - DEBUG(0,("ERROR smb_shm_open : mmap failed with code %s\n",strerror(errno))); + /* paranoia */ + if(sys_lseek(smb_shm_fd,0,SEEK_SET) == -1) + { + DEBUG(0,("ERROR smb_shm_open : sys_lseek failed with code %s\n", + strerror(errno))); smb_shm_unregister_process(smb_shm_processreg_name, getpid()); smb_shm_global_unlock(); close(smb_shm_fd); return NULL; - } + } + + filesize = size; + } + + if (size != filesize ) + { + /* the existing file has a different size and we are not the first opener. + Since another process is still using it, we will use the file size */ + DEBUG(0,("WARNING smb_shm_open : filesize (%.0f) != expected \ +size (%.0f), using filesize\n", (double)filesize, (double)size)); + + size = filesize; + } + + smb_shm_header_p = (struct SmbShmHeader *)mmap(NULL, size, + read_only?PROT_READ: (PROT_READ | PROT_WRITE), + MAP_FILE | MAP_SHARED, smb_shm_fd, 0); + + /* + * WARNING, smb_shm_header_p can be different for different + * processes mapping the same file ! + */ + if (smb_shm_header_p == (struct SmbShmHeader *)(-1)) + { + DEBUG(0,("ERROR smb_shm_open : mmap failed with code %s\n",strerror(errno))); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; + } - if (!read_only && (created_new || !other_processes)) - { - smb_shm_initialize(size); - /* Create the hash buckets for the share file entries. */ - smb_shm_create_hash_table(SHMEM_HASH_SIZE); - } - else if (!smb_shm_validate_header(size) ) - { - /* existing file is corrupt, samba admin should remove it by hand */ - DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n")); - munmap((caddr_t)smb_shm_header_p, size); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; - } + if (!read_only && (created_new || !other_processes)) + { + smb_shm_initialize(size); + /* Create the hash buckets for the share file entries. */ + smb_shm_create_hash_table(SHMEM_HASH_SIZE); + } + else if (!smb_shm_validate_header(size) ) + { + /* existing file is corrupt, samba admin should remove it by hand */ + DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n")); + munmap((caddr_t)smb_shm_header_p, size); + smb_shm_unregister_process(smb_shm_processreg_name, getpid()); + smb_shm_global_unlock(); + close(smb_shm_fd); + return NULL; + } - smb_shm_global_unlock(); - return &shmops; + smb_shm_global_unlock(); + return &shmops; } -- cgit From 9bb7ac81b6e4d33e1be49447dbdbbb8d24259f53 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Oct 1998 03:34:50 +0000 Subject: Reasonably large change to give us *exactly* correct NT delete on close semantics. This was trickier than it looks :-). Check out the new DELETE_ON_CLOSE flag in the share modes and the new code that iterates through all open files on the same device and inode in files.c and trans2.c Also changed the code that modifies share mode entries to take generic function pointers rather than doing a specific thing so this sort of change should be easier in the future. Jeremy. (This used to be commit 5e6a7cd99d29d1cf068fc517272559c1cf47ea3a) --- source3/locking/locking.c | 45 ++++++++++++++++++++++++++++++-- source3/locking/locking_shm.c | 29 +++++++++++++-------- source3/locking/locking_slow.c | 59 +++++++++++++++++++++++++++++------------- 3 files changed, 102 insertions(+), 31 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f088720e0a..b71b775524 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -229,12 +229,53 @@ BOOL set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type) return share_ops->set_entry(token, fsp, port, op_type); } +/******************************************************************* + Static function that actually does the work for the generic function + below. +********************************************************************/ + +static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, + void *param) +{ + DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode )); + /* Delete the oplock info. */ + entry->op_port = 0; + entry->op_type = 0; +} + /******************************************************************* Remove an oplock port and mode entry from a share mode. ********************************************************************/ -BOOL remove_share_oplock(files_struct *fsp, int token) + +BOOL remove_share_oplock(int token, files_struct *fsp) +{ + return share_ops->mod_entry(token, fsp, remove_share_oplock_fn, NULL); +} + +/******************************************************************* + Static function that actually does the work for the generic function + below. +********************************************************************/ + +static void modify_share_mode_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, + void *param) +{ + int new_share_mode = *(int *)param; + DEBUG(10,("modify_share_mode_fn: changing share mode info from %x to %x for entry dev=%x ino=%.0f\n", + entry->share_mode, new_share_mode, (unsigned int)dev, (double)inode )); + /* Change the share mode info. */ + entry->share_mode = new_share_mode; +} + +/******************************************************************* + Modify a share mode on a file. Used by the delete open file code. + Return False on fail, True on success. +********************************************************************/ + +BOOL modify_share_mode(int token, files_struct *fsp, int new_mode) { - return share_ops->remove_oplock(fsp, token); + return share_ops->mod_entry(token, fsp, modify_share_mode_fn, (void *)&new_mode); } /******************************************************************* diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 1077cf23eb..375a8b7f10 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -495,9 +495,12 @@ static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 } /******************************************************************* -Remove an oplock port and mode entry from a share mode. + Call a generic modify function for a share mode entry. ********************************************************************/ -static BOOL shm_remove_share_oplock(files_struct *fsp, int token) + +static BOOL shm_mod_share_entry(int token, files_struct *fsp, + void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), + void *param) { SMB_DEV_T dev; SMB_INO_T inode; @@ -518,7 +521,7 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) if(mode_array[hash_entry] == 0) { - DEBUG(0,("PANIC ERROR:remove_share_oplock: hash bucket %d empty\n", + DEBUG(0,("PANIC ERROR:modify_share_entry: hash bucket %d empty\n", hash_entry)); return False; } @@ -543,14 +546,14 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) if(!found) { - DEBUG(0,("ERROR:remove_share_oplock: no entry found for dev=%x ino=%.0f\n", + DEBUG(0,("ERROR:modify_share_entry: no entry found for dev=%x ino=%.0f\n", (unsigned int)dev, (double)inode)); return False; } if(file_scanner_p->locking_version != LOCKING_VERSION) { - DEBUG(0,("ERROR: remove_share_oplock: Deleting old share mode v1=%d dev=%x ino=%.0f\n", + DEBUG(0,("ERROR: modify_share_entry: Deleting old share mode v1=%d dev=%x ino=%.0f\n", file_scanner_p->locking_version, (unsigned int)dev, (double)inode)); if(file_prev_p == file_scanner_p) @@ -571,9 +574,14 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) (memcmp(&entry_scanner_p->e.time, &fsp->open_time,sizeof(struct timeval)) == 0) ) { - /* Delete the oplock info. */ - entry_scanner_p->e.op_port = 0; - entry_scanner_p->e.op_type = 0; + /* + * Call the generic function with the given parameter. + */ + + DEBUG(5,("modify_share_entry: Calling generic function to modify entry for dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode)); + + (*mod_fn)( &entry_scanner_p->e, dev, inode, param); found = True; break; } @@ -586,7 +594,7 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) if(!found) { - DEBUG(0,("ERROR: remove_share_oplock: No oplock granted. dev=%x ino=%.0f\n", + DEBUG(0,("ERROR: modify_share_entry: No entry found for dev=%x ino=%.0f\n", (unsigned int)dev, (double)inode)); return False; } @@ -594,7 +602,6 @@ static BOOL shm_remove_share_oplock(files_struct *fsp, int token) return True; } - /******************************************************************* call the specified function on each entry under management by the share mode system @@ -670,7 +677,7 @@ static struct share_ops share_ops = { shm_get_share_modes, shm_del_share_mode, shm_set_share_mode, - shm_remove_share_oplock, + shm_mod_share_entry, shm_share_forall, shm_share_status, }; diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index f2c2d3e9d9..f1e0fa2149 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -827,9 +827,12 @@ mode 0x%X pid=%d\n",fname,fsp->share_mode,pid)); } /******************************************************************* -Remove an oplock port and mode entry from a share mode. + Call a generic modify function for a share mode entry. ********************************************************************/ -static BOOL slow_remove_share_oplock(files_struct *fsp, int token) + +static BOOL slow_mod_share_entry(int token, files_struct *fsp, + void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), + void *param) { pstring fname; int fd = (int)token; @@ -841,20 +844,21 @@ static BOOL slow_remove_share_oplock(files_struct *fsp, int token) int pid; BOOL found = False; BOOL new_file; + share_mode_entry entry; share_name(fsp->conn, fsp->fd_ptr->dev, fsp->fd_ptr->inode, fname); if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0) { - DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n", + DEBUG(0,("ERROR: slow_mod_share_entry: Failed to read share file %s\n", fname)); return False; } if(new_file == True) { - DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \ + DEBUG(0,("ERROR: slow_mod_share_entry: share file %s is new (size zero), \ deleting it.\n", fname)); delete_share_file(fsp->conn, fname); return False; @@ -862,13 +866,13 @@ deleting it.\n", fname)); num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n", + DEBUG(5,("slow_mod_share_entry: share file %s has %d share mode entries.\n", fname, num_entries)); /* PARANOIA TEST */ if(num_entries < 0) { - DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \ + DEBUG(0,("PANIC ERROR:slow_mod_share_entry: num_share_mode_entries < 0 (%d) \ for share file %s\n", num_entries, fname)); return False; } @@ -876,7 +880,7 @@ for share file %s\n", num_entries, fname)); if(num_entries == 0) { /* No entries - just delete the file. */ - DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n", + DEBUG(0,("slow_mod_share_entry: share file %s has no share mode entries - deleting.\n", fname)); if(buf) free(buf); @@ -886,10 +890,6 @@ for share file %s\n", num_entries, fname)); pid = getpid(); - /* Go through the entries looking for the particular one - we have set - remove the oplock settings on it. - */ - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); for(i = 0; i < num_entries; i++) @@ -902,18 +902,41 @@ for share file %s\n", num_entries, fname)); (IVAL(p,SME_PID_OFFSET) != pid)) continue; - DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \ + DEBUG(5,("slow_mod_share_entry: Calling generic function to modify entry number %d (of %d) \ from the share file %s\n", i, num_entries, fname)); - SSVAL(p,SME_PORT_OFFSET,0); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0); + /* + * Copy into the share_mode_entry structure and then call + * the generic function with the given parameter. + */ + + entry.pid = IVAL(p,SME_PID_OFFSET); + entry.op_port = SVAL(p,SME_PORT_OFFSET); + entry.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); + entry.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); + entry.time.tv_sec = IVAL(p,SME_SEC_OFFSET) + entry.time.tv_sec = IVAL(p,SME_USEC_OFFSET); + + (*mod_fn)( &entry, fsp->fd_ptr->dev, fsp->fd_ptr->inode, param); + + /* + * Now copy any changes the function made back into the buffer. + */ + + SIVAL(p,SME_PID_OFFSET, entry.pid) + SSVAL(p,SME_PORT_OFFSET,entry.op_port); + SSVAL(p,SME_OPLOCK_TYPE_OFFSET,entry.op_type); + SIVAL(p,SME_SHAREMODE_OFFSET,entry.share_mode); + SIVAL(p,SME_SEC_OFFSET,entry.time.tv_sec) + SIVAL(p,SME_USEC_OFFSET,entry.time.tv_sec); + found = True; break; } if(!found) { - DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname)); + DEBUG(0,("slow_mod_share_entry: entry not found in share file %s\n", fname)); if(buf) free(buf); return False; @@ -922,7 +945,7 @@ from the share file %s\n", i, num_entries, fname)); /* Re-write the file - and truncate it at the correct point. */ if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) { - DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \ + DEBUG(0,("ERROR: slow_mod_share_entry: lseek failed to reset to \ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); if(buf) free(buf); @@ -932,7 +955,7 @@ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); if(write(fd, buf, fsize) != fsize) { - DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \ + DEBUG(0,("ERROR: slow_mod_share_entry: failed to re-write share \ mode file %s (%s)\n", fname, strerror(errno))); if(buf) free(buf); @@ -1048,7 +1071,7 @@ static struct share_ops share_ops = { slow_get_share_modes, slow_del_share_mode, slow_set_share_mode, - slow_remove_share_oplock, + slow_mod_share_entry, slow_share_forall, slow_share_status, }; -- cgit From 233aae20814d1e0d90805279182b6acd09697871 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 31 Oct 1998 09:31:29 +0000 Subject: don't core dump in smbstatus if we can't open the shmem system (This used to be commit ef9749798ab72a5e26f9cb5d0904266d6df70f8c) --- source3/locking/locking.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index b71b775524..84c9c442b5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -285,6 +285,7 @@ BOOL modify_share_mode(int token, files_struct *fsp, int new_mode) int share_mode_forall(void (*fn)(share_mode_entry *, char *)) { + if (!share_ops) return 0; return share_ops->forall(fn); } -- cgit From 768761820e8d7481c586c4e0ab4ac7cb36d18c4b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Nov 1998 20:50:07 +0000 Subject: Added the same open()/fopen()/creat()/mmap() -> sys_XXX calls. Tidied up some of the mess (no other word for it). Still doesn't compile cleanly. There are calls with incorrect parameters that don't seem to be doing the right thing. This code still needs surgery :-(. Jeremy. (This used to be commit 18ff93a9abbf68ee8c59c0af3e57c63e4a015dac) --- source3/locking/locking_slow.c | 5 ++--- source3/locking/shmem.c | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index f1e0fa2149..7c27355224 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -165,8 +165,7 @@ static BOOL slow_lock_share_entry(connection_struct *conn, { SMB_STRUCT_STAT dummy_stat; - fd = (int)open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT), - SHARE_FILE_MODE); + fd = sys_open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT), SHARE_FILE_MODE); if(fd < 0) { @@ -1008,7 +1007,7 @@ static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) pstrcat(lname,"/"); pstrcat(lname,s); - fd = open(lname,read_only?O_RDONLY:O_RDWR,0); + fd = sys_open(lname,read_only?O_RDONLY:O_RDWR,0); if (fd < 0) { continue; } diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 2a4e4de129..435c0d4c78 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -318,7 +318,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth SMB_OFF_T free_slot = -1; SMB_OFF_T erased_slot; - smb_shm_processes_fd = open(processreg_file, + smb_shm_processes_fd = sys_open(processreg_file, read_only?O_RDONLY:(O_RDWR|O_CREAT), SHM_FILE_MODE); @@ -429,7 +429,7 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) BOOL found = False; - smb_shm_processes_fd = open(processreg_file, O_RDWR); + smb_shm_processes_fd = sys_open(processreg_file, O_RDWR, 0); if ( smb_shm_processes_fd < 0 ) { DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file open failed with code %s\n",strerror(errno))); @@ -818,7 +818,7 @@ struct shmem_ops *smb_shm_open(int ronly) DEBUG(5,("smb_shm_open : using shmem file %s to be of size %.0f\n", file_name,(double)size)); - smb_shm_fd = open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), + smb_shm_fd = sys_open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), SHM_FILE_MODE); if ( smb_shm_fd < 0 ) @@ -917,9 +917,9 @@ size (%.0f), using filesize\n", (double)filesize, (double)size)); size = filesize; } - smb_shm_header_p = (struct SmbShmHeader *)mmap(NULL, size, + smb_shm_header_p = (struct SmbShmHeader *)sys_mmap(NULL, size, read_only?PROT_READ: (PROT_READ | PROT_WRITE), - MAP_FILE | MAP_SHARED, smb_shm_fd, 0); + MAP_FILE | MAP_SHARED, smb_shm_fd, (SMB_OFF_T)0); /* * WARNING, smb_shm_header_p can be different for different -- cgit From bfc38ff872446e0ad365c22327c779e72a81bef9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Nov 1998 21:17:20 +0000 Subject: Makefile.in: Added maintainer mode fixes. aclocal.m4: Added AC_LIBTESTFUNC. configure.in: Fixed -lsecurity -lsec problems. client.c: dos_ fixes. groupdb/aliasunix.c: Dead code removal. include/includes.h: Added default PRINTCAP_NAME. lib/genrand.c: dos_ fixes. lib/replace.c: Added strtoul. lib/system.c: dos_ fixes. lib/util.c: dos_ fixes. lib/util_sid.c: Signed/unsigned fixes. lib/util_str.c: removed bad const. locking/locking_slow.c: dos_ fixes. printing/printing.c: dos_ fixes. rpc_server/srv_samr.c: Dead code removal. rpc_server/srv_sid.c: global_myworkgroup defined with wrong size AGAIN ! smbd/dir.c: dos_ fixes. smbd/open.c: dos_ fixes. smbd/oplock.c: dos_ fixes. smbd/reply.c smbd/server.c smbd/service.c smbd/uid.c: dos_ fixes. Jeremy. (This used to be commit 6acb4b68f68d516e2ac3c47e500f5600d653435e) --- source3/locking/locking_slow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 7c27355224..a465363467 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -973,7 +973,7 @@ share ode system static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) { int i, count=0; - void *dir; + DIR *dir; char *s; share_mode_entry e; -- cgit From d330c907bdc5d8e3c242cea76dfafaae84041270 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Apr 1999 05:22:58 +0000 Subject: Ken McDonell from SGI was interested in adding some profiling capabilities to Samba so that Samba could talk to the SGI PCP (Performance Co-Pilot) apps. This change adds a profiling shared memory area and uses it to count two fairly trivial things, the number of uid switches and the number of SMB packets processes. To add more just edit include/profile.h and then increment it at the right place. I've also added a -P switch to smbstatus to dump the profile area. (This used to be commit ef3d61a80ad0b87c196a63ef2bd4fe8fc3863bd0) --- source3/locking/shmem_sysv.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 1dd4743df0..d4e814d26f 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -33,11 +33,7 @@ extern int DEBUGLEVEL; #define SHM_MAGIC 0x53484100 #define SHM_VERSION 2 -#ifdef SHM_R #define IPC_PERMS ((SHM_R | SHM_W) | (SHM_R>>3) | (SHM_R>>6)) -#else -#define IPC_PERMS 0644 -#endif #ifdef SECURE_SEMAPHORES -- cgit From 9d4b57069cc5ce46c33079ed5ca3dfa3f58118e1 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 05:32:42 +0000 Subject: Use VFS operations for file I/O. (This used to be commit 20bfa71c951a6e6018aafbd43946d1e0669feacb) --- source3/locking/locking.c | 9 +++++---- source3/locking/locking_slow.c | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 84c9c442b5..fdc39d0040 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -87,7 +87,8 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, * fd. So we don't need to use map_lock_type here. */ - return(fcntl_lock(fsp->fd_ptr->fd,SMB_F_GETLK,offset,count,lock_type)); + return(conn->vfs_ops.lock(fsp->fd_ptr->fd,SMB_F_GETLK,offset,count, + lock_type)); } @@ -113,8 +114,8 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, lock_type, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, - map_lock_type(fsp,lock_type)); + ok = conn->vfs_ops.lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, + map_lock_type(fsp,lock_type)); if (!ok) { *eclass = ERRDOS; @@ -140,7 +141,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); + ok = conn->vfs_ops.lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); if (!ok) { *eclass = ERRDOS; diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index a465363467..64bedca4ad 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -177,7 +177,7 @@ static BOOL slow_lock_share_entry(connection_struct *conn, /* At this point we have an open fd to the share mode file. Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) + if(conn->vfs_ops.lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) { DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", fname, strerror(errno))); @@ -254,7 +254,7 @@ static BOOL slow_unlock_share_entry(connection_struct *conn, /* token is the fd of the open share mode file. */ /* Unlock the first byte. */ - if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False) + if(conn->vfs_ops.lock(fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False) { DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", strerror(errno))); @@ -692,7 +692,7 @@ static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 share_name(fsp->conn, fsp->fd_ptr->dev, fsp->fd_ptr->inode, fname); - if(sys_fstat(fd, &sb) != 0) + if(fsp->conn->vfs_ops.fstat_file(fd, &sb) != 0) { DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", fname)); -- cgit From 3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Dec 1999 13:27:58 +0000 Subject: first pass at updating head branch to be to be the same as the SAMBA_2_0 branch (This used to be commit 453a822a76780063dff23526c35408866d0c0154) --- source3/locking/locking.c | 84 ++++++++++++++++++++++++--------- source3/locking/locking_shm.c | 25 +++++----- source3/locking/locking_slow.c | 102 ++++++++++++++++++++++++++++++----------- source3/locking/shmem.c | 2 +- source3/locking/shmem_sysv.c | 28 +++++++---- 5 files changed, 169 insertions(+), 72 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index fdc39d0040..012d954e50 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -87,8 +87,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, * fd. So we don't need to use map_lock_type here. */ - return(conn->vfs_ops.lock(fsp->fd_ptr->fd,SMB_F_GETLK,offset,count, - lock_type)); + return(fcntl_lock(fsp->fd_ptr->fd,SMB_F_GETLK,offset,count,lock_type)); } @@ -114,8 +113,8 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, lock_type, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = conn->vfs_ops.lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, - map_lock_type(fsp,lock_type)); + ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, + map_lock_type(fsp,lock_type)); if (!ok) { *eclass = ERRDOS; @@ -141,7 +140,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = conn->vfs_ops.lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); + ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); if (!ok) { *eclass = ERRDOS; @@ -157,21 +156,26 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, BOOL locking_init(int read_only) { - if (share_ops) - return True; + if (share_ops) + return True; #ifdef FAST_SHARE_MODES - share_ops = locking_shm_init(read_only); + share_ops = locking_shm_init(read_only); + if (!share_ops && read_only && (getuid() == 0)) { + /* this may be the first time the share modes code has + been run. Initialise it now by running it read-write */ + share_ops = locking_shm_init(0); + } #else - share_ops = locking_slow_init(read_only); + share_ops = locking_slow_init(read_only); #endif - if (!share_ops) { - DEBUG(0,("ERROR: Failed to initialise share modes!\n")); - return False; - } + if (!share_ops) { + DEBUG(0,("ERROR: Failed to initialise share modes\n")); + return False; + } - return True; + return True; } /******************************************************************* @@ -242,7 +246,7 @@ static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_I (unsigned int)dev, (double)inode )); /* Delete the oplock info. */ entry->op_port = 0; - entry->op_type = 0; + entry->op_type = NO_OPLOCK; } /******************************************************************* @@ -259,14 +263,45 @@ BOOL remove_share_oplock(int token, files_struct *fsp) below. ********************************************************************/ +static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, + void *param) +{ + DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode )); + entry->op_type = LEVEL_II_OPLOCK; +} + +/******************************************************************* + Downgrade a oplock type from exclusive to level II. +********************************************************************/ + +BOOL downgrade_share_oplock(int token, files_struct *fsp) +{ + return share_ops->mod_entry(token, fsp, downgrade_share_oplock_fn, NULL); +} + +/******************************************************************* + Static function that actually does the work for the generic function + below. +********************************************************************/ + +struct mod_val { + int new_share_mode; + uint16 new_oplock; +}; + static void modify_share_mode_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, void *param) { - int new_share_mode = *(int *)param; - DEBUG(10,("modify_share_mode_fn: changing share mode info from %x to %x for entry dev=%x ino=%.0f\n", - entry->share_mode, new_share_mode, (unsigned int)dev, (double)inode )); - /* Change the share mode info. */ - entry->share_mode = new_share_mode; + struct mod_val *mvp = (struct mod_val *)param; + + DEBUG(10,("modify_share_mode_fn: changing share mode info from %x to %x for entry dev=%x ino=%.0f\n", + entry->share_mode, mvp->new_share_mode, (unsigned int)dev, (double)inode )); + DEBUG(10,("modify_share_mode_fn: changing oplock state from %x to %x for entry dev=%x ino=%.0f\n", + entry->op_type, (int)mvp->new_oplock, (unsigned int)dev, (double)inode )); + /* Change the share mode info. */ + entry->share_mode = mvp->new_share_mode; + entry->op_type = mvp->new_oplock; } /******************************************************************* @@ -274,9 +309,14 @@ static void modify_share_mode_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO Return False on fail, True on success. ********************************************************************/ -BOOL modify_share_mode(int token, files_struct *fsp, int new_mode) +BOOL modify_share_mode(int token, files_struct *fsp, int new_mode, uint16 new_oplock) { - return share_ops->mod_entry(token, fsp, modify_share_mode_fn, (void *)&new_mode); + struct mod_val mv; + + mv.new_share_mode = new_mode; + mv.new_oplock = new_oplock; + + return share_ops->mod_entry(token, fsp, modify_share_mode_fn, (void *)&mv); } /******************************************************************* diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 375a8b7f10..174ad73e97 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -80,6 +80,7 @@ static BOOL shm_stop_share_mode_mgmt(void) static BOOL shm_lock_share_entry(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, int *ptok) { + *ptok = 0; /* For purify... */ return shmops->lock_hash_entry(HASH_ENTRY(dev, inode)); } @@ -165,7 +166,7 @@ static int shm_get_share_modes(connection_struct *conn, malloc(num_entries * sizeof(share_mode_entry)); if(*old_shares == 0) { - DEBUG(0,("get_share_modes: malloc fail!\n")); + DEBUG(0,("get_share_modes: malloc fail for size 0x%x!\n", (unsigned int)(num_entries * sizeof(share_mode_entry)))); return 0; } } @@ -177,7 +178,7 @@ static int shm_get_share_modes(connection_struct *conn, entry_prev_p = entry_scanner_p; while(entry_scanner_p) { - int pid = entry_scanner_p->e.pid; + pid_t pid = entry_scanner_p->e.pid; if (pid && !process_exists(pid)) { @@ -209,7 +210,7 @@ static int shm_get_share_modes(connection_struct *conn, return 0; } - DEBUG(0,("get_share_modes: process %d no longer exists\n", pid)); + DEBUG(0,("get_share_modes: process %d no longer exists\n", (int)pid)); shmops->shm_free(shmops->addr2offset(delete_entry_p)); } @@ -226,7 +227,7 @@ static int shm_get_share_modes(connection_struct *conn, sizeof(struct timeval)); num_entries_copied++; DEBUG(5,("get_share_modes Read share mode 0x%X pid=%d\n", - entry_scanner_p->e.share_mode, entry_scanner_p->e.pid)); + entry_scanner_p->e.share_mode, (int)entry_scanner_p->e.pid)); entry_prev_p = entry_scanner_p; entry_scanner_p = (shm_share_mode_entry *) shmops->offset2addr(entry_scanner_p->next_share_mode_entry); @@ -270,7 +271,7 @@ static void shm_del_share_mode(int token, files_struct *fsp) shm_share_mode_entry *entry_scanner_p; shm_share_mode_entry *entry_prev_p; BOOL found = False; - int pid = getpid(); + pid_t pid = getpid(); dev = fsp->fd_ptr->dev; inode = fsp->fd_ptr->inode; @@ -430,7 +431,7 @@ static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 /* We must create a share_mode_record */ share_mode_record *new_mode_p = NULL; int new_offset = shmops->shm_alloc(sizeof(share_mode_record) + - strlen(fsp->fsp_name) + 1); + strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2); if(new_offset == 0) { DEBUG(0,("ERROR:set_share_mode shmops->shm_alloc fail!\n")); return False; @@ -441,7 +442,9 @@ static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 new_mode_p->st_ino = inode; new_mode_p->num_share_mode_entries = 0; new_mode_p->share_mode_entries = 0; - pstrcpy(new_mode_p->file_name, fsp->fsp_name); + pstrcpy(new_mode_p->file_name, fsp->conn->connectpath); + pstrcat(new_mode_p->file_name, "/"); + pstrcat(new_mode_p->file_name, fsp->fsp_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]; @@ -489,7 +492,7 @@ static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 file_scanner_p->num_share_mode_entries += 1; DEBUG(3,("set_share_mode: Created share entry for %s with mode 0x%X pid=%d\n", - fsp->fsp_name, fsp->share_mode, new_entry_p->e.pid)); + fsp->fsp_name, fsp->share_mode, (int)new_entry_p->e.pid)); return(True); } @@ -510,7 +513,7 @@ static BOOL shm_mod_share_entry(int token, files_struct *fsp, share_mode_record *file_prev_p; shm_share_mode_entry *entry_scanner_p; BOOL found = False; - int pid = getpid(); + pid_t pid = getpid(); dev = fsp->fd_ptr->dev; inode = fsp->fd_ptr->inode; @@ -689,12 +692,12 @@ struct share_ops *locking_shm_init(int ronly) { read_only = ronly; -#ifdef HAVE_SYSV_IPC +#ifdef USE_SYSV_IPC shmops = sysv_shm_open(read_only); if (shmops) return &share_ops; #endif -#ifdef HAVE_SHARED_MMAP +#ifdef USE_SHARED_MMAP shmops = smb_shm_open(read_only); if (shmops) return &share_ops; #endif diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c index 64bedca4ad..58673d2707 100644 --- a/source3/locking/locking_slow.c +++ b/source3/locking/locking_slow.c @@ -118,7 +118,7 @@ static int delete_share_file(connection_struct *conn, char *fname ) DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); } - /* return to our previous privilage level */ + /* return to our previous privilege level */ unbecome_root(False); return 0; @@ -177,7 +177,7 @@ static BOOL slow_lock_share_entry(connection_struct *conn, /* At this point we have an open fd to the share mode file. Lock the first byte exclusively to signify a lock. */ - if(conn->vfs_ops.lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) + if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) { DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", fname, strerror(errno))); @@ -210,7 +210,7 @@ static BOOL slow_lock_share_entry(connection_struct *conn, *ptok = (int)fd; - /* return to our previous privilage level */ + /* return to our previous privilege level */ unbecome_root(False); return ret; @@ -254,7 +254,7 @@ static BOOL slow_unlock_share_entry(connection_struct *conn, /* token is the fd of the open share mode file. */ /* Unlock the first byte. */ - if(conn->vfs_ops.lock(fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False) + if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False) { DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", strerror(errno))); @@ -434,16 +434,16 @@ for share file %s\n", num_entries, fname)); for( i = 0; i < num_entries; i++) { - int pid; + pid_t pid; char *p = base + (i*SMF_ENTRY_LENGTH); - pid = IVAL(p,SME_PID_OFFSET); + pid = (pid_t)IVAL(p,SME_PID_OFFSET); if(!process_exists(pid)) { DEBUG(0,("get_share_modes: process %d no longer exists and \ it left a share mode entry with mode 0x%X in share file %s\n", - pid, IVAL(p,SME_SHAREMODE_OFFSET), fname)); + (int)pid, IVAL(p,SME_SHAREMODE_OFFSET), fname)); continue; } share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET); @@ -492,7 +492,7 @@ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); { char *p = base + (i*SMF_ENTRY_LENGTH); - SIVAL(p,SME_PID_OFFSET,share_array[i].pid); + SIVAL(p,SME_PID_OFFSET,(uint32)share_array[i].pid); SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); @@ -513,8 +513,18 @@ mode file %s (%s)\n", fname, strerror(errno))); return 0; } /* Now truncate the file at this point. */ +#ifdef FTRUNCATE_NEEDS_ROOT + become_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + if(sys_ftruncate(fd, (SMB_OFF_T)newsize)!= 0) { +#ifdef FTRUNCATE_NEEDS_ROOT + int saved_errno = errno; + unbecome_root(False); + errno = saved_errno; +#endif /* FTRUNCATE_NEEDS_ROOT */ + DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); if(*old_shares) @@ -526,6 +536,10 @@ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); } } +#ifdef FTRUNCATE_NEEDS_ROOT + unbecome_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + if(buf) free(buf); @@ -547,7 +561,7 @@ static void slow_del_share_mode(int token, files_struct *fsp) int num_entries; int newsize; int i; - int pid; + pid_t pid; BOOL deleted = False; BOOL new_file; @@ -608,7 +622,7 @@ for share file %s\n", num_entries, fname)); if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) || (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || - (IVAL(p,SME_PID_OFFSET) != pid)) + (((pid_t)IVAL(p,SME_PID_OFFSET)) != pid)) continue; DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", @@ -665,14 +679,30 @@ mode file %s (%s)\n", fname, strerror(errno))); } /* Now truncate the file at this point. */ +#ifdef FTRUNCATE_NEEDS_ROOT + become_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + if(sys_ftruncate(fd, (SMB_OFF_T)newsize) != 0) { +#ifdef FTRUNCATE_NEEDS_ROOT + int saved_errno = errno; + unbecome_root(False); + errno = saved_errno; +#endif /* FTRUNCATE_NEEDS_ROOT */ + + DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); if(buf) free(buf); return; } + +#ifdef FTRUNCATE_NEEDS_ROOT + unbecome_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + } /******************************************************************* @@ -682,7 +712,7 @@ static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 { pstring fname; int fd = (int)token; - int pid = (int)getpid(); + pid_t pid = getpid(); SMB_STRUCT_STAT sb; char *buf; int num_entries; @@ -692,7 +722,7 @@ static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 share_name(fsp->conn, fsp->fd_ptr->dev, fsp->fd_ptr->inode, fname); - if(fsp->conn->vfs_ops.fstat_file(fd, &sb) != 0) + if(sys_fstat(fd, &sb) != 0) { DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", fname)); @@ -759,15 +789,17 @@ deleting it.\n", fname)); { /* New file - just use a single_entry. */ if((buf = (char *)malloc(SMF_HEADER_LENGTH + - strlen(fsp->fsp_name) + 1 + SMF_ENTRY_LENGTH)) == NULL) + strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2 + SMF_ENTRY_LENGTH)) == NULL) { DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); return False; } SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); - SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fsp->fsp_name) + 1); - pstrcpy(buf + SMF_HEADER_LENGTH, fsp->fsp_name); + SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2); + pstrcpy(buf + SMF_HEADER_LENGTH, fsp->conn->connectpath); + pstrcat(buf + SMF_HEADER_LENGTH, "/"); + pstrcat(buf + SMF_HEADER_LENGTH, fsp->fsp_name); } num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); @@ -776,7 +808,7 @@ deleting it.\n", fname)); SIVAL(p,SME_SEC_OFFSET,fsp->open_time.tv_sec); SIVAL(p,SME_USEC_OFFSET,fsp->open_time.tv_usec); SIVAL(p,SME_SHAREMODE_OFFSET,fsp->share_mode); - SIVAL(p,SME_PID_OFFSET,pid); + SIVAL(p,SME_PID_OFFSET,(uint32)pid); SSVAL(p,SME_PORT_OFFSET,port); SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); @@ -806,8 +838,19 @@ deleting it (%s).\n",fname, strerror(errno))); /* Now truncate the file at this point - just for safety. */ +#ifdef FTRUNCATE_NEEDS_ROOT + become_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + if(sys_ftruncate(fd, (SMB_OFF_T)(header_size + (SMF_ENTRY_LENGTH*num_entries)))!= 0) { + +#ifdef FTRUNCATE_NEEDS_ROOT + int saved_errno = errno; + unbecome_root(False); + errno = saved_errno; +#endif /* FTRUNCATE_NEEDS_ROOT */ + DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), strerror(errno))); @@ -816,11 +859,15 @@ mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entr return False; } +#ifdef FTRUNCATE_NEEDS_ROOT + unbecome_root(False); +#endif /* FTRUNCATE_NEEDS_ROOT */ + if(buf) free(buf); DEBUG(3,("set_share_mode: Created share file %s with \ -mode 0x%X pid=%d\n",fname,fsp->share_mode,pid)); +mode 0x%X pid=%d\n",fname,fsp->share_mode,(int)pid)); return True; } @@ -840,7 +887,7 @@ static BOOL slow_mod_share_entry(int token, files_struct *fsp, int num_entries; int fsize; int i; - int pid; + pid_t pid; BOOL found = False; BOOL new_file; share_mode_entry entry; @@ -898,7 +945,7 @@ for share file %s\n", num_entries, fname)); if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) || (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || - (IVAL(p,SME_PID_OFFSET) != pid)) + (((pid_t)IVAL(p,SME_PID_OFFSET)) != pid)) continue; DEBUG(5,("slow_mod_share_entry: Calling generic function to modify entry number %d (of %d) \ @@ -909,12 +956,12 @@ from the share file %s\n", i, num_entries, fname)); * the generic function with the given parameter. */ - entry.pid = IVAL(p,SME_PID_OFFSET); + entry.pid = (pid_t)IVAL(p,SME_PID_OFFSET); entry.op_port = SVAL(p,SME_PORT_OFFSET); entry.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); entry.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - entry.time.tv_sec = IVAL(p,SME_SEC_OFFSET) - entry.time.tv_sec = IVAL(p,SME_USEC_OFFSET); + entry.time.tv_sec = IVAL(p,SME_SEC_OFFSET); + entry.time.tv_usec = IVAL(p,SME_USEC_OFFSET); (*mod_fn)( &entry, fsp->fd_ptr->dev, fsp->fd_ptr->inode, param); @@ -922,12 +969,12 @@ from the share file %s\n", i, num_entries, fname)); * Now copy any changes the function made back into the buffer. */ - SIVAL(p,SME_PID_OFFSET, entry.pid) + SIVAL(p,SME_PID_OFFSET, (uint32)entry.pid); SSVAL(p,SME_PORT_OFFSET,entry.op_port); SSVAL(p,SME_OPLOCK_TYPE_OFFSET,entry.op_type); SIVAL(p,SME_SHAREMODE_OFFSET,entry.share_mode); - SIVAL(p,SME_SEC_OFFSET,entry.time.tv_sec) - SIVAL(p,SME_USEC_OFFSET,entry.time.tv_sec); + SIVAL(p,SME_SEC_OFFSET,entry.time.tv_sec); + SIVAL(p,SME_USEC_OFFSET,entry.time.tv_usec); found = True; break; @@ -968,7 +1015,7 @@ mode file %s (%s)\n", fname, strerror(errno))); /******************************************************************* call the specified function on each entry under management by the -share ode system +share mode system ********************************************************************/ static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) { @@ -1030,12 +1077,11 @@ static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) SVAL(buf,SMF_FILENAME_LEN_OFFSET); for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) { char *p = base + (i*SMF_ENTRY_LENGTH); - e.pid = IVAL(p,SME_PID_OFFSET); + e.pid = (pid_t)IVAL(p,SME_PID_OFFSET); e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); e.time.tv_sec = IVAL(p,SME_SEC_OFFSET); e.time.tv_usec = IVAL(p,SME_USEC_OFFSET); e.op_port = SVAL(p,SME_PORT_OFFSET); - e.pid = SVAL(p,SME_PID_OFFSET); e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); if (process_exists(e.pid)) { diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c index 435c0d4c78..bf2802c9ec 100644 --- a/source3/locking/shmem.c +++ b/source3/locking/shmem.c @@ -23,7 +23,7 @@ #include "includes.h" -#ifdef HAVE_SHARED_MMAP +#ifdef USE_SHARED_MMAP extern int DEBUGLEVEL; diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index d4e814d26f..04a2e74460 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -23,7 +23,7 @@ #include "includes.h" -#ifdef HAVE_SYSV_IPC +#ifdef USE_SYSV_IPC extern int DEBUGLEVEL; @@ -33,7 +33,11 @@ extern int DEBUGLEVEL; #define SHM_MAGIC 0x53484100 #define SHM_VERSION 2 +#ifdef SHM_R #define IPC_PERMS ((SHM_R | SHM_W) | (SHM_R>>3) | (SHM_R>>6)) +#else +#define IPC_PERMS 0644 +#endif #ifdef SECURE_SEMAPHORES @@ -320,7 +324,7 @@ static BOOL shm_free(int offset) shm_header_p->consistent = False; DEBUG(6,("shm_free : freeing %d bytes at offset %d\n", - header_p->size*CellSize,offset)); + (int)(header_p->size*CellSize),(int)offset)); /* zero the area being freed - this allows us to find bugs faster */ memset(shm_offset2addr(offset), 0, header_p->size*CellSize); @@ -524,6 +528,7 @@ static struct shmem_ops shmops = { /******************************************************************* open the shared memory ******************************************************************/ + struct shmem_ops *sysv_shm_open(int ronly) { BOOL other_processes; @@ -531,7 +536,9 @@ struct shmem_ops *sysv_shm_open(int ronly) struct semid_ds sem_ds; union semun su; int i; - int pid; + pid_t pid; + struct passwd *root_pwd = sys_getpwuid((uid_t)0); + gid_t root_gid = root_pwd ? root_pwd->pw_gid : (gid_t)0; read_only = ronly; @@ -589,15 +596,16 @@ struct shmem_ops *sysv_shm_open(int ronly) hash_size = sem_ds.sem_nsems-1; if (!read_only) { - if (sem_ds.sem_perm.cuid != 0 || sem_ds.sem_perm.cgid != 0) { - DEBUG(0,("ERROR: root did not create the semaphore\n")); + if (sem_ds.sem_perm.cuid != 0 || ((sem_ds.sem_perm.cgid != root_gid) && (sem_ds.sem_perm.cgid != 0))) { + DEBUG(0,("ERROR: root did not create the semaphore: semgid=%u, rootgid=%u\n", + (unsigned int)sem_ds.sem_perm.cgid, (unsigned int)root_gid)); return NULL; } if (semctl(sem_id, 0, GETVAL, su) == 0 && - !process_exists((pid=semctl(sem_id, 0, GETPID, su)))) { + !process_exists((pid=(pid_t)semctl(sem_id, 0, GETPID, su)))) { DEBUG(0,("WARNING: clearing global IPC lock set by dead process %d\n", - pid)); + (int)pid)); su.val = 1; if (semctl(sem_id, 0, SETVAL, su) != 0) { DEBUG(0,("ERROR: Failed to clear global lock. Error was %s\n", @@ -620,9 +628,9 @@ struct shmem_ops *sysv_shm_open(int ronly) for (i=1;i Date: Tue, 21 Dec 1999 09:25:59 +0000 Subject: converted all our existing shared memory code to use a tdb database instead of either sysv or mmap shared memory or lock files. this means we can now completely remove locking_shm.c locking_slow.c shmem.c shmem_sysv.c and lots of other things also got simpler locking.c got a bit larger, but is much better compartmentalised now (This used to be commit e48c2d9937eea0667b8cd3332e49c06314ef31e7) --- source3/locking/locking.c | 423 ++++++++++----- source3/locking/locking_shm.c | 711 ------------------------- source3/locking/locking_slow.c | 1144 ---------------------------------------- source3/locking/shmem.c | 963 --------------------------------- source3/locking/shmem_sysv.c | 724 ------------------------- 5 files changed, 295 insertions(+), 3670 deletions(-) delete mode 100644 source3/locking/locking_shm.c delete mode 100644 source3/locking/locking_slow.c delete mode 100644 source3/locking/shmem.c delete mode 100644 source3/locking/shmem_sysv.c (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 012d954e50..fc4ce725c5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1,8 +1,8 @@ /* Unix SMB/Netbios implementation. - Version 1.9. + Version 3.0 Locking functions - Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Andrew Tridgell 1992-1999 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 @@ -29,42 +29,43 @@ September 1997. Jeremy Allison (jallison@whistle.com). Added oplock support. + rewrtten completely to use new tdb code. Tridge, Dec '99 */ #include "includes.h" extern int DEBUGLEVEL; -static struct share_ops *share_ops; +/* the locking database handle */ +static TDB_CONTEXT *tdb; /**************************************************************************** Utility function to map a lock type correctly depending on the real open mode of a file. ****************************************************************************/ - -static int map_lock_type( files_struct *fsp, int lock_type) +static int map_lock_type(files_struct *fsp, int lock_type) { - if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) { - /* - * Many UNIX's cannot get a write lock on a file opened read-only. - * Win32 locking semantics allow this. - * Do the best we can and attempt a read-only lock. - */ - DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n")); - return F_RDLCK; - } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { - /* - * Ditto for read locks on write only files. - */ - DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n")); - return F_WRLCK; - } - - /* - * This return should be the most normal, as we attempt - * to always open files read/write. - */ - - return lock_type; + if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) { + /* + * Many UNIX's cannot get a write lock on a file opened read-only. + * Win32 locking semantics allow this. + * Do the best we can and attempt a read-only lock. + */ + DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n")); + return F_RDLCK; + } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { + /* + * Ditto for read locks on write only files. + */ + DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n")); + return F_WRLCK; + } + + /* + * This return should be the most normal, as we attempt + * to always open files read/write. + */ + + return lock_type; } /**************************************************************************** @@ -74,7 +75,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, SMB_OFF_T count,SMB_OFF_T offset, int lock_type) { int snum = SNUM(conn); - + if (count == 0) return(False); @@ -98,30 +99,30 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, SMB_OFF_T count,SMB_OFF_T offset,int lock_type, int *eclass,uint32 *ecode) { - BOOL ok = False; - - if (!lp_locking(SNUM(conn))) - return(True); - - if (count == 0) { - *eclass = ERRDOS; - *ecode = ERRnoaccess; - return False; - } - - DEBUG(10,("do_lock: lock type %d start=%.0f len=%.0f requested for file %s\n", - lock_type, (double)offset, (double)count, fsp->fsp_name )); - - if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, - map_lock_type(fsp,lock_type)); - - if (!ok) { - *eclass = ERRDOS; - *ecode = ERRlock; - return False; - } - return True; /* Got lock */ + BOOL ok = False; + + if (!lp_locking(SNUM(conn))) + return(True); + + if (count == 0) { + *eclass = ERRDOS; + *ecode = ERRnoaccess; + return False; + } + + DEBUG(10,("do_lock: lock type %d start=%.0f len=%.0f requested for file %s\n", + lock_type, (double)offset, (double)count, fsp->fsp_name )); + + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) + ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, + map_lock_type(fsp,lock_type)); + + if (!ok) { + *eclass = ERRDOS; + *ecode = ERRlock; + return False; + } + return True; /* Got lock */ } @@ -131,46 +132,38 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, BOOL do_unlock(files_struct *fsp,connection_struct *conn, SMB_OFF_T count,SMB_OFF_T offset,int *eclass,uint32 *ecode) { - BOOL ok = False; - - if (!lp_locking(SNUM(conn))) - return(True); - - DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", - (double)offset, (double)count, fsp->fsp_name )); - - if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); + BOOL ok = False; + + if (!lp_locking(SNUM(conn))) + return(True); + + DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", + (double)offset, (double)count, fsp->fsp_name )); + + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) + ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); - if (!ok) { - *eclass = ERRDOS; - *ecode = ERRlock; - return False; - } - return True; /* Did unlock */ + if (!ok) { + *eclass = ERRDOS; + *ecode = ERRlock; + return False; + } + return True; /* Did unlock */ } /**************************************************************************** Initialise the locking functions. ****************************************************************************/ - BOOL locking_init(int read_only) { - if (share_ops) - return True; + if (tdb) return True; -#ifdef FAST_SHARE_MODES - share_ops = locking_shm_init(read_only); - if (!share_ops && read_only && (getuid() == 0)) { - /* this may be the first time the share modes code has - been run. Initialise it now by running it read-write */ - share_ops = locking_shm_init(0); - } -#else - share_ops = locking_slow_init(read_only); -#endif + tdb = tdb_open(lock_path("locking.tdb"), + 0, + read_only?O_RDONLY:O_RDWR|O_CREAT, + 0644); - if (!share_ops) { + if (!tdb) { DEBUG(0,("ERROR: Failed to initialise share modes\n")); return False; } @@ -181,110 +174,271 @@ BOOL locking_init(int read_only) /******************************************************************* Deinitialize the share_mode management. ******************************************************************/ - BOOL locking_end(void) { - if (share_ops) - return share_ops->stop_mgmt(); + if (tdb && tdb_close(tdb) != 0) return False; return True; } +/******************************************************************* + form a static locking key for a dev/inode pair +******************************************************************/ +static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) +{ + static struct locking_key key; + TDB_DATA kbuf; + key.dev = dev; + key.inode = inode; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + return kbuf; +} +static TDB_DATA locking_key_fsp(files_struct *fsp) +{ + return locking_key(fsp->fd_ptr->dev, fsp->fd_ptr->inode); +} /******************************************************************* Lock a hash bucket entry. ******************************************************************/ BOOL lock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, int *ptok) + SMB_DEV_T dev, SMB_INO_T inode) { - return share_ops->lock_entry(conn, dev, inode, ptok); + return tdb_lockchain(tdb, locking_key(dev, inode)) == 0; } /******************************************************************* Unlock a hash bucket entry. ******************************************************************/ BOOL unlock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, int token) + SMB_DEV_T dev, SMB_INO_T inode) { - return share_ops->unlock_entry(conn, dev, inode, token); + return tdb_unlockchain(tdb, locking_key(dev, inode)) == 0; } /******************************************************************* Get all share mode entries for a dev/inode pair. ********************************************************************/ int get_share_modes(connection_struct *conn, - int token, SMB_DEV_T dev, SMB_INO_T inode, + SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry **shares) { - return share_ops->get_entries(conn, token, dev, inode, shares); + TDB_DATA dbuf; + struct locking_data *data; + int ret; + + dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + if (!dbuf.dptr) return 0; + + data = (struct locking_data *)dbuf.dptr; + ret = data->num_share_mode_entries; + *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares)); + free(dbuf.dptr); + + if (! *shares) return 0; + + return ret; +} + +/******************************************************************* + Del the share mode of a file for this process +********************************************************************/ +void del_share_mode(files_struct *fsp) +{ + TDB_DATA dbuf; + struct locking_data *data; + int i, del_count=0; + share_mode_entry *shares; + pid_t pid = getpid(); + + /* read in the existing share modes */ + dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); + if (!dbuf.dptr) return; + + data = (struct locking_data *)dbuf.dptr; + shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); + + /* find any with our pid and delete it by overwriting with the rest of the data + from the record */ + for (i=0;inum_share_mode_entries;) { + if (shares[i].pid == pid && + memcmp(&shares[i].time, + &fsp->open_time,sizeof(struct timeval)) == 0) { + data->num_share_mode_entries--; + memmove(&shares[i], &shares[i+1], + dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); + del_count++; + } else { + i++; + } + } + + /* the record has shrunk a bit */ + dbuf.dsize -= del_count * sizeof(*shares); + + /* store it back in the database */ + tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + + free(dbuf.dptr); } /******************************************************************* - Del the share mode of a file. +fill a share mode entry ********************************************************************/ -void del_share_mode(int token, files_struct *fsp) +static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type) { - share_ops->del_entry(token, fsp); + share_mode_entry *e = (share_mode_entry *)p; + e->pid = getpid(); + e->share_mode = fsp->share_mode; + e->op_port = port; + e->op_type = op_type; + memcpy((char *)&e->time, (char *)&fsp->open_time, sizeof(struct timeval)); } /******************************************************************* Set the share mode of a file. Return False on fail, True on success. ********************************************************************/ -BOOL set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type) +BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) { - return share_ops->set_entry(token, fsp, port, op_type); + TDB_DATA dbuf; + struct locking_data *data; + share_mode_entry *shares; + char *p=NULL; + int size; + + /* read in the existing share modes if any */ + dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); + if (!dbuf.dptr) { + /* we'll need to create a new record */ + pstring fname; + + pstrcpy(fname, fsp->conn->connectpath); + pstrcat(fname, "/"); + pstrcat(fname, fsp->fsp_name); + + size = sizeof(*data) + sizeof(*shares) + strlen(fname) + 1; + p = (char *)malloc(size); + data = (struct locking_data *)p; + shares = (share_mode_entry *)(p + sizeof(*data)); + data->num_share_mode_entries = 1; + pstrcpy(p + sizeof(*data) + sizeof(*shares), fname); + fill_share_mode(p + sizeof(*data), fsp, port, op_type); + dbuf.dptr = p; + dbuf.dsize = size; + tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + free(p); + return True; + } + + /* we're adding to an existing entry - this is a bit fiddly */ + data = (struct locking_data *)dbuf.dptr; + shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); + + data->num_share_mode_entries++; + size = dbuf.dsize + sizeof(*shares); + p = malloc(size); + memcpy(p, dbuf.dptr, sizeof(*data)); + fill_share_mode(p + sizeof(*data), fsp, port, op_type); + memcpy(p + sizeof(*data) + sizeof(*shares), dbuf.dptr + sizeof(*data), + dbuf.dsize - sizeof(*data)); + free(dbuf.dptr); + dbuf.dptr = p; + dbuf.dsize = size; + tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + free(p); + return True; } + +/******************************************************************* +a generic in-place modification call for share mode entries +********************************************************************/ +static BOOL mod_share_mode(files_struct *fsp, + void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), + void *param) +{ + TDB_DATA dbuf; + struct locking_data *data; + int i; + share_mode_entry *shares; + pid_t pid = getpid(); + int need_store=0; + + /* read in the existing share modes */ + dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); + if (!dbuf.dptr) return False; + + data = (struct locking_data *)dbuf.dptr; + shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); + + /* find any with our pid and call the supplied function */ + for (i=0;inum_share_mode_entries;i++) { + if (pid == shares[i].pid && + shares[i].share_mode == fsp->share_mode && + memcmp(&shares[i].time, + &fsp->open_time,sizeof(struct timeval)) == 0) { + mod_fn(&shares[i], fsp->fd_ptr->dev, fsp->fd_ptr->inode, param); + need_store=1; + } + } + + /* if the mod fn was called then store it back */ + if (need_store) { + tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + } + + free(dbuf.dptr); + return need_store; +} + + /******************************************************************* Static function that actually does the work for the generic function below. ********************************************************************/ - static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, void *param) { - DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode )); - /* Delete the oplock info. */ - entry->op_port = 0; - entry->op_type = NO_OPLOCK; + DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode )); + /* Delete the oplock info. */ + entry->op_port = 0; + entry->op_type = NO_OPLOCK; } /******************************************************************* Remove an oplock port and mode entry from a share mode. ********************************************************************/ - -BOOL remove_share_oplock(int token, files_struct *fsp) +BOOL remove_share_oplock(files_struct *fsp) { - return share_ops->mod_entry(token, fsp, remove_share_oplock_fn, NULL); + return mod_share_mode(fsp, remove_share_oplock_fn, NULL); } /******************************************************************* Static function that actually does the work for the generic function below. ********************************************************************/ - static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, void *param) { - DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode )); - entry->op_type = LEVEL_II_OPLOCK; + DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode )); + entry->op_type = LEVEL_II_OPLOCK; } /******************************************************************* Downgrade a oplock type from exclusive to level II. ********************************************************************/ - -BOOL downgrade_share_oplock(int token, files_struct *fsp) +BOOL downgrade_share_oplock(files_struct *fsp) { - return share_ops->mod_entry(token, fsp, downgrade_share_oplock_fn, NULL); + return mod_share_mode(fsp, downgrade_share_oplock_fn, NULL); } + /******************************************************************* Static function that actually does the work for the generic function below. ********************************************************************/ - struct mod_val { int new_share_mode; uint16 new_oplock; @@ -308,33 +462,46 @@ static void modify_share_mode_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO Modify a share mode on a file. Used by the delete open file code. Return False on fail, True on success. ********************************************************************/ - -BOOL modify_share_mode(int token, files_struct *fsp, int new_mode, uint16 new_oplock) +BOOL modify_share_mode(files_struct *fsp, int new_mode, uint16 new_oplock) { struct mod_val mv; mv.new_share_mode = new_mode; - mv.new_oplock = new_oplock; + mv.new_oplock = new_oplock; - return share_ops->mod_entry(token, fsp, modify_share_mode_fn, (void *)&mv); + return mod_share_mode(fsp, modify_share_mode_fn, (void *)&mv); } -/******************************************************************* - Call the specified function on each entry under management by the - share mode system. -********************************************************************/ +static void (*traverse_callback)(share_mode_entry *, char *); -int share_mode_forall(void (*fn)(share_mode_entry *, char *)) +/**************************************************************************** +traverse the whole database with this function, calling traverse_callback +on each share mode +****************************************************************************/ +int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) { - if (!share_ops) return 0; - return share_ops->forall(fn); + struct locking_data *data; + share_mode_entry *shares; + char *name; + int i; + + data = (struct locking_data *)dbuf.dptr; + shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); + name = dbuf.dptr + sizeof(*data) + data->num_share_mode_entries*sizeof(*shares); + + for (i=0;inum_share_mode_entries;i++) { + traverse_callback(&shares[i], name); + } + return 0; } /******************************************************************* - Dump the state of the system. + Call the specified function on each entry under management by the + share mode system. ********************************************************************/ - -void share_status(FILE *f) +int share_mode_forall(void (*fn)(share_mode_entry *, char *)) { - share_ops->status(f); + if (!tdb) return 0; + traverse_callback = fn; + return tdb_traverse(tdb, traverse_fn); } diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c deleted file mode 100644 index 174ad73e97..0000000000 --- a/source3/locking/locking_shm.c +++ /dev/null @@ -1,711 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - shared memory locking implementation - Copyright (C) Andrew Tridgell 1992-1998 - - 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) -*/ - -#include "includes.h" - -#ifdef FAST_SHARE_MODES - -extern int DEBUGLEVEL; - -static struct shmem_ops *shmops; - -/* share mode record pointed to in shared memory hash bucket */ -typedef struct -{ - int next_offset; /* offset of next record in chain from hash bucket */ - int locking_version; - SMB_DEV_T st_dev; - SMB_INO_T st_ino; - int num_share_mode_entries; - int 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 -{ - int next_share_mode_entry; - share_mode_entry e; -} shm_share_mode_entry; - -static int read_only; - - -/* Conversion to hash entry index from device and inode numbers. */ -#define HASH_ENTRY(dev,ino) ((unsigned int)(((dev) ^ (ino)) % shmops->hash_size())) - - -/******************************************************************* - deinitialize the shared memory for share_mode management - ******************************************************************/ -static BOOL shm_stop_share_mode_mgmt(void) -{ - return shmops->shm_close(); -} - -/******************************************************************* - lock a hash bucket entry in shared memory for share_mode management - ******************************************************************/ -static BOOL shm_lock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, int *ptok) -{ - *ptok = 0; /* For purify... */ - return shmops->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(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, int token) -{ - return shmops->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(connection_struct *conn, - int token, SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry **old_shares) -{ - int *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; - - mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); - - if(mode_array[hash_entry] == 0) - { - DEBUG(5,("get_share_modes hash bucket %d empty\n", hash_entry)); - return 0; - } - - file_scanner_p = (share_mode_record *)shmops->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 *)shmops->offset2addr( - file_scanner_p->next_offset); - } - } - - if(!found) - { - DEBUG(5,("get_share_modes no entry for file dev = %x ino = %.0f\n", - (unsigned int)dev, (double)inode)); - return (0); - } - - if(file_scanner_p->locking_version != LOCKING_VERSION) - { - 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)); - - 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; - shmops->shm_free(shmops->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: malloc fail for size 0x%x!\n", (unsigned int)(num_entries * sizeof(share_mode_entry)))); - return 0; - } - } - - num_entries_copied = 0; - - entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr( - file_scanner_p->share_mode_entries); - entry_prev_p = entry_scanner_p; - while(entry_scanner_p) - { - pid_t 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; - entry_scanner_p = (shm_share_mode_entry*)shmops->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*) - shmops->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: entries=%d dev=%x ino=%.0f\n", - file_scanner_p->num_share_mode_entries, (unsigned int)dev, (double)inode)); - return 0; - } - - DEBUG(0,("get_share_modes: process %d no longer exists\n", (int)pid)); - - shmops->shm_free(shmops->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 Read share mode 0x%X pid=%d\n", - entry_scanner_p->e.share_mode, (int)entry_scanner_p->e.pid)); - entry_prev_p = entry_scanner_p; - entry_scanner_p = (shm_share_mode_entry *) - shmops->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: file with dev %x inode %.0f empty\n", - (unsigned int)dev, (double)inode)); - - 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; - shmops->shm_free(shmops->addr2offset(file_scanner_p)); - } - - DEBUG(5,("get_share_modes: file with dev %x inode %.0f -> %d entries\n", - (unsigned int)dev, (double)inode, num_entries_copied)); - - return(num_entries_copied); -} - -/******************************************************************* -del the share mode of a file. -********************************************************************/ -static void shm_del_share_mode(int token, files_struct *fsp) -{ - SMB_DEV_T dev; - SMB_INO_T inode; - int *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; - pid_t pid = getpid(); - - dev = fsp->fd_ptr->dev; - inode = fsp->fd_ptr->inode; - - hash_entry = HASH_ENTRY(dev, inode); - - mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); - - if(mode_array[hash_entry] == 0) - { - DEBUG(0,("PANIC ERROR:del_share_mode hash bucket %d empty\n", - hash_entry)); - return; - } - - file_scanner_p = (share_mode_record *)shmops->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 *) - shmops->offset2addr(file_scanner_p->next_offset); - } - } - - if(!found) - { - DEBUG(0,("ERROR: del_share_mode no entry for dev %x inode %.0f\n", - (unsigned int)dev, (double)inode)); - return; - } - - if(file_scanner_p->locking_version != LOCKING_VERSION) - { - 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)); - - 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; - shmops->shm_free(shmops->addr2offset(file_scanner_p)); - return; - } - - found = False; - entry_scanner_p = (shm_share_mode_entry*)shmops->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, - &fsp->open_time,sizeof(struct timeval)) == 0) ) - { - found = True; - break; - } - else - { - entry_prev_p = entry_scanner_p; - entry_scanner_p = (shm_share_mode_entry *) - shmops->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 Deleting share mode entry dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode)); - - 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; - shmops->shm_free(shmops->addr2offset(entry_scanner_p)); - - /* PARANOIA TEST */ - if(file_scanner_p->num_share_mode_entries < 0) - { - DEBUG(0,("PANIC ERROR:del_share_mode num_share_mode_entries=%d\n", - file_scanner_p->num_share_mode_entries)); - 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 num entries = 0, deleting share_mode dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode)); - - 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; - shmops->shm_free(shmops->addr2offset(file_scanner_p)); - } - } - else - { - DEBUG(0,("ERROR: del_share_modes No share mode dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode)); - } -} - -/******************************************************************* -set the share mode of a file. Return False on fail, True on success. -********************************************************************/ -static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type) -{ - SMB_DEV_T dev; - SMB_INO_T inode; - int *mode_array; - unsigned int hash_entry; - share_mode_record *file_scanner_p; - shm_share_mode_entry *new_entry_p; - int new_entry_offset; - BOOL found = False; - - dev = fsp->fd_ptr->dev; - inode = fsp->fd_ptr->inode; - - hash_entry = HASH_ENTRY(dev, inode); - - mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); - - file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]); - - 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 *) - shmops->offset2addr(file_scanner_p->next_offset); - } - } - - if(!found) - { - /* We must create a share_mode_record */ - share_mode_record *new_mode_p = NULL; - int new_offset = shmops->shm_alloc(sizeof(share_mode_record) + - strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2); - if(new_offset == 0) { - DEBUG(0,("ERROR:set_share_mode shmops->shm_alloc fail!\n")); - return False; - } - new_mode_p = shmops->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 = 0; - pstrcpy(new_mode_p->file_name, fsp->conn->connectpath); - pstrcat(new_mode_p->file_name, "/"); - pstrcat(new_mode_p->file_name, fsp->fsp_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: Created share record for %s (dev %x inode %.0f)\n", - fsp->fsp_name, (unsigned int)dev, (double)inode)); - } - - /* Now create the share mode entry */ - new_entry_offset = shmops->shm_alloc(sizeof(shm_share_mode_entry)); - if(new_entry_offset == 0) { - int delete_offset = mode_array[hash_entry]; - DEBUG(0,("ERROR:set_share_mode: shmops->shm_alloc fail 1!\n")); - /* Unlink the damaged record */ - mode_array[hash_entry] = file_scanner_p->next_offset; - /* And delete it */ - shmops->shm_free( delete_offset ); - return False; - } - - new_entry_p = shmops->offset2addr(new_entry_offset); - - new_entry_p->e.pid = getpid(); - new_entry_p->e.share_mode = fsp->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 *)&fsp->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 num_share_mode_entries=%d\n", - file_scanner_p->num_share_mode_entries)); - return False; - } - - /* Increment the share_mode_entries counter */ - file_scanner_p->num_share_mode_entries += 1; - - DEBUG(3,("set_share_mode: Created share entry for %s with mode 0x%X pid=%d\n", - fsp->fsp_name, fsp->share_mode, (int)new_entry_p->e.pid)); - - return(True); -} - -/******************************************************************* - Call a generic modify function for a share mode entry. -********************************************************************/ - -static BOOL shm_mod_share_entry(int token, files_struct *fsp, - void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), - void *param) -{ - SMB_DEV_T dev; - SMB_INO_T inode; - int *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; - BOOL found = False; - pid_t pid = getpid(); - - dev = fsp->fd_ptr->dev; - inode = fsp->fd_ptr->inode; - - hash_entry = HASH_ENTRY(dev, inode); - - mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); - - if(mode_array[hash_entry] == 0) - { - DEBUG(0,("PANIC ERROR:modify_share_entry: hash bucket %d empty\n", - hash_entry)); - return False; - } - - file_scanner_p = (share_mode_record *)shmops->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 *) - shmops->offset2addr(file_scanner_p->next_offset); - } - } - - if(!found) - { - DEBUG(0,("ERROR:modify_share_entry: no entry found for dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode)); - return False; - } - - if(file_scanner_p->locking_version != LOCKING_VERSION) - { - DEBUG(0,("ERROR: modify_share_entry: Deleting old share mode v1=%d dev=%x ino=%.0f\n", - file_scanner_p->locking_version, (unsigned int)dev, (double)inode)); - - 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; - shmops->shm_free(shmops->addr2offset(file_scanner_p)); - return False; - } - - found = False; - entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr( - file_scanner_p->share_mode_entries); - while(entry_scanner_p) - { - if( (pid == entry_scanner_p->e.pid) && - (entry_scanner_p->e.share_mode == fsp->share_mode) && - (memcmp(&entry_scanner_p->e.time, - &fsp->open_time,sizeof(struct timeval)) == 0) ) - { - /* - * Call the generic function with the given parameter. - */ - - DEBUG(5,("modify_share_entry: Calling generic function to modify entry for dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode)); - - (*mod_fn)( &entry_scanner_p->e, dev, inode, param); - found = True; - break; - } - else - { - entry_scanner_p = (shm_share_mode_entry *) - shmops->offset2addr(entry_scanner_p->next_share_mode_entry); - } - } - - if(!found) - { - DEBUG(0,("ERROR: modify_share_entry: No entry found for dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode)); - return False; - } - - return True; -} - -/******************************************************************* -call the specified function on each entry under management by the -share mode system -********************************************************************/ -static int shm_share_forall(void (*fn)(share_mode_entry *, char *)) -{ - int i, count=0; - int *mode_array; - share_mode_record *file_scanner_p; - - mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off()); - - for( i = 0; i < shmops->hash_size(); i++) { - shmops->lock_hash_entry(i); - if(mode_array[i] == 0) { - shmops->unlock_hash_entry(i); - continue; - } - - file_scanner_p = (share_mode_record *)shmops->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 *) - shmops->offset2addr(file_scanner_p->share_mode_entries); - - while(entry_scanner_p != 0) { - - if (process_exists(entry_scanner_p->e.pid)) { - fn(&entry_scanner_p->e, - file_scanner_p->file_name); - count++; - } - - entry_scanner_p = - (shm_share_mode_entry *) - shmops->offset2addr( - entry_scanner_p->next_share_mode_entry); - } /* end while entry_scanner_p */ - file_scanner_p = (share_mode_record *) - shmops->offset2addr(file_scanner_p->next_offset); - } /* end while file_scanner_p */ - shmops->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; - - shmops->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_mod_share_entry, - shm_share_forall, - shm_share_status, -}; - -/******************************************************************* - initialize the shared memory for share_mode management - ******************************************************************/ -struct share_ops *locking_shm_init(int ronly) -{ - read_only = ronly; - -#ifdef USE_SYSV_IPC - shmops = sysv_shm_open(read_only); - if (shmops) return &share_ops; -#endif - -#ifdef USE_SHARED_MMAP - shmops = smb_shm_open(read_only); - if (shmops) return &share_ops; -#endif - - return NULL; -} - -#else - int locking_shm_dummy_procedure(void) -{return 0;} -#endif /* FAST_SHARE_MODES */ diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c deleted file mode 100644 index 58673d2707..0000000000 --- a/source3/locking/locking_slow.c +++ /dev/null @@ -1,1144 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - slow (lockfile) locking implementation - Copyright (C) Andrew Tridgell 1992-1998 - - 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) -*/ - -#include "includes.h" - -#ifndef FAST_SHARE_MODES - -extern int DEBUGLEVEL; - -/* - * 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 - -/* we need world read for smbstatus to function correctly */ -#ifdef SECURE_SHARE_MODES -#define SHARE_FILE_MODE 0600 -#else -#define SHARE_FILE_MODE 0644 -#endif - -static int read_only; - -/******************************************************************* - deinitialize share_mode management - ******************************************************************/ -static BOOL slow_stop_share_mode_mgmt(void) -{ - return True; -} - - -/******************************************************************* - name a share file - ******************************************************************/ -static BOOL share_name(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, char *name) -{ - int len; - pstrcpy(name,lp_lockdir()); - trim_string(name,"","/"); - if (!*name) return(False); - len = strlen(name); - name += len; - -#ifdef LARGE_SMB_INO_T - slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%.0f",(unsigned int)dev,(double)inode); -#else /* LARGE_SMB_INO_T */ - slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%lu",(unsigned int)dev,(unsigned long)inode); -#endif /* LARGE_SMB_INO_T */ - return(True); -} - -/******************************************************************* -Force a share file to be deleted. -********************************************************************/ -static int delete_share_file(connection_struct *conn, char *fname ) -{ - if (read_only) return -1; - - /* the share file could be owned by anyone, so do this as root */ - become_root(False); - - if(unlink(fname) != 0) - { - DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", - fname, strerror(errno))); - } - else - { - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); - } - - /* return to our previous privilege level */ - unbecome_root(False); - - return 0; -} - -/******************************************************************* - lock a share mode file. - ******************************************************************/ -static BOOL slow_lock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, int *ptok) -{ - pstring fname; - int fd; - int ret = True; - - *ptok = (int)-1; - - if(!share_name(conn, dev, inode, fname)) - return False; - - if (read_only) return True; - - /* we need to do this as root */ - become_root(False); - - { - BOOL gotlock = False; - /* - * There was a race condition in the original slow share mode code. - * A smbd could open a share mode file, and before getting - * the lock, another smbd could delete the last entry for - * the share mode file and delete the file entry from the - * directory. Thus this smbd would be left with a locked - * share mode fd attached to a file that no longer had a - * directory entry. Thus another smbd would think that - * there were no outstanding opens on the file. To fix - * this we now check we can do a stat() call on the filename - * before allowing the lock to proceed, and back out completely - * and try the open again if we cannot. - * Jeremy Allison (jallison@whistle.com). - */ - - do - { - SMB_STRUCT_STAT dummy_stat; - - fd = sys_open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT), SHARE_FILE_MODE); - - if(fd < 0) - { - DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n", - fname, strerror(errno))); - ret = False; - break; - } - - /* At this point we have an open fd to the share mode file. - Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", - fname, strerror(errno))); - close(fd); - ret = False; - break; - } - - /* - * If we cannot stat the filename, the file was deleted between - * the open and the lock call. Back out and try again. - */ - - if(sys_stat(fname, &dummy_stat)!=0) - { - DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", - fname, strerror(errno))); - close(fd); - } - else - gotlock = True; - } while(!gotlock); - - /* - * We have to come here if any of the above calls fail - * as we don't want to return and leave ourselves running - * as root ! - */ - } - - *ptok = (int)fd; - - /* return to our previous privilege level */ - unbecome_root(False); - - return ret; -} - -/******************************************************************* - unlock a share mode file. - ******************************************************************/ -static BOOL slow_unlock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, int token) -{ - int fd = token; - int ret = True; - SMB_STRUCT_STAT sb; - pstring fname; - - if (read_only) return True; - - /* Fix for zero length share files from - Gerald Werner */ - - share_name(conn, dev, inode, fname); - - /* get the share mode file size */ - if(sys_fstat((int)token, &sb) != 0) - { - DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - sb.st_size = 1; - ret = False; - } - - /* If the file was zero length, we must delete before - doing the unlock to avoid a race condition (see - the code in lock_share_mode_entry for details. - */ - - /* remove the share file if zero length */ - if(sb.st_size == 0) - delete_share_file(conn, fname); - - /* token is the fd of the open share mode file. */ - /* Unlock the first byte. */ - if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False) - { - DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - ret = False; - } - - close(fd); - return ret; -} - -/******************************************************************* -Read a share file into a buffer. -********************************************************************/ -static int read_share_file(connection_struct *conn, int fd, char *fname, char **out, BOOL *p_new_file) -{ - SMB_STRUCT_STAT sb; - char *buf; - SMB_OFF_T size; - - *out = 0; - *p_new_file = False; - - if(sys_fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - return -1; - } - - if(sb.st_size == 0) - { - *p_new_file = True; - return 0; - } - - /* Allocate space for the file */ - if((buf = (char *)malloc((size_t)sb.st_size)) == NULL) - { - DEBUG(0,("read_share_file: malloc for file size %d fail !\n", - (int)sb.st_size)); - return -1; - } - - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \ -for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (read(fd,buf,(size_t)sb.st_size) != (size_t)sb.st_size) - { - DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { - DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, - IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(conn, fname); - return -1; - } - - /* 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) - { - DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(conn, fname); - return -1; - } - - *out = buf; - return 0; -} - -/******************************************************************* -get all share mode entries in a share file for a dev/inode pair. -********************************************************************/ -static int slow_get_share_modes(connection_struct *conn, int token, - SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry **old_shares) -{ - int fd = token; - pstring fname; - int i; - int num_entries; - int num_entries_copied; - int newsize; - share_mode_entry *share_array; - char *buf = 0; - char *base = 0; - BOOL new_file; - - *old_shares = 0; - - /* Read the share file header - this is of the form: - 0 - locking version. - 4 - number of share mode entries. - 8 - 2 byte name length - [n bytes] file name (zero terminated). - - Followed by share mode entries of the form : - - 0 - tv_sec - 4 - tv_usec - 8 - share_mode - 12 - pid - 16 - oplock port (if oplocks in use) - 2 bytes. - */ - - share_name(conn, dev, inode, fname); - - if(read_share_file( conn, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n", - fname)); - return 0; - } - - if(new_file == True) - return 0; - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %s\n", num_entries, fname)); - return 0; - } - - 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: malloc fail !\n")); - return 0; - } - } - else - { - /* No entries - just delete the file. */ - DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(conn, fname); - return 0; - } - - num_entries_copied = 0; - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for( i = 0; i < num_entries; i++) - { - pid_t pid; - char *p = base + (i*SMF_ENTRY_LENGTH); - - pid = (pid_t)IVAL(p,SME_PID_OFFSET); - - if(!process_exists(pid)) - { - DEBUG(0,("get_share_modes: process %d no longer exists and \ -it left a share mode entry with mode 0x%X in share file %s\n", - (int)pid, IVAL(p,SME_SHAREMODE_OFFSET), fname)); - continue; - } - share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET); - share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); - share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - share_array[num_entries_copied].pid = pid; - share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); - share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - - num_entries_copied++; - } - - if(num_entries_copied == 0) - { - /* Delete the whole file. */ - DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n", - fname)); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - delete_share_file(conn, fname); - return 0; - } - - /* If we deleted some entries we need to re-write the whole number of - share mode entries back into the file. */ - - if(num_entries_copied != num_entries) - { - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - - SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied); - for( i = 0; i < num_entries_copied; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - SIVAL(p,SME_PID_OFFSET,(uint32)share_array[i].pid); - SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); - SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); - SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); - } - - newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - /* Now truncate the file at this point. */ -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(sys_ftruncate(fd, (SMB_OFF_T)newsize)!= 0) - { -#ifdef FTRUNCATE_NEEDS_ROOT - int saved_errno = errno; - unbecome_root(False); - errno = saved_errno; -#endif /* FTRUNCATE_NEEDS_ROOT */ - - DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - } - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(buf) - free(buf); - - DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname, - num_entries_copied)); - - return num_entries_copied; -} - -/******************************************************************* -del a share mode from a share mode file. -********************************************************************/ -static void slow_del_share_mode(int token, files_struct *fsp) -{ - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int newsize; - int i; - pid_t pid; - BOOL deleted = False; - BOOL new_file; - - share_name(fsp->conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, fname); - - if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", - fname)); - return; - } - - if(new_file == True) - { - DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", - fname)); - delete_share_file(fsp->conn, fname); - return; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %s\n", num_entries, fname)); - return; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return; - } - - pid = getpid(); - - /* Go through the entries looking for the particular one - we have set - delete it. - */ - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || - (((pid_t)IVAL(p,SME_PID_OFFSET)) != pid)) - continue; - - DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", - i, num_entries, fname)); - - /* Remove this entry. */ - if(i != num_entries - 1) - memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH); - - deleted = True; - break; - } - - if(!deleted) - { - DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return; - } - - num_entries--; - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries); - - if(num_entries == 0) - { - /* Deleted the last entry - remove the file. */ - DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n", - fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn,fname); - return; - } - - /* Re-write the file - and truncate it at the correct point. */ - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - - newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - - /* Now truncate the file at this point. */ -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(sys_ftruncate(fd, (SMB_OFF_T)newsize) != 0) - { -#ifdef FTRUNCATE_NEEDS_ROOT - int saved_errno = errno; - unbecome_root(False); - errno = saved_errno; -#endif /* FTRUNCATE_NEEDS_ROOT */ - - - DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(buf) - free(buf); - return; - } - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - -} - -/******************************************************************* -set the share mode of a file -********************************************************************/ -static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 op_type) -{ - pstring fname; - int fd = (int)token; - pid_t pid = getpid(); - SMB_STRUCT_STAT sb; - char *buf; - int num_entries; - int header_size; - char *p; - - share_name(fsp->conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, fname); - - if(sys_fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", - fname)); - return False; - } - - /* Sanity check for file contents (if it's not a new share file). */ - if(sb.st_size != 0) - { - SMB_OFF_T size = sb.st_size; - - /* Allocate space for the file plus one extra entry */ - if((buf = (char *)malloc((size_t)(sb.st_size + SMF_ENTRY_LENGTH))) == NULL) - { - DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", - (int)(sb.st_size + SMF_ENTRY_LENGTH))); - return False; - } - - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to reset position \ -to 0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (read(fd,buf,(size_t)sb.st_size) != (size_t)sb.st_size) - { - DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) - { - DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), - LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return False; - } - - size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */ - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 0) - { - DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return False; - } - - } - else - { - /* New file - just use a single_entry. */ - if((buf = (char *)malloc(SMF_HEADER_LENGTH + - strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2 + SMF_ENTRY_LENGTH)) == NULL) - { - DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); - return False; - } - SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); - SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2); - pstrcpy(buf + SMF_HEADER_LENGTH, fsp->conn->connectpath); - pstrcat(buf + SMF_HEADER_LENGTH, "/"); - pstrcat(buf + SMF_HEADER_LENGTH, fsp->fsp_name); - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH); - SIVAL(p,SME_SEC_OFFSET,fsp->open_time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,fsp->open_time.tv_usec); - SIVAL(p,SME_SHAREMODE_OFFSET,fsp->share_mode); - SIVAL(p,SME_PID_OFFSET,(uint32)pid); - SSVAL(p,SME_PORT_OFFSET,port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); - - num_entries++; - - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries); - - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \ -0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != - (header_size + (num_entries*SMF_ENTRY_LENGTH))) - { - DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ -deleting it (%s).\n",fname, strerror(errno))); - delete_share_file(fsp->conn, fname); - if(buf) - free(buf); - return False; - } - - /* Now truncate the file at this point - just for safety. */ - -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(sys_ftruncate(fd, (SMB_OFF_T)(header_size + (SMF_ENTRY_LENGTH*num_entries)))!= 0) - { - -#ifdef FTRUNCATE_NEEDS_ROOT - int saved_errno = errno; - unbecome_root(False); - errno = saved_errno; -#endif /* FTRUNCATE_NEEDS_ROOT */ - - DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), - strerror(errno))); - if(buf) - free(buf); - return False; - } - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(buf) - free(buf); - - DEBUG(3,("set_share_mode: Created share file %s with \ -mode 0x%X pid=%d\n",fname,fsp->share_mode,(int)pid)); - - return True; -} - -/******************************************************************* - Call a generic modify function for a share mode entry. -********************************************************************/ - -static BOOL slow_mod_share_entry(int token, files_struct *fsp, - void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), - void *param) -{ - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int fsize; - int i; - pid_t pid; - BOOL found = False; - BOOL new_file; - share_mode_entry entry; - - share_name(fsp->conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, fname); - - if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: slow_mod_share_entry: Failed to read share file %s\n", - fname)); - return False; - } - - if(new_file == True) - { - DEBUG(0,("ERROR: slow_mod_share_entry: share file %s is new (size zero), \ -deleting it.\n", fname)); - delete_share_file(fsp->conn, fname); - return False; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("slow_mod_share_entry: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:slow_mod_share_entry: num_share_mode_entries < 0 (%d) \ -for share file %s\n", num_entries, fname)); - return False; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("slow_mod_share_entry: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return False; - } - - pid = getpid(); - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || - (((pid_t)IVAL(p,SME_PID_OFFSET)) != pid)) - continue; - - DEBUG(5,("slow_mod_share_entry: Calling generic function to modify entry number %d (of %d) \ -from the share file %s\n", i, num_entries, fname)); - - /* - * Copy into the share_mode_entry structure and then call - * the generic function with the given parameter. - */ - - entry.pid = (pid_t)IVAL(p,SME_PID_OFFSET); - entry.op_port = SVAL(p,SME_PORT_OFFSET); - entry.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - entry.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - entry.time.tv_sec = IVAL(p,SME_SEC_OFFSET); - entry.time.tv_usec = IVAL(p,SME_USEC_OFFSET); - - (*mod_fn)( &entry, fsp->fd_ptr->dev, fsp->fd_ptr->inode, param); - - /* - * Now copy any changes the function made back into the buffer. - */ - - SIVAL(p,SME_PID_OFFSET, (uint32)entry.pid); - SSVAL(p,SME_PORT_OFFSET,entry.op_port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,entry.op_type); - SIVAL(p,SME_SHAREMODE_OFFSET,entry.share_mode); - SIVAL(p,SME_SEC_OFFSET,entry.time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,entry.time.tv_usec); - - found = True; - break; - } - - if(!found) - { - DEBUG(0,("slow_mod_share_entry: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return False; - } - - /* Re-write the file - and truncate it at the correct point. */ - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: slow_mod_share_entry: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, fsize) != fsize) - { - DEBUG(0,("ERROR: slow_mod_share_entry: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - return True; -} - - - -/******************************************************************* -call the specified function on each entry under management by the -share mode system -********************************************************************/ -static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) -{ - int i, count=0; - DIR *dir; - char *s; - share_mode_entry e; - - dir = opendir(lp_lockdir()); - if (!dir) { - return(0); - } - - while ((s=readdirname(dir))) { - char *buf; - char *base; - int fd; - pstring lname; - SMB_DEV_T dev; - SMB_INO_T inode; - BOOL new_file; - pstring fname; - -#ifdef LARGE_SMB_INO_T - double inode_ascii; - if (sscanf(s,"share.%u.%lf",&dev,&inode_ascii)!=2) continue; - inode = (SMB_INO_T)inode_ascii; -#else /* LARGE_SMB_INO_T */ - unsigned long inode_long; - if (sscanf(s,"share.%u.%lu",&dev,&inode_long)!=2) continue; - inode = (SMB_INO_T)inode_long; -#endif /* LARGE_SMB_INO_T */ - - pstrcpy(lname,lp_lockdir()); - trim_string(lname,NULL,"/"); - pstrcat(lname,"/"); - pstrcat(lname,s); - - fd = sys_open(lname,read_only?O_RDONLY:O_RDWR,0); - if (fd < 0) { - continue; - } - - /* Lock the share mode file while we read it. */ - if(!read_only && - fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) { - close(fd); - continue; - } - - if(read_share_file( 0, fd, lname, &buf, &new_file)) { - close(fd); - continue; - } - pstrcpy( 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); - e.pid = (pid_t)IVAL(p,SME_PID_OFFSET); - e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - e.time.tv_sec = IVAL(p,SME_SEC_OFFSET); - e.time.tv_usec = IVAL(p,SME_USEC_OFFSET); - e.op_port = SVAL(p,SME_PORT_OFFSET); - e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - - if (process_exists(e.pid)) { - fn(&e, fname); - count++; - } - } /* end for i */ - - if(buf) - free(buf); - base = 0; - } /* end while */ - closedir(dir); - - return count; -} - - -/******************************************************************* -dump the state of the system -********************************************************************/ -static void slow_share_status(FILE *f) -{ - -} - - -static struct share_ops share_ops = { - slow_stop_share_mode_mgmt, - slow_lock_share_entry, - slow_unlock_share_entry, - slow_get_share_modes, - slow_del_share_mode, - slow_set_share_mode, - slow_mod_share_entry, - slow_share_forall, - slow_share_status, -}; - -/******************************************************************* - initialize the slow share_mode management - ******************************************************************/ -struct share_ops *locking_slow_init(int ronly) -{ - - read_only = ronly; - - if (!directory_exist(lp_lockdir(),NULL)) { - if (!read_only) - mkdir(lp_lockdir(),0755); - if (!directory_exist(lp_lockdir(),NULL)) - return NULL; - } - - return &share_ops; -} -#else - int locking_slow_dummy_procedure(void); - int locking_slow_dummy_procedure(void) {return 0;} -#endif /* !FAST_SHARE_MODES */ diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c deleted file mode 100644 index bf2802c9ec..0000000000 --- a/source3/locking/shmem.c +++ /dev/null @@ -1,963 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Shared memory functions - Copyright (C) Erik Devriendt 1996-1998 - - 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. - -*/ - -#include "includes.h" - - -#ifdef USE_SHARED_MMAP - - -extern int DEBUGLEVEL; - - -#define SMB_SHM_MAGIC 0x53484100 -/* = "SHM" in hex */ - -#define SMB_SHM_VERSION 2 - -/* we need world read for smbstatus to function correctly */ -#ifdef SECURE_SHARE_MODES -#define SHM_FILE_MODE 0600 -#else -#define SHM_FILE_MODE 0644 -#endif - -#define SHMEM_HASH_SIZE 13 - - -/* WARNING : offsets are used because mmap() does not guarantee that all processes have the - shared memory mapped to the same address */ - -struct SmbShmHeader -{ - int smb_shm_magic; - int smb_shm_version; - int total_size; /* in bytes */ - BOOL consistent; - int first_free_off; - int userdef_off; /* a userdefined offset. can be used to store root of tree or list */ - struct { /* a cell is a range of bytes of sizeof(struct SmbShmBlockDesc) size */ - int cells_free; - int cells_used; - int cells_system; /* number of cells used as allocated block descriptors */ - } statistics; -}; - -#define SMB_SHM_NOT_FREE_OFF (-1) -struct SmbShmBlockDesc -{ - int next; /* offset of next block in the free list or SMB_SHM_NOT_FREE_OFF when block in use */ - int size; /* user size in BlockDescSize units */ -}; - -#define EOList_Addr (struct SmbShmBlockDesc *)( 0 ) -#define EOList_Off 0 - -#define CellSize sizeof(struct SmbShmBlockDesc) - -/* HeaderSize aligned on 8 byte boundary */ -#define AlignedHeaderSize ((sizeof(struct SmbShmHeader)+7) & ~7) - -static int smb_shm_fd = -1; -static pstring smb_shm_processreg_name = ""; - -static struct SmbShmHeader *smb_shm_header_p = (struct SmbShmHeader *)0; -static int smb_shm_times_locked = 0; - -static BOOL smb_shm_initialize_called = False; - -static int read_only; - -static BOOL smb_shm_global_lock(void) -{ - if (smb_shm_fd < 0) - { - DEBUG(0,("ERROR smb_shm_global_lock : bad smb_shm_fd (%d)\n",smb_shm_fd)); - return False; - } - - smb_shm_times_locked++; - - if(smb_shm_times_locked > 1) - { - DEBUG(5,("smb_shm_global_lock : locked %d times\n",smb_shm_times_locked)); - return True; - } - - if (read_only) - return True; - - /* Do an exclusive wait lock on the first byte of the file */ - if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR smb_shm_global_lock : fcntl_lock failed with code %s\n",strerror(errno))); - smb_shm_times_locked--; - return False; - } - - return True; - -} - -static BOOL smb_shm_global_unlock(void) -{ - if (smb_shm_fd < 0) - { - DEBUG(0,("ERROR smb_shm_global_unlock : bad smb_shm_fd (%d)\n",smb_shm_fd)); - return False; - } - - if(smb_shm_times_locked == 0) - { - DEBUG(0,("ERROR smb_shm_global_unlock : shmem not locked\n")); - return False; - } - - smb_shm_times_locked--; - - if(smb_shm_times_locked > 0) - { - DEBUG(5,("smb_shm_global_unlock : still locked %d times\n",smb_shm_times_locked)); - return True; - } - - if (read_only) - return True; - - /* Do a wait unlock on the first byte of the file */ - if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False) - { - DEBUG(0,("ERROR smb_shm_global_unlock : fcntl_lock failed with code %s\n",strerror(errno))); - smb_shm_times_locked++; - return False; - } - - return True; - -} - - -static void *smb_shm_offset2addr(int offset) -{ - if (offset == 0 ) - return (void *)(0); - - if (!smb_shm_header_p) - return (void *)(0); - - return (void *)((char *)smb_shm_header_p + offset ); -} - -static int smb_shm_addr2offset(void *addr) -{ - if (!addr) - return 0; - - if (!smb_shm_header_p) - return 0; - - return (int)((char *)addr - (char *)smb_shm_header_p); -} - - - -static int smb_shm_alloc(int size) -{ - unsigned num_cells ; - struct SmbShmBlockDesc *scanner_p; - struct SmbShmBlockDesc *prev_p; - struct SmbShmBlockDesc *new_p; - int result_offset; - - - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_alloc : shmem not mapped\n")); - return 0; - } - - smb_shm_global_lock(); - - if( !smb_shm_header_p->consistent) - { - DEBUG(0,("ERROR smb_shm_alloc : shmem not consistent\n")); - smb_shm_global_unlock(); - return 0; - } - - - /* calculate the number of cells */ - num_cells = (size + CellSize -1) / CellSize; - - /* set start of scan */ - prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); - scanner_p = prev_p ; - - /* scan the free list to find a matching free space */ - while ( ( scanner_p != EOList_Addr ) && ( scanner_p->size < num_cells ) ) - { - prev_p = scanner_p; - scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next); - } - - /* at this point scanner point to a block header or to the end of the list */ - if ( scanner_p == EOList_Addr ) - { - DEBUG(0,("ERROR smb_shm_alloc : alloc of %d bytes failed, no free space found\n",size)); - smb_shm_global_unlock(); - return (0); - } - - /* going to modify shared mem */ - smb_shm_header_p->consistent = False; - - /* if we found a good one : scanner == the good one */ - if ( scanner_p->size <= num_cells + 2 ) - { - /* there is no use in making a new one, it will be too small anyway - * we will link out scanner - */ - if ( prev_p == scanner_p ) - { - smb_shm_header_p->first_free_off = scanner_p->next ; - } - else - { - prev_p->next = scanner_p->next ; - } - smb_shm_header_p->statistics.cells_free -= scanner_p->size; - smb_shm_header_p->statistics.cells_used += scanner_p->size; - } - else - { - /* Make a new one */ - new_p = scanner_p + 1 + num_cells; - new_p->size = scanner_p->size - num_cells - 1; - new_p->next = scanner_p->next; - scanner_p->size = num_cells; - scanner_p->next = smb_shm_addr2offset(new_p); - - if ( prev_p != scanner_p ) - { - prev_p->next = smb_shm_addr2offset(new_p) ; - } - else - { - smb_shm_header_p->first_free_off = smb_shm_addr2offset(new_p) ; - } - smb_shm_header_p->statistics.cells_free -= num_cells+1; - smb_shm_header_p->statistics.cells_used += num_cells; - smb_shm_header_p->statistics.cells_system += 1; - } - - result_offset = smb_shm_addr2offset( &(scanner_p[1]) ); - scanner_p->next = SMB_SHM_NOT_FREE_OFF ; - - /* end modification of shared mem */ - smb_shm_header_p->consistent = True; - - DEBUG(6,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); - - smb_shm_global_unlock(); - return ( result_offset ); -} - - - - -/* - * Function to create the hash table for the share mode entries. Called - * when smb shared memory is global locked. - */ -static BOOL smb_shm_create_hash_table( unsigned int size ) -{ - size *= sizeof(int); - - smb_shm_global_lock(); - smb_shm_header_p->userdef_off = smb_shm_alloc( size ); - - if(smb_shm_header_p->userdef_off == 0) - { - DEBUG(0,("smb_shm_create_hash_table: Failed to create hash table of size %d\n",size)); - smb_shm_global_unlock(); - return False; - } - - /* Clear hash buckets. */ - memset( smb_shm_offset2addr(smb_shm_header_p->userdef_off), '\0', size); - smb_shm_global_unlock(); - return True; -} - -static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *other_processes) -{ - int smb_shm_processes_fd = -1; - int nb_read; - pid_t other_pid; - SMB_OFF_T seek_back = -((SMB_OFF_T)sizeof(other_pid)); - SMB_OFF_T free_slot = -1; - SMB_OFF_T erased_slot; - - smb_shm_processes_fd = sys_open(processreg_file, - read_only?O_RDONLY:(O_RDWR|O_CREAT), - SHM_FILE_MODE); - - if ( smb_shm_processes_fd < 0 ) - { - DEBUG(0, ("ERROR smb_shm_register_process : processreg_file \ -open failed with code %s\n",strerror(errno))); - return False; - } - - *other_processes = False; - - while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) - { - if(other_pid) - { - if(process_exists(other_pid)) - *other_processes = True; - else - { - /* erase old pid */ - DEBUG(5,("smb_shm_register_process : erasing stale record \ -for pid %d (seek_back = %.0f)\n", (int)other_pid, (double)seek_back)); - other_pid = (pid_t)0; - if((erased_slot = sys_lseek(smb_shm_processes_fd, - seek_back, SEEK_CUR)) == -1) - { - DEBUG(0, ("ERROR smb_shm_register_process : sys_lseek failed \ -with error %s\n", strerror(errno))); - close(smb_shm_processes_fd); - return False; - } - - if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) == -1) - { - DEBUG(0, ("ERROR smb_shm_register_process : write failed \ -with error %s\n", strerror(errno))); - close(smb_shm_processes_fd); - return False; - } - - if(free_slot < 0) - free_slot = erased_slot; - } - } - else - { - if(free_slot < 0) - { - if((free_slot = sys_lseek(smb_shm_processes_fd, - seek_back, SEEK_CUR))==-1) - { - DEBUG(0, ("ERROR smb_shm_register_process : sys_lseek \ -failed with error %s\n", strerror(errno))); - close(smb_shm_processes_fd); - return False; - } - } /* end if free_slot */ - } /* end else */ - } /* end if other_pid */ - - if (nb_read < 0) - { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file read \ -failed with code %s\n",strerror(errno))); - close(smb_shm_processes_fd); - return False; - } - - if(free_slot < 0) - { - if((free_slot = sys_lseek(smb_shm_processes_fd, 0, SEEK_END)) == -1) - { - DEBUG(0,("ERROR smb_shm_register_process : sys_lseek failed with code %s\n",strerror(errno))); - close(smb_shm_processes_fd); - return False; - } - } - - DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %.0f\n", - (int)pid, (double)free_slot)); - - if(sys_lseek(smb_shm_processes_fd, free_slot, SEEK_SET) == -1) - { - DEBUG(0,("ERROR smb_shm_register_process : sys_lseek failed with code %s\n",strerror(errno))); - close(smb_shm_processes_fd); - return False; - } - - if(write(smb_shm_processes_fd, &pid, sizeof(pid)) == -1) - { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %s\n",strerror(errno))); - close(smb_shm_processes_fd); - return False; - } - - close(smb_shm_processes_fd); - - return True; -} - -static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) -{ - int smb_shm_processes_fd = -1; - int nb_read; - pid_t other_pid; - SMB_OFF_T seek_back = -((SMB_OFF_T)sizeof(other_pid)); - BOOL found = False; - - - smb_shm_processes_fd = sys_open(processreg_file, O_RDWR, 0); - if ( smb_shm_processes_fd < 0 ) - { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file open failed with code %s\n",strerror(errno))); - return False; - } - - while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) - { - DEBUG(5,("smb_shm_unregister_process : read record for pid %d\n",(int)other_pid)); - if(other_pid == pid) - { - /* erase pid */ - DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %.0f)\n", - (int)other_pid, (double)seek_back)); - other_pid = (pid_t)0; - if(sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR) == -1) - { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file sys_lseek failed with code %s\n",strerror(errno))); - close(smb_shm_processes_fd); - return False; - } - if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) - { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %s\n",strerror(errno))); - close(smb_shm_processes_fd); - return False; - } - - found = True; - break; - } - } - if (nb_read < 0) - { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file read failed with code %s\n",strerror(errno))); - close(smb_shm_processes_fd); - return False; - } - - if(!found) - { - DEBUG(0,("ERROR smb_shm_unregister_process : couldn't find pid %d in file %s\n", - (int)pid,processreg_file)); - close(smb_shm_processes_fd); - return False; - } - - - close(smb_shm_processes_fd); - - return True; -} - - -static BOOL smb_shm_validate_header(int size) -{ - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_validate_header : shmem not mapped\n")); - return False; - } - - if(smb_shm_header_p->smb_shm_magic != SMB_SHM_MAGIC) - { - DEBUG(0,("ERROR smb_shm_validate_header : bad magic\n")); - return False; - } - if(smb_shm_header_p->smb_shm_version != SMB_SHM_VERSION) - { - DEBUG(0,("ERROR smb_shm_validate_header : bad version %X\n",smb_shm_header_p->smb_shm_version)); - return False; - } - - if(smb_shm_header_p->total_size != size) - { - DEBUG(0,("ERROR smb_shm_validate_header : shmem size mismatch (old = %d, new = %d)\n",smb_shm_header_p->total_size,size)); - return False; - } - - if(!smb_shm_header_p->consistent) - { - DEBUG(0,("ERROR smb_shm_validate_header : shmem not consistent\n")); - return False; - } - return True; -} - -static BOOL smb_shm_initialize(int size) -{ - struct SmbShmBlockDesc * first_free_block_p; - - DEBUG(5,("smb_shm_initialize : initializing shmem file of size %d\n",size)); - - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_initialize : shmem not mapped\n")); - return False; - } - - smb_shm_header_p->smb_shm_magic = SMB_SHM_MAGIC; - smb_shm_header_p->smb_shm_version = SMB_SHM_VERSION; - smb_shm_header_p->total_size = size; - smb_shm_header_p->first_free_off = AlignedHeaderSize; - smb_shm_header_p->userdef_off = 0; - - first_free_block_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); - first_free_block_p->next = EOList_Off; - first_free_block_p->size = ( size - AlignedHeaderSize - CellSize ) / CellSize ; - - smb_shm_header_p->statistics.cells_free = first_free_block_p->size; - smb_shm_header_p->statistics.cells_used = 0; - smb_shm_header_p->statistics.cells_system = 1; - - smb_shm_header_p->consistent = True; - - smb_shm_initialize_called = True; - - return True; -} - -static void smb_shm_solve_neighbors(struct SmbShmBlockDesc *head_p ) -{ - struct SmbShmBlockDesc *next_p; - - /* Check if head_p and head_p->next are neighbors and if so join them */ - if ( head_p == EOList_Addr ) return ; - if ( head_p->next == EOList_Off ) return ; - - next_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(head_p->next); - if ( ( head_p + head_p->size + 1 ) == next_p) - { - head_p->size += next_p->size +1 ; /* adapt size */ - head_p->next = next_p->next ; /* link out */ - - smb_shm_header_p->statistics.cells_free += 1; - smb_shm_header_p->statistics.cells_system -= 1; - } -} - - - -static BOOL smb_shm_close( void ) -{ - - if(smb_shm_initialize_called == False) - return True; - - DEBUG(5,("smb_shm_close\n")); - if(smb_shm_times_locked > 0) - DEBUG(0,("WARNING smb_shm_close : shmem was still locked %d times\n",smb_shm_times_locked));; - if ((smb_shm_header_p != NULL) && - (munmap((caddr_t)smb_shm_header_p, smb_shm_header_p->total_size) < 0)) - { - DEBUG(0,("ERROR smb_shm_close : munmap failed with code %s\n",strerror(errno))); - } - - smb_shm_global_lock(); - DEBUG(5,("calling smb_shm_unregister_process(%s, %d)\n", - smb_shm_processreg_name, (int)getpid())); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - - close(smb_shm_fd); - - smb_shm_fd = -1; - smb_shm_processreg_name[0] = '\0'; - - smb_shm_header_p = (struct SmbShmHeader *)0; - smb_shm_times_locked = 0; - - return True; -} - - -static BOOL smb_shm_free(int offset) -{ - struct SmbShmBlockDesc *header_p ; /* pointer to header of block to free */ - struct SmbShmBlockDesc *scanner_p ; /* used to scan the list */ - struct SmbShmBlockDesc *prev_p ; /* holds previous in the list */ - - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_free : shmem not mapped\n")); - return False; - } - - smb_shm_global_lock(); - - if( !smb_shm_header_p->consistent) - { - DEBUG(0,("ERROR smb_shm_free : shmem not consistent\n")); - smb_shm_global_unlock(); - return False; - } - - header_p = ( (struct SmbShmBlockDesc *)smb_shm_offset2addr(offset) - 1); /* make pointer to header of block */ - - if (header_p->next != SMB_SHM_NOT_FREE_OFF) - { - DEBUG(0,("ERROR smb_shm_free : bad offset (%d)\n",offset)); - smb_shm_global_unlock(); - return False; - } - - /* find a place in the free_list to put the header in */ - - /* set scanner and previous pointer to start of list */ - prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); - scanner_p = prev_p ; - - while ( ( scanner_p != EOList_Addr) && (scanner_p < header_p) ) /* while we didn't scan past its position */ - { - prev_p = scanner_p ; - scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next); - } - - smb_shm_header_p->consistent = False; - - DEBUG(6,("smb_shm_free : freeing %d bytes at offset %d\n",header_p->size*CellSize,offset)); - - /* zero the area being freed - this allows us to find bugs faster */ - memset(smb_shm_offset2addr(offset), 0, header_p->size*CellSize); - - if ( scanner_p == prev_p ) - { - smb_shm_header_p->statistics.cells_free += header_p->size; - smb_shm_header_p->statistics.cells_used -= header_p->size; - - /* we must free it at the beginning of the list */ - smb_shm_header_p->first_free_off = smb_shm_addr2offset(header_p); /* set the free_list_pointer to this block_header */ - - /* scanner is the one that was first in the list */ - header_p->next = smb_shm_addr2offset(scanner_p); - smb_shm_solve_neighbors( header_p ); /* if neighbors then link them */ - - smb_shm_header_p->consistent = True; - smb_shm_global_unlock(); - return True; - } - else - { - smb_shm_header_p->statistics.cells_free += header_p->size; - smb_shm_header_p->statistics.cells_used -= header_p->size; - - prev_p->next = smb_shm_addr2offset(header_p); - header_p->next = smb_shm_addr2offset(scanner_p); - smb_shm_solve_neighbors(header_p) ; - smb_shm_solve_neighbors(prev_p) ; - - smb_shm_header_p->consistent = True; - smb_shm_global_unlock(); - return True; - } -} - -static int smb_shm_get_userdef_off(void) -{ - if (!smb_shm_header_p) - return 0; - else - return smb_shm_header_p->userdef_off; -} - -/******************************************************************* - Lock a particular hash bucket entry. - ******************************************************************/ -static BOOL smb_shm_lock_hash_entry( unsigned int entry) -{ - int start = (smb_shm_header_p->userdef_off + (entry * sizeof(int))); - - if (smb_shm_fd < 0) - { - DEBUG(0,("ERROR smb_shm_lock_hash_entry : bad smb_shm_fd (%d)\n",smb_shm_fd)); - return False; - } - - if (read_only) - return True; - - /* Do an exclusive wait lock on the 4 byte region mapping into this entry */ - if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, start, sizeof(int), F_WRLCK) == False) - { - DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno))); - return False; - } - - DEBUG(9,("smb_shm_lock_hash_entry: locked hash bucket %d\n", entry)); - return True; -} - -/******************************************************************* - Unlock a particular hash bucket entry. - ******************************************************************/ -static BOOL smb_shm_unlock_hash_entry( unsigned int entry ) -{ - int start = (smb_shm_header_p->userdef_off + (entry * sizeof(int))); - - if (smb_shm_fd < 0) - { - DEBUG(0,("ERROR smb_shm_unlock_hash_entry : bad smb_shm_fd (%d)\n",smb_shm_fd)); - return False; - } - - if (read_only) - return True; - - /* Do a wait lock on the 4 byte region mapping into this entry */ - if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, start, sizeof(int), F_UNLCK) == False) - { - DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno))); - return False; - } - - DEBUG(9,("smb_shm_unlock_hash_entry: unlocked hash bucket %d\n", entry)); - return True; -} - -/******************************************************************* - Gather statistics on shared memory usage. - ******************************************************************/ -static BOOL smb_shm_get_usage(int *bytes_free, - int *bytes_used, - int *bytes_overhead) -{ - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_free : shmem not mapped\n")); - return False; - } - *bytes_free = smb_shm_header_p->statistics.cells_free * CellSize; - *bytes_used = smb_shm_header_p->statistics.cells_used * CellSize; - *bytes_overhead = smb_shm_header_p->statistics.cells_system * CellSize + AlignedHeaderSize; - - return True; -} - -/******************************************************************* -hash a number into a hash_entry - ******************************************************************/ -static unsigned smb_shm_hash_size(void) -{ - return SHMEM_HASH_SIZE; -} - -static struct shmem_ops shmops = { - smb_shm_close, - smb_shm_alloc, - smb_shm_free, - smb_shm_get_userdef_off, - smb_shm_offset2addr, - smb_shm_addr2offset, - smb_shm_lock_hash_entry, - smb_shm_unlock_hash_entry, - smb_shm_get_usage, - smb_shm_hash_size, -}; - -/******************************************************************* - open the shared memory - ******************************************************************/ -struct shmem_ops *smb_shm_open(int ronly) -{ - pstring file_name; - SMB_OFF_T filesize; - BOOL created_new = False; - BOOL other_processes = True; - SMB_OFF_T size = (SMB_OFF_T)lp_shmem_size(); - - read_only = ronly; - - pstrcpy(file_name,lp_lockdir()); - if (!directory_exist(file_name,NULL)) { - if (read_only) - return NULL; - mkdir(file_name,0755); - } - trim_string(file_name,"","/"); - if (!*file_name) - return(False); - pstrcat(file_name, "/SHARE_MEM_FILE"); - - DEBUG(5,("smb_shm_open : using shmem file %s to be of size %.0f\n", - file_name,(double)size)); - - smb_shm_fd = sys_open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT), - SHM_FILE_MODE); - - if ( smb_shm_fd < 0 ) - { - DEBUG(0,("ERROR smb_shm_open : open failed with code %s\n",strerror(errno))); - return NULL; - } - - if (!smb_shm_global_lock()) - { - DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n")); - return NULL; - } - - if( (filesize = sys_lseek(smb_shm_fd, 0, SEEK_END)) == -1) - { - DEBUG(0,("ERROR smb_shm_open : sys_lseek failed with code %s\n", - strerror(errno))); - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; - } - - /* - * Return the file offset to 0 to save on later seeks. - */ - if(sys_lseek(smb_shm_fd,0,SEEK_SET) == -1) - { - DEBUG(0,("ERROR smb_shm_open : sys_lseek failed with code %s\n", - strerror(errno))); - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; - } - - if (filesize == 0) - { - /* - * We just created a new one. - */ - created_new = True; - } - - /* - * To find out if some other process is already mapping the file, - * we use a registration file containing the processids of the file - * mapping processes. - */ - - /* construct processreg file name */ - pstrcpy(smb_shm_processreg_name, file_name); - pstrcat(smb_shm_processreg_name, ".processes"); - - if (!read_only && !smb_shm_register_process(smb_shm_processreg_name, - getpid(), &other_processes)) - { - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; - } - - if (!read_only && (created_new || !other_processes)) - { - /* we just created a new one, or are the first opener, lets set it size */ - if( sys_ftruncate(smb_shm_fd, size) <0) - { - DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %s\n", - strerror(errno))); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; - } - - /* paranoia */ - if(sys_lseek(smb_shm_fd,0,SEEK_SET) == -1) - { - DEBUG(0,("ERROR smb_shm_open : sys_lseek failed with code %s\n", - strerror(errno))); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; - } - - filesize = size; - } - - if (size != filesize ) - { - /* the existing file has a different size and we are not the first opener. - Since another process is still using it, we will use the file size */ - DEBUG(0,("WARNING smb_shm_open : filesize (%.0f) != expected \ -size (%.0f), using filesize\n", (double)filesize, (double)size)); - - size = filesize; - } - - smb_shm_header_p = (struct SmbShmHeader *)sys_mmap(NULL, size, - read_only?PROT_READ: (PROT_READ | PROT_WRITE), - MAP_FILE | MAP_SHARED, smb_shm_fd, (SMB_OFF_T)0); - - /* - * WARNING, smb_shm_header_p can be different for different - * processes mapping the same file ! - */ - if (smb_shm_header_p == (struct SmbShmHeader *)(-1)) - { - DEBUG(0,("ERROR smb_shm_open : mmap failed with code %s\n",strerror(errno))); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; - } - - - if (!read_only && (created_new || !other_processes)) - { - smb_shm_initialize(size); - /* Create the hash buckets for the share file entries. */ - smb_shm_create_hash_table(SHMEM_HASH_SIZE); - } - else if (!smb_shm_validate_header(size) ) - { - /* existing file is corrupt, samba admin should remove it by hand */ - DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n")); - munmap((caddr_t)smb_shm_header_p, size); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return NULL; - } - - smb_shm_global_unlock(); - return &shmops; -} - - -#else /* HAVE_SHARED_MMAP */ - int shmem_dummy_procedure(void) -{return 0;} -#endif /* HAVE_SHARED_MMAP */ diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c deleted file mode 100644 index 04a2e74460..0000000000 --- a/source3/locking/shmem_sysv.c +++ /dev/null @@ -1,724 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Shared memory functions - SYSV IPC implementation - Copyright (C) Andrew Tridgell 1997-1998 - - 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. - -*/ - -#include "includes.h" - - -#ifdef USE_SYSV_IPC - -extern int DEBUGLEVEL; - -#define SHMEM_KEY ((key_t)0x280267) -#define SEMAPHORE_KEY (SHMEM_KEY+2) - -#define SHM_MAGIC 0x53484100 -#define SHM_VERSION 2 - -#ifdef SHM_R -#define IPC_PERMS ((SHM_R | SHM_W) | (SHM_R>>3) | (SHM_R>>6)) -#else -#define IPC_PERMS 0644 -#endif - - -#ifdef SECURE_SEMAPHORES -/* secure semaphores are slow because we have to do a become_root() - on every call! */ -#define SEMAPHORE_PERMS IPC_PERMS -#else -#define SEMAPHORE_PERMS 0666 -#endif - -#define SHMEM_HASH_SIZE 13 - -#define MIN_SHM_SIZE 0x1000 - -static int shm_id; -static int sem_id; -static int shm_size; -static int hash_size; -static int global_lock_count; - -struct ShmHeader { - int shm_magic; - int shm_version; - int total_size; /* in bytes */ - BOOL consistent; - int first_free_off; - int userdef_off; /* a userdefined offset. can be used to store - root of tree or list */ - struct { /* a cell is a range of bytes of sizeof(struct - ShmBlockDesc) size */ - int cells_free; - int cells_used; - int cells_system; /* number of cells used as allocated - block descriptors */ - } statistics; -}; - -#define SHM_NOT_FREE_OFF (-1) -struct ShmBlockDesc -{ - int next; /* offset of next block in the free list or - SHM_NOT_FREE_OFF when block in use */ - int size; /* user size in BlockDescSize units */ -}; - -#define EOList_Addr NULL -#define EOList_Off (0) - -#define CellSize sizeof(struct ShmBlockDesc) - -/* HeaderSize aligned on a 8 byte boundary */ -#define AlignedHeaderSize ((sizeof(struct ShmHeader)+7) & ~7) - -static struct ShmHeader *shm_header_p = NULL; - -static int read_only; - -static BOOL sem_change(int i, int op) -{ -#ifdef SECURE_SEMAPHORES - extern struct current_user current_user; - int became_root=0; -#endif - struct sembuf sb; - int ret; - - if (read_only) return True; - -#ifdef SECURE_SEMAPHORES - if (current_user.uid != 0) { - become_root(0); - became_root = 1; - } -#endif - - sb.sem_num = i; - sb.sem_op = op; - sb.sem_flg = 0; - - ret = semop(sem_id, &sb, 1); - - if (ret != 0) { - DEBUG(0,("ERROR: sem_change(%d,%d) failed (%s)\n", - i, op, strerror(errno))); - } - -#ifdef SECURE_SEMAPHORES - if (became_root) { - unbecome_root(0); - } -#endif - - return ret == 0; -} - -static BOOL global_lock(void) -{ - global_lock_count++; - if (global_lock_count == 1) - return sem_change(0, -1); - return True; -} - -static BOOL global_unlock(void) -{ - global_lock_count--; - if (global_lock_count == 0) - return sem_change(0, 1); - return True; -} - -static void *shm_offset2addr(int offset) -{ - if (offset == 0 ) - return (void *)(0); - - if (!shm_header_p) - return (void *)(0); - - return (void *)((char *)shm_header_p + offset); -} - -static int shm_addr2offset(void *addr) -{ - if (!addr) - return 0; - - if (!shm_header_p) - return 0; - - return (int)((char *)addr - (char *)shm_header_p); -} - - -static int shm_alloc(int size) -{ - unsigned num_cells ; - struct ShmBlockDesc *scanner_p; - struct ShmBlockDesc *prev_p; - struct ShmBlockDesc *new_p; - int result_offset; - - - if (!shm_header_p) { - /* not mapped yet */ - DEBUG(0,("ERROR shm_alloc : shmem not mapped\n")); - return 0; - } - - global_lock(); - - if (!shm_header_p->consistent) { - DEBUG(0,("ERROR shm_alloc : shmem not consistent\n")); - global_unlock(); - return 0; - } - - /* calculate the number of cells */ - num_cells = (size + (CellSize-1)) / CellSize; - - /* set start of scan */ - prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off); - scanner_p = prev_p ; - - /* scan the free list to find a matching free space */ - while ((scanner_p != EOList_Addr) && (scanner_p->size < num_cells)) { - prev_p = scanner_p; - scanner_p = (struct ShmBlockDesc *)shm_offset2addr(scanner_p->next); - } - - /* at this point scanner point to a block header or to the end of - the list */ - if (scanner_p == EOList_Addr) { - DEBUG(0,("ERROR shm_alloc : alloc of %d bytes failed\n",size)); - global_unlock(); - return (0); - } - - /* going to modify shared mem */ - shm_header_p->consistent = False; - - /* if we found a good one : scanner == the good one */ - if (scanner_p->size > num_cells + 2) { - /* Make a new one */ - new_p = scanner_p + 1 + num_cells; - new_p->size = scanner_p->size - (num_cells + 1); - new_p->next = scanner_p->next; - scanner_p->size = num_cells; - scanner_p->next = shm_addr2offset(new_p); - - shm_header_p->statistics.cells_free -= 1; - shm_header_p->statistics.cells_system += 1; - } - - /* take it from the free list */ - if (prev_p == scanner_p) { - shm_header_p->first_free_off = scanner_p->next; - } else { - prev_p->next = scanner_p->next; - } - shm_header_p->statistics.cells_free -= scanner_p->size; - shm_header_p->statistics.cells_used += scanner_p->size; - - result_offset = shm_addr2offset(&(scanner_p[1])); - scanner_p->next = SHM_NOT_FREE_OFF; - - /* end modification of shared mem */ - shm_header_p->consistent = True; - - global_unlock(); - - DEBUG(6,("shm_alloc : allocated %d bytes at offset %d\n", - size,result_offset)); - - return result_offset; -} - -static void shm_solve_neighbors(struct ShmBlockDesc *head_p ) -{ - struct ShmBlockDesc *next_p; - - /* Check if head_p and head_p->next are neighbors and if so - join them */ - if ( head_p == EOList_Addr ) return ; - if ( head_p->next == EOList_Off ) return ; - - next_p = (struct ShmBlockDesc *)shm_offset2addr(head_p->next); - if ((head_p + head_p->size + 1) == next_p) { - head_p->size += next_p->size + 1; /* adapt size */ - head_p->next = next_p->next; /* link out */ - - shm_header_p->statistics.cells_free += 1; - shm_header_p->statistics.cells_system -= 1; - } -} - - -static BOOL shm_free(int offset) -{ - struct ShmBlockDesc *header_p; /* pointer to header of - block to free */ - struct ShmBlockDesc *scanner_p; /* used to scan the list */ - struct ShmBlockDesc *prev_p; /* holds previous in the - list */ - - if (!shm_header_p) { - /* not mapped yet */ - DEBUG(0,("ERROR shm_free : shmem not mapped\n")); - return False; - } - - global_lock(); - - if (!shm_header_p->consistent) { - DEBUG(0,("ERROR shm_free : shmem not consistent\n")); - global_unlock(); - return False; - } - - /* make pointer to header of block */ - header_p = ((struct ShmBlockDesc *)shm_offset2addr(offset) - 1); - - if (header_p->next != SHM_NOT_FREE_OFF) { - DEBUG(0,("ERROR shm_free : bad offset (%d)\n",offset)); - global_unlock(); - return False; - } - - /* find a place in the free_list to put the header in */ - - /* set scanner and previous pointer to start of list */ - prev_p = (struct ShmBlockDesc *) - shm_offset2addr(shm_header_p->first_free_off); - scanner_p = prev_p ; - - while ((scanner_p != EOList_Addr) && - (scanner_p < header_p)) { - /* while we didn't scan past its position */ - prev_p = scanner_p ; - scanner_p = (struct ShmBlockDesc *) - shm_offset2addr(scanner_p->next); - } - - shm_header_p->consistent = False; - - DEBUG(6,("shm_free : freeing %d bytes at offset %d\n", - (int)(header_p->size*CellSize),(int)offset)); - - /* zero the area being freed - this allows us to find bugs faster */ - memset(shm_offset2addr(offset), 0, header_p->size*CellSize); - - if (scanner_p == prev_p) { - shm_header_p->statistics.cells_free += header_p->size; - shm_header_p->statistics.cells_used -= header_p->size; - - /* we must free it at the beginning of the list */ - shm_header_p->first_free_off = shm_addr2offset(header_p); - /* set the free_list_pointer to this block_header */ - - /* scanner is the one that was first in the list */ - header_p->next = shm_addr2offset(scanner_p); - shm_solve_neighbors(header_p); - - shm_header_p->consistent = True; - } else { - shm_header_p->statistics.cells_free += header_p->size; - shm_header_p->statistics.cells_used -= header_p->size; - - prev_p->next = shm_addr2offset(header_p); - header_p->next = shm_addr2offset(scanner_p); - shm_solve_neighbors(header_p) ; - shm_solve_neighbors(prev_p) ; - - shm_header_p->consistent = True; - } - - global_unlock(); - return True; -} - - -/* - * Function to create the hash table for the share mode entries. Called - * when smb shared memory is global locked. - */ -static BOOL shm_create_hash_table(unsigned int hash_entries) -{ - int size = hash_entries * sizeof(int); - - global_lock(); - shm_header_p->userdef_off = shm_alloc(size); - - if(shm_header_p->userdef_off == 0) { - DEBUG(0,("shm_create_hash_table: Failed to create hash table of size %d\n", - size)); - global_unlock(); - return False; - } - - /* Clear hash buckets. */ - memset(shm_offset2addr(shm_header_p->userdef_off), '\0', size); - global_unlock(); - return True; -} - - -static BOOL shm_validate_header(int size) -{ - if(!shm_header_p) { - /* not mapped yet */ - DEBUG(0,("ERROR shm_validate_header : shmem not mapped\n")); - return False; - } - - if(shm_header_p->shm_magic != SHM_MAGIC) { - DEBUG(0,("ERROR shm_validate_header : bad magic\n")); - return False; - } - - if(shm_header_p->shm_version != SHM_VERSION) { - DEBUG(0,("ERROR shm_validate_header : bad version %X\n", - shm_header_p->shm_version)); - return False; - } - - if(shm_header_p->total_size != size) { - DEBUG(0,("ERROR shmem size mismatch (old = %d, new = %d)\n", - shm_header_p->total_size,size)); - return False; - } - - if(!shm_header_p->consistent) { - DEBUG(0,("ERROR shmem not consistent\n")); - return False; - } - return True; -} - - -static BOOL shm_initialize(int size) -{ - struct ShmBlockDesc * first_free_block_p; - - DEBUG(5,("shm_initialize : initializing shmem size %d\n",size)); - - if( !shm_header_p ) { - /* not mapped yet */ - DEBUG(0,("ERROR shm_initialize : shmem not mapped\n")); - return False; - } - - shm_header_p->shm_magic = SHM_MAGIC; - shm_header_p->shm_version = SHM_VERSION; - shm_header_p->total_size = size; - shm_header_p->first_free_off = AlignedHeaderSize; - shm_header_p->userdef_off = 0; - - first_free_block_p = (struct ShmBlockDesc *) - shm_offset2addr(shm_header_p->first_free_off); - first_free_block_p->next = EOList_Off; - first_free_block_p->size = - (size - (AlignedHeaderSize+CellSize))/CellSize; - shm_header_p->statistics.cells_free = first_free_block_p->size; - shm_header_p->statistics.cells_used = 0; - shm_header_p->statistics.cells_system = 1; - - shm_header_p->consistent = True; - - return True; -} - -static BOOL shm_close( void ) -{ - return True; -} - - -static int shm_get_userdef_off(void) -{ - if (!shm_header_p) - return 0; - else - return shm_header_p->userdef_off; -} - - -/******************************************************************* - Lock a particular hash bucket entry. - ******************************************************************/ -static BOOL shm_lock_hash_entry(unsigned int entry) -{ - return sem_change(entry+1, -1); -} - -/******************************************************************* - Unlock a particular hash bucket entry. - ******************************************************************/ -static BOOL shm_unlock_hash_entry(unsigned int entry) -{ - return sem_change(entry+1, 1); -} - - -/******************************************************************* - Gather statistics on shared memory usage. - ******************************************************************/ -static BOOL shm_get_usage(int *bytes_free, - int *bytes_used, - int *bytes_overhead) -{ - if(!shm_header_p) { - /* not mapped yet */ - DEBUG(0,("ERROR shm_free : shmem not mapped\n")); - return False; - } - - *bytes_free = shm_header_p->statistics.cells_free * CellSize; - *bytes_used = shm_header_p->statistics.cells_used * CellSize; - *bytes_overhead = shm_header_p->statistics.cells_system * CellSize + - AlignedHeaderSize; - - return True; -} - - -/******************************************************************* -hash a number into a hash_entry - ******************************************************************/ -static unsigned shm_hash_size(void) -{ - return hash_size; -} - - -static struct shmem_ops shmops = { - shm_close, - shm_alloc, - shm_free, - shm_get_userdef_off, - shm_offset2addr, - shm_addr2offset, - shm_lock_hash_entry, - shm_unlock_hash_entry, - shm_get_usage, - shm_hash_size, -}; - -/******************************************************************* - open the shared memory - ******************************************************************/ - -struct shmem_ops *sysv_shm_open(int ronly) -{ - BOOL other_processes; - struct shmid_ds shm_ds; - struct semid_ds sem_ds; - union semun su; - int i; - pid_t pid; - struct passwd *root_pwd = sys_getpwuid((uid_t)0); - gid_t root_gid = root_pwd ? root_pwd->pw_gid : (gid_t)0; - - read_only = ronly; - - shm_size = lp_shmem_size(); - - DEBUG(4,("Trying sysv shmem open of size %d\n", shm_size)); - - /* first the semaphore */ - sem_id = semget(SEMAPHORE_KEY, 0, 0); - if (sem_id == -1) { - if (read_only) return NULL; - - hash_size = SHMEM_HASH_SIZE; - - while (hash_size > 1) { - sem_id = semget(SEMAPHORE_KEY, hash_size+1, - IPC_CREAT|IPC_EXCL| SEMAPHORE_PERMS); - if (sem_id != -1 || - (errno != EINVAL && errno != ENOSPC)) break; - hash_size -= 5; - } - - if (sem_id == -1) { - DEBUG(0,("Can't create or use semaphore [1]. Error was %s\n", - strerror(errno))); - return NULL; - } - - if (sem_id != -1) { - su.val = 1; - for (i=0;i - * for pointing this out. - */ - - shm_id = shmget(SHMEM_KEY, 0, 0); - - /* if that failed then create one */ - if (shm_id == -1) { - if (read_only) return NULL; - while (shm_size > MIN_SHM_SIZE) { - shm_id = shmget(SHMEM_KEY, shm_size, - IPC_CREAT | IPC_EXCL | IPC_PERMS); - if (shm_id != -1 || - (errno != EINVAL && errno != ENOSPC)) break; - shm_size *= 0.8; - } - } - - if (shm_id == -1) { - DEBUG(0,("Can't create or use IPC area. Error was %s\n", strerror(errno))); - global_unlock(); - return NULL; - } - - - shm_header_p = (struct ShmHeader *)shmat(shm_id, 0, - read_only?SHM_RDONLY:0); - if ((long)shm_header_p == -1) { - DEBUG(0,("Can't attach to IPC area. Error was %s\n", strerror(errno))); - global_unlock(); - return NULL; - } - - /* to find out if some other process is already mapping the file, - we use a registration file containing the processids of the file - mapping processes */ - if (shmctl(shm_id, IPC_STAT, &shm_ds) != 0) { - DEBUG(0,("ERROR shmctl : can't IPC_STAT. Error was %s\n", strerror(errno))); - global_unlock(); - return NULL; - } - - if (!read_only) { - if (shm_ds.shm_perm.cuid != 0 || ((shm_ds.shm_perm.cgid != root_gid) && (shm_ds.shm_perm.cgid != 0))) { - DEBUG(0,("ERROR: root did not create the shmem\n")); - global_unlock(); - return NULL; - } - } - - shm_size = shm_ds.shm_segsz; - - other_processes = (shm_ds.shm_nattch > 1); - - if (!read_only && !other_processes) { - memset((char *)shm_header_p, 0, shm_size); - shm_initialize(shm_size); - shm_create_hash_table(hash_size); - DEBUG(3,("Initialised IPC area of size %d\n", shm_size)); - } else if (!shm_validate_header(shm_size)) { - /* existing file is corrupt, samba admin should remove - it by hand */ - DEBUG(0,("ERROR shm_open : corrupt IPC area - remove it!\n")); - global_unlock(); - return NULL; - } - - global_unlock(); - return &shmops; -} - - - -#else - int ipc_dummy_procedure(void) -{return 0;} -#endif -- cgit From 4b37a2c1ee8b7bedeb10950a4bae80b7545df2c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 22 Dec 1999 00:08:25 +0000 Subject: when no shares are returned the *shares pointer must be set to null (This used to be commit 84fe2337c701a52c6dc5cd8c1f6e9050478703f1) --- source3/locking/locking.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index fc4ce725c5..156ff016ea 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -227,6 +227,8 @@ int get_share_modes(connection_struct *conn, struct locking_data *data; int ret; + *shares = NULL; + dbuf = tdb_fetch(tdb, locking_key(dev, inode)); if (!dbuf.dptr) return 0; -- cgit From 9a781a8c6de9513ba5f4cafef41379fae96807c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2000 23:00:27 +0000 Subject: - added tdb_flags option to tdb_open() - added TDB_CLEAR_IF_FIRST flag to clear the database if this is the first attached process. Useful for non-persistent databases like our locking area (this will also make upgrades to new database layouts easier) - use lock_path() in a couple of places - leave connections database open while smbd running - cleaned up some tdb code a little, using macros for constants (This used to be commit 00e9da3ca577527db392aced62f02c69cfee8f4f) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 156ff016ea..dafd324edc 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -159,7 +159,7 @@ BOOL locking_init(int read_only) if (tdb) return True; tdb = tdb_open(lock_path("locking.tdb"), - 0, + 0, TDB_CLEAR_IF_FIRST, read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); -- cgit From 574788039f53fada4769731ea3fafe9710417b71 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 Jan 2000 03:17:16 +0000 Subject: added the unexpected packet database (unexpected.tdb) this means "nmblookup -S" now always works, even with broken servers the database stores all unexpected replies and these can be accessed by any client. while doing this I cleaned up a couple of functions, and put in place a better trn_id generator. in most places the code got quite a bit simpler due to the addition of simple helper functions. I haven't yet put the code in to take advantage of this for pdc replies - that will be next. Jeremys pdc finding code will then work :) (This used to be commit 280e6359d36c9bc8dcded302f15c3a1db8e3feeb) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index dafd324edc..78d5899322 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -480,7 +480,7 @@ static void (*traverse_callback)(share_mode_entry *, char *); traverse the whole database with this function, calling traverse_callback on each share mode ****************************************************************************/ -int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) +static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) { struct locking_data *data; share_mode_entry *shares; -- cgit From 6c2a1fdf360a8fcb100543fdb994860fe6268102 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 13 Jan 2000 12:09:36 +0000 Subject: the bulk of the new byte range locking coode it doesn't map to posix locks yet, that will come later. (This used to be commit 7f2a493095887cb0aae915ac36b9cded71d3a7a7) --- source3/locking/brlock.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++ source3/locking/locking.c | 66 ++++------- 2 files changed, 296 insertions(+), 45 deletions(-) create mode 100644 source3/locking/brlock.c (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c new file mode 100644 index 0000000000..5d928daa58 --- /dev/null +++ b/source3/locking/brlock.c @@ -0,0 +1,275 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + byte range locking code + Copyright (C) Andrew Tridgell 1992-1998 + + 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. +*/ + +/* this module implements a tdb based byte range locking service, + replacing the fcntl() based byte range locking previously + used. This allows us to provide the same semantics as NT */ + +#include "includes.h" + +extern int DEBUGLEVEL; + +/* this contains elements that differentiate locks. The smbpid is a + client supplied pid, and is essentially the locking context for + this client */ +struct lock_context { + uint16 smbpid; + uint16 tid; + pid_t pid; +}; + +/* the data in brlock records is an unsorted linear array of these + records. It is unnecessary to store the count as tdb provides the + size of the record */ +struct lock_struct { + struct lock_context context; + br_off start; + br_off size; + enum lock_type lock_type; +}; + +/* the key used in the brlock database */ +struct lock_key { + SMB_DEV_T device; + SMB_INO_T inode; +}; + +/* the open brlock.tdb database */ +static TDB_CONTEXT *tdb; + + +/**************************************************************************** +see if two locking contexts are equal +****************************************************************************/ +static BOOL brl_same_context(struct lock_context *ctx1, + struct lock_context *ctx2) +{ + return (ctx1->pid == ctx2->pid) && + (ctx1->smbpid == ctx2->smbpid) && + (ctx1->tid == ctx2->tid); +} + +/**************************************************************************** +see if lock2 can be added when lock1 is in place +****************************************************************************/ +static BOOL brl_conflict(struct lock_struct *lck1, + struct lock_struct *lck2) +{ + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) return False; + + if (brl_same_context(&lck1->context, &lck2->context) && + lck2->lock_type == READ_LOCK) return False; + + if (lck1->start >= (lck2->start + lck2->size) || + lck2->start >= (lck1->start + lck1->size)) return False; + + return True; +} + + +/**************************************************************************** +open up the brlock.tdb database +****************************************************************************/ +void brl_init(void) +{ + if (tdb) return; + tdb = tdb_open(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST, + O_RDWR | O_CREAT, 0644); + if (!tdb) { + DEBUG(0,("Failed to open byte range locking database\n")); + } +} + + +/**************************************************************************** +lock a range of bytes +****************************************************************************/ +BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, + uint16 smbpid, pid_t pid, uint16 tid, + br_off start, br_off size, + enum lock_type lock_type) +{ + struct lock_key key; + TDB_DATA kbuf, dbuf; + int count, i; + struct lock_struct lock, *locks; + + key.device = dev; + key.inode = ino; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + + dbuf.dptr = NULL; + + tdb_lockchain(tdb, kbuf); + dbuf = tdb_fetch(tdb, kbuf); + + lock.context.smbpid = smbpid; + lock.context.pid = pid; + lock.context.tid = tid; + lock.start = start; + lock.size = size; + lock.lock_type = lock_type; + + if (dbuf.dptr) { + /* there are existing locks - make sure they don't conflict */ + locks = (struct lock_struct *)dbuf.dptr; + count = dbuf.dsize / sizeof(*locks); + for (i=0; ifd_ptr->real_open_flags == O_RDONLY)) { - /* - * Many UNIX's cannot get a write lock on a file opened read-only. - * Win32 locking semantics allow this. - * Do the best we can and attempt a read-only lock. - */ - DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n")); - return F_RDLCK; - } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { - /* - * Ditto for read locks on write only files. - */ - DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n")); - return F_WRLCK; - } - - /* - * This return should be the most normal, as we attempt - * to always open files read/write. - */ - - return lock_type; -} - /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ BOOL is_locked(files_struct *fsp,connection_struct *conn, - SMB_OFF_T count,SMB_OFF_T offset, int lock_type) + SMB_OFF_T count,SMB_OFF_T offset, + enum lock_type lock_type) { int snum = SNUM(conn); @@ -82,13 +53,9 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - /* - * Note that most UNIX's can *test* for a write lock on - * a read-only fd, just not *set* a write lock on a read-only - * fd. So we don't need to use map_lock_type here. - */ - - return(fcntl_lock(fsp->fd_ptr->fd,SMB_F_GETLK,offset,count,lock_type)); + return !brl_locktest(fsp->fd_ptr->inode, fsp->fd_ptr->dev, + 1, getpid(), conn->cnum, + offset, count, lock_type); } @@ -96,7 +63,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, Utility function called by locking requests. ****************************************************************************/ BOOL do_lock(files_struct *fsp,connection_struct *conn, - SMB_OFF_T count,SMB_OFF_T offset,int lock_type, + SMB_OFF_T count,SMB_OFF_T offset,enum lock_type lock_type, int *eclass,uint32 *ecode) { BOOL ok = False; @@ -113,9 +80,12 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, DEBUG(10,("do_lock: lock type %d start=%.0f len=%.0f requested for file %s\n", lock_type, (double)offset, (double)count, fsp->fsp_name )); - if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, - map_lock_type(fsp,lock_type)); + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { + ok = brl_lock(fsp->fd_ptr->inode, fsp->fd_ptr->dev, + 1, getpid(), conn->cnum, + offset, count, + lock_type); + } if (!ok) { *eclass = ERRDOS; @@ -130,7 +100,8 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, Utility function called by unlocking requests. ****************************************************************************/ BOOL do_unlock(files_struct *fsp,connection_struct *conn, - SMB_OFF_T count,SMB_OFF_T offset,int *eclass,uint32 *ecode) + SMB_OFF_T count,SMB_OFF_T offset, + int *eclass,uint32 *ecode) { BOOL ok = False; @@ -140,8 +111,11 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", (double)offset, (double)count, fsp->fsp_name )); - if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { + ok = brl_unlock(fsp->fd_ptr->inode, fsp->fd_ptr->dev, + 1, getpid(), conn->cnum, + offset, count); + } if (!ok) { *eclass = ERRDOS; @@ -156,6 +130,8 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, ****************************************************************************/ BOOL locking_init(int read_only) { + brl_init(); + if (tdb) return True; tdb = tdb_open(lock_path("locking.tdb"), -- cgit From 2afd5d5eb5c176f09a9f4f00ea3b517e89ef0ddf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 14 Jan 2000 00:50:48 +0000 Subject: some more work on the byte range locking note the ugly global_smbpid - I hope that won't bethere for long, I just didn't want to do two lots of major surgery at the one time. Using global_smbpid avoids the big change of getting rid of our inbuf/outbuf interface to reply routines. I'll do that once the locking stuff passes all tests. (This used to be commit f8bebf91abcaa5bda3ec8701f9242f220da8943a) --- source3/locking/locking.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index a0d140bffd..e95ec08c58 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -38,6 +38,8 @@ extern int DEBUGLEVEL; /* the locking database handle */ static TDB_CONTEXT *tdb; +int global_smbpid; + /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ @@ -53,8 +55,8 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - return !brl_locktest(fsp->fd_ptr->inode, fsp->fd_ptr->dev, - 1, getpid(), conn->cnum, + return !brl_locktest(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + global_smbpid, getpid(), conn->cnum, offset, count, lock_type); } @@ -81,8 +83,8 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, lock_type, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - ok = brl_lock(fsp->fd_ptr->inode, fsp->fd_ptr->dev, - 1, getpid(), conn->cnum, + ok = brl_lock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + global_smbpid, getpid(), conn->cnum, offset, count, lock_type); } @@ -112,8 +114,8 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - ok = brl_unlock(fsp->fd_ptr->inode, fsp->fd_ptr->dev, - 1, getpid(), conn->cnum, + ok = brl_unlock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + global_smbpid, getpid(), conn->cnum, offset, count); } -- cgit From 82af221e4a7e456f580f16bc5d2fd904fc018c96 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 14 Jan 2000 04:32:57 +0000 Subject: we now pass all byte range locking tests the last piece was to use a smb timeout slightly larger than the locking timeout in bloking locks to prevent a race (This used to be commit 1b54cb4a33a65e62c2e3189b78ef073869a60c75) --- source3/locking/brlock.c | 59 +++++++++++++++++++++++++++++++++++++++++++++-- source3/locking/locking.c | 17 ++++++++++++-- 2 files changed, 72 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 5d928daa58..653a40728b 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -43,6 +43,7 @@ struct lock_struct { struct lock_context context; br_off start; br_off size; + int fnum; enum lock_type lock_type; }; @@ -102,7 +103,7 @@ void brl_init(void) /**************************************************************************** lock a range of bytes ****************************************************************************/ -BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, +BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, enum lock_type lock_type) @@ -127,6 +128,7 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, lock.context.tid = tid; lock.start = start; lock.size = size; + lock.fnum = fnum; lock.lock_type = lock_type; if (dbuf.dptr) { @@ -161,7 +163,7 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, /**************************************************************************** unlock a range of bytes ****************************************************************************/ -BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, +BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size) { @@ -192,6 +194,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, count = dbuf.dsize / sizeof(*locks); for (i=0; i 1 && i < count-1) { + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((count-1) - i)); + } + count--; + i--; + } + } + + if (count == 0) { + tdb_delete(tdb, kbuf); + } else if (count < (dbuf.dsize / sizeof(*locks))) { + tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); + } + + /* we didn't find it */ + fail: + if (dbuf.dptr) free(dbuf.dptr); + tdb_unlockchain(tdb, kbuf); +} diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e95ec08c58..350057d1a7 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -40,6 +40,19 @@ static TDB_CONTEXT *tdb; int global_smbpid; + +/**************************************************************************** +remove any locks on this fd +****************************************************************************/ +void locking_close_file(files_struct *fsp) +{ + if (!lp_locking(SNUM(fsp->conn))) return; + + brl_close(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + getpid(), fsp->conn->cnum, fsp->fnum); +} + + /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ @@ -83,7 +96,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, lock_type, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - ok = brl_lock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + ok = brl_lock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, fsp->fnum, global_smbpid, getpid(), conn->cnum, offset, count, lock_type); @@ -114,7 +127,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - ok = brl_unlock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + ok = brl_unlock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, fsp->fnum, global_smbpid, getpid(), conn->cnum, offset, count); } -- cgit From 7bc1cc7e07991641d436b2c8a35b52663d4c5c05 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 14 Jan 2000 08:01:44 +0000 Subject: damn, Solaris already has a "enum lock_type" changed it to "enum brl_type" (This used to be commit 6b9ee7662c7afa70f6b20889e6b0ae1dcd677f9f) --- source3/locking/brlock.c | 9 +++++---- source3/locking/locking.c | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 653a40728b..11766433fc 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -44,7 +44,7 @@ struct lock_struct { br_off start; br_off size; int fnum; - enum lock_type lock_type; + enum brl_type lock_type; }; /* the key used in the brlock database */ @@ -74,7 +74,8 @@ see if lock2 can be added when lock1 is in place static BOOL brl_conflict(struct lock_struct *lck1, struct lock_struct *lck2) { - if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) return False; + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) + return False; if (brl_same_context(&lck1->context, &lck2->context) && lck2->lock_type == READ_LOCK) return False; @@ -106,7 +107,7 @@ lock a range of bytes BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, - enum lock_type lock_type) + enum brl_type lock_type) { struct lock_key key; TDB_DATA kbuf, dbuf; @@ -231,7 +232,7 @@ test if we could add a lock if we wanted to BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, - enum lock_type lock_type) + enum brl_type lock_type) { struct lock_key key; TDB_DATA kbuf, dbuf; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 350057d1a7..5348659917 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -58,7 +58,7 @@ void locking_close_file(files_struct *fsp) ****************************************************************************/ BOOL is_locked(files_struct *fsp,connection_struct *conn, SMB_OFF_T count,SMB_OFF_T offset, - enum lock_type lock_type) + enum brl_type lock_type) { int snum = SNUM(conn); @@ -78,7 +78,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, Utility function called by locking requests. ****************************************************************************/ BOOL do_lock(files_struct *fsp,connection_struct *conn, - SMB_OFF_T count,SMB_OFF_T offset,enum lock_type lock_type, + SMB_OFF_T count,SMB_OFF_T offset,enum brl_type lock_type, int *eclass,uint32 *ecode) { BOOL ok = False; -- cgit From 54e1176ba17eaaba82254e4b629fa135802cec10 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2000 11:14:44 +0000 Subject: added code to allow traversal of the byte range lock database this is used with "smbstatus -B" to dump the lock list (This used to be commit 5f022629146701e6d543f77007dc944e4277ab0c) --- source3/locking/brlock.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- source3/locking/locking.c | 2 +- 2 files changed, 43 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 11766433fc..7e8adf4f86 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -90,11 +90,11 @@ static BOOL brl_conflict(struct lock_struct *lck1, /**************************************************************************** open up the brlock.tdb database ****************************************************************************/ -void brl_init(void) +void brl_init(int read_only) { if (tdb) return; tdb = tdb_open(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST, - O_RDWR | O_CREAT, 0644); + read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); if (!tdb) { DEBUG(0,("Failed to open byte range locking database\n")); } @@ -329,3 +329,43 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) if (dbuf.dptr) free(dbuf.dptr); tdb_unlockchain(tdb, kbuf); } + + +static void (*traverse_callback)(SMB_DEV_T dev, SMB_INO_T ino, int pid, + enum brl_type lock_type, + br_off start, br_off size); + +/**************************************************************************** +traverse the whole database with this function, calling traverse_callback +on each lock +****************************************************************************/ +static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) +{ + struct lock_struct *locks; + struct lock_key *key; + int i; + + locks = (struct lock_struct *)dbuf.dptr; + key = (struct lock_key *)kbuf.dptr; + + for (i=0;idevice, key->inode, + locks[i].context.pid, + locks[i].lock_type, + locks[i].start, + locks[i].size); + } + return 0; +} + +/******************************************************************* + Call the specified function on each lock in the database +********************************************************************/ +int brl_forall(void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, int pid, + enum brl_type lock_type, + br_off start, br_off size)) +{ + if (!tdb) return 0; + traverse_callback = fn; + return tdb_traverse(tdb, traverse_fn); +} diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 5348659917..9753b5ea61 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -145,7 +145,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, ****************************************************************************/ BOOL locking_init(int read_only) { - brl_init(); + brl_init(read_only); if (tdb) return True; -- cgit From bbe275e95b86bc7af5a641455cbb379974823f84 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 4 Feb 2000 04:59:31 +0000 Subject: 1) added void* state argument to tdb_traverse. guess what! there were two places i found where it was appropriate to _use_ that third argument, in locking.c and brlock.c! there was a static traverse_function and i removed the static variable, typecast it to a void*, passed it to tdb_traverse and re-cast it back to the traverse_function inside the tdb_traverse function. this makes the use of tdb_traverse() reentrant, which is never going to happen, i know, i just don't like to see statics lying about when there's no need for them. as i had to do in samba-tng, all uses of tdb_traverse modified to take the new void* state argument. 2) disabled rpcclient: referring people to use SAMBA_TNG rpcclient. i don't know how the other samba team members would react if i deleted rpcclient from cvs main. damn, that code's so old, it's unreal. 20 rpcclient commands, instead of about 70 in SAMBA_TNG. (This used to be commit 49d7f0afbc1c5425d53019e234d54ddf205c8e9a) --- source3/locking/brlock.c | 15 +++++---------- source3/locking/locking.c | 10 +++++----- 2 files changed, 10 insertions(+), 15 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 7e8adf4f86..71fc45854a 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -331,20 +331,18 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) } -static void (*traverse_callback)(SMB_DEV_T dev, SMB_INO_T ino, int pid, - enum brl_type lock_type, - br_off start, br_off size); - /**************************************************************************** traverse the whole database with this function, calling traverse_callback on each lock ****************************************************************************/ -static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) +static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) { struct lock_struct *locks; struct lock_key *key; int i; + BRLOCK_FN(traverse_callback) = (BRLOCK_FN_CAST())state; + locks = (struct lock_struct *)dbuf.dptr; key = (struct lock_key *)kbuf.dptr; @@ -361,11 +359,8 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) /******************************************************************* Call the specified function on each lock in the database ********************************************************************/ -int brl_forall(void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, int pid, - enum brl_type lock_type, - br_off start, br_off size)) +int brl_forall(BRLOCK_FN(fn)) { if (!tdb) return 0; - traverse_callback = fn; - return tdb_traverse(tdb, traverse_fn); + return tdb_traverse(tdb, traverse_fn, (BRLOCK_FN_CAST())fn); } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 9753b5ea61..890214f10e 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -465,19 +465,20 @@ BOOL modify_share_mode(files_struct *fsp, int new_mode, uint16 new_oplock) return mod_share_mode(fsp, modify_share_mode_fn, (void *)&mv); } -static void (*traverse_callback)(share_mode_entry *, char *); /**************************************************************************** traverse the whole database with this function, calling traverse_callback on each share mode ****************************************************************************/ -static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) +static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state) { struct locking_data *data; share_mode_entry *shares; char *name; int i; + SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state; + data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); name = dbuf.dptr + sizeof(*data) + data->num_share_mode_entries*sizeof(*shares); @@ -492,9 +493,8 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) Call the specified function on each entry under management by the share mode system. ********************************************************************/ -int share_mode_forall(void (*fn)(share_mode_entry *, char *)) +int share_mode_forall(SHAREMODE_FN(fn)) { if (!tdb) return 0; - traverse_callback = fn; - return tdb_traverse(tdb, traverse_fn); + return tdb_traverse(tdb, traverse_fn, (void*)fn); } -- cgit From ebbb007ed274c975ef5f36f6eb10e6e46df00dcb Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 7 Feb 2000 00:24:04 +0000 Subject: Fixed compile warning in locking.c:traverse_fn() (This used to be commit eefc8972217e5a700b90f13ab040a0919f184d23) --- source3/locking/locking.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 890214f10e..2f85e92932 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -470,7 +470,8 @@ BOOL modify_share_mode(files_struct *fsp, int new_mode, uint16 new_oplock) traverse the whole database with this function, calling traverse_callback on each share mode ****************************************************************************/ -static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state) +static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, + void* state) { struct locking_data *data; share_mode_entry *shares; -- cgit From b36ea9a7e1fadc30a78c4eb2aabab9ff2011eacd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Apr 2000 12:58:14 +0000 Subject: the first of a bunch of changes to code with getting rid of the fd_ptr element in the fsp pretty mechanical stuff, but it affects lots of files. (This used to be commit 368b0bc1b122ece18d11854c1506517816a01a82) --- source3/locking/locking.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 2f85e92932..45d414daf1 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -48,7 +48,7 @@ void locking_close_file(files_struct *fsp) { if (!lp_locking(SNUM(fsp->conn))) return; - brl_close(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + brl_close(fsp->dev, fsp->inode, getpid(), fsp->conn->cnum, fsp->fnum); } @@ -68,7 +68,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - return !brl_locktest(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + return !brl_locktest(fsp->dev, fsp->inode, global_smbpid, getpid(), conn->cnum, offset, count, lock_type); } @@ -96,7 +96,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, lock_type, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - ok = brl_lock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, fsp->fnum, + ok = brl_lock(fsp->dev, fsp->inode, fsp->fnum, global_smbpid, getpid(), conn->cnum, offset, count, lock_type); @@ -127,7 +127,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - ok = brl_unlock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, fsp->fnum, + ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, global_smbpid, getpid(), conn->cnum, offset, count); } @@ -186,7 +186,7 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) } static TDB_DATA locking_key_fsp(files_struct *fsp) { - return locking_key(fsp->fd_ptr->dev, fsp->fd_ptr->inode); + return locking_key(fsp->dev, fsp->inode); } /******************************************************************* @@ -207,6 +207,23 @@ BOOL unlock_share_entry(connection_struct *conn, return tdb_unlockchain(tdb, locking_key(dev, inode)) == 0; } + +/******************************************************************* + Lock a hash bucket entry. use a fsp for convenience +******************************************************************/ +BOOL lock_share_entry_fsp(files_struct *fsp) +{ + return tdb_lockchain(tdb, locking_key(fsp->dev, fsp->inode)) == 0; +} + +/******************************************************************* + Unlock a hash bucket entry. +******************************************************************/ +BOOL unlock_share_entry_fsp(files_struct *fsp) +{ + return tdb_unlockchain(tdb, locking_key(fsp->dev, fsp->inode)) == 0; +} + /******************************************************************* Get all share mode entries for a dev/inode pair. ********************************************************************/ @@ -370,7 +387,7 @@ static BOOL mod_share_mode(files_struct *fsp, shares[i].share_mode == fsp->share_mode && memcmp(&shares[i].time, &fsp->open_time,sizeof(struct timeval)) == 0) { - mod_fn(&shares[i], fsp->fd_ptr->dev, fsp->fd_ptr->inode, param); + mod_fn(&shares[i], fsp->dev, fsp->inode, param); need_store=1; } } -- cgit From f6be38cae223f1ad3f4ecc5b81d14c44d92f58ba Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Apr 2000 19:44:54 +0000 Subject: include/byteorder.h: ALIGN4/ALIGN2 macros. include/includes.h: Added SMB_BIG_UINT_BITS. lib/util.c: Removed align2/align4 - use macros. libsmb/namequery.c: Use ALIGN2. locking/locking.c: Replace do_lock, do_unlock, args with SMB_BIG_UINT, not SMB_OFF_T. Needed to move to hiding POSIX locks at a lower layer. nmbd/nmbd_processlogon.c: Use ALIGN2/ALIGN4 macros. smbd/blocking.c: Replace do_lock, do_unlock, args with SMB_BIG_UINT, not SMB_OFF_T. smbd/reply.c: Replace do_lock, do_unlock, args with SMB_BIG_UINT, not SMB_OFF_T. Jeremy. (This used to be commit 491eea8a20bf80d426625479326211dc975857a6) --- source3/locking/locking.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 45d414daf1..1bb0a3b59c 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -57,7 +57,7 @@ void locking_close_file(files_struct *fsp) Utility function called to see if a file region is locked. ****************************************************************************/ BOOL is_locked(files_struct *fsp,connection_struct *conn, - SMB_OFF_T count,SMB_OFF_T offset, + SMB_BIG_UINT count,SMB_BIG_UINT offset, enum brl_type lock_type) { int snum = SNUM(conn); @@ -78,7 +78,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, Utility function called by locking requests. ****************************************************************************/ BOOL do_lock(files_struct *fsp,connection_struct *conn, - SMB_OFF_T count,SMB_OFF_T offset,enum brl_type lock_type, + SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, int *eclass,uint32 *ecode) { BOOL ok = False; @@ -115,7 +115,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, Utility function called by unlocking requests. ****************************************************************************/ BOOL do_unlock(files_struct *fsp,connection_struct *conn, - SMB_OFF_T count,SMB_OFF_T offset, + SMB_BIG_UINT count,SMB_BIG_UINT offset, int *eclass,uint32 *ecode) { BOOL ok = False; -- cgit From 8316237e9ca83d1bd0cecdc63d7e47b44cf13181 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Apr 2000 17:59:09 +0000 Subject: Code to map tdb locks onto POSIX. Mainly placeholder code at the moment, but the structure is done enough so that Andrew can look it over and give a yea/nay decision. Jeremy. (This used to be commit db96f83e34a139f47776fcbb5c1624fbf9d9943b) --- source3/locking/locking.c | 166 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 157 insertions(+), 9 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 1bb0a3b59c..72ca91566a 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -40,27 +40,134 @@ static TDB_CONTEXT *tdb; int global_smbpid; - /**************************************************************************** -remove any locks on this fd + Remove any locks on this fd. ****************************************************************************/ + void locking_close_file(files_struct *fsp) { - if (!lp_locking(SNUM(fsp->conn))) return; + if (!lp_locking(SNUM(fsp->conn))) + return; + + if(lp_posix_locking(SNUM(fsp->conn))) { + /* + * We need to release all POSIX locks we have on this + * fd. + */ + } + + /* + * Now release all the tdb locks. + */ + + brl_close(fsp->dev, fsp->inode, getpid(), fsp->conn->cnum, fsp->fnum); + + /* + * We now need to search our open file list for any other + * fd open on this file with outstanding POSIX locks. If we + * don't find one, great, just return. If we do find one then + * we have to add this file descriptor to the 'pending close' + * list of that fd, to stop the POSIX problem where the locks + * on *that* fd will get lost when we close this one. POSIX + * braindamage... JRA. + */ + + /* Placeholder for code here.... */ +} + +/**************************************************************************** + Debugging aid :-). +****************************************************************************/ + +static const char *lock_type_name(enum brl_type lock_type) +{ + return (lock_type == READ_LOCK) ? "READ" : "WRITE"; +} + +/**************************************************************************** + Check to see if the given unsigned lock range is within the possible POSIX + range. Modifies the given args to be in range if possible, just returns + False if not. +****************************************************************************/ - brl_close(fsp->dev, fsp->inode, - getpid(), fsp->conn->cnum, fsp->fnum); +static BOOL posix_lock_in_range(SMB_OFF_T *p_offset, SMB_OFF_T *p_count) +{ + /* Placeholder. */ + return True; } +/**************************************************************************** + POSIX function to see if a file region is locked. Returns True if the + lock could be granted, False if not. +****************************************************************************/ + +static BOOL posix_locktest(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) +{ + SMB_OFF_T offset = (SMB_OFF_T)u_offset; + SMB_OFF_T count = (SMB_OFF_T)u_count; + + DEBUG(10,("posix_locktest: File %s, offset = %.0f, count = %.0f, type = %s\n", + fsp->fsp_name, (double)offset, (double)count, lock_type_name(lock_type) )); + + if(!posix_lock_in_range(&offset, &count)) + return True; + + /* Placeholder - for now always return that the lock could be granted. */ + return True; +} + +/**************************************************************************** + POSIX function to acquire a lock. Returns True if the + lock could be granted, False if not. +****************************************************************************/ + +static BOOL get_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) +{ + SMB_OFF_T offset = (SMB_OFF_T)u_offset; + SMB_OFF_T count = (SMB_OFF_T)u_count; + + DEBUG(10,("get_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", + fsp->fsp_name, (double)offset, (double)count, lock_type_name(lock_type) )); + + if(!posix_lock_in_range(&offset, &count)) + return True; + + /* Placeholder - for now always return that the lock could be granted. */ + fsp->num_posix_locks++; + return True; +} + +/**************************************************************************** + POSIX function to release a lock. Returns True if the + lock could be granted, False if not. +****************************************************************************/ + +static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) +{ + SMB_OFF_T offset = (SMB_OFF_T)u_offset; + SMB_OFF_T count = (SMB_OFF_T)u_count; + + DEBUG(10,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", + fsp->fsp_name, (double)offset, (double)count )); + + if(!posix_lock_in_range(&offset, &count)) + return True; + + /* Placeholder - for now always return that the lock could be granted. */ + fsp->num_posix_locks--; + return True; +} /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ + BOOL is_locked(files_struct *fsp,connection_struct *conn, SMB_BIG_UINT count,SMB_BIG_UINT offset, enum brl_type lock_type) { int snum = SNUM(conn); + BOOL ret; if (count == 0) return(False); @@ -68,15 +175,28 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - return !brl_locktest(fsp->dev, fsp->inode, + ret = !brl_locktest(fsp->dev, fsp->inode, global_smbpid, getpid(), conn->cnum, offset, count, lock_type); -} + /* + * There is no lock held by an SMB daemon, check to + * see if there is a POSIX lock from a UNIX or NFS process. + * Note that as an optimisation we only bother to + * check this if the file is not exclusively + * oplocked. JRA. + */ + + if(!ret && !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_posix_locking(snum)) + ret = !posix_locktest(fsp, offset, count, lock_type); + + return ret; +} /**************************************************************************** Utility function called by locking requests. ****************************************************************************/ + BOOL do_lock(files_struct *fsp,connection_struct *conn, SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, int *eclass,uint32 *ecode) @@ -92,14 +212,33 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, return False; } - DEBUG(10,("do_lock: lock type %d start=%.0f len=%.0f requested for file %s\n", - lock_type, (double)offset, (double)count, fsp->fsp_name )); + DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n", + lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { ok = brl_lock(fsp->dev, fsp->inode, fsp->fnum, global_smbpid, getpid(), conn->cnum, offset, count, lock_type); + + if(ok && lp_posix_locking(SNUM(conn))) { + + /* + * Try and get a POSIX lock on this range. + */ + + ok = get_posix_lock(fsp, offset, count, lock_type); + + if(!ok) { + /* + * We failed to map - we must now remove the brl + * lock entry. + */ + (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + global_smbpid, getpid(), conn->cnum, + offset, count); + } + } } if (!ok) { @@ -130,6 +269,15 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, global_smbpid, getpid(), conn->cnum, offset, count); + + if(ok && lp_posix_locking(SNUM(conn))) { + + /* + * Release the POSIX lock on this range. + */ + + (void)release_posix_lock(fsp, offset, count); + } } if (!ok) { -- cgit From 96b3bf3140a57c6adeaedd9f7ed427d207d47ee9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Apr 2000 21:46:22 +0000 Subject: Implmented mapping of lock offset/count from 64 bit MS ranges to either 63 or 31 bit POSIX ranges. Code to get these locks not yet added. Jeremy. (This used to be commit 9c3b9146a3baff4b2e403ae8fac6c48df1b7e642) --- source3/locking/locking.c | 170 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 157 insertions(+), 13 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 72ca91566a..d72d3908ce 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -90,9 +90,153 @@ static const char *lock_type_name(enum brl_type lock_type) False if not. ****************************************************************************/ -static BOOL posix_lock_in_range(SMB_OFF_T *p_offset, SMB_OFF_T *p_count) +static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, + SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) { - /* Placeholder. */ + SMB_OFF_T offset; + SMB_OFF_T count; + +#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) + + /* + * In this case SMB_OFF_T is 64 bits, + * and the underlying system can handle 64 bit signed locks. + * Cast to signed type. + */ + + offset = (SMB_OFF_T)u_offset; + count = (SMB_OFF_T)u_count; + + /* + * POSIX lock ranges cannot be negative. + * Fail if any combination becomes negative. + */ + + if(offset < 0 || count < 0 || (offset + count < 0)) { + DEBUG(10,("posix_lock_in_range: negative range offset = %.0f, count = %.0f. Ignoring lock.\n", + (double)offset, (double)count )); + return False; + + /* + * In this case SMB_OFF_T is 64 bits, the offset and count + * fit within the positive range, and the underlying + * system can handle 64 bit locks. Just return as the + * cast values are ok. + */ + +#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * In this case either SMB_OFF_T is 32 bits, + * or the underlying system cannot handle 64 bit signed locks. + * Either way we have to try and mangle to fit within 31 bits. + * This is difficult. + */ + +#if defined(HAVE_BROKEN_FCNTL64_LOCKS) + + /* + * SMB_OFF_T is 64 bits, but we need to use 31 bits due to + * broken large locking. + */ + + if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) { + DEBUG(10,("posix_lock_in_range: top 32 bits not zero. offset = %.0f, count = %.0f. Ignoring lock.\n", + (double)u_offset, (double)u_count )); + /* Top 32 bits of offset or count were not zero. */ + return False; + } + + /* Cast from 64 bits unsigned to 64 bits signed. */ + offset = (SMB_OFF_T)u_offset; + count = (SMB_OFF_T)u_count; + + /* + * Check if we are within the 2^31 range. + */ + + { + int32 low_offset = (int32)offset; + int32 low_count = (int32)count; + + if(low_offset < 0 || low_count < 0 || (low_offset + low_count < 0)) { + DEBUG(10,("posix_lock_in_range: not within 2^31 range. low_offset = %d, low_count = %d. Ignoring lock.\n", + low_offset, low_count )); + return False; + } + } + + /* + * Ok - we can map from a 64 bit number to a 31 bit lock. + */ + +#else /* HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * SMB_OFF_T is 32 bits. + */ + +#if defined(HAVE_LONGLONG) + + /* + * SMB_BIG_UINT is 64 bits, we can do a 32 bit shift. + */ + + if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) { + DEBUG(10,("posix_lock_in_range: top 32 bits not zero. u_offset = %.0f, u_count = %.0f. Ignoring lock.\n", + (double)u_offset, (double)u_count )); + return False; + } + + /* Cast from 64 bits unsigned to 32 bits signed. */ + offset = (SMB_OFF_T)u_offset; + count = (SMB_OFF_T)u_count; + + /* + * Check if we are within the 2^31 range. + */ + + if(offset < 0 || count < 0 || (offset + count < 0)) { + DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n", + (int)offset, (int)count )); + return False; + } + +#else /* HAVE_LONGLONG */ + + /* + * SMB_BIG_UINT and SMB_OFF_T are both 32 bits, + * just cast. + */ + + /* Cast from 32 bits unsigned to 32 bits signed. */ + offset = (SMB_OFF_T)u_offset; + count = (SMB_OFF_T)u_count; + + /* + * Check if we are within the 2^31 range. + */ + + if(offset < 0 || count < 0 || (offset + count < 0)) { + DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n", + (int)offset, (int)count )); + return False; + } + +#endif /* HAVE_LONGLONG */ +#endif /* LARGE_SMB_OFF_T */ +#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * The mapping was successful. + */ + + DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n", + (double)offset, (double)count )); + + *offset_out = offset; + *count_out = count; + return True; } @@ -103,13 +247,13 @@ static BOOL posix_lock_in_range(SMB_OFF_T *p_offset, SMB_OFF_T *p_count) static BOOL posix_locktest(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) { - SMB_OFF_T offset = (SMB_OFF_T)u_offset; - SMB_OFF_T count = (SMB_OFF_T)u_count; + SMB_OFF_T offset; + SMB_OFF_T count; DEBUG(10,("posix_locktest: File %s, offset = %.0f, count = %.0f, type = %s\n", fsp->fsp_name, (double)offset, (double)count, lock_type_name(lock_type) )); - if(!posix_lock_in_range(&offset, &count)) + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) return True; /* Placeholder - for now always return that the lock could be granted. */ @@ -123,13 +267,13 @@ static BOOL posix_locktest(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UIN static BOOL get_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) { - SMB_OFF_T offset = (SMB_OFF_T)u_offset; - SMB_OFF_T count = (SMB_OFF_T)u_count; + SMB_OFF_T offset; + SMB_OFF_T count; - DEBUG(10,("get_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", + DEBUG(5,("get_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", fsp->fsp_name, (double)offset, (double)count, lock_type_name(lock_type) )); - if(!posix_lock_in_range(&offset, &count)) + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) return True; /* Placeholder - for now always return that the lock could be granted. */ @@ -144,13 +288,13 @@ static BOOL get_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UIN static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) { - SMB_OFF_T offset = (SMB_OFF_T)u_offset; - SMB_OFF_T count = (SMB_OFF_T)u_count; + SMB_OFF_T offset; + SMB_OFF_T count; - DEBUG(10,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", + DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", fsp->fsp_name, (double)offset, (double)count )); - if(!posix_lock_in_range(&offset, &count)) + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) return True; /* Placeholder - for now always return that the lock could be granted. */ -- cgit From a018d6b3262d0617242f8be10b4e2dfb96f813e1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Apr 2000 23:01:11 +0000 Subject: Removed "ole locking compat" parameter (no longer used). We now get/set/check POSIX locks, but I still need to code up the close fd braindamage... Jeremy. (This used to be commit 3de058bd43976853b0ed2b6b5529e2a3a08909eb) --- source3/locking/locking.c | 131 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 113 insertions(+), 18 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d72d3908ce..decc36fc03 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -84,6 +84,37 @@ static const char *lock_type_name(enum brl_type lock_type) return (lock_type == READ_LOCK) ? "READ" : "WRITE"; } +/**************************************************************************** + Utility function to map a lock type correctly depending on the open + mode of a file. +****************************************************************************/ + +static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) +{ + if((lock_type == WRITE_LOCK) && !fsp->can_write) { + /* + * Many UNIX's cannot get a write lock on a file opened read-only. + * Win32 locking semantics allow this. + * Do the best we can and attempt a read-only lock. + */ + DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n")); + return F_RDLCK; + } else if((lock_type == READ_LOCK) && !fsp->can_read) { + /* + * Ditto for read locks on write only files. + */ + DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n")); + return F_WRLCK; + } + + /* + * This return should be the most normal, as we attempt + * to always open files read/write. + */ + + return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK; +} + /**************************************************************************** Check to see if the given unsigned lock range is within the possible POSIX range. Modifies the given args to be in range if possible, just returns @@ -98,6 +129,10 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, #if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) + SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); + SMB_OFF_T mask = (mask2<<1); + SMB_OFF_T neg_mask = ~mask; + /* * In this case SMB_OFF_T is 64 bits, * and the underlying system can handle 64 bit signed locks. @@ -107,13 +142,21 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, offset = (SMB_OFF_T)u_offset; count = (SMB_OFF_T)u_count; + /* + * Deal with a very common case of count of all ones. + * (lock entire file). + */ + + if(count == (SMB_OFF_T)-1) + count &= ~mask; + /* * POSIX lock ranges cannot be negative. * Fail if any combination becomes negative. */ if(offset < 0 || count < 0 || (offset + count < 0)) { - DEBUG(10,("posix_lock_in_range: negative range offset = %.0f, count = %.0f. Ignoring lock.\n", + DEBUG(10,("posix_lock_in_range: negative range: offset = %.0f, count = %.0f. Ignoring lock.\n", (double)offset, (double)count )); return False; @@ -140,6 +183,14 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, * broken large locking. */ + /* + * Deal with a very common case of count of all ones. + * (lock entire file). + */ + + if(u_count == (SMB_BIG_UINT)-1) + count = 0x7FFFFFFF; + if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) { DEBUG(10,("posix_lock_in_range: top 32 bits not zero. offset = %.0f, count = %.0f. Ignoring lock.\n", (double)u_offset, (double)u_count )); @@ -182,6 +233,14 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, * SMB_BIG_UINT is 64 bits, we can do a 32 bit shift. */ + /* + * Deal with a very common case of count of all ones. + * (lock entire file). + */ + + if(u_count == (SMB_BIG_UINT)-1) + count = 0x7FFFFFFF; + if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) { DEBUG(10,("posix_lock_in_range: top 32 bits not zero. u_offset = %.0f, u_count = %.0f. Ignoring lock.\n", (double)u_offset, (double)u_count )); @@ -209,6 +268,14 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, * just cast. */ + /* + * Deal with a very common case of count of all ones. + * (lock entire file). + */ + + if(u_count == (SMB_BIG_UINT)-1) + count = 0x7FFFFFFF; + /* Cast from 32 bits unsigned to 32 bits signed. */ offset = (SMB_OFF_T)u_offset; count = (SMB_OFF_T)u_count; @@ -242,22 +309,32 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, /**************************************************************************** POSIX function to see if a file region is locked. Returns True if the - lock could be granted, False if not. + region is locked, False otherwise. ****************************************************************************/ -static BOOL posix_locktest(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) +static BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) { SMB_OFF_T offset; SMB_OFF_T count; - DEBUG(10,("posix_locktest: File %s, offset = %.0f, count = %.0f, type = %s\n", + DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", fsp->fsp_name, (double)offset, (double)count, lock_type_name(lock_type) )); + /* + * If the requested lock won't fit in the POSIX range, we will + * never set it, so presume it is not locked. + */ + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) - return True; + return False; - /* Placeholder - for now always return that the lock could be granted. */ - return True; + /* + * Note that most UNIX's can *test* for a write lock on + * a read-only fd, just not *set* a write lock on a read-only + * fd. So we don't need to use map_lock_type here. + */ + + return fcntl_lock(fsp->fd,SMB_F_GETLK,offset,count,lock_type); } /**************************************************************************** @@ -265,40 +342,58 @@ static BOOL posix_locktest(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UIN lock could be granted, False if not. ****************************************************************************/ -static BOOL get_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) +static BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) { SMB_OFF_T offset; SMB_OFF_T count; + BOOL ret = True; - DEBUG(5,("get_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", + DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", fsp->fsp_name, (double)offset, (double)count, lock_type_name(lock_type) )); + /* + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. + */ + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) return True; - /* Placeholder - for now always return that the lock could be granted. */ - fsp->num_posix_locks++; - return True; + ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,map_posix_lock_type(fsp,lock_type)); + + if(ret) + fsp->num_posix_locks++; + + return ret; } /**************************************************************************** POSIX function to release a lock. Returns True if the - lock could be granted, False if not. + lock could be released, False if not. ****************************************************************************/ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) { SMB_OFF_T offset; SMB_OFF_T count; + BOOL ret; DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", fsp->fsp_name, (double)offset, (double)count )); + /* + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. + */ + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) return True; - /* Placeholder - for now always return that the lock could be granted. */ - fsp->num_posix_locks--; + ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK); + + if(ret) + fsp->num_posix_locks--; + return True; } @@ -332,7 +427,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, */ if(!ret && !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_posix_locking(snum)) - ret = !posix_locktest(fsp, offset, count, lock_type); + ret = is_posix_locked(fsp, offset, count, lock_type); return ret; } @@ -371,7 +466,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, * Try and get a POSIX lock on this range. */ - ok = get_posix_lock(fsp, offset, count, lock_type); + ok = set_posix_lock(fsp, offset, count, lock_type); if(!ok) { /* @@ -393,10 +488,10 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, return True; /* Got lock */ } - /**************************************************************************** Utility function called by unlocking requests. ****************************************************************************/ + BOOL do_unlock(files_struct *fsp,connection_struct *conn, SMB_BIG_UINT count,SMB_BIG_UINT offset, int *eclass,uint32 *ecode) -- cgit From 019bab27c8ac811885a836eaf234a3ba6aa8a361 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Apr 2000 16:46:32 +0000 Subject: Typo - missing '}'. Jeremy. (This used to be commit 0216d81f061ee599a798fdbf25625fbbbd88ef08) --- source3/locking/locking.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index decc36fc03..9ea9e08ded 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -159,6 +159,7 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, DEBUG(10,("posix_lock_in_range: negative range: offset = %.0f, count = %.0f. Ignoring lock.\n", (double)offset, (double)count )); return False; + } /* * In this case SMB_OFF_T is 64 bits, the offset and count -- cgit From 4217c939ec6bdb80a3fe953e5b60f6f7b7a43635 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Apr 2000 20:41:04 +0000 Subject: locking/locking.c: Fixed placeholder code for POSIX locking. printing/printing.c: Cast tdb_delete to (tdb_traverse_func) to stop warning. tmpfile gives mirror warning. smbd/groupname.c: Remember to file_lines_free() on exit. tdb/tdb.h: Add tdb_traverse_func typedef. Jeremy (This used to be commit 204ca1195c86499bd9beb273ce573db7a56ccead) --- source3/locking/locking.c | 66 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 17 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 9ea9e08ded..bde1ffb567 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -60,6 +60,8 @@ void locking_close_file(files_struct *fsp) * Now release all the tdb locks. */ + /* Placeholder for code here.... */ +#if 0 brl_close(fsp->dev, fsp->inode, getpid(), fsp->conn->cnum, fsp->fnum); /* @@ -71,8 +73,7 @@ void locking_close_file(files_struct *fsp) * on *that* fd will get lost when we close this one. POSIX * braindamage... JRA. */ - - /* Placeholder for code here.... */ +#endif } /**************************************************************************** @@ -360,10 +361,15 @@ static BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UIN if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) return True; - ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,map_posix_lock_type(fsp,lock_type)); + /* + * Note that setting multiple overlapping read locks on different + * file descriptors will not be held separately by the kernel (POSIX + * braindamage), but will be merged into one continuous read lock + * range. We cope with this case in the release_posix_lock code + * below. JRA. + */ - if(ret) - fsp->num_posix_locks++; + ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,map_posix_lock_type(fsp,lock_type)); return ret; } @@ -377,11 +383,23 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG { SMB_OFF_T offset; SMB_OFF_T count; - BOOL ret; + BOOL ret = True; DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", fsp->fsp_name, (double)offset, (double)count )); + if(u_count == 0) { + + /* + * This lock must overlap with an existing read-only lock + * help by another fd. Just decrement the count but don't + * do any POSIX call. + */ + + fsp->num_posix_locks--; + return True; + } + /* * If the requested lock won't fit in the POSIX range, we will * pretend it was successful. @@ -422,12 +440,9 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, /* * There is no lock held by an SMB daemon, check to * see if there is a POSIX lock from a UNIX or NFS process. - * Note that as an optimisation we only bother to - * check this if the file is not exclusively - * oplocked. JRA. */ - if(!ret && !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_posix_locking(snum)) + if(!ret && lp_posix_locking(snum)) ret = is_posix_locked(fsp, offset, count, lock_type); return ret; @@ -465,11 +480,13 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, /* * Try and get a POSIX lock on this range. + * Note that this is ok if it is a read lock + * overlapping on a different fd. JRA. */ - ok = set_posix_lock(fsp, offset, count, lock_type); - - if(!ok) { + if((ok = set_posix_lock(fsp, offset, count, lock_type)) == True) + fsp->num_posix_locks++; + else { /* * We failed to map - we must now remove the brl * lock entry. @@ -506,18 +523,33 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, getpid(), conn->cnum, - offset, count); - if(ok && lp_posix_locking(SNUM(conn))) { + if(lp_posix_locking(SNUM(conn))) { + +#if 0 + /* + * The following call calculates if there are any + * overlapping read locks held by this process on + * other fd's open on the same file and truncates + * any overlapping range and returns the value in + * the non_overlap_XXX variables. Thus the POSIX + * unlock may not be done on the same region as + * the brl_lock. JRA. + */ + + brl_unlock_list(fsp->dev, fsp->inode, fsp->fnum, +#endif /* * Release the POSIX lock on this range. */ (void)release_posix_lock(fsp, offset, count); + fsp->num_posix_locks--; } + + ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + global_smbpid, getpid(), conn->cnum, offset, count); } if (!ok) { -- cgit From 6259f51dd9918eccc9697f3763d918f7c9b82b50 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 22 Apr 2000 00:33:16 +0000 Subject: This is a *big* checkin that may break some things, but implements the new open mechanism Andrew & I discussed. config.sub: configure: Included the QNX patch. include/vfs.h: smbd/vfs-wrap.c: smbd/vfs.c: Added ftruncate vfs call (needed). Note that we will also need locking calls in the vfs (to be added). lib/util_unistr.c: nmbd/nmbd_processlogon.c: Fix for NT domain logons causing nmbd to core dump. Also fix for sidsize DOS bug. locking/locking.c: Check value of ret before using it for memdup. printing/printing.c: Convert print_fsp_open to return an allocated fsp. rpc_server/srv_lsa.c: Fix for NT domain logons. I have removed all use of lp_share_modes() from the code (although I left the parameter in the table for backwards compatibility). It no longer makes sense for this to exist. smbd/close.c: Removed lp_share_modes(). smbd/fileio.c: Fixed parameters to unlock_share_entry call in panic code. smbd/files.c: Correctly set the unix_ERR_code to ERRnofids on fsp allocation fail. smbd/nttrans.c: smbd/reply.c: smbd/trans2.c: Changed all occurrences of open_file_shared/open_directory/ open_file_stat to return an fsp from the call. smbd/open.c: Changed all occurrences of open_file_shared/open_directory/ open_file_stat to return an fsp from the call. In addition I have fixed a long standing race condition in the deny mode processing w.r.t. two smbd's creating a file. Andrew, please note that your original idea of using open with O_EXCL in this case would not work (I went over the races very carefully) and so we must re-check deny modes *after* the open() call returns. This is because there is a race between the open with O_EXCL and the lock of the share mode entry. Imagine the case where the first smbd does the open with O_EXCL and a deny mode of DENY_ALL, but is pre-empted before it locks the share modes and creates the deny mode entry for DENY_ALL. A second smbd could then come in with O_RDONLY and a deny mode of DENY_NONE and the two opens would be allowed. The *only* way to fix this race is to lock the share modes after the open and then do the deny mode checks *after* this lock in the case where the file did not originally exist. This code will need extensive testing but seems to initially work. Jeremy. (This used to be commit ab0ecc39d688f16b9692fe90b991f0b89287070a) --- source3/locking/locking.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index bde1ffb567..affda89f08 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -662,7 +662,8 @@ int get_share_modes(connection_struct *conn, data = (struct locking_data *)dbuf.dptr; ret = data->num_share_mode_entries; - *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares)); + if(ret) + *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares)); free(dbuf.dptr); if (! *shares) return 0; -- cgit From a069d4d72fea8c283dd67a08ba30b49beefcd7de Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 23 Apr 2000 14:25:04 +0000 Subject: fixed a locking database bug - it was actually harmless except that smbstatus could display the wrong filename when files change dev/inum after a rename (This used to be commit 990b16fcf7af74f376db157a3e5de7bb68c1a4a1) --- source3/locking/locking.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index affda89f08..9f33cba338 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -708,7 +708,11 @@ void del_share_mode(files_struct *fsp) dbuf.dsize -= del_count * sizeof(*shares); /* store it back in the database */ - tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + if (data->num_share_mode_entries == 0) { + tdb_delete(tdb, locking_key_fsp(fsp)); + } else { + tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + } free(dbuf.dptr); } @@ -815,7 +819,11 @@ static BOOL mod_share_mode(files_struct *fsp, /* if the mod fn was called then store it back */ if (need_store) { - tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + if (data->num_share_mode_entries == 0) { + tdb_delete(tdb, locking_key_fsp(fsp)); + } else { + tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + } } free(dbuf.dptr); -- cgit From 644f22ac6141f58f2badd3a9761ac156831c16a3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Apr 2000 20:48:40 +0000 Subject: Added the code that keeps fd's open across a close if there are other fsp's open on the same dev/inode pair with existing POSIX locks. This is done at the smbd/open layer, so smbd just calls fd_close() and the transfer of any open fd's is done under the covers of fd_close(). When an fsp is closed and no other fsp's open on the same dev/inode pair have existing POSIX locks then all fd's associated with this fsp are closed. Now only the hard part of doing the POSIX range unlock code when read locks overlap remains for full POSIX/SMB lock integration.... Jeremy. (This used to be commit 1df48ed55ee303b6d84d7277fd79761cfe5f7052) --- source3/locking/locking.c | 59 ++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 36 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 9f33cba338..a73af8fd07 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -40,42 +40,6 @@ static TDB_CONTEXT *tdb; int global_smbpid; -/**************************************************************************** - Remove any locks on this fd. -****************************************************************************/ - -void locking_close_file(files_struct *fsp) -{ - if (!lp_locking(SNUM(fsp->conn))) - return; - - if(lp_posix_locking(SNUM(fsp->conn))) { - /* - * We need to release all POSIX locks we have on this - * fd. - */ - } - - /* - * Now release all the tdb locks. - */ - - /* Placeholder for code here.... */ -#if 0 - brl_close(fsp->dev, fsp->inode, getpid(), fsp->conn->cnum, fsp->fnum); - - /* - * We now need to search our open file list for any other - * fd open on this file with outstanding POSIX locks. If we - * don't find one, great, just return. If we do find one then - * we have to add this file descriptor to the 'pending close' - * list of that fd, to stop the POSIX problem where the locks - * on *that* fd will get lost when we close this one. POSIX - * braindamage... JRA. - */ -#endif -} - /**************************************************************************** Debugging aid :-). ****************************************************************************/ @@ -416,6 +380,29 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG return True; } +/**************************************************************************** + Remove any locks on this fd. Called from file_close(). +****************************************************************************/ + +void locking_close_file(files_struct *fsp) +{ + if (!lp_locking(SNUM(fsp->conn))) + return; + + if(lp_posix_locking(SNUM(fsp->conn))) { + /* + * We need to release all POSIX locks we have on this + * fd. + */ + } + + /* + * Now release all the tdb locks. + */ + + brl_close(fsp->dev, fsp->inode, getpid(), fsp->conn->cnum, fsp->fnum); +} + /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ -- cgit From e4d382750caa522b5e249d690fdb469d7b0c12a1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Apr 2000 20:30:58 +0000 Subject: Added the hard code :-). HEAD should now map brl locks correctly into POSIX locks, including the really nasty case of large range unlock. There is a lot of pretty ASCII art in locking/brlock.c explaining exactly how this code works. If it is unclear, please ask me. Jeremy. (This used to be commit 135855dbd3b8934a49229b81646cd4469acba926) --- source3/locking/brlock.c | 359 ++++++++++++++++++++++++++++++++++++++++++---- source3/locking/locking.c | 171 +++++++++++++++------- 2 files changed, 453 insertions(+), 77 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 71fc45854a..68daa7e0bb 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -2,7 +2,10 @@ Unix SMB/Netbios implementation. Version 3.0 byte range locking code - Copyright (C) Andrew Tridgell 1992-1998 + Updated to handle range splits/merges. + + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Jeremy Allison 1992-2000 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 @@ -19,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* this module implements a tdb based byte range locking service, +/* This module implements a tdb based byte range locking service, replacing the fcntl() based byte range locking previously used. This allows us to provide the same semantics as NT */ @@ -27,18 +30,20 @@ extern int DEBUGLEVEL; -/* this contains elements that differentiate locks. The smbpid is a +/* This contains elements that differentiate locks. The smbpid is a client supplied pid, and is essentially the locking context for this client */ + struct lock_context { uint16 smbpid; uint16 tid; pid_t pid; }; -/* the data in brlock records is an unsorted linear array of these +/* The data in brlock records is an unsorted linear array of these records. It is unnecessary to store the count as tdb provides the size of the record */ + struct lock_struct { struct lock_context context; br_off start; @@ -47,19 +52,21 @@ struct lock_struct { enum brl_type lock_type; }; -/* the key used in the brlock database */ +/* The key used in the brlock database. */ + struct lock_key { SMB_DEV_T device; SMB_INO_T inode; }; -/* the open brlock.tdb database */ -static TDB_CONTEXT *tdb; +/* The open brlock.tdb database. */ +static TDB_CONTEXT *tdb; /**************************************************************************** -see if two locking contexts are equal + See if two locking contexts are equal. ****************************************************************************/ + static BOOL brl_same_context(struct lock_context *ctx1, struct lock_context *ctx2) { @@ -69,8 +76,9 @@ static BOOL brl_same_context(struct lock_context *ctx1, } /**************************************************************************** -see if lock2 can be added when lock1 is in place + See if lock2 can be added when lock1 is in place. ****************************************************************************/ + static BOOL brl_conflict(struct lock_struct *lck1, struct lock_struct *lck2) { @@ -88,8 +96,9 @@ static BOOL brl_conflict(struct lock_struct *lck1, /**************************************************************************** -open up the brlock.tdb database + Open up the brlock.tdb database. ****************************************************************************/ + void brl_init(int read_only) { if (tdb) return; @@ -102,8 +111,9 @@ void brl_init(int read_only) /**************************************************************************** -lock a range of bytes + Lock a range of bytes. ****************************************************************************/ + BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, @@ -160,10 +170,238 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, return False; } +/**************************************************************************** + Create a list of lock ranges that don't overlap a given range. Used in calculating + POSIX lock unlocks. This is a difficult function that requires ASCII art to + understand it :-). +****************************************************************************/ + +struct unlock_list *brl_unlock_list(TALLOC_CTX *ctx, struct unlock_list *ulhead, + pid_t pid, SMB_DEV_T dev, SMB_INO_T ino) +{ + struct lock_key key; + TDB_DATA kbuf, dbuf; + struct lock_struct *locks; + int num_locks, i; + + /* + * Setup the key for this fetch. + */ + key.device = dev; + key.inode = ino; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + + dbuf.dptr = NULL; + + tdb_lockchain(tdb, kbuf); + dbuf = tdb_fetch(tdb, kbuf); + + if (!dbuf.dptr) { + tdb_unlockchain(tdb, kbuf); + return ulhead; + } + + locks = (struct lock_struct *)dbuf.dptr; + num_locks = dbuf.dsize / sizeof(*locks); + + /* + * Check the current lock list on this dev/inode pair. + * Quit if the list is deleted. + */ + + for (i=0; icontext.pid != pid) + continue; + + /* + * Walk the unlock list, checking for overlaps. Note that + * the unlock list can expand within this loop if the current + * range being examined needs to be split. + */ + + for (ul_curr = ulhead; ul_curr;) { + + DEBUG(10,("brl_unlock_list: curr: start=%.0f,size=%.0f \ +lock: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, + (double)lock->start, (double)lock->size )); + + if ( (ul_curr->start >= (lock->start + lock->size)) || + (lock->start > (ul_curr->start + ul_curr->size))) { + + /* No overlap with this lock - leave this range alone. */ +/********************************************* + +---------+ + | ul_curr | + +---------+ + +-------+ + | lock | + +-------+ +OR.... + +---------+ + | ul_curr | + +---------+ +**********************************************/ + + DEBUG(10,("brl_unlock_list: no overlap case.\n" )); + + ul_curr = ul_curr->next; + + } else if ( (ul_curr->start >= lock->start) && + (ul_curr->start + ul_curr->size <= lock->start + lock->size) ) { + + /* + * This unlock is completely overlapped by this existing lock range + * and thus should have no effect (not be unlocked). Delete it from the list. + */ +/********************************************* + +---------+ + | ul_curr | + +---------+ + +---------------------------+ + | lock | + +---------------------------+ +**********************************************/ + /* Save the next pointer */ + struct unlock_list *ul_next = ul_curr->next; + + DEBUG(10,("brl_unlock_list: delete case.\n" )); + + DLIST_REMOVE(ulhead, ul_curr); + if(ulhead == NULL) + break; /* No more list... */ + + ul_curr = ul_next; + + } else if ( (ul_curr->start >= lock->start) && + (ul_curr->start < lock->start + lock->size) && + (ul_curr->start + ul_curr->size > lock->start + lock->size) ) { + + /* + * This unlock overlaps the existing lock range at the high end. + * Truncate by moving start to existing range end and reducing size. + */ +/********************************************* + +---------------+ + | ul_curr | + +---------------+ + +---------------+ + | lock | + +---------------+ +BECOMES.... + +-------+ + |ul_curr| + +-------+ +**********************************************/ + + ul_curr->size = (ul_curr->start + ul_curr->size) - (lock->start + lock->size); + ul_curr->start = lock->start + lock->size; + + DEBUG(10,("brl_unlock_list: truncate high case: start=%.0f,size=%.0f\n", + (double)ul_curr->start, (double)ul_curr->size )); + + ul_curr = ul_curr->next; + + } else if ( (ul_curr->start < lock->start) && + (ul_curr->start + ul_curr->size > lock->start) ) { + + /* + * This unlock overlaps the existing lock range at the low end. + * Truncate by reducing size. + */ +/********************************************* + +---------------+ + | ul_curr | + +---------------+ + +---------------+ + | lock | + +---------------+ +BECOMES.... + +-------+ + |ul_curr| + +-------+ +**********************************************/ + + ul_curr->size = lock->start - ul_curr->start; + + DEBUG(10,("brl_unlock_list: truncate low case: start=%.0f,size=%.0f\n", + (double)ul_curr->start, (double)ul_curr->size )); + + ul_curr = ul_curr->next; + + } else if ( (ul_curr->start < lock->start) && + (ul_curr->start + ul_curr->size > lock->start + lock->size) ) { + /* + * Worst case scenario. Unlock request completely overlaps an existing + * lock range. Split the request into two, push the new (upper) request + * into the dlink list, and continue with the entry after ul_new (as we + * know that ul_new will not overlap with this lock). + */ +/********************************************* + +---------------------------+ + | ul_curr | + +---------------------------+ + +---------+ + | lock | + +---------+ +BECOMES..... + +-------+ +---------+ + |ul_curr| |ul_new | + +-------+ +---------+ +**********************************************/ + struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx, + sizeof(struct unlock_list)); + + if(ul_new == NULL) { + DEBUG(0,("brl_unlock_list: talloc fail.\n")); + return NULL; /* The talloc_destroy takes care of cleanup. */ + } + + ZERO_STRUCTP(ul_new); + ul_new->start = lock->start + lock->size; + ul_new->size = ul_curr->start + ul_curr->size - ul_new->start; + + /* Add into the dlink list after the ul_curr point - NOT at ulhead. */ + DLIST_ADD(ul_curr, ul_new); + + /* Truncate the ul_curr. */ + ul_curr->size = lock->start - ul_curr->start; + + DEBUG(10,("brl_unlock_list: split case: curr: start=%.0f,size=%.0f \ +new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, + (double)ul_new->start, (double)ul_new->size )); + + ul_curr = ul_new->next; + + } else { + + /* + * This logic case should never happen. Ensure this is the + * case by forcing an abort.... Remove in production. + */ + + smb_panic("brl_unlock_list: logic flaw in cases...\n"); + } + } /* end for ( ul_curr = ulhead; ul_curr;) */ + } /* end for (i=0; icontext, &context) && + lock->fnum == fnum && + lock->start == start && + lock->size == size) { /* found it - delete it */ if (count == 1) { tdb_delete(tdb, kbuf); @@ -224,11 +465,10 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, return False; } - - /**************************************************************************** -test if we could add a lock if we wanted to + Test if we could add a lock if we wanted to. ****************************************************************************/ + BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, @@ -278,10 +518,10 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, return False; } - /**************************************************************************** -remove any locks associated with a open file + Remove any locks associated with a open file. ****************************************************************************/ + void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) { struct lock_key key; @@ -305,9 +545,11 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) locks = (struct lock_struct *)dbuf.dptr; count = dbuf.dsize / sizeof(*locks); for (i=0; icontext.tid == tid && + lock->context.pid == pid && + lock->fnum == fnum) { /* found it - delete it */ if (count > 1 && i < count-1) { memmove(&locks[i], &locks[i+1], @@ -330,11 +572,73 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) tdb_unlockchain(tdb, kbuf); } +/**************************************************************************** + Return a lock list associated with an open file. +****************************************************************************/ + +struct unlock_list *brl_getlocklist( TALLOC_CTX *ctx, SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) +{ + struct lock_key key; + TDB_DATA kbuf, dbuf; + int i, count; + struct lock_struct *locks; + struct unlock_list *ulist = NULL; + + key.device = dev; + key.inode = ino; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + + dbuf.dptr = NULL; + + tdb_lockchain(tdb, kbuf); + dbuf = tdb_fetch(tdb, kbuf); + + if (!dbuf.dptr) { + tdb_unlockchain(tdb, kbuf); + return NULL; + } + + /* There are existing locks - allocate an entry for each one. */ + locks = (struct lock_struct *)dbuf.dptr; + count = dbuf.dsize / sizeof(*locks); + + for (i=0; icontext.tid == tid && + lock->context.pid == pid && + lock->fnum == fnum) { + + struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx, + sizeof(struct unlock_list)); + + if(ul_new == NULL) { + DEBUG(0,("brl_getlocklist: talloc fail.\n")); + return NULL; /* The talloc_destroy takes care of cleanup. */ + } + + ZERO_STRUCTP(ul_new); + ul_new->start = lock->start; + ul_new->size = lock->size; + + DLIST_ADD(ulist, ul_new); + } + } + + if (dbuf.dptr) + free(dbuf.dptr); + tdb_unlockchain(tdb, kbuf); + + return ulist; +} + /**************************************************************************** -traverse the whole database with this function, calling traverse_callback -on each lock + Traverse the whole database with this function, calling traverse_callback + on each lock. ****************************************************************************/ + static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) { struct lock_struct *locks; @@ -357,8 +661,9 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st } /******************************************************************* - Call the specified function on each lock in the database + Call the specified function on each lock in the database. ********************************************************************/ + int brl_forall(BRLOCK_FN(fn)) { if (!tdb) return 0; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index a73af8fd07..811dfbc101 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -380,29 +380,6 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG return True; } -/**************************************************************************** - Remove any locks on this fd. Called from file_close(). -****************************************************************************/ - -void locking_close_file(files_struct *fsp) -{ - if (!lp_locking(SNUM(fsp->conn))) - return; - - if(lp_posix_locking(SNUM(fsp->conn))) { - /* - * We need to release all POSIX locks we have on this - * fd. - */ - } - - /* - * Now release all the tdb locks. - */ - - brl_close(fsp->dev, fsp->inode, getpid(), fsp->conn->cnum, fsp->fnum); -} - /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ @@ -502,51 +479,145 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, int *eclass,uint32 *ecode) { BOOL ok = False; + TALLOC_CTX *ul_ctx = NULL; + struct unlock_list *ulist = NULL; + struct unlock_list *ul = NULL; + pid_t pid; if (!lp_locking(SNUM(conn))) return(True); + if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) { + *eclass = ERRDOS; + *ecode = ERRlock; + return False; + } + DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", (double)offset, (double)count, fsp->fsp_name )); - - if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - - if(lp_posix_locking(SNUM(conn))) { - -#if 0 - /* - * The following call calculates if there are any - * overlapping read locks held by this process on - * other fd's open on the same file and truncates - * any overlapping range and returns the value in - * the non_overlap_XXX variables. Thus the POSIX - * unlock may not be done on the same region as - * the brl_lock. JRA. - */ - brl_unlock_list(fsp->dev, fsp->inode, fsp->fnum, -#endif - - /* - * Release the POSIX lock on this range. - */ + /* + * Remove the existing lock record from the tdb lockdb + * before looking at POSIX locks. If this record doesn't + * match then don't bother looking to remove POSIX locks. + */ - (void)release_posix_lock(fsp, offset, count); - fsp->num_posix_locks--; - } + pid = getpid(); - ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, getpid(), conn->cnum, offset, count); - } + ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + global_smbpid, pid, conn->cnum, offset, count); if (!ok) { *eclass = ERRDOS; *ecode = ERRlock; return False; } + + if (!lp_posix_locking(SNUM(conn))) + return True; + + if ((ul_ctx = talloc_init()) == NULL) { + DEBUG(0,("do_unlock: unable to init talloc context.\n")); + return True; /* Not a fatal error. */ + } + + if ((ul = (struct unlock_list *)talloc(ul_ctx, sizeof(struct unlock_list))) == NULL) { + DEBUG(0,("do_unlock: unable to talloc unlock list.\n")); + talloc_destroy(ul_ctx); + return True; /* Not a fatal error. */ + } + + /* + * Create the initial list entry containing the + * lock we want to remove. + */ + + ZERO_STRUCTP(ul); + ul->start = offset; + ul->size = count; + + DLIST_ADD(ulist, ul); + + /* + * The following call calculates if there are any + * overlapping read locks held by this process on + * other fd's open on the same file and creates a + * list of unlock ranges that will allow other + * POSIX lock ranges to remain on the file whilst the + * unlocks are performed. + */ + + ulist = brl_unlock_list(ul_ctx, ulist, pid, fsp->dev, fsp->inode); + + /* + * Release the POSIX locks on the list of ranges returned. + */ + + for(; ulist; ulist = ulist->next) + (void)release_posix_lock(fsp, ulist->start, ulist->size); + + talloc_destroy(ul_ctx); + + /* + * We treat this as one unlock request for POSIX accounting purposes even + * if it may have been split into multiple smaller POSIX unlock ranges. + */ + + fsp->num_posix_locks--; + return True; /* Did unlock */ } +/**************************************************************************** + Remove any locks on this fd. Called from file_close(). +****************************************************************************/ + +void locking_close_file(files_struct *fsp) +{ + pid_t pid = getpid(); + + if (!lp_locking(SNUM(fsp->conn))) + return; + + if(lp_posix_locking(SNUM(fsp->conn))) { + + TALLOC_CTX *ul_ctx = NULL; + struct unlock_list *ul = NULL; + int eclass; + uint32 ecode; + + if ((ul_ctx = talloc_init()) == NULL) { + DEBUG(0,("locking_close_file: unable to init talloc context.\n")); + return; + } + + /* + * We need to release all POSIX locks we have on this + * fd. Get all our existing locks from the tdb locking database. + */ + + ul = brl_getlocklist(ul_ctx, fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); + + /* + * Now unlock all of them. This will remove the brl entry also + * for each lock. + */ + + for(; ul; ul = ul->next) + do_unlock(fsp,fsp->conn,ul->size,ul->start,&eclass,&ecode); + + talloc_destroy(ul_ctx); + + } else { + + /* + * Just release all the tdb locks, no need to release individually. + */ + + brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); + } +} + /**************************************************************************** Initialise the locking functions. ****************************************************************************/ -- cgit From e3987ff7a638f9ea8b6794f1ed0df530d8488033 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 18:46:10 +0000 Subject: Fixed crash bugs Andrew pointed out with LOCK4 smbtorture test. Was miscounting posix locks, plus was not taking into account the case where other_fsp == fsp in the 'move locks' case. DOH ! This code will be re-written anyway :-). Jeremy. (This used to be commit 5278ec016cb24d8263fe6e7c1d389f466270ef24) --- source3/locking/locking.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 811dfbc101..b61e8acedc 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -284,7 +284,7 @@ static BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UI SMB_OFF_T count; DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)offset, (double)count, lock_type_name(lock_type) )); + fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) )); /* * If the requested lock won't fit in the POSIX range, we will @@ -315,7 +315,7 @@ static BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UIN BOOL ret = True; DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)offset, (double)count, lock_type_name(lock_type) )); + fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) )); /* * If the requested lock won't fit in the POSIX range, we will @@ -350,17 +350,15 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG BOOL ret = True; DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", - fsp->fsp_name, (double)offset, (double)count )); + fsp->fsp_name, (double)u_offset, (double)u_count )); if(u_count == 0) { /* * This lock must overlap with an existing read-only lock - * help by another fd. Just decrement the count but don't - * do any POSIX call. + * help by another fd. Don't do any POSIX call. */ - fsp->num_posix_locks--; return True; } @@ -374,10 +372,7 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK); - if(ret) - fsp->num_posix_locks--; - - return True; + return ret; } /**************************************************************************** @@ -565,6 +560,8 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, fsp->num_posix_locks--; + SMB_ASSERT(fsp->num_posix_locks >= 0); + return True; /* Did unlock */ } -- cgit From 3d3c50326ba7f32ebb2fc683a3410dc0d1f18cdc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 21:12:33 +0000 Subject: Did the rewrite Andrew wanted where all knowledge of POSIX locking is removed from the smbd/open.c code. We now use a dlink list of structures indexed by dev/inode to store all pending fd's for close. This could be rewritten to use lib/hash.c if this is discovered to be too slow in use. Andrew, please take a look and let me know if this is what you had in mind. Jeremy. (This used to be commit 0487841120a7584da9a2b83b9574562c415d7024) --- source3/locking/locking.c | 184 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 179 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index b61e8acedc..9d407bf16b 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -2,7 +2,8 @@ Unix SMB/Netbios implementation. Version 3.0 Locking functions - Copyright (C) Andrew Tridgell 1992-1999 + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Jeremy Allison 1992-2000 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 @@ -30,6 +31,8 @@ support. rewrtten completely to use new tdb code. Tridge, Dec '99 + + Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000. */ #include "includes.h" @@ -40,6 +43,179 @@ static TDB_CONTEXT *tdb; int global_smbpid; +/* + * Doubly linked list to hold pending closes needed for + * POSIX locks. This may be changed to use a hash table (as + * in lib/hash.c if this is too slow in use.... JRA. + */ + +struct pending_closes { + struct pending_closes *next; + struct pending_closes *prev; + SMB_DEV_T dev; + SMB_INO_T inode; + int num_posix_locks; + size_t fd_array_size; + int *fd_array; +}; + +static struct pending_closes *pending_close_list = NULL; + +/**************************************************************************** + Find a dev/inode pair in the pending close list. +****************************************************************************/ + +static struct pending_closes *find_pending_close_entry(SMB_DEV_T dev, SMB_INO_T inode) +{ + struct pending_closes *pc; + + for(pc = pending_close_list; pc; pc = pc->next) { + if (dev == pc->dev && inode == pc->inode) { + DLIST_PROMOTE(pending_close_list,pc); + return pc; + } + } + + return NULL; +} + +/**************************************************************************** + Add an fd into the pending close array. +****************************************************************************/ + +static BOOL add_fd_to_close_entry(struct pending_closes *pc, int fd) +{ + if ((pc->fd_array = (int *)Realloc(pc->fd_array, (pc->fd_array_size + 1)*sizeof(int))) == NULL) { + DEBUG(0,("add_fd_to_close_entry: Unable to increase fd_array !\n")); + return False; + } + + pc->fd_array[pc->fd_array_size] = fd; + pc->fd_array_size++; + + DEBUG(10,("add_fd_to_close_entry: added fd = %d, size = %u : dev = %.0f, ino = %.0f\n", + fd, (unsigned int)pc->fd_array_size, (double)pc->dev, (double)pc->inode )); + + return True; +} + +/**************************************************************************** + Deal with pending closes needed by POSIX locking support. +****************************************************************************/ + +BOOL fd_close_posix_locks(struct connection_struct *conn, files_struct *fsp) +{ + struct pending_closes *pc; + int saved_errno = 0; + size_t i; + + if (!lp_posix_locking(SNUM(conn))) + return True; + + pc = find_pending_close_entry(fsp->dev, fsp->inode); + + if (!pc) { + /* + * No other open with a POSIX lock on this dev/inode within this smbd. + * Just exit. + */ + return True; + } + + if (pc->num_posix_locks) { + /* + * There are outstanding locks on this dev/inode pair. + * Add our fd to the list and set fsp->fd to -1 to + * stop the close. + */ + + if (!add_fd_to_close_entry(pc, fsp->fd)) + return False; + + fsp->fd = -1; + return True; + } + + DEBUG(10,("fd_close_posix_locks: doing close on %u fd's.\n", (unsigned int)pc->fd_array_size )); + + /* + * This is the last close. If there are pending fd's close them + * now. Save the errno just in case. + */ + + for(i = 0; i < pc->fd_array_size; i++) { + if (pc->fd_array[i] != -1) { + if (conn->vfs_ops.close(pc->fd_array[i]) == -1) { + saved_errno = errno; + } + } + } + + if (pc->fd_array) + free((char *)pc->fd_array); + + DLIST_REMOVE(pending_close_list, pc); + + free((char *)pc); + + if (saved_errno != 0) { + errno = saved_errno; + } + + return True; +} + +/**************************************************************************** + A POSIX lock was granted. Increment the lock list count (create if needed). +****************************************************************************/ + +static void increment_posix_lock_list(files_struct *fsp) +{ + struct pending_closes *pc; + + if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) == NULL) { + if (!(pc = (struct pending_closes *)malloc(sizeof(struct pending_closes)))) { + DEBUG(0,("increment_lock_list: malloc fail.\n")); + return; + } + ZERO_STRUCTP(pc); + pc->dev = fsp->dev; + pc->inode = fsp->inode; + DLIST_ADD(pending_close_list, pc); + + DEBUG(10,("increment_posix_lock_list: creating entry for file %s: dev = %.0f, ino = %.0f\n", + fsp->fsp_name, (double)fsp->dev, (double)fsp->inode )); + } + + pc->num_posix_locks++; + + DEBUG(10,("increment_posix_lock_list: entry for file %s: dev = %.0f, ino = %.0f, num_locks = %d\n", + fsp->fsp_name, (double)pc->dev, (double)pc->inode, pc->num_posix_locks )); +} + + +/**************************************************************************** + A POSIX lock was granted. Decrement the lock list count. +****************************************************************************/ + +static void decrement_posix_lock_list(files_struct *fsp) +{ + struct pending_closes *pc; + + pc = find_pending_close_entry(fsp->dev, fsp->inode); + + if (pc == NULL) { + smb_panic("decrement_lock_list: Unlock not found !\n"); + } + + pc->num_posix_locks--; + + DEBUG(10,("decrement_posix_lock_list: entry for file %s: dev = %.0f, ino = %.0f, num_locks = %d\n", + fsp->fsp_name, (double)pc->dev, (double)pc->inode, pc->num_posix_locks )); + + SMB_ASSERT(pc->num_posix_locks >= 0); +} + /**************************************************************************** Debugging aid :-). ****************************************************************************/ @@ -444,7 +620,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, */ if((ok = set_posix_lock(fsp, offset, count, lock_type)) == True) - fsp->num_posix_locks++; + increment_posix_lock_list(fsp); else { /* * We failed to map - we must now remove the brl @@ -558,9 +734,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, * if it may have been split into multiple smaller POSIX unlock ranges. */ - fsp->num_posix_locks--; - - SMB_ASSERT(fsp->num_posix_locks >= 0); + decrement_posix_lock_list(fsp); return True; /* Did unlock */ } -- cgit From 36db78fedad935aaa689d52d7f58e075f1f71812 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 22:23:04 +0000 Subject: Fixed subtle unlocking bug when a file is closed. We need to store the smbpid used when a file was opened in the files_struct. Else we use the wrong global_smbpid when we are closing the file and trying to remove the brl locks - this causes the brl locks to be left when the file is closed as the samba_context check fails. Jeremy. (This used to be commit 2746e5602e493e5b022764b4b839eb4d2f14363b) --- source3/locking/brlock.c | 37 +++++++++++++++++++++++++++---------- source3/locking/locking.c | 11 +++++------ 2 files changed, 32 insertions(+), 16 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 68daa7e0bb..ed1f73df5e 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -210,6 +210,9 @@ struct unlock_list *brl_unlock_list(TALLOC_CTX *ctx, struct unlock_list *ulhead, * Quit if the list is deleted. */ + DEBUG(10,("brl_unlock_list: curr: start=%.0f,size=%.0f\n", + (double)ulhead->start, (double)ulhead->size )); + for (i=0; istart, (double)ul_curr->size, - (double)lock->start, (double)lock->size )); + DEBUG(10,("brl_unlock_list: lock: start=%.0f,size=%.0f:", + (double)lock->start, (double)lock->size )); if ( (ul_curr->start >= (lock->start + lock->size)) || (lock->start > (ul_curr->start + ul_curr->size))) { @@ -248,7 +250,7 @@ OR.... +---------+ **********************************************/ - DEBUG(10,("brl_unlock_list: no overlap case.\n" )); + DEBUG(10,("no overlap case.\n" )); ul_curr = ul_curr->next; @@ -270,7 +272,7 @@ OR.... /* Save the next pointer */ struct unlock_list *ul_next = ul_curr->next; - DEBUG(10,("brl_unlock_list: delete case.\n" )); + DEBUG(10,("delete case.\n" )); DLIST_REMOVE(ulhead, ul_curr); if(ulhead == NULL) @@ -302,7 +304,7 @@ BECOMES.... ul_curr->size = (ul_curr->start + ul_curr->size) - (lock->start + lock->size); ul_curr->start = lock->start + lock->size; - DEBUG(10,("brl_unlock_list: truncate high case: start=%.0f,size=%.0f\n", + DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size )); ul_curr = ul_curr->next; @@ -329,7 +331,7 @@ BECOMES.... ul_curr->size = lock->start - ul_curr->start; - DEBUG(10,("brl_unlock_list: truncate low case: start=%.0f,size=%.0f\n", + DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size )); ul_curr = ul_curr->next; @@ -372,7 +374,7 @@ BECOMES..... /* Truncate the ul_curr. */ ul_curr->size = lock->start - ul_curr->start; - DEBUG(10,("brl_unlock_list: split case: curr: start=%.0f,size=%.0f \ + DEBUG(10,("split case: curr: start=%.0f,size=%.0f \ new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, (double)ul_new->start, (double)ul_new->size )); @@ -385,7 +387,7 @@ new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, * case by forcing an abort.... Remove in production. */ - smb_panic("brl_unlock_list: logic flaw in cases...\n"); + smb_panic("logic flaw in cases...\n"); } } /* end for ( ul_curr = ulhead; ul_curr;) */ } /* end for (i=0; icontext, &context)) { + DEBUG(10,("brl_unlock: Not same context. l_smbpid = %u, l_pid = %u, l_tid = %u: \ +smbpid = %u, pid = %u, tid = %u\n", + lock->context.smbpid, lock->context.pid, lock->context.tid, + context.smbpid, context.pid, context.tid )); + + } + /* JRATEST */ +#endif + if (brl_same_context(&lock->context, &context) && lock->fnum == fnum && lock->start == start && diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 9d407bf16b..b6b34138e3 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -41,8 +41,6 @@ extern int DEBUGLEVEL; /* the locking database handle */ static TDB_CONTEXT *tdb; -int global_smbpid; - /* * Doubly linked list to hold pending closes needed for * POSIX locks. This may be changed to use a hash table (as @@ -569,7 +567,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, return(False); ret = !brl_locktest(fsp->dev, fsp->inode, - global_smbpid, getpid(), conn->cnum, + fsp->smbpid, getpid(), conn->cnum, offset, count, lock_type); /* @@ -607,7 +605,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { ok = brl_lock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, getpid(), conn->cnum, + fsp->smbpid, getpid(), conn->cnum, offset, count, lock_type); @@ -627,7 +625,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, * lock entry. */ (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, getpid(), conn->cnum, + fsp->smbpid, getpid(), conn->cnum, offset, count); } } @@ -676,9 +674,10 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, pid = getpid(); ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, pid, conn->cnum, offset, count); + fsp->smbpid, pid, conn->cnum, offset, count); if (!ok) { + DEBUG(10,("do_unlock: returning ERRlock.\n" )); *eclass = ERRDOS; *ecode = ERRlock; return False; -- cgit From 4b60a33c6fa733060068e192b87c2e858103d6eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 23:28:56 +0000 Subject: Ok - this is more subtle than it looks :-). When a file is being closed, once it passes the fnum and tid tests then the locking context should be ignored when removing all locks. This is what is done in the brl close case, but when you have outstanding POSIX locks, then you cannot remove all the brl locks in one go, you have to get the lock list and call do_unlock individually. As this uses global_smbpid as the locking context, you need to make sure that this is set correctly for the specific lock being removed. I now do this by storing the smbpid in each entry in the unlock list returned from the query call. I removed the smbpid from fsp (not needed) and things seem ok (even with the stupid smbpid tricks that smbtorture plays :-). Jeremy. (This used to be commit 6baa96bb466915cc17e8cbad50254d6bd47b967b) --- source3/locking/brlock.c | 2 ++ source3/locking/locking.c | 20 +++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index ed1f73df5e..410fb3fc0b 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -367,6 +367,7 @@ BECOMES..... ZERO_STRUCTP(ul_new); ul_new->start = lock->start + lock->size; ul_new->size = ul_curr->start + ul_curr->size - ul_new->start; + ul_new->smbpid = ul_curr->smbpid; /* Add into the dlink list after the ul_curr point - NOT at ulhead. */ DLIST_ADD(ul_curr, ul_new); @@ -638,6 +639,7 @@ struct unlock_list *brl_getlocklist( TALLOC_CTX *ctx, SMB_DEV_T dev, SMB_INO_T i ZERO_STRUCTP(ul_new); ul_new->start = lock->start; ul_new->size = lock->size; + ul_new->smbpid = lock->context.smbpid; DLIST_ADD(ulist, ul_new); } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index b6b34138e3..088693b6d4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -37,6 +37,7 @@ #include "includes.h" extern int DEBUGLEVEL; +int global_smbpid; /* the locking database handle */ static TDB_CONTEXT *tdb; @@ -567,7 +568,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, return(False); ret = !brl_locktest(fsp->dev, fsp->inode, - fsp->smbpid, getpid(), conn->cnum, + global_smbpid, getpid(), conn->cnum, offset, count, lock_type); /* @@ -605,7 +606,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { ok = brl_lock(fsp->dev, fsp->inode, fsp->fnum, - fsp->smbpid, getpid(), conn->cnum, + global_smbpid, getpid(), conn->cnum, offset, count, lock_type); @@ -625,7 +626,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, * lock entry. */ (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - fsp->smbpid, getpid(), conn->cnum, + global_smbpid, getpid(), conn->cnum, offset, count); } } @@ -674,7 +675,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, pid = getpid(); ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - fsp->smbpid, pid, conn->cnum, offset, count); + global_smbpid, pid, conn->cnum, offset, count); if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); @@ -705,6 +706,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, ZERO_STRUCTP(ul); ul->start = offset; ul->size = count; + ul->smbpid = global_smbpid; DLIST_ADD(ulist, ul); @@ -770,12 +772,16 @@ void locking_close_file(files_struct *fsp) /* * Now unlock all of them. This will remove the brl entry also - * for each lock. + * for each lock. Note we need to make sure the global_smbpid matches + * the one associated with each lock in case the client plays games + * with smbpids (like smbtorture does :-). */ - for(; ul; ul = ul->next) + for(; ul; ul = ul->next) { + global_smbpid = ul->smbpid; do_unlock(fsp,fsp->conn,ul->size,ul->start,&eclass,&ecode); - + } + talloc_destroy(ul_ctx); } else { -- cgit From be828fcec88a43306ddfb53473fda52df1d9965b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Apr 2000 00:39:23 +0000 Subject: Made changes suggested by Andrew review. fd_close now calls fd_close_posix() directly. set_posix_lock/release_posix_lock() now handle the reference counting. More changes due when this gets moved to the file locking/posix.c Jeremy. (This used to be commit 239abd48f049c6a8d2bbc0636eacf347ab77588c) --- source3/locking/locking.c | 89 +++++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 37 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 088693b6d4..d69ab18006 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -102,10 +102,11 @@ static BOOL add_fd_to_close_entry(struct pending_closes *pc, int fd) Deal with pending closes needed by POSIX locking support. ****************************************************************************/ -BOOL fd_close_posix_locks(struct connection_struct *conn, files_struct *fsp) +int fd_close_posix(struct connection_struct *conn, files_struct *fsp) { struct pending_closes *pc; int saved_errno = 0; + int ret; size_t i; if (!lp_posix_locking(SNUM(conn))) @@ -116,9 +117,11 @@ BOOL fd_close_posix_locks(struct connection_struct *conn, files_struct *fsp) if (!pc) { /* * No other open with a POSIX lock on this dev/inode within this smbd. - * Just exit. + * Just close the fd. */ - return True; + ret = conn->vfs_ops.close(fsp->fd); + fsp->fd = -1; + return ret; } if (pc->num_posix_locks) { @@ -132,10 +135,10 @@ BOOL fd_close_posix_locks(struct connection_struct *conn, files_struct *fsp) return False; fsp->fd = -1; - return True; + return 0; } - DEBUG(10,("fd_close_posix_locks: doing close on %u fd's.\n", (unsigned int)pc->fd_array_size )); + DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)pc->fd_array_size )); /* * This is the last close. If there are pending fd's close them @@ -157,11 +160,16 @@ BOOL fd_close_posix_locks(struct connection_struct *conn, files_struct *fsp) free((char *)pc); + ret = conn->vfs_ops.close(fsp->fd); + if (saved_errno != 0) { errno = saved_errno; + ret = -1; } - return True; + fsp->fd = -1; + + return ret; } /**************************************************************************** @@ -497,8 +505,10 @@ static BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UIN * pretend it was successful. */ - if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { + increment_posix_lock_list(fsp); return True; + } /* * Note that setting multiple overlapping read locks on different @@ -510,42 +520,55 @@ static BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UIN ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,map_posix_lock_type(fsp,lock_type)); + if (ret) + increment_posix_lock_list(fsp); + return ret; } /**************************************************************************** - POSIX function to release a lock. Returns True if the + POSIX function to release a lock given a list. Returns True if the lock could be released, False if not. ****************************************************************************/ -static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) +static BOOL release_posix_lock(files_struct *fsp, struct unlock_list *ulist) { - SMB_OFF_T offset; - SMB_OFF_T count; BOOL ret = True; - DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", - fsp->fsp_name, (double)u_offset, (double)u_count )); + for(; ulist; ulist = ulist->next) { + SMB_OFF_T offset = ulist->start; + SMB_OFF_T count = ulist->size; + + DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", + fsp->fsp_name, (double)offset, (double)count )); + + if(count == 0) { - if(u_count == 0) { + /* + * This lock must overlap with an existing read-only lock + * held by another fd. Don't do any POSIX call. + */ + + continue; + } /* - * This lock must overlap with an existing read-only lock - * help by another fd. Don't do any POSIX call. + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. */ - return True; + if(!posix_lock_in_range(&offset, &count, offset, count)) + continue; + + ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK); } /* - * If the requested lock won't fit in the POSIX range, we will - * pretend it was successful. - */ - - if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) - return True; + * We treat this as one unlock request for POSIX accounting purposes even + * if it may have been split into multiple smaller POSIX unlock ranges. + */ - ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK); + decrement_posix_lock_list(fsp); return ret; } @@ -610,7 +633,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, offset, count, lock_type); - if(ok && lp_posix_locking(SNUM(conn))) { + if (ok && lp_posix_locking(SNUM(conn))) { /* * Try and get a POSIX lock on this range. @@ -618,9 +641,9 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, * overlapping on a different fd. JRA. */ - if((ok = set_posix_lock(fsp, offset, count, lock_type)) == True) - increment_posix_lock_list(fsp); - else { + ok = set_posix_lock(fsp, offset, count, lock_type); + + if (!ok) { /* * We failed to map - we must now remove the brl * lock entry. @@ -725,18 +748,10 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, * Release the POSIX locks on the list of ranges returned. */ - for(; ulist; ulist = ulist->next) - (void)release_posix_lock(fsp, ulist->start, ulist->size); + (void)release_posix_lock(fsp, ulist); talloc_destroy(ul_ctx); - /* - * We treat this as one unlock request for POSIX accounting purposes even - * if it may have been split into multiple smaller POSIX unlock ranges. - */ - - decrement_posix_lock_list(fsp); - return True; /* Did unlock */ } -- cgit From f8e5696bd6d839dee9c98640519efe2f2512df99 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Apr 2000 01:01:07 +0000 Subject: Added optimization where we are single opener (don't free POSIX locks). Jeremy. (This used to be commit a2deb91128d59ad04f4ec858ffe4e30f2afb0edd) --- source3/locking/locking.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d69ab18006..62304076af 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -772,6 +772,26 @@ void locking_close_file(files_struct *fsp) struct unlock_list *ul = NULL; int eclass; uint32 ecode; + struct pending_closes *pc; + + /* + * Optimization for the common case where we are the only + * opener of a file. If all fd entries are our own, we don't + * need to explicitly release all the locks via the POSIX functions, + * we can just release all the brl locks, as in the no POSIX locking case. + */ + + if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) != NULL) { + + if (pc->fd_array_size == 1 && pc->fd_array[0] == fsp->fd ) { + /* + * Just release all the brl locks, no need to release individually. + */ + + brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); + return; + } + } if ((ul_ctx = talloc_init()) == NULL) { DEBUG(0,("locking_close_file: unable to init talloc context.\n")); @@ -802,7 +822,7 @@ void locking_close_file(files_struct *fsp) } else { /* - * Just release all the tdb locks, no need to release individually. + * Just release all the brl locks, no need to release individually. */ brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); -- cgit From 1f7d96ee0310f50af953621a81d335778b0c76dc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Apr 2000 01:08:32 +0000 Subject: Forgot to close when "posix locking" is set to False. Jeremy. (This used to be commit b812f09ba8ef074c9ff0747ea03a1e33f1ebbe71) --- source3/locking/locking.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 62304076af..fa56e0a628 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -109,8 +109,11 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) int ret; size_t i; - if (!lp_posix_locking(SNUM(conn))) - return True; + if (!lp_posix_locking(SNUM(conn))) { + ret = conn->vfs_ops.close(fsp->fd); + fsp->fd = -1; + return ret; + } pc = find_pending_close_entry(fsp->dev, fsp->inode); -- cgit From 46e84a0090516e3ae67b3ceb06b3d9a546e8e71e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Apr 2000 19:38:38 +0000 Subject: Split off of POSIX locking into separate unit as Andrew requested. Done so I don't lose my edits... :-). Jeremy. (This used to be commit 31a57be658f3fa3569a552e9c5d30174f5a51649) --- source3/locking/posix.c | 1208 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1208 insertions(+) create mode 100644 source3/locking/posix.c (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c new file mode 100644 index 0000000000..f05a0a2a31 --- /dev/null +++ b/source3/locking/posix.c @@ -0,0 +1,1208 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + Locking functions + Copyright (C) Jeremy Allison 1992-2000 + + 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: + + POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000. +*/ + +#include "includes.h" +extern int DEBUGLEVEL; +extern int global_smbpid; + +/* + * The POSIX locking database handle. + */ + +static TDB_CONTEXT *posix_lock_tdb; + +/* + * The pending close database handle. + */ + +static TDB_CONTEXT *posix_pending_close_tdb; + +/* + * The data in POSIX lock records is an unsorted linear array of these + * records. It is unnecessary to store the count as tdb provides the + * size of the record. + */ + +struct posix_lock { + int fd; + SMB_OFF_T start; + SMB_OFF_T size; + int lock_type; +}; + +/* + * The data in POSIX pending close records is an unsorted linear array of ints + * records. It is unnecessary to store the count as tdb provides the + * size of the record. + */ + +/* The key used in both the POSIX databases. */ + +struct posix_lock_key { + SMB_DEV_T device; + SMB_INO_T inode; +}; + +/******************************************************************* + Form a static locking key for a dev/inode pair. +******************************************************************/ + +static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) +{ + static struct posix_lock_key key; + TDB_DATA kbuf; + key.dev = dev; + key.inode = inode; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + return kbuf; +} + +/******************************************************************* + Convenience function to get a key from an fsp. +******************************************************************/ + +static TDB_DATA locking_key_fsp(files_struct *fsp) +{ + return locking_key(fsp->dev, fsp->inode); +} + +/**************************************************************************** + Add an fd to the pending close tdb. +****************************************************************************/ + +static BOOL add_fd_to_close_entry(files_struct *fsp) +{ + struct posix_lock_key = locking_key_fsp(fsp); + TDB_DATA kbuf, dbuf; + size_t count = 0; + int *fd_array = NULL; + + dbuf.dptr = NULL; + + tdb_lockchain(posix_pending_close_tdb, kbuf); + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + + dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(int)); + if (!dbuf.dptr) { + DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n")); + tdb_unlockchain(posix_pending_close_tdb, kbuf); + return False; + } + memcpy(dbuf.dptr + dbuf.dsize, &fsp->fd, sizeof(int)); + dbuf.dsize += sizeof(int); + + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n")); + } + + free(dbuf.dptr); + tdb_unlockchain(posix_pending_close_tdb, kbuf); + return True; +} + +/**************************************************************************** + Remove all fd entries for a specific dev/inode pair from the tdb. +****************************************************************************/ + +static void delete_close_entries(files_struct *fsp) +{ + struct posix_lock_key = locking_key_fsp(fsp); + TDB_DATA kbuf, dbuf; + + tdb_lockchain(posix_pending_close_tdb, kbuf); + if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) + DEBUG(0,("delete_close_entries: tdb_delete fail !\n")); + tdb_unlockchain(posix_pending_close_tdb, kbuf); +} + +/**************************************************************************** + Get the array of POSIX pending close records for an open fsp. Caller must + free. Returns number of entries. +****************************************************************************/ + +static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) +{ + struct posix_lock_key = locking_key_fsp(fsp); + TDB_DATA kbuf, dbuf; + size_t count = 0; + + *entries = NULL; + dbuf.dptr = NULL; + + tdb_lockchain(posix_pending_close_tdb, kbuf); + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + + if (!dbuf.dptr) { + tdb_unlockchain(posix_pending_close_tdb, kbuf); + return 0; + } + + *entries = (int *)dbuf.dptr; + count = (size_t)(dbuf.dsize / sizeof(int)); + + tdb_unlockchain(posix_pending_close_tdb, kbuf); + + return count; +} + +/**************************************************************************** + Get the array of POSIX locks for an fsp. Caller must free. Returns + number of entries. +****************************************************************************/ + +static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries) +{ + struct posix_lock_key = locking_key_fsp(fsp); + TDB_DATA kbuf, dbuf; + size_t count = 0; + + *entries = NULL; + + dbuf.dptr = NULL; + + tdb_lockchain(posix_lock_tdb, kbuf); + dbuf = tdb_fetch(posix_lock_tdb, kbuf); + + if (!dbuf.dptr) { + tdb_unlockchain(posix_lock_tdb, kbuf); + return 0; + } + + *entries = (struct posix_lock_struct *)dbuf.dptr; + count = (size_t)(dbuf.dsize / sizeof(struct posix_lock_struct)); + + tdb_unlockchain(posix_lock_tdb, kbuf); + + return count; +} + +/**************************************************************************** + Deal with pending closes needed by POSIX locking support. +****************************************************************************/ + +int fd_close_posix(struct connection_struct *conn, files_struct *fsp) +{ + int saved_errno = 0; + int ret; + size_t count, i; + struct posix_lock *entries = NULL; + int *fd_array = NULL; + + if (!lp_posix_locking(SNUM(conn))) { + /* + * No POSIX to worry about, just close. + */ + ret = conn->vfs_ops.close(fsp->fd); + fsp->fd = -1; + return ret; + } + + /* + * Get the number of outstanding POSIX locks on this dev/inode pair. + */ + + count = get_posix_lock_entries(fsp, &entries); + + if (count) { + + /* + * There are outstanding locks on this dev/inode pair on other fds. + * Add our fd to the pending close tdb and set fsp->fd to -1. + */ + + if (!add_fd_to_close_entry(fsp)) { + free((char *)entries); + return False; + } + + free((char *)entries); + fsp->fd = -1; + return 0; + } + + if(entries) + free((char *)entries); + + /* + * No outstanding POSIX locks. Get the pending close fd's + * from the tdb and close them all. + */ + + count = get_posix_pending_close_entries(fsp, &fd_array) + + if (count) { + DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); + + for(i = 0; i < count; i++) { + if (conn->vfs_ops.close(fd_array[i]) == -1) { + saved_errno = errno; + } + } + + if (fd_array) + free((char *)fd_array); + + /* + * Delete all fd's stored in the tdb + * for this dev/inode pair. + */ + + delete_close_entries(fsp); + } + + if (fd_array) + free((char *)fd_array); + + /* + * Finally close the fd associated with this fsp. + */ + + ret = conn->vfs_ops.close(fsp->fd); + + if (saved_errno != 0) { + errno = saved_errno; + ret = -1; + } + + fsp->fd = -1; + + return ret; +} + +/**************************************************************************** + Debugging aid :-). +****************************************************************************/ + +static const char *posix_lock_type_name(int lock_type) +{ + return (lock_type == F_RDLCK) ? "READ" : "WRITE"; +} + +/**************************************************************************** + Add an entry into the POSIX locking tdb. +****************************************************************************/ + +static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type) +{ + struct posix_lock_key = locking_key_fsp(fsp); + TDB_DATA kbuf, dbuf; + struct posix_lock pl; + + /* + * Now setup the new record. + */ + + pl.fd = fsp->fd; + pl.start = start; + pl.size = size; + pl.lock_type = lock_type; + + dbuf.dptr = NULL; + + tdb_lockchain(posix_lock_tdb, kbuf); + dbuf = tdb_fetch(posix_lock_tdb, kbuf); + + dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*pl)); + if (!dbuf.dptr) { + DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); + goto fail; + } + + memcpy(dbuf.dptr + dbuf.dsize, rec, sizeof(*pl)); + dbuf.dsize += sizeof(*pl); + + if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name)); + goto fail; + } + + free(dbuf.dptr); + tdb_unlockchain(posix_lock_tdb, kbuf); + + DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f:dev=%.0f inode=%.0f\n", + fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, + (double)fsp->dev, (double)fsp->inode )); + + return True; + + fail: + if (dbuf.dptr) + free(dbuf.dptr); + tdb_unlockchain(tdb, kbuf); + return False; +} + +/**************************************************************************** + Delete an entry from the POSIX locking tdb. +****************************************************************************/ + +static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size) +{ + struct posix_lock_key = locking_key_fsp(fsp); + TDB_DATA kbuf, dbuf; + struct posix_lock *locks; + size_t i, count; + + dbuf.dptr = NULL; + + tdb_lockchain(posix_lock_tdb, kbuf); + dbuf = tdb_fetch(posix_lock_tdb, kbuf); + + if (!dbuf.dptr) { + DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n")); + goto fail; + } + + /* There are existing locks - find a match. */ + locks = (struct lock_struct *)dbuf.dptr; + count = (size_t(dbuf.dsize / sizeof(*locks)); + + for (i=0; ifd == fd && + pl->start == start && + pl->size == size) { + /* Found it - delete it. */ + if (count == 1) { + tdb_delete(posix_lock_tdb, kbuf); + } else { + if (i < count-1) { + memmove(&locks[i], &locks[i+1], sizeof(*locks)*((count-1) - i)); + } + dbuf.dsize -= sizeof(*locks); + tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); + } + + free(dbuf.dptr); + tdb_unlockchain(tdb, kbuf); + return True; + } + } + + /* We didn't find it. */ + + fail: + if (dbuf.dptr) + free(dbuf.dptr); + tdb_unlockchain(tdb, kbuf); + return False; +} + +/**************************************************************************** + Utility function to map a lock type correctly depending on the open + mode of a file. +****************************************************************************/ + +static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) +{ + if((lock_type == WRITE_LOCK) && !fsp->can_write) { + /* + * Many UNIX's cannot get a write lock on a file opened read-only. + * Win32 locking semantics allow this. + * Do the best we can and attempt a read-only lock. + */ + DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n")); + return F_RDLCK; + } else if((lock_type == READ_LOCK) && !fsp->can_read) { + /* + * Ditto for read locks on write only files. + */ + DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n")); + return F_WRLCK; + } + + /* + * This return should be the most normal, as we attempt + * to always open files read/write. + */ + + return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK; +} + +/**************************************************************************** + Check to see if the given unsigned lock range is within the possible POSIX + range. Modifies the given args to be in range if possible, just returns + False if not. +****************************************************************************/ + +static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, + SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) +{ + SMB_OFF_T offset; + SMB_OFF_T count; + +#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) + + SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); + SMB_OFF_T mask = (mask2<<1); + SMB_OFF_T neg_mask = ~mask; + + /* + * In this case SMB_OFF_T is 64 bits, + * and the underlying system can handle 64 bit signed locks. + * Cast to signed type. + */ + + offset = (SMB_OFF_T)u_offset; + count = (SMB_OFF_T)u_count; + + /* + * Deal with a very common case of count of all ones. + * (lock entire file). + */ + + if(count == (SMB_OFF_T)-1) + count &= ~mask; + + /* + * POSIX lock ranges cannot be negative. + * Fail if any combination becomes negative. + */ + + if(offset < 0 || count < 0 || (offset + count < 0)) { + DEBUG(10,("posix_lock_in_range: negative range: offset = %.0f, count = %.0f. Ignoring lock.\n", + (double)offset, (double)count )); + return False; + } + + /* + * In this case SMB_OFF_T is 64 bits, the offset and count + * fit within the positive range, and the underlying + * system can handle 64 bit locks. Just return as the + * cast values are ok. + */ + +#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * In this case either SMB_OFF_T is 32 bits, + * or the underlying system cannot handle 64 bit signed locks. + * Either way we have to try and mangle to fit within 31 bits. + * This is difficult. + */ + +#if defined(HAVE_BROKEN_FCNTL64_LOCKS) + + /* + * SMB_OFF_T is 64 bits, but we need to use 31 bits due to + * broken large locking. + */ + + /* + * Deal with a very common case of count of all ones. + * (lock entire file). + */ + + if(u_count == (SMB_BIG_UINT)-1) + count = 0x7FFFFFFF; + + if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) { + DEBUG(10,("posix_lock_in_range: top 32 bits not zero. offset = %.0f, count = %.0f. Ignoring lock.\n", + (double)u_offset, (double)u_count )); + /* Top 32 bits of offset or count were not zero. */ + return False; + } + + /* Cast from 64 bits unsigned to 64 bits signed. */ + offset = (SMB_OFF_T)u_offset; + count = (SMB_OFF_T)u_count; + + /* + * Check if we are within the 2^31 range. + */ + + { + int32 low_offset = (int32)offset; + int32 low_count = (int32)count; + + if(low_offset < 0 || low_count < 0 || (low_offset + low_count < 0)) { + DEBUG(10,("posix_lock_in_range: not within 2^31 range. low_offset = %d, low_count = %d. Ignoring lock.\n", + low_offset, low_count )); + return False; + } + } + + /* + * Ok - we can map from a 64 bit number to a 31 bit lock. + */ + +#else /* HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * SMB_OFF_T is 32 bits. + */ + +#if defined(HAVE_LONGLONG) + + /* + * SMB_BIG_UINT is 64 bits, we can do a 32 bit shift. + */ + + /* + * Deal with a very common case of count of all ones. + * (lock entire file). + */ + + if(u_count == (SMB_BIG_UINT)-1) + count = 0x7FFFFFFF; + + if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) { + DEBUG(10,("posix_lock_in_range: top 32 bits not zero. u_offset = %.0f, u_count = %.0f. Ignoring lock.\n", + (double)u_offset, (double)u_count )); + return False; + } + + /* Cast from 64 bits unsigned to 32 bits signed. */ + offset = (SMB_OFF_T)u_offset; + count = (SMB_OFF_T)u_count; + + /* + * Check if we are within the 2^31 range. + */ + + if(offset < 0 || count < 0 || (offset + count < 0)) { + DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n", + (int)offset, (int)count )); + return False; + } + +#else /* HAVE_LONGLONG */ + + /* + * SMB_BIG_UINT and SMB_OFF_T are both 32 bits, + * just cast. + */ + + /* + * Deal with a very common case of count of all ones. + * (lock entire file). + */ + + if(u_count == (SMB_BIG_UINT)-1) + count = 0x7FFFFFFF; + + /* Cast from 32 bits unsigned to 32 bits signed. */ + offset = (SMB_OFF_T)u_offset; + count = (SMB_OFF_T)u_count; + + /* + * Check if we are within the 2^31 range. + */ + + if(offset < 0 || count < 0 || (offset + count < 0)) { + DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n", + (int)offset, (int)count )); + return False; + } + +#endif /* HAVE_LONGLONG */ +#endif /* LARGE_SMB_OFF_T */ +#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * The mapping was successful. + */ + + DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n", + (double)offset, (double)count )); + + *offset_out = offset; + *count_out = count; + + return True; +} + +/**************************************************************************** + POSIX function to see if a file region is locked. Returns True if the + region is locked, False otherwise. +****************************************************************************/ + +BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) +{ + SMB_OFF_T offset; + SMB_OFF_T count; + int posix_lock_type = map_posix_lock_type(fsp,lock_type); + + DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", + fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) )); + + /* + * If the requested lock won't fit in the POSIX range, we will + * never set it, so presume it is not locked. + */ + + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) + return False; + + /* + * Note that most UNIX's can *test* for a write lock on + * a read-only fd, just not *set* a write lock on a read-only + * fd. So we don't need to use map_lock_type here. + */ + + return fcntl_lock(fsp->fd,SMB_F_GETLK,offset,count,posix_lock_type); +} + +/**************************************************************************** + POSIX function to acquire a lock. Returns True if the + lock could be granted, False if not. +****************************************************************************/ + +BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) +{ + SMB_OFF_T offset; + SMB_OFF_T count; + BOOL ret = True; + int posix_lock_type = map_posix_lock_type(fsp,lock_type); + + DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", + fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) )); + + /* + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. + */ + + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) + return True; + + /* + * Note that setting multiple overlapping read locks on different + * file descriptors will not be held separately by the kernel (POSIX + * braindamage), but will be merged into one continuous read lock + * range. We cope with this case in the release_posix_lock code + * below. JRA. + */ + + ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,posix_lock_type); + + if (ret) + add_posix_lock_entry(fsp,offset,count,posix_lock_type); + + return ret; +} + +/* + * Structure used when splitting a lock range + * into a POSIX lock range. Doubly linked list. + */ + +struct unlock_list { + struct unlock_list *next; + struct unlock_list *prev; + SMB_OFF_T start; + SMB_OFF_T size; + int fd; +}; + +/**************************************************************************** + Create a list of lock ranges that don't overlap a given range. Used in calculating + POSIX lock unlocks. This is a difficult function that requires ASCII art to + understand it :-). +****************************************************************************/ + +static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list *ulhead, files_struct *fsp) +{ + struct lock_key key; + TDB_DATA kbuf, dbuf; + struct lock_struct *locks; + int num_locks, i; + + /* + * Setup the key for this fetch. + */ + key.device = dev; + key.inode = ino; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + + dbuf.dptr = NULL; + + tdb_lockchain(tdb, kbuf); + dbuf = tdb_fetch(tdb, kbuf); + + if (!dbuf.dptr) { + tdb_unlockchain(tdb, kbuf); + return ulhead; + } + + locks = (struct lock_struct *)dbuf.dptr; + num_locks = dbuf.dsize / sizeof(*locks); + + /* + * Check the current lock list on this dev/inode pair. + * Quit if the list is deleted. + */ + + DEBUG(10,("brl_unlock_list: curr: start=%.0f,size=%.0f\n", + (double)ulhead->start, (double)ulhead->size )); + + for (i=0; icontext.pid != pid) + continue; + + /* + * Walk the unlock list, checking for overlaps. Note that + * the unlock list can expand within this loop if the current + * range being examined needs to be split. + */ + + for (ul_curr = ulhead; ul_curr;) { + + DEBUG(10,("brl_unlock_list: lock: start=%.0f,size=%.0f:", + (double)lock->start, (double)lock->size )); + + if ( (ul_curr->start >= (lock->start + lock->size)) || + (lock->start > (ul_curr->start + ul_curr->size))) { + + /* No overlap with this lock - leave this range alone. */ +/********************************************* + +---------+ + | ul_curr | + +---------+ + +-------+ + | lock | + +-------+ +OR.... + +---------+ + | ul_curr | + +---------+ +**********************************************/ + + DEBUG(10,("no overlap case.\n" )); + + ul_curr = ul_curr->next; + + } else if ( (ul_curr->start >= lock->start) && + (ul_curr->start + ul_curr->size <= lock->start + lock->size) ) { + + /* + * This unlock is completely overlapped by this existing lock range + * and thus should have no effect (not be unlocked). Delete it from the list. + */ +/********************************************* + +---------+ + | ul_curr | + +---------+ + +---------------------------+ + | lock | + +---------------------------+ +**********************************************/ + /* Save the next pointer */ + struct unlock_list *ul_next = ul_curr->next; + + DEBUG(10,("delete case.\n" )); + + DLIST_REMOVE(ulhead, ul_curr); + if(ulhead == NULL) + break; /* No more list... */ + + ul_curr = ul_next; + + } else if ( (ul_curr->start >= lock->start) && + (ul_curr->start < lock->start + lock->size) && + (ul_curr->start + ul_curr->size > lock->start + lock->size) ) { + + /* + * This unlock overlaps the existing lock range at the high end. + * Truncate by moving start to existing range end and reducing size. + */ +/********************************************* + +---------------+ + | ul_curr | + +---------------+ + +---------------+ + | lock | + +---------------+ +BECOMES.... + +-------+ + |ul_curr| + +-------+ +**********************************************/ + + ul_curr->size = (ul_curr->start + ul_curr->size) - (lock->start + lock->size); + ul_curr->start = lock->start + lock->size; + + DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n", + (double)ul_curr->start, (double)ul_curr->size )); + + ul_curr = ul_curr->next; + + } else if ( (ul_curr->start < lock->start) && + (ul_curr->start + ul_curr->size > lock->start) ) { + + /* + * This unlock overlaps the existing lock range at the low end. + * Truncate by reducing size. + */ +/********************************************* + +---------------+ + | ul_curr | + +---------------+ + +---------------+ + | lock | + +---------------+ +BECOMES.... + +-------+ + |ul_curr| + +-------+ +**********************************************/ + + ul_curr->size = lock->start - ul_curr->start; + + DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n", + (double)ul_curr->start, (double)ul_curr->size )); + + ul_curr = ul_curr->next; + + } else if ( (ul_curr->start < lock->start) && + (ul_curr->start + ul_curr->size > lock->start + lock->size) ) { + /* + * Worst case scenario. Unlock request completely overlaps an existing + * lock range. Split the request into two, push the new (upper) request + * into the dlink list, and continue with the entry after ul_new (as we + * know that ul_new will not overlap with this lock). + */ +/********************************************* + +---------------------------+ + | ul_curr | + +---------------------------+ + +---------+ + | lock | + +---------+ +BECOMES..... + +-------+ +---------+ + |ul_curr| |ul_new | + +-------+ +---------+ +**********************************************/ + struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx, + sizeof(struct unlock_list)); + + if(ul_new == NULL) { + DEBUG(0,("brl_unlock_list: talloc fail.\n")); + return NULL; /* The talloc_destroy takes care of cleanup. */ + } + + ZERO_STRUCTP(ul_new); + ul_new->start = lock->start + lock->size; + ul_new->size = ul_curr->start + ul_curr->size - ul_new->start; + ul_new->smbpid = ul_curr->smbpid; + + /* Add into the dlink list after the ul_curr point - NOT at ulhead. */ + DLIST_ADD(ul_curr, ul_new); + + /* Truncate the ul_curr. */ + ul_curr->size = lock->start - ul_curr->start; + + DEBUG(10,("split case: curr: start=%.0f,size=%.0f \ +new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, + (double)ul_new->start, (double)ul_new->size )); + + ul_curr = ul_new->next; + + } else { + + /* + * This logic case should never happen. Ensure this is the + * case by forcing an abort.... Remove in production. + */ + + smb_panic("logic flaw in cases...\n"); + } + } /* end for ( ul_curr = ulhead; ul_curr;) */ + } /* end for (i=0; ifsp_name, (double)offset, (double)count )); + + /* + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. + */ + + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) + return True; + + if ((ul_ctx = talloc_init()) == NULL) { + DEBUG(0,("release_posix_lock: unable to init talloc context.\n")); + return True; /* Not a fatal error. */ + } + + if ((ul = (struct unlock_list *)talloc(ul_ctx, sizeof(struct unlock_list))) == NULL) { + DEBUG(0,("release_posix_lock: unable to talloc unlock list.\n")); + talloc_destroy(ul_ctx); + return True; /* Not a fatal error. */ + } + + /* + * Create the initial list entry containing the + * lock we want to remove. + */ + + ZERO_STRUCTP(ul); + ul->start = offset; + ul->size = count; + ul->fd = fsp->fd; + + DLIST_ADD(ulist, ul); + + /* + * The following call calculates if there are any + * overlapping read locks held by this process on + * other fd's open on the same file and creates a + * list of unlock ranges that will allow other + * POSIX lock ranges to remain on the file whilst the + * unlocks are performed. + */ + + ulist = posix_unlock_list(ul_ctx, ulist, fsp); + + /* + * Release the POSIX locks on the list of ranges returned. + */ + + for(; ulist; ulist = ulist->next) { + SMB_OFF_T offset = ulist->start; + SMB_OFF_T count = ulist->size; + + DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n", + (double)offset, (double)count )); + + if(u_count == 0) { + + /* + * This lock must overlap with an existing read-only lock + * held by another fd. Don't do any POSIX call. + */ + + continue; + } + + /* + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. + */ + + if(!posix_lock_in_range(&offset, &count, offset, count)) + continue; + + DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n", + (double)offset, (double)count )); + + ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK); + } + + talloc_destroy(ul_ctx); + + /* + * We treat this as one unlock request for POSIX accounting purposes even + * if it may have been split into multiple smaller POSIX unlock ranges. + */ + + delete_posix_lock_entry(fsp-> + + return ret; +} + +/**************************************************************************** + Return a lock list associated with an open file. +****************************************************************************/ + +struct unlock_list *brl_getlocklist( TALLOC_CTX *ctx, SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) +{ + struct lock_key key; + TDB_DATA kbuf, dbuf; + int i, count; + struct lock_struct *locks; + struct unlock_list *ulist = NULL; + + key.device = dev; + key.inode = ino; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + + dbuf.dptr = NULL; + + tdb_lockchain(tdb, kbuf); + dbuf = tdb_fetch(tdb, kbuf); + + if (!dbuf.dptr) { + tdb_unlockchain(tdb, kbuf); + return NULL; + } + + /* There are existing locks - allocate an entry for each one. */ + locks = (struct lock_struct *)dbuf.dptr; + count = dbuf.dsize / sizeof(*locks); + + for (i=0; icontext.tid == tid && + lock->context.pid == pid && + lock->fnum == fnum) { + + struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx, + sizeof(struct unlock_list)); + + if(ul_new == NULL) { + DEBUG(0,("brl_getlocklist: talloc fail.\n")); + return NULL; /* The talloc_destroy takes care of cleanup. */ + } + + ZERO_STRUCTP(ul_new); + ul_new->start = lock->start; + ul_new->size = lock->size; + ul_new->smbpid = lock->context.smbpid; + + DLIST_ADD(ulist, ul_new); + } + } + + if (dbuf.dptr) + free(dbuf.dptr); + tdb_unlockchain(tdb, kbuf); + + return ulist; +} + +/**************************************************************************** + Remove any locks on this fd. Called from file_close(). +****************************************************************************/ + +void posix_locking_close_file(files_struct *fsp) +{ + TALLOC_CTX *ul_ctx = NULL; + struct unlock_list *ul = NULL; + int eclass; + uint32 ecode; + struct pending_closes *pc; + + /* + * Optimization for the common case where we are the only + * opener of a file. If all fd entries are our own, we don't + * need to explicitly release all the locks via the POSIX functions, + * we can just release all the brl locks, as in the no POSIX locking case. + */ + + if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) != NULL) { + + if (pc->fd_array_size == 1 && pc->fd_array[0] == fsp->fd ) { + /* + * Just release all the brl locks, no need to release individually. + */ + + brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); + return; + } + } + + if ((ul_ctx = talloc_init()) == NULL) { + DEBUG(0,("locking_close_file: unable to init talloc context.\n")); + return; + } + + /* + * We need to release all POSIX locks we have on this + * fd. Get all our existing locks from the tdb locking database. + */ + + ul = brl_getlocklist(ul_ctx, fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); + + /* + * Now unlock all of them. This will remove the brl entry also + * for each lock. Note we need to make sure the global_smbpid matches + * the one associated with each lock in case the client plays games + * with smbpids (like smbtorture does :-). + */ + + for(; ul; ul = ul->next) { + global_smbpid = ul->smbpid; + do_unlock(fsp,fsp->conn,ul->size,ul->start,&eclass,&ecode); + } + + talloc_destroy(ul_ctx); + + } else { + + /* + * Just release all the brl locks, no need to release individually. + */ + + brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); + } +} + +/******************************************************************* + Create the in-memory POSIX lock databases. +********************************************************************/ + +void posix_lock_init(void) +{ + if (posix_lock_tdb && posix_pending_close_tdb) + return; + + if (!posix_lock_tdb) + posix_lock_tdb = tdb_open(NULL, 0, TDB_CLEAR_IF_FIRST, + O_RDWR|O_CREAT, 0644); + if (!posix_lock_tdb) { + DEBUG(0,("Failed to open POSIX byte range locking database.\n")); + } + if (!posix_pending_close_tdb) + posix_pending_close_tdb = tdb_open(NULL, 0, TDB_CLEAR_IF_FIRST, + O_RDWR|O_CREAT, 0644); + if (!posix_pending_close_tdb) { + DEBUG(0,("Failed to open POSIX pending close database.\n")); + } +} -- cgit From 9a5eb068ab32418e793d482db1f078f147f9ee08 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Apr 2000 20:54:23 +0000 Subject: Ok - this is the *third* implementation of this (third time's the charm :-). This implementation keeps all POSIX lock records in a separate in memory tdb database only known about in locking/posix.c. In addition, the pending close fd's are also held in a tdb which has an array of fd's indexed by device and inode. The walk-split code uglyness has been moved to posix.c from brlock.c, which is the only place that needs to know about it, and the extra functions hacked into brlock to expose internal state have been removed. This implementation passes smbtorture locktest4, the only thing I need to check now for completeness is what to do about lock upgrade/downgrades which Win32 allows under some *very* strange circumstances. Jeremy. (This used to be commit 3f655de1c764b9ee1472a111621d4317f19f624d) --- source3/locking/brlock.c | 296 +-------------------- source3/locking/locking.c | 641 +--------------------------------------------- source3/locking/posix.c | 322 +++++++++-------------- 3 files changed, 137 insertions(+), 1122 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 410fb3fc0b..0ded1846b4 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -170,237 +170,6 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, return False; } -/**************************************************************************** - Create a list of lock ranges that don't overlap a given range. Used in calculating - POSIX lock unlocks. This is a difficult function that requires ASCII art to - understand it :-). -****************************************************************************/ - -struct unlock_list *brl_unlock_list(TALLOC_CTX *ctx, struct unlock_list *ulhead, - pid_t pid, SMB_DEV_T dev, SMB_INO_T ino) -{ - struct lock_key key; - TDB_DATA kbuf, dbuf; - struct lock_struct *locks; - int num_locks, i; - - /* - * Setup the key for this fetch. - */ - key.device = dev; - key.inode = ino; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); - - dbuf.dptr = NULL; - - tdb_lockchain(tdb, kbuf); - dbuf = tdb_fetch(tdb, kbuf); - - if (!dbuf.dptr) { - tdb_unlockchain(tdb, kbuf); - return ulhead; - } - - locks = (struct lock_struct *)dbuf.dptr; - num_locks = dbuf.dsize / sizeof(*locks); - - /* - * Check the current lock list on this dev/inode pair. - * Quit if the list is deleted. - */ - - DEBUG(10,("brl_unlock_list: curr: start=%.0f,size=%.0f\n", - (double)ulhead->start, (double)ulhead->size )); - - for (i=0; icontext.pid != pid) - continue; - - /* - * Walk the unlock list, checking for overlaps. Note that - * the unlock list can expand within this loop if the current - * range being examined needs to be split. - */ - - for (ul_curr = ulhead; ul_curr;) { - - DEBUG(10,("brl_unlock_list: lock: start=%.0f,size=%.0f:", - (double)lock->start, (double)lock->size )); - - if ( (ul_curr->start >= (lock->start + lock->size)) || - (lock->start > (ul_curr->start + ul_curr->size))) { - - /* No overlap with this lock - leave this range alone. */ -/********************************************* - +---------+ - | ul_curr | - +---------+ - +-------+ - | lock | - +-------+ -OR.... - +---------+ - | ul_curr | - +---------+ -**********************************************/ - - DEBUG(10,("no overlap case.\n" )); - - ul_curr = ul_curr->next; - - } else if ( (ul_curr->start >= lock->start) && - (ul_curr->start + ul_curr->size <= lock->start + lock->size) ) { - - /* - * This unlock is completely overlapped by this existing lock range - * and thus should have no effect (not be unlocked). Delete it from the list. - */ -/********************************************* - +---------+ - | ul_curr | - +---------+ - +---------------------------+ - | lock | - +---------------------------+ -**********************************************/ - /* Save the next pointer */ - struct unlock_list *ul_next = ul_curr->next; - - DEBUG(10,("delete case.\n" )); - - DLIST_REMOVE(ulhead, ul_curr); - if(ulhead == NULL) - break; /* No more list... */ - - ul_curr = ul_next; - - } else if ( (ul_curr->start >= lock->start) && - (ul_curr->start < lock->start + lock->size) && - (ul_curr->start + ul_curr->size > lock->start + lock->size) ) { - - /* - * This unlock overlaps the existing lock range at the high end. - * Truncate by moving start to existing range end and reducing size. - */ -/********************************************* - +---------------+ - | ul_curr | - +---------------+ - +---------------+ - | lock | - +---------------+ -BECOMES.... - +-------+ - |ul_curr| - +-------+ -**********************************************/ - - ul_curr->size = (ul_curr->start + ul_curr->size) - (lock->start + lock->size); - ul_curr->start = lock->start + lock->size; - - DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n", - (double)ul_curr->start, (double)ul_curr->size )); - - ul_curr = ul_curr->next; - - } else if ( (ul_curr->start < lock->start) && - (ul_curr->start + ul_curr->size > lock->start) ) { - - /* - * This unlock overlaps the existing lock range at the low end. - * Truncate by reducing size. - */ -/********************************************* - +---------------+ - | ul_curr | - +---------------+ - +---------------+ - | lock | - +---------------+ -BECOMES.... - +-------+ - |ul_curr| - +-------+ -**********************************************/ - - ul_curr->size = lock->start - ul_curr->start; - - DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n", - (double)ul_curr->start, (double)ul_curr->size )); - - ul_curr = ul_curr->next; - - } else if ( (ul_curr->start < lock->start) && - (ul_curr->start + ul_curr->size > lock->start + lock->size) ) { - /* - * Worst case scenario. Unlock request completely overlaps an existing - * lock range. Split the request into two, push the new (upper) request - * into the dlink list, and continue with the entry after ul_new (as we - * know that ul_new will not overlap with this lock). - */ -/********************************************* - +---------------------------+ - | ul_curr | - +---------------------------+ - +---------+ - | lock | - +---------+ -BECOMES..... - +-------+ +---------+ - |ul_curr| |ul_new | - +-------+ +---------+ -**********************************************/ - struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx, - sizeof(struct unlock_list)); - - if(ul_new == NULL) { - DEBUG(0,("brl_unlock_list: talloc fail.\n")); - return NULL; /* The talloc_destroy takes care of cleanup. */ - } - - ZERO_STRUCTP(ul_new); - ul_new->start = lock->start + lock->size; - ul_new->size = ul_curr->start + ul_curr->size - ul_new->start; - ul_new->smbpid = ul_curr->smbpid; - - /* Add into the dlink list after the ul_curr point - NOT at ulhead. */ - DLIST_ADD(ul_curr, ul_new); - - /* Truncate the ul_curr. */ - ul_curr->size = lock->start - ul_curr->start; - - DEBUG(10,("split case: curr: start=%.0f,size=%.0f \ -new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, - (double)ul_new->start, (double)ul_new->size )); - - ul_curr = ul_new->next; - - } else { - - /* - * This logic case should never happen. Ensure this is the - * case by forcing an abort.... Remove in production. - */ - - smb_panic("logic flaw in cases...\n"); - } - } /* end for ( ul_curr = ulhead; ul_curr;) */ - } /* end for (i=0; icontext.tid == tid && - lock->context.pid == pid && - lock->fnum == fnum) { - - struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx, - sizeof(struct unlock_list)); - - if(ul_new == NULL) { - DEBUG(0,("brl_getlocklist: talloc fail.\n")); - return NULL; /* The talloc_destroy takes care of cleanup. */ - } - - ZERO_STRUCTP(ul_new); - ul_new->start = lock->start; - ul_new->size = lock->size; - ul_new->smbpid = lock->context.smbpid; - - DLIST_ADD(ulist, ul_new); - } - } - - if (dbuf.dptr) - free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); - - return ulist; -} - - /**************************************************************************** Traverse the whole database with this function, calling traverse_callback on each lock. diff --git a/source3/locking/locking.c b/source3/locking/locking.c index fa56e0a628..75198d6303 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -42,190 +42,6 @@ int global_smbpid; /* the locking database handle */ static TDB_CONTEXT *tdb; -/* - * Doubly linked list to hold pending closes needed for - * POSIX locks. This may be changed to use a hash table (as - * in lib/hash.c if this is too slow in use.... JRA. - */ - -struct pending_closes { - struct pending_closes *next; - struct pending_closes *prev; - SMB_DEV_T dev; - SMB_INO_T inode; - int num_posix_locks; - size_t fd_array_size; - int *fd_array; -}; - -static struct pending_closes *pending_close_list = NULL; - -/**************************************************************************** - Find a dev/inode pair in the pending close list. -****************************************************************************/ - -static struct pending_closes *find_pending_close_entry(SMB_DEV_T dev, SMB_INO_T inode) -{ - struct pending_closes *pc; - - for(pc = pending_close_list; pc; pc = pc->next) { - if (dev == pc->dev && inode == pc->inode) { - DLIST_PROMOTE(pending_close_list,pc); - return pc; - } - } - - return NULL; -} - -/**************************************************************************** - Add an fd into the pending close array. -****************************************************************************/ - -static BOOL add_fd_to_close_entry(struct pending_closes *pc, int fd) -{ - if ((pc->fd_array = (int *)Realloc(pc->fd_array, (pc->fd_array_size + 1)*sizeof(int))) == NULL) { - DEBUG(0,("add_fd_to_close_entry: Unable to increase fd_array !\n")); - return False; - } - - pc->fd_array[pc->fd_array_size] = fd; - pc->fd_array_size++; - - DEBUG(10,("add_fd_to_close_entry: added fd = %d, size = %u : dev = %.0f, ino = %.0f\n", - fd, (unsigned int)pc->fd_array_size, (double)pc->dev, (double)pc->inode )); - - return True; -} - -/**************************************************************************** - Deal with pending closes needed by POSIX locking support. -****************************************************************************/ - -int fd_close_posix(struct connection_struct *conn, files_struct *fsp) -{ - struct pending_closes *pc; - int saved_errno = 0; - int ret; - size_t i; - - if (!lp_posix_locking(SNUM(conn))) { - ret = conn->vfs_ops.close(fsp->fd); - fsp->fd = -1; - return ret; - } - - pc = find_pending_close_entry(fsp->dev, fsp->inode); - - if (!pc) { - /* - * No other open with a POSIX lock on this dev/inode within this smbd. - * Just close the fd. - */ - ret = conn->vfs_ops.close(fsp->fd); - fsp->fd = -1; - return ret; - } - - if (pc->num_posix_locks) { - /* - * There are outstanding locks on this dev/inode pair. - * Add our fd to the list and set fsp->fd to -1 to - * stop the close. - */ - - if (!add_fd_to_close_entry(pc, fsp->fd)) - return False; - - fsp->fd = -1; - return 0; - } - - DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)pc->fd_array_size )); - - /* - * This is the last close. If there are pending fd's close them - * now. Save the errno just in case. - */ - - for(i = 0; i < pc->fd_array_size; i++) { - if (pc->fd_array[i] != -1) { - if (conn->vfs_ops.close(pc->fd_array[i]) == -1) { - saved_errno = errno; - } - } - } - - if (pc->fd_array) - free((char *)pc->fd_array); - - DLIST_REMOVE(pending_close_list, pc); - - free((char *)pc); - - ret = conn->vfs_ops.close(fsp->fd); - - if (saved_errno != 0) { - errno = saved_errno; - ret = -1; - } - - fsp->fd = -1; - - return ret; -} - -/**************************************************************************** - A POSIX lock was granted. Increment the lock list count (create if needed). -****************************************************************************/ - -static void increment_posix_lock_list(files_struct *fsp) -{ - struct pending_closes *pc; - - if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) == NULL) { - if (!(pc = (struct pending_closes *)malloc(sizeof(struct pending_closes)))) { - DEBUG(0,("increment_lock_list: malloc fail.\n")); - return; - } - ZERO_STRUCTP(pc); - pc->dev = fsp->dev; - pc->inode = fsp->inode; - DLIST_ADD(pending_close_list, pc); - - DEBUG(10,("increment_posix_lock_list: creating entry for file %s: dev = %.0f, ino = %.0f\n", - fsp->fsp_name, (double)fsp->dev, (double)fsp->inode )); - } - - pc->num_posix_locks++; - - DEBUG(10,("increment_posix_lock_list: entry for file %s: dev = %.0f, ino = %.0f, num_locks = %d\n", - fsp->fsp_name, (double)pc->dev, (double)pc->inode, pc->num_posix_locks )); -} - - -/**************************************************************************** - A POSIX lock was granted. Decrement the lock list count. -****************************************************************************/ - -static void decrement_posix_lock_list(files_struct *fsp) -{ - struct pending_closes *pc; - - pc = find_pending_close_entry(fsp->dev, fsp->inode); - - if (pc == NULL) { - smb_panic("decrement_lock_list: Unlock not found !\n"); - } - - pc->num_posix_locks--; - - DEBUG(10,("decrement_posix_lock_list: entry for file %s: dev = %.0f, ino = %.0f, num_locks = %d\n", - fsp->fsp_name, (double)pc->dev, (double)pc->inode, pc->num_posix_locks )); - - SMB_ASSERT(pc->num_posix_locks >= 0); -} - /**************************************************************************** Debugging aid :-). ****************************************************************************/ @@ -235,347 +51,6 @@ static const char *lock_type_name(enum brl_type lock_type) return (lock_type == READ_LOCK) ? "READ" : "WRITE"; } -/**************************************************************************** - Utility function to map a lock type correctly depending on the open - mode of a file. -****************************************************************************/ - -static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) -{ - if((lock_type == WRITE_LOCK) && !fsp->can_write) { - /* - * Many UNIX's cannot get a write lock on a file opened read-only. - * Win32 locking semantics allow this. - * Do the best we can and attempt a read-only lock. - */ - DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n")); - return F_RDLCK; - } else if((lock_type == READ_LOCK) && !fsp->can_read) { - /* - * Ditto for read locks on write only files. - */ - DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n")); - return F_WRLCK; - } - - /* - * This return should be the most normal, as we attempt - * to always open files read/write. - */ - - return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK; -} - -/**************************************************************************** - Check to see if the given unsigned lock range is within the possible POSIX - range. Modifies the given args to be in range if possible, just returns - False if not. -****************************************************************************/ - -static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, - SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) -{ - SMB_OFF_T offset; - SMB_OFF_T count; - -#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) - - SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); - SMB_OFF_T mask = (mask2<<1); - SMB_OFF_T neg_mask = ~mask; - - /* - * In this case SMB_OFF_T is 64 bits, - * and the underlying system can handle 64 bit signed locks. - * Cast to signed type. - */ - - offset = (SMB_OFF_T)u_offset; - count = (SMB_OFF_T)u_count; - - /* - * Deal with a very common case of count of all ones. - * (lock entire file). - */ - - if(count == (SMB_OFF_T)-1) - count &= ~mask; - - /* - * POSIX lock ranges cannot be negative. - * Fail if any combination becomes negative. - */ - - if(offset < 0 || count < 0 || (offset + count < 0)) { - DEBUG(10,("posix_lock_in_range: negative range: offset = %.0f, count = %.0f. Ignoring lock.\n", - (double)offset, (double)count )); - return False; - } - - /* - * In this case SMB_OFF_T is 64 bits, the offset and count - * fit within the positive range, and the underlying - * system can handle 64 bit locks. Just return as the - * cast values are ok. - */ - -#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ - - /* - * In this case either SMB_OFF_T is 32 bits, - * or the underlying system cannot handle 64 bit signed locks. - * Either way we have to try and mangle to fit within 31 bits. - * This is difficult. - */ - -#if defined(HAVE_BROKEN_FCNTL64_LOCKS) - - /* - * SMB_OFF_T is 64 bits, but we need to use 31 bits due to - * broken large locking. - */ - - /* - * Deal with a very common case of count of all ones. - * (lock entire file). - */ - - if(u_count == (SMB_BIG_UINT)-1) - count = 0x7FFFFFFF; - - if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) { - DEBUG(10,("posix_lock_in_range: top 32 bits not zero. offset = %.0f, count = %.0f. Ignoring lock.\n", - (double)u_offset, (double)u_count )); - /* Top 32 bits of offset or count were not zero. */ - return False; - } - - /* Cast from 64 bits unsigned to 64 bits signed. */ - offset = (SMB_OFF_T)u_offset; - count = (SMB_OFF_T)u_count; - - /* - * Check if we are within the 2^31 range. - */ - - { - int32 low_offset = (int32)offset; - int32 low_count = (int32)count; - - if(low_offset < 0 || low_count < 0 || (low_offset + low_count < 0)) { - DEBUG(10,("posix_lock_in_range: not within 2^31 range. low_offset = %d, low_count = %d. Ignoring lock.\n", - low_offset, low_count )); - return False; - } - } - - /* - * Ok - we can map from a 64 bit number to a 31 bit lock. - */ - -#else /* HAVE_BROKEN_FCNTL64_LOCKS */ - - /* - * SMB_OFF_T is 32 bits. - */ - -#if defined(HAVE_LONGLONG) - - /* - * SMB_BIG_UINT is 64 bits, we can do a 32 bit shift. - */ - - /* - * Deal with a very common case of count of all ones. - * (lock entire file). - */ - - if(u_count == (SMB_BIG_UINT)-1) - count = 0x7FFFFFFF; - - if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) { - DEBUG(10,("posix_lock_in_range: top 32 bits not zero. u_offset = %.0f, u_count = %.0f. Ignoring lock.\n", - (double)u_offset, (double)u_count )); - return False; - } - - /* Cast from 64 bits unsigned to 32 bits signed. */ - offset = (SMB_OFF_T)u_offset; - count = (SMB_OFF_T)u_count; - - /* - * Check if we are within the 2^31 range. - */ - - if(offset < 0 || count < 0 || (offset + count < 0)) { - DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n", - (int)offset, (int)count )); - return False; - } - -#else /* HAVE_LONGLONG */ - - /* - * SMB_BIG_UINT and SMB_OFF_T are both 32 bits, - * just cast. - */ - - /* - * Deal with a very common case of count of all ones. - * (lock entire file). - */ - - if(u_count == (SMB_BIG_UINT)-1) - count = 0x7FFFFFFF; - - /* Cast from 32 bits unsigned to 32 bits signed. */ - offset = (SMB_OFF_T)u_offset; - count = (SMB_OFF_T)u_count; - - /* - * Check if we are within the 2^31 range. - */ - - if(offset < 0 || count < 0 || (offset + count < 0)) { - DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n", - (int)offset, (int)count )); - return False; - } - -#endif /* HAVE_LONGLONG */ -#endif /* LARGE_SMB_OFF_T */ -#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ - - /* - * The mapping was successful. - */ - - DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n", - (double)offset, (double)count )); - - *offset_out = offset; - *count_out = count; - - return True; -} - -/**************************************************************************** - POSIX function to see if a file region is locked. Returns True if the - region is locked, False otherwise. -****************************************************************************/ - -static BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) -{ - SMB_OFF_T offset; - SMB_OFF_T count; - - DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) )); - - /* - * If the requested lock won't fit in the POSIX range, we will - * never set it, so presume it is not locked. - */ - - if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) - return False; - - /* - * Note that most UNIX's can *test* for a write lock on - * a read-only fd, just not *set* a write lock on a read-only - * fd. So we don't need to use map_lock_type here. - */ - - return fcntl_lock(fsp->fd,SMB_F_GETLK,offset,count,lock_type); -} - -/**************************************************************************** - POSIX function to acquire a lock. Returns True if the - lock could be granted, False if not. -****************************************************************************/ - -static BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) -{ - SMB_OFF_T offset; - SMB_OFF_T count; - BOOL ret = True; - - DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) )); - - /* - * If the requested lock won't fit in the POSIX range, we will - * pretend it was successful. - */ - - if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { - increment_posix_lock_list(fsp); - return True; - } - - /* - * Note that setting multiple overlapping read locks on different - * file descriptors will not be held separately by the kernel (POSIX - * braindamage), but will be merged into one continuous read lock - * range. We cope with this case in the release_posix_lock code - * below. JRA. - */ - - ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,map_posix_lock_type(fsp,lock_type)); - - if (ret) - increment_posix_lock_list(fsp); - - return ret; -} - -/**************************************************************************** - POSIX function to release a lock given a list. Returns True if the - lock could be released, False if not. -****************************************************************************/ - -static BOOL release_posix_lock(files_struct *fsp, struct unlock_list *ulist) -{ - BOOL ret = True; - - for(; ulist; ulist = ulist->next) { - SMB_OFF_T offset = ulist->start; - SMB_OFF_T count = ulist->size; - - DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", - fsp->fsp_name, (double)offset, (double)count )); - - if(count == 0) { - - /* - * This lock must overlap with an existing read-only lock - * held by another fd. Don't do any POSIX call. - */ - - continue; - } - - /* - * If the requested lock won't fit in the POSIX range, we will - * pretend it was successful. - */ - - if(!posix_lock_in_range(&offset, &count, offset, count)) - continue; - - ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK); - } - - /* - * We treat this as one unlock request for POSIX accounting purposes even - * if it may have been split into multiple smaller POSIX unlock ranges. - */ - - decrement_posix_lock_list(fsp); - - return ret; -} - /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ @@ -675,10 +150,6 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, int *eclass,uint32 *ecode) { BOOL ok = False; - TALLOC_CTX *ul_ctx = NULL; - struct unlock_list *ulist = NULL; - struct unlock_list *ul = NULL; - pid_t pid; if (!lp_locking(SNUM(conn))) return(True); @@ -698,10 +169,8 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, * match then don't bother looking to remove POSIX locks. */ - pid = getpid(); - ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, pid, conn->cnum, offset, count); + global_smbpid, getpid(), conn->cnum, offset, count); if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); @@ -713,47 +182,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, if (!lp_posix_locking(SNUM(conn))) return True; - if ((ul_ctx = talloc_init()) == NULL) { - DEBUG(0,("do_unlock: unable to init talloc context.\n")); - return True; /* Not a fatal error. */ - } - - if ((ul = (struct unlock_list *)talloc(ul_ctx, sizeof(struct unlock_list))) == NULL) { - DEBUG(0,("do_unlock: unable to talloc unlock list.\n")); - talloc_destroy(ul_ctx); - return True; /* Not a fatal error. */ - } - - /* - * Create the initial list entry containing the - * lock we want to remove. - */ - - ZERO_STRUCTP(ul); - ul->start = offset; - ul->size = count; - ul->smbpid = global_smbpid; - - DLIST_ADD(ulist, ul); - - /* - * The following call calculates if there are any - * overlapping read locks held by this process on - * other fd's open on the same file and creates a - * list of unlock ranges that will allow other - * POSIX lock ranges to remain on the file whilst the - * unlocks are performed. - */ - - ulist = brl_unlock_list(ul_ctx, ulist, pid, fsp->dev, fsp->inode); - - /* - * Release the POSIX locks on the list of ranges returned. - */ - - (void)release_posix_lock(fsp, ulist); - - talloc_destroy(ul_ctx); + (void)release_posix_lock(fsp, offset, count); return True; /* Did unlock */ } @@ -769,66 +198,19 @@ void locking_close_file(files_struct *fsp) if (!lp_locking(SNUM(fsp->conn))) return; - if(lp_posix_locking(SNUM(fsp->conn))) { - - TALLOC_CTX *ul_ctx = NULL; - struct unlock_list *ul = NULL; - int eclass; - uint32 ecode; - struct pending_closes *pc; - - /* - * Optimization for the common case where we are the only - * opener of a file. If all fd entries are our own, we don't - * need to explicitly release all the locks via the POSIX functions, - * we can just release all the brl locks, as in the no POSIX locking case. - */ - - if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) != NULL) { - - if (pc->fd_array_size == 1 && pc->fd_array[0] == fsp->fd ) { - /* - * Just release all the brl locks, no need to release individually. - */ - - brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); - return; - } - } - - if ((ul_ctx = talloc_init()) == NULL) { - DEBUG(0,("locking_close_file: unable to init talloc context.\n")); - return; - } - - /* - * We need to release all POSIX locks we have on this - * fd. Get all our existing locks from the tdb locking database. - */ - - ul = brl_getlocklist(ul_ctx, fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); - - /* - * Now unlock all of them. This will remove the brl entry also - * for each lock. Note we need to make sure the global_smbpid matches - * the one associated with each lock in case the client plays games - * with smbpids (like smbtorture does :-). - */ + /* + * Just release all the brl locks, no need to release individually. + */ - for(; ul; ul = ul->next) { - global_smbpid = ul->smbpid; - do_unlock(fsp,fsp->conn,ul->size,ul->start,&eclass,&ecode); - } - - talloc_destroy(ul_ctx); + brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); - } else { + if(lp_posix_locking(SNUM(fsp->conn))) { - /* - * Just release all the brl locks, no need to release individually. + /* + * Release all the POSIX locks. */ + posix_locking_close_file(fsp); - brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); } } @@ -851,6 +233,9 @@ BOOL locking_init(int read_only) return False; } + if (!posix_locking_init()) + return False; + return True; } diff --git a/source3/locking/posix.c b/source3/locking/posix.c index f05a0a2a31..0fcba3432d 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -53,7 +53,7 @@ struct posix_lock { }; /* - * The data in POSIX pending close records is an unsorted linear array of ints + * The data in POSIX pending close records is an unsorted linear array of int * records. It is unnecessary to store the count as tdb provides the * size of the record. */ @@ -73,7 +73,7 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) { static struct posix_lock_key key; TDB_DATA kbuf; - key.dev = dev; + key.device = dev; key.inode = inode; kbuf.dptr = (char *)&key; kbuf.dsize = sizeof(key); @@ -95,10 +95,8 @@ static TDB_DATA locking_key_fsp(files_struct *fsp) static BOOL add_fd_to_close_entry(files_struct *fsp) { - struct posix_lock_key = locking_key_fsp(fsp); - TDB_DATA kbuf, dbuf; - size_t count = 0; - int *fd_array = NULL; + TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA dbuf; dbuf.dptr = NULL; @@ -129,8 +127,7 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) static void delete_close_entries(files_struct *fsp) { - struct posix_lock_key = locking_key_fsp(fsp); - TDB_DATA kbuf, dbuf; + TDB_DATA kbuf = locking_key_fsp(fsp); tdb_lockchain(posix_pending_close_tdb, kbuf); if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) @@ -145,8 +142,8 @@ static void delete_close_entries(files_struct *fsp) static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) { - struct posix_lock_key = locking_key_fsp(fsp); - TDB_DATA kbuf, dbuf; + TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA dbuf; size_t count = 0; *entries = NULL; @@ -175,8 +172,8 @@ static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries) { - struct posix_lock_key = locking_key_fsp(fsp); - TDB_DATA kbuf, dbuf; + TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA dbuf; size_t count = 0; *entries = NULL; @@ -191,8 +188,8 @@ static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entr return 0; } - *entries = (struct posix_lock_struct *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock_struct)); + *entries = (struct posix_lock *)dbuf.dptr; + count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); tdb_unlockchain(posix_lock_tdb, kbuf); @@ -251,7 +248,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) * from the tdb and close them all. */ - count = get_posix_pending_close_entries(fsp, &fd_array) + count = get_posix_pending_close_entries(fsp, &fd_array); if (count) { DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); @@ -307,8 +304,8 @@ static const char *posix_lock_type_name(int lock_type) static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type) { - struct posix_lock_key = locking_key_fsp(fsp); - TDB_DATA kbuf, dbuf; + TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA dbuf; struct posix_lock pl; /* @@ -325,14 +322,14 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s tdb_lockchain(posix_lock_tdb, kbuf); dbuf = tdb_fetch(posix_lock_tdb, kbuf); - dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*pl)); + dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl)); if (!dbuf.dptr) { DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); goto fail; } - memcpy(dbuf.dptr + dbuf.dsize, rec, sizeof(*pl)); - dbuf.dsize += sizeof(*pl); + memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl)); + dbuf.dsize += sizeof(pl); if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name)); @@ -351,7 +348,7 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s fail: if (dbuf.dptr) free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); + tdb_unlockchain(posix_lock_tdb, kbuf); return False; } @@ -361,8 +358,8 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size) { - struct posix_lock_key = locking_key_fsp(fsp); - TDB_DATA kbuf, dbuf; + TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA dbuf; struct posix_lock *locks; size_t i, count; @@ -377,13 +374,13 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_ } /* There are existing locks - find a match. */ - locks = (struct lock_struct *)dbuf.dptr; - count = (size_t(dbuf.dsize / sizeof(*locks)); + locks = (struct posix_lock *)dbuf.dptr; + count = (size_t)(dbuf.dsize / sizeof(*locks)); for (i=0; ifd == fd && + if (pl->fd == fsp->fd && pl->start == start && pl->size == size) { /* Found it - delete it. */ @@ -394,11 +391,11 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_ memmove(&locks[i], &locks[i+1], sizeof(*locks)*((count-1) - i)); } dbuf.dsize -= sizeof(*locks); - tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); + tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); } free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); + tdb_unlockchain(posix_lock_tdb, kbuf); return True; } } @@ -408,7 +405,7 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_ fail: if (dbuf.dptr) free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); + tdb_unlockchain(posix_lock_tdb, kbuf); return False; } @@ -648,7 +645,7 @@ BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_co int posix_lock_type = map_posix_lock_type(fsp,lock_type); DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) )); + fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); /* * If the requested lock won't fit in the POSIX range, we will @@ -680,7 +677,7 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou int posix_lock_type = map_posix_lock_type(fsp,lock_type); DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) )); + fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); /* * If the requested lock won't fit in the POSIX range, we will @@ -691,9 +688,9 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou return True; /* - * Note that setting multiple overlapping read locks on different + * Note that setting multiple overlapping locks on different * file descriptors will not be held separately by the kernel (POSIX - * braindamage), but will be merged into one continuous read lock + * braindamage), but will be merged into one continuous lock * range. We cope with this case in the release_posix_lock code * below. JRA. */ @@ -716,7 +713,6 @@ struct unlock_list { struct unlock_list *prev; SMB_OFF_T start; SMB_OFF_T size; - int fd; }; /**************************************************************************** @@ -727,49 +723,37 @@ struct unlock_list { static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list *ulhead, files_struct *fsp) { - struct lock_key key; - TDB_DATA kbuf, dbuf; - struct lock_struct *locks; - int num_locks, i; - - /* - * Setup the key for this fetch. - */ - key.device = dev; - key.inode = ino; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); + TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA dbuf; + struct posix_lock *locks; + size_t num_locks, i; dbuf.dptr = NULL; - tdb_lockchain(tdb, kbuf); - dbuf = tdb_fetch(tdb, kbuf); + tdb_lockchain(posix_lock_tdb, kbuf); + dbuf = tdb_fetch(posix_lock_tdb, kbuf); if (!dbuf.dptr) { - tdb_unlockchain(tdb, kbuf); + tdb_unlockchain(posix_lock_tdb, kbuf); return ulhead; } - locks = (struct lock_struct *)dbuf.dptr; - num_locks = dbuf.dsize / sizeof(*locks); + locks = (struct posix_lock *)dbuf.dptr; + num_locks = (size_t)(dbuf.dsize / sizeof(*locks)); /* * Check the current lock list on this dev/inode pair. * Quit if the list is deleted. */ - DEBUG(10,("brl_unlock_list: curr: start=%.0f,size=%.0f\n", + DEBUG(10,("posix_unlock_list: curr: start=%.0f,size=%.0f\n", (double)ulhead->start, (double)ulhead->size )); for (i=0; icontext.pid != pid) - continue; - /* * Walk the unlock list, checking for overlaps. Note that * the unlock list can expand within this loop if the current @@ -778,7 +762,7 @@ static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list for (ul_curr = ulhead; ul_curr;) { - DEBUG(10,("brl_unlock_list: lock: start=%.0f,size=%.0f:", + DEBUG(10,("posix_unlock_list: lock: start=%.0f,size=%.0f:", (double)lock->start, (double)lock->size )); if ( (ul_curr->start >= (lock->start + lock->size)) || @@ -908,14 +892,13 @@ BECOMES..... sizeof(struct unlock_list)); if(ul_new == NULL) { - DEBUG(0,("brl_unlock_list: talloc fail.\n")); + DEBUG(0,("posix_unlock_list: talloc fail.\n")); return NULL; /* The talloc_destroy takes care of cleanup. */ } ZERO_STRUCTP(ul_new); ul_new->start = lock->start + lock->size; ul_new->size = ul_curr->start + ul_curr->size - ul_new->start; - ul_new->smbpid = ul_curr->smbpid; /* Add into the dlink list after the ul_curr point - NOT at ulhead. */ DLIST_ADD(ul_curr, ul_new); @@ -941,7 +924,7 @@ new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, } /* end for ( ul_curr = ulhead; ul_curr;) */ } /* end for (i=0; istart, (double)ul_curr->size, } /**************************************************************************** - POSIX function to release a lock given a list. Returns True if the + POSIX function to release a lock. Returns True if the lock could be released, False if not. ****************************************************************************/ -static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) +BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) { SMB_OFF_T offset; SMB_OFF_T count; @@ -964,7 +947,7 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG struct unlock_list *ul = NULL; DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", - fsp->fsp_name, (double)offset, (double)count )); + fsp->fsp_name, (double)u_offset, (double)u_count )); /* * If the requested lock won't fit in the POSIX range, we will @@ -974,6 +957,13 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) return True; + /* + * We treat this as one unlock request for POSIX accounting purposes even + * if it may have been split into multiple smaller POSIX unlock ranges. + */ + + delete_posix_lock_entry(fsp, offset, count); + if ((ul_ctx = talloc_init()) == NULL) { DEBUG(0,("release_posix_lock: unable to init talloc context.\n")); return True; /* Not a fatal error. */ @@ -993,15 +983,14 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG ZERO_STRUCTP(ul); ul->start = offset; ul->size = count; - ul->fd = fsp->fd; DLIST_ADD(ulist, ul); /* * The following call calculates if there are any - * overlapping read locks held by this process on - * other fd's open on the same file and creates a - * list of unlock ranges that will allow other + * overlapping locks held by this process on + * fd's open on the same file and creates a + * list of unlock ranges that will allow * POSIX lock ranges to remain on the file whilst the * unlocks are performed. */ @@ -1013,108 +1002,43 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG */ for(; ulist; ulist = ulist->next) { - SMB_OFF_T offset = ulist->start; - SMB_OFF_T count = ulist->size; - - DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n", - (double)offset, (double)count )); + offset = ulist->start; + count = ulist->size; if(u_count == 0) { /* - * This lock must overlap with an existing read-only lock - * held by another fd. Don't do any POSIX call. + * This lock must overlap with an existing lock. + * Don't do any POSIX call. */ continue; } - /* - * If the requested lock won't fit in the POSIX range, we will - * pretend it was successful. - */ - - if(!posix_lock_in_range(&offset, &count, offset, count)) - continue; - DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n", (double)offset, (double)count )); - ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK); + if (!fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK)) + ret = False; } talloc_destroy(ul_ctx); - /* - * We treat this as one unlock request for POSIX accounting purposes even - * if it may have been split into multiple smaller POSIX unlock ranges. - */ - - delete_posix_lock_entry(fsp-> - return ret; } /**************************************************************************** - Return a lock list associated with an open file. + Remove all lock entries for a specific dev/inode pair from the tdb. ****************************************************************************/ -struct unlock_list *brl_getlocklist( TALLOC_CTX *ctx, SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) +static void delete_posix_lock_entries(files_struct *fsp) { - struct lock_key key; - TDB_DATA kbuf, dbuf; - int i, count; - struct lock_struct *locks; - struct unlock_list *ulist = NULL; - - key.device = dev; - key.inode = ino; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); - - dbuf.dptr = NULL; - - tdb_lockchain(tdb, kbuf); - dbuf = tdb_fetch(tdb, kbuf); - - if (!dbuf.dptr) { - tdb_unlockchain(tdb, kbuf); - return NULL; - } - - /* There are existing locks - allocate an entry for each one. */ - locks = (struct lock_struct *)dbuf.dptr; - count = dbuf.dsize / sizeof(*locks); - - for (i=0; icontext.tid == tid && - lock->context.pid == pid && - lock->fnum == fnum) { - - struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx, - sizeof(struct unlock_list)); - - if(ul_new == NULL) { - DEBUG(0,("brl_getlocklist: talloc fail.\n")); - return NULL; /* The talloc_destroy takes care of cleanup. */ - } - - ZERO_STRUCTP(ul_new); - ul_new->start = lock->start; - ul_new->size = lock->size; - ul_new->smbpid = lock->context.smbpid; - - DLIST_ADD(ulist, ul_new); - } - } + TDB_DATA kbuf = locking_key_fsp(fsp); - if (dbuf.dptr) - free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); - - return ulist; + tdb_lockchain(posix_lock_tdb, kbuf); + if (tdb_delete(posix_lock_tdb, kbuf) == -1) + DEBUG(0,("delete_close_entries: tdb_delete fail !\n")); + tdb_unlockchain(posix_lock_tdb, kbuf); } /**************************************************************************** @@ -1123,86 +1047,86 @@ struct unlock_list *brl_getlocklist( TALLOC_CTX *ctx, SMB_DEV_T dev, SMB_INO_T i void posix_locking_close_file(files_struct *fsp) { - TALLOC_CTX *ul_ctx = NULL; - struct unlock_list *ul = NULL; - int eclass; - uint32 ecode; - struct pending_closes *pc; - - /* - * Optimization for the common case where we are the only - * opener of a file. If all fd entries are our own, we don't - * need to explicitly release all the locks via the POSIX functions, - * we can just release all the brl locks, as in the no POSIX locking case. - */ - - if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) != NULL) { - - if (pc->fd_array_size == 1 && pc->fd_array[0] == fsp->fd ) { - /* - * Just release all the brl locks, no need to release individually. - */ - - brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); - return; - } - } - - if ((ul_ctx = talloc_init()) == NULL) { - DEBUG(0,("locking_close_file: unable to init talloc context.\n")); - return; - } + struct posix_lock *entries = NULL; + size_t count, i; - /* - * We need to release all POSIX locks we have on this - * fd. Get all our existing locks from the tdb locking database. - */ + /* + * Optimization for the common case where we are the only + * opener of a file. If all fd entries are our own, we don't + * need to explicitly release all the locks via the POSIX functions, + * we can just remove all the entries in the tdb and allow the + * close to remove the real locks. + */ - ul = brl_getlocklist(ul_ctx, fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); + count = get_posix_lock_entries(fsp, &entries); - /* - * Now unlock all of them. This will remove the brl entry also - * for each lock. Note we need to make sure the global_smbpid matches - * the one associated with each lock in case the client plays games - * with smbpids (like smbtorture does :-). - */ + if (count == 0) { + DEBUG(10,("posix_locking_close_file: file %s has no outstanding locks.\n", fsp->fsp_name )); + return; + } - for(; ul; ul = ul->next) { - global_smbpid = ul->smbpid; - do_unlock(fsp,fsp->conn,ul->size,ul->start,&eclass,&ecode); - } - - talloc_destroy(ul_ctx); + for (i = 0; i < count; i++) { + if (entries[i].fd != fsp->fd ) + break; + } - } else { + if (i == count) { + /* All locks are ours. */ + DEBUG(10,("posix_locking_close_file: file %s has %u outstanding locks, but all on one fd.\n", + fsp->fsp_name, (unsigned int)count )); + free((char *)entries); + delete_posix_lock_entries(fsp); + return; + } - /* - * Just release all the brl locks, no need to release individually. - */ + /* + * Difficult case. We need to delete all our locks, whilst leaving + * all other POSIX locks in place. + */ - brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); + for (i = 0; i < count; i++) { + struct posix_lock *pl = &entries[i]; + release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size ); } + free((char *)entries); } /******************************************************************* Create the in-memory POSIX lock databases. ********************************************************************/ -void posix_lock_init(void) +BOOL posix_locking_init(void) { if (posix_lock_tdb && posix_pending_close_tdb) - return; + return True; if (!posix_lock_tdb) posix_lock_tdb = tdb_open(NULL, 0, TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0644); if (!posix_lock_tdb) { DEBUG(0,("Failed to open POSIX byte range locking database.\n")); + return False; } if (!posix_pending_close_tdb) posix_pending_close_tdb = tdb_open(NULL, 0, TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0644); if (!posix_pending_close_tdb) { DEBUG(0,("Failed to open POSIX pending close database.\n")); + return False; } + + return True; +} + +/******************************************************************* + Delete the in-memory POSIX lock databases. +********************************************************************/ + +BOOL posix_locking_end(void) +{ + if (posix_lock_tdb && tdb_close(posix_lock_tdb) != 0) + return False; + if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) + return False; + return True; } -- cgit From 74ac259e071db2a5bec716c6508e4ce232b9b1e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 29 Apr 2000 01:09:31 +0000 Subject: Removed tdb locking calls (picky Andrew...:-) (This used to be commit 6bded3b74e974b97d54acf9289f4cf812e2b1af7) --- source3/locking/posix.c | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 0fcba3432d..1117bed8da 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -100,13 +100,11 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) dbuf.dptr = NULL; - tdb_lockchain(posix_pending_close_tdb, kbuf); dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(int)); if (!dbuf.dptr) { DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n")); - tdb_unlockchain(posix_pending_close_tdb, kbuf); return False; } memcpy(dbuf.dptr + dbuf.dsize, &fsp->fd, sizeof(int)); @@ -117,7 +115,6 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) } free(dbuf.dptr); - tdb_unlockchain(posix_pending_close_tdb, kbuf); return True; } @@ -129,10 +126,8 @@ static void delete_close_entries(files_struct *fsp) { TDB_DATA kbuf = locking_key_fsp(fsp); - tdb_lockchain(posix_pending_close_tdb, kbuf); if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) DEBUG(0,("delete_close_entries: tdb_delete fail !\n")); - tdb_unlockchain(posix_pending_close_tdb, kbuf); } /**************************************************************************** @@ -149,19 +144,15 @@ static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) *entries = NULL; dbuf.dptr = NULL; - tdb_lockchain(posix_pending_close_tdb, kbuf); dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); if (!dbuf.dptr) { - tdb_unlockchain(posix_pending_close_tdb, kbuf); return 0; } *entries = (int *)dbuf.dptr; count = (size_t)(dbuf.dsize / sizeof(int)); - tdb_unlockchain(posix_pending_close_tdb, kbuf); - return count; } @@ -180,19 +171,15 @@ static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entr dbuf.dptr = NULL; - tdb_lockchain(posix_lock_tdb, kbuf); dbuf = tdb_fetch(posix_lock_tdb, kbuf); if (!dbuf.dptr) { - tdb_unlockchain(posix_lock_tdb, kbuf); return 0; } *entries = (struct posix_lock *)dbuf.dptr; count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); - tdb_unlockchain(posix_lock_tdb, kbuf); - return count; } @@ -319,7 +306,6 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s dbuf.dptr = NULL; - tdb_lockchain(posix_lock_tdb, kbuf); dbuf = tdb_fetch(posix_lock_tdb, kbuf); dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl)); @@ -337,7 +323,6 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s } free(dbuf.dptr); - tdb_unlockchain(posix_lock_tdb, kbuf); DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f:dev=%.0f inode=%.0f\n", fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, @@ -348,7 +333,6 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s fail: if (dbuf.dptr) free(dbuf.dptr); - tdb_unlockchain(posix_lock_tdb, kbuf); return False; } @@ -365,7 +349,6 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_ dbuf.dptr = NULL; - tdb_lockchain(posix_lock_tdb, kbuf); dbuf = tdb_fetch(posix_lock_tdb, kbuf); if (!dbuf.dptr) { @@ -395,7 +378,6 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_ } free(dbuf.dptr); - tdb_unlockchain(posix_lock_tdb, kbuf); return True; } } @@ -405,7 +387,6 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_ fail: if (dbuf.dptr) free(dbuf.dptr); - tdb_unlockchain(posix_lock_tdb, kbuf); return False; } @@ -730,11 +711,9 @@ static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list dbuf.dptr = NULL; - tdb_lockchain(posix_lock_tdb, kbuf); dbuf = tdb_fetch(posix_lock_tdb, kbuf); if (!dbuf.dptr) { - tdb_unlockchain(posix_lock_tdb, kbuf); return ulhead; } @@ -924,8 +903,6 @@ new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, } /* end for ( ul_curr = ulhead; ul_curr;) */ } /* end for (i=0; istart, (double)pl->size, (int)pl->lock_type, pl->fd )); } /**************************************************************************** @@ -1068,6 +1053,8 @@ void posix_locking_close_file(files_struct *fsp) for (i = 0; i < count; i++) { if (entries[i].fd != fsp->fd ) break; + + dump_entry(&entries[i]); } if (i == count) { -- cgit From 700f72453ed8dfd356a5591b9447127b5066ac4b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 11:04:28 +0000 Subject: - removed all our old wildcard matching code and replaced it with a call to ms_fnmatch(). This also removes all the Win9X semantics stuff and a bunch of other associated cruft. - moved the stat cache code into statcache.c - fixed the uint16 alignment requirements of ascii_to_unistr() and unistr_to_ascii() - trans2 SMB_FIND_FILE_BOTH_DIRECTORY_INFO returns the short name as unicode always (at least thats what NT4 does) - fixed some errors in the in-memory tdb code. Still ugly, but doesn't crash as much (This used to be commit 03e9cea004bbba72161a5323cf3b4556c94aed8e) --- source3/locking/posix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 1117bed8da..7b4075d5d8 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -999,7 +999,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u ret = False; } - talloc_destroy(ul_ctx); + talloc_destroy(ul_ctx); return ret; } @@ -1020,7 +1020,7 @@ static void delete_posix_lock_entries(files_struct *fsp) Debug function. ****************************************************************************/ -void dump_entry(struct posix_lock *pl) +static void dump_entry(struct posix_lock *pl) { DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n", (double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd )); -- cgit From 99fbf5c4bc870119a12e9b6467beb6a8b8650cc0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 May 2000 00:41:47 +0000 Subject: added TDB_INTERNAL, TDB_NOLOCK and TDB_NOMMAP flags. TDB_INTERNAL replaces the old method of passing a null filename (This used to be commit 8ec815920d46f205b9f3fff82397c731753c3a10) --- source3/locking/posix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 7b4075d5d8..d6eaad89c1 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -1088,14 +1088,14 @@ BOOL posix_locking_init(void) return True; if (!posix_lock_tdb) - posix_lock_tdb = tdb_open(NULL, 0, TDB_CLEAR_IF_FIRST, - O_RDWR|O_CREAT, 0644); + posix_lock_tdb = tdb_open(NULL, 0, TDB_INTERNAL, + O_RDWR|O_CREAT, 0644); if (!posix_lock_tdb) { DEBUG(0,("Failed to open POSIX byte range locking database.\n")); return False; } if (!posix_pending_close_tdb) - posix_pending_close_tdb = tdb_open(NULL, 0, TDB_CLEAR_IF_FIRST, + posix_pending_close_tdb = tdb_open(NULL, 0, TDB_INTERNAL, O_RDWR|O_CREAT, 0644); if (!posix_pending_close_tdb) { DEBUG(0,("Failed to open POSIX pending close database.\n")); -- cgit From 830a9e571eee5330097376e94af7dc0f2d5f2f02 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 1 May 2000 19:43:50 +0000 Subject: locking/posix.c: Fixed double-free nasty crash bug found by insure. utils/make_smbcodepage.c: utils/make_unicodemap.c: Insure 'make install' fixes. Jeremy. (This used to be commit 3b25f7368be3877e9ad27498bc9451ec88d4b07f) --- source3/locking/posix.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index d6eaad89c1..7cada20ac3 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -246,9 +246,6 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) } } - if (fd_array) - free((char *)fd_array); - /* * Delete all fd's stored in the tdb * for this dev/inode pair. -- cgit From 693ffb8466ada58ecc59fde754ba79fc6f51528d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 May 2000 02:23:41 +0000 Subject: Added sys_fork() and sys_getpid() functions to stop the overhead of doing a system call every time we want to just get our pid. Jeremy. (This used to be commit 148628b616b5c29ba6340d65fc3ddbcabba6e67a) --- source3/locking/locking.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 75198d6303..47ae917f9a 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -69,7 +69,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, return(False); ret = !brl_locktest(fsp->dev, fsp->inode, - global_smbpid, getpid(), conn->cnum, + global_smbpid, sys_getpid(), conn->cnum, offset, count, lock_type); /* @@ -107,7 +107,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { ok = brl_lock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, getpid(), conn->cnum, + global_smbpid, sys_getpid(), conn->cnum, offset, count, lock_type); @@ -127,7 +127,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, * lock entry. */ (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, getpid(), conn->cnum, + global_smbpid, sys_getpid(), conn->cnum, offset, count); } } @@ -170,7 +170,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, */ ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, getpid(), conn->cnum, offset, count); + global_smbpid, sys_getpid(), conn->cnum, offset, count); if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); @@ -193,7 +193,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, void locking_close_file(files_struct *fsp) { - pid_t pid = getpid(); + pid_t pid = sys_getpid(); if (!lp_locking(SNUM(fsp->conn))) return; @@ -337,7 +337,7 @@ void del_share_mode(files_struct *fsp) struct locking_data *data; int i, del_count=0; share_mode_entry *shares; - pid_t pid = getpid(); + pid_t pid = sys_getpid(); /* read in the existing share modes */ dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); @@ -380,7 +380,7 @@ fill a share mode entry static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type) { share_mode_entry *e = (share_mode_entry *)p; - e->pid = getpid(); + e->pid = sys_getpid(); e->share_mode = fsp->share_mode; e->op_port = port; e->op_type = op_type; @@ -453,7 +453,7 @@ static BOOL mod_share_mode(files_struct *fsp, struct locking_data *data; int i; share_mode_entry *shares; - pid_t pid = getpid(); + pid_t pid = sys_getpid(); int need_store=0; /* read in the existing share modes */ -- cgit From ba020b0612ee975df15ceaf2eabf0cc3f208dc3e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 May 2000 03:20:47 +0000 Subject: Moved uglyness needed in fcntl locking (64->32 bit mapping, NFS errors etc.) into locking/posix.c, where it is needed. fcntl_lock in lib/util.c is now very small and clean. Added (*lock) op to vfs layer. Jeremy. (This used to be commit 46092ee1410faa4e3c143d80a960a8adaa19d7fc) --- source3/locking/posix.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 7cada20ac3..094cb87bc8 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -611,6 +611,124 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, return True; } +/**************************************************************************** + Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). +****************************************************************************/ + +static uint32 map_lock_offset(uint32 high, uint32 low) +{ + unsigned int i; + uint32 mask = 0; + uint32 highcopy = high; + + /* + * Try and find out how many significant bits there are in high. + */ + + for(i = 0; highcopy; i++) + highcopy >>= 1; + + /* + * We use 31 bits not 32 here as POSIX + * lock offsets may not be negative. + */ + + mask = (~0) << (31 - i); + + if(low & mask) + return 0; /* Fail. */ + + high <<= (31 - i); + + return (high|low); +} + +/**************************************************************************** + Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and + broken NFS implementations. +****************************************************************************/ + +static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +{ + int ret; + struct connection_struct *conn = fsp->conn; + +#if defined(LARGE_SMB_OFF_T) + /* + * In the 64 bit locking case we store the original + * values in case we have to map to a 32 bit lock on + * a filesystem that doesn't support 64 bit locks. + */ + SMB_OFF_T orig_offset = offset; + SMB_OFF_T orig_count = count; +#endif /* LARGE_SMB_OFF_T */ + + DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fd,op,(double)offset,(double)count,type)); + + ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type); + + if (!ret && (errno == EFBIG)) { + if( DEBUGLVL( 0 )) { + dbgtext("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count); + dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n"); + dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n"); + } + /* 32 bit NFS file system, retry with smaller offset */ + errno = 0; + count &= 0x7fffffff; + ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type); + } + + /* A lock query - just return. */ + if (op == SMB_F_GETLK) + return ret; + + /* A lock set or unset. */ + if (!ret) { + DEBUG(3,("posix_fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n", + (double)offset,(double)count,op,type,strerror(errno))); + + /* Perhaps it doesn't support this sort of locking ? */ + if (errno == EINVAL) { +#if defined(LARGE_SMB_OFF_T) + { + /* + * Ok - if we get here then we have a 64 bit lock request + * that has returned EINVAL. Try and map to 31 bits for offset + * and length and try again. This may happen if a filesystem + * doesn't support 64 bit offsets (efs/ufs) although the underlying + * OS does. + */ + uint32 off_low = (orig_offset & 0xFFFFFFFF); + uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF); + + count = (orig_count & 0x7FFFFFFF); + offset = (SMB_OFF_T)map_lock_offset(off_high, off_low); + ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type); + if (!ret) { + if (errno == EINVAL) { + DEBUG(3,("posix_fcntl_lock: locking not supported? returning True\n")); + return(True); + } + return False; + } + DEBUG(3,("posix_fcntl_lock: 64 -> 32 bit modified lock call successful\n")); + return True; + } +#else /* LARGE_SMB_OFF_T */ + DEBUG(3,("locking not supported? returning True\n")); + return(True); +#endif /* LARGE_SMB_OFF_T */ + } + + return(False); + } + + DEBUG(8,("posix_fcntl_lock: Lock call successful\n")); + + return(True); +} + /**************************************************************************** POSIX function to see if a file region is locked. Returns True if the region is locked, False otherwise. @@ -639,7 +757,7 @@ BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_co * fd. So we don't need to use map_lock_type here. */ - return fcntl_lock(fsp->fd,SMB_F_GETLK,offset,count,posix_lock_type); + return posix_fcntl_lock(fsp,SMB_F_GETLK,offset,count,posix_lock_type); } /**************************************************************************** @@ -673,7 +791,7 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou * below. JRA. */ - ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,posix_lock_type); + ret = posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type); if (ret) add_posix_lock_entry(fsp,offset,count,posix_lock_type); @@ -992,7 +1110,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n", (double)offset, (double)count )); - if (!fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK)) + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) ret = False; } -- cgit From 32d5416b6a777a7874fec8518ec44e750560d882 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 May 2000 13:55:42 +0000 Subject: split the username in the vuser structure into a separate userdom_struct. As the name implies this also contains a domain (unused at the moment). This will be important shortly, as operation in appliance mode needs the domain to be always carried with the username. (This used to be commit ee8546342d5be90e730372b985710d764564b124) --- source3/locking/posix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 094cb87bc8..ab58607172 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -611,10 +611,10 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, return True; } +#if defined(LARGE_SMB_OFF_T) /**************************************************************************** Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). ****************************************************************************/ - static uint32 map_lock_offset(uint32 high, uint32 low) { unsigned int i; @@ -642,6 +642,7 @@ static uint32 map_lock_offset(uint32 high, uint32 low) return (high|low); } +#endif /**************************************************************************** Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and -- cgit From d009301464a70853cd10b0acbf0718d660368793 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 May 2000 21:07:25 +0000 Subject: Implemented the last (I hope:-) part of the locking puzzle, the reference counting when Windows downgrades a write lock to a read lock, then reference counts the unlocks to match the locks. With this code the POSIX unlock isn't done until the final Windows unlock. Jeremy. (This used to be commit 6eb4fb6eef367f68169d6ec1c816226b1ad9f110) --- source3/locking/posix.c | 113 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 23 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index ab58607172..ce9474fdda 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -50,6 +50,7 @@ struct posix_lock { SMB_OFF_T start; SMB_OFF_T size; int lock_type; + size_t ref_count; }; /* @@ -290,29 +291,83 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s { TDB_DATA kbuf = locking_key_fsp(fsp); TDB_DATA dbuf; - struct posix_lock pl; + struct posix_lock *entries; + size_t count, i, ref_count; /* - * Now setup the new record. + * Windows is very strange. It allows a write lock to be downgraded to + * a read lock, but reference counts the locks. This means if you get + * the following sequence : + * + * WRITE LOCK : start = 0, len = 10 + * READ LOCK : start = 0, len = 10 + * + * then another process will be able to get a read lock, but the unlock + * sequence must be done twice to remove the read lock. + * + * Under POSIX, the same sequence would not be reference counted, but + * would leave a single read lock over the 0-10 region. In order to + * re-create Windows semantics mapped to POSIX locks, we reference + * count the POSIX lock request, so that when multiple locks over a + * region is requested of the Samba POSIX lock code (this can only + * be an overlay of a read onto a write lock due to the checks already + * being done in brlock.c) then we map the lock onto POSIX, but just + * increment the reference count in the tdb. Unlocks decrement the + * reference count and only do the POSIX unlock call when the refcount + * reaches zero. */ - - pl.fd = fsp->fd; - pl.start = start; - pl.size = size; - pl.lock_type = lock_type; - + dbuf.dptr = NULL; dbuf = tdb_fetch(posix_lock_tdb, kbuf); - dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl)); - if (!dbuf.dptr) { - DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); - goto fail; + /* + * Look for an existing entry matching this region. + */ + + entries = (struct posix_lock *)dbuf.dptr; + count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); + + for (i = 0; i < count; i++) { + struct posix_lock *entry = &entries[i]; + + /* + * Just increment the ref_count on a matching entry. + * Note we don't take lock type into account here. + */ + + if ((entry->fd == fsp->fd) && + (entry->start == start) && + (entry->size == size)) { + /* Overwrite the lock type also. */ + entry->lock_type = lock_type; + ref_count = ++entry->ref_count; + break; + } } - memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl)); - dbuf.dsize += sizeof(pl); + if (i == count) { + struct posix_lock pl; + + /* + * New record needed. + */ + + pl.fd = fsp->fd; + pl.start = start; + pl.size = size; + pl.lock_type = lock_type; + ref_count = pl.ref_count = 1; + + dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl)); + if (!dbuf.dptr) { + DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); + goto fail; + } + + memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl)); + dbuf.dsize += sizeof(pl); + } if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name)); @@ -321,8 +376,8 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s free(dbuf.dptr); - DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f:dev=%.0f inode=%.0f\n", - fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, + DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f, ref_count = %u :dev=%.0f inode=%.0f\n", + fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, (unsigned int)ref_count, (double)fsp->dev, (double)fsp->inode )); return True; @@ -363,14 +418,26 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_ if (pl->fd == fsp->fd && pl->start == start && pl->size == size) { - /* Found it - delete it. */ - if (count == 1) { - tdb_delete(posix_lock_tdb, kbuf); - } else { - if (i < count-1) { - memmove(&locks[i], &locks[i+1], sizeof(*locks)*((count-1) - i)); + + pl->ref_count--; + + DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, ref_count = %u\n", + posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, + (unsigned int)pl->ref_count )); + + if (pl->ref_count == 0) { + /* Found it - delete it. */ + if (count == 1) { + tdb_delete(posix_lock_tdb, kbuf); + } else { + if (i < count-1) { + memmove(&locks[i], &locks[i+1], sizeof(*locks)*((count-1) - i)); + } + dbuf.dsize -= sizeof(*locks); + tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); } - dbuf.dsize -= sizeof(*locks); + } else { + /* Just re-store the new ref count. */ tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); } -- cgit From 20ce61ccc88dd3868176932736e03e4d85f1bfd0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 May 2000 02:27:41 +0000 Subject: Fix for stacking locks in brlock and POSIX. Windows only allows a read lock to overlay a write lock on the same fnum. When overlaying read locks onto a write lock, the number of locks is counted, and the first unlock removes the write lock and downgrades this to a read lock. Do the same when mapping to POSIX. Jeremy. (This used to be commit 74d42644e6e52808037975e909aa56c850838b76) --- source3/locking/brlock.c | 2 +- source3/locking/posix.c | 220 +++++++++++++++++++++++++++-------------------- 2 files changed, 130 insertions(+), 92 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 0ded1846b4..7e403bc954 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -86,7 +86,7 @@ static BOOL brl_conflict(struct lock_struct *lck1, return False; if (brl_same_context(&lck1->context, &lck2->context) && - lck2->lock_type == READ_LOCK) return False; + lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) return False; if (lck1->start >= (lck2->start + lck2->size) || lck2->start >= (lck1->start + lck1->size)) return False; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index ce9474fdda..df5fefdb49 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -50,7 +50,6 @@ struct posix_lock { SMB_OFF_T start; SMB_OFF_T size; int lock_type; - size_t ref_count; }; /* @@ -284,89 +283,73 @@ static const char *posix_lock_type_name(int lock_type) } /**************************************************************************** - Add an entry into the POSIX locking tdb. + Add an entry into the POSIX locking tdb. Returns the number of records that + match the given start and size, or -1 on error. ****************************************************************************/ -static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type) +static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type) { TDB_DATA kbuf = locking_key_fsp(fsp); TDB_DATA dbuf; + struct posix_lock pl; struct posix_lock *entries; - size_t count, i, ref_count; + size_t i, count; + int num_records = 0; /* - * Windows is very strange. It allows a write lock to be downgraded to - * a read lock, but reference counts the locks. This means if you get - * the following sequence : + * Windows is very strange. It allows read locks to be overlayed on + * a write lock, but leaves the write lock in force until the first + * unlock. It also reference counts the locks. This means the following sequence : * + * process1 process2 + * ------------------------------------------------------------------------ * WRITE LOCK : start = 0, len = 10 + * READ LOCK: start =0, len = 10 - FAIL * READ LOCK : start = 0, len = 10 - * - * then another process will be able to get a read lock, but the unlock - * sequence must be done twice to remove the read lock. - * - * Under POSIX, the same sequence would not be reference counted, but + * READ LOCK: start =0, len = 10 - FAIL + * UNLOCK : start = 0, len = 10 + * READ LOCK: start =0, len = 10 - OK + * + * Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but * would leave a single read lock over the 0-10 region. In order to - * re-create Windows semantics mapped to POSIX locks, we reference - * count the POSIX lock request, so that when multiple locks over a - * region is requested of the Samba POSIX lock code (this can only - * be an overlay of a read onto a write lock due to the checks already - * being done in brlock.c) then we map the lock onto POSIX, but just - * increment the reference count in the tdb. Unlocks decrement the - * reference count and only do the POSIX unlock call when the refcount - * reaches zero. + * re-create Windows semantics mapped to POSIX locks, we create multiple TDB + * entries, one for each overlayed lock request. We are guarenteed by the brlock + * semantics that if a write lock is added, then it will be first in the array. */ dbuf.dptr = NULL; dbuf = tdb_fetch(posix_lock_tdb, kbuf); - /* - * Look for an existing entry matching this region. + /* + * New record. */ - - entries = (struct posix_lock *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); - - for (i = 0; i < count; i++) { - struct posix_lock *entry = &entries[i]; - /* - * Just increment the ref_count on a matching entry. - * Note we don't take lock type into account here. - */ + pl.fd = fsp->fd; + pl.start = start; + pl.size = size; + pl.lock_type = lock_type; - if ((entry->fd == fsp->fd) && - (entry->start == start) && - (entry->size == size)) { - /* Overwrite the lock type also. */ - entry->lock_type = lock_type; - ref_count = ++entry->ref_count; - break; - } + dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl)); + if (!dbuf.dptr) { + DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); + goto fail; } - if (i == count) { - struct posix_lock pl; + memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl)); + dbuf.dsize += sizeof(pl); - /* - * New record needed. - */ + count = (size_t)(dbuf.dsize / sizeof(pl)); + entries = (struct posix_lock *)dbuf.dptr; - pl.fd = fsp->fd; - pl.start = start; - pl.size = size; - pl.lock_type = lock_type; - ref_count = pl.ref_count = 1; + for (i = 0; i < count; i++) { + struct posix_lock *entry = &entries[i]; - dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl)); - if (!dbuf.dptr) { - DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); - goto fail; - } + if (fsp->fd == entry->fd && + start == entry->start && + size == entry->size) + num_records++; - memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl)); - dbuf.dsize += sizeof(pl); } if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { @@ -376,31 +359,33 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s free(dbuf.dptr); - DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f, ref_count = %u :dev=%.0f inode=%.0f\n", - fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, (unsigned int)ref_count, + DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: num_records = %d : dev=%.0f inode=%.0f\n", + fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, num_records, (double)fsp->dev, (double)fsp->inode )); - return True; + return num_records; fail: if (dbuf.dptr) free(dbuf.dptr); - return False; + return -1; } /**************************************************************************** - Delete an entry from the POSIX locking tdb. + Delete an entry from the POSIX locking tdb. Returns a copy of the entry being + deleted and the number of remaining matching records, or -1 on error. ****************************************************************************/ -static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size) +static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl) { TDB_DATA kbuf = locking_key_fsp(fsp); TDB_DATA dbuf; struct posix_lock *locks; size_t i, count; + int num_records = 0; dbuf.dptr = NULL; - + dbuf = tdb_fetch(posix_lock_tdb, kbuf); if (!dbuf.dptr) { @@ -412,37 +397,51 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_ locks = (struct posix_lock *)dbuf.dptr; count = (size_t)(dbuf.dsize / sizeof(*locks)); + /* + * Count the number of entries that match this + * unlock request. + */ + + for (i = 0; i < count; i++) { + struct posix_lock *entry = &locks[i]; + + if (entry->fd == fsp->fd && + entry->start == start && + entry->size == size) { + num_records++; + } + } + for (i=0; ifd == fsp->fd && - pl->start == start && - pl->size == size) { + if (entry->fd == fsp->fd && + entry->start == start && + entry->size == size) { - pl->ref_count--; + num_records--; /* We're deleting one. */ - DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, ref_count = %u\n", + DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, - (unsigned int)pl->ref_count )); - - if (pl->ref_count == 0) { - /* Found it - delete it. */ - if (count == 1) { - tdb_delete(posix_lock_tdb, kbuf); - } else { - if (i < count-1) { - memmove(&locks[i], &locks[i+1], sizeof(*locks)*((count-1) - i)); - } - dbuf.dsize -= sizeof(*locks); - tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); - } + (unsigned int)num_records )); + + /* Make a copy if requested. */ + if (pl) + *pl = *entry; + + /* Found it - delete it. */ + if (count == 1) { + tdb_delete(posix_lock_tdb, kbuf); } else { - /* Just re-store the new ref count. */ + if (i < count-1) { + memmove(&locks[i], &locks[i+1], sizeof(*locks)*((count-1) - i)); + } + dbuf.dsize -= sizeof(*locks); tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); } free(dbuf.dptr); - return True; + return num_records; } } @@ -451,7 +450,7 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_ fail: if (dbuf.dptr) free(dbuf.dptr); - return False; + return -1; } /**************************************************************************** @@ -682,6 +681,7 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, /**************************************************************************** Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). ****************************************************************************/ + static uint32 map_lock_offset(uint32 high, uint32 low) { unsigned int i; @@ -839,6 +839,7 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou SMB_OFF_T count; BOOL ret = True; int posix_lock_type = map_posix_lock_type(fsp,lock_type); + int ref_count; DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); @@ -856,13 +857,25 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou * file descriptors will not be held separately by the kernel (POSIX * braindamage), but will be merged into one continuous lock * range. We cope with this case in the release_posix_lock code - * below. JRA. + * below. We need to add the posix lock entry into the tdb before + * doing the real posix lock call to deal with the locking overlay + * case described above in add_posix_lock_entry(). */ - ret = posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type); + ref_count = add_posix_lock_entry(fsp,offset,count,posix_lock_type); + + if (ref_count == 1) { + /* + * First lock entry created. Do a real POSIX lock. + */ + ret = posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type); - if (ret) - add_posix_lock_entry(fsp,offset,count,posix_lock_type); + /* + * Oops, POSIX lock failed, delete the tdb entry. + */ + if (!ret) + delete_posix_lock_entry(fsp,offset,count,NULL); + } return ret; } @@ -1105,6 +1118,8 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u TALLOC_CTX *ul_ctx = NULL; struct unlock_list *ulist = NULL; struct unlock_list *ul = NULL; + struct posix_lock deleted_lock; + int num_entries; DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", fsp->fsp_name, (double)u_offset, (double)u_count )); @@ -1122,7 +1137,30 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u * if it may have been split into multiple smaller POSIX unlock ranges. */ - delete_posix_lock_entry(fsp, offset, count); + num_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock); + + if (num_entries == -1) { + smb_panic("release_posix_lock: unable find entry to delete !\n"); + } + + /* + * If num_entries is > 0, and the lock_type we just deleted from the tdb was + * a POSIX write lock, then rather than doing an unlock we need to downgrade + * the POSIX lock to a read lock. + */ + + if (num_entries > 0 && deleted_lock.lock_type == F_WRLCK) { + return posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK); + } + + /* + * Only do the POSIX unlock when the num_entries is now zero. + */ + + if (num_entries > 0) { + DEBUG(10, ("release_posix_lock: num_entries = %d\n", num_entries )); + return True; + } if ((ul_ctx = talloc_init()) == NULL) { DEBUG(0,("release_posix_lock: unable to init talloc context.\n")); -- cgit From c6230f64313feb596def5685141a5de958b07d43 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 3 May 2000 14:29:05 +0000 Subject: - clear dead locks at startup - fixed a bug which caused lock records to not decrease in size (This used to be commit 51624a3a2f5a4ac55b4f26f572a2fc399f9c808e) --- source3/locking/brlock.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 7e403bc954..c590c51272 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -96,9 +96,46 @@ static BOOL brl_conflict(struct lock_struct *lck1, /**************************************************************************** - Open up the brlock.tdb database. +delete a record if it is for a dead process ****************************************************************************/ +static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +{ + struct lock_struct *locks; + struct lock_key *key; + int count, i; + + tdb_lockchain(tdb, kbuf); + + locks = (struct lock_struct *)dbuf.dptr; + key = (struct lock_key *)kbuf.dptr; + + count = dbuf.dsize / sizeof(*locks); + for (i=0; icontext.pid)) continue; + + if (count > 1 && i < count-1) { + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((count-1) - i)); + } + count--; + i--; + } + if (count == 0) { + tdb_delete(tdb, kbuf); + } else if (count < (dbuf.dsize / sizeof(*locks))) { + tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); + } + + tdb_unlockchain(tdb, kbuf); + return 0; +} + +/**************************************************************************** + Open up the brlock.tdb database. +****************************************************************************/ void brl_init(int read_only) { if (tdb) return; @@ -106,6 +143,12 @@ void brl_init(int read_only) read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); if (!tdb) { DEBUG(0,("Failed to open byte range locking database\n")); + return; + } + + /* delete any dead locks */ + if (!read_only) { + tdb_traverse(tdb, delete_fn, NULL); } } @@ -313,7 +356,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) { struct lock_key key; TDB_DATA kbuf, dbuf; - int count, i; + int count, i, dcount=0; struct lock_struct *locks; key.device = dev; @@ -344,12 +387,14 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) } count--; i--; + dcount++; } } if (count == 0) { tdb_delete(tdb, kbuf); } else if (count < (dbuf.dsize / sizeof(*locks))) { + dbuf.dsize -= dcount * sizeof(*locks); tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); } -- cgit From f6bcf3d3243de4209b67024ca07252f17d4add24 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 May 2000 17:50:42 +0000 Subject: Added range info to the panic message to track down the bug with locktest. Jeremy. (This used to be commit 91f038356b7efa04cf4bfa5e6afd8b144b6b4ad5) --- source3/locking/posix.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index df5fefdb49..c712e8c26f 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -1093,8 +1093,12 @@ new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, * This logic case should never happen. Ensure this is the * case by forcing an abort.... Remove in production. */ + pstring msg; - smb_panic("logic flaw in cases...\n"); + slprintf(msg, sizeof(msg)-1, "logic flaw in cases: ul_curr: start = %.0f, size = %.0f : \ +lock: start = %.0f, size = %.0f\n", (double)ul_curr->start, (double)ul_curr->size, (double)lock->start, (double)lock->size ); + + smb_panic(msg); } } /* end for ( ul_curr = ulhead; ul_curr;) */ } /* end for (i=0; i Date: Wed, 3 May 2000 18:57:21 +0000 Subject: Fixed silly bug where I wasn't checking for matching fd's in closing a file. This caused smbd crashes on SIGKILL. Jeremy. (This used to be commit d4dcefd12d14df112f083c312acbea0196bc5c23) --- source3/locking/posix.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index c712e8c26f..5dd7f18470 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -185,6 +185,8 @@ static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entr /**************************************************************************** Deal with pending closes needed by POSIX locking support. + Note that posix_locking_close_file() is expected to have been called + to delete all locks on this fsp before this function is called. ****************************************************************************/ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) @@ -194,6 +196,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) size_t count, i; struct posix_lock *entries = NULL; int *fd_array = NULL; + BOOL locks_on_other_fds = False; if (!lp_posix_locking(SNUM(conn))) { /* @@ -209,8 +212,21 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) */ count = get_posix_lock_entries(fsp, &entries); - - if (count) { + + /* + * Check if there are any outstanding locks belonging to + * other fd's. This should never be the case if posix_locking_close_file() + * has been called first, but it never hurts to be *sure*. + */ + + for (i = 0; i < count; i++) { + if (entries[i].fd != fsp->fd) { + locks_on_other_fds = True; + break; + } + } + + if (locks_on_other_fds) { /* * There are outstanding locks on this dev/inode pair on other fds. @@ -421,14 +437,14 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T num_records--; /* We're deleting one. */ - DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", - posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, - (unsigned int)num_records )); - /* Make a copy if requested. */ if (pl) *pl = *entry; + DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", + posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, + (unsigned int)num_records )); + /* Found it - delete it. */ if (count == 1) { tdb_delete(posix_lock_tdb, kbuf); @@ -1298,7 +1314,8 @@ void posix_locking_close_file(files_struct *fsp) for (i = 0; i < count; i++) { struct posix_lock *pl = &entries[i]; - release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size ); + if (pl->fd == fsp->fd) + release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size ); } free((char *)entries); } -- cgit From 756798d00050eea4468c2d8bb0c3b98390c0e8eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 May 2000 19:37:47 +0000 Subject: Fixed the bug locktest.c found, it was an off-by-one error in the non-overlap case. Jeremy. (This used to be commit 65150c408a5254215de89c8c774c33c4d011c2c0) --- source3/locking/posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 5dd7f18470..752311e76f 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -957,7 +957,7 @@ static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list (double)lock->start, (double)lock->size )); if ( (ul_curr->start >= (lock->start + lock->size)) || - (lock->start > (ul_curr->start + ul_curr->size))) { + (lock->start >= (ul_curr->start + ul_curr->size))) { /* No overlap with this lock - leave this range alone. */ /********************************************* -- cgit From 8c19fa8f7abaf97a994e733394ad3631a31dca40 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 May 2000 20:33:25 +0000 Subject: Fix based on Elrond's code to reduce the store size on removing dead records. Jeremy. (This used to be commit 09e92a61a966d09f543ba541ddb3240cc4718579) --- source3/locking/brlock.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index c590c51272..51f3175dbf 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -126,6 +126,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat if (count == 0) { tdb_delete(tdb, kbuf); } else if (count < (dbuf.dsize / sizeof(*locks))) { + dbuf.dsize = count * sizeof(*locks); tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); } -- cgit From 05a28f1dfdb57561812f1d490c2c6453a9d59136 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 May 2000 00:29:50 +0000 Subject: Fix for debug statement crash. Jeremy. (This used to be commit 57bf92d90147b207664152d44ce4bfb5235dc7d8) --- source3/locking/posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 752311e76f..45d139b734 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -442,7 +442,7 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T *pl = *entry; DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", - posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, + posix_lock_type_name(entry->lock_type), (double)entry->start, (double)entry->size, (unsigned int)num_records )); /* Found it - delete it. */ -- cgit From fffeaf527d82b3535938cb89da7f4aa5ab8edc48 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 May 2000 19:01:14 +0000 Subject: Updated to fix overlapping problem. Jeremy. (This used to be commit 9bdfe0f5023988962f8a8b4d847de7a0ee27f85c) --- source3/locking/posix.c | 210 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 142 insertions(+), 68 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 45d139b734..f7468aac4b 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -298,19 +298,67 @@ static const char *posix_lock_type_name(int lock_type) return (lock_type == F_RDLCK) ? "READ" : "WRITE"; } +/**************************************************************************** + Delete a POSIX lock entry by index number. Used if the tdb add succeeds, but + then the POSIX fcntl lock fails. +****************************************************************************/ + +static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry) +{ + TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA dbuf; + struct posix_lock *locks; + size_t count; + + dbuf.dptr = NULL; + + dbuf = tdb_fetch(posix_lock_tdb, kbuf); + + if (!dbuf.dptr) { + DEBUG(10,("delete_posix_lock_entry_by_index: tdb_fetch failed !\n")); + goto fail; + } + + count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); + locks = (struct posix_lock *)dbuf.dptr; + + if (count == 1) { + tdb_delete(posix_lock_tdb, kbuf); + } else { + if (entry < count-1) { + memmove(&locks[entry], &locks[entry+1], sizeof(*locks)*((count-1) - entry)); + } + dbuf.dsize -= sizeof(*locks); + tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); + } + + free(dbuf.dptr); + + return True; + + fail: + if (dbuf.dptr) + free(dbuf.dptr); + return False; +} + /**************************************************************************** Add an entry into the POSIX locking tdb. Returns the number of records that - match the given start and size, or -1 on error. + completely overlap this request, or -1 on error. entry_num gets set to the + index number of the added lock (used in case we need to delete *exactly* + this entry). ****************************************************************************/ -static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type) +static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *entry_num) { TDB_DATA kbuf = locking_key_fsp(fsp); TDB_DATA dbuf; struct posix_lock pl; struct posix_lock *entries; size_t i, count; - int num_records = 0; + int num_overlapping_records = 0; + + *entry_num = 0; /* * Windows is very strange. It allows read locks to be overlayed on @@ -321,7 +369,7 @@ static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T si * ------------------------------------------------------------------------ * WRITE LOCK : start = 0, len = 10 * READ LOCK: start =0, len = 10 - FAIL - * READ LOCK : start = 0, len = 10 + * READ LOCK : start = 5, len = 2 * READ LOCK: start =0, len = 10 - FAIL * UNLOCK : start = 0, len = 10 * READ LOCK: start =0, len = 10 - OK @@ -337,8 +385,26 @@ static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T si dbuf = tdb_fetch(posix_lock_tdb, kbuf); + count = (size_t)(dbuf.dsize / sizeof(pl)); + entries = (struct posix_lock *)dbuf.dptr; + + /* + * Ensure we look for overlapping entries *before* + * we add this entry. Count the number of entries + * that completely overlap this request. + */ + + for (i = 0; i < count; i++) { + struct posix_lock *entry = &entries[i]; + + if (fsp->fd == entry->fd && + start >= entry->start && + start + size <= entry->start + entry->size) + num_overlapping_records++; + } + /* - * New record. + * Add new record. */ pl.fd = fsp->fd; @@ -355,18 +421,7 @@ static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T si memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl)); dbuf.dsize += sizeof(pl); - count = (size_t)(dbuf.dsize / sizeof(pl)); - entries = (struct posix_lock *)dbuf.dptr; - - for (i = 0; i < count; i++) { - struct posix_lock *entry = &entries[i]; - - if (fsp->fd == entry->fd && - start == entry->start && - size == entry->size) - num_records++; - - } + *entry_num = count; if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name)); @@ -376,20 +431,22 @@ static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T si free(dbuf.dptr); DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: num_records = %d : dev=%.0f inode=%.0f\n", - fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, num_records, + fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, num_overlapping_records, (double)fsp->dev, (double)fsp->inode )); - return num_records; + return num_overlapping_records; fail: if (dbuf.dptr) free(dbuf.dptr); + *entry_num = 0; return -1; } /**************************************************************************** Delete an entry from the POSIX locking tdb. Returns a copy of the entry being - deleted and the number of remaining matching records, or -1 on error. + deleted and the number of records that are completely overlapped by this one, + or -1 on error. ****************************************************************************/ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl) @@ -398,7 +455,8 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T TDB_DATA dbuf; struct posix_lock *locks; size_t i, count; - int num_records = 0; + BOOL found = False; + int num_overlapping_records = 0; dbuf.dptr = NULL; @@ -414,20 +472,10 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T count = (size_t)(dbuf.dsize / sizeof(*locks)); /* - * Count the number of entries that match this - * unlock request. + * Search for and delete the first record that matches the + * unlock criteria. */ - for (i = 0; i < count; i++) { - struct posix_lock *entry = &locks[i]; - - if (entry->fd == fsp->fd && - entry->start == start && - entry->size == size) { - num_records++; - } - } - for (i=0; istart == start && entry->size == size) { - num_records--; /* We're deleting one. */ - /* Make a copy if requested. */ if (pl) *pl = *entry; - DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", - posix_lock_type_name(entry->lock_type), (double)entry->start, (double)entry->size, - (unsigned int)num_records )); - /* Found it - delete it. */ if (count == 1) { tdb_delete(posix_lock_tdb, kbuf); @@ -455,13 +497,39 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T dbuf.dsize -= sizeof(*locks); tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); } - - free(dbuf.dptr); - return num_records; + count--; + found = True; + break; } } - /* We didn't find it. */ + if (!found) + goto fail; + + /* + * Count the number of entries that are + * overlapped completely by this unlock request. + * (Note that this is the reverse of the test in + * add_posix_lock). + */ + + for (i = 0; i < count; i++) { + struct posix_lock *entry = &locks[i]; + + if (fsp->fd == entry->fd && + entry->start >= start && + entry->start + entry->size <= start + size) + num_overlapping_records++; + } + + DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", + posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, + (unsigned int)num_overlapping_records )); + + if (dbuf.dptr) + free(dbuf.dptr); + + return num_overlapping_records; fail: if (dbuf.dptr) @@ -854,8 +922,9 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou SMB_OFF_T offset; SMB_OFF_T count; BOOL ret = True; + size_t entry_num = 0; int posix_lock_type = map_posix_lock_type(fsp,lock_type); - int ref_count; + int num_overlapping_records; DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); @@ -878,19 +947,30 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou * case described above in add_posix_lock_entry(). */ - ref_count = add_posix_lock_entry(fsp,offset,count,posix_lock_type); + num_overlapping_records = add_posix_lock_entry(fsp,offset,count,posix_lock_type,&entry_num); + + if (num_overlapping_records == -1) { + DEBUG(0,("set_posix_lock: Unable to create posix lock entry !\n")); + return False; + } - if (ref_count == 1) { + /* + * num_overlapping_records is the count of lock records that + * completely contain this request on the same fsp. Only bother + * with the real lock request if there are none, otherwise ignore. + */ + + if (num_overlapping_records == 0) { /* - * First lock entry created. Do a real POSIX lock. + * First lock entry for this range created. Do a real POSIX lock. */ ret = posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type); /* - * Oops, POSIX lock failed, delete the tdb entry. + * Oops, POSIX lock failed, delete the tdb entry we just added. */ if (!ret) - delete_posix_lock_entry(fsp,offset,count,NULL); + delete_posix_lock_entry_by_index(fsp,entry_num); } return ret; @@ -953,8 +1033,8 @@ static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list for (ul_curr = ulhead; ul_curr;) { - DEBUG(10,("posix_unlock_list: lock: start=%.0f,size=%.0f:", - (double)lock->start, (double)lock->size )); + DEBUG(10,("posix_unlock_list: lock: fd=%d: start=%.0f,size=%.0f:type=%s", lock->fd, + (double)lock->start, (double)lock->size, posix_lock_type_name(lock->lock_type) )); if ( (ul_curr->start >= (lock->start + lock->size)) || (lock->start >= (ul_curr->start + ul_curr->size))) { @@ -1139,7 +1219,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u struct unlock_list *ulist = NULL; struct unlock_list *ul = NULL; struct posix_lock deleted_lock; - int num_entries; + int num_overlapped_entries; DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", fsp->fsp_name, (double)u_offset, (double)u_count )); @@ -1154,32 +1234,26 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u /* * We treat this as one unlock request for POSIX accounting purposes even - * if it may have been split into multiple smaller POSIX unlock ranges. + * if it may later be split into multiple smaller POSIX unlock ranges. */ - num_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock); + num_overlapped_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock); - if (num_entries == -1) { + if (num_overlapped_entries == -1) { smb_panic("release_posix_lock: unable find entry to delete !\n"); } /* - * If num_entries is > 0, and the lock_type we just deleted from the tdb was - * a POSIX write lock, then rather than doing an unlock we need to downgrade + * If num_overlapped_entries is > 0, and the lock_type we just deleted from the tdb was + * a POSIX write lock, then before doing the unlock we need to downgrade * the POSIX lock to a read lock. */ - if (num_entries > 0 && deleted_lock.lock_type == F_WRLCK) { - return posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK); - } - - /* - * Only do the POSIX unlock when the num_entries is now zero. - */ - - if (num_entries > 0) { - DEBUG(10, ("release_posix_lock: num_entries = %d\n", num_entries )); - return True; + if (num_overlapped_entries > 0 && deleted_lock.lock_type == F_WRLCK) { + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) { + DEBUG(0,("release_posix_lock: downgrade of lock failed !\n")); + return False; + } } if ((ul_ctx = talloc_init()) == NULL) { -- cgit From 091c9706829ad0a076ee7ae9ffc77b65fd502508 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 May 2000 02:17:39 +0000 Subject: Two fixes. Added missong logic & case in lock split code. Fixed range split into two, as DLIST_ADD has the wrong semantics... Jeremy. (This used to be commit 82681edda14dcc3d58bb303cfac5452072de67df) --- source3/locking/posix.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index f7468aac4b..0ab46f9ca4 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -1113,7 +1113,8 @@ BECOMES.... ul_curr = ul_curr->next; } else if ( (ul_curr->start < lock->start) && - (ul_curr->start + ul_curr->size > lock->start) ) { + (ul_curr->start + ul_curr->size > lock->start) && + (ul_curr->start + ul_curr->size <= lock->start + lock->size) ) { /* * This unlock overlaps the existing lock range at the low end. @@ -1171,9 +1172,6 @@ BECOMES..... ul_new->start = lock->start + lock->size; ul_new->size = ul_curr->start + ul_curr->size - ul_new->start; - /* Add into the dlink list after the ul_curr point - NOT at ulhead. */ - DLIST_ADD(ul_curr, ul_new); - /* Truncate the ul_curr. */ ul_curr->size = lock->start - ul_curr->start; @@ -1181,6 +1179,16 @@ BECOMES..... new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, (double)ul_new->start, (double)ul_new->size )); + /* + * Add into the dlink list after the ul_curr point - NOT at ulhead. + * Note we can't use DLINK_ADD here as this inserts at the head of the given list. + */ + + ul_new->prev = ul_curr; + ul_new->next = ul_curr->next; + ul_curr->next = ul_new; + + /* And move after the link we added. */ ul_curr = ul_new->next; } else { -- cgit From 6d9ce383061782b888f4b3403099a3c2c34b1a4c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 May 2000 20:50:22 +0000 Subject: Fix for uninitialized memory read in brlock code. brl_locktest now needs to correctly set the fnum, as the brl_conflict code looks at it. Jeremy. (This used to be commit df87259a356b91989604a10b3691480dcd16cf3f) --- source3/locking/brlock.c | 3 ++- source3/locking/locking.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 51f3175dbf..78a9174141 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -300,7 +300,7 @@ smbpid = %u, pid = %u, tid = %u\n", Test if we could add a lock if we wanted to. ****************************************************************************/ -BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, +BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, enum brl_type lock_type) @@ -325,6 +325,7 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, lock.context.tid = tid; lock.start = start; lock.size = size; + lock.fnum = fnum; lock.lock_type = lock_type; if (dbuf.dptr) { diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 47ae917f9a..07411e8919 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -68,7 +68,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - ret = !brl_locktest(fsp->dev, fsp->inode, + ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, global_smbpid, sys_getpid(), conn->cnum, offset, count, lock_type); -- cgit From e522de480891b9d72ba4cd2d4c8decb6909809a9 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 10 May 2000 00:05:27 +0000 Subject: Using a structure for a tdb key can lead to insideous, hard to find bugs. On 64 bit IRIX, structure packing means that a struct { SMB_DEV_T dev /* 4 bytes */ SMB_INO_T ino /* 8 bytes */ } has 4 bytes of padding between the two members. If you don't null the memory before using it as a tdb key, you randomly can't find keys depending on what is in the padding. This caused me immense pain and was hard to track down.... :-) Jeremy. (This used to be commit f2a5ba3f0939f59097f0ef6a25f1cf9b5574f157) --- source3/locking/brlock.c | 41 +++++++++++++++++++++-------------------- source3/locking/locking.c | 2 ++ source3/locking/posix.c | 2 ++ 3 files changed, 25 insertions(+), 20 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 78a9174141..933fc142e9 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -63,6 +63,23 @@ struct lock_key { static TDB_CONTEXT *tdb; +/**************************************************************************** + Create a locking key - ensuring zero filled for pad purposes. +****************************************************************************/ + +static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) +{ + static struct lock_key key; + TDB_DATA kbuf; + + memset(&key, '\0', sizeof(key)); + key.device = dev; + key.inode = inode; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + return kbuf; +} + /**************************************************************************** See if two locking contexts are equal. ****************************************************************************/ @@ -163,15 +180,11 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, br_off start, br_off size, enum brl_type lock_type) { - struct lock_key key; TDB_DATA kbuf, dbuf; int count, i; struct lock_struct lock, *locks; - key.device = dev; - key.inode = ino; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); + kbuf = locking_key(dev,ino); dbuf.dptr = NULL; @@ -222,16 +235,12 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size) { - struct lock_key key; TDB_DATA kbuf, dbuf; int count, i; struct lock_struct *locks; struct lock_context context; - key.device = dev; - key.inode = ino; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); + kbuf = locking_key(dev,ino); dbuf.dptr = NULL; @@ -305,15 +314,11 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, br_off start, br_off size, enum brl_type lock_type) { - struct lock_key key; TDB_DATA kbuf, dbuf; int count, i; struct lock_struct lock, *locks; - key.device = dev; - key.inode = ino; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); + kbuf = locking_key(dev,ino); dbuf.dptr = NULL; @@ -356,15 +361,11 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) { - struct lock_key key; TDB_DATA kbuf, dbuf; int count, i, dcount=0; struct lock_struct *locks; - key.device = dev; - key.inode = ino; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); + kbuf = locking_key(dev,ino); dbuf.dptr = NULL; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 07411e8919..302b5b56c9 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -255,6 +255,8 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) { static struct locking_key key; TDB_DATA kbuf; + + memset(&key, '\0', sizeof(key)); key.dev = dev; key.inode = inode; kbuf.dptr = (char *)&key; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 0ab46f9ca4..d1edb1ef57 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -73,6 +73,8 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) { static struct posix_lock_key key; TDB_DATA kbuf; + + memset(&key, '\0', sizeof(key)); key.device = dev; key.inode = inode; kbuf.dptr = (char *)&key; -- cgit From 9c4079d8c3b158369585d33f7b19fc7bd585401e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 25 May 2000 20:05:50 +0000 Subject: Fixed misunderstanding found during CIFS conference. Overlapping lock ranges (not just included lock ranges) should be handled correctly. UNIT test still needed. Jeremy. (This used to be commit 07872298e3ee8b4b50b69cb4e49b88635792128e) --- source3/locking/posix.c | 618 ++++++++++++++++++++++-------------------------- 1 file changed, 278 insertions(+), 340 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index d1edb1ef57..6ab4bef4cc 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -345,65 +345,22 @@ static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry) } /**************************************************************************** - Add an entry into the POSIX locking tdb. Returns the number of records that - completely overlap this request, or -1 on error. entry_num gets set to the - index number of the added lock (used in case we need to delete *exactly* - this entry). + Add an entry into the POSIX locking tdb. We return the index number of the + added lock (used in case we need to delete *exactly* this entry). Returns + False on fail, True on success. ****************************************************************************/ -static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *entry_num) +static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *pentry_num) { TDB_DATA kbuf = locking_key_fsp(fsp); TDB_DATA dbuf; struct posix_lock pl; - struct posix_lock *entries; - size_t i, count; - int num_overlapping_records = 0; - *entry_num = 0; - - /* - * Windows is very strange. It allows read locks to be overlayed on - * a write lock, but leaves the write lock in force until the first - * unlock. It also reference counts the locks. This means the following sequence : - * - * process1 process2 - * ------------------------------------------------------------------------ - * WRITE LOCK : start = 0, len = 10 - * READ LOCK: start =0, len = 10 - FAIL - * READ LOCK : start = 5, len = 2 - * READ LOCK: start =0, len = 10 - FAIL - * UNLOCK : start = 0, len = 10 - * READ LOCK: start =0, len = 10 - OK - * - * Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but - * would leave a single read lock over the 0-10 region. In order to - * re-create Windows semantics mapped to POSIX locks, we create multiple TDB - * entries, one for each overlayed lock request. We are guarenteed by the brlock - * semantics that if a write lock is added, then it will be first in the array. - */ - dbuf.dptr = NULL; dbuf = tdb_fetch(posix_lock_tdb, kbuf); - count = (size_t)(dbuf.dsize / sizeof(pl)); - entries = (struct posix_lock *)dbuf.dptr; - - /* - * Ensure we look for overlapping entries *before* - * we add this entry. Count the number of entries - * that completely overlap this request. - */ - - for (i = 0; i < count; i++) { - struct posix_lock *entry = &entries[i]; - - if (fsp->fd == entry->fd && - start >= entry->start && - start + size <= entry->start + entry->size) - num_overlapping_records++; - } + *pentry_num = (size_t)(dbuf.dsize / sizeof(pl)); /* * Add new record. @@ -423,8 +380,6 @@ static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T si memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl)); dbuf.dsize += sizeof(pl); - *entry_num = count; - if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name)); goto fail; @@ -432,23 +387,36 @@ static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T si free(dbuf.dptr); - DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: num_records = %d : dev=%.0f inode=%.0f\n", - fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, num_overlapping_records, + DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n", + fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, (double)fsp->dev, (double)fsp->inode )); - return num_overlapping_records; + return True; fail: if (dbuf.dptr) free(dbuf.dptr); - *entry_num = 0; - return -1; + return False; +} + +/**************************************************************************** + Calculate if locks have any overlap at all. +****************************************************************************/ + +static BOOL does_lock_overlap(SMB_OFF_T start1, SMB_OFF_T size1, SMB_OFF_T start2, SMB_OFF_T size2) +{ + if (start1 >= start2 && start1 <= start2 + size2) + return True; + + if (start1 < start2 && start1 + size1 > start2); + return True; + + return False; } /**************************************************************************** Delete an entry from the POSIX locking tdb. Returns a copy of the entry being - deleted and the number of records that are completely overlapped by this one, - or -1 on error. + deleted and the number of records that are overlapped by this one, or -1 on error. ****************************************************************************/ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl) @@ -510,23 +478,20 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T /* * Count the number of entries that are - * overlapped completely by this unlock request. - * (Note that this is the reverse of the test in - * add_posix_lock). + * overlapped by this unlock request. */ for (i = 0; i < count; i++) { struct posix_lock *entry = &locks[i]; if (fsp->fd == entry->fd && - entry->start >= start && - entry->start + entry->size <= start + size) + does_lock_overlap( start, size, entry->start, entry->size)) num_overlapping_records++; } - DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", - posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, - (unsigned int)num_overlapping_records )); + DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", + posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, + (unsigned int)num_overlapping_records )); if (dbuf.dptr) free(dbuf.dptr); @@ -579,177 +544,81 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) { - SMB_OFF_T offset; - SMB_OFF_T count; - -#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) - - SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); - SMB_OFF_T mask = (mask2<<1); - SMB_OFF_T neg_mask = ~mask; - - /* - * In this case SMB_OFF_T is 64 bits, - * and the underlying system can handle 64 bit signed locks. - * Cast to signed type. - */ - - offset = (SMB_OFF_T)u_offset; - count = (SMB_OFF_T)u_count; + SMB_OFF_T offset = (SMB_OFF_T)u_offset; + SMB_OFF_T count = (SMB_OFF_T)u_count; /* - * Deal with a very common case of count of all ones. - * (lock entire file). + * For the type of system we are, attempt to + * find the maximum positive lock offset as an SMB_OFF_T. */ - if(count == (SMB_OFF_T)-1) - count &= ~mask; +#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) /* - * POSIX lock ranges cannot be negative. - * Fail if any combination becomes negative. + * In this case SMB_OFF_T is 64 bits, + * and the underlying system can handle 64 bit signed locks. */ - if(offset < 0 || count < 0 || (offset + count < 0)) { - DEBUG(10,("posix_lock_in_range: negative range: offset = %.0f, count = %.0f. Ignoring lock.\n", - (double)offset, (double)count )); - return False; - } - - /* - * In this case SMB_OFF_T is 64 bits, the offset and count - * fit within the positive range, and the underlying - * system can handle 64 bit locks. Just return as the - * cast values are ok. - */ + SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); + SMB_OFF_T mask = (mask2<<1); + SMB_OFF_T max_positive_lock_offset = ~mask; #else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ /* * In this case either SMB_OFF_T is 32 bits, * or the underlying system cannot handle 64 bit signed locks. - * Either way we have to try and mangle to fit within 31 bits. - * This is difficult. + * All offsets & counts must be 2^31 or less. */ -#if defined(HAVE_BROKEN_FCNTL64_LOCKS) + SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF; - /* - * SMB_OFF_T is 64 bits, but we need to use 31 bits due to - * broken large locking. - */ +#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ /* - * Deal with a very common case of count of all ones. - * (lock entire file). + * If the given offset was > max_positive_lock_offset then we cannot map this at all + * ignore this lock. */ - if(u_count == (SMB_BIG_UINT)-1) - count = 0x7FFFFFFF; - - if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) { - DEBUG(10,("posix_lock_in_range: top 32 bits not zero. offset = %.0f, count = %.0f. Ignoring lock.\n", - (double)u_offset, (double)u_count )); - /* Top 32 bits of offset or count were not zero. */ + if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) { + DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n", + (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) )); return False; } - /* Cast from 64 bits unsigned to 64 bits signed. */ - offset = (SMB_OFF_T)u_offset; - count = (SMB_OFF_T)u_count; - - /* - * Check if we are within the 2^31 range. - */ - - { - int32 low_offset = (int32)offset; - int32 low_count = (int32)count; - - if(low_offset < 0 || low_count < 0 || (low_offset + low_count < 0)) { - DEBUG(10,("posix_lock_in_range: not within 2^31 range. low_offset = %d, low_count = %d. Ignoring lock.\n", - low_offset, low_count )); - return False; - } - } - - /* - * Ok - we can map from a 64 bit number to a 31 bit lock. - */ - -#else /* HAVE_BROKEN_FCNTL64_LOCKS */ - /* - * SMB_OFF_T is 32 bits. + * We must truncate the offset and count to less than max_positive_lock_offset. */ -#if defined(HAVE_LONGLONG) + offset &= max_positive_lock_offset; + count &= max_positive_lock_offset; - /* - * SMB_BIG_UINT is 64 bits, we can do a 32 bit shift. - */ /* * Deal with a very common case of count of all ones. * (lock entire file). */ - if(u_count == (SMB_BIG_UINT)-1) - count = 0x7FFFFFFF; - - if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) { - DEBUG(10,("posix_lock_in_range: top 32 bits not zero. u_offset = %.0f, u_count = %.0f. Ignoring lock.\n", - (double)u_offset, (double)u_count )); - return False; - } - - /* Cast from 64 bits unsigned to 32 bits signed. */ - offset = (SMB_OFF_T)u_offset; - count = (SMB_OFF_T)u_count; - - /* - * Check if we are within the 2^31 range. - */ - - if(offset < 0 || count < 0 || (offset + count < 0)) { - DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n", - (int)offset, (int)count )); - return False; - } - -#else /* HAVE_LONGLONG */ - - /* - * SMB_BIG_UINT and SMB_OFF_T are both 32 bits, - * just cast. - */ + if(count == (SMB_OFF_T)-1) + count = max_positive_lock_offset; /* - * Deal with a very common case of count of all ones. - * (lock entire file). + * Truncate count to end at max lock offset. */ - if(u_count == (SMB_BIG_UINT)-1) - count = 0x7FFFFFFF; - - /* Cast from 32 bits unsigned to 32 bits signed. */ - offset = (SMB_OFF_T)u_offset; - count = (SMB_OFF_T)u_count; + if (offset + count < 0 || offset + count > max_positive_lock_offset) + count = max_positive_lock_offset - offset; /* - * Check if we are within the 2^31 range. + * If we ate all the count, ignore this lock. */ - if(offset < 0 || count < 0 || (offset + count < 0)) { - DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n", - (int)offset, (int)count )); + if (count == 0) { + DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n", + (double)u_offset, (double)u_count )); return False; } -#endif /* HAVE_LONGLONG */ -#endif /* LARGE_SMB_OFF_T */ -#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ - /* * The mapping was successful. */ @@ -914,89 +783,25 @@ BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_co return posix_fcntl_lock(fsp,SMB_F_GETLK,offset,count,posix_lock_type); } -/**************************************************************************** - POSIX function to acquire a lock. Returns True if the - lock could be granted, False if not. -****************************************************************************/ - -BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) -{ - SMB_OFF_T offset; - SMB_OFF_T count; - BOOL ret = True; - size_t entry_num = 0; - int posix_lock_type = map_posix_lock_type(fsp,lock_type); - int num_overlapping_records; - - DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); - - /* - * If the requested lock won't fit in the POSIX range, we will - * pretend it was successful. - */ - - if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) - return True; - - /* - * Note that setting multiple overlapping locks on different - * file descriptors will not be held separately by the kernel (POSIX - * braindamage), but will be merged into one continuous lock - * range. We cope with this case in the release_posix_lock code - * below. We need to add the posix lock entry into the tdb before - * doing the real posix lock call to deal with the locking overlay - * case described above in add_posix_lock_entry(). - */ - - num_overlapping_records = add_posix_lock_entry(fsp,offset,count,posix_lock_type,&entry_num); - - if (num_overlapping_records == -1) { - DEBUG(0,("set_posix_lock: Unable to create posix lock entry !\n")); - return False; - } - - /* - * num_overlapping_records is the count of lock records that - * completely contain this request on the same fsp. Only bother - * with the real lock request if there are none, otherwise ignore. - */ - - if (num_overlapping_records == 0) { - /* - * First lock entry for this range created. Do a real POSIX lock. - */ - ret = posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type); - - /* - * Oops, POSIX lock failed, delete the tdb entry we just added. - */ - if (!ret) - delete_posix_lock_entry_by_index(fsp,entry_num); - } - - return ret; -} - /* * Structure used when splitting a lock range * into a POSIX lock range. Doubly linked list. */ -struct unlock_list { - struct unlock_list *next; - struct unlock_list *prev; +struct lock_list { + struct lock_list *next; + struct lock_list *prev; SMB_OFF_T start; SMB_OFF_T size; }; /**************************************************************************** Create a list of lock ranges that don't overlap a given range. Used in calculating - POSIX lock unlocks. This is a difficult function that requires ASCII art to + POSIX locks and unlocks. This is a difficult function that requires ASCII art to understand it :-). ****************************************************************************/ -static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list *ulhead, files_struct *fsp) +static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhead, files_struct *fsp) { TDB_DATA kbuf = locking_key_fsp(fsp); TDB_DATA dbuf; @@ -1007,9 +812,8 @@ static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list dbuf = tdb_fetch(posix_lock_tdb, kbuf); - if (!dbuf.dptr) { - return ulhead; - } + if (!dbuf.dptr) + return lhead; locks = (struct posix_lock *)dbuf.dptr; num_locks = (size_t)(dbuf.dsize / sizeof(*locks)); @@ -1019,48 +823,48 @@ static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list * Quit if the list is deleted. */ - DEBUG(10,("posix_unlock_list: curr: start=%.0f,size=%.0f\n", - (double)ulhead->start, (double)ulhead->size )); + DEBUG(10,("posix_lock_list: curr: start=%.0f,size=%.0f\n", + (double)lhead->start, (double)lhead->size )); - for (i=0; ifd, + DEBUG(10,("posix_lock_list: lock: fd=%d: start=%.0f,size=%.0f:type=%s", lock->fd, (double)lock->start, (double)lock->size, posix_lock_type_name(lock->lock_type) )); - if ( (ul_curr->start >= (lock->start + lock->size)) || - (lock->start >= (ul_curr->start + ul_curr->size))) { + if ( (l_curr->start >= (lock->start + lock->size)) || + (lock->start >= (l_curr->start + l_curr->size))) { /* No overlap with this lock - leave this range alone. */ /********************************************* +---------+ - | ul_curr | + | l_curr | +---------+ +-------+ | lock | +-------+ OR.... +---------+ - | ul_curr | + | l_curr | +---------+ **********************************************/ DEBUG(10,("no overlap case.\n" )); - ul_curr = ul_curr->next; + l_curr = l_curr->next; - } else if ( (ul_curr->start >= lock->start) && - (ul_curr->start + ul_curr->size <= lock->start + lock->size) ) { + } else if ( (l_curr->start >= lock->start) && + (l_curr->start + l_curr->size <= lock->start + lock->size) ) { /* * This unlock is completely overlapped by this existing lock range @@ -1068,26 +872,26 @@ OR.... */ /********************************************* +---------+ - | ul_curr | + | l_curr | +---------+ +---------------------------+ | lock | +---------------------------+ **********************************************/ /* Save the next pointer */ - struct unlock_list *ul_next = ul_curr->next; + struct lock_list *ul_next = l_curr->next; DEBUG(10,("delete case.\n" )); - DLIST_REMOVE(ulhead, ul_curr); - if(ulhead == NULL) + DLIST_REMOVE(lhead, l_curr); + if(lhead == NULL) break; /* No more list... */ - ul_curr = ul_next; + l_curr = ul_next; - } else if ( (ul_curr->start >= lock->start) && - (ul_curr->start < lock->start + lock->size) && - (ul_curr->start + ul_curr->size > lock->start + lock->size) ) { + } else if ( (l_curr->start >= lock->start) && + (l_curr->start < lock->start + lock->size) && + (l_curr->start + l_curr->size > lock->start + lock->size) ) { /* * This unlock overlaps the existing lock range at the high end. @@ -1095,28 +899,28 @@ OR.... */ /********************************************* +---------------+ - | ul_curr | + | l_curr | +---------------+ +---------------+ | lock | +---------------+ BECOMES.... +-------+ - |ul_curr| + | l_curr| +-------+ **********************************************/ - ul_curr->size = (ul_curr->start + ul_curr->size) - (lock->start + lock->size); - ul_curr->start = lock->start + lock->size; + l_curr->size = (l_curr->start + l_curr->size) - (lock->start + lock->size); + l_curr->start = lock->start + lock->size; DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n", - (double)ul_curr->start, (double)ul_curr->size )); + (double)l_curr->start, (double)l_curr->size )); - ul_curr = ul_curr->next; + l_curr = l_curr->next; - } else if ( (ul_curr->start < lock->start) && - (ul_curr->start + ul_curr->size > lock->start) && - (ul_curr->start + ul_curr->size <= lock->start + lock->size) ) { + } else if ( (l_curr->start < lock->start) && + (l_curr->start + l_curr->size > lock->start) && + (l_curr->start + l_curr->size <= lock->start + lock->size) ) { /* * This unlock overlaps the existing lock range at the low end. @@ -1124,26 +928,26 @@ BECOMES.... */ /********************************************* +---------------+ - | ul_curr | + | l_curr | +---------------+ +---------------+ | lock | +---------------+ BECOMES.... +-------+ - |ul_curr| + | l_curr| +-------+ **********************************************/ - ul_curr->size = lock->start - ul_curr->start; + l_curr->size = lock->start - l_curr->start; DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n", - (double)ul_curr->start, (double)ul_curr->size )); + (double)l_curr->start, (double)l_curr->size )); - ul_curr = ul_curr->next; + l_curr = l_curr->next; - } else if ( (ul_curr->start < lock->start) && - (ul_curr->start + ul_curr->size > lock->start + lock->size) ) { + } else if ( (l_curr->start < lock->start) && + (l_curr->start + l_curr->size > lock->start + lock->size) ) { /* * Worst case scenario. Unlock request completely overlaps an existing * lock range. Split the request into two, push the new (upper) request @@ -1152,46 +956,46 @@ BECOMES.... */ /********************************************* +---------------------------+ - | ul_curr | + | l_curr | +---------------------------+ +---------+ | lock | +---------+ BECOMES..... +-------+ +---------+ - |ul_curr| |ul_new | + | l_curr| | l_new | +-------+ +---------+ **********************************************/ - struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx, - sizeof(struct unlock_list)); + struct lock_list *l_new = (struct lock_list *)talloc(ctx, + sizeof(struct lock_list)); - if(ul_new == NULL) { - DEBUG(0,("posix_unlock_list: talloc fail.\n")); + if(l_new == NULL) { + DEBUG(0,("posix_lock_list: talloc fail.\n")); return NULL; /* The talloc_destroy takes care of cleanup. */ } - ZERO_STRUCTP(ul_new); - ul_new->start = lock->start + lock->size; - ul_new->size = ul_curr->start + ul_curr->size - ul_new->start; + ZERO_STRUCTP(l_new); + l_new->start = lock->start + lock->size; + l_new->size = l_curr->start + l_curr->size - l_new->start; - /* Truncate the ul_curr. */ - ul_curr->size = lock->start - ul_curr->start; + /* Truncate the l_curr. */ + l_curr->size = lock->start - l_curr->start; DEBUG(10,("split case: curr: start=%.0f,size=%.0f \ -new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, - (double)ul_new->start, (double)ul_new->size )); +new: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size, + (double)l_new->start, (double)l_new->size )); /* - * Add into the dlink list after the ul_curr point - NOT at ulhead. + * Add into the dlink list after the l_curr point - NOT at lhead. * Note we can't use DLINK_ADD here as this inserts at the head of the given list. */ - ul_new->prev = ul_curr; - ul_new->next = ul_curr->next; - ul_curr->next = ul_new; + l_new->prev = l_curr; + l_new->next = l_curr->next; + l_curr->next = l_new; /* And move after the link we added. */ - ul_curr = ul_new->next; + l_curr = l_new->next; } else { @@ -1201,18 +1005,159 @@ new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size, */ pstring msg; - slprintf(msg, sizeof(msg)-1, "logic flaw in cases: ul_curr: start = %.0f, size = %.0f : \ -lock: start = %.0f, size = %.0f\n", (double)ul_curr->start, (double)ul_curr->size, (double)lock->start, (double)lock->size ); + slprintf(msg, sizeof(msg)-1, "logic flaw in cases: l_curr: start = %.0f, size = %.0f : \ +lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size, (double)lock->start, (double)lock->size ); smb_panic(msg); } - } /* end for ( ul_curr = ulhead; ul_curr;) */ + } /* end for ( l_curr = lhead; l_curr;) */ } /* end for (i=0; ifsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); + + /* + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. + */ + + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) + return True; + + /* + * Windows is very strange. It allows read locks to be overlayed + * (even over a write lock), but leaves the write lock in force until the first + * unlock. It also reference counts the locks. This means the following sequence : + * + * process1 process2 + * ------------------------------------------------------------------------ + * WRITE LOCK : start = 2, len = 10 + * READ LOCK: start =0, len = 10 - FAIL + * READ LOCK : start = 0, len = 14 + * READ LOCK: start =0, len = 10 - FAIL + * UNLOCK : start = 2, len = 10 + * READ LOCK: start =0, len = 10 - OK + * + * Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but + * would leave a single read lock over the 0-14 region. In order to + * re-create Windows semantics mapped to POSIX locks, we create multiple TDB + * entries, one for each overlayed lock request. We are guarenteed by the brlock + * semantics that if a write lock is added, then it will be first in the array. + */ + + if ((l_ctx = talloc_init()) == NULL) { + DEBUG(0,("set_posix_lock: unable to init talloc context.\n")); + return True; /* Not a fatal error. */ + } + + if ((ll = (struct lock_list *)talloc(l_ctx, sizeof(struct lock_list))) == NULL) { + DEBUG(0,("set_posix_lock: unable to talloc unlock list.\n")); + talloc_destroy(l_ctx); + return True; /* Not a fatal error. */ + } + + /* + * Create the initial list entry containing the + * lock we want to add. + */ + + ZERO_STRUCTP(ll); + ll->start = offset; + ll->size = count; + + DLIST_ADD(llist, ll); + + /* + * The following call calculates if there are any + * overlapping locks held by this process on + * fd's open on the same file and splits this list + * into a list of lock ranges that do not overlap with existing + * POSIX locks. + */ + + llist = posix_lock_list(l_ctx, llist, fsp); + + /* + * Now we have the list of ranges to lock it is safe to add the + * entry into the POSIX lock tdb. We take note of the entry we + * added here in case we have to remove it on POSIX lock fail. + */ + + if (!add_posix_lock_entry(fsp,offset,count,posix_lock_type,&entry_num)) { + DEBUG(0,("set_posix_lock: Unable to create posix lock entry !\n")); + talloc_destroy(l_ctx); + return False; + } + + /* + * Add the POSIX locks on the list of ranges returned. + * As the lock is supposed to be added atomically, we need to + * back out all the locks if any one of these calls fail. + */ + + for (lock_count = 0, ll = llist; ll; ll = ll->next, lock_count++) { + offset = ll->start; + count = ll->size; + + DEBUG(5,("set_posix_lock: Real lock: Type = %s: offset = %.0f, count = %.0f\n", + posix_lock_type_name(posix_lock_type), (double)offset, (double)count )); + + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) { + DEBUG(5,("set_posix_lock: Lock fail !: Type = %s: offset = %.0f, count = %.0f\n", + posix_lock_type_name(posix_lock_type), (double)offset, (double)count )); + ret = False; + break; + } + } + + if (!ret) { + + /* + * Back out all the POSIX locks we have on fail. + */ + + for (ll = llist; lock_count; ll = ll->next, lock_count--) { + offset = ll->start; + count = ll->size; + + DEBUG(5,("set_posix_lock: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n", + posix_lock_type_name(posix_lock_type), (double)offset, (double)count )); + + posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK); + } + + /* + * Remove the tdb entry for this lock. + */ + + delete_posix_lock_entry_by_index(fsp,entry_num); + } + + talloc_destroy(l_ctx); + return ret; } /**************************************************************************** @@ -1226,8 +1171,8 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u SMB_OFF_T count; BOOL ret = True; TALLOC_CTX *ul_ctx = NULL; - struct unlock_list *ulist = NULL; - struct unlock_list *ul = NULL; + struct lock_list *ulist = NULL; + struct lock_list *ul = NULL; struct posix_lock deleted_lock; int num_overlapped_entries; @@ -1245,6 +1190,8 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u /* * We treat this as one unlock request for POSIX accounting purposes even * if it may later be split into multiple smaller POSIX unlock ranges. + * num_overlapped_entries is the number of existing locks that have any + * overlap with this unlock request. */ num_overlapped_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock); @@ -1256,7 +1203,8 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u /* * If num_overlapped_entries is > 0, and the lock_type we just deleted from the tdb was * a POSIX write lock, then before doing the unlock we need to downgrade - * the POSIX lock to a read lock. + * the POSIX lock to a read lock. This allows any overlapping read locks + * to be atomically maintained. */ if (num_overlapped_entries > 0 && deleted_lock.lock_type == F_WRLCK) { @@ -1267,11 +1215,11 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u } if ((ul_ctx = talloc_init()) == NULL) { - DEBUG(0,("release_posix_lock: unable to init talloc context.\n")); + DEBUG(0,("release_posix_lock: unable to init talloc context.\n")); return True; /* Not a fatal error. */ } - if ((ul = (struct unlock_list *)talloc(ul_ctx, sizeof(struct unlock_list))) == NULL) { + if ((ul = (struct lock_list *)talloc(ul_ctx, sizeof(struct lock_list))) == NULL) { DEBUG(0,("release_posix_lock: unable to talloc unlock list.\n")); talloc_destroy(ul_ctx); return True; /* Not a fatal error. */ @@ -1297,7 +1245,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u * unlocks are performed. */ - ulist = posix_unlock_list(ul_ctx, ulist, fsp); + ulist = posix_lock_list(ul_ctx, ulist, fsp); /* * Release the POSIX locks on the list of ranges returned. @@ -1307,16 +1255,6 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u offset = ulist->start; count = ulist->size; - if(u_count == 0) { - - /* - * This lock must overlap with an existing lock. - * Don't do any POSIX call. - */ - - continue; - } - DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n", (double)offset, (double)count )); -- cgit From 33179a95d82a27a077acbad57d3cd9c403afb7eb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Jun 2000 15:46:15 +0000 Subject: add some brackets (This used to be commit bf67721ef5cc6d5ad1762fca320ef612025b4593) --- source3/locking/brlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 933fc142e9..7e22b8ac7a 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -158,7 +158,7 @@ void brl_init(int read_only) { if (tdb) return; tdb = tdb_open(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST, - read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); if (!tdb) { DEBUG(0,("Failed to open byte range locking database\n")); return; -- cgit From b50ca095af232be3a88231965449a836e5321db5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Jun 2000 15:46:46 +0000 Subject: allow posix locking database to be opened read-only (for smbstatus) (This used to be commit b9d78738bb30da3d989dfacc95cfde529f2afca5) --- source3/locking/locking.c | 2 +- source3/locking/posix.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 302b5b56c9..8fc1c4a4bc 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -233,7 +233,7 @@ BOOL locking_init(int read_only) return False; } - if (!posix_locking_init()) + if (!posix_locking_init(read_only)) return False; return True; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 6ab4bef4cc..69df55ba3c 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -1346,25 +1346,25 @@ void posix_locking_close_file(files_struct *fsp) Create the in-memory POSIX lock databases. ********************************************************************/ -BOOL posix_locking_init(void) +BOOL posix_locking_init(int read_only) { if (posix_lock_tdb && posix_pending_close_tdb) return True; - + if (!posix_lock_tdb) posix_lock_tdb = tdb_open(NULL, 0, TDB_INTERNAL, - O_RDWR|O_CREAT, 0644); - if (!posix_lock_tdb) { - DEBUG(0,("Failed to open POSIX byte range locking database.\n")); + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); + if (!posix_lock_tdb) { + DEBUG(0,("Failed to open POSIX byte range locking database.\n")); return False; - } + } if (!posix_pending_close_tdb) posix_pending_close_tdb = tdb_open(NULL, 0, TDB_INTERNAL, - O_RDWR|O_CREAT, 0644); - if (!posix_pending_close_tdb) { - DEBUG(0,("Failed to open POSIX pending close database.\n")); + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); + if (!posix_pending_close_tdb) { + DEBUG(0,("Failed to open POSIX pending close database.\n")); return False; - } + } return True; } -- cgit From 3689e4ffc10fceb4c39814ef58fe31697e7dd976 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Sep 2000 07:02:43 +0000 Subject: the first cut of the internal messaging system. The motivation for this system is to replace the UDP message for oplocks, but this commit only does the "set debug level" message. (This used to be commit 2a34ee95f3929cff131db6c5a2b4820194c05b2d) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8fc1c4a4bc..58e6b06e66 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -229,7 +229,7 @@ BOOL locking_init(int read_only) 0644); if (!tdb) { - DEBUG(0,("ERROR: Failed to initialise share modes\n")); + DEBUG(0,("ERROR: Failed to initialise locking database\n")); return False; } -- cgit From 636f146abf0a75cd3b21a57b50627ee149a635ab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Oct 2000 03:21:49 +0000 Subject: Restructuring of vfs layer to include a "this" pointer - can be an fsp or a conn struct depending on the call. We need this to have a clean NT ACL call interface. This will break any existing VFS libraries (that's why this is pre-release code). Andrew gets credit for this one :-) :-). In addition - added Herb's WITH_PROFILE changes - Herb - please examine the changes I've made to the smbd/reply.c code you added. The original code was very ugly and I have replaced it with a START_PROFILE(x)/END_PROFILE(x) pair using the preprocessor. Please check this compiles ok with the --with-profile switch. Jeremy. (This used to be commit b07611f8159b0b3f42e7e02611be9f4d56de96f5) --- source3/locking/posix.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 69df55ba3c..7bac1ffe37 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -204,7 +204,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) /* * No POSIX to worry about, just close. */ - ret = conn->vfs_ops.close(fsp->fd); + ret = conn->vfs_ops.close(fsp,fsp->fd); fsp->fd = -1; return ret; } @@ -259,7 +259,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); for(i = 0; i < count; i++) { - if (conn->vfs_ops.close(fd_array[i]) == -1) { + if (conn->vfs_ops.close(fsp,fd_array[i]) == -1) { saved_errno = errno; } } @@ -279,7 +279,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) * Finally close the fd associated with this fsp. */ - ret = conn->vfs_ops.close(fsp->fd); + ret = conn->vfs_ops.close(fsp,fsp->fd); if (saved_errno != 0) { errno = saved_errno; @@ -688,7 +688,7 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fd,op,(double)offset,(double)count,type)); - ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type); + ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); if (!ret && (errno == EFBIG)) { if( DEBUGLVL( 0 )) { @@ -699,7 +699,7 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF /* 32 bit NFS file system, retry with smaller offset */ errno = 0; count &= 0x7fffffff; - ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type); + ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); } /* A lock query - just return. */ @@ -727,7 +727,7 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF count = (orig_count & 0x7FFFFFFF); offset = (SMB_OFF_T)map_lock_offset(off_high, off_low); - ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type); + ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); if (!ret) { if (errno == EINVAL) { DEBUG(3,("posix_fcntl_lock: locking not supported? returning True\n")); -- cgit From ba00796e6dd13b87b7988a98e532676d9eab702c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Oct 2000 18:13:52 +0000 Subject: Herb's warning fixes. Also the POSIX locking fix. We now use our own vfs layer to do get/set acl calls (hurrah!). Jeremy. (This used to be commit dfe77c7046cbd65ee52aea7439f21503c1eac41d) --- source3/locking/posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 7bac1ffe37..fbdcf662fc 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -408,7 +408,7 @@ static BOOL does_lock_overlap(SMB_OFF_T start1, SMB_OFF_T size1, SMB_OFF_T start if (start1 >= start2 && start1 <= start2 + size2) return True; - if (start1 < start2 && start1 + size1 > start2); + if (start1 < start2 && start1 + size1 > start2) return True; return False; -- cgit From ac4d2775618a9ac3428d60bf667e3b968d634799 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Nov 2000 23:10:56 +0000 Subject: Fix from John Reilly for equivalence tests. Jeremy. (This used to be commit b456274a7ba22d512bab5ede979cd9363398825b) --- source3/locking/brlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 7e22b8ac7a..979910970f 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -440,5 +440,5 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st int brl_forall(BRLOCK_FN(fn)) { if (!tdb) return 0; - return tdb_traverse(tdb, traverse_fn, (BRLOCK_FN_CAST())fn); + return tdb_traverse(tdb, traverse_fn, (void *)fn); } -- cgit From 7e4c4721b4fbfa71ce6712ec5b9f3e8e8a105147 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 Dec 2000 00:05:15 +0000 Subject: Changed to sourceforge tdb code. This includes spinlocks (so we now have a --with-spinlocks option to configure, this does mean the on-disk tdb format has changed, so 2.2alphaX sites will need to re-create their tdb's. The upside is no more tdb fragmentation and a +5% on netbench. Swings and roundabouts.... Jeremy. (This used to be commit 9dea7b7c257db487f8ced7dad3fce92fba03ea91) --- source3/locking/brlock.c | 26 +++++++++++++------------- source3/locking/locking.c | 8 ++++---- 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 979910970f..5c3dae02c0 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -121,7 +121,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat struct lock_key *key; int count, i; - tdb_lockchain(tdb, kbuf); + tdb_chainlock(tdb, kbuf); locks = (struct lock_struct *)dbuf.dptr; key = (struct lock_key *)kbuf.dptr; @@ -147,7 +147,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); } - tdb_unlockchain(tdb, kbuf); + tdb_chainunlock(tdb, kbuf); return 0; } @@ -188,7 +188,7 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, dbuf.dptr = NULL; - tdb_lockchain(tdb, kbuf); + tdb_chainlock(tdb, kbuf); dbuf = tdb_fetch(tdb, kbuf); lock.context.smbpid = smbpid; @@ -218,12 +218,12 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); + tdb_chainunlock(tdb, kbuf); return True; fail: if (dbuf.dptr) free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); + tdb_chainunlock(tdb, kbuf); return False; } @@ -244,7 +244,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, dbuf.dptr = NULL; - tdb_lockchain(tdb, kbuf); + tdb_chainlock(tdb, kbuf); dbuf = tdb_fetch(tdb, kbuf); if (!dbuf.dptr) { @@ -292,7 +292,7 @@ smbpid = %u, pid = %u, tid = %u\n", } free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); + tdb_chainunlock(tdb, kbuf); return True; } } @@ -301,7 +301,7 @@ smbpid = %u, pid = %u, tid = %u\n", fail: if (dbuf.dptr) free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); + tdb_chainunlock(tdb, kbuf); return False; } @@ -322,7 +322,7 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, dbuf.dptr = NULL; - tdb_lockchain(tdb, kbuf); + tdb_chainlock(tdb, kbuf); dbuf = tdb_fetch(tdb, kbuf); lock.context.smbpid = smbpid; @@ -346,12 +346,12 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, /* no conflicts - we could have added it */ free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); + tdb_chainunlock(tdb, kbuf); return True; fail: if (dbuf.dptr) free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); + tdb_chainunlock(tdb, kbuf); return False; } @@ -369,7 +369,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) dbuf.dptr = NULL; - tdb_lockchain(tdb, kbuf); + tdb_chainlock(tdb, kbuf); dbuf = tdb_fetch(tdb, kbuf); if (!dbuf.dptr) goto fail; @@ -404,7 +404,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) /* we didn't find it */ fail: if (dbuf.dptr) free(dbuf.dptr); - tdb_unlockchain(tdb, kbuf); + tdb_chainunlock(tdb, kbuf); } /**************************************************************************** diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 58e6b06e66..2056e6dcf5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -274,7 +274,7 @@ static TDB_DATA locking_key_fsp(files_struct *fsp) BOOL lock_share_entry(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) { - return tdb_lockchain(tdb, locking_key(dev, inode)) == 0; + return tdb_chainlock(tdb, locking_key(dev, inode)) == 0; } /******************************************************************* @@ -283,7 +283,7 @@ BOOL lock_share_entry(connection_struct *conn, BOOL unlock_share_entry(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) { - return tdb_unlockchain(tdb, locking_key(dev, inode)) == 0; + return tdb_chainunlock(tdb, locking_key(dev, inode)) == 0; } @@ -292,7 +292,7 @@ BOOL unlock_share_entry(connection_struct *conn, ******************************************************************/ BOOL lock_share_entry_fsp(files_struct *fsp) { - return tdb_lockchain(tdb, locking_key(fsp->dev, fsp->inode)) == 0; + return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0; } /******************************************************************* @@ -300,7 +300,7 @@ BOOL lock_share_entry_fsp(files_struct *fsp) ******************************************************************/ BOOL unlock_share_entry_fsp(files_struct *fsp) { - return tdb_unlockchain(tdb, locking_key(fsp->dev, fsp->inode)) == 0; + return tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0; } /******************************************************************* -- cgit From a58ca91245334515fbc0132ab72772bb067a8131 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 6 Dec 2000 02:51:13 +0000 Subject: tdb_unlockchain() no longer returns a value (This used to be commit aee52c7acf138f8fd651aeb3d9bef79f99d1a2a9) --- source3/locking/locking.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 2056e6dcf5..b3601e8752 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -280,10 +280,10 @@ BOOL lock_share_entry(connection_struct *conn, /******************************************************************* Unlock a hash bucket entry. ******************************************************************/ -BOOL unlock_share_entry(connection_struct *conn, +void unlock_share_entry(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) { - return tdb_chainunlock(tdb, locking_key(dev, inode)) == 0; + tdb_chainunlock(tdb, locking_key(dev, inode)); } @@ -298,9 +298,9 @@ BOOL lock_share_entry_fsp(files_struct *fsp) /******************************************************************* Unlock a hash bucket entry. ******************************************************************/ -BOOL unlock_share_entry_fsp(files_struct *fsp) +void unlock_share_entry_fsp(files_struct *fsp) { - return tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0; + tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode)); } /******************************************************************* -- cgit From da3053048c3d224a20d6383ac6682d31059cd46c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Mar 2001 00:32:10 +0000 Subject: Merge of new 2.2 code into HEAD (Gerald I hate you :-) :-). Allows new SAMR RPC code to merge with new passdb code. Currently rpcclient doesn't compile. I'm working on it... Jeremy. (This used to be commit 0be41d5158ea4e645e93e8cd30617c038416e549) --- source3/locking/brlock.c | 2 -- source3/locking/locking.c | 11 ++++------- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 5c3dae02c0..175ab5c9b0 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -118,13 +118,11 @@ delete a record if it is for a dead process static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) { struct lock_struct *locks; - struct lock_key *key; int count, i; tdb_chainlock(tdb, kbuf); locks = (struct lock_struct *)dbuf.dptr; - key = (struct lock_key *)kbuf.dptr; count = dbuf.dsize / sizeof(*locks); for (i=0; ifsp_name); - size = sizeof(*data) + sizeof(*shares) + strlen(fname) + 1; + size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1; p = (char *)malloc(size); data = (struct locking_data *)p; - shares = (share_mode_entry *)(p + sizeof(*data)); data->num_share_mode_entries = 1; - pstrcpy(p + sizeof(*data) + sizeof(*shares), fname); + pstrcpy(p + sizeof(*data) + sizeof(share_mode_entry), fname); fill_share_mode(p + sizeof(*data), fsp, port, op_type); dbuf.dptr = p; dbuf.dsize = size; @@ -426,14 +424,13 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) /* we're adding to an existing entry - this is a bit fiddly */ data = (struct locking_data *)dbuf.dptr; - shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); data->num_share_mode_entries++; - size = dbuf.dsize + sizeof(*shares); + size = dbuf.dsize + sizeof(share_mode_entry); p = malloc(size); memcpy(p, dbuf.dptr, sizeof(*data)); fill_share_mode(p + sizeof(*data), fsp, port, op_type); - memcpy(p + sizeof(*data) + sizeof(*shares), dbuf.dptr + sizeof(*data), + memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data), dbuf.dsize - sizeof(*data)); free(dbuf.dptr); dbuf.dptr = p; -- cgit From 6e7f03f9b920d1b81056959cca8c0b27ada4ee2d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Mar 2001 08:57:24 +0000 Subject: This is a big, rather ugly patch. Whilst investigating the files not truncated when copying to a full disk problem, I discovered that we were not allowing the delete on close flag to be set properly, this led to other things, and after investigation of the proper delete on close semantics and their relationship to the file_share_delete flag I discovered there were some cases where we weren't doing the deny modes properly. And this after only 5 years working on them..... :-) :-). So here's the latest attempt. I realised the delete on close flag needs to be set across all smbds with a dev/ino pair open - in addition, the delete on close flag, allow share delete and delete access requested all need to be stored in the share mode tdb. The "delete_on_close" entry in the fsp struct is now redundant and should really be removed. This may also mean we can get rid of the "iterate_fsp" calls that I didn't like adding in the first place. Whilst doing this patch, I also discovered we needed to do the se_map_generic() call for file opens and POSIX ACL mapping, so I added that also. This code, although ugly, now passes the deny mode torture tests plus the delete on close tests I added. I do need to add one more multiple connection delete on close test to make sure I got the semantics exactly right, plus we should also (as Andrew suggested) move to random testing here. The good news is that NT should now correctly delete the file on disk full error when copying to a disk :-). Jeremy. (This used to be commit 51987684bd231c744da2e5f3705fd236d5616173) --- source3/locking/locking.c | 71 ++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 32 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 118d59cc10..5824287e91 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -331,19 +331,24 @@ int get_share_modes(connection_struct *conn, } /******************************************************************* - Del the share mode of a file for this process + Del the share mode of a file for this process. Return the number + of entries left, and a memdup'ed copy of the entry deleted. ********************************************************************/ -void del_share_mode(files_struct *fsp) + +size_t del_share_mode(files_struct *fsp, share_mode_entry **ppse) { TDB_DATA dbuf; struct locking_data *data; int i, del_count=0; share_mode_entry *shares; pid_t pid = sys_getpid(); + size_t count; + + *ppse = NULL; /* read in the existing share modes */ dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); - if (!dbuf.dptr) return; + if (!dbuf.dptr) return 0; data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); @@ -354,6 +359,7 @@ void del_share_mode(files_struct *fsp) if (shares[i].pid == pid && memcmp(&shares[i].time, &fsp->open_time,sizeof(struct timeval)) == 0) { + *ppse = memdup(&shares[i], sizeof(*shares)); data->num_share_mode_entries--; memmove(&shares[i], &shares[i+1], dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); @@ -366,6 +372,8 @@ void del_share_mode(files_struct *fsp) /* the record has shrunk a bit */ dbuf.dsize -= del_count * sizeof(*shares); + count = data->num_share_mode_entries; + /* store it back in the database */ if (data->num_share_mode_entries == 0) { tdb_delete(tdb, locking_key_fsp(fsp)); @@ -374,6 +382,7 @@ void del_share_mode(files_struct *fsp) } free(dbuf.dptr); + return count; } /******************************************************************* @@ -529,42 +538,40 @@ BOOL downgrade_share_oplock(files_struct *fsp) return mod_share_mode(fsp, downgrade_share_oplock_fn, NULL); } - /******************************************************************* - Static function that actually does the work for the generic function - below. + Get/Set the delete on close flag in a set of share modes. + Return False on fail, True on success. ********************************************************************/ -struct mod_val { - int new_share_mode; - uint16 new_oplock; -}; -static void modify_share_mode_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, - void *param) +BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) { - struct mod_val *mvp = (struct mod_val *)param; - - DEBUG(10,("modify_share_mode_fn: changing share mode info from %x to %x for entry dev=%x ino=%.0f\n", - entry->share_mode, mvp->new_share_mode, (unsigned int)dev, (double)inode )); - DEBUG(10,("modify_share_mode_fn: changing oplock state from %x to %x for entry dev=%x ino=%.0f\n", - entry->op_type, (int)mvp->new_oplock, (unsigned int)dev, (double)inode )); - /* Change the share mode info. */ - entry->share_mode = mvp->new_share_mode; - entry->op_type = mvp->new_oplock; -} + TDB_DATA dbuf; + struct locking_data *data; + int i; + share_mode_entry *shares; -/******************************************************************* - Modify a share mode on a file. Used by the delete open file code. - Return False on fail, True on success. -********************************************************************/ -BOOL modify_share_mode(files_struct *fsp, int new_mode, uint16 new_oplock) -{ - struct mod_val mv; + /* read in the existing share modes */ + dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + if (!dbuf.dptr) return False; + + data = (struct locking_data *)dbuf.dptr; + shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - mv.new_share_mode = new_mode; - mv.new_oplock = new_oplock; + /* Set/Unset the delete on close element. */ + for (i=0;inum_share_mode_entries;i++,shares++) { + shares->share_mode = (delete_on_close ? + (shares->share_mode | DELETE_ON_CLOSE_FLAG) : + (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) ); + } - return mod_share_mode(fsp, modify_share_mode_fn, (void *)&mv); + /* store it back */ + if (data->num_share_mode_entries) { + if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) + return False; + } + + free(dbuf.dptr); + return True; } -- cgit From 2ef68c7e92d4661664f0410509f7cb551e74a198 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Apr 2001 19:12:06 +0000 Subject: Merge of Andrew's changes in 2.2. Jeremy. (This used to be commit fc76681812b1469208ad6c8847afdfc68bc6db49) --- source3/locking/posix.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index fbdcf662fc..75fc6272b5 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -632,12 +632,11 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, return True; } -#if defined(LARGE_SMB_OFF_T) /**************************************************************************** Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). ****************************************************************************/ -static uint32 map_lock_offset(uint32 high, uint32 low) +uint32 map_lock_offset(uint32 high, uint32 low) { unsigned int i; uint32 mask = 0; @@ -664,7 +663,6 @@ static uint32 map_lock_offset(uint32 high, uint32 low) return (high|low); } -#endif /**************************************************************************** Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and -- cgit From faa0bef196b732b45c4614acd655af4881504808 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 May 2001 20:35:48 +0000 Subject: Defensive brlock and locking database cleaning code. Jeremy. (This used to be commit d7aa42e4593b02ee6e487f7a4633bd7e7620ef2f) --- source3/locking/brlock.c | 49 ++++++++++++++++++++++++---- source3/locking/locking.c | 83 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 8 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 175ab5c9b0..089818c9aa 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -113,12 +113,16 @@ static BOOL brl_conflict(struct lock_struct *lck1, /**************************************************************************** -delete a record if it is for a dead process + Delete a record if it is for a dead process, if check_self is true, then + delete any records belonging to this pid also (there shouldn't be any). ****************************************************************************/ + static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) { struct lock_struct *locks; int count, i; + BOOL check_self = *(BOOL *)state; + pid_t mypid = sys_getpid(); tdb_chainlock(tdb, kbuf); @@ -128,7 +132,20 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat for (i=0; icontext.pid)) continue; + /* If check_self is true we want to remove our own records. */ + if (check_self && (mypid == lock->context.pid)) { + + DEBUG(0,("brlock : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n", + (unsigned int)lock->context.pid )); + + } else if (process_exists(lock->context.pid)) { + + DEBUG(10,("brlock : delete_fn. pid %u exists.\n", (unsigned int)lock->context.pid )); + continue; + } + + DEBUG(10,("brlock : delete_fn. Deleting record for process %u\n", + (unsigned int)lock->context.pid )); if (count > 1 && i < count-1) { memmove(&locks[i], &locks[i+1], @@ -152,9 +169,13 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat /**************************************************************************** Open up the brlock.tdb database. ****************************************************************************/ + void brl_init(int read_only) { - if (tdb) return; + BOOL check_self = False; + + if (tdb) + return; tdb = tdb_open(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST, read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); if (!tdb) { @@ -163,11 +184,27 @@ void brl_init(int read_only) } /* delete any dead locks */ - if (!read_only) { - tdb_traverse(tdb, delete_fn, NULL); - } + if (!read_only) + tdb_traverse(tdb, delete_fn, &check_self); } +/**************************************************************************** + Close down the brlock.tdb database. +****************************************************************************/ + +void brl_shutdown(int read_only) +{ + BOOL check_self = True; + + if (tdb) + return; + + /* delete any dead locks */ + if (!read_only) + tdb_traverse(tdb, delete_fn, &check_self); + + tdb_close(tdb); +} /**************************************************************************** Lock a range of bytes. diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 5824287e91..c2d3106a67 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -214,14 +214,73 @@ void locking_close_file(files_struct *fsp) } } +/**************************************************************************** + Delete a record if it is for a dead process, if check_self is true, then + delete any records belonging to this pid also (there shouldn't be any). + This function is only called on locking startup and shutdown. +****************************************************************************/ + +static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +{ + struct locking_data *data; + share_mode_entry *shares; + int i, del_count=0; + pid_t mypid = sys_getpid(); + BOOL check_self = *(BOOL *)state; + + tdb_chainlock(tdb, kbuf); + + data = (struct locking_data *)dbuf.dptr; + shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); + + for (i=0;inum_share_mode_entries;) { + + if (check_self && (shares[i].pid == mypid)) { + DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n", + (unsigned int)shares[i].pid )); + } else if (!process_exists(shares[i].pid)) { + DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Entry for pid %u and it no longer exists !\n", + (unsigned int)shares[i].pid )); + } else { + /* Process exists, leave this record alone. */ + i++; + continue; + } + + data->num_share_mode_entries--; + memmove(&shares[i], &shares[i+1], + dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); + del_count++; + + } + + /* the record has shrunk a bit */ + dbuf.dsize -= del_count * sizeof(*shares); + + /* store it back in the database */ + if (data->num_share_mode_entries == 0) + tdb_delete(ttdb, kbuf); + else + tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE); + + tdb_chainunlock(tdb, kbuf); + return 0; +} + /**************************************************************************** Initialise the locking functions. ****************************************************************************/ + +static int open_read_only; + BOOL locking_init(int read_only) { + BOOL check_self = False; + brl_init(read_only); - if (tdb) return True; + if (tdb) + return True; tdb = tdb_open(lock_path("locking.tdb"), 0, TDB_CLEAR_IF_FIRST, @@ -236,15 +295,35 @@ BOOL locking_init(int read_only) if (!posix_locking_init(read_only)) return False; + /* delete any dead locks */ + if (!read_only) + tdb_traverse(tdb, delete_fn, &check_self); + + open_read_only = read_only; + return True; } /******************************************************************* Deinitialize the share_mode management. ******************************************************************/ + BOOL locking_end(void) { - if (tdb && tdb_close(tdb) != 0) return False; + BOOL check_self = True; + + brl_shutdown(open_read_only); + if (tdb) { + + /* delete any dead locks */ + + if (!open_read_only) + tdb_traverse(tdb, delete_fn, &check_self); + + if (tdb_close(tdb) != 0) + return False; + } + return True; } -- cgit From 840fb1643dbaa3ca1b435ccd85ce50123cf6252d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 May 2001 18:33:45 +0000 Subject: Stupid typo. Should be if (!tdb). Jeremy. (This used to be commit d3496897f167a8deb1d0034797e8b29f2c51acef) --- source3/locking/brlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 089818c9aa..552ea617aa 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -196,7 +196,7 @@ void brl_shutdown(int read_only) { BOOL check_self = True; - if (tdb) + if (!tdb) return; /* delete any dead locks */ -- cgit From 05fc3e578c895f632b351969d09cd00feb7599c7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 4 Jun 2001 05:13:59 +0000 Subject: use LDSHFLAGS not -shared in several places (This used to be commit 8ec9c87b5d1a7dae17d5b1a30f58effaf5e69e4b) --- source3/locking/brlock.c | 2 +- source3/locking/locking.c | 2 +- source3/locking/posix.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 552ea617aa..8f73327830 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -176,7 +176,7 @@ void brl_init(int read_only) if (tdb) return; - tdb = tdb_open(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST, + tdb = tdb_open_log(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST, read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); if (!tdb) { DEBUG(0,("Failed to open byte range locking database\n")); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index c2d3106a67..c77a86cbf4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -282,7 +282,7 @@ BOOL locking_init(int read_only) if (tdb) return True; - tdb = tdb_open(lock_path("locking.tdb"), + tdb = tdb_open_log(lock_path("locking.tdb"), 0, TDB_CLEAR_IF_FIRST, read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 75fc6272b5..9cfe25ed9d 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -1350,14 +1350,14 @@ BOOL posix_locking_init(int read_only) return True; if (!posix_lock_tdb) - posix_lock_tdb = tdb_open(NULL, 0, TDB_INTERNAL, + posix_lock_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); if (!posix_lock_tdb) { DEBUG(0,("Failed to open POSIX byte range locking database.\n")); return False; } if (!posix_pending_close_tdb) - posix_pending_close_tdb = tdb_open(NULL, 0, TDB_INTERNAL, + posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); if (!posix_pending_close_tdb) { DEBUG(0,("Failed to open POSIX pending close database.\n")); -- cgit From d1f38ac53107d818b88cae9ee4d4442381dc4702 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 30 Jun 2001 01:59:48 +0000 Subject: Fixed the first locking error (test #8 found by locktest code from Clarion locktest. Jeremy. (This used to be commit 5c42845b5bb6fafd0ebf93fbdd23d9bf861da865) --- source3/locking/brlock.c | 33 ++++++++++++++++++++++++++++++--- source3/locking/locking.c | 18 +++++++++++++++--- 2 files changed, 45 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 8f73327830..7f3ec6757e 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -340,6 +340,26 @@ smbpid = %u, pid = %u, tid = %u\n", return False; } +/**************************************************************************** + Check to see if this lock conflicts, but ignore our own locks on the + same fnum only. +****************************************************************************/ + +static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck2) +{ + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) + return False; + + if (brl_same_context(&lck1->context, &lck2->context) && + lck1->fnum == lck2->fnum) + return False; + + if (lck1->start >= (lck2->start + lck2->size) || + lck2->start >= (lck1->start + lck1->size)) return False; + + return True; +} + /**************************************************************************** Test if we could add a lock if we wanted to. ****************************************************************************/ @@ -347,7 +367,7 @@ smbpid = %u, pid = %u, tid = %u\n", BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, - enum brl_type lock_type) + enum brl_type lock_type, int check_self) { TDB_DATA kbuf, dbuf; int count, i; @@ -373,8 +393,15 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, locks = (struct lock_struct *)dbuf.dptr; count = dbuf.dsize / sizeof(*locks); for (i=0; idev, fsp->inode, fsp->fnum, global_smbpid, sys_getpid(), conn->cnum, - offset, count, lock_type); + offset, count, lock_type, check_self); + + DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n", + (double)offset, (double)count, ret ? "locked" : "unlocked", + fsp->fsp_name )); /* * There is no lock held by an SMB daemon, check to * see if there is a POSIX lock from a UNIX or NFS process. */ - if(!ret && lp_posix_locking(snum)) + if(!ret && lp_posix_locking(snum)) { ret = is_posix_locked(fsp, offset, count, lock_type); + DEBUG(10,("is_locked: posix start=%.0f len=%.0f %s for file %s\n", + (double)offset, (double)count, ret ? "locked" : "unlocked", + fsp->fsp_name )); + } + return ret; } -- cgit From 064b4904f9695a766acc0d87a630e18a59e5c540 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 30 Jun 2001 03:11:44 +0000 Subject: Ensure we return correct error on trying to unlock a region not locked. Jeremy. (This used to be commit 015a077acc49e59179dc10256fd32166ee4623e2) --- source3/locking/locking.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 68c3c5b653..a75388081e 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -168,7 +168,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) { *eclass = ERRDOS; - *ecode = ERRlock; + *ecode = ERRbadfid; return False; } @@ -187,7 +187,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); *eclass = ERRDOS; - *ecode = ERRlock; + *ecode = ERRnotlocked; return False; } -- cgit From 5b69009b25886bfa8b07e3ac885064ffa730f9bf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 2 Jul 2001 02:42:41 +0000 Subject: Fixed the nastiest locking bug to track down.... smb_pids are sent in the lockingX calls - use that instead of smb_pid in the packet. Jeremy. (This used to be commit a3925cb9c6303ce24e5fecad6c8f3a0ba78b9ee0) --- source3/locking/locking.c | 12 ++++++------ source3/locking/posix.c | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index a75388081e..067b1dc0dd 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -37,7 +37,7 @@ #include "includes.h" extern int DEBUGLEVEL; -int global_smbpid; +uint16 global_smbpid; /* the locking database handle */ static TDB_CONTEXT *tdb; @@ -99,7 +99,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, Utility function called by locking requests. ****************************************************************************/ -BOOL do_lock(files_struct *fsp,connection_struct *conn, +BOOL do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, int *eclass,uint32 *ecode) { @@ -119,7 +119,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { ok = brl_lock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, sys_getpid(), conn->cnum, + lock_pid, sys_getpid(), conn->cnum, offset, count, lock_type); @@ -139,7 +139,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, * lock entry. */ (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, sys_getpid(), conn->cnum, + lock_pid, sys_getpid(), conn->cnum, offset, count); } } @@ -157,7 +157,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, Utility function called by unlocking requests. ****************************************************************************/ -BOOL do_unlock(files_struct *fsp,connection_struct *conn, +BOOL do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, SMB_BIG_UINT count,SMB_BIG_UINT offset, int *eclass,uint32 *ecode) { @@ -182,7 +182,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, */ ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, sys_getpid(), conn->cnum, offset, count); + lock_pid, sys_getpid(), conn->cnum, offset, count); if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 9cfe25ed9d..2a8a7aacd7 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -25,7 +25,6 @@ #include "includes.h" extern int DEBUGLEVEL; -extern int global_smbpid; /* * The POSIX locking database handle. -- cgit From 996719cce26700c68ff0e456e6a25d20085d091f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Jul 2001 22:21:31 +0000 Subject: Added "use mmap" for HPUX. Jeremy. (This used to be commit 840802f10677cb0009cb4df4c37c7d01aa5edacd) --- source3/locking/brlock.c | 2 +- source3/locking/locking.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 7f3ec6757e..1982d9982c 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -176,7 +176,7 @@ void brl_init(int read_only) if (tdb) return; - tdb = tdb_open_log(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST, + tdb = tdb_open_log(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST|USE_TDB_MMAP_FLAG, read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); if (!tdb) { DEBUG(0,("Failed to open byte range locking database\n")); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 067b1dc0dd..9b393ed6ba 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -295,7 +295,7 @@ BOOL locking_init(int read_only) return True; tdb = tdb_open_log(lock_path("locking.tdb"), - 0, TDB_CLEAR_IF_FIRST, + 0, TDB_CLEAR_IF_FIRST|USE_TDB_MMAP_FLAG, read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); -- cgit From 2e783a47076bd0994b6ce86df7ec967bc1c2da63 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 12 Aug 2001 17:30:01 +0000 Subject: this is a big global fix for the ptr = Realloc(ptr, size) bug. many possible mem leaks, and segfaults fixed. someone should port this fix to 2.2 also. (This used to be commit fa8e55b8b465114ce209344965c1ca0333b84db9) --- source3/locking/brlock.c | 6 ++++-- source3/locking/posix.c | 13 +++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 1982d9982c..d22297a948 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -218,6 +218,7 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, TDB_DATA kbuf, dbuf; int count, i; struct lock_struct lock, *locks; + char *tp; kbuf = locking_key(dev,ino); @@ -246,8 +247,9 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, } /* no conflicts - add it to the list of locks */ - dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*locks)); - if (!dbuf.dptr) goto fail; + tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*locks)); + if (!tp) goto fail; + else dbuf.dptr = tp; memcpy(dbuf.dptr + dbuf.dsize, &lock, sizeof(lock)); dbuf.dsize += sizeof(lock); tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 2a8a7aacd7..833914c7aa 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -98,16 +98,19 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) { TDB_DATA kbuf = locking_key_fsp(fsp); TDB_DATA dbuf; + char *tp; dbuf.dptr = NULL; dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(int)); - if (!dbuf.dptr) { + tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(int)); + if (!tp) { DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n")); + if (dbuf.dptr) free(dbuf.dptr); return False; } + else dbuf.dptr = tp; memcpy(dbuf.dptr + dbuf.dsize, &fsp->fd, sizeof(int)); dbuf.dsize += sizeof(int); @@ -354,6 +357,7 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s TDB_DATA kbuf = locking_key_fsp(fsp); TDB_DATA dbuf; struct posix_lock pl; + char *tp; dbuf.dptr = NULL; @@ -370,11 +374,12 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s pl.size = size; pl.lock_type = lock_type; - dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl)); - if (!dbuf.dptr) { + tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl)); + if (!tp) { DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); goto fail; } + else dbuf.dptr = tp; memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl)); dbuf.dsize += sizeof(pl); -- cgit From e430190a66933bc89837daca04f8d524af0284fa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 13 Aug 2001 17:58:54 +0000 Subject: Add printing of errno when POSIX lock requests fail. Jeremy. (This used to be commit befbfea21035b0566fc6ba8674587fc44ad7bbdc) --- source3/locking/posix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 833914c7aa..2a6f2be562 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -1128,8 +1128,8 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou posix_lock_type_name(posix_lock_type), (double)offset, (double)count )); if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) { - DEBUG(5,("set_posix_lock: Lock fail !: Type = %s: offset = %.0f, count = %.0f\n", - posix_lock_type_name(posix_lock_type), (double)offset, (double)count )); + DEBUG(5,("set_posix_lock: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n", + posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) )); ret = False; break; } @@ -1211,7 +1211,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u if (num_overlapped_entries > 0 && deleted_lock.lock_type == F_WRLCK) { if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) { - DEBUG(0,("release_posix_lock: downgrade of lock failed !\n")); + DEBUG(0,("release_posix_lock: downgrade of lock failed with error %s !\n", strerror(errno) )); return False; } } -- cgit From c786a4d89a3c4b7f2c6fdf0762e835ad7edbd664 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Aug 2001 22:13:53 +0000 Subject: Ensure we are very explicit about what we're comparing when we're comparing structures (ie. don't just do a memcmp). I don't think this will fix the fcntl spin issue, but it's a "just in case" change. Jeremy. (This used to be commit 41066208ad8ca20d35a32bdf9ad934e11465c8f1) --- source3/locking/locking.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 9b393ed6ba..ee3ce7c7d4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -448,8 +448,8 @@ size_t del_share_mode(files_struct *fsp, share_mode_entry **ppse) from the record */ for (i=0;inum_share_mode_entries;) { if (shares[i].pid == pid && - memcmp(&shares[i].time, - &fsp->open_time,sizeof(struct timeval)) == 0) { + shares[i].time.tv_sec == fsp->open_time.tv_sec && + shares[i].time.tv_usec == fsp->open_time.tv_usec ) { *ppse = memdup(&shares[i], sizeof(*shares)); data->num_share_mode_entries--; memmove(&shares[i], &shares[i+1], @@ -566,8 +566,8 @@ static BOOL mod_share_mode(files_struct *fsp, for (i=0;inum_share_mode_entries;i++) { if (pid == shares[i].pid && shares[i].share_mode == fsp->share_mode && - memcmp(&shares[i].time, - &fsp->open_time,sizeof(struct timeval)) == 0) { + shares[i].time.tv_sec == fsp->open_time.tv_sec && + shares[i].time.tv_usec == fsp->open_time.tv_usec ) { mod_fn(&shares[i], fsp->dev, fsp->inode, param); need_store=1; } -- cgit From e6a6dee0272a170848d3b9c177bf3839214d0a20 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 21 Aug 2001 01:25:45 +0000 Subject: This is Jeremy pretending to be Volker, 'cos the link from Seattle is having problems. I've added 3 things here to work on the fcntl spin problem. 1). Check *all* tdb return codes... :-). 2). If we're asking ourselves to break an oplock, and we can't find a fsp pointer that matches the entry, this is a *logic bug* and we should abort and panic so someone with gdb can pick up the pieces. 3). After we've broken an oplock, ensure that the entry itself has been removed, and if not remove it ourselves. This should not be neccessary in a correctly working environmen,t, but will provide an added layer of robustness in error situations. 4). I hate german keyboards :-) :-). Jeremy. (This used to be commit 1c94fa80646f9e31377fbb41332fe4780f550cab) --- source3/locking/locking.c | 200 +++++++++++++++++++++++++++++++--------------- 1 file changed, 136 insertions(+), 64 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index ee3ce7c7d4..4b037c0f3d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -239,6 +239,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat int i, del_count=0; pid_t mypid = sys_getpid(); BOOL check_self = *(BOOL *)state; + int ret = 0; tdb_chainlock(tdb, kbuf); @@ -270,13 +271,16 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat dbuf.dsize -= del_count * sizeof(*shares); /* store it back in the database */ - if (data->num_share_mode_entries == 0) - tdb_delete(ttdb, kbuf); - else - tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE); + if (data->num_share_mode_entries == 0) { + if (tdb_delete(ttdb, kbuf) == -1) + ret = -1; + } else { + if (tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE) == -1) + ret = -1; + } tdb_chainunlock(tdb, kbuf); - return 0; + return ret; } /**************************************************************************** @@ -340,8 +344,9 @@ BOOL locking_end(void) } /******************************************************************* - form a static locking key for a dev/inode pair + Form a static locking key for a dev/inode pair. ******************************************************************/ + static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) { static struct locking_key key; @@ -354,6 +359,7 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) kbuf.dsize = sizeof(key); return kbuf; } + static TDB_DATA locking_key_fsp(files_struct *fsp) { return locking_key(fsp->dev, fsp->inode); @@ -377,10 +383,10 @@ void unlock_share_entry(connection_struct *conn, tdb_chainunlock(tdb, locking_key(dev, inode)); } - /******************************************************************* Lock a hash bucket entry. use a fsp for convenience ******************************************************************/ + BOOL lock_share_entry_fsp(files_struct *fsp) { return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0; @@ -389,6 +395,7 @@ BOOL lock_share_entry_fsp(files_struct *fsp) /******************************************************************* Unlock a hash bucket entry. ******************************************************************/ + void unlock_share_entry_fsp(files_struct *fsp) { tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode)); @@ -397,6 +404,7 @@ void unlock_share_entry_fsp(files_struct *fsp) /******************************************************************* Get all share mode entries for a dev/inode pair. ********************************************************************/ + int get_share_modes(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry **shares) @@ -408,7 +416,8 @@ int get_share_modes(connection_struct *conn, *shares = NULL; dbuf = tdb_fetch(tdb, locking_key(dev, inode)); - if (!dbuf.dptr) return 0; + if (!dbuf.dptr) + return 0; data = (struct locking_data *)dbuf.dptr; ret = data->num_share_mode_entries; @@ -416,41 +425,76 @@ int get_share_modes(connection_struct *conn, *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares)); free(dbuf.dptr); - if (! *shares) return 0; + if (! *shares) + return 0; return ret; } /******************************************************************* - Del the share mode of a file for this process. Return the number - of entries left, and a memdup'ed copy of the entry deleted. + Fill a share mode entry. ********************************************************************/ -size_t del_share_mode(files_struct *fsp, share_mode_entry **ppse) +static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type) +{ + share_mode_entry *e = (share_mode_entry *)p; + memset(e, '\0', sizeof(share_mode_entry)); + e->pid = sys_getpid(); + e->share_mode = fsp->share_mode; + e->op_port = port; + e->op_type = op_type; + memcpy((char *)&e->time, (char *)&fsp->open_time, sizeof(struct timeval)); +} + +/******************************************************************* + Check if two share mode entries are identical, ignoring oplock + and port info. +********************************************************************/ + +static BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) +{ + return (e1->pid == e2->pid && + e1->share_mode == e2->share_mode && + e1->time.tv_sec == e2->time.tv_sec && + e1->time.tv_usec == e2->time.tv_usec ); +} + +/******************************************************************* + Delete a specific share mode. Return the number + of entries left, and a memdup'ed copy of the entry deleted (if required). + Ignore if no entry deleted. +********************************************************************/ + +ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, + share_mode_entry *entry, share_mode_entry **ppse) { TDB_DATA dbuf; struct locking_data *data; int i, del_count=0; share_mode_entry *shares; - pid_t pid = sys_getpid(); - size_t count; + ssize_t count; - *ppse = NULL; + if (ppse) + *ppse = NULL; /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); - if (!dbuf.dptr) return 0; + dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + if (!dbuf.dptr) + return -1; data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - /* find any with our pid and delete it by overwriting with the rest of the data - from the record */ + /* + * Find any with this pid and delete it + * by overwriting with the rest of the data + * from the record. + */ + for (i=0;inum_share_mode_entries;) { - if (shares[i].pid == pid && - shares[i].time.tv_sec == fsp->open_time.tv_sec && - shares[i].time.tv_usec == fsp->open_time.tv_usec ) { - *ppse = memdup(&shares[i], sizeof(*shares)); + if (share_modes_identical(&shares[i], entry)) { + if (ppse) + *ppse = memdup(&shares[i], sizeof(*shares)); data->num_share_mode_entries--; memmove(&shares[i], &shares[i+1], dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); @@ -460,44 +504,53 @@ size_t del_share_mode(files_struct *fsp, share_mode_entry **ppse) } } - /* the record has shrunk a bit */ - dbuf.dsize -= del_count * sizeof(*shares); + if (del_count) { + /* the record may have shrunk a bit */ + dbuf.dsize -= del_count * sizeof(*shares); - count = data->num_share_mode_entries; + count = (ssize_t)data->num_share_mode_entries; - /* store it back in the database */ - if (data->num_share_mode_entries == 0) { - tdb_delete(tdb, locking_key_fsp(fsp)); - } else { - tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + /* store it back in the database */ + if (data->num_share_mode_entries == 0) { + if (tdb_delete(tdb, locking_key(dev, inode)) == -1) + count = -1; + } else { + if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) + count = -1; + } } - free(dbuf.dptr); return count; } /******************************************************************* -fill a share mode entry + Del the share mode of a file for this process. Return the number + of entries left, and a memdup'ed copy of the entry deleted. ********************************************************************/ -static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type) + +ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse) { - share_mode_entry *e = (share_mode_entry *)p; - e->pid = sys_getpid(); - e->share_mode = fsp->share_mode; - e->op_port = port; - e->op_type = op_type; - memcpy((char *)&e->time, (char *)&fsp->open_time, sizeof(struct timeval)); + share_mode_entry entry; + + /* + * Fake up a share_mode_entry for comparisons. + */ + + fill_share_mode((char *)&entry, fsp, 0, 0); + return del_share_entry(fsp->dev, fsp->inode, &entry, ppse); } /******************************************************************* Set the share mode of a file. Return False on fail, True on success. ********************************************************************/ + BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) { TDB_DATA dbuf; struct locking_data *data; char *p=NULL; int size; + BOOL ret = True; /* read in the existing share modes if any */ dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); @@ -511,15 +564,18 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1; p = (char *)malloc(size); + if (!p) + return False; data = (struct locking_data *)p; data->num_share_mode_entries = 1; pstrcpy(p + sizeof(*data) + sizeof(share_mode_entry), fname); fill_share_mode(p + sizeof(*data), fsp, port, op_type); dbuf.dptr = p; dbuf.dsize = size; - tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) + ret = False; free(p); - return True; + return ret; } /* we're adding to an existing entry - this is a bit fiddly */ @@ -528,6 +584,8 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) data->num_share_mode_entries++; size = dbuf.dsize + sizeof(share_mode_entry); p = malloc(size); + if (!p) + return False; memcpy(p, dbuf.dptr, sizeof(*data)); fill_share_mode(p + sizeof(*data), fsp, port, op_type); memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data), @@ -535,15 +593,16 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) free(dbuf.dptr); dbuf.dptr = p; dbuf.dsize = size; - tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) + ret = False; free(p); - return True; + return ret; } - /******************************************************************* -a generic in-place modification call for share mode entries + A generic in-place modification call for share mode entries. ********************************************************************/ + static BOOL mod_share_mode(files_struct *fsp, void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), void *param) @@ -551,34 +610,39 @@ static BOOL mod_share_mode(files_struct *fsp, TDB_DATA dbuf; struct locking_data *data; int i; - share_mode_entry *shares; - pid_t pid = sys_getpid(); - int need_store=0; + share_mode_entry *shares, entry; + BOOL need_store=False; /* read in the existing share modes */ dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); - if (!dbuf.dptr) return False; + if (!dbuf.dptr) + return False; data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); + /* + * Fake up a share_mode_entry for comparisons. + */ + + fill_share_mode((char *)&entry, fsp, 0, 0); + /* find any with our pid and call the supplied function */ for (i=0;inum_share_mode_entries;i++) { - if (pid == shares[i].pid && - shares[i].share_mode == fsp->share_mode && - shares[i].time.tv_sec == fsp->open_time.tv_sec && - shares[i].time.tv_usec == fsp->open_time.tv_usec ) { + if (share_modes_identical(&entry, &shares[i])) { mod_fn(&shares[i], fsp->dev, fsp->inode, param); - need_store=1; + need_store=True; } } /* if the mod fn was called then store it back */ if (need_store) { if (data->num_share_mode_entries == 0) { - tdb_delete(tdb, locking_key_fsp(fsp)); + if (tdb_delete(tdb, locking_key_fsp(fsp)) == -1) + need_store = False; } else { - tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE); + if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) + need_store = False; } } @@ -586,11 +650,11 @@ static BOOL mod_share_mode(files_struct *fsp, return need_store; } - /******************************************************************* Static function that actually does the work for the generic function below. ********************************************************************/ + static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, void *param) { @@ -604,6 +668,7 @@ static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_I /******************************************************************* Remove an oplock port and mode entry from a share mode. ********************************************************************/ + BOOL remove_share_oplock(files_struct *fsp) { return mod_share_mode(fsp, remove_share_oplock_fn, NULL); @@ -613,6 +678,7 @@ BOOL remove_share_oplock(files_struct *fsp) Static function that actually does the work for the generic function below. ********************************************************************/ + static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, void *param) { @@ -624,6 +690,7 @@ static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SM /******************************************************************* Downgrade a oplock type from exclusive to level II. ********************************************************************/ + BOOL downgrade_share_oplock(files_struct *fsp) { return mod_share_mode(fsp, downgrade_share_oplock_fn, NULL); @@ -643,7 +710,8 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) /* read in the existing share modes */ dbuf = tdb_fetch(tdb, locking_key(dev, inode)); - if (!dbuf.dptr) return False; + if (!dbuf.dptr) + return False; data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); @@ -657,19 +725,21 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) /* store it back */ if (data->num_share_mode_entries) { - if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) + if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) { + free(dbuf.dptr); return False; + } } free(dbuf.dptr); return True; } - /**************************************************************************** -traverse the whole database with this function, calling traverse_callback -on each share mode + Traverse the whole database with this function, calling traverse_callback + on each share mode ****************************************************************************/ + static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state) { @@ -694,8 +764,10 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, Call the specified function on each entry under management by the share mode system. ********************************************************************/ + int share_mode_forall(SHAREMODE_FN(fn)) { - if (!tdb) return 0; + if (!tdb) + return 0; return tdb_traverse(tdb, traverse_fn, (void*)fn); } -- cgit From dd5378522539b913e140dd58f72b5eca1d61360a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Aug 2001 18:33:58 +0000 Subject: Missed uninitialized variable return for del_share_mode(). Jeremy. (This used to be commit e4a57fb45660b82eaec751f1b41f657a64d963fd) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4b037c0f3d..a9bcada026 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -472,7 +472,7 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, struct locking_data *data; int i, del_count=0; share_mode_entry *shares; - ssize_t count; + ssize_t count = 0; if (ppse) *ppse = NULL; -- cgit From e4275a35a64fde95a3b59307572d44c8d53909ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Aug 2001 00:29:40 +0000 Subject: Fixed the (incorrect) paranioa fix I put in for the fcntl lock spin. Don't delete a share mode that failed to remove the oplock (doh!), just set the oplock entry to zero.... Jeremy. (This used to be commit fe4aa720181a43f7a636ca029680fab0c836b968) --- source3/locking/locking.c | 52 +++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 17 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index a9bcada026..fea821baa1 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -451,7 +451,7 @@ static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_t and port info. ********************************************************************/ -static BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) +BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) { return (e1->pid == e2->pid && e1->share_mode == e2->share_mode && @@ -465,7 +465,7 @@ static BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) Ignore if no entry deleted. ********************************************************************/ -ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, +static ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry, share_mode_entry **ppse) { TDB_DATA dbuf; @@ -491,6 +491,8 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, * from the record. */ + DEBUG(10,("del_share_mode: num_share_modes = %d\n", data->num_share_mode_entries )); + for (i=0;inum_share_mode_entries;) { if (share_modes_identical(&shares[i], entry)) { if (ppse) @@ -499,6 +501,9 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, memmove(&shares[i], &shares[i+1], dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); del_count++; + + DEBUG(10,("del_share_mode: deleting entry %d\n", i )); + } else { i++; } @@ -603,34 +608,28 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) A generic in-place modification call for share mode entries. ********************************************************************/ -static BOOL mod_share_mode(files_struct *fsp, +static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry, void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), void *param) { TDB_DATA dbuf; struct locking_data *data; int i; - share_mode_entry *shares, entry; + share_mode_entry *shares; BOOL need_store=False; /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); + dbuf = tdb_fetch(tdb, locking_key(dev, inode)); if (!dbuf.dptr) return False; data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - /* - * Fake up a share_mode_entry for comparisons. - */ - - fill_share_mode((char *)&entry, fsp, 0, 0); - /* find any with our pid and call the supplied function */ for (i=0;inum_share_mode_entries;i++) { - if (share_modes_identical(&entry, &shares[i])) { - mod_fn(&shares[i], fsp->dev, fsp->inode, param); + if (share_modes_identical(entry, &shares[i])) { + mod_fn(&shares[i], dev, inode, param); need_store=True; } } @@ -638,10 +637,10 @@ static BOOL mod_share_mode(files_struct *fsp, /* if the mod fn was called then store it back */ if (need_store) { if (data->num_share_mode_entries == 0) { - if (tdb_delete(tdb, locking_key_fsp(fsp)) == -1) + if (tdb_delete(tdb, locking_key(dev, inode)) == -1) need_store = False; } else { - if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) + if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) need_store = False; } } @@ -671,7 +670,12 @@ static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_I BOOL remove_share_oplock(files_struct *fsp) { - return mod_share_mode(fsp, remove_share_oplock_fn, NULL); + share_mode_entry entry; + /* + * Fake up an entry for comparisons... + */ + fill_share_mode((char *)&entry, fsp, 0, 0); + return mod_share_mode(fsp->dev, fsp->inode, &entry, remove_share_oplock_fn, NULL); } /******************************************************************* @@ -693,7 +697,21 @@ static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SM BOOL downgrade_share_oplock(files_struct *fsp) { - return mod_share_mode(fsp, downgrade_share_oplock_fn, NULL); + share_mode_entry entry; + /* + * Fake up an entry for comparisons... + */ + fill_share_mode((char *)&entry, fsp, 0, 0); + return mod_share_mode(fsp->dev, fsp->inode, &entry, downgrade_share_oplock_fn, NULL); +} + +/******************************************************************* + Delete an exclusive share oplock owned by a defunct smbd.. +********************************************************************/ + +BOOL clear_share_entry(SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry) +{ + return mod_share_mode(dev, inode, entry, remove_share_oplock_fn, NULL); } /******************************************************************* -- cgit From 85e063f5b8b9ac872dc5e30da99b34230434df84 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Aug 2001 01:01:37 +0000 Subject: Tidyup fixes for fcntl spin problem. Jeremy. (This used to be commit 27d3dd0e7cb777ef6b21d6966c07045c2940fd37) --- source3/locking/locking.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index fea821baa1..80537c8bc1 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -299,7 +299,7 @@ BOOL locking_init(int read_only) return True; tdb = tdb_open_log(lock_path("locking.tdb"), - 0, TDB_CLEAR_IF_FIRST|USE_TDB_MMAP_FLAG, + 0, USE_TDB_MMAP_FLAG|(read_only?0x0:TDB_CLEAR_IF_FIRST), read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); @@ -365,18 +365,35 @@ static TDB_DATA locking_key_fsp(files_struct *fsp) return locking_key(fsp->dev, fsp->inode); } +#ifndef LOCK_SHARE_ENTRY_SPIN_COUNT +#define LOCK_SHARE_ENTRY_SPIN_COUNT 100 +#endif + /******************************************************************* Lock a hash bucket entry. ******************************************************************/ + BOOL lock_share_entry(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) { +#if 1 /* JRATEST */ + int count = 0; + for (count = 0; count < LOCK_SHARE_ENTRY_SPIN_COUNT; count++) + if (tdb_chainlock(tdb, locking_key(dev, inode)) == 0) + return True; + else + DEBUG(0,("lock_share_entry: locking (%d) for dev = %x, inode = %.0f failed with error %s\n", + count, (unsigned int)dev, (double)inode, strerror(errno) )); + return False; +#else return tdb_chainlock(tdb, locking_key(dev, inode)) == 0; +#endif } /******************************************************************* Unlock a hash bucket entry. ******************************************************************/ + void unlock_share_entry(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) { @@ -389,7 +406,18 @@ void unlock_share_entry(connection_struct *conn, BOOL lock_share_entry_fsp(files_struct *fsp) { +#if 1 /* JRATEST */ + int count = 0; + for (count = 0; count < LOCK_SHARE_ENTRY_SPIN_COUNT; count++) + if (tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0) + return True; + else + DEBUG(0,("lock_share_entry_fsp: locking (%d) for dev = %x, inode = %.0f failed with error %s\n", + count, (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno) )); + return False; +#else return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0; +#endif } /******************************************************************* @@ -465,7 +493,7 @@ BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) Ignore if no entry deleted. ********************************************************************/ -static ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, +ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry, share_mode_entry **ppse) { TDB_DATA dbuf; @@ -705,15 +733,6 @@ BOOL downgrade_share_oplock(files_struct *fsp) return mod_share_mode(fsp->dev, fsp->inode, &entry, downgrade_share_oplock_fn, NULL); } -/******************************************************************* - Delete an exclusive share oplock owned by a defunct smbd.. -********************************************************************/ - -BOOL clear_share_entry(SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry) -{ - return mod_share_mode(dev, inode, entry, remove_share_oplock_fn, NULL); -} - /******************************************************************* Get/Set the delete on close flag in a set of share modes. Return False on fail, True on success. -- cgit From 7874b0ac171449148a370f8c9da771efb591d0be Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 24 Aug 2001 04:55:28 +0000 Subject: 0 byte lock ranges ARE valid (This used to be commit 5498da6664a457e4d64502d37fa887dabd9baaa0) --- source3/locking/locking.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 80537c8bc1..81b2e92f68 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -108,12 +108,9 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, if (!lp_locking(SNUM(conn))) return(True); - if (count == 0) { - *eclass = ERRDOS; - *ecode = ERRnoaccess; - return False; - } - + /* NOTE! 0 byte long ranges ARE allowed and should be stored */ + + DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n", lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name )); -- cgit From c1598db18e2f9aafaa42bce833192bd5b83f5723 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 24 Aug 2001 21:09:38 +0000 Subject: we now have all but the dreaded 0/0 lock working (This used to be commit 98b6aef18c793187f392f944af516c8b9ebf86e9) --- source3/locking/brlock.c | 97 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 30 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index d22297a948..a642be317c 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -98,12 +98,37 @@ static BOOL brl_same_context(struct lock_context *ctx1, static BOOL brl_conflict(struct lock_struct *lck1, struct lock_struct *lck2) +{ + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) { + return False; + } + + if (brl_same_context(&lck1->context, &lck2->context) && + lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) { + return False; + } + + if (lck1->start >= (lck2->start + lck2->size) || + lck2->start >= (lck1->start + lck1->size)) { + return False; + } + + return True; +} + +/**************************************************************************** + Check to see if this lock conflicts, but ignore our own locks on the + same fnum only. +****************************************************************************/ + +static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck2) { if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) return False; if (brl_same_context(&lck1->context, &lck2->context) && - lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) return False; + lck1->fnum == lck2->fnum) + return False; if (lck1->start >= (lck2->start + lck2->size) || lck2->start >= (lck1->start + lck1->size)) return False; @@ -224,6 +249,13 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, dbuf.dptr = NULL; +#if 0 + if (start == 0 && size == 0) { + tdb_delete(tdb, kbuf); + return True; + } +#endif + tdb_chainlock(tdb, kbuf); dbuf = tdb_fetch(tdb, kbuf); @@ -246,6 +278,14 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, } } +#if 0 + if (start == 0 && size == 0) { + if (dbuf.dptr) free(dbuf.dptr); + tdb_chainunlock(tdb, kbuf); + return True; + } +#endif + /* no conflicts - add it to the list of locks */ tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*locks)); if (!tp) goto fail; @@ -296,21 +336,37 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, /* there are existing locks - find a match */ locks = (struct lock_struct *)dbuf.dptr; count = dbuf.dsize / sizeof(*locks); - for (i=0; icontext, &context)) { - DEBUG(10,("brl_unlock: Not same context. l_smbpid = %u, l_pid = %u, l_tid = %u: \ -smbpid = %u, pid = %u, tid = %u\n", - lock->context.smbpid, lock->context.pid, lock->context.tid, - context.smbpid, context.pid, context.tid )); + if (lock->lock_type == WRITE_LOCK && + brl_same_context(&lock->context, &context) && + lock->fnum == fnum && + lock->start == start && + lock->size == size) { + /* found it - delete it */ + if (count == 1) { + tdb_delete(tdb, kbuf); + } else { + if (i < count-1) { + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((count-1) - i)); + } + dbuf.dsize -= sizeof(*locks); + tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); + } + free(dbuf.dptr); + tdb_chainunlock(tdb, kbuf); + return True; } - /* JRATEST */ -#endif + } + + locks = (struct lock_struct *)dbuf.dptr; + count = dbuf.dsize / sizeof(*locks); + for (i=0; icontext, &context) && lock->fnum == fnum && @@ -342,25 +398,6 @@ smbpid = %u, pid = %u, tid = %u\n", return False; } -/**************************************************************************** - Check to see if this lock conflicts, but ignore our own locks on the - same fnum only. -****************************************************************************/ - -static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck2) -{ - if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) - return False; - - if (brl_same_context(&lck1->context, &lck2->context) && - lck1->fnum == lck2->fnum) - return False; - - if (lck1->start >= (lck2->start + lck2->size) || - lck2->start >= (lck1->start + lck1->size)) return False; - - return True; -} /**************************************************************************** Test if we could add a lock if we wanted to. -- cgit From 10c240ef977333e3ad0f340961c5d4a807d35144 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 26 Aug 2001 19:27:18 +0000 Subject: Don't use CLEAR_IF_FIRST if opening read-only. Jeremy. (This used to be commit f5ba19c12989dd1e996473869468afcfc5dce72e) --- source3/locking/brlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index a642be317c..dc2f39e7d9 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -201,7 +201,7 @@ void brl_init(int read_only) if (tdb) return; - tdb = tdb_open_log(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST|USE_TDB_MMAP_FLAG, + tdb = tdb_open_log(lock_path("brlock.tdb"), 0, USE_TDB_MMAP_FLAG|(read_only?0x0:TDB_CLEAR_IF_FIRST), read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); if (!tdb) { DEBUG(0,("Failed to open byte range locking database\n")); -- cgit From 4a3f07456d0a04b84916a99af6ce1cbe65e0370c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 26 Aug 2001 19:39:40 +0000 Subject: Ignore locks of length zero as they mean different things in Win32 and POSIX. Jeremy. (This used to be commit bd9cbf4c6883c1a39f28db8afa7cc0bd04b1b09f) --- source3/locking/posix.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 2a6f2be562..6a621200ca 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -107,10 +107,12 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(int)); if (!tp) { DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n")); - if (dbuf.dptr) free(dbuf.dptr); + if (dbuf.dptr) + free(dbuf.dptr); return False; - } - else dbuf.dptr = tp; + } else + dbuf.dptr = tp; + memcpy(dbuf.dptr + dbuf.dsize, &fsp->fd, sizeof(int)); dbuf.dsize += sizeof(int); @@ -378,8 +380,8 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s if (!tp) { DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); goto fail; - } - else dbuf.dptr = tp; + } else + dbuf.dptr = tp; memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl)); dbuf.dsize += sizeof(pl); @@ -579,6 +581,17 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, #endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + /* + * POSIX locks of length zero mean lock to end-of-file. + * Win32 locks of length zero are point probes. Ignore + * any Win32 locks of length zero. JRA. + */ + + if (count == (SMB_OFF_T)0) { + DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n")); + return False; + } + /* * If the given offset was > max_positive_lock_offset then we cannot map this at all * ignore this lock. -- cgit From e8e98c9ea0690e3acf1126b50882e59e1056c7b3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Aug 2001 08:19:43 +0000 Subject: converted smbd to use NTSTATUS by default major changes include: - added NSTATUS type - added automatic mapping between dos and nt error codes - changed all ERROR() calls to ERROR_DOS() and many to ERROR_NT() these calls auto-translate to the client error code system - got rid of the cached error code and the writebmpx code We eventually will need to also: - get rid of BOOL, so we don't lose error info - replace all ERROR_DOS() calls with ERROR_NT() calls but that is too much for one night (This used to be commit 83d9896c1ea8be796192b51a4678c2a3b87f7518) --- source3/locking/brlock.c | 71 +++++++++++++++++++++++++++++++++++++++-------- source3/locking/locking.c | 35 +++++++++-------------- 2 files changed, 73 insertions(+), 33 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index dc2f39e7d9..e21effe6eb 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -30,6 +30,8 @@ extern int DEBUGLEVEL; +#define ZERO_ZERO 0 + /* This contains elements that differentiate locks. The smbpid is a client supplied pid, and is essentially the locking context for this client */ @@ -116,6 +118,32 @@ static BOOL brl_conflict(struct lock_struct *lck1, return True; } +#if ZERO_ZERO +static BOOL brl_conflict1(struct lock_struct *lck1, + struct lock_struct *lck2) +{ + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) { + return False; + } + + if (brl_same_context(&lck1->context, &lck2->context) && + lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) { + return False; + } + + if (lck2->start == 0 && lck2->size == 0 && lck1->size != 0) { + return True; + } + + if (lck1->start >= (lck2->start + lck2->size) || + lck2->start >= (lck1->start + lck1->size)) { + return False; + } + + return True; +} +#endif + /**************************************************************************** Check to see if this lock conflicts, but ignore our own locks on the same fnum only. @@ -231,6 +259,21 @@ void brl_shutdown(int read_only) tdb_close(tdb); } +#if ZERO_ZERO +/**************************************************************************** +compare two locks for sorting +****************************************************************************/ +static int lock_compare(struct lock_struct *lck1, + struct lock_struct *lck2) +{ + if (lck1->start != lck2->start) return (lck1->start - lck2->start); + if (lck2->size != lck1->size) { + return ((int)lck1->size - (int)lck2->size); + } + return 0; +} +#endif + /**************************************************************************** Lock a range of bytes. ****************************************************************************/ @@ -249,10 +292,10 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, dbuf.dptr = NULL; -#if 0 +#if !ZERO_ZERO if (start == 0 && size == 0) { - tdb_delete(tdb, kbuf); - return True; + DEBUG(0,("client sent 0/0 lock - please report this\n")); + return False; } #endif @@ -275,23 +318,27 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, if (brl_conflict(&locks[i], &lock)) { goto fail; } +#if ZERO_ZERO + if (lock.start == 0 && lock.size == 0 && + locks[i].size == 0) { + break; + } +#endif } } -#if 0 - if (start == 0 && size == 0) { - if (dbuf.dptr) free(dbuf.dptr); - tdb_chainunlock(tdb, kbuf); - return True; - } -#endif - /* no conflicts - add it to the list of locks */ tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*locks)); if (!tp) goto fail; else dbuf.dptr = tp; memcpy(dbuf.dptr + dbuf.dsize, &lock, sizeof(lock)); dbuf.dsize += sizeof(lock); + +#if ZERO_ZERO + /* sort the lock list */ + qsort(dbuf.dptr, dbuf.dsize/sizeof(lock), sizeof(lock), lock_compare); +#endif + tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); free(dbuf.dptr); @@ -337,6 +384,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, locks = (struct lock_struct *)dbuf.dptr; count = dbuf.dsize / sizeof(*locks); +#if ZERO_ZERO for (i=0; ican_lock || (fsp->conn != conn)) { - *eclass = ERRDOS; - *ecode = ERRbadfid; - return False; + return NT_STATUS_INVALID_HANDLE; } DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", @@ -183,17 +176,15 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); - *eclass = ERRDOS; - *ecode = ERRnotlocked; - return False; + return NT_STATUS_LOCK_NOT_GRANTED; } if (!lp_posix_locking(SNUM(conn))) - return True; + return NT_STATUS_NOPROBLEMO; (void)release_posix_lock(fsp, offset, count); - return True; /* Did unlock */ + return NT_STATUS_NOPROBLEMO; /* Did unlock */ } /**************************************************************************** -- cgit From ee5f7237decfe446f4fdb08422beb2e6cb43af7f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Aug 2001 17:52:23 +0000 Subject: started converting NTSTATUS to be a structure on systems with gcc in order to make it type incompatible with BOOL so we catch errors sooner. This has already found a number of bugs (This used to be commit 1b778bc7d22efff3f90dc450eb12baa1241cf68f) --- source3/locking/locking.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d6915140a5..e905bd56e9 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -105,7 +105,7 @@ NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, BOOL ok = False; if (!lp_locking(SNUM(conn))) - return NT_STATUS_NOPROBLEMO; + return NT_STATUS(0); /* NOTE! 0 byte long ranges ARE allowed and should be stored */ @@ -156,10 +156,10 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, BOOL ok = False; if (!lp_locking(SNUM(conn))) - return NT_STATUS_NOPROBLEMO; + return NT_STATUS(0); if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) { - return NT_STATUS_INVALID_HANDLE; + return NT_STATUS(NT_STATUS_INVALID_HANDLE); } DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", @@ -176,15 +176,15 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); - return NT_STATUS_LOCK_NOT_GRANTED; + return NT_STATUS(NT_STATUS_LOCK_NOT_GRANTED); } if (!lp_posix_locking(SNUM(conn))) - return NT_STATUS_NOPROBLEMO; + return NT_STATUS(0); (void)release_posix_lock(fsp, offset, count); - return NT_STATUS_NOPROBLEMO; /* Did unlock */ + return NT_STATUS(0); } /**************************************************************************** -- cgit From b031af348c7dcc8c74bf49945211c466b8eca079 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Aug 2001 19:46:22 +0000 Subject: converted another bunch of stuff to NTSTATUS (This used to be commit 1d36250e338ae0ff9fbbf86019809205dd97d05e) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e905bd56e9..4928d6d160 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -143,7 +143,7 @@ NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, if (!ok) return NT_STATUS_FILE_LOCK_CONFLICT; - return NT_STATUS_NOPROBLEMO; /* Got lock */ + return NT_STATUS_OK; /* Got lock */ } /**************************************************************************** -- cgit From 19fea3242cf6234786b6cbb60631e0071f31ff9f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 Sep 2001 07:13:01 +0000 Subject: the next stage in the NTSTATUS/WERROR change. smbd and nmbd now compile, but the client code still needs some work (This used to be commit dcd6e735f709a9231860ceb9682db40ff26c9a66) --- source3/locking/locking.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4928d6d160..1ed238f4d8 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -105,7 +105,7 @@ NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, BOOL ok = False; if (!lp_locking(SNUM(conn))) - return NT_STATUS(0); + return NT_STATUS_OK; /* NOTE! 0 byte long ranges ARE allowed and should be stored */ @@ -156,10 +156,10 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, BOOL ok = False; if (!lp_locking(SNUM(conn))) - return NT_STATUS(0); + return NT_STATUS_OK; if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) { - return NT_STATUS(NT_STATUS_INVALID_HANDLE); + return NT_STATUS_INVALID_HANDLE; } DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", @@ -176,15 +176,15 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); - return NT_STATUS(NT_STATUS_LOCK_NOT_GRANTED); + return NT_STATUS_LOCK_NOT_GRANTED; } if (!lp_posix_locking(SNUM(conn))) - return NT_STATUS(0); + return NT_STATUS_OK; (void)release_posix_lock(fsp, offset, count); - return NT_STATUS(0); + return NT_STATUS_OK; } /**************************************************************************** -- cgit From d3518f1d8a63cab323a9c5c94d5eb552302b4df6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Sep 2001 00:05:07 +0000 Subject: NFS v2 can return ENOLCK when greater than 31 bit offsets are used. Treat this the same as an EFBIG error. Jeremy (This used to be commit 8fad5177701c1738a7f5bdd7c0082ef23a00b876) --- source3/locking/posix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 6a621200ca..b2ffbeda8f 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -705,10 +705,10 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); - if (!ret && (errno == EFBIG)) { + if (!ret && ((errno == EFBIG) || (errno == ENOLCK))) { if( DEBUGLVL( 0 )) { dbgtext("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count); - dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n"); + dbgtext("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)); dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n"); } /* 32 bit NFS file system, retry with smaller offset */ -- cgit From 4f0509aeeb0e1a8ff6b962985e4468e94dab8273 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Sep 2001 21:39:43 +0000 Subject: 2nd DELETE_ON_CLOSE_FLAG fix ... we set the DELETE_ON_CLOSE_FLAG on all share modes on the file, which means the share mode in the fsp will not match the one in the tdb when we come to close for other file handles, which means we end up with share modes on files after all handles are closed fixed by making the comparison function that says if two shares modes are equal ignore the DELETE_ON_CLOSE_FLAG (This used to be commit 7b39c4c59897669106d7129bad8af3d592d25838) --- source3/locking/locking.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 1ed238f4d8..d2bfc08dd3 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -470,9 +470,9 @@ static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_t BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) { return (e1->pid == e2->pid && - e1->share_mode == e2->share_mode && - e1->time.tv_sec == e2->time.tv_sec && - e1->time.tv_usec == e2->time.tv_usec ); + (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) == (e2->share_mode & ~DELETE_ON_CLOSE_FLAG) && + e1->time.tv_sec == e2->time.tv_sec && + e1->time.tv_usec == e2->time.tv_usec ); } /******************************************************************* -- cgit From 9ef7a6c7865c14480139188c30744914c5b7af43 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Sep 2001 01:19:35 +0000 Subject: use NTSTATUS not BOOL in do_lock() (This used to be commit b1b2a5fa5d084dad8ae47777419ab75db1e51eff) --- source3/locking/brlock.c | 24 +++++++++++++++--------- source3/locking/locking.c | 21 +++++++++------------ 2 files changed, 24 insertions(+), 21 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index e21effe6eb..f4c41d0349 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -278,15 +278,16 @@ static int lock_compare(struct lock_struct *lck1, Lock a range of bytes. ****************************************************************************/ -BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, - uint16 smbpid, pid_t pid, uint16 tid, - br_off start, br_off size, - enum brl_type lock_type) +NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, + uint16 smbpid, pid_t pid, uint16 tid, + br_off start, br_off size, + enum brl_type lock_type) { TDB_DATA kbuf, dbuf; int count, i; struct lock_struct lock, *locks; char *tp; + NTSTATUS status = NT_STATUS_OK; kbuf = locking_key(dev,ino); @@ -295,7 +296,7 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, #if !ZERO_ZERO if (start == 0 && size == 0) { DEBUG(0,("client sent 0/0 lock - please report this\n")); - return False; + return NT_STATUS_INVALID_PARAMETER; } #endif @@ -316,6 +317,7 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, count = dbuf.dsize / sizeof(*locks); for (i=0; ifsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - ok = brl_lock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, sys_getpid(), conn->cnum, - offset, count, - lock_type); + status = brl_lock(fsp->dev, fsp->inode, fsp->fnum, + lock_pid, sys_getpid(), conn->cnum, + offset, count, + lock_type); - if (ok && lp_posix_locking(SNUM(conn))) { + if (NT_STATUS_IS_OK(status) && lp_posix_locking(SNUM(conn))) { /* * Try and get a POSIX lock on this range. @@ -127,9 +127,8 @@ NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, * overlapping on a different fd. JRA. */ - ok = set_posix_lock(fsp, offset, count, lock_type); - - if (!ok) { + if (!set_posix_lock(fsp, offset, count, lock_type)) { + status = NT_STATUS_LOCK_NOT_GRANTED; /* * We failed to map - we must now remove the brl * lock entry. @@ -141,9 +140,7 @@ NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, } } - if (!ok) return NT_STATUS_FILE_LOCK_CONFLICT; - - return NT_STATUS_OK; /* Got lock */ + return status; } /**************************************************************************** -- cgit From 9a9ac2739bbdc993ecdfa78298bdd9c059328378 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Sep 2001 22:08:19 +0000 Subject: got rid of USE_TDB_MMAP_FLAG as its not needed any more (This used to be commit c26e0d3f27a05ecc8bd2390f9aab7f9451524e47) --- source3/locking/brlock.c | 2 +- source3/locking/locking.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index f4c41d0349..2b21761cb2 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -229,7 +229,7 @@ void brl_init(int read_only) if (tdb) return; - tdb = tdb_open_log(lock_path("brlock.tdb"), 0, USE_TDB_MMAP_FLAG|(read_only?0x0:TDB_CLEAR_IF_FIRST), + tdb = tdb_open_log(lock_path("brlock.tdb"), 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); if (!tdb) { DEBUG(0,("Failed to open byte range locking database\n")); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index a1e4ba6d6c..4092c989d0 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -284,7 +284,7 @@ BOOL locking_init(int read_only) return True; tdb = tdb_open_log(lock_path("locking.tdb"), - 0, USE_TDB_MMAP_FLAG|(read_only?0x0:TDB_CLEAR_IF_FIRST), + 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); -- cgit From 83ebf2b6b282926930dc2c5dee3b5f18447d6e81 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Sep 2001 22:43:21 +0000 Subject: Fix the 62bit locking onto 32 bit NFS mounts problem generically for HPUX. Don. please check this out. Jeremy. (This used to be commit ce9f95996498f7795aaef069e1443ea1c7d524b3) --- source3/locking/posix.c | 115 +++++++++--------------------------------------- 1 file changed, 21 insertions(+), 94 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index b2ffbeda8f..eb5e4b6460 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -649,38 +649,6 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, return True; } -/**************************************************************************** - Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). -****************************************************************************/ - -uint32 map_lock_offset(uint32 high, uint32 low) -{ - unsigned int i; - uint32 mask = 0; - uint32 highcopy = high; - - /* - * Try and find out how many significant bits there are in high. - */ - - for(i = 0; highcopy; i++) - highcopy >>= 1; - - /* - * We use 31 bits not 32 here as POSIX - * lock offsets may not be negative. - */ - - mask = (~0) << (31 - i); - - if(low & mask) - return 0; /* Fail. */ - - high <<= (31 - i); - - return (high|low); -} - /**************************************************************************** Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and broken NFS implementations. @@ -691,80 +659,39 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF int ret; struct connection_struct *conn = fsp->conn; -#if defined(LARGE_SMB_OFF_T) - /* - * In the 64 bit locking case we store the original - * values in case we have to map to a 32 bit lock on - * a filesystem that doesn't support 64 bit locks. - */ - SMB_OFF_T orig_offset = offset; - SMB_OFF_T orig_count = count; -#endif /* LARGE_SMB_OFF_T */ - DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fd,op,(double)offset,(double)count,type)); ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); - if (!ret && ((errno == EFBIG) || (errno == ENOLCK))) { - if( DEBUGLVL( 0 )) { - dbgtext("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count); - dbgtext("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)); - dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n"); - } - /* 32 bit NFS file system, retry with smaller offset */ - errno = 0; - count &= 0x7fffffff; - ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); - } + if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { - /* A lock query - just return. */ - if (op == SMB_F_GETLK) - return ret; + DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", + (double)offset,(double)count)); + DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); + DEBUG(0,("on 32 bit NFS mounted file systems.\n")); - /* A lock set or unset. */ - if (!ret) { - DEBUG(3,("posix_fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n", - (double)offset,(double)count,op,type,strerror(errno))); + /* + * If the offset is > 0x7FFFFFFF then this will cause problems on + * 32 bit NFS mounted filesystems. Just ignore it. + */ - /* Perhaps it doesn't support this sort of locking ? */ - if (errno == EINVAL) { -#if defined(LARGE_SMB_OFF_T) - { - /* - * Ok - if we get here then we have a 64 bit lock request - * that has returned EINVAL. Try and map to 31 bits for offset - * and length and try again. This may happen if a filesystem - * doesn't support 64 bit offsets (efs/ufs) although the underlying - * OS does. - */ - uint32 off_low = (orig_offset & 0xFFFFFFFF); - uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF); - - count = (orig_count & 0x7FFFFFFF); - offset = (SMB_OFF_T)map_lock_offset(off_high, off_low); - ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); - if (!ret) { - if (errno == EINVAL) { - DEBUG(3,("posix_fcntl_lock: locking not supported? returning True\n")); - return(True); - } - return False; - } - DEBUG(3,("posix_fcntl_lock: 64 -> 32 bit modified lock call successful\n")); - return True; - } -#else /* LARGE_SMB_OFF_T */ - DEBUG(3,("locking not supported? returning True\n")); - return(True); -#endif /* LARGE_SMB_OFF_T */ + if (offset & ~((SMB_OFF_T)0x7fffffff)) { + DEBUG(0,("Offset greater than 31 bits. Returning success.\n")); + return True; } - return(False); + if (count & ~((SMB_OFF_T)0x7fffffff)) { + /* 32 bit NFS file system, retry with smaller offset */ + DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); + errno = 0; + count &= 0x7fffffff; + ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); + } } - DEBUG(8,("posix_fcntl_lock: Lock call successful\n")); + DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed")); - return(True); + return ret; } /**************************************************************************** -- cgit From 81fdc3c3f76075babe3e1f4bf43ed2cfd5723472 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 17 Sep 2001 04:16:35 +0000 Subject: move to SAFE_FREE() (This used to be commit e61aec84edaf55b9ee087b076d2f1311033dc839) --- source3/locking/brlock.c | 16 ++++++++-------- source3/locking/locking.c | 16 ++++++++-------- source3/locking/posix.c | 38 +++++++++++++++----------------------- 3 files changed, 31 insertions(+), 39 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 2b21761cb2..b16cc539c8 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -347,12 +347,12 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); return NT_STATUS_OK; fail: - if (dbuf.dptr) free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); return status; } @@ -411,7 +411,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); } - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); return True; } @@ -439,7 +439,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); } - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); return True; } @@ -448,7 +448,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, /* we didn't find it */ fail: - if (dbuf.dptr) free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); return False; } @@ -501,12 +501,12 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, } /* no conflicts - we could have added it */ - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); return True; fail: - if (dbuf.dptr) free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); return False; } @@ -559,7 +559,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) /* we didn't find it */ fail: - if (dbuf.dptr) free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4092c989d0..750ebe6716 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -436,7 +436,7 @@ int get_share_modes(connection_struct *conn, ret = data->num_share_mode_entries; if(ret) *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares)); - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); if (! *shares) return 0; @@ -537,7 +537,7 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, count = -1; } } - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return count; } @@ -592,7 +592,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) dbuf.dsize = size; if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) ret = False; - free(p); + SAFE_FREE(p); return ret; } @@ -608,12 +608,12 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) fill_share_mode(p + sizeof(*data), fsp, port, op_type); memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data), dbuf.dsize - sizeof(*data)); - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); dbuf.dptr = p; dbuf.dsize = size; if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) ret = False; - free(p); + SAFE_FREE(p); return ret; } @@ -658,7 +658,7 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en } } - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return need_store; } @@ -748,12 +748,12 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) /* store it back */ if (data->num_share_mode_entries) { if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) { - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return False; } } - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return True; } diff --git a/source3/locking/posix.c b/source3/locking/posix.c index eb5e4b6460..8fbe2e2fda 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -107,8 +107,7 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(int)); if (!tp) { DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n")); - if (dbuf.dptr) - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return False; } else dbuf.dptr = tp; @@ -120,7 +119,7 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n")); } - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return True; } @@ -240,17 +239,16 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) */ if (!add_fd_to_close_entry(fsp)) { - free((char *)entries); + SAFE_FREE(entries); return False; } - free((char *)entries); + SAFE_FREE(entries); fsp->fd = -1; return 0; } - if(entries) - free((char *)entries); + SAFE_FREE(entries); /* * No outstanding POSIX locks. Get the pending close fd's @@ -276,8 +274,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) delete_close_entries(fsp); } - if (fd_array) - free((char *)fd_array); + SAFE_FREE(fd_array); /* * Finally close the fd associated with this fsp. @@ -338,13 +335,12 @@ static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry) tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); } - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return True; fail: - if (dbuf.dptr) - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return False; } @@ -391,7 +387,7 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s goto fail; } - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n", fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, @@ -400,8 +396,7 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s return True; fail: - if (dbuf.dptr) - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return False; } @@ -499,14 +494,12 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, (unsigned int)num_overlapping_records )); - if (dbuf.dptr) - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return num_overlapping_records; fail: - if (dbuf.dptr) - free(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return -1; } @@ -955,8 +948,7 @@ lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size, } /* end for ( l_curr = lhead; l_curr;) */ } /* end for (i=0; ifsp_name, (unsigned int)count )); - free((char *)entries); + SAFE_FREE(entries); delete_posix_lock_entries(fsp); return; } @@ -1281,7 +1273,7 @@ void posix_locking_close_file(files_struct *fsp) if (pl->fd == fsp->fd) release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size ); } - free((char *)entries); + SAFE_FREE(entries); } /******************************************************************* -- cgit From 36a6611da2820da3635a8158dd26f41732b5b4fd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Sep 2001 06:20:28 +0000 Subject: Use structure copy to fix unaligned accesses on 64bit architectures on Linux. Jeremy. (This used to be commit b4b891279b6292237113456f1bb0d4393f1f9af1) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 750ebe6716..a942965684 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -456,7 +456,7 @@ static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_t e->share_mode = fsp->share_mode; e->op_port = port; e->op_type = op_type; - memcpy((char *)&e->time, (char *)&fsp->open_time, sizeof(struct timeval)); + e->time = fsp->open_time; } /******************************************************************* -- cgit From 5bc82e443b2da885aa0a504906789c006b3cf17a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Sep 2001 06:41:29 +0000 Subject: Correct fix for unaligned memcpy - malloc'ed memory incremented by sizeof(struct locking_data) was not forced to be 8 byte aligned. Use union to force it to be correctly aligned for memcpy and use void *, to tell compiler not to optimize aligned copy (this last fix suggested by Trond @ RedHat). The first fix should be sufficient, but this provides a "belt and braces" fix. Jeremy. (This used to be commit 22c5915bb466529ac1bcb5c2574888b360a9775b) --- source3/locking/locking.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index a942965684..23766f41dc 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -231,7 +231,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - for (i=0;inum_share_mode_entries;) { + for (i=0;iu.num_share_mode_entries;) { if (check_self && (shares[i].pid == mypid)) { DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n", @@ -245,7 +245,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat continue; } - data->num_share_mode_entries--; + data->u.num_share_mode_entries--; memmove(&shares[i], &shares[i+1], dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); del_count++; @@ -256,7 +256,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat dbuf.dsize -= del_count * sizeof(*shares); /* store it back in the database */ - if (data->num_share_mode_entries == 0) { + if (data->u.num_share_mode_entries == 0) { if (tdb_delete(ttdb, kbuf) == -1) ret = -1; } else { @@ -433,7 +433,7 @@ int get_share_modes(connection_struct *conn, return 0; data = (struct locking_data *)dbuf.dptr; - ret = data->num_share_mode_entries; + ret = data->u.num_share_mode_entries; if(ret) *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares)); SAFE_FREE(dbuf.dptr); @@ -451,12 +451,14 @@ int get_share_modes(connection_struct *conn, static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type) { share_mode_entry *e = (share_mode_entry *)p; + void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */ + memset(e, '\0', sizeof(share_mode_entry)); e->pid = sys_getpid(); e->share_mode = fsp->share_mode; e->op_port = port; e->op_type = op_type; - e->time = fsp->open_time; + memcpy(x, &fsp->open_time, sizeof(struct timeval)); } /******************************************************************* @@ -504,13 +506,13 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, * from the record. */ - DEBUG(10,("del_share_mode: num_share_modes = %d\n", data->num_share_mode_entries )); + DEBUG(10,("del_share_mode: num_share_modes = %d\n", data->u.num_share_mode_entries )); - for (i=0;inum_share_mode_entries;) { + for (i=0;iu.num_share_mode_entries;) { if (share_modes_identical(&shares[i], entry)) { if (ppse) *ppse = memdup(&shares[i], sizeof(*shares)); - data->num_share_mode_entries--; + data->u.num_share_mode_entries--; memmove(&shares[i], &shares[i+1], dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); del_count++; @@ -526,10 +528,10 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, /* the record may have shrunk a bit */ dbuf.dsize -= del_count * sizeof(*shares); - count = (ssize_t)data->num_share_mode_entries; + count = (ssize_t)data->u.num_share_mode_entries; /* store it back in the database */ - if (data->num_share_mode_entries == 0) { + if (data->u.num_share_mode_entries == 0) { if (tdb_delete(tdb, locking_key(dev, inode)) == -1) count = -1; } else { @@ -585,7 +587,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) if (!p) return False; data = (struct locking_data *)p; - data->num_share_mode_entries = 1; + data->u.num_share_mode_entries = 1; pstrcpy(p + sizeof(*data) + sizeof(share_mode_entry), fname); fill_share_mode(p + sizeof(*data), fsp, port, op_type); dbuf.dptr = p; @@ -599,7 +601,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) /* we're adding to an existing entry - this is a bit fiddly */ data = (struct locking_data *)dbuf.dptr; - data->num_share_mode_entries++; + data->u.num_share_mode_entries++; size = dbuf.dsize + sizeof(share_mode_entry); p = malloc(size); if (!p) @@ -640,7 +642,7 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); /* find any with our pid and call the supplied function */ - for (i=0;inum_share_mode_entries;i++) { + for (i=0;iu.num_share_mode_entries;i++) { if (share_modes_identical(entry, &shares[i])) { mod_fn(&shares[i], dev, inode, param); need_store=True; @@ -649,7 +651,7 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en /* if the mod fn was called then store it back */ if (need_store) { - if (data->num_share_mode_entries == 0) { + if (data->u.num_share_mode_entries == 0) { if (tdb_delete(tdb, locking_key(dev, inode)) == -1) need_store = False; } else { @@ -739,14 +741,14 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); /* Set/Unset the delete on close element. */ - for (i=0;inum_share_mode_entries;i++,shares++) { + for (i=0;iu.num_share_mode_entries;i++,shares++) { shares->share_mode = (delete_on_close ? (shares->share_mode | DELETE_ON_CLOSE_FLAG) : (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) ); } /* store it back */ - if (data->num_share_mode_entries) { + if (data->u.num_share_mode_entries) { if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) { SAFE_FREE(dbuf.dptr); return False; @@ -774,9 +776,9 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - name = dbuf.dptr + sizeof(*data) + data->num_share_mode_entries*sizeof(*shares); + name = dbuf.dptr + sizeof(*data) + data->u.num_share_mode_entries*sizeof(*shares); - for (i=0;inum_share_mode_entries;i++) { + for (i=0;iu.num_share_mode_entries;i++) { traverse_callback(&shares[i], name); } return 0; -- cgit From 8c8b9c69e5c92c6e18710af33c7851c2fb8913d3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Sep 2001 06:49:02 +0000 Subject: Removed test code that got added by accident. Jeremy. (This used to be commit fc91ecc236e0d27f5836e9820332ababd762f1a7) --- source3/locking/locking.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 23766f41dc..db0de5bb3f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -361,18 +361,7 @@ static TDB_DATA locking_key_fsp(files_struct *fsp) BOOL lock_share_entry(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) { -#if 1 /* JRATEST */ - int count = 0; - for (count = 0; count < LOCK_SHARE_ENTRY_SPIN_COUNT; count++) - if (tdb_chainlock(tdb, locking_key(dev, inode)) == 0) - return True; - else - DEBUG(0,("lock_share_entry: locking (%d) for dev = %x, inode = %.0f failed with error %s\n", - count, (unsigned int)dev, (double)inode, strerror(errno) )); - return False; -#else return tdb_chainlock(tdb, locking_key(dev, inode)) == 0; -#endif } /******************************************************************* @@ -391,18 +380,7 @@ void unlock_share_entry(connection_struct *conn, BOOL lock_share_entry_fsp(files_struct *fsp) { -#if 1 /* JRATEST */ - int count = 0; - for (count = 0; count < LOCK_SHARE_ENTRY_SPIN_COUNT; count++) - if (tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0) - return True; - else - DEBUG(0,("lock_share_entry_fsp: locking (%d) for dev = %x, inode = %.0f failed with error %s\n", - count, (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno) )); - return False; -#else return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0; -#endif } /******************************************************************* -- cgit From dc1fc3ee8ec2199bc73bb5d7ec711c6800f61d65 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 2 Oct 2001 04:29:50 +0000 Subject: Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header. (This used to be commit 2d0922b0eabfdc0aaf1d0797482fef47ed7fde8e) --- source3/locking/brlock.c | 2 -- source3/locking/locking.c | 1 - source3/locking/posix.c | 1 - 3 files changed, 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index b16cc539c8..cbf98c46a5 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -28,8 +28,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - #define ZERO_ZERO 0 /* This contains elements that differentiate locks. The smbpid is a diff --git a/source3/locking/locking.c b/source3/locking/locking.c index db0de5bb3f..70995da3e2 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -36,7 +36,6 @@ */ #include "includes.h" -extern int DEBUGLEVEL; uint16 global_smbpid; /* the locking database handle */ diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 8fbe2e2fda..8b3538d8ca 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -24,7 +24,6 @@ */ #include "includes.h" -extern int DEBUGLEVEL; /* * The POSIX locking database handle. -- cgit From 07f54cb59270e2c3168ab2bb3e73e7a8d8563843 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Oct 2001 23:56:21 +0000 Subject: Ensure we mask off deny modes correctly on being set (this shouldn't have caused problems but is tidier). Fix debug statement in locking.c Jeremy. (This used to be commit eac6bbd24ebf00b35e50953bc11186111dc39059) --- source3/locking/locking.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 70995da3e2..ca57bd6b8f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -483,7 +483,7 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, * from the record. */ - DEBUG(10,("del_share_mode: num_share_modes = %d\n", data->u.num_share_mode_entries )); + DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.num_share_mode_entries )); for (i=0;iu.num_share_mode_entries;) { if (share_modes_identical(&shares[i], entry)) { @@ -494,7 +494,7 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); del_count++; - DEBUG(10,("del_share_mode: deleting entry %d\n", i )); + DEBUG(10,("del_share_entry: deleting entry %d\n", i )); } else { i++; -- cgit From 88b55f47b4914f7d390939e4394ec3edd42be91f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 20 Oct 2001 21:59:34 +0000 Subject: Move from timestamp to gen count file id's for finding oplocked files in a tdb. Jeremy. (This used to be commit 058ae6b58f61ef46013dd076af3a84de5fbaaab1) --- source3/locking/locking.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index ca57bd6b8f..b551d8c6d6 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -349,10 +349,6 @@ static TDB_DATA locking_key_fsp(files_struct *fsp) return locking_key(fsp->dev, fsp->inode); } -#ifndef LOCK_SHARE_ENTRY_SPIN_COUNT -#define LOCK_SHARE_ENTRY_SPIN_COUNT 100 -#endif - /******************************************************************* Lock a hash bucket entry. ******************************************************************/ @@ -436,6 +432,9 @@ static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_t e->op_port = port; e->op_type = op_type; memcpy(x, &fsp->open_time, sizeof(struct timeval)); + e->share_file_id = fsp->file_id; + e->dev = fsp->dev; + e->inode = fsp->inode; } /******************************************************************* @@ -445,10 +444,24 @@ static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_t BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) { +#if 1 /* JRA PARANOIA TEST - REMOVE LATER */ + if (e1->pid == e2->pid && + e1->share_file_id == e2->share_file_id && + e1->dev == e2->dev && + e1->inode == e2->inode && + (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) != (e2->share_mode & ~DELETE_ON_CLOSE_FLAG)) { + DEBUG(0,("PANIC: share_modes_identical: share_mode missmatch (e1 = %u, e2 = %u). Logic error.\n", + (unsigned int)(e1->share_mode & ~DELETE_ON_CLOSE_FLAG), + (unsigned int)(e2->share_mode & ~DELETE_ON_CLOSE_FLAG) )); + smb_panic("PANIC: share_modes_identical logic error.\n"); + } +#endif + return (e1->pid == e2->pid && (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) == (e2->share_mode & ~DELETE_ON_CLOSE_FLAG) && - e1->time.tv_sec == e2->time.tv_sec && - e1->time.tv_usec == e2->time.tv_usec ); + e1->dev == e2->dev && + e1->inode == e2->inode && + e1->share_file_id == e2->share_file_id ); } /******************************************************************* -- cgit From e5c5adb197b29b729598a74929558cc5fcd37ce9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Nov 2001 04:00:35 +0000 Subject: Don't scan locking db on closedown. Jeremy. (This used to be commit 59cfcd8a6c510204ac059a0d2fddc2fa17199f82) --- source3/locking/locking.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index b551d8c6d6..023ec59e89 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -310,15 +310,19 @@ BOOL locking_init(int read_only) BOOL locking_end(void) { +#if 0 BOOL check_self = True; +#endif brl_shutdown(open_read_only); if (tdb) { /* delete any dead locks */ +#if 0 /* Don't scan on close. */ if (!open_read_only) tdb_traverse(tdb, delete_fn, &check_self); +#endif if (tdb_close(tdb) != 0) return False; -- cgit From 9e88a7ebe9b37d642241f404fb4867ee0239cf6f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Nov 2001 01:59:03 +0000 Subject: After conversations with Andrew, improved the robustness of the sharemode db in the following way. Originally, on startup and shutdown, smbd would scan the share mode db to ensure it was correct. This lead to scalability issues as scans lock the db for quite a long time. Andrew had the brainstorm that we only care about the record we're about to read. This new code (small change really, but quite significant) causes get_share_modes() to do a process_exists() call against each pid in each record, and to delete any that don't and re-write the entry if any dead records were detected. This allowed me to remove the startup/shutdown scans of the db (they can be added into smbstatus if anyone really cares to have them back). This will please the vfs author who was worried about the time taken on open() calls, and will lead to much greater robustness and scalability in the share mode db. We need much testing of this, and also netbench tests to ensure the extra process_exists() calls don't hurt performance (they shouldn't it's a very simple system call). Jeremy. (This used to be commit 4098d442030e66601450baeb09ae06b39a1ab571) --- source3/locking/locking.c | 79 +++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 26 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 023ec59e89..8a8a33b808 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -275,8 +275,6 @@ static int open_read_only; BOOL locking_init(int read_only) { - BOOL check_self = False; - brl_init(read_only); if (tdb) @@ -295,10 +293,6 @@ BOOL locking_init(int read_only) if (!posix_locking_init(read_only)) return False; - /* delete any dead locks */ - if (!read_only) - tdb_traverse(tdb, delete_fn, &check_self); - open_read_only = read_only; return True; @@ -310,20 +304,10 @@ BOOL locking_init(int read_only) BOOL locking_end(void) { -#if 0 - BOOL check_self = True; -#endif brl_shutdown(open_read_only); if (tdb) { - /* delete any dead locks */ - -#if 0 /* Don't scan on close. */ - if (!open_read_only) - tdb_traverse(tdb, delete_fn, &check_self); -#endif - if (tdb_close(tdb) != 0) return False; } @@ -397,28 +381,71 @@ void unlock_share_entry_fsp(files_struct *fsp) int get_share_modes(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry **shares) + share_mode_entry **pp_shares) { TDB_DATA dbuf; struct locking_data *data; - int ret; + int num_share_modes; + share_mode_entry *shares = NULL; - *shares = NULL; + *pp_shares = NULL; dbuf = tdb_fetch(tdb, locking_key(dev, inode)); if (!dbuf.dptr) return 0; data = (struct locking_data *)dbuf.dptr; - ret = data->u.num_share_mode_entries; - if(ret) - *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares)); - SAFE_FREE(dbuf.dptr); + num_share_modes = data->u.num_share_mode_entries; + if(num_share_modes) { + int i; + int del_count = 0; - if (! *shares) - return 0; + shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), + num_share_modes * sizeof(share_mode_entry)); - return ret; + if (!shares) { + SAFE_FREE(dbuf.dptr); + return 0; + } + + /* + * Ensure that each entry has a real process attached. + */ + + for (i = 0; i < num_share_modes; ) { + share_mode_entry *entry_p = &shares[i]; + if (process_exists(entry_p->pid)) + i++; + else { + memcpy( &shares[i], &shares[i+1], + sizeof(share_mode_entry) * (num_share_modes - i - 1)); + num_share_modes--; + del_count++; + } + } + + /* Did we delete any ? If so, re-store in tdb. */ + if (del_count) { + data->u.num_share_mode_entries = num_share_modes; + + if (num_share_modes) + memcpy(dbuf.dptr + sizeof(*data), shares, + num_share_modes * sizeof(share_mode_entry)); + + /* The record has shrunk a bit */ + dbuf.dsize -= del_count * sizeof(share_mode_entry); + + if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) { + SAFE_FREE(shares); + SAFE_FREE(dbuf.dptr); + return 0; + } + } + } + + SAFE_FREE(dbuf.dptr); + *pp_shares = shares; + return num_share_modes; } /******************************************************************* -- cgit From 95a4903b20b892c461198dd1dff77ccca159d2ca Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 18 Dec 2001 05:04:09 +0000 Subject: Removed unused function, delete_fn() (This used to be commit f26e8205cff63967b9c1659b8e6ad71cbe36dace) --- source3/locking/locking.c | 57 ----------------------------------------------- 1 file changed, 57 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8a8a33b808..cb523532d8 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -210,63 +210,6 @@ void locking_close_file(files_struct *fsp) } } -/**************************************************************************** - Delete a record if it is for a dead process, if check_self is true, then - delete any records belonging to this pid also (there shouldn't be any). - This function is only called on locking startup and shutdown. -****************************************************************************/ - -static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) -{ - struct locking_data *data; - share_mode_entry *shares; - int i, del_count=0; - pid_t mypid = sys_getpid(); - BOOL check_self = *(BOOL *)state; - int ret = 0; - - tdb_chainlock(tdb, kbuf); - - data = (struct locking_data *)dbuf.dptr; - shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - - for (i=0;iu.num_share_mode_entries;) { - - if (check_self && (shares[i].pid == mypid)) { - DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n", - (unsigned int)shares[i].pid )); - } else if (!process_exists(shares[i].pid)) { - DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Entry for pid %u and it no longer exists !\n", - (unsigned int)shares[i].pid )); - } else { - /* Process exists, leave this record alone. */ - i++; - continue; - } - - data->u.num_share_mode_entries--; - memmove(&shares[i], &shares[i+1], - dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); - del_count++; - - } - - /* the record has shrunk a bit */ - dbuf.dsize -= del_count * sizeof(*shares); - - /* store it back in the database */ - if (data->u.num_share_mode_entries == 0) { - if (tdb_delete(ttdb, kbuf) == -1) - ret = -1; - } else { - if (tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE) == -1) - ret = -1; - } - - tdb_chainunlock(tdb, kbuf); - return ret; -} - /**************************************************************************** Initialise the locking functions. ****************************************************************************/ -- cgit From 86b3aeb42a32a767e6411a730526d67472273c6f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 5 Jan 2002 02:37:23 +0000 Subject: Added DEBUG in set_share_mode to track down logic insanity. Jeremy. (This used to be commit 32f4f3a45d473b3be1ae07f6c60897c12323d60c) --- source3/locking/locking.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index cb523532d8..0eca0b61bc 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -552,6 +552,10 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) return False; data = (struct locking_data *)p; data->u.num_share_mode_entries = 1; + + DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n", + fsp->fsp_name )); + pstrcpy(p + sizeof(*data) + sizeof(share_mode_entry), fname); fill_share_mode(p + sizeof(*data), fsp, port, op_type); dbuf.dptr = p; @@ -566,6 +570,10 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) data = (struct locking_data *)dbuf.dptr; data->u.num_share_mode_entries++; + + DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n", + fsp->fsp_name, data->u.num_share_mode_entries )); + size = dbuf.dsize + sizeof(share_mode_entry); p = malloc(size); if (!p) -- cgit From c1efcac59c001f70dcb4468d927cadcd49fdcf7a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jan 2002 00:52:36 +0000 Subject: Debugs that print out a share mode table in debug level 10. This code enabled me to track down a *nasty* bug. Jeremy. (This used to be commit ed5a9a0ee32aec460b9247ab4e4f5e38e8149e08) --- source3/locking/locking.c | 50 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 0eca0b61bc..8aace93503 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -318,6 +318,38 @@ void unlock_share_entry_fsp(files_struct *fsp) tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode)); } +/******************************************************************* + Print out a share mode. +********************************************************************/ + +static char *share_mode_str(int num, share_mode_entry *e) +{ + static pstring share_str; + + slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: \ +pid = %u, share_mode = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f", + num, e->pid, e->share_mode, e->op_port, e->op_type, e->share_file_id, + (unsigned int)e->dev, (double)e->inode ); + + return share_str; +} + +/******************************************************************* + Print out a share mode table. +********************************************************************/ + +static void print_share_mode_table(struct locking_data *data) +{ + int num_share_modes = data->u.num_share_mode_entries; + share_mode_entry *shares = (share_mode_entry *)(data + 1); + int i; + + for (i = 0; i < num_share_modes; i++) { + share_mode_entry *entry_p = &shares[i]; + DEBUG(10,("print_share_mode_table: %s\n", share_mode_str(i, entry_p) )); + } +} + /******************************************************************* Get all share mode entries for a dev/inode pair. ********************************************************************/ @@ -344,7 +376,7 @@ int get_share_modes(connection_struct *conn, int del_count = 0; shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), - num_share_modes * sizeof(share_mode_entry)); + num_share_modes * sizeof(share_mode_entry)); if (!shares) { SAFE_FREE(dbuf.dptr); @@ -357,11 +389,13 @@ int get_share_modes(connection_struct *conn, for (i = 0; i < num_share_modes; ) { share_mode_entry *entry_p = &shares[i]; - if (process_exists(entry_p->pid)) + if (process_exists(entry_p->pid)) { + DEBUG(10,("get_share_modes: %s\n", share_mode_str(i, entry_p) )); i++; - else { + } else { + DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) )); memcpy( &shares[i], &shares[i+1], - sizeof(share_mode_entry) * (num_share_modes - i - 1)); + sizeof(share_mode_entry) * (num_share_modes - i - 1)); num_share_modes--; del_count++; } @@ -474,6 +508,8 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, for (i=0;iu.num_share_mode_entries;) { if (share_modes_identical(&shares[i], entry)) { + DEBUG(10,("del_share_entry: deleted %s\n", + share_mode_str(i, &shares[i]) )); if (ppse) *ppse = memdup(&shares[i], sizeof(*shares)); data->u.num_share_mode_entries--; @@ -503,6 +539,8 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, count = -1; } } + DEBUG(10,("del_share_entry: Remaining table.\n")); + print_share_mode_table((struct locking_data *)dbuf.dptr); SAFE_FREE(dbuf.dptr); return count; } @@ -562,6 +600,9 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) dbuf.dsize = size; if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) ret = False; + + print_share_mode_table((struct locking_data *)p); + SAFE_FREE(p); return ret; } @@ -587,6 +628,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) dbuf.dsize = size; if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) ret = False; + print_share_mode_table((struct locking_data *)p); SAFE_FREE(p); return ret; } -- cgit From cd68afe31256ad60748b34f7318a180cfc2127cc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 30 Jan 2002 06:08:46 +0000 Subject: Removed version number from file header. Changed "SMB/Netbios" to "SMB/CIFS" in file header. (This used to be commit 6a58c9bd06d0d7502a24bf5ce5a2faf0a146edfa) --- source3/locking/brlock.c | 3 +-- source3/locking/locking.c | 3 +-- source3/locking/posix.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index cbf98c46a5..2131919674 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. byte range locking code Updated to handle range splits/merges. diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8aace93503..97366a1f9b 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. Locking functions Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1992-2000 diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 8b3538d8ca..f7a8cd3d39 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. Locking functions Copyright (C) Jeremy Allison 1992-2000 -- cgit From d160b3524063607b6e7431ec5973af3eaa176f6c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 5 Mar 2002 19:54:45 +0000 Subject: accept the 0/0 lock but don't treat it in any sort of special way (This used to be commit 8f7bf38de16a1f5316aa6a413fb697c43862c4c6) --- source3/locking/brlock.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 2131919674..10c1d5053b 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -293,7 +293,6 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, #if !ZERO_ZERO if (start == 0 && size == 0) { DEBUG(0,("client sent 0/0 lock - please report this\n")); - return NT_STATUS_INVALID_PARAMETER; } #endif -- cgit From be389e25ddff982a490c2b88c4649ce437a0d4d7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 10 Mar 2002 23:17:07 +0000 Subject: this attempts to handle the rather bizarre lock cache semantics in w2k. It isn't entirely accurate, but its close (This used to be commit e02d7364707c4939efa4ff0ddf9b6d4f48e5d411) --- source3/locking/brlock.c | 14 ++++++++++++++ source3/locking/locking.c | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 10c1d5053b..e7fa4022f6 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -285,6 +285,8 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, struct lock_struct lock, *locks; char *tp; NTSTATUS status = NT_STATUS_OK; + static int last_failed = -1; + static br_off last_failed_start; kbuf = locking_key(dev,ino); @@ -348,6 +350,18 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, return NT_STATUS_OK; fail: + /* this is a nasty hack to try to simulate the lock result cache code in w2k. + It isn't completely accurate as I haven't yet worked out the correct + semantics (tridge) + */ + if (last_failed == fnum && + last_failed_start == start && + NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) { + status = NT_STATUS_FILE_LOCK_CONFLICT; + } + last_failed = fnum; + last_failed_start = start; + SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); return status; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 97366a1f9b..dd6ca62e70 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -171,7 +171,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); - return NT_STATUS_LOCK_NOT_GRANTED; + return NT_STATUS_RANGE_NOT_LOCKED; } if (!lp_posix_locking(SNUM(conn))) -- cgit From 5e3b923124e82b1d19875746676df13cfdb0f918 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 13 Mar 2002 20:28:19 +0000 Subject: include/smb_macros.h: Don't round up an allocation if the size is zero. "One of these locks is not like the others... One of these locks is not quite the same" :-). When is a zero timeout lock not zero ? When it's being processed by Windows 2000 of course.. This code change, ugly though it is - completely fixes the foxpro/access multi-user file system database problems that people have been having. I used a *wonderful* test program donated by "Gerald Drouillard" which allowed me to completely reproduce this problem, and to finally determine the correct fix. This also explains why Windows 2000 is *so slow* when responding to the smbtorture lock tests. I *love* it when all these things come together and finally make sense :-). Jeremy. (This used to be commit 8aa9860ea2ea7f5aed4b6aa12794fffdfa81b0d0) --- source3/locking/locking.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index dd6ca62e70..8f3e4a278e 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -97,7 +97,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, Utility function called by locking requests. ****************************************************************************/ -NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, +static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type) { NTSTATUS status; @@ -141,6 +141,30 @@ NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, return status; } +/**************************************************************************** + Utility function called by locking requests. This is *DISGISTING*. It also + appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000 + is so slow on the locking tests...... ? This is the reason. Much though I hate + it, we need this. JRA. +****************************************************************************/ + +NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid, + SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type) +{ + int j, maxj = lp_lock_spin_count(); + int sleeptime = lp_lock_sleep_time(); + NTSTATUS status; + + for (j = 0; j < maxj; j++) { + status = do_lock(fsp, conn, lock_pid, count, offset, lock_type); + if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) && + !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) + break; + usleep(sleeptime); + } + return status; +} + /**************************************************************************** Utility function called by unlocking requests. ****************************************************************************/ -- cgit From f9af25c4ecaf30ccd9bb01762f65fe93ef566687 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 13 Mar 2002 20:49:57 +0000 Subject: Ensure we attempt to lock at least once. Only sleep if time param set. Jeremy. (This used to be commit 62b80d5c65ae8cf35347ee5c3d21ce1702c6449e) --- source3/locking/locking.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8f3e4a278e..1090b0fcbf 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -155,12 +155,16 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid int sleeptime = lp_lock_sleep_time(); NTSTATUS status; + if (maxj <= 0) + maxj = 1; + for (j = 0; j < maxj; j++) { status = do_lock(fsp, conn, lock_pid, count, offset, lock_type); if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) break; - usleep(sleeptime); + if (sleeptime) + usleep(sleeptime); } return status; } -- cgit From d6d9e385cc6ce61de9fec572209134be728cf1b0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Mar 2002 01:05:34 +0000 Subject: Use sys_usleep not usleep. Jeremy. (This used to be commit 8587dd95f850b4c6d2f015fe97ef98759ee8c236) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 1090b0fcbf..7a2e8cf1d7 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -164,7 +164,7 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) break; if (sleeptime) - usleep(sleeptime); + sys_usleep(sleeptime); } return status; } -- cgit From 7d4378cc892550465b75aae563cd6f7ea1608c21 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Mar 2002 09:51:37 +0000 Subject: if our lock spin code fails then return the first error code, not the last one. This is what caused the lock1 and lock2 tests to fail. (This used to be commit e7ae8003cb4fdc93db5f842754884a6d2ec93dc0) --- source3/locking/locking.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 7a2e8cf1d7..6efe4a73d7 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -153,20 +153,27 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid { int j, maxj = lp_lock_spin_count(); int sleeptime = lp_lock_sleep_time(); - NTSTATUS status; + NTSTATUS status, ret; if (maxj <= 0) maxj = 1; + ret = NT_STATUS_OK; /* to keep dumb compilers happy */ + for (j = 0; j < maxj; j++) { status = do_lock(fsp, conn, lock_pid, count, offset, lock_type); if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) && - !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) - break; + !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { + return status; + } + /* if we do fail then return the first error code we got */ + if (j == 0) { + ret = status; + } if (sleeptime) sys_usleep(sleeptime); } - return status; + return ret; } /**************************************************************************** -- cgit From c90cd26e9430b2fc065f620bdb6aaf4be0372fcc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 23 Mar 2002 02:57:44 +0000 Subject: Fix the mp3 rename bug - also tidy up our open code and remove the special cases for rename and unlink. Had to add desired_access into the share mode record. Jeremy. (This used to be commit 3b1b8ac43535fb0839c5474fa55bf7150f6cde31) --- source3/locking/locking.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 6efe4a73d7..87df805250 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -361,8 +361,8 @@ static char *share_mode_str(int num, share_mode_entry *e) static pstring share_str; slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: \ -pid = %u, share_mode = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f", - num, e->pid, e->share_mode, e->op_port, e->op_type, e->share_file_id, +pid = %u, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f", + num, e->pid, e->share_mode, (unsigned int)e->desired_access, e->op_port, e->op_type, e->share_file_id, (unsigned int)e->dev, (double)e->inode ); return share_str; @@ -471,6 +471,7 @@ static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_t memset(e, '\0', sizeof(share_mode_entry)); e->pid = sys_getpid(); e->share_mode = fsp->share_mode; + e->desired_access = fsp->desired_access; e->op_port = port; e->op_type = op_type; memcpy(x, &fsp->open_time, sizeof(struct timeval)); @@ -481,7 +482,7 @@ static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_t /******************************************************************* Check if two share mode entries are identical, ignoring oplock - and port info. + and port info and desired_access. ********************************************************************/ BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) -- cgit From e90b65284812aaa5ff9e9935ce9bbad7791cbbcd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Jul 2002 10:35:28 +0000 Subject: updated the 3.0 branch from the head branch - ready for alpha18 (This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce) --- source3/locking/brlock.c | 23 +++++++++++++++++------ source3/locking/locking.c | 7 ++++--- 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index e7fa4022f6..8c22f7d7ab 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -162,6 +162,10 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck } +#if DONT_DO_THIS + /* doing this traversal could kill solaris machines under high load (tridge) */ + /* delete any dead locks */ + /**************************************************************************** Delete a record if it is for a dead process, if check_self is true, then delete any records belonging to this pid also (there shouldn't be any). @@ -215,6 +219,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat tdb_chainunlock(tdb, kbuf); return 0; } +#endif /**************************************************************************** Open up the brlock.tdb database. @@ -222,8 +227,6 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat void brl_init(int read_only) { - BOOL check_self = False; - if (tdb) return; tdb = tdb_open_log(lock_path("brlock.tdb"), 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), @@ -233,9 +236,14 @@ void brl_init(int read_only) return; } +#if DONT_DO_THIS + /* doing this traversal could kill solaris machines under high load (tridge) */ /* delete any dead locks */ - if (!read_only) + if (!read_only) { + BOOL check_self = False; tdb_traverse(tdb, delete_fn, &check_self); + } +#endif } /**************************************************************************** @@ -244,14 +252,17 @@ void brl_init(int read_only) void brl_shutdown(int read_only) { - BOOL check_self = True; - if (!tdb) return; +#if DONT_DO_THIS + /* doing this traversal could kill solaris machines under high load (tridge) */ /* delete any dead locks */ - if (!read_only) + if (!read_only) { + BOOL check_self = True; tdb_traverse(tdb, delete_fn, &check_self); + } +#endif tdb_close(tdb); } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 87df805250..d42d041b79 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -681,6 +681,7 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en int i; share_mode_entry *shares; BOOL need_store=False; + BOOL ret = True; /* read in the existing share modes */ dbuf = tdb_fetch(tdb, locking_key(dev, inode)); @@ -702,15 +703,15 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en if (need_store) { if (data->u.num_share_mode_entries == 0) { if (tdb_delete(tdb, locking_key(dev, inode)) == -1) - need_store = False; + ret = False; } else { if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) - need_store = False; + ret = False; } } SAFE_FREE(dbuf.dptr); - return need_store; + return ret; } /******************************************************************* -- cgit From a834a73e341059be154426390304a42e4a011f72 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 25 Sep 2002 15:19:00 +0000 Subject: sync'ing up for 3.0alpha20 release (This used to be commit 65e7b5273bb58802bf0c389b77f7fcae0a1f6139) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d42d041b79..3eb7ca4783 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -142,7 +142,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p } /**************************************************************************** - Utility function called by locking requests. This is *DISGISTING*. It also + Utility function called by locking requests. This is *DISGUSTING*. It also appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000 is so slow on the locking tests...... ? This is the reason. Much though I hate it, we need this. JRA. -- cgit From de474974ea25df7738dd175126e3f1de0df47ea6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 23 Nov 2002 02:52:36 +0000 Subject: Lots of fixes for error paths where tdb_fetch() data need freeing. Found via a post from Arcady Chernyak . Jeremy. (This used to be commit 5d5762d1787db4392d2dff16024097c638b2d494) --- source3/locking/locking.c | 4 +++- source3/locking/posix.c | 25 ++++++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 3eb7ca4783..e8b6f3428f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -652,8 +652,10 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) size = dbuf.dsize + sizeof(share_mode_entry); p = malloc(size); - if (!p) + if (!p) { + SAFE_FREE(dbuf.dptr); return False; + } memcpy(p, dbuf.dptr, sizeof(*data)); fill_share_mode(p + sizeof(*data), fsp, port, op_type); memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data), diff --git a/source3/locking/posix.c b/source3/locking/posix.c index f7a8cd3d39..94055de2b0 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -149,7 +149,7 @@ static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - if (!dbuf.dptr) { + if (!dbuf.dptr) { return 0; } @@ -176,7 +176,7 @@ static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entr dbuf = tdb_fetch(posix_lock_tdb, kbuf); - if (!dbuf.dptr) { + if (!dbuf.dptr) { return 0; } @@ -338,8 +338,9 @@ static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry) return True; fail: - SAFE_FREE(dbuf.dptr); - return False; + + SAFE_FREE(dbuf.dptr); + return False; } /**************************************************************************** @@ -385,17 +386,18 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s goto fail; } - SAFE_FREE(dbuf.dptr); + SAFE_FREE(dbuf.dptr); DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n", fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, (double)fsp->dev, (double)fsp->inode )); - return True; + return True; fail: - SAFE_FREE(dbuf.dptr); - return False; + + SAFE_FREE(dbuf.dptr); + return False; } /**************************************************************************** @@ -492,13 +494,14 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, (unsigned int)num_overlapping_records )); - SAFE_FREE(dbuf.dptr); + SAFE_FREE(dbuf.dptr); return num_overlapping_records; fail: - SAFE_FREE(dbuf.dptr); - return -1; + + SAFE_FREE(dbuf.dptr); + return -1; } /**************************************************************************** -- cgit From ef8bd7c4f7ae8192ea05db070962ecf0ff3615f3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Dec 2002 20:21:31 +0000 Subject: Forward port the change to talloc_init() to make all talloc contexts named. Ensure we can query them. Jeremy. (This used to be commit 09a218a9f6fb0bd922940467bf8500eb4f1bcf84) --- source3/locking/posix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 94055de2b0..fcf19d21cf 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -1003,7 +1003,7 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou * semantics that if a write lock is added, then it will be first in the array. */ - if ((l_ctx = talloc_init()) == NULL) { + if ((l_ctx = talloc_init("set_posix_lock")) == NULL) { DEBUG(0,("set_posix_lock: unable to init talloc context.\n")); return True; /* Not a fatal error. */ } @@ -1149,7 +1149,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u } } - if ((ul_ctx = talloc_init()) == NULL) { + if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) { DEBUG(0,("release_posix_lock: unable to init talloc context.\n")); return True; /* Not a fatal error. */ } -- cgit From 20f1cf6cdcf9fc74d18fb9401e627a3455183ef3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Jan 2003 18:50:13 +0000 Subject: Fix problem with "hide unreadable". stat file opens are baaack :-). Jeremy. (This used to be commit 62038a0abf193d4dc4f37c31ac77216a10f6f326) --- source3/locking/locking.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e8b6f3428f..e5a72d2208 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -100,14 +100,13 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type) { - NTSTATUS status; + NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED; if (!lp_locking(SNUM(conn))) return NT_STATUS_OK; /* NOTE! 0 byte long ranges ARE allowed and should be stored */ - DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n", lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name )); -- cgit From 8a20407442efa0f9fe43e1b1c61140a0771c6ff8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 10 Feb 2003 11:47:21 +0000 Subject: Cleanups: (merge from HEAD) - use safe_strcpy() instead of pstrcpy() for malloc()ed strings - CUPS: a failure in an attempt to automaticly add a printer is not level 0 stuff. - Fix up a possible Realloc() failure segfault Andrew Bartlett (This used to be commit c1cfc296c2efdb2b5972202146e80f0e3b6a3da4) --- source3/locking/locking.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e5a72d2208..d4794560f6 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -611,6 +611,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) /* read in the existing share modes if any */ dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); if (!dbuf.dptr) { + size_t offset; /* we'll need to create a new record */ pstring fname; @@ -628,7 +629,8 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n", fsp->fsp_name )); - pstrcpy(p + sizeof(*data) + sizeof(share_mode_entry), fname); + offset = sizeof(*data) + sizeof(share_mode_entry); + safe_strcpy(p + offset, fname, size - offset); fill_share_mode(p + sizeof(*data), fsp, port, op_type); dbuf.dptr = p; dbuf.dsize = size; -- cgit From 7fe6742d04f05c28af9e5bda37bc1dce734fe559 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Feb 2003 20:40:29 +0000 Subject: Fixes for HPUX only having limited POSIX lock range from Michael Steffens Jeremy. (This used to be commit e9b4fb8b9aedda9afc01af976264298002be3096) --- source3/locking/posix.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index fcf19d21cf..2b64631d39 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -552,7 +552,11 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, * find the maximum positive lock offset as an SMB_OFF_T. */ -#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) +#if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */ + + SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET); + +#elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) /* * In this case SMB_OFF_T is 64 bits, @@ -598,19 +602,10 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, } /* - * We must truncate the offset and count to less than max_positive_lock_offset. - */ - - offset &= max_positive_lock_offset; - count &= max_positive_lock_offset; - - - /* - * Deal with a very common case of count of all ones. - * (lock entire file). + * We must truncate the count to less than max_positive_lock_offset. */ - if(count == (SMB_OFF_T)-1) + if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) count = max_positive_lock_offset; /* -- cgit From 285a3b0ef869382aea892cad37284ba9cbe529d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 22 Feb 2003 01:09:57 +0000 Subject: When checking is_locked() new WRITE locks conflict with existing READ locks even if the context is the same. See LOCKTEST7 in smbtorture. Jeremy. (This used to be commit 1698092ba5a169de369ad1182a6f270de174c3f5) --- source3/locking/brlock.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 8c22f7d7ab..9902c7bbd7 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -151,9 +151,16 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) return False; - if (brl_same_context(&lck1->context, &lck2->context) && - lck1->fnum == lck2->fnum) - return False; + /* + * Incoming WRITE locks conflict with existing READ locks even + * if the context is the same. JRA. See LOCKTEST7 in smbtorture. + */ + + if (!(lck2->lock_type == WRITE_LOCK && lck1->lock_type == READ_LOCK)) { + if (brl_same_context(&lck1->context, &lck2->context) && + lck1->fnum == lck2->fnum) + return False; + } if (lck1->start >= (lck2->start + lck2->size) || lck2->start >= (lck1->start + lck1->size)) return False; -- cgit From 98410be6074362acdd3c1799a59602f590c9decb Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 24 Feb 2003 03:03:15 +0000 Subject: Merge off-by-one fix from HEAD (caused crash with --enable-developer) (This used to be commit d71425413075af25f91f715950c06ab698cf5fb7) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d4794560f6..fdfd4d661c 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -630,7 +630,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) fsp->fsp_name )); offset = sizeof(*data) + sizeof(share_mode_entry); - safe_strcpy(p + offset, fname, size - offset); + safe_strcpy(p + offset, fname, size - offset - 1); fill_share_mode(p + sizeof(*data), fsp, port, op_type); dbuf.dptr = p; dbuf.dsize = size; -- cgit From fb3e4b87973e9ad0c818e8d9dd60329c47f22afe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Feb 2003 01:04:34 +0000 Subject: Fix to allow blocking lock notification to be done rapidly (no wait for smb -> smb lock release). Adds new PENDING_LOCK type to lockdb (does not interfere with existing locks). Jeremy. (This used to be commit 766928bbba1e597c9c2b12458dd8d37e6080593e) --- source3/locking/brlock.c | 82 +++++++++++++++++++++++++++++++++++++++++++---- source3/locking/locking.c | 4 +-- 2 files changed, 78 insertions(+), 8 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 9902c7bbd7..4cd885f1a6 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -98,6 +98,9 @@ static BOOL brl_same_context(struct lock_context *ctx1, static BOOL brl_conflict(struct lock_struct *lck1, struct lock_struct *lck2) { + if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) + return False; + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) { return False; } @@ -119,6 +122,9 @@ static BOOL brl_conflict(struct lock_struct *lck1, static BOOL brl_conflict1(struct lock_struct *lck1, struct lock_struct *lck2) { + if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) + return False; + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) { return False; } @@ -148,6 +154,9 @@ static BOOL brl_conflict1(struct lock_struct *lck1, static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck2) { + if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) + return False; + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) return False; @@ -385,16 +394,30 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, return status; } +/**************************************************************************** + Check if an unlock overlaps a pending lock. +****************************************************************************/ + +static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pend_lock) +{ + if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start)) + return True; + if ((lock->start >= pend_lock->start) && (lock->start <= pend_lock->start + pend_lock->size)) + return True; + return False; +} + /**************************************************************************** Unlock a range of bytes. ****************************************************************************/ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, - br_off start, br_off size) + br_off start, br_off size, + BOOL remove_pending_locks_only) { TDB_DATA kbuf, dbuf; - int count, i; + int count, i, j; struct lock_struct *locks; struct lock_context context; @@ -452,9 +475,34 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, struct lock_struct *lock = &locks[i]; if (brl_same_context(&lock->context, &context) && - lock->fnum == fnum && - lock->start == start && - lock->size == size) { + lock->fnum == fnum && + lock->start == start && + lock->size == size) { + + if (remove_pending_locks_only && lock->lock_type != PENDING_LOCK) + continue; + + if (lock->lock_type != PENDING_LOCK) { + /* Send unlock messages to any pending waiters that overlap. */ + for (j=0; jlock_type != PENDING_LOCK) + continue; + + /* We could send specific lock info here... */ + if (brl_pending_overlap(lock, pend_lock)) { + DEBUG(10,("brl_unlock: sending unlock message to pid %u\n", + (unsigned int)pend_lock->context.pid )); + + message_send_pid(pend_lock->context.pid, + MSG_SMB_UNLOCK, + NULL, 0, True); + } + } + } + /* found it - delete it */ if (count == 1) { tdb_delete(tdb, kbuf); @@ -546,7 +594,7 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) { TDB_DATA kbuf, dbuf; - int count, i, dcount=0; + int count, i, j, dcount=0; struct lock_struct *locks; kbuf = locking_key(dev,ino); @@ -561,12 +609,34 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) /* there are existing locks - remove any for this fnum */ locks = (struct lock_struct *)dbuf.dptr; count = dbuf.dsize / sizeof(*locks); + for (i=0; icontext.tid == tid && lock->context.pid == pid && lock->fnum == fnum) { + + /* Send unlock messages to any pending waiters that overlap. */ + for (j=0; jlock_type != PENDING_LOCK) + continue; + + if (pend_lock->context.tid == tid && + pend_lock->context.pid == pid && + pend_lock->fnum == fnum) + continue; + + /* We could send specific lock info here... */ + if (brl_pending_overlap(lock, pend_lock)) + message_send_pid(pend_lock->context.pid, + MSG_SMB_UNLOCK, + NULL, 0, True); + } + /* found it - delete it */ if (count > 1 && i < count-1) { memmove(&locks[i], &locks[i+1], diff --git a/source3/locking/locking.c b/source3/locking/locking.c index fdfd4d661c..651f905e15 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -132,7 +132,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p */ (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum, lock_pid, sys_getpid(), conn->cnum, - offset, count); + offset, count, False); } } } @@ -201,7 +201,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, */ ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, sys_getpid(), conn->cnum, offset, count); + lock_pid, sys_getpid(), conn->cnum, offset, count, False); if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); -- cgit From 34226f1bd4d90ffe0f324277b11bbc4f2b575740 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Apr 2003 20:38:12 +0000 Subject: Fix for very subtle POSIX lock interaction race condition found by Herb. We need to unlock POSIX locks before notifying pending lock processes. Jeremy. (This used to be commit 6999eef51c3e597b3b2cd9cc26138acdfbb6a23a) --- source3/locking/brlock.c | 13 ++++++++++++- source3/locking/locking.c | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 9 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 4cd885f1a6..20d76c9c79 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -414,7 +414,9 @@ static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pe BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, - BOOL remove_pending_locks_only) + BOOL remove_pending_locks_only, + void (*pre_unlock_fn)(void *), + void *pre_unlock_data) { TDB_DATA kbuf, dbuf; int count, i, j; @@ -450,6 +452,10 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, lock->fnum == fnum && lock->start == start && lock->size == size) { + + if (pre_unlock_fn) + (*pre_unlock_fn)(pre_unlock_data); + /* found it - delete it */ if (count == 1) { tdb_delete(tdb, kbuf); @@ -483,6 +489,11 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, continue; if (lock->lock_type != PENDING_LOCK) { + + /* Do any POSIX unlocks needed. */ + if (pre_unlock_fn) + (*pre_unlock_fn)(pre_unlock_data); + /* Send unlock messages to any pending waiters that overlap. */ for (j=0; jdev, fsp->inode, fsp->fnum, lock_pid, sys_getpid(), conn->cnum, - offset, count, False); + offset, count, False, + NULL, NULL); } } } @@ -175,6 +176,25 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid return ret; } +/* Struct passed to brl_unlock. */ +struct posix_unlock_data_struct { + files_struct *fsp; + SMB_BIG_UINT offset; + SMB_BIG_UINT count; +}; + +/**************************************************************************** + Function passed to brl_unlock to allow POSIX unlock to be done first. +****************************************************************************/ + +static void posix_unlock(void *pre_data) +{ + struct posix_unlock_data_struct *pdata = (struct posix_unlock_data_struct *)pre_data; + + if (lp_posix_locking(SNUM(pdata->fsp->conn))) + release_posix_lock(pdata->fsp, pdata->offset, pdata->count); +} + /**************************************************************************** Utility function called by unlocking requests. ****************************************************************************/ @@ -183,6 +203,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, SMB_BIG_UINT count,SMB_BIG_UINT offset) { BOOL ok = False; + struct posix_unlock_data_struct posix_data; if (!lp_locking(SNUM(conn))) return NT_STATUS_OK; @@ -200,19 +221,18 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, * match then don't bother looking to remove POSIX locks. */ + posix_data.fsp = fsp; + posix_data.offset = offset; + posix_data.count = count; + ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, sys_getpid(), conn->cnum, offset, count, False); + lock_pid, sys_getpid(), conn->cnum, offset, count, + False, posix_unlock, (void *)&posix_data); if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); return NT_STATUS_RANGE_NOT_LOCKED; } - - if (!lp_posix_locking(SNUM(conn))) - return NT_STATUS_OK; - - (void)release_posix_lock(fsp, offset, count); - return NT_STATUS_OK; } -- cgit From e7c8c15888454043c73967635deb4d3419a489e9 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Sun, 11 May 2003 23:34:18 +0000 Subject: Fix VFS layer: 1. Finally work with cascaded modules with private data storage per module 2. Convert VFS API to macro calls to simplify cascading 3. Add quota support to VFS layer (prepare to NT quota support) Patch by Stefan (metze) Metzemacher, with review of Jelmer and me Tested in past few weeks. Documentation to new VFS API for third-party developers to follow (This used to be commit 91984ef5caa2d13c5d52e1f535bd3bbbae1ec978) --- source3/locking/posix.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 2b64631d39..1c794a1c86 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -205,7 +205,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) /* * No POSIX to worry about, just close. */ - ret = conn->vfs_ops.close(fsp,fsp->fd); + ret = VFS_CLOSE(fsp,fsp->fd); fsp->fd = -1; return ret; } @@ -259,7 +259,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); for(i = 0; i < count; i++) { - if (conn->vfs_ops.close(fsp,fd_array[i]) == -1) { + if (VFS_CLOSE(fsp,fd_array[i]) == -1) { saved_errno = errno; } } @@ -278,7 +278,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) * Finally close the fd associated with this fsp. */ - ret = conn->vfs_ops.close(fsp,fsp->fd); + ret = VFS_CLOSE(fsp,fsp->fd); if (saved_errno != 0) { errno = saved_errno; @@ -646,11 +646,10 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { int ret; - struct connection_struct *conn = fsp->conn; DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fd,op,(double)offset,(double)count,type)); - ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); + ret = VFS_LOCK(fsp,fsp->fd,op,offset,count,type); if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { @@ -674,7 +673,7 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); errno = 0; count &= 0x7fffffff; - ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); + ret = VFS_LOCK(fsp,fsp->fd,op,offset,count,type); } } -- cgit From bc2a3748e9caa8f60f7c2387e7eecd7fb3fae899 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 14 May 2003 10:59:01 +0000 Subject: Prefix VFS API macros with SMB_ for consistency and to avoid problems with VFS_ macros at system side. We currently have one clash with AIX and its VFS_LOCK. Compiled and tested -- no new functionality or code, just plain rename of macros for yet-unreleased VFS API version. Needs to be done before a24 is out (This used to be commit c2689ed118b490e49497a76ed6a2251262018769) --- source3/locking/posix.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 1c794a1c86..6173c80b2f 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -205,7 +205,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) /* * No POSIX to worry about, just close. */ - ret = VFS_CLOSE(fsp,fsp->fd); + ret = SMB_VFS_CLOSE(fsp,fsp->fd); fsp->fd = -1; return ret; } @@ -259,7 +259,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); for(i = 0; i < count; i++) { - if (VFS_CLOSE(fsp,fd_array[i]) == -1) { + if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) { saved_errno = errno; } } @@ -278,7 +278,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) * Finally close the fd associated with this fsp. */ - ret = VFS_CLOSE(fsp,fsp->fd); + ret = SMB_VFS_CLOSE(fsp,fsp->fd); if (saved_errno != 0) { errno = saved_errno; @@ -649,7 +649,7 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fd,op,(double)offset,(double)count,type)); - ret = VFS_LOCK(fsp,fsp->fd,op,offset,count,type); + ret = SMB_VFS_LOCK(fsp,fsp->fd,op,offset,count,type); if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { @@ -673,7 +673,7 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); errno = 0; count &= 0x7fffffff; - ret = VFS_LOCK(fsp,fsp->fd,op,offset,count,type); + ret = SMB_VFS_LOCK(fsp,fsp->fd,op,offset,count,type); } } -- cgit From 78a4f6fc4b8938fcab5bb3b7ae9c3a151f7070f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 May 2003 18:56:51 +0000 Subject: More fixes for debug log to catch logic error. Jeremy. (This used to be commit 84a7714eba801fefa7ad56493f20813de3943bc5) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 1b40187ac4..1a5757f817 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -375,7 +375,7 @@ void unlock_share_entry_fsp(files_struct *fsp) Print out a share mode. ********************************************************************/ -static char *share_mode_str(int num, share_mode_entry *e) +char *share_mode_str(int num, share_mode_entry *e) { static pstring share_str; -- cgit From 80c1f1d865b13a63c7a60876b63458119566e044 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 22 Jul 2003 04:31:20 +0000 Subject: Fixup a bunch of printf-style functions and debugs to use unsigned long when displaying pid_t, uid_t and gid_t values. This removes a whole lot of warnings on some of the 64-bit build farm machines as well as help us out when 64-bit uid/gid/pid values come along. (This used to be commit f93528ba007c8800a850678f35f499fb7360fb9a) --- source3/locking/locking.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 1a5757f817..f4de83c346 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -380,8 +380,8 @@ char *share_mode_str(int num, share_mode_entry *e) static pstring share_str; slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: \ -pid = %u, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f", - num, e->pid, e->share_mode, (unsigned int)e->desired_access, e->op_port, e->op_type, e->share_file_id, +pid = %lu, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f", + num, (unsigned long)e->pid, e->share_mode, (unsigned int)e->desired_access, e->op_port, e->op_type, e->share_file_id, (unsigned int)e->dev, (double)e->inode ); return share_str; -- cgit From ef915c8eaf1d8335aa331d3b2376c40e3a63de22 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 1 Aug 2003 06:10:30 +0000 Subject: Final fix for the bug tridge found. Only push locks onto a blocking lock queue if the posix lock failed with EACCES or EAGAIN (this means another lock conflicts). Else return an error and don't queue the request. Jeremy. (This used to be commit 43fbc18fdc184bf29c15186c16bc99fb208de963) --- source3/locking/locking.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f4de83c346..4475f1446f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -125,7 +125,11 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p */ if (!set_posix_lock(fsp, offset, count, lock_type)) { - status = NT_STATUS_LOCK_NOT_GRANTED; + if (errno == EACCES || errno == EAGAIN) + status = NT_STATUS_FILE_LOCK_CONFLICT; + else + status = map_nt_error_from_unix(errno); + /* * We failed to map - we must now remove the brl * lock entry. -- cgit From 07c90e499e5e02db94d4ca3f3d303b2b1952ace9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 8 Sep 2003 20:42:33 +0000 Subject: Tidy up some formatting. Get ready for allowing bad password lockout. (based on a patch posted from Richard Renard . Jeremy. (This used to be commit abf54b58e95a949cb883d4485853dc560489c03f) --- source3/locking/locking.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4475f1446f..91bc20af90 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -419,10 +419,10 @@ int get_share_modes(connection_struct *conn, struct locking_data *data; int num_share_modes; share_mode_entry *shares = NULL; - + TDB_DATA key = locking_key(dev, inode); *pp_shares = NULL; - dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) return 0; @@ -469,7 +469,7 @@ int get_share_modes(connection_struct *conn, /* The record has shrunk a bit */ dbuf.dsize -= del_count * sizeof(share_mode_entry); - if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) { + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { SAFE_FREE(shares); SAFE_FREE(dbuf.dptr); return 0; @@ -544,12 +544,13 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, int i, del_count=0; share_mode_entry *shares; ssize_t count = 0; + TDB_DATA key = locking_key(dev, inode); if (ppse) *ppse = NULL; /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) return -1; @@ -590,10 +591,10 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, /* store it back in the database */ if (data->u.num_share_mode_entries == 0) { - if (tdb_delete(tdb, locking_key(dev, inode)) == -1) + if (tdb_delete(tdb, key) == -1) count = -1; } else { - if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) count = -1; } } @@ -630,10 +631,11 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) struct locking_data *data; char *p=NULL; int size; + TDB_DATA key = locking_key_fsp(fsp); BOOL ret = True; /* read in the existing share modes if any */ - dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); + dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) { size_t offset; /* we'll need to create a new record */ @@ -658,7 +660,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) fill_share_mode(p + sizeof(*data), fsp, port, op_type); dbuf.dptr = p; dbuf.dsize = size; - if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) ret = False; print_share_mode_table((struct locking_data *)p); @@ -688,7 +690,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) SAFE_FREE(dbuf.dptr); dbuf.dptr = p; dbuf.dsize = size; - if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) ret = False; print_share_mode_table((struct locking_data *)p); SAFE_FREE(p); @@ -709,9 +711,10 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en share_mode_entry *shares; BOOL need_store=False; BOOL ret = True; + TDB_DATA key = locking_key(dev, inode); /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) return False; @@ -729,10 +732,10 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en /* if the mod fn was called then store it back */ if (need_store) { if (data->u.num_share_mode_entries == 0) { - if (tdb_delete(tdb, locking_key(dev, inode)) == -1) + if (tdb_delete(tdb, key) == -1) ret = False; } else { - if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) ret = False; } } @@ -808,9 +811,10 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) struct locking_data *data; int i; share_mode_entry *shares; + TDB_DATA key = locking_key(dev, inode); /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) return False; @@ -826,7 +830,7 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) /* store it back */ if (data->u.num_share_mode_entries) { - if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) { + if (tdb_store(tdb, key, dbuf, TDB_REPLACE)==-1) { SAFE_FREE(dbuf.dptr); return False; } -- cgit From 22c024157129e287a6e4bb4bc7232144c36d9604 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Oct 2003 01:46:01 +0000 Subject: Changes to allow Samba3 to pass the Samba4 RAW-READ tests. Jeremy. (This used to be commit e7565dbba696adbb0fd8cca6b86a1a7e5a655f2e) --- source3/locking/brlock.c | 9 +++++++-- source3/locking/locking.c | 11 +++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 20d76c9c79..c51a5a2aac 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -172,7 +172,8 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck } if (lck1->start >= (lck2->start + lck2->size) || - lck2->start >= (lck1->start + lck1->size)) return False; + lck2->start >= (lck1->start + lck1->size)) + return False; return True; } @@ -305,7 +306,7 @@ static int lock_compare(struct lock_struct *lck1, NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, - enum brl_type lock_type) + enum brl_type lock_type, BOOL *my_lock_ctx) { TDB_DATA kbuf, dbuf; int count, i; @@ -315,6 +316,7 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, static int last_failed = -1; static br_off last_failed_start; + *my_lock_ctx = False; kbuf = locking_key(dev,ino); dbuf.dptr = NULL; @@ -343,6 +345,9 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, for (i=0; idev, fsp->inode, fsp->fnum, lock_pid, sys_getpid(), conn->cnum, offset, count, - lock_type); + lock_type, my_lock_ctx); if (NT_STATUS_IS_OK(status) && lp_posix_locking(SNUM(conn))) { @@ -153,7 +153,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p ****************************************************************************/ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid, - SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type) + SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx) { int j, maxj = lp_lock_spin_count(); int sleeptime = lp_lock_sleep_time(); @@ -165,7 +165,7 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid ret = NT_STATUS_OK; /* to keep dumb compilers happy */ for (j = 0; j < maxj; j++) { - status = do_lock(fsp, conn, lock_pid, count, offset, lock_type); + status = do_lock(fsp, conn, lock_pid, count, offset, lock_type, my_lock_ctx); if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { return status; @@ -173,6 +173,9 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid /* if we do fail then return the first error code we got */ if (j == 0) { ret = status; + /* Don't spin if we blocked ourselves. */ + if (*my_lock_ctx) + return ret; } if (sleeptime) sys_usleep(sleeptime); -- cgit From df6d2db4ced5586320804950da58a62248db4d56 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 12 Feb 2004 05:24:02 +0000 Subject: merge from old APP_HEAD * remove corrupt tdb and shutdown (only for printing tdbs, connections, sessionid & locking) * decrement smbd counter in connections.tdb in smb_panic() * various Makefile hack to get things to link 'max smbd processes' looks like it might be broken. The counter KEY is not being set. Will look into that tomorrow. (This used to be commit 6e22c5da929b6d9a4e32dc704c83112b2ad8fcfd) --- source3/locking/brlock.c | 4 ++-- source3/locking/locking.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index c51a5a2aac..47001c8b89 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -246,8 +246,8 @@ void brl_init(int read_only) { if (tdb) return; - tdb = tdb_open_log(lock_path("brlock.tdb"), 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); + tdb = tdb_open_ex(lock_path("brlock.tdb"), 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644, smbd_tdb_log); if (!tdb) { DEBUG(0,("Failed to open byte range locking database\n")); return; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index c3abd63818..42036cc70c 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -283,10 +283,10 @@ BOOL locking_init(int read_only) if (tdb) return True; - tdb = tdb_open_log(lock_path("locking.tdb"), + tdb = tdb_open_ex(lock_path("locking.tdb"), 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), read_only?O_RDONLY:O_RDWR|O_CREAT, - 0644); + 0644, smbd_tdb_log); if (!tdb) { DEBUG(0,("ERROR: Failed to initialise locking database\n")); -- cgit From ac5f0785c83d971a043cc99369dd491bee2be302 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Jun 2004 23:19:36 +0000 Subject: r984: Ensure memmove & memcpy aren't called with len == 0. Jeremy. (This used to be commit 40c77dddc65e18b879d922379d562ffb8be80ab5) --- source3/locking/locking.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 42036cc70c..2a27d7d4cd 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -454,8 +454,10 @@ int get_share_modes(connection_struct *conn, i++; } else { DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) )); - memcpy( &shares[i], &shares[i+1], - sizeof(share_mode_entry) * (num_share_modes - i - 1)); + if (num_share_modes - i - 1 > 0) { + memcpy( &shares[i], &shares[i+1], + sizeof(share_mode_entry) * (num_share_modes - i - 1)); + } num_share_modes--; del_count++; } @@ -575,8 +577,10 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, if (ppse) *ppse = memdup(&shares[i], sizeof(*shares)); data->u.num_share_mode_entries--; - memmove(&shares[i], &shares[i+1], - dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); + if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))) > 0) { + memmove(&shares[i], &shares[i+1], + dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); + } del_count++; DEBUG(10,("del_share_entry: deleting entry %d\n", i )); -- cgit From 386a11f49eff2ec60d75b9966ecdc5627b259f0d Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 4 Jun 2004 17:26:09 +0000 Subject: r1011: fix bad merge (from a few months ago) and ensure that we always use tdb_open_log() instead of tdb_open_ex() (This used to be commit e65564ab4aa1240e84b8d272510aa770cad0ed0e) --- source3/locking/brlock.c | 4 ++-- source3/locking/locking.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 47001c8b89..990a6a25d2 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -246,8 +246,8 @@ void brl_init(int read_only) { if (tdb) return; - tdb = tdb_open_ex(lock_path("brlock.tdb"), 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644, smbd_tdb_log); + tdb = tdb_open_log(lock_path("brlock.tdb"), 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 ); if (!tdb) { DEBUG(0,("Failed to open byte range locking database\n")); return; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 2a27d7d4cd..fd03a25940 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -283,10 +283,10 @@ BOOL locking_init(int read_only) if (tdb) return True; - tdb = tdb_open_ex(lock_path("locking.tdb"), + tdb = tdb_open_log(lock_path("locking.tdb"), 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), read_only?O_RDONLY:O_RDWR|O_CREAT, - 0644, smbd_tdb_log); + 0644); if (!tdb) { DEBUG(0,("ERROR: Failed to initialise locking database\n")); -- cgit From 2fc57c9a2ce3a266534dd20e6fed4883e052c557 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jun 2004 16:14:31 +0000 Subject: r1085: Now it's had some proper user testing, merge in the deferred open fix. I'm still doing more testing, but it fixes a behaviour that we've been wrong on ever since the start of Samba. Jeremy. (This used to be commit 894cc6d16296b934c112786eec896846156aee5d) --- source3/locking/locking.c | 392 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 387 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index fd03a25940..8f53b55fc5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -40,6 +40,17 @@ uint16 global_smbpid; /* the locking database handle */ static TDB_CONTEXT *tdb; +struct locking_data { + union { + int num_share_mode_entries; + share_mode_entry dummy; /* Needed for alignment. */ + } u; + /* the following two entries are implicit + share_mode_entry modes[num_share_mode_entries]; + char file_name[]; + */ +}; + /**************************************************************************** Debugging aid :-). ****************************************************************************/ @@ -432,6 +443,7 @@ int get_share_modes(connection_struct *conn, data = (struct locking_data *)dbuf.dptr; num_share_modes = data->u.num_share_mode_entries; if(num_share_modes) { + pstring fname; int i; int del_count = 0; @@ -443,6 +455,9 @@ int get_share_modes(connection_struct *conn, return 0; } + /* Save off the associated filename. */ + pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry)); + /* * Ensure that each entry has a real process attached. */ @@ -467,17 +482,28 @@ int get_share_modes(connection_struct *conn, if (del_count) { data->u.num_share_mode_entries = num_share_modes; - if (num_share_modes) + if (num_share_modes) { memcpy(dbuf.dptr + sizeof(*data), shares, num_share_modes * sizeof(share_mode_entry)); + /* Append the filename. */ + pstrcpy(dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry), fname); + } /* The record has shrunk a bit */ dbuf.dsize -= del_count * sizeof(share_mode_entry); - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { - SAFE_FREE(shares); - SAFE_FREE(dbuf.dptr); - return 0; + if (data->u.num_share_mode_entries == 0) { + if (tdb_delete(tdb, key) == -1) { + SAFE_FREE(shares); + SAFE_FREE(dbuf.dptr); + return 0; + } + } else { + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { + SAFE_FREE(shares); + SAFE_FREE(dbuf.dptr); + return 0; + } } } } @@ -847,6 +873,358 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) return True; } +/******************************************************************* + Print out a deferred open entry. +********************************************************************/ + +char *deferred_open_str(int num, deferred_open_entry *e) +{ + static pstring de_str; + + slprintf(de_str, sizeof(de_str)-1, "deferred_open_entry[%d]: \ +pid = %lu, mid = %u, dev = 0x%x, inode = %.0f, port = %u, time = [%u.%06u]", + num, (unsigned long)e->pid, (unsigned int)e->mid, (unsigned int)e->dev, (double)e->inode, + (unsigned int)e->port, + (unsigned int)e->time.tv_sec, (unsigned int)e->time.tv_usec ); + + return de_str; +} + +/* Internal data structures for deferred opens... */ + +struct de_locking_key { + char name[4]; + SMB_DEV_T dev; + SMB_INO_T inode; +}; + +struct deferred_open_data { + union { + int num_deferred_open_entries; + deferred_open_entry dummy; /* Needed for alignment. */ + } u; + /* the following two entries are implicit + deferred_open_entry de_entries[num_deferred_open_entries]; + char file_name[]; + */ +}; + +/******************************************************************* + Print out a deferred open table. +********************************************************************/ + +static void print_deferred_open_table(struct deferred_open_data *data) +{ + int num_de_entries = data->u.num_deferred_open_entries; + deferred_open_entry *de_entries = (deferred_open_entry *)(data + 1); + int i; + + for (i = 0; i < num_de_entries; i++) { + deferred_open_entry *entry_p = &de_entries[i]; + DEBUG(10,("print_deferred_open_table: %s\n", deferred_open_str(i, entry_p) )); + } +} + + +/******************************************************************* + Form a static deferred open locking key for a dev/inode pair. +******************************************************************/ + +static TDB_DATA deferred_open_locking_key(SMB_DEV_T dev, SMB_INO_T inode) +{ + static struct de_locking_key key; + TDB_DATA kbuf; + + memset(&key, '\0', sizeof(key)); + memcpy(&key.name[0], "DOE", 4); + key.dev = dev; + key.inode = inode; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + return kbuf; +} + +/******************************************************************* + Get all deferred open entries for a dev/inode pair. +********************************************************************/ + +int get_deferred_opens(connection_struct *conn, + SMB_DEV_T dev, SMB_INO_T inode, + deferred_open_entry **pp_de_entries) +{ + TDB_DATA dbuf; + struct deferred_open_data *data; + int num_de_entries; + deferred_open_entry *de_entries = NULL; + TDB_DATA key = deferred_open_locking_key(dev, inode); + + *pp_de_entries = NULL; + + dbuf = tdb_fetch(tdb, key); + if (!dbuf.dptr) + return 0; + + data = (struct deferred_open_data *)dbuf.dptr; + num_de_entries = data->u.num_deferred_open_entries; + if(num_de_entries) { + pstring fname; + int i; + int del_count = 0; + + de_entries = (deferred_open_entry *)memdup(dbuf.dptr + sizeof(*data), + num_de_entries * sizeof(deferred_open_entry)); + + if (!de_entries) { + SAFE_FREE(dbuf.dptr); + return 0; + } + + /* Save off the associated filename. */ + pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry)); + + /* + * Ensure that each entry has a real process attached. + */ + + for (i = 0; i < num_de_entries; ) { + deferred_open_entry *entry_p = &de_entries[i]; + if (process_exists(entry_p->pid)) { + DEBUG(10,("get_deferred_opens: %s\n", deferred_open_str(i, entry_p) )); + i++; + } else { + DEBUG(10,("get_deferred_opens: deleted %s\n", deferred_open_str(i, entry_p) )); + if (num_de_entries - i - 1 > 0) { + memcpy( &de_entries[i], &de_entries[i+1], + sizeof(deferred_open_entry) * (num_de_entries - i - 1)); + } + num_de_entries--; + del_count++; + } + } + + /* Did we delete any ? If so, re-store in tdb. */ + if (del_count) { + data->u.num_deferred_open_entries = num_de_entries; + + if (num_de_entries) { + memcpy(dbuf.dptr + sizeof(*data), de_entries, + num_de_entries * sizeof(deferred_open_entry)); + /* Append the filename. */ + pstrcpy(dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry), fname); + } + + /* The record has shrunk a bit */ + dbuf.dsize -= del_count * sizeof(deferred_open_entry); + + if (data->u.num_deferred_open_entries == 0) { + if (tdb_delete(tdb, key) == -1) { + SAFE_FREE(de_entries); + SAFE_FREE(dbuf.dptr); + return 0; + } + } else { + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { + SAFE_FREE(de_entries); + SAFE_FREE(dbuf.dptr); + return 0; + } + } + } + } + + SAFE_FREE(dbuf.dptr); + *pp_de_entries = de_entries; + return num_de_entries; +} + +/******************************************************************* + Check if two deferred open entries are identical. +********************************************************************/ + +static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_open_entry *e2) +{ +#if 1 /* JRA PARANOIA TEST - REMOVE LATER */ + if (e1->pid == e2->pid && + e1->port == e2->port && + e1->dev == e2->dev && + e1->inode == e2->inode && + ((e1->time.tv_sec != e2->time.tv_sec) || + (e1->time.tv_usec != e2->time.tv_usec) || + (e1->mid != e2->mid))) { + smb_panic("PANIC: deferred_open_entries_identical: logic error.\n"); + } +#endif + + return (e1->pid == e2->pid && + e1->mid == e2->mid && + e1->port == e2->port && + e1->dev == e2->dev && + e1->inode == e2->inode && + e1->time.tv_sec == e2->time.tv_sec && + e1->time.tv_usec == e2->time.tv_usec); +} + + +/******************************************************************* + Delete a specific deferred open entry. + Ignore if no entry deleted. +********************************************************************/ + +BOOL delete_deferred_open_entry(deferred_open_entry *entry) +{ + TDB_DATA dbuf; + struct deferred_open_data *data; + int i, del_count=0; + deferred_open_entry *de_entries; + BOOL ret = True; + TDB_DATA key = deferred_open_locking_key(entry->dev, entry->inode); + + /* read in the existing share modes */ + dbuf = tdb_fetch(tdb, key); + if (!dbuf.dptr) + return -1; + + data = (struct deferred_open_data *)dbuf.dptr; + de_entries = (deferred_open_entry *)(dbuf.dptr + sizeof(*data)); + + /* + * Find any with this pid and delete it + * by overwriting with the rest of the data + * from the record. + */ + + DEBUG(10,("delete_deferred_open_entry: num_deferred_open_entries = %d\n", + data->u.num_deferred_open_entries )); + + for (i=0;iu.num_deferred_open_entries;) { + if (deferred_open_entries_identical(&de_entries[i], entry)) { + DEBUG(10,("delete_deferred_open_entry: deleted %s\n", + deferred_open_str(i, &de_entries[i]) )); + + data->u.num_deferred_open_entries--; + if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))) > 0) { + memmove(&de_entries[i], &de_entries[i+1], + dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))); + } + del_count++; + + DEBUG(10,("delete_deferred_open_entry: deleting entry %d\n", i )); + + } else { + i++; + } + } + + SMB_ASSERT(del_count == 0 || del_count == 1); + + if (del_count) { + /* the record may have shrunk a bit */ + dbuf.dsize -= del_count * sizeof(*de_entries); + + /* store it back in the database */ + if (data->u.num_deferred_open_entries == 0) { + if (tdb_delete(tdb, key) == -1) + ret = False; + } else { + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) + ret = False; + } + } + DEBUG(10,("delete_deferred_open_entry: Remaining table.\n")); + print_deferred_open_table((struct deferred_open_data*)dbuf.dptr); + SAFE_FREE(dbuf.dptr); + return ret; +} + +/******************************************************************* + Fill a deferred open entry. +********************************************************************/ + +static void fill_deferred_open(char *p, uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port) +{ + deferred_open_entry *e = (deferred_open_entry *)p; + void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */ + + memset(e, '\0', sizeof(deferred_open_entry)); + e->mid = mid; + e->pid = sys_getpid(); + memcpy(x, ptv, sizeof(struct timeval)); + e->dev = dev; + e->inode = inode; + e->port = port; +} + +/******************************************************************* + Add a deferred open record. Return False on fail, True on success. +********************************************************************/ + +BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port, const char *fname) +{ + TDB_DATA dbuf; + struct deferred_open_data *data; + char *p=NULL; + int size; + TDB_DATA key = deferred_open_locking_key(dev, inode); + BOOL ret = True; + + /* read in the existing deferred open records if any */ + dbuf = tdb_fetch(tdb, key); + if (!dbuf.dptr) { + size_t offset; + /* we'll need to create a new record */ + + size = sizeof(*data) + sizeof(deferred_open_entry) + strlen(fname) + 1; + p = (char *)malloc(size); + if (!p) + return False; + data = (struct deferred_open_data *)p; + data->u.num_deferred_open_entries = 1; + + DEBUG(10,("add_deferred_open: creating entry for file %s. num_deferred_open_entries = 1\n", + fname )); + + offset = sizeof(*data) + sizeof(deferred_open_entry); + safe_strcpy(p + offset, fname, size - offset - 1); + fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port); + dbuf.dptr = p; + dbuf.dsize = size; + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) + ret = False; + + print_deferred_open_table((struct deferred_open_data *)p); + + SAFE_FREE(p); + return ret; + } + + /* we're adding to an existing entry - this is a bit fiddly */ + data = (struct deferred_open_data *)dbuf.dptr; + + data->u.num_deferred_open_entries++; + + DEBUG(10,("add_deferred_open: adding entry for file %s. new num_deferred_open_entries = %d\n", + fname, data->u.num_deferred_open_entries )); + + size = dbuf.dsize + sizeof(deferred_open_entry); + p = malloc(size); + if (!p) { + SAFE_FREE(dbuf.dptr); + return False; + } + memcpy(p, dbuf.dptr, sizeof(*data)); + fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port); + memcpy(p + sizeof(*data) + sizeof(deferred_open_entry), dbuf.dptr + sizeof(*data), + dbuf.dsize - sizeof(*data)); + SAFE_FREE(dbuf.dptr); + dbuf.dptr = p; + dbuf.dsize = size; + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) + ret = False; + print_deferred_open_table((struct deferred_open_data *)p); + SAFE_FREE(p); + return ret; +} + /**************************************************************************** Traverse the whole database with this function, calling traverse_callback on each share mode @@ -862,6 +1240,10 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state; + /* Ensure this is a locking_key record. */ + if (kbuf.dsize != sizeof(struct locking_key)) + return 0; + data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); name = dbuf.dptr + sizeof(*data) + data->u.num_share_mode_entries*sizeof(*shares); -- cgit From f820b921cdeba93f21237e32f9872340d3afc347 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 19 Sep 2004 01:16:45 +0000 Subject: r2413: Arggg. Stupid, stupid, stupid me ! I added a paranoia test case when I was developing the deferred open case and made it too tight. It will fire (incorrectly) and panic when a client does a second open for a file with a different mid (multiplex-id) request. Doh ! This is a perfectly valid thing for a client to do (have two pending opens with different mids outstanding on the same file) and currently when the first pending open expires with a share violation the paranoia code will panic smbd. It's a rare condition, but obvious now I've looked at the code. Fix for bug #1743. Jeremy. (This used to be commit e1bf108ae965ae730c67524164fa36497ea905b5) --- source3/locking/locking.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8f53b55fc5..d4e8c493d5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1043,18 +1043,6 @@ int get_deferred_opens(connection_struct *conn, static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_open_entry *e2) { -#if 1 /* JRA PARANOIA TEST - REMOVE LATER */ - if (e1->pid == e2->pid && - e1->port == e2->port && - e1->dev == e2->dev && - e1->inode == e2->inode && - ((e1->time.tv_sec != e2->time.tv_sec) || - (e1->time.tv_usec != e2->time.tv_usec) || - (e1->mid != e2->mid))) { - smb_panic("PANIC: deferred_open_entries_identical: logic error.\n"); - } -#endif - return (e1->pid == e2->pid && e1->mid == e2->mid && e1->port == e2->port && @@ -1064,7 +1052,6 @@ static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_o e1->time.tv_usec == e2->time.tv_usec); } - /******************************************************************* Delete a specific deferred open entry. Ignore if no entry deleted. -- cgit From b0202c7b851bb15f856ba526857e8b2f7cfabfec Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 00:22:11 +0000 Subject: r3008: when checking for the existance of a lock we are only doing a single tdb call, so there is no need to get the chainlock. This reduces the number of tdb locking calls made on file IO (This used to be commit 78e904c27b31d7123b521c446247d6ff558c84cc) --- source3/locking/brlock.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 990a6a25d2..4c34bd7dfd 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -563,7 +563,6 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, dbuf.dptr = NULL; - tdb_chainlock(tdb, kbuf); dbuf = tdb_fetch(tdb, kbuf); lock.context.smbpid = smbpid; @@ -594,12 +593,10 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, /* no conflicts - we could have added it */ SAFE_FREE(dbuf.dptr); - tdb_chainunlock(tdb, kbuf); return True; fail: SAFE_FREE(dbuf.dptr); - tdb_chainunlock(tdb, kbuf); return False; } -- cgit From 8c1c918c94b443c7154d535b1f99201dc1767f97 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Oct 2004 22:01:10 +0000 Subject: r3050: Steal from Samba4 :-). Make us pass most of the new lock tests (except for the cancel lock which I have to add). Jeremy. (This used to be commit cf7f89999e0c6becd4617c812400d1e71b9c0a30) --- source3/locking/brlock.c | 73 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 17 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 4c34bd7dfd..61144eb59a 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -91,6 +91,28 @@ static BOOL brl_same_context(struct lock_context *ctx1, (ctx1->tid == ctx2->tid); } +/**************************************************************************** + See if lck1 and lck2 overlap. +****************************************************************************/ + +static BOOL brl_overlap(struct lock_struct *lck1, + struct lock_struct *lck2) +{ + /* this extra check is not redundent - it copes with locks + that go beyond the end of 64 bit file space */ + if (lck1->size != 0 && + lck1->start == lck2->start && + lck1->size == lck2->size) { + return True; + } + + if (lck1->start >= (lck2->start+lck2->size) || + lck2->start >= (lck1->start+lck1->size)) { + return False; + } + return True; +} + /**************************************************************************** See if lock2 can be added when lock1 is in place. ****************************************************************************/ @@ -115,7 +137,7 @@ static BOOL brl_conflict(struct lock_struct *lck1, return False; } - return True; + return brl_overlap(lck1, lck2); } #if ZERO_ZERO @@ -175,9 +197,36 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck lck2->start >= (lck1->start + lck1->size)) return False; - return True; + return brl_overlap(lck1, lck2); } +/**************************************************************************** + Amazingly enough, w2k3 "remembers" whether the last lock failure + is the same as this one and changes its error code. I wonder if any + app depends on this ? +****************************************************************************/ + +static NTSTATUS brl_lock_failed(struct lock_struct *lock) +{ + static struct lock_struct last_lock_failure; + + if (brl_same_context(&lock->context, &last_lock_failure.context) && + lock->fnum == last_lock_failure.fnum && + lock->start == last_lock_failure.start && + lock->size == last_lock_failure.size) { + return NT_STATUS_FILE_LOCK_CONFLICT; + } + last_lock_failure = *lock; + if (lock->start >= 0xEF000000 && + (lock->start >> 63) == 0) { + /* amazing the little things you learn with a test + suite. Locks beyond this offset (as a 64 bit + number!) always generate the conflict error code, + unless the top bit is set */ + return NT_STATUS_FILE_LOCK_CONFLICT; + } + return NT_STATUS_LOCK_NOT_GRANTED; +} #if DONT_DO_THIS /* doing this traversal could kill solaris machines under high load (tridge) */ @@ -313,8 +362,6 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, struct lock_struct lock, *locks; char *tp; NTSTATUS status = NT_STATUS_OK; - static int last_failed = -1; - static br_off last_failed_start; *my_lock_ctx = False; kbuf = locking_key(dev,ino); @@ -344,7 +391,7 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, count = dbuf.dsize / sizeof(*locks); for (i=0; i Date: Thu, 21 Oct 2004 18:39:16 +0000 Subject: r3120: Fix bug #1955 reported by Love . Inconsistent error return. Jeremy. (This used to be commit c6b144654ae544c86f7caa35483e25f0cfe5e904) --- source3/locking/posix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 6173c80b2f..0e5edfa0eb 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -238,7 +238,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) if (!add_fd_to_close_entry(fsp)) { SAFE_FREE(entries); - return False; + return -1; } SAFE_FREE(entries); @@ -281,9 +281,9 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) ret = SMB_VFS_CLOSE(fsp,fsp->fd); if (saved_errno != 0) { - errno = saved_errno; + errno = saved_errno; ret = -1; - } + } fsp->fd = -1; -- cgit From acf9d61421faa6c0055d57fdee7db300dc5431aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Dec 2004 18:25:53 +0000 Subject: r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation functions so we can funnel through some well known functions. Should help greatly with malloc checking. HEAD patch to follow. Jeremy. (This used to be commit 620f2e608f70ba92f032720c031283d295c5c06a) --- source3/locking/brlock.c | 2 +- source3/locking/locking.c | 8 ++++---- source3/locking/posix.c | 11 +++++------ 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 61144eb59a..d92027e267 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -407,7 +407,7 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, } /* no conflicts - add it to the list of locks */ - tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*locks)); + tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(*locks)); if (!tp) { status = NT_STATUS_NO_MEMORY; goto fail; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d4e8c493d5..b2f30a5684 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -679,7 +679,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) pstrcat(fname, fsp->fsp_name); size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1; - p = (char *)malloc(size); + p = (char *)SMB_MALLOC(size); if (!p) return False; data = (struct locking_data *)p; @@ -711,7 +711,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) fsp->fsp_name, data->u.num_share_mode_entries )); size = dbuf.dsize + sizeof(share_mode_entry); - p = malloc(size); + p = SMB_MALLOC(size); if (!p) { SAFE_FREE(dbuf.dptr); return False; @@ -1161,7 +1161,7 @@ BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T /* we'll need to create a new record */ size = sizeof(*data) + sizeof(deferred_open_entry) + strlen(fname) + 1; - p = (char *)malloc(size); + p = (char *)SMB_MALLOC(size); if (!p) return False; data = (struct deferred_open_data *)p; @@ -1193,7 +1193,7 @@ BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T fname, data->u.num_deferred_open_entries )); size = dbuf.dsize + sizeof(deferred_open_entry); - p = malloc(size); + p = SMB_MALLOC(size); if (!p) { SAFE_FREE(dbuf.dptr); return False; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 0e5edfa0eb..6ab2ed377e 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -102,7 +102,7 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(int)); + tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); if (!tp) { DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n")); SAFE_FREE(dbuf.dptr); @@ -371,7 +371,7 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s pl.size = size; pl.lock_type = lock_type; - tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl)); + tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(pl)); if (!tp) { DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); goto fail; @@ -896,8 +896,7 @@ BECOMES..... | l_curr| | l_new | +-------+ +---------+ **********************************************/ - struct lock_list *l_new = (struct lock_list *)talloc(ctx, - sizeof(struct lock_list)); + struct lock_list *l_new = TALLOC_P(ctx, struct lock_list); if(l_new == NULL) { DEBUG(0,("posix_lock_list: talloc fail.\n")); @@ -1002,7 +1001,7 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou return True; /* Not a fatal error. */ } - if ((ll = (struct lock_list *)talloc(l_ctx, sizeof(struct lock_list))) == NULL) { + if ((ll = TALLOC_P(l_ctx, struct lock_list)) == NULL) { DEBUG(0,("set_posix_lock: unable to talloc unlock list.\n")); talloc_destroy(l_ctx); return True; /* Not a fatal error. */ @@ -1148,7 +1147,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u return True; /* Not a fatal error. */ } - if ((ul = (struct lock_list *)talloc(ul_ctx, sizeof(struct lock_list))) == NULL) { + if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) { DEBUG(0,("release_posix_lock: unable to talloc unlock list.\n")); talloc_destroy(ul_ctx); return True; /* Not a fatal error. */ -- cgit From 695188cc262c08807760670c2b6d8c70deda2cdc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Dec 2004 01:07:06 +0000 Subject: r4108: As check_self is *always* False in every invokation, remove the logic for it. We still pass Samba4 RAW-LOCK test. Jeremy. (This used to be commit 596f23051363f8cc8896119b3eca0663a61a38c3) --- source3/locking/brlock.c | 17 ++++++----------- source3/locking/locking.c | 7 ++----- 2 files changed, 8 insertions(+), 16 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index d92027e267..3451b0cc1a 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -592,7 +592,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, - enum brl_type lock_type, int check_self) + enum brl_type lock_type) { TDB_DATA kbuf, dbuf; int count, i; @@ -617,16 +617,11 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, locks = (struct lock_struct *)dbuf.dptr; count = dbuf.dsize / sizeof(*locks); for (i=0; idev, fsp->inode, fsp->fnum, global_smbpid, sys_getpid(), conn->cnum, - offset, count, lock_type, check_self); + offset, count, lock_type); DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n", (double)offset, (double)count, ret ? "locked" : "unlocked", -- cgit From 822fcec39d6597524a94b0e8b9c244d5eb62b972 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Dec 2004 22:10:40 +0000 Subject: r4121: Optimisation from Nadav Danieli . If we're oplocked, short circuit some is_locked() tests. Jeremy. (This used to be commit f4feed8f90be98eaea59bebcc142fd398ffe2a59) --- source3/locking/locking.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index b6e2ced336..4c6d89571e 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -77,9 +77,17 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) { + DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name )); + ret = 0; + } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK)) { + DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); + ret = 0; + } else { + ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, global_smbpid, sys_getpid(), conn->cnum, offset, count, lock_type); + } DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n", (double)offset, (double)count, ret ? "locked" : "unlocked", -- cgit From 934566332835eed5a3b768e07642c569eca37001 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 11 Dec 2004 00:30:28 +0000 Subject: r4143: Make strict locking an enum. Auto means use oplock optimization. Jeremy. (This used to be commit 0dd4adeae2042d0ea64398a78b3f48eb0150c133) --- source3/locking/locking.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4c6d89571e..e10e8a1fa0 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -69,24 +69,31 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, enum brl_type lock_type) { int snum = SNUM(conn); + int strict_locking = lp_strict_locking(snum); BOOL ret; if (count == 0) return(False); - if (!lp_locking(snum) || !lp_strict_locking(snum)) + if (!lp_locking(snum) || !strict_locking) return(False); - if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) { - DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name )); - ret = 0; - } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK)) { - DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); - ret = 0; + if (strict_locking == Auto) { + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) { + DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name )); + ret = 0; + } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK)) { + DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); + ret = 0; + } else { + ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, + global_smbpid, sys_getpid(), conn->cnum, + offset, count, lock_type); + } } else { ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, sys_getpid(), conn->cnum, - offset, count, lock_type); + global_smbpid, sys_getpid(), conn->cnum, + offset, count, lock_type); } DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n", -- cgit From c4591307aacd87fa2a6a167a4d75d889c5dd63bf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Mar 2005 20:19:10 +0000 Subject: r5625: Reformat (tidy). (This used to be commit b94db3a75806f1b09a8a0366029812ba2195727c) --- source3/locking/posix.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 6ab2ed377e..95d4518c17 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -563,9 +563,9 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, * and the underlying system can handle 64 bit signed locks. */ - SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); - SMB_OFF_T mask = (mask2<<1); - SMB_OFF_T max_positive_lock_offset = ~mask; + SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); + SMB_OFF_T mask = (mask2<<1); + SMB_OFF_T max_positive_lock_offset = ~mask; #else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ @@ -575,7 +575,7 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, * All offsets & counts must be 2^31 or less. */ - SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF; + SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF; #endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ -- cgit From 8dddd763d876cc7a340ffb7813f87187d77b84f2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Mar 2005 02:07:00 +0000 Subject: r5634: Fix 64-bit overflow problems found by BlueArc torture tester. We still have a few strange bugs with 64-bit locking values. I will get traces. Jeremy. (This used to be commit ff4c201d93e1f59ce61e9341f7f94ce92389ed7b) --- source3/locking/brlock.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 3451b0cc1a..09c96b1286 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -132,11 +132,6 @@ static BOOL brl_conflict(struct lock_struct *lck1, return False; } - if (lck1->start >= (lck2->start + lck2->size) || - lck2->start >= (lck1->start + lck1->size)) { - return False; - } - return brl_overlap(lck1, lck2); } @@ -193,10 +188,6 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck return False; } - if (lck1->start >= (lck2->start + lck2->size) || - lck2->start >= (lck1->start + lck1->size)) - return False; - return brl_overlap(lck1, lck2); } -- cgit From ed1f7121a39d863066ef47e985b77fe3dbedbc9b Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 27 Apr 2005 18:32:37 +0000 Subject: r6502: add LOCKING debug class - pull PRINTINGDB class definition from trunk so our numbers don't get out of sync (This used to be commit 58e307664e02ebf0415f19ed625d2f166d9cb1cc) --- source3/locking/brlock.c | 3 +++ source3/locking/locking.c | 3 +++ source3/locking/posix.c | 3 +++ 3 files changed, 9 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 09c96b1286..da7fc1e67d 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -27,6 +27,9 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_LOCKING + #define ZERO_ZERO 0 /* This contains elements that differentiate locks. The smbpid is a diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e10e8a1fa0..75b40d74a4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -37,6 +37,9 @@ #include "includes.h" uint16 global_smbpid; +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_LOCKING + /* the locking database handle */ static TDB_CONTEXT *tdb; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 95d4518c17..5b001b7141 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -24,6 +24,9 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_LOCKING + /* * The POSIX locking database handle. */ -- cgit From fc396cb2202dadc9acf741957d2dc3420bd0a7ac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 1 May 2005 07:01:18 +0000 Subject: r6543: Fix EDEADLCK problem with deferred open calls. Problem found by "Hu, David J" Jeremy. (This used to be commit ec86ac4b28e99df41d3dd77586ea259500e5dfcd) --- source3/locking/locking.c | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 75b40d74a4..f0a45c2bcb 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -42,6 +42,7 @@ uint16 global_smbpid; /* the locking database handle */ static TDB_CONTEXT *tdb; +static TDB_CONTEXT *deferred_open_tdb; struct locking_data { union { @@ -318,7 +319,21 @@ BOOL locking_init(int read_only) DEBUG(0,("ERROR: Failed to initialise locking database\n")); return False; } - + + if (!read_only && !deferred_open_tdb) { + deferred_open_tdb = tdb_open_log(lock_path("deferred_open.tdb"), + 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, + O_RDWR|O_CREAT, + 0644); + + if (!deferred_open_tdb) { + DEBUG(0,("ERROR: Failed to initialise deferred open database\n")); + tdb_close(tdb); + tdb = NULL; + return False; + } + } + if (!posix_locking_init(read_only)) return False; @@ -333,15 +348,20 @@ BOOL locking_init(int read_only) BOOL locking_end(void) { + BOOL ret = True; brl_shutdown(open_read_only); if (tdb) { - if (tdb_close(tdb) != 0) - return False; + ret = False; } - return True; + if (deferred_open_tdb) { + if (tdb_close(tdb) != 0) + ret = False; + } + + return ret; } /******************************************************************* @@ -975,7 +995,7 @@ int get_deferred_opens(connection_struct *conn, *pp_de_entries = NULL; - dbuf = tdb_fetch(tdb, key); + dbuf = tdb_fetch(deferred_open_tdb, key); if (!dbuf.dptr) return 0; @@ -1032,13 +1052,13 @@ int get_deferred_opens(connection_struct *conn, dbuf.dsize -= del_count * sizeof(deferred_open_entry); if (data->u.num_deferred_open_entries == 0) { - if (tdb_delete(tdb, key) == -1) { + if (tdb_delete(deferred_open_tdb, key) == -1) { SAFE_FREE(de_entries); SAFE_FREE(dbuf.dptr); return 0; } } else { - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { + if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) { SAFE_FREE(de_entries); SAFE_FREE(dbuf.dptr); return 0; @@ -1082,7 +1102,7 @@ BOOL delete_deferred_open_entry(deferred_open_entry *entry) TDB_DATA key = deferred_open_locking_key(entry->dev, entry->inode); /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, key); + dbuf = tdb_fetch(deferred_open_tdb, key); if (!dbuf.dptr) return -1; @@ -1125,10 +1145,10 @@ BOOL delete_deferred_open_entry(deferred_open_entry *entry) /* store it back in the database */ if (data->u.num_deferred_open_entries == 0) { - if (tdb_delete(tdb, key) == -1) + if (tdb_delete(deferred_open_tdb, key) == -1) ret = False; } else { - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) + if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) ret = False; } } @@ -1170,7 +1190,7 @@ BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T BOOL ret = True; /* read in the existing deferred open records if any */ - dbuf = tdb_fetch(tdb, key); + dbuf = tdb_fetch(deferred_open_tdb, key); if (!dbuf.dptr) { size_t offset; /* we'll need to create a new record */ @@ -1190,7 +1210,7 @@ BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port); dbuf.dptr = p; dbuf.dsize = size; - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) + if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) ret = False; print_deferred_open_table((struct deferred_open_data *)p); @@ -1220,7 +1240,7 @@ BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T SAFE_FREE(dbuf.dptr); dbuf.dptr = p; dbuf.dsize = size; - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) + if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) ret = False; print_deferred_open_table((struct deferred_open_data *)p); SAFE_FREE(p); -- cgit From 114067ced1d301a3c8b67aee0af0eab771d44dd4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 May 2005 07:27:44 +0000 Subject: r6594: Fix silly typo causing tdb to be freed twice. Jeremy. (This used to be commit 4f431dfc6b57e1609672c4daa53ab5d62613f6d1) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f0a45c2bcb..3c5ab63b4a 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -357,7 +357,7 @@ BOOL locking_end(void) } if (deferred_open_tdb) { - if (tdb_close(tdb) != 0) + if (tdb_close(deferred_open_tdb) != 0) ret = False; } -- cgit From 3d306127aaa69d22d8494fa291e3feaa15bcde53 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Jun 2005 01:05:59 +0000 Subject: r7972: Tidy up the posix locking in memory db code whilst I'm waiting for jht to get back to me with a backtrace. Jeremy. (This used to be commit f2bcfdddc769a2939b03a1a6742fec86712c9097) --- source3/locking/posix.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 5b001b7141..3859896c47 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -332,7 +332,7 @@ static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry) if (entry < count-1) { memmove(&locks[entry], &locks[entry+1], sizeof(*locks)*((count-1) - entry)); } - dbuf.dsize -= sizeof(*locks); + dbuf.dsize -= sizeof(struct posix_lock); tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); } @@ -360,10 +360,11 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s char *tp; dbuf.dptr = NULL; + dbuf.dsize = 0; dbuf = tdb_fetch(posix_lock_tdb, kbuf); - *pentry_num = (size_t)(dbuf.dsize / sizeof(pl)); + *pentry_num = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); /* * Add new record. @@ -374,15 +375,15 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s pl.size = size; pl.lock_type = lock_type; - tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(pl)); + tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock)); if (!tp) { DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); goto fail; } else dbuf.dptr = tp; - memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl)); - dbuf.dsize += sizeof(pl); + memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock)); + dbuf.dsize += sizeof(struct posix_lock); if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name)); @@ -443,7 +444,7 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T /* There are existing locks - find a match. */ locks = (struct posix_lock *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(*locks)); + count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); /* * Search for and delete the first record that matches the @@ -466,9 +467,9 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T tdb_delete(posix_lock_tdb, kbuf); } else { if (i < count-1) { - memmove(&locks[i], &locks[i+1], sizeof(*locks)*((count-1) - i)); + memmove(&locks[i], &locks[i+1], sizeof(struct posix_lock)*((count-1) - i)); } - dbuf.dsize -= sizeof(*locks); + dbuf.dsize -= sizeof(struct posix_lock); tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); } count--; @@ -530,12 +531,12 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) return F_WRLCK; } - /* - * This return should be the most normal, as we attempt - * to always open files read/write. - */ + /* + * This return should be the most normal, as we attempt + * to always open files read/write. + */ - return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK; + return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK; } /**************************************************************************** @@ -545,7 +546,7 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) ****************************************************************************/ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, - SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) + SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) { SMB_OFF_T offset = (SMB_OFF_T)u_offset; SMB_OFF_T count = (SMB_OFF_T)u_count; @@ -722,10 +723,10 @@ BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_co */ struct lock_list { - struct lock_list *next; - struct lock_list *prev; - SMB_OFF_T start; - SMB_OFF_T size; + struct lock_list *next; + struct lock_list *prev; + SMB_OFF_T start; + SMB_OFF_T size; }; /**************************************************************************** @@ -749,7 +750,7 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea return lhead; locks = (struct posix_lock *)dbuf.dptr; - num_locks = (size_t)(dbuf.dsize / sizeof(*locks)); + num_locks = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); /* * Check the current lock list on this dev/inode pair. @@ -1128,7 +1129,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u num_overlapped_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock); if (num_overlapped_entries == -1) { - smb_panic("release_posix_lock: unable find entry to delete !\n"); + smb_panic("release_posix_lock: unable find entry to delete !\n"); } /* -- cgit From 74563c5806c23735a90b4ab3323ffa9875dce609 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Jun 2005 01:37:19 +0000 Subject: r7975: One more tidyup to ensure we're using "struct posix_lock". Jeremy. (This used to be commit 960a5d37d1cfa25e4f7491b175dab68ac9f37c43) --- source3/locking/posix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 3859896c47..218c441028 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -102,6 +102,7 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) char *tp; dbuf.dptr = NULL; + dbuf.dsize = 0; dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); @@ -330,7 +331,7 @@ static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry) tdb_delete(posix_lock_tdb, kbuf); } else { if (entry < count-1) { - memmove(&locks[entry], &locks[entry+1], sizeof(*locks)*((count-1) - entry)); + memmove(&locks[entry], &locks[entry+1], sizeof(struct posix_lock)*((count-1) - entry)); } dbuf.dsize -= sizeof(struct posix_lock); tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); -- cgit From af8a691db11a5072865f8b03fd1cbd3aab5cb6d7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Jul 2005 04:51:27 +0000 Subject: r8219: Merge the new open code from HEAD to 3.0. Haven't yet run the torture tests on this as it's very late NY time (just wanted to get this work into the tree). I'll test this over the weekend.... Jerry - in looking at the difference between the two trees there seem to be some printing/ntprinting.c and registry changes we might want to examine to try keep in sync. Jeremy. (This used to be commit c7fe18761e2c753afbffd3a78abff46472a9b8eb) --- source3/locking/locking.c | 120 ++++++++++++++++++++++++++-------------------- source3/locking/posix.c | 38 ++++++++------- 2 files changed, 90 insertions(+), 68 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 3c5ab63b4a..5bcf7f2eda 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -3,6 +3,7 @@ Locking functions Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1992-2000 + Copyright (C) Volker Lendecke 2005 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 @@ -46,7 +47,10 @@ static TDB_CONTEXT *deferred_open_tdb; struct locking_data { union { - int num_share_mode_entries; + struct { + int num_share_mode_entries; + BOOL delete_on_close; + } s; share_mode_entry dummy; /* Needed for alignment. */ } u; /* the following two entries are implicit @@ -432,10 +436,14 @@ char *share_mode_str(int num, share_mode_entry *e) { static pstring share_str; - slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: \ -pid = %lu, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f", - num, (unsigned long)e->pid, e->share_mode, (unsigned int)e->desired_access, e->op_port, e->op_type, e->share_file_id, - (unsigned int)e->dev, (double)e->inode ); + slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: " + "pid = %lu, share_access = 0x%x, private_options = 0x%x, " + "access_mask = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, " + "dev = 0x%x, inode = %.0f", + num, (unsigned long)e->pid, + e->share_access, e->private_options, + e->access_mask, e->op_port, e->op_type, e->share_file_id, + (unsigned int)e->dev, (double)e->inode ); return share_str; } @@ -446,7 +454,7 @@ pid = %lu, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, fi static void print_share_mode_table(struct locking_data *data) { - int num_share_modes = data->u.num_share_mode_entries; + int num_share_modes = data->u.s.num_share_mode_entries; share_mode_entry *shares = (share_mode_entry *)(data + 1); int i; @@ -460,9 +468,9 @@ static void print_share_mode_table(struct locking_data *data) Get all share mode entries for a dev/inode pair. ********************************************************************/ -int get_share_modes(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry **pp_shares) +int get_share_modes(SMB_DEV_T dev, SMB_INO_T inode, + share_mode_entry **pp_shares, + BOOL *delete_on_close) { TDB_DATA dbuf; struct locking_data *data; @@ -470,13 +478,18 @@ int get_share_modes(connection_struct *conn, share_mode_entry *shares = NULL; TDB_DATA key = locking_key(dev, inode); *pp_shares = NULL; + *delete_on_close = False; dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) return 0; data = (struct locking_data *)dbuf.dptr; - num_share_modes = data->u.num_share_mode_entries; + + *delete_on_close = data->u.s.delete_on_close; + DEBUG(10, ("get_share_modes: delete_on_close: %d\n", + *delete_on_close)); + num_share_modes = data->u.s.num_share_mode_entries; if(num_share_modes) { pstring fname; int i; @@ -515,7 +528,7 @@ int get_share_modes(connection_struct *conn, /* Did we delete any ? If so, re-store in tdb. */ if (del_count) { - data->u.num_share_mode_entries = num_share_modes; + data->u.s.num_share_mode_entries = num_share_modes; if (num_share_modes) { memcpy(dbuf.dptr + sizeof(*data), shares, @@ -527,7 +540,7 @@ int get_share_modes(connection_struct *conn, /* The record has shrunk a bit */ dbuf.dsize -= del_count * sizeof(share_mode_entry); - if (data->u.num_share_mode_entries == 0) { + if (data->u.s.num_share_mode_entries == 0) { if (tdb_delete(tdb, key) == -1) { SAFE_FREE(shares); SAFE_FREE(dbuf.dptr); @@ -548,6 +561,15 @@ int get_share_modes(connection_struct *conn, return num_share_modes; } +BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) +{ + share_mode_entry *shares; + BOOL result; + get_share_modes(dev, inode, &shares, &result); + SAFE_FREE(shares); + return result; +} + /******************************************************************* Fill a share mode entry. ********************************************************************/ @@ -559,8 +581,9 @@ static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_t memset(e, '\0', sizeof(share_mode_entry)); e->pid = sys_getpid(); - e->share_mode = fsp->share_mode; - e->desired_access = fsp->desired_access; + e->share_access = fsp->share_access; + e->private_options = fsp->fh->private_options; + e->access_mask = fsp->access_mask; e->op_port = port; e->op_type = op_type; memcpy(x, &fsp->open_time, sizeof(struct timeval)); @@ -581,16 +604,17 @@ BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) e1->share_file_id == e2->share_file_id && e1->dev == e2->dev && e1->inode == e2->inode && - (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) != (e2->share_mode & ~DELETE_ON_CLOSE_FLAG)) { - DEBUG(0,("PANIC: share_modes_identical: share_mode missmatch (e1 = %u, e2 = %u). Logic error.\n", - (unsigned int)(e1->share_mode & ~DELETE_ON_CLOSE_FLAG), - (unsigned int)(e2->share_mode & ~DELETE_ON_CLOSE_FLAG) )); + (e1->share_access) != (e2->share_access)) { + DEBUG(0,("PANIC: share_modes_identical: share_mode " + "mismatch (e1 = 0x%x, e2 = 0x%x). Logic error.\n", + (unsigned int)e1->share_access, + (unsigned int)e2->share_access )); smb_panic("PANIC: share_modes_identical logic error.\n"); } #endif return (e1->pid == e2->pid && - (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) == (e2->share_mode & ~DELETE_ON_CLOSE_FLAG) && + (e1->share_access) == (e2->share_access) && e1->dev == e2->dev && e1->inode == e2->inode && e1->share_file_id == e2->share_file_id ); @@ -602,8 +626,9 @@ BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) Ignore if no entry deleted. ********************************************************************/ -ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry *entry, share_mode_entry **ppse) +ssize_t del_share_entry(SMB_DEV_T dev, SMB_INO_T inode, + share_mode_entry *entry, share_mode_entry **ppse, + BOOL *delete_on_close) { TDB_DATA dbuf; struct locking_data *data; @@ -621,6 +646,7 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, return -1; data = (struct locking_data *)dbuf.dptr; + *delete_on_close = data->u.s.delete_on_close; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); /* @@ -629,15 +655,15 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, * from the record. */ - DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.num_share_mode_entries )); + DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.s.num_share_mode_entries )); - for (i=0;iu.num_share_mode_entries;) { + for (i=0;iu.s.num_share_mode_entries;) { if (share_modes_identical(&shares[i], entry)) { DEBUG(10,("del_share_entry: deleted %s\n", share_mode_str(i, &shares[i]) )); if (ppse) *ppse = memdup(&shares[i], sizeof(*shares)); - data->u.num_share_mode_entries--; + data->u.s.num_share_mode_entries--; if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))) > 0) { memmove(&shares[i], &shares[i+1], dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); @@ -655,10 +681,10 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, /* the record may have shrunk a bit */ dbuf.dsize -= del_count * sizeof(*shares); - count = (ssize_t)data->u.num_share_mode_entries; + count = (ssize_t)data->u.s.num_share_mode_entries; /* store it back in the database */ - if (data->u.num_share_mode_entries == 0) { + if (data->u.s.num_share_mode_entries == 0) { if (tdb_delete(tdb, key) == -1) count = -1; } else { @@ -677,7 +703,8 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, of entries left, and a memdup'ed copy of the entry deleted. ********************************************************************/ -ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse) +ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse, + BOOL *delete_on_close) { share_mode_entry entry; @@ -686,7 +713,8 @@ ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse) */ fill_share_mode((char *)&entry, fsp, 0, 0); - return del_share_entry(fsp->dev, fsp->inode, &entry, ppse); + return del_share_entry(fsp->dev, fsp->inode, &entry, ppse, + delete_on_close); } /******************************************************************* @@ -718,7 +746,8 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) if (!p) return False; data = (struct locking_data *)p; - data->u.num_share_mode_entries = 1; + ZERO_STRUCT(data->u); /* Keep valgrind happy */ + data->u.s.num_share_mode_entries = 1; DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n", fsp->fsp_name )); @@ -740,10 +769,10 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) /* we're adding to an existing entry - this is a bit fiddly */ data = (struct locking_data *)dbuf.dptr; - data->u.num_share_mode_entries++; + data->u.s.num_share_mode_entries++; DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n", - fsp->fsp_name, data->u.num_share_mode_entries )); + fsp->fsp_name, data->u.s.num_share_mode_entries )); size = dbuf.dsize + sizeof(share_mode_entry); p = SMB_MALLOC(size); @@ -790,7 +819,7 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); /* find any with our pid and call the supplied function */ - for (i=0;iu.num_share_mode_entries;i++) { + for (i=0;iu.s.num_share_mode_entries;i++) { if (share_modes_identical(entry, &shares[i])) { mod_fn(&shares[i], dev, inode, param); need_store=True; @@ -799,7 +828,7 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en /* if the mod fn was called then store it back */ if (need_store) { - if (data->u.num_share_mode_entries == 0) { + if (data->u.s.num_share_mode_entries == 0) { if (tdb_delete(tdb, key) == -1) ret = False; } else { @@ -877,8 +906,7 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) { TDB_DATA dbuf; struct locking_data *data; - int i; - share_mode_entry *shares; + BOOL res; TDB_DATA key = locking_key(dev, inode); /* read in the existing share modes */ @@ -887,25 +915,14 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) return False; data = (struct locking_data *)dbuf.dptr; - shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); /* Set/Unset the delete on close element. */ - for (i=0;iu.num_share_mode_entries;i++,shares++) { - shares->share_mode = (delete_on_close ? - (shares->share_mode | DELETE_ON_CLOSE_FLAG) : - (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) ); - } + data->u.s.delete_on_close = delete_on_close; - /* store it back */ - if (data->u.num_share_mode_entries) { - if (tdb_store(tdb, key, dbuf, TDB_REPLACE)==-1) { - SAFE_FREE(dbuf.dptr); - return False; - } - } + res = (tdb_store(tdb, key, dbuf, TDB_REPLACE)!=-1); SAFE_FREE(dbuf.dptr); - return True; + return res; } /******************************************************************* @@ -1200,6 +1217,7 @@ BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T if (!p) return False; data = (struct deferred_open_data *)p; + ZERO_STRUCT(data->u.dummy); /* Keep valgrind happy */ data->u.num_deferred_open_entries = 1; DEBUG(10,("add_deferred_open: creating entry for file %s. num_deferred_open_entries = 1\n", @@ -1268,9 +1286,9 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - name = dbuf.dptr + sizeof(*data) + data->u.num_share_mode_entries*sizeof(*shares); + name = dbuf.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares); - for (i=0;iu.num_share_mode_entries;i++) { + for (i=0;iu.s.num_share_mode_entries;i++) { traverse_callback(&shares[i], name); } return 0; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 218c441028..c63992adc5 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -114,7 +114,7 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) } else dbuf.dptr = tp; - memcpy(dbuf.dptr + dbuf.dsize, &fsp->fd, sizeof(int)); + memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int)); dbuf.dsize += sizeof(int); if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { @@ -209,8 +209,8 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) /* * No POSIX to worry about, just close. */ - ret = SMB_VFS_CLOSE(fsp,fsp->fd); - fsp->fd = -1; + ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); + fsp->fh->fd = -1; return ret; } @@ -227,7 +227,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) */ for (i = 0; i < count; i++) { - if (entries[i].fd != fsp->fd) { + if (entries[i].fd != fsp->fh->fd) { locks_on_other_fds = True; break; } @@ -237,7 +237,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) /* * There are outstanding locks on this dev/inode pair on other fds. - * Add our fd to the pending close tdb and set fsp->fd to -1. + * Add our fd to the pending close tdb and set fsp->fh->fd to -1. */ if (!add_fd_to_close_entry(fsp)) { @@ -246,7 +246,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) } SAFE_FREE(entries); - fsp->fd = -1; + fsp->fh->fd = -1; return 0; } @@ -282,14 +282,14 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) * Finally close the fd associated with this fsp. */ - ret = SMB_VFS_CLOSE(fsp,fsp->fd); + ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); if (saved_errno != 0) { errno = saved_errno; ret = -1; } - fsp->fd = -1; + fsp->fh->fd = -1; return ret; } @@ -371,7 +371,7 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s * Add new record. */ - pl.fd = fsp->fd; + pl.fd = fsp->fh->fd; pl.start = start; pl.size = size; pl.lock_type = lock_type; @@ -455,7 +455,7 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T for (i=0; ifd == fsp->fd && + if (entry->fd == fsp->fh->fd && entry->start == start && entry->size == size) { @@ -490,7 +490,7 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T for (i = 0; i < count; i++) { struct posix_lock *entry = &locks[i]; - if (fsp->fd == entry->fd && + if (fsp->fh->fd == entry->fd && does_lock_overlap( start, size, entry->start, entry->size)) num_overlapping_records++; } @@ -524,13 +524,17 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) */ DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n")); return F_RDLCK; - } else if((lock_type == READ_LOCK) && !fsp->can_read) { + } +#if 0 + /* We no longer open files write-only. */ + else if((lock_type == READ_LOCK) && !fsp->can_read) { /* * Ditto for read locks on write only files. */ DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n")); return F_WRLCK; } +#endif /* * This return should be the most normal, as we attempt @@ -652,9 +656,9 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF { int ret; - DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fd,op,(double)offset,(double)count,type)); + DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type)); - ret = SMB_VFS_LOCK(fsp,fsp->fd,op,offset,count,type); + ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { @@ -678,7 +682,7 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); errno = 0; count &= 0x7fffffff; - ret = SMB_VFS_LOCK(fsp,fsp->fd,op,offset,count,type); + ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); } } @@ -1247,7 +1251,7 @@ void posix_locking_close_file(files_struct *fsp) } for (i = 0; i < count; i++) { - if (entries[i].fd != fsp->fd ) + if (entries[i].fd != fsp->fh->fd ) break; dump_entry(&entries[i]); @@ -1269,7 +1273,7 @@ void posix_locking_close_file(files_struct *fsp) for (i = 0; i < count; i++) { struct posix_lock *pl = &entries[i]; - if (pl->fd == fsp->fd) + if (pl->fd == fsp->fh->fd) release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size ); } SAFE_FREE(entries); -- cgit From 54abd2aa66069e6baf7769c496f46d9dba18db39 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 30 Sep 2005 17:13:37 +0000 Subject: r10656: BIG merge from trunk. Features not copied over * \PIPE\unixinfo * winbindd's {group,alias}membership new functions * winbindd's lookupsids() functionality * swat (trunk changes to be reverted as per discussion with Deryck) (This used to be commit 939c3cb5d78e3a2236209b296aa8aba8bdce32d3) --- source3/locking/brlock.c | 24 +- source3/locking/locking.c | 1204 +++++++++++++++++---------------------------- 2 files changed, 467 insertions(+), 761 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index da7fc1e67d..25a1ed5e2f 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -39,7 +39,7 @@ struct lock_context { uint16 smbpid; uint16 tid; - pid_t pid; + struct process_id pid; }; /* The data in brlock records is an unsorted linear array of these @@ -89,9 +89,9 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) static BOOL brl_same_context(struct lock_context *ctx1, struct lock_context *ctx2) { - return (ctx1->pid == ctx2->pid) && + return (procid_equal(&ctx1->pid, &ctx2->pid) && (ctx1->smbpid == ctx2->smbpid) && - (ctx1->tid == ctx2->tid); + (ctx1->tid == ctx2->tid)); } /**************************************************************************** @@ -252,7 +252,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat DEBUG(0,("brlock : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n", (unsigned int)lock->context.pid )); - } else if (process_exists(lock->context.pid)) { + } else if (process_exists(&lock->context.pid)) { DEBUG(10,("brlock : delete_fn. pid %u exists.\n", (unsigned int)lock->context.pid )); continue; @@ -347,7 +347,7 @@ static int lock_compare(struct lock_struct *lck1, ****************************************************************************/ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, - uint16 smbpid, pid_t pid, uint16 tid, + uint16 smbpid, struct process_id pid, uint16 tid, br_off start, br_off size, enum brl_type lock_type, BOOL *my_lock_ctx) { @@ -450,7 +450,7 @@ static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pe ****************************************************************************/ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, - uint16 smbpid, pid_t pid, uint16 tid, + uint16 smbpid, struct process_id pid, uint16 tid, br_off start, br_off size, BOOL remove_pending_locks_only, void (*pre_unlock_fn)(void *), @@ -542,8 +542,8 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, /* We could send specific lock info here... */ if (brl_pending_overlap(lock, pend_lock)) { - DEBUG(10,("brl_unlock: sending unlock message to pid %u\n", - (unsigned int)pend_lock->context.pid )); + DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", + procid_str_static(&pend_lock->context.pid ))); message_send_pid(pend_lock->context.pid, MSG_SMB_UNLOCK, @@ -584,7 +584,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, ****************************************************************************/ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, - uint16 smbpid, pid_t pid, uint16 tid, + uint16 smbpid, struct process_id pid, uint16 tid, br_off start, br_off size, enum brl_type lock_type) { @@ -632,7 +632,7 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, Remove any locks associated with a open file. ****************************************************************************/ -void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) +void brl_close(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, int tid, int fnum) { TDB_DATA kbuf, dbuf; int count, i, j, dcount=0; @@ -655,7 +655,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) struct lock_struct *lock = &locks[i]; if (lock->context.tid == tid && - lock->context.pid == pid && + procid_equal(&lock->context.pid, &pid) && lock->fnum == fnum) { /* Send unlock messages to any pending waiters that overlap. */ @@ -667,7 +667,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) continue; if (pend_lock->context.tid == tid && - pend_lock->context.pid == pid && + procid_equal(&pend_lock->context.pid, &pid) && pend_lock->fnum == fnum) continue; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 5bcf7f2eda..e3131e26a2 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -43,7 +43,6 @@ uint16 global_smbpid; /* the locking database handle */ static TDB_CONTEXT *tdb; -static TDB_CONTEXT *deferred_open_tdb; struct locking_data { union { @@ -51,10 +50,10 @@ struct locking_data { int num_share_mode_entries; BOOL delete_on_close; } s; - share_mode_entry dummy; /* Needed for alignment. */ + struct share_mode_entry dummy; /* Needed for alignment. */ } u; /* the following two entries are implicit - share_mode_entry modes[num_share_mode_entries]; + struct share_mode_entry modes[num_share_mode_entries]; char file_name[]; */ }; @@ -90,17 +89,18 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) { DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name )); ret = 0; - } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK)) { + } else if ((fsp->oplock_type == LEVEL_II_OPLOCK) && + (lock_type == READ_LOCK)) { DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); ret = 0; } else { ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, sys_getpid(), conn->cnum, + global_smbpid, procid_self(), conn->cnum, offset, count, lock_type); } } else { ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, sys_getpid(), conn->cnum, + global_smbpid, procid_self(), conn->cnum, offset, count, lock_type); } @@ -143,7 +143,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { status = brl_lock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, sys_getpid(), conn->cnum, + lock_pid, procid_self(), conn->cnum, offset, count, lock_type, my_lock_ctx); @@ -166,7 +166,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p * lock entry. */ (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, sys_getpid(), conn->cnum, + lock_pid, procid_self(), conn->cnum, offset, count, False, NULL, NULL); } @@ -264,7 +264,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, posix_data.count = count; ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, sys_getpid(), conn->cnum, offset, count, + lock_pid, procid_self(), conn->cnum, offset, count, False, posix_unlock, (void *)&posix_data); if (!ok) { @@ -280,7 +280,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, void locking_close_file(files_struct *fsp) { - pid_t pid = sys_getpid(); + struct process_id pid = procid_self(); if (!lp_locking(SNUM(fsp->conn))) return; @@ -324,20 +324,6 @@ BOOL locking_init(int read_only) return False; } - if (!read_only && !deferred_open_tdb) { - deferred_open_tdb = tdb_open_log(lock_path("deferred_open.tdb"), - 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, - O_RDWR|O_CREAT, - 0644); - - if (!deferred_open_tdb) { - DEBUG(0,("ERROR: Failed to initialise deferred open database\n")); - tdb_close(tdb); - tdb = NULL; - return False; - } - } - if (!posix_locking_init(read_only)) return False; @@ -360,11 +346,6 @@ BOOL locking_end(void) ret = False; } - if (deferred_open_tdb) { - if (tdb_close(deferred_open_tdb) != 0) - ret = False; - } - return ret; } @@ -372,6 +353,16 @@ BOOL locking_end(void) Form a static locking key for a dev/inode pair. ******************************************************************/ +/* key and data records in the tdb locking database */ +struct locking_key { + SMB_DEV_T dev; + SMB_INO_T ino; +}; + +/******************************************************************* + Form a static locking key for a dev/inode pair. +******************************************************************/ + static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) { static struct locking_key key; @@ -379,70 +370,27 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) memset(&key, '\0', sizeof(key)); key.dev = dev; - key.inode = inode; + key.ino = inode; kbuf.dptr = (char *)&key; kbuf.dsize = sizeof(key); return kbuf; } -static TDB_DATA locking_key_fsp(files_struct *fsp) -{ - return locking_key(fsp->dev, fsp->inode); -} - -/******************************************************************* - Lock a hash bucket entry. -******************************************************************/ - -BOOL lock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode) -{ - return tdb_chainlock(tdb, locking_key(dev, inode)) == 0; -} - -/******************************************************************* - Unlock a hash bucket entry. -******************************************************************/ - -void unlock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode) -{ - tdb_chainunlock(tdb, locking_key(dev, inode)); -} - -/******************************************************************* - Lock a hash bucket entry. use a fsp for convenience -******************************************************************/ - -BOOL lock_share_entry_fsp(files_struct *fsp) -{ - return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0; -} - -/******************************************************************* - Unlock a hash bucket entry. -******************************************************************/ - -void unlock_share_entry_fsp(files_struct *fsp) -{ - tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode)); -} - /******************************************************************* Print out a share mode. ********************************************************************/ -char *share_mode_str(int num, share_mode_entry *e) +char *share_mode_str(int num, struct share_mode_entry *e) { static pstring share_str; slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: " - "pid = %lu, share_access = 0x%x, private_options = 0x%x, " - "access_mask = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, " + "pid = %s, share_access = 0x%x, private_options = 0x%x, " + "access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, " "dev = 0x%x, inode = %.0f", - num, (unsigned long)e->pid, + num, procid_str_static(&e->pid), e->share_access, e->private_options, - e->access_mask, e->op_port, e->op_type, e->share_file_id, + e->access_mask, e->op_mid, e->op_type, e->share_file_id, (unsigned int)e->dev, (double)e->inode ); return share_str; @@ -455,12 +403,14 @@ char *share_mode_str(int num, share_mode_entry *e) static void print_share_mode_table(struct locking_data *data) { int num_share_modes = data->u.s.num_share_mode_entries; - share_mode_entry *shares = (share_mode_entry *)(data + 1); + struct share_mode_entry *shares = + (struct share_mode_entry *)(data + 1); int i; for (i = 0; i < num_share_modes; i++) { - share_mode_entry *entry_p = &shares[i]; - DEBUG(10,("print_share_mode_table: %s\n", share_mode_str(i, entry_p) )); + struct share_mode_entry *entry_p = &shares[i]; + DEBUG(10,("print_share_mode_table: %s\n", + share_mode_str(i, entry_p))); } } @@ -468,825 +418,581 @@ static void print_share_mode_table(struct locking_data *data) Get all share mode entries for a dev/inode pair. ********************************************************************/ -int get_share_modes(SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry **pp_shares, - BOOL *delete_on_close) +static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) { - TDB_DATA dbuf; struct locking_data *data; - int num_share_modes; - share_mode_entry *shares = NULL; - TDB_DATA key = locking_key(dev, inode); - *pp_shares = NULL; - *delete_on_close = False; - - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) - return 0; - - data = (struct locking_data *)dbuf.dptr; + int i; - *delete_on_close = data->u.s.delete_on_close; - DEBUG(10, ("get_share_modes: delete_on_close: %d\n", - *delete_on_close)); - num_share_modes = data->u.s.num_share_mode_entries; - if(num_share_modes) { - pstring fname; - int i; - int del_count = 0; - - shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), - num_share_modes * sizeof(share_mode_entry)); - - if (!shares) { - SAFE_FREE(dbuf.dptr); - return 0; - } + if (dbuf.dsize < sizeof(struct locking_data)) { + DEBUG(0, ("parse_share_modes: buffer too short\n")); + return False; + } - /* Save off the associated filename. */ - pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry)); + data = (struct locking_data *)dbuf.dptr; - /* - * Ensure that each entry has a real process attached. - */ + lck->delete_on_close = data->u.s.delete_on_close; + lck->num_share_modes = data->u.s.num_share_mode_entries; - for (i = 0; i < num_share_modes; ) { - share_mode_entry *entry_p = &shares[i]; - if (process_exists(entry_p->pid)) { - DEBUG(10,("get_share_modes: %s\n", share_mode_str(i, entry_p) )); - i++; - } else { - DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) )); - if (num_share_modes - i - 1 > 0) { - memcpy( &shares[i], &shares[i+1], - sizeof(share_mode_entry) * (num_share_modes - i - 1)); - } - num_share_modes--; - del_count++; - } - } + DEBUG(10, ("parse_share_modes: delete_on_close: %d, " + "num_share_modes: %d\n", lck->delete_on_close, + lck->num_share_modes)); - /* Did we delete any ? If so, re-store in tdb. */ - if (del_count) { - data->u.s.num_share_mode_entries = num_share_modes; - - if (num_share_modes) { - memcpy(dbuf.dptr + sizeof(*data), shares, - num_share_modes * sizeof(share_mode_entry)); - /* Append the filename. */ - pstrcpy(dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry), fname); - } - - /* The record has shrunk a bit */ - dbuf.dsize -= del_count * sizeof(share_mode_entry); - - if (data->u.s.num_share_mode_entries == 0) { - if (tdb_delete(tdb, key) == -1) { - SAFE_FREE(shares); - SAFE_FREE(dbuf.dptr); - return 0; - } - } else { - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { - SAFE_FREE(shares); - SAFE_FREE(dbuf.dptr); - return 0; - } - } - } + if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { + DEBUG(0, ("invalid number of share modes: %d\n", + lck->num_share_modes)); + return False; } - SAFE_FREE(dbuf.dptr); - *pp_shares = shares; - return num_share_modes; -} + lck->share_modes = NULL; -BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) -{ - share_mode_entry *shares; - BOOL result; - get_share_modes(dev, inode, &shares, &result); - SAFE_FREE(shares); - return result; -} + if (lck->num_share_modes != 0) { -/******************************************************************* - Fill a share mode entry. -********************************************************************/ + if (dbuf.dsize < (sizeof(struct locking_data) + + (lck->num_share_modes * + sizeof(struct share_mode_entry)))) { + DEBUG(0, ("parse_share_modes: buffer too short\n")); + return False; + } + + lck->share_modes = talloc_memdup(lck, dbuf.dptr+sizeof(*data), + lck->num_share_modes * + sizeof(struct share_mode_entry)); -static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type) -{ - share_mode_entry *e = (share_mode_entry *)p; - void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */ + if (lck->share_modes == NULL) { + DEBUG(0, ("talloc failed\n")); + return False; + } + } - memset(e, '\0', sizeof(share_mode_entry)); - e->pid = sys_getpid(); - e->share_access = fsp->share_access; - e->private_options = fsp->fh->private_options; - e->access_mask = fsp->access_mask; - e->op_port = port; - e->op_type = op_type; - memcpy(x, &fsp->open_time, sizeof(struct timeval)); - e->share_file_id = fsp->file_id; - e->dev = fsp->dev; - e->inode = fsp->inode; -} + /* Save off the associated filename. */ + lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + + lck->num_share_modes * + sizeof(struct share_mode_entry)); -/******************************************************************* - Check if two share mode entries are identical, ignoring oplock - and port info and desired_access. -********************************************************************/ + /* + * Ensure that each entry has a real process attached. + */ -BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) -{ -#if 1 /* JRA PARANOIA TEST - REMOVE LATER */ - if (e1->pid == e2->pid && - e1->share_file_id == e2->share_file_id && - e1->dev == e2->dev && - e1->inode == e2->inode && - (e1->share_access) != (e2->share_access)) { - DEBUG(0,("PANIC: share_modes_identical: share_mode " - "mismatch (e1 = 0x%x, e2 = 0x%x). Logic error.\n", - (unsigned int)e1->share_access, - (unsigned int)e2->share_access )); - smb_panic("PANIC: share_modes_identical logic error.\n"); + for (i = 0; i < lck->num_share_modes; i++) { + struct share_mode_entry *entry_p = &lck->share_modes[i]; + DEBUG(10,("parse_share_modes: %s\n", + share_mode_str(i, entry_p) )); + if (!process_exists(entry_p->pid)) { + DEBUG(10,("parse_share_modes: deleted %s\n", + share_mode_str(i, entry_p) )); + entry_p->op_type = UNUSED_SHARE_MODE_ENTRY; + lck->modified = True; + } } -#endif - return (e1->pid == e2->pid && - (e1->share_access) == (e2->share_access) && - e1->dev == e2->dev && - e1->inode == e2->inode && - e1->share_file_id == e2->share_file_id ); + return True; } -/******************************************************************* - Delete a specific share mode. Return the number - of entries left, and a memdup'ed copy of the entry deleted (if required). - Ignore if no entry deleted. -********************************************************************/ - -ssize_t del_share_entry(SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry *entry, share_mode_entry **ppse, - BOOL *delete_on_close) +static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) { - TDB_DATA dbuf; + TDB_DATA result; + int num_valid = 0; + int i; struct locking_data *data; - int i, del_count=0; - share_mode_entry *shares; - ssize_t count = 0; - TDB_DATA key = locking_key(dev, inode); - - if (ppse) - *ppse = NULL; - - /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) - return -1; - - data = (struct locking_data *)dbuf.dptr; - *delete_on_close = data->u.s.delete_on_close; - shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - - /* - * Find any with this pid and delete it - * by overwriting with the rest of the data - * from the record. - */ - - DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.s.num_share_mode_entries )); - - for (i=0;iu.s.num_share_mode_entries;) { - if (share_modes_identical(&shares[i], entry)) { - DEBUG(10,("del_share_entry: deleted %s\n", - share_mode_str(i, &shares[i]) )); - if (ppse) - *ppse = memdup(&shares[i], sizeof(*shares)); - data->u.s.num_share_mode_entries--; - if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))) > 0) { - memmove(&shares[i], &shares[i+1], - dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); - } - del_count++; + ssize_t offset; - DEBUG(10,("del_share_entry: deleting entry %d\n", i )); + result.dptr = NULL; + result.dsize = 0; - } else { - i++; + for (i=0; inum_share_modes; i++) { + if (!is_unused_share_mode_entry(&lck->share_modes[i])) { + num_valid += 1; } } - if (del_count) { - /* the record may have shrunk a bit */ - dbuf.dsize -= del_count * sizeof(*shares); - - count = (ssize_t)data->u.s.num_share_mode_entries; - - /* store it back in the database */ - if (data->u.s.num_share_mode_entries == 0) { - if (tdb_delete(tdb, key) == -1) - count = -1; - } else { - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) - count = -1; - } + if (num_valid == 0) { + return result; } - DEBUG(10,("del_share_entry: Remaining table.\n")); - print_share_mode_table((struct locking_data *)dbuf.dptr); - SAFE_FREE(dbuf.dptr); - return count; -} -/******************************************************************* - Del the share mode of a file for this process. Return the number - of entries left, and a memdup'ed copy of the entry deleted. -********************************************************************/ - -ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse, - BOOL *delete_on_close) -{ - share_mode_entry entry; + result.dsize = sizeof(*data) + + lck->num_share_modes * sizeof(struct share_mode_entry) + + strlen(lck->filename) + 1; + result.dptr = talloc_size(lck, result.dsize); - /* - * Fake up a share_mode_entry for comparisons. - */ + if (result.dptr == NULL) { + smb_panic("talloc failed\n"); + } - fill_share_mode((char *)&entry, fsp, 0, 0); - return del_share_entry(fsp->dev, fsp->inode, &entry, ppse, - delete_on_close); + data = (struct locking_data *)result.dptr; + ZERO_STRUCTP(data); + data->u.s.num_share_mode_entries = lck->num_share_modes; + data->u.s.delete_on_close = lck->delete_on_close; + DEBUG(10, ("unparse_share_modes: del: %d, num: %d\n", + data->u.s.delete_on_close, + data->u.s.num_share_mode_entries)); + memcpy(result.dptr + sizeof(*data), lck->share_modes, + sizeof(struct share_mode_entry)*lck->num_share_modes); + offset = sizeof(*data) + + sizeof(struct share_mode_entry)*lck->num_share_modes; + safe_strcpy(result.dptr + offset, lck->filename, + result.dsize - offset - 1); + print_share_mode_table(data); + return result; } -/******************************************************************* - Set the share mode of a file. Return False on fail, True on success. -********************************************************************/ - -BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) +static int share_mode_lock_destructor(void *p) { - TDB_DATA dbuf; - struct locking_data *data; - char *p=NULL; - int size; - TDB_DATA key = locking_key_fsp(fsp); - BOOL ret = True; - - /* read in the existing share modes if any */ - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) { - size_t offset; - /* we'll need to create a new record */ - pstring fname; - - pstrcpy(fname, fsp->conn->connectpath); - pstrcat(fname, "/"); - pstrcat(fname, fsp->fsp_name); - - size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1; - p = (char *)SMB_MALLOC(size); - if (!p) - return False; - data = (struct locking_data *)p; - ZERO_STRUCT(data->u); /* Keep valgrind happy */ - data->u.s.num_share_mode_entries = 1; - - DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n", - fsp->fsp_name )); + struct share_mode_lock *lck = + talloc_get_type_abort(p, struct share_mode_lock); + TDB_DATA key = locking_key(lck->dev, lck->ino); + TDB_DATA data; - offset = sizeof(*data) + sizeof(share_mode_entry); - safe_strcpy(p + offset, fname, size - offset - 1); - fill_share_mode(p + sizeof(*data), fsp, port, op_type); - dbuf.dptr = p; - dbuf.dsize = size; - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; + if (!lck->modified) { + goto done; + } - print_share_mode_table((struct locking_data *)p); + data = unparse_share_modes(lck); - SAFE_FREE(p); - return ret; + if (data.dptr == NULL) { + if (!lck->fresh) { + /* There has been an entry before, delete it */ + if (tdb_delete(tdb, key) == -1) { + smb_panic("Could not delete share entry\n"); + } + } + goto done; } - /* we're adding to an existing entry - this is a bit fiddly */ - data = (struct locking_data *)dbuf.dptr; + if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) { + smb_panic("Could not store share mode entry\n"); + } - data->u.s.num_share_mode_entries++; - - DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n", - fsp->fsp_name, data->u.s.num_share_mode_entries )); + done: + tdb_chainunlock(tdb, key); - size = dbuf.dsize + sizeof(share_mode_entry); - p = SMB_MALLOC(size); - if (!p) { - SAFE_FREE(dbuf.dptr); - return False; - } - memcpy(p, dbuf.dptr, sizeof(*data)); - fill_share_mode(p + sizeof(*data), fsp, port, op_type); - memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data), - dbuf.dsize - sizeof(*data)); - SAFE_FREE(dbuf.dptr); - dbuf.dptr = p; - dbuf.dsize = size; - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; - print_share_mode_table((struct locking_data *)p); - SAFE_FREE(p); - return ret; + return 0; } -/******************************************************************* - A generic in-place modification call for share mode entries. -********************************************************************/ - -static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry, - void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), - void *param) +struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, + SMB_DEV_T dev, SMB_INO_T ino, + const char *fname) { - TDB_DATA dbuf; - struct locking_data *data; - int i; - share_mode_entry *shares; - BOOL need_store=False; - BOOL ret = True; - TDB_DATA key = locking_key(dev, inode); - - /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) - return False; + struct share_mode_lock *lck; + TDB_DATA key = locking_key(dev, ino); + TDB_DATA data; - data = (struct locking_data *)dbuf.dptr; - shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); + lck = TALLOC_P(mem_ctx, struct share_mode_lock); + if (lck == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } - /* find any with our pid and call the supplied function */ - for (i=0;iu.s.num_share_mode_entries;i++) { - if (share_modes_identical(entry, &shares[i])) { - mod_fn(&shares[i], dev, inode, param); - need_store=True; - } + lck->dev = dev; + lck->ino = ino; + lck->delete_on_close = False; + lck->num_share_modes = 0; + lck->share_modes = NULL; + lck->modified = False; + + if (tdb_chainlock(tdb, key) != 0) { + DEBUG(3, ("Could not lock share entry\n")); + talloc_free(lck); + return NULL; } - /* if the mod fn was called then store it back */ - if (need_store) { - if (data->u.s.num_share_mode_entries == 0) { - if (tdb_delete(tdb, key) == -1) - ret = False; - } else { - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; + data = tdb_fetch(tdb, key); + lck->fresh = (data.dptr == NULL); + + if (lck->fresh) { + if (fname == NULL) { + DEBUG(0, ("New file, but no filename supplied\n")); + talloc_free(lck); + return NULL; + } + lck->filename = talloc_strdup(lck, fname); + if (lck->filename == NULL) { + DEBUG(0, ("talloc failed\n")); + talloc_free(lck); + return NULL; + } + } else { + if (!parse_share_modes(data, lck)) { + DEBUG(0, ("Could not parse share modes\n")); + talloc_free(lck); + SAFE_FREE(data.dptr); + return NULL; } } - SAFE_FREE(dbuf.dptr); - return ret; -} + talloc_set_destructor(lck, share_mode_lock_destructor); + SAFE_FREE(data.dptr); -/******************************************************************* - Static function that actually does the work for the generic function - below. -********************************************************************/ + return lck; +} -static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, - void *param) +BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode, + const char *fname) { - DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode )); - /* Delete the oplock info. */ - entry->op_port = 0; - entry->op_type = NO_OPLOCK; + BOOL result; + struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, + fname); + result = lck->delete_on_close; + talloc_free(lck); + return result; } -/******************************************************************* - Remove an oplock port and mode entry from a share mode. -********************************************************************/ - -BOOL remove_share_oplock(files_struct *fsp) +BOOL is_valid_share_mode_entry(const struct share_mode_entry *e) { - share_mode_entry entry; - /* - * Fake up an entry for comparisons... - */ - fill_share_mode((char *)&entry, fsp, 0, 0); - return mod_share_mode(fsp->dev, fsp->inode, &entry, remove_share_oplock_fn, NULL); + int num_props = 0; + + num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0); + num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0); + num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0); + + SMB_ASSERT(num_props <= 1); + return (num_props != 0); } -/******************************************************************* - Static function that actually does the work for the generic function - below. -********************************************************************/ +BOOL is_deferred_open_entry(const struct share_mode_entry *e) +{ + return (e->op_type == DEFERRED_OPEN_ENTRY); +} -static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, - void *param) +BOOL is_unused_share_mode_entry(const struct share_mode_entry *e) { - DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode )); - entry->op_type = LEVEL_II_OPLOCK; + return (e->op_type == UNUSED_SHARE_MODE_ENTRY); } /******************************************************************* - Downgrade a oplock type from exclusive to level II. + Fill a share mode entry. ********************************************************************/ -BOOL downgrade_share_oplock(files_struct *fsp) +static void fill_share_mode_entry(struct share_mode_entry *e, + files_struct *fsp, + uint16 mid, uint16 op_type) { - share_mode_entry entry; - /* - * Fake up an entry for comparisons... - */ - fill_share_mode((char *)&entry, fsp, 0, 0); - return mod_share_mode(fsp->dev, fsp->inode, &entry, downgrade_share_oplock_fn, NULL); + ZERO_STRUCTP(e); + e->pid = procid_self(); + e->share_access = fsp->share_access; + e->private_options = fsp->fh->private_options; + e->access_mask = fsp->access_mask; + e->op_mid = mid; + e->op_type = op_type; + e->time.tv_sec = fsp->open_time.tv_sec; + e->time.tv_usec = fsp->open_time.tv_usec; + e->share_file_id = fsp->file_id; + e->dev = fsp->dev; + e->inode = fsp->inode; } -/******************************************************************* - Get/Set the delete on close flag in a set of share modes. - Return False on fail, True on success. -********************************************************************/ - -BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) +static void fill_deferred_open_entry(struct share_mode_entry *e, + const struct timeval request_time, + SMB_DEV_T dev, SMB_INO_T ino, uint16 mid) { - TDB_DATA dbuf; - struct locking_data *data; - BOOL res; - TDB_DATA key = locking_key(dev, inode); + ZERO_STRUCTP(e); + e->pid = procid_self(); + e->op_mid = mid; + e->op_type = DEFERRED_OPEN_ENTRY; + e->time.tv_sec = request_time.tv_sec; + e->time.tv_usec = request_time.tv_usec; + e->dev = dev; + e->inode = ino; +} - /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) - return False; +static void add_share_mode_entry(struct share_mode_lock *lck, + const struct share_mode_entry *entry) +{ + int i; - data = (struct locking_data *)dbuf.dptr; + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + if (is_unused_share_mode_entry(e)) { + *e = *entry; + break; + } + } - /* Set/Unset the delete on close element. */ - data->u.s.delete_on_close = delete_on_close; + if (i == lck->num_share_modes) { + /* No unused entry found */ + ADD_TO_ARRAY(lck, struct share_mode_entry, *entry, + &lck->share_modes, &lck->num_share_modes); + } + lck->modified = True; +} - res = (tdb_store(tdb, key, dbuf, TDB_REPLACE)!=-1); +void set_share_mode(struct share_mode_lock *lck, files_struct *fsp, + uint16 mid, uint16 op_type) +{ + struct share_mode_entry entry; + fill_share_mode_entry(&entry, fsp, mid, op_type); + add_share_mode_entry(lck, &entry); +} - SAFE_FREE(dbuf.dptr); - return res; +void add_deferred_open(struct share_mode_lock *lck, uint16 mid, + struct timeval request_time, + SMB_DEV_T dev, SMB_INO_T ino) +{ + struct share_mode_entry entry; + fill_deferred_open_entry(&entry, request_time, dev, ino, mid); + add_share_mode_entry(lck, &entry); } /******************************************************************* - Print out a deferred open entry. + Check if two share mode entries are identical, ignoring oplock + and mid info and desired_access. ********************************************************************/ -char *deferred_open_str(int num, deferred_open_entry *e) +static BOOL share_modes_identical(struct share_mode_entry *e1, + struct share_mode_entry *e2) { - static pstring de_str; - - slprintf(de_str, sizeof(de_str)-1, "deferred_open_entry[%d]: \ -pid = %lu, mid = %u, dev = 0x%x, inode = %.0f, port = %u, time = [%u.%06u]", - num, (unsigned long)e->pid, (unsigned int)e->mid, (unsigned int)e->dev, (double)e->inode, - (unsigned int)e->port, - (unsigned int)e->time.tv_sec, (unsigned int)e->time.tv_usec ); +#if 1 /* JRA PARANOIA TEST - REMOVE LATER */ + if (procid_equal(&e1->pid, &e2->pid) && + e1->share_file_id == e2->share_file_id && + e1->dev == e2->dev && + e1->inode == e2->inode && + (e1->share_access) != (e2->share_access)) { + DEBUG(0,("PANIC: share_modes_identical: share_mode " + "mismatch (e1 = 0x%x, e2 = 0x%x). Logic error.\n", + (unsigned int)e1->share_access, + (unsigned int)e2->share_access )); + smb_panic("PANIC: share_modes_identical logic error.\n"); + } +#endif - return de_str; + return (procid_equal(&e1->pid, &e2->pid) && + (e1->share_access) == (e2->share_access) && + e1->dev == e2->dev && + e1->inode == e2->inode && + e1->share_file_id == e2->share_file_id ); } -/* Internal data structures for deferred opens... */ +static BOOL deferred_open_identical(struct share_mode_entry *e1, + struct share_mode_entry *e2) +{ + return (procid_equal(&e1->pid, &e2->pid) && + (e1->op_mid == e2->op_mid) && + (e1->dev == e2->dev) && + (e1->inode == e2->inode)); +} -struct de_locking_key { - char name[4]; - SMB_DEV_T dev; - SMB_INO_T inode; -}; +static struct share_mode_entry *find_share_mode_entry(struct share_mode_lock *lck, + struct share_mode_entry *entry) +{ + int i; -struct deferred_open_data { - union { - int num_deferred_open_entries; - deferred_open_entry dummy; /* Needed for alignment. */ - } u; - /* the following two entries are implicit - deferred_open_entry de_entries[num_deferred_open_entries]; - char file_name[]; - */ -}; + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + if (is_valid_share_mode_entry(entry) && + is_valid_share_mode_entry(e) && + share_modes_identical(e, entry)) { + return e; + } + if (is_deferred_open_entry(entry) && + is_deferred_open_entry(e) && + deferred_open_identical(e, entry)) { + return e; + } + } + return NULL; +} /******************************************************************* - Print out a deferred open table. + Del the share mode of a file for this process. Return the number of + entries left. ********************************************************************/ -static void print_deferred_open_table(struct deferred_open_data *data) +BOOL del_share_mode(struct share_mode_lock *lck, files_struct *fsp) { - int num_de_entries = data->u.num_deferred_open_entries; - deferred_open_entry *de_entries = (deferred_open_entry *)(data + 1); - int i; + struct share_mode_entry entry, *e; + + fill_share_mode_entry(&entry, fsp, 0, 0); - for (i = 0; i < num_de_entries; i++) { - deferred_open_entry *entry_p = &de_entries[i]; - DEBUG(10,("print_deferred_open_table: %s\n", deferred_open_str(i, entry_p) )); + e = find_share_mode_entry(lck, &entry); + if (e == NULL) { + return False; } + + e->op_type = UNUSED_SHARE_MODE_ENTRY; + lck->modified = True; + return True; } +void del_deferred_open_entry(struct share_mode_lock *lck, uint16 mid) +{ + struct share_mode_entry entry, *e; -/******************************************************************* - Form a static deferred open locking key for a dev/inode pair. -******************************************************************/ + fill_deferred_open_entry(&entry, timeval_zero(), + lck->dev, lck->ino, mid); -static TDB_DATA deferred_open_locking_key(SMB_DEV_T dev, SMB_INO_T inode) -{ - static struct de_locking_key key; - TDB_DATA kbuf; + e = find_share_mode_entry(lck, &entry); + if (e == NULL) { + return; + } - memset(&key, '\0', sizeof(key)); - memcpy(&key.name[0], "DOE", 4); - key.dev = dev; - key.inode = inode; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); - return kbuf; + e->op_type = UNUSED_SHARE_MODE_ENTRY; + lck->modified = True; } /******************************************************************* - Get all deferred open entries for a dev/inode pair. + Remove an oplock mid and mode entry from a share mode. ********************************************************************/ -int get_deferred_opens(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, - deferred_open_entry **pp_de_entries) +BOOL remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp) { - TDB_DATA dbuf; - struct deferred_open_data *data; - int num_de_entries; - deferred_open_entry *de_entries = NULL; - TDB_DATA key = deferred_open_locking_key(dev, inode); + struct share_mode_entry entry, *e; - *pp_de_entries = NULL; + fill_share_mode_entry(&entry, fsp, 0, 0); - dbuf = tdb_fetch(deferred_open_tdb, key); - if (!dbuf.dptr) - return 0; - - data = (struct deferred_open_data *)dbuf.dptr; - num_de_entries = data->u.num_deferred_open_entries; - if(num_de_entries) { - pstring fname; - int i; - int del_count = 0; - - de_entries = (deferred_open_entry *)memdup(dbuf.dptr + sizeof(*data), - num_de_entries * sizeof(deferred_open_entry)); - - if (!de_entries) { - SAFE_FREE(dbuf.dptr); - return 0; - } + e = find_share_mode_entry(lck, &entry); + if (e == NULL) { + return False; + } - /* Save off the associated filename. */ - pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry)); + e->op_mid = 0; + e->op_type = NO_OPLOCK; + lck->modified = True; + return True; +} - /* - * Ensure that each entry has a real process attached. - */ +/******************************************************************* + Downgrade a oplock type from exclusive to level II. +********************************************************************/ - for (i = 0; i < num_de_entries; ) { - deferred_open_entry *entry_p = &de_entries[i]; - if (process_exists(entry_p->pid)) { - DEBUG(10,("get_deferred_opens: %s\n", deferred_open_str(i, entry_p) )); - i++; - } else { - DEBUG(10,("get_deferred_opens: deleted %s\n", deferred_open_str(i, entry_p) )); - if (num_de_entries - i - 1 > 0) { - memcpy( &de_entries[i], &de_entries[i+1], - sizeof(deferred_open_entry) * (num_de_entries - i - 1)); - } - num_de_entries--; - del_count++; - } - } +BOOL downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp) +{ + struct share_mode_entry entry, *e; - /* Did we delete any ? If so, re-store in tdb. */ - if (del_count) { - data->u.num_deferred_open_entries = num_de_entries; - - if (num_de_entries) { - memcpy(dbuf.dptr + sizeof(*data), de_entries, - num_de_entries * sizeof(deferred_open_entry)); - /* Append the filename. */ - pstrcpy(dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry), fname); - } + fill_share_mode_entry(&entry, fsp, 0, 0); - /* The record has shrunk a bit */ - dbuf.dsize -= del_count * sizeof(deferred_open_entry); - - if (data->u.num_deferred_open_entries == 0) { - if (tdb_delete(deferred_open_tdb, key) == -1) { - SAFE_FREE(de_entries); - SAFE_FREE(dbuf.dptr); - return 0; - } - } else { - if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) { - SAFE_FREE(de_entries); - SAFE_FREE(dbuf.dptr); - return 0; - } - } - } + e = find_share_mode_entry(lck, &entry); + if (e == NULL) { + return False; } - SAFE_FREE(dbuf.dptr); - *pp_de_entries = de_entries; - return num_de_entries; + e->op_type = LEVEL_II_OPLOCK; + lck->modified = True; + return True; } + /******************************************************************* - Check if two deferred open entries are identical. + We've just told all the smbd's that our level2 or fake level2 has been + written to. ********************************************************************/ - -static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_open_entry *e2) +BOOL remove_all_share_oplocks(struct share_mode_lock *lck, files_struct *fsp) { - return (e1->pid == e2->pid && - e1->mid == e2->mid && - e1->port == e2->port && - e1->dev == e2->dev && - e1->inode == e2->inode && - e1->time.tv_sec == e2->time.tv_sec && - e1->time.tv_usec == e2->time.tv_usec); + int i; + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + if (!is_valid_share_mode_entry(e)) { + continue; + } + if (e->op_type == NO_OPLOCK) { + continue; + } + e->op_type = NO_OPLOCK; + lck->modified = True; + } + return True; } -/******************************************************************* - Delete a specific deferred open entry. - Ignore if no entry deleted. -********************************************************************/ +/**************************************************************************** + Deal with the internal needs of setting the delete on close flag. Note that + as the tdb locking is recursive, it is safe to call this from within + open_file_shared. JRA. +****************************************************************************/ -BOOL delete_deferred_open_entry(deferred_open_entry *entry) +NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, + uint32 dosmode) { - TDB_DATA dbuf; - struct deferred_open_data *data; - int i, del_count=0; - deferred_open_entry *de_entries; - BOOL ret = True; - TDB_DATA key = deferred_open_locking_key(entry->dev, entry->inode); - - /* read in the existing share modes */ - dbuf = tdb_fetch(deferred_open_tdb, key); - if (!dbuf.dptr) - return -1; - - data = (struct deferred_open_data *)dbuf.dptr; - de_entries = (deferred_open_entry *)(dbuf.dptr + sizeof(*data)); + if (!delete_on_close) { + return NT_STATUS_OK; + } /* - * Find any with this pid and delete it - * by overwriting with the rest of the data - * from the record. + * Only allow delete on close for writable files. */ - DEBUG(10,("delete_deferred_open_entry: num_deferred_open_entries = %d\n", - data->u.num_deferred_open_entries )); - - for (i=0;iu.num_deferred_open_entries;) { - if (deferred_open_entries_identical(&de_entries[i], entry)) { - DEBUG(10,("delete_deferred_open_entry: deleted %s\n", - deferred_open_str(i, &de_entries[i]) )); - - data->u.num_deferred_open_entries--; - if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))) > 0) { - memmove(&de_entries[i], &de_entries[i+1], - dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))); - } - del_count++; - - DEBUG(10,("delete_deferred_open_entry: deleting entry %d\n", i )); - - } else { - i++; - } + if ((dosmode & aRONLY) && + !lp_delete_readonly(SNUM(fsp->conn))) { + DEBUG(10,("can_set_delete_on_close: file %s delete on close " + "flag set but file attribute is readonly.\n", + fsp->fsp_name )); + return NT_STATUS_CANNOT_DELETE; } - SMB_ASSERT(del_count == 0 || del_count == 1); - - if (del_count) { - /* the record may have shrunk a bit */ - dbuf.dsize -= del_count * sizeof(*de_entries); + /* + * Only allow delete on close for writable shares. + */ - /* store it back in the database */ - if (data->u.num_deferred_open_entries == 0) { - if (tdb_delete(deferred_open_tdb, key) == -1) - ret = False; - } else { - if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; - } + if (!CAN_WRITE(fsp->conn)) { + DEBUG(10,("can_set_delete_on_close: file %s delete on " + "close flag set but write access denied on share.\n", + fsp->fsp_name )); + return NT_STATUS_ACCESS_DENIED; } - DEBUG(10,("delete_deferred_open_entry: Remaining table.\n")); - print_deferred_open_table((struct deferred_open_data*)dbuf.dptr); - SAFE_FREE(dbuf.dptr); - return ret; -} -/******************************************************************* - Fill a deferred open entry. -********************************************************************/ + /* + * Only allow delete on close for files/directories opened with delete + * intent. + */ -static void fill_deferred_open(char *p, uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port) -{ - deferred_open_entry *e = (deferred_open_entry *)p; - void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */ + if (!(fsp->access_mask & DELETE_ACCESS)) { + DEBUG(10,("can_set_delete_on_close: file %s delete on " + "close flag set but delete access denied.\n", + fsp->fsp_name )); + return NT_STATUS_ACCESS_DENIED; + } - memset(e, '\0', sizeof(deferred_open_entry)); - e->mid = mid; - e->pid = sys_getpid(); - memcpy(x, ptv, sizeof(struct timeval)); - e->dev = dev; - e->inode = inode; - e->port = port; + return NT_STATUS_OK; } -/******************************************************************* - Add a deferred open record. Return False on fail, True on success. -********************************************************************/ +/**************************************************************************** + Sets the delete on close flag over all share modes on this file. + Modify the share mode entry for all files open + on this device and inode to tell other smbds we have + changed the delete on close flag. This will be noticed + in the close code, the last closer will delete the file + if flag is set. +****************************************************************************/ -BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port, const char *fname) +BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) { - TDB_DATA dbuf; - struct deferred_open_data *data; - char *p=NULL; - int size; - TDB_DATA key = deferred_open_locking_key(dev, inode); - BOOL ret = True; - - /* read in the existing deferred open records if any */ - dbuf = tdb_fetch(deferred_open_tdb, key); - if (!dbuf.dptr) { - size_t offset; - /* we'll need to create a new record */ - - size = sizeof(*data) + sizeof(deferred_open_entry) + strlen(fname) + 1; - p = (char *)SMB_MALLOC(size); - if (!p) - return False; - data = (struct deferred_open_data *)p; - ZERO_STRUCT(data->u.dummy); /* Keep valgrind happy */ - data->u.num_deferred_open_entries = 1; + struct share_mode_lock *lck; - DEBUG(10,("add_deferred_open: creating entry for file %s. num_deferred_open_entries = 1\n", - fname )); - - offset = sizeof(*data) + sizeof(deferred_open_entry); - safe_strcpy(p + offset, fname, size - offset - 1); - fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port); - dbuf.dptr = p; - dbuf.dsize = size; - if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; - - print_deferred_open_table((struct deferred_open_data *)p); - - SAFE_FREE(p); - return ret; - } - - /* we're adding to an existing entry - this is a bit fiddly */ - data = (struct deferred_open_data *)dbuf.dptr; + DEBUG(10,("set_delete_on_close: %s delete on close flag for " + "fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, + fsp->fsp_name )); - data->u.num_deferred_open_entries++; - - DEBUG(10,("add_deferred_open: adding entry for file %s. new num_deferred_open_entries = %d\n", - fname, data->u.num_deferred_open_entries )); + if (fsp->is_directory || fsp->is_stat) + return True; - size = dbuf.dsize + sizeof(deferred_open_entry); - p = SMB_MALLOC(size); - if (!p) { - SAFE_FREE(dbuf.dptr); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + if (lck == NULL) { return False; } - memcpy(p, dbuf.dptr, sizeof(*data)); - fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port); - memcpy(p + sizeof(*data) + sizeof(deferred_open_entry), dbuf.dptr + sizeof(*data), - dbuf.dsize - sizeof(*data)); - SAFE_FREE(dbuf.dptr); - dbuf.dptr = p; - dbuf.dsize = size; - if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; - print_deferred_open_table((struct deferred_open_data *)p); - SAFE_FREE(p); - return ret; -} + if (lck->delete_on_close != delete_on_close) { + lck->delete_on_close = delete_on_close; + lck->modified = True; + } -/**************************************************************************** - Traverse the whole database with this function, calling traverse_callback - on each share mode -****************************************************************************/ + talloc_free(lck); + return True; +} static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, - void* state) + void *state) { struct locking_data *data; - share_mode_entry *shares; + struct share_mode_entry *shares; char *name; int i; - - SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state; + void (*traverse_callback)(struct share_mode_entry *, char *) = state; /* Ensure this is a locking_key record. */ if (kbuf.dsize != sizeof(struct locking_key)) return 0; data = (struct locking_data *)dbuf.dptr; - shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - name = dbuf.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares); + shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data)); + name = dbuf.dptr + sizeof(*data) + + data->u.s.num_share_mode_entries*sizeof(*shares); for (i=0;iu.s.num_share_mode_entries;i++) { traverse_callback(&shares[i], name); @@ -1299,9 +1005,9 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, share mode system. ********************************************************************/ -int share_mode_forall(SHAREMODE_FN(fn)) +int share_mode_forall(void (*fn)(const struct share_mode_entry *, char *)) { - if (!tdb) + if (tdb == NULL) return 0; - return tdb_traverse(tdb, traverse_fn, (void*)fn); + return tdb_traverse(tdb, traverse_fn, fn); } -- cgit From 533da83852b13c2e008938a026f99937ef320f3c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Oct 2005 22:35:08 +0000 Subject: r11341: Put directory opens into the share mode db so we can treat them similarly to file opens (delete on close, share mode violations etc.). This fixes bug #3216 I will up the default hash size on the locking db in a later commit as this means more entries. Jeremy. (This used to be commit 1134abbbb3fd8e8b88e1a5817aae106476a4c126) --- source3/locking/locking.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e3131e26a2..aad254f276 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -960,8 +960,9 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); - if (fsp->is_directory || fsp->is_stat) + if (fsp->is_stat) { return True; + } lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); if (lck == NULL) { -- cgit From a00c76d9fb11241f968336834ba4e4ced926e727 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Nov 2005 02:07:26 +0000 Subject: r11435: Allow the hash size of the tdb open (locking) database to be set in local.h. Change from the default (131) to another prime (1049). Should this be an smb.conf tunable parameter based on the number of open file descriptors available ? If so what scaling factor ? More tests to follow. Jeremy. (This used to be commit 6a902ec49ffea5d0ca0308d5ff51584cece41043) --- source3/locking/locking.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index aad254f276..322824ea2f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -315,9 +315,9 @@ BOOL locking_init(int read_only) return True; tdb = tdb_open_log(lock_path("locking.tdb"), - 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), - read_only?O_RDONLY:O_RDWR|O_CREAT, - 0644); + SMB_OPEN_DATABASE_TDB_HASH_SIZE, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), + read_only?O_RDONLY:O_RDWR|O_CREAT, + 0644); if (!tdb) { DEBUG(0,("ERROR: Failed to initialise locking database\n")); -- cgit From 7d2771e758d4e8ef0adb45e55775b524de4dba9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Dec 2005 22:07:36 +0000 Subject: r12203: Add the share path into the sharemode db. This involves revving the minor version number for libsmbsharemodes (we now have a new _ex interface that takes the share path as well as the filename). Needed for #3303. Some code written by SATOH Fumiyasu included in the changes to locking/locking.c. The smbstatus output is a bit of a mess and needs overhauling... Jeremy. (This used to be commit 9d93af713f8520ca506730dd32aa2b994937eaba) --- source3/locking/locking.c | 84 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 18 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 322824ea2f..2debc2c23e 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -464,10 +464,15 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) } } - /* Save off the associated filename. */ + /* Save off the associated service path and filename. */ + lck->servicepath = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + + (lck->num_share_modes * + sizeof(struct share_mode_entry))); + lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + - lck->num_share_modes * - sizeof(struct share_mode_entry)); + (lck->num_share_modes * + sizeof(struct share_mode_entry)) + + strlen(lck->servicepath) + 1 ); /* * Ensure that each entry has a real process attached. @@ -495,6 +500,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) int i; struct locking_data *data; ssize_t offset; + ssize_t sp_len; result.dptr = NULL; result.dsize = 0; @@ -509,8 +515,11 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) return result; } + sp_len = strlen(lck->servicepath); + result.dsize = sizeof(*data) + lck->num_share_modes * sizeof(struct share_mode_entry) + + sp_len + 1 + strlen(lck->filename) + 1; result.dptr = talloc_size(lck, result.dsize); @@ -529,6 +538,9 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) sizeof(struct share_mode_entry)*lck->num_share_modes); offset = sizeof(*data) + sizeof(struct share_mode_entry)*lck->num_share_modes; + safe_strcpy(result.dptr + offset, lck->servicepath, + result.dsize - offset - 1); + offset += sp_len + 1; safe_strcpy(result.dptr + offset, lck->filename, result.dsize - offset - 1); print_share_mode_table(data); @@ -569,8 +581,9 @@ static int share_mode_lock_destructor(void *p) } struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, - SMB_DEV_T dev, SMB_INO_T ino, - const char *fname) + SMB_DEV_T dev, SMB_INO_T ino, + const char *servicepath, + const char *fname) { struct share_mode_lock *lck; TDB_DATA key = locking_key(dev, ino); @@ -599,13 +612,15 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, lck->fresh = (data.dptr == NULL); if (lck->fresh) { - if (fname == NULL) { - DEBUG(0, ("New file, but no filename supplied\n")); + + if (fname == NULL || servicepath == NULL) { + DEBUG(0, ("New file, but no filename or servicepath supplied\n")); talloc_free(lck); return NULL; } lck->filename = talloc_strdup(lck, fname); - if (lck->filename == NULL) { + lck->servicepath = talloc_strdup(lck, servicepath); + if (lck->filename == NULL || lck->servicepath == NULL) { DEBUG(0, ("talloc failed\n")); talloc_free(lck); return NULL; @@ -625,12 +640,41 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, return lck; } -BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode, - const char *fname) +/******************************************************************* + Sets the service name and filename for rename. + At this point we should emit "rename" smbd messages to all + interested process id's. +********************************************************************/ + +BOOL rename_share_filename(struct share_mode_lock *lck, + const char *servicepath, + const char *newname) +{ + /* + * rename_internal_fsp() and rename_internals() add './' to + * head of newname if newname does not contain a '/'. + */ + while (newname[0] && newname[1] && newname[0] == '.' && newname[1] == '/') { + newname += 2; + } + + lck->filename = talloc_strdup(lck, newname); + lck->servicepath = talloc_strdup(lck, servicepath); + if (lck->filename == NULL || lck->servicepath == NULL) { + DEBUG(0, ("rename_share_filename: talloc failed\n")); + return False; + } + lck->modified = True; + return True; +} + +BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) { BOOL result; - struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, - fname); + struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, NULL, NULL); + if (!lck) { + return False; + } result = lck->delete_on_close; talloc_free(lck); return result; @@ -964,7 +1008,7 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) return True; } - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); if (lck == NULL) { return False; } @@ -982,9 +1026,10 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, { struct locking_data *data; struct share_mode_entry *shares; - char *name; + const char *sharepath; + const char *fname; int i; - void (*traverse_callback)(struct share_mode_entry *, char *) = state; + void (*traverse_callback)(struct share_mode_entry *, const char *, const char *) = state; /* Ensure this is a locking_key record. */ if (kbuf.dsize != sizeof(struct locking_key)) @@ -992,11 +1037,14 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, data = (struct locking_data *)dbuf.dptr; shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data)); - name = dbuf.dptr + sizeof(*data) + + sharepath = dbuf.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares); + fname = dbuf.dptr + sizeof(*data) + + data->u.s.num_share_mode_entries*sizeof(*shares) + + strlen(sharepath) + 1; for (i=0;iu.s.num_share_mode_entries;i++) { - traverse_callback(&shares[i], name); + traverse_callback(&shares[i], sharepath, fname); } return 0; } @@ -1006,7 +1054,7 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, share mode system. ********************************************************************/ -int share_mode_forall(void (*fn)(const struct share_mode_entry *, char *)) +int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, const char *)) { if (tdb == NULL) return 0; -- cgit From ab7a4f7e8e4b946a8acd0a205c16dbf6a3afecad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 Dec 2005 18:11:50 +0000 Subject: r12213: Final fix for #3303 - send rename messages to smbd's that have open file handles to allow them to correctly implement delete on close. There is a further correctness fix I'm intending to add to this to cope with different share paths, but not right now... Jeremy. (This used to be commit 932e337db8788e75344e1c7cf1ef009d090cb039) --- source3/locking/locking.c | 56 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 2debc2c23e..d89fe931ef 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -642,14 +642,24 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, /******************************************************************* Sets the service name and filename for rename. - At this point we should emit "rename" smbd messages to all - interested process id's. + At this point we emit "file renamed" messages to all + process id's that have this file open. + Based on an initial code idea from SATOH Fumiyasu ********************************************************************/ BOOL rename_share_filename(struct share_mode_lock *lck, const char *servicepath, const char *newname) { + struct file_renamed_message *frm = NULL; + size_t sp_len; + size_t fn_len; + size_t msg_len; + int i; + + DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n", + servicepath, newname)); + /* * rename_internal_fsp() and rename_internals() add './' to * head of newname if newname does not contain a '/'. @@ -658,13 +668,53 @@ BOOL rename_share_filename(struct share_mode_lock *lck, newname += 2; } - lck->filename = talloc_strdup(lck, newname); lck->servicepath = talloc_strdup(lck, servicepath); + lck->filename = talloc_strdup(lck, newname); if (lck->filename == NULL || lck->servicepath == NULL) { DEBUG(0, ("rename_share_filename: talloc failed\n")); return False; } lck->modified = True; + + sp_len = strlen(lck->servicepath); + fn_len = strlen(lck->filename); + + msg_len = sizeof(*frm) + sp_len + 1 + fn_len + 1; + + /* Set up the name changed message. */ + frm = TALLOC(lck, msg_len); + if (!frm) { + return False; + } + frm->dev = lck->dev; + frm->inode = lck->ino; + + DEBUG(10,("rename_share_filename: msg_len = %d\n", msg_len )); + + safe_strcpy(&frm->names[0], lck->servicepath, sp_len); + safe_strcpy(&frm->names[sp_len + 1], lck->filename, fn_len); + + /* Send the messages. */ + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *se = &lck->share_modes[i]; + if (!is_valid_share_mode_entry(se)) { + continue; + } + /* But not to ourselves... */ + if (procid_is_me(&se->pid)) { + continue; + } + + DEBUG(10,("rename_share_filename: sending rename message to pid %u " + "dev %x, inode %.0f sharepath %s newname %s\n", + (unsigned int)procid_to_pid(&se->pid), + (unsigned int)frm->dev, (double)frm->inode, + lck->servicepath, lck->filename )); + + message_send_pid(se->pid, MSG_SMB_FILE_RENAME, + frm, msg_len, True); + } + return True; } -- cgit From 762901cfb9aabb717b8312d546ab20f8bacb1e29 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Dec 2005 00:42:40 +0000 Subject: r12221: Fix error code paths that can potentially leave a dangling lock. Jeremy. (This used to be commit 123135ed1ddd84cc0a5e8e5ca06a0703d1944e37) --- source3/locking/locking.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d89fe931ef..b823b4712e 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -595,12 +595,18 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, return NULL; } + /* Ensure we set every field here as the destructor must be + valid even if parse_share_modes fails. */ + + lck->servicepath = NULL; + lck->filename = NULL; lck->dev = dev; lck->ino = ino; - lck->delete_on_close = False; lck->num_share_modes = 0; lck->share_modes = NULL; + lck->delete_on_close = False; lck->modified = False; + lck->fresh = False; if (tdb_chainlock(tdb, key) != 0) { DEBUG(3, ("Could not lock share entry\n")); @@ -608,6 +614,12 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, return NULL; } + /* We must set the destructor immediately after the chainlock + ensure the lock is cleaned up on any of the error return + paths below. */ + + talloc_set_destructor(lck, share_mode_lock_destructor); + data = tdb_fetch(tdb, key); lck->fresh = (data.dptr == NULL); @@ -634,7 +646,6 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, } } - talloc_set_destructor(lck, share_mode_lock_destructor); SAFE_FREE(data.dptr); return lck; -- cgit From e7d2e311a293709c74a97d0e30665dadae510712 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Dec 2005 17:46:29 +0000 Subject: r12234: Reduce the race condition for renames by holding the lock longer. Instigated by complaints on the fix for #3303 from SATOH Fumiyasu . Jeremy. (This used to be commit 855f5f8c32aa530dbad244805a40200824724618) --- source3/locking/locking.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index b823b4712e..07377831b4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -605,8 +605,8 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, lck->num_share_modes = 0; lck->share_modes = NULL; lck->delete_on_close = False; - lck->modified = False; lck->fresh = False; + lck->modified = False; if (tdb_chainlock(tdb, key) != 0) { DEBUG(3, ("Could not lock share entry\n")); @@ -668,6 +668,10 @@ BOOL rename_share_filename(struct share_mode_lock *lck, size_t msg_len; int i; + if (!lck) { + return False; + } + DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n", servicepath, newname)); -- cgit From 33174847994128387a36a8103f147fe5a96c15fd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Jan 2006 22:17:54 +0000 Subject: r12877: Stop passing structs around in smb messages, instead always linearize into little-endian. Should fix all Solaris issues with this, plus provide a cleaner base moving forward for cluster-aware Samba where smbd's can communicate across different compilers/architectures (eventually these message will have to go cross-machine). Jeremy. (This used to be commit d01824b78576a034428e1cef73868d1169057991) --- source3/locking/locking.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 07377831b4..d9737895ba 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -662,10 +662,10 @@ BOOL rename_share_filename(struct share_mode_lock *lck, const char *servicepath, const char *newname) { - struct file_renamed_message *frm = NULL; size_t sp_len; size_t fn_len; size_t msg_len; + char *frm = NULL; int i; if (!lck) { @@ -694,20 +694,21 @@ BOOL rename_share_filename(struct share_mode_lock *lck, sp_len = strlen(lck->servicepath); fn_len = strlen(lck->filename); - msg_len = sizeof(*frm) + sp_len + 1 + fn_len + 1; + msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + fn_len + 1; /* Set up the name changed message. */ frm = TALLOC(lck, msg_len); if (!frm) { return False; } - frm->dev = lck->dev; - frm->inode = lck->ino; + + SDEV_T_VAL(frm,0,lck->dev); + SINO_T_VAL(frm,8,lck->ino); DEBUG(10,("rename_share_filename: msg_len = %d\n", msg_len )); - safe_strcpy(&frm->names[0], lck->servicepath, sp_len); - safe_strcpy(&frm->names[sp_len + 1], lck->filename, fn_len); + safe_strcpy(&frm[16], lck->servicepath, sp_len); + safe_strcpy(&frm[16 + sp_len + 1], lck->filename, fn_len); /* Send the messages. */ for (i=0; inum_share_modes; i++) { @@ -723,11 +724,13 @@ BOOL rename_share_filename(struct share_mode_lock *lck, DEBUG(10,("rename_share_filename: sending rename message to pid %u " "dev %x, inode %.0f sharepath %s newname %s\n", (unsigned int)procid_to_pid(&se->pid), - (unsigned int)frm->dev, (double)frm->inode, + (unsigned int)lck->dev, (double)lck->ino, lck->servicepath, lck->filename )); + become_root(); message_send_pid(se->pid, MSG_SMB_FILE_RENAME, frm, msg_len, True); + unbecome_root(); } return True; -- cgit From 6afd823e42aef3cc64a64d085438cc4d14ef3498 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 24 Jan 2006 17:27:30 +0000 Subject: r13110: remove an invalid debug message about call get_share_mode_lock() with a NULL service path and fname (we do it all the time internally) (This used to be commit e1f75ea63780f4a1661f19554d18bbd73b069c1b) --- source3/locking/locking.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d9737895ba..9a13e099db 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -626,7 +626,6 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, if (lck->fresh) { if (fname == NULL || servicepath == NULL) { - DEBUG(0, ("New file, but no filename or servicepath supplied\n")); talloc_free(lck); return NULL; } -- cgit From 6a097ab20ea54a7b090ad6e62c1538d5e5997f31 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Jan 2006 19:54:39 +0000 Subject: r13192: Fix up alignment issues when printing share mode entries. Add paranioa to debug so we know when an entry is unused. Jeremy. (This used to be commit fa5fab313e3728ff49c00ca1097242039506f83e) --- source3/locking/locking.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 9a13e099db..770ef918b8 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -384,11 +384,13 @@ char *share_mode_str(int num, struct share_mode_entry *e) { static pstring share_str; - slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: " + slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s " "pid = %s, share_access = 0x%x, private_options = 0x%x, " "access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, " "dev = 0x%x, inode = %.0f", - num, procid_str_static(&e->pid), + num, + e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "", + procid_str_static(&e->pid), e->share_access, e->private_options, e->access_mask, e->op_mid, e->op_type, e->share_file_id, (unsigned int)e->dev, (double)e->inode ); @@ -408,9 +410,11 @@ static void print_share_mode_table(struct locking_data *data) int i; for (i = 0; i < num_share_modes; i++) { - struct share_mode_entry *entry_p = &shares[i]; + struct share_mode_entry entry; + + memcpy(&entry, &shares[i], sizeof(struct share_mode_entry)); DEBUG(10,("print_share_mode_table: %s\n", - share_mode_str(i, entry_p))); + share_mode_str(i, &entry))); } } -- cgit From 6f08a557bae46eb9a2f992dfcdc6c1954f55c703 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Jan 2006 19:59:48 +0000 Subject: r13194: Don't do extra memcpy's unless we're asked to. Jeremy. (This used to be commit f93e1e75563679dc07958168b283dfc0eb2de5b0) --- source3/locking/locking.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 770ef918b8..be1e83121b 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -547,7 +547,11 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) offset += sp_len + 1; safe_strcpy(result.dptr + offset, lck->filename, result.dsize - offset - 1); - print_share_mode_table(data); + + if (DEBUGLEVEL >= 10) { + print_share_mode_table(data); + } + return result; } -- cgit From bd34c2ac25af690a00cbbded5b57a834a4e35875 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Jan 2006 23:30:30 +0000 Subject: r13198: Fix issues exposed by Jerry's testing on 64-bit Solaris (I hope). Separate 3.0.21b patch sent to Jerry. Jeremy. (This used to be commit 837e7ea7e40cedc6b01e023445feb4a90c4bf8b9) --- source3/locking/locking.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index be1e83121b..e31ead30e4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -988,28 +988,6 @@ BOOL downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp) return True; } - -/******************************************************************* - We've just told all the smbd's that our level2 or fake level2 has been - written to. -********************************************************************/ -BOOL remove_all_share_oplocks(struct share_mode_lock *lck, files_struct *fsp) -{ - int i; - for (i=0; inum_share_modes; i++) { - struct share_mode_entry *e = &lck->share_modes[i]; - if (!is_valid_share_mode_entry(e)) { - continue; - } - if (e->op_type == NO_OPLOCK) { - continue; - } - e->op_type = NO_OPLOCK; - lck->modified = True; - } - return True; -} - /**************************************************************************** Deal with the internal needs of setting the delete on close flag. Note that as the tdb locking is recursive, it is safe to call this from within -- cgit From 86c9bac4c31df1606e3758ec42672506dde26cc6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Feb 2006 04:14:07 +0000 Subject: r13274: Fix for bug #3467. Not a show stopper. jason qian was a *fantastic* help in tracking this down. Jeremy. (This used to be commit 9f4a9c70fa232047868e5d8a3f132a2dd6bfee82) --- source3/locking/locking.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e31ead30e4..e8309582fd 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -49,6 +49,7 @@ struct locking_data { struct { int num_share_mode_entries; BOOL delete_on_close; + BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */ } s; struct share_mode_entry dummy; /* Needed for alignment. */ } u; @@ -435,11 +436,15 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) data = (struct locking_data *)dbuf.dptr; lck->delete_on_close = data->u.s.delete_on_close; + lck->initial_delete_on_close = data->u.s.initial_delete_on_close; lck->num_share_modes = data->u.s.num_share_mode_entries; DEBUG(10, ("parse_share_modes: delete_on_close: %d, " - "num_share_modes: %d\n", lck->delete_on_close, - lck->num_share_modes)); + "initial_delete_on_close: %d, " + "num_share_modes: %d\n", + lck->delete_on_close, + lck->initial_delete_on_close, + lck->num_share_modes)); if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { DEBUG(0, ("invalid number of share modes: %d\n", @@ -535,8 +540,10 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) ZERO_STRUCTP(data); data->u.s.num_share_mode_entries = lck->num_share_modes; data->u.s.delete_on_close = lck->delete_on_close; - DEBUG(10, ("unparse_share_modes: del: %d, num: %d\n", + data->u.s.initial_delete_on_close = lck->initial_delete_on_close; + DEBUG(10, ("unparse_share_modes: del: %d, initial del %d, num: %d\n", data->u.s.delete_on_close, + data->u.s.initial_delete_on_close, data->u.s.num_share_mode_entries)); memcpy(result.dptr + sizeof(*data), lck->share_modes, sizeof(struct share_mode_entry)*lck->num_share_modes); @@ -613,6 +620,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, lck->num_share_modes = 0; lck->share_modes = NULL; lck->delete_on_close = False; + lck->initial_delete_on_close = False; lck->fresh = False; lck->modified = False; @@ -1046,6 +1054,7 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, changed the delete on close flag. This will be noticed in the close code, the last closer will delete the file if flag is set. + Note that setting this to any value clears the initial_delete_on_close flag. ****************************************************************************/ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) @@ -1070,6 +1079,11 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) lck->modified = True; } + if (lck->initial_delete_on_close) { + lck->initial_delete_on_close = False; + lck->modified = True; + } + talloc_free(lck); return True; } -- cgit From d14af63e6ab600eb3ac705f2f425c860e927553a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Feb 2006 20:44:50 +0000 Subject: r13293: Rather a big patch I'm afraid, but this should fix bug #3347 by saving the UNIX token used to set a delete on close flag, and using it when doing the delete. libsmbsharemodes.so still needs updating to cope with this change. Samba4 torture tests to follow. Jeremy. (This used to be commit 23f16cbc2e8cde97c486831e26bcafd4ab4a9654) --- source3/locking/locking.c | 157 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 142 insertions(+), 15 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e8309582fd..e558c6d74f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -50,6 +50,9 @@ struct locking_data { int num_share_mode_entries; BOOL delete_on_close; BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */ + uint32 delete_token_size; /* Only valid if either of + the two previous fields + are True. */ } s; struct share_mode_entry dummy; /* Needed for alignment. */ } u; @@ -429,8 +432,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) int i; if (dbuf.dsize < sizeof(struct locking_data)) { - DEBUG(0, ("parse_share_modes: buffer too short\n")); - return False; + smb_panic("PANIC: parse_share_modes: buffer too short.\n"); } data = (struct locking_data *)dbuf.dptr; @@ -449,18 +451,17 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { DEBUG(0, ("invalid number of share modes: %d\n", lck->num_share_modes)); - return False; + smb_panic("PANIC: invalid number of share modes"); } lck->share_modes = NULL; - + if (lck->num_share_modes != 0) { if (dbuf.dsize < (sizeof(struct locking_data) + (lck->num_share_modes * sizeof(struct share_mode_entry)))) { - DEBUG(0, ("parse_share_modes: buffer too short\n")); - return False; + smb_panic("PANIC: parse_share_modes: buffer too short.\n"); } lck->share_modes = talloc_memdup(lck, dbuf.dptr+sizeof(*data), @@ -468,20 +469,67 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) sizeof(struct share_mode_entry)); if (lck->share_modes == NULL) { - DEBUG(0, ("talloc failed\n")); - return False; + smb_panic("talloc failed\n"); } } + /* Get any delete token. */ + if (data->u.s.delete_token_size) { + /* Each uid/gid is stored as a 4 byte value. */ + uint32 val; + uint32 *p = (uint32 *)(dbuf.dptr + sizeof(*data) + + (lck->num_share_modes * + sizeof(struct share_mode_entry))); + + if ((data->u.s.delete_token_size < 8) || (data->u.s.delete_token_size % 4) != 0) { + DEBUG(0, ("parse_share_modes: invalid token size %d\n", + data->u.s.delete_token_size)); + smb_panic("parse_share_modes: invalid token size\n"); + } + + lck->delete_token = TALLOC_P(lck, UNIX_USER_TOKEN); + if (!lck->delete_token) { + smb_panic("talloc failed\n"); + } + + /* Copy out the uid and gid. */ + memcpy(&val, p++, 4); + lck->delete_token->uid = (uid_t)val; + memcpy(&val, p++, 4); + lck->delete_token->gid = (gid_t)val; + + /* Any supplementary groups ? */ + lck->delete_token->ngroups = (data->u.s.delete_token_size > 8) ? + ((data->u.s.delete_token_size - 8)/4) : 0; + if (lck->delete_token->ngroups) { + /* Make this a talloc child of lck->delete_token. */ + lck->delete_token->groups = TALLOC_ARRAY(lck->delete_token, gid_t, + lck->delete_token->ngroups); + if (!lck->delete_token) { + smb_panic("talloc failed\n"); + } + + for (i = 0; i < lck->delete_token->ngroups; i++) { + memcpy(&val, p++, 4); + lck->delete_token->groups[i] = (gid_t)val; + } + } + + } else { + lck->delete_token = NULL; + } + /* Save off the associated service path and filename. */ lck->servicepath = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + - (lck->num_share_modes * - sizeof(struct share_mode_entry))); + (lck->num_share_modes * + sizeof(struct share_mode_entry)) + + data->u.s.delete_token_size ); lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + - (lck->num_share_modes * - sizeof(struct share_mode_entry)) + - strlen(lck->servicepath) + 1 ); + (lck->num_share_modes * + sizeof(struct share_mode_entry)) + + data->u.s.delete_token_size + + strlen(lck->servicepath) + 1 ); /* * Ensure that each entry has a real process attached. @@ -528,6 +576,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) result.dsize = sizeof(*data) + lck->num_share_modes * sizeof(struct share_mode_entry) + + (lck->delete_token ? (8 + (lck->delete_token->ngroups*4)) : 0) + sp_len + 1 + strlen(lck->filename) + 1; result.dptr = talloc_size(lck, result.dsize); @@ -549,6 +598,25 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) sizeof(struct share_mode_entry)*lck->num_share_modes); offset = sizeof(*data) + sizeof(struct share_mode_entry)*lck->num_share_modes; + + /* Store any delete on close token. */ + if (lck->delete_token) { + uint32 val; + uint32 *p = (uint32 *)(result.dptr + offset); + + val = (uint32)lck->delete_token->uid; + memcpy(p++, &val, 4); + + val = (uint32)lck->delete_token->uid; + memcpy(p++, &val, 4); + + for (i = 0; i < lck->delete_token->ngroups; i++) { + val = (uint32)lck->delete_token->groups[i]; + memcpy(p++, &val, 4); + } + offset = ((char *)p - result.dptr); + } + safe_strcpy(result.dptr + offset, lck->servicepath, result.dsize - offset - 1); offset += sp_len + 1; @@ -619,6 +687,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, lck->ino = ino; lck->num_share_modes = 0; lck->share_modes = NULL; + lck->delete_token = NULL; lck->delete_on_close = False; lck->initial_delete_on_close = False; lck->fresh = False; @@ -1047,6 +1116,55 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, return NT_STATUS_OK; } +/************************************************************************* + Return a talloced copy of a UNIX_USER_TOKEN. NULL on fail. + (Should this be in locking.c.... ?). +*************************************************************************/ + +static UNIX_USER_TOKEN *copy_unix_token(TALLOC_CTX *ctx, UNIX_USER_TOKEN *tok) +{ + UNIX_USER_TOKEN *cpy; + + if (tok == NULL) { + return NULL; + } + + cpy = TALLOC_P(ctx, UNIX_USER_TOKEN); + if (!cpy) { + return NULL; + } + + cpy->uid = tok->uid; + cpy->gid = tok->gid; + cpy->ngroups = tok->ngroups; + if (tok->ngroups) { + /* Make this a talloc child of cpy. */ + cpy->groups = TALLOC_ARRAY(cpy, gid_t, tok->ngroups); + if (!cpy->groups) { + return NULL; + } + memcpy(cpy->groups, tok->groups, tok->ngroups * sizeof(gid_t)); + } + return cpy; +} + +/**************************************************************************** + Replace the delete on close token. +****************************************************************************/ + +void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok) +{ + /* Ensure there's no token. */ + if (lck->delete_token) { + talloc_free(lck->delete_token); /* Also deletes groups... */ + lck->delete_token = NULL; + } + + /* Copy the new token (can be NULL). */ + lck->delete_token = copy_unix_token(lck, tok); + lck->modified = True; +} + /**************************************************************************** Sets the delete on close flag over all share modes on this file. Modify the share mode entry for all files open @@ -1055,9 +1173,11 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, in the close code, the last closer will delete the file if flag is set. Note that setting this to any value clears the initial_delete_on_close flag. + If delete_on_close is True this makes a copy of any UNIX_USER_TOKEN into the + lck entry. ****************************************************************************/ -BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) +BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKEN *tok) { struct share_mode_lock *lck; @@ -1074,8 +1194,13 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) if (lck == NULL) { return False; } + if (lck->delete_on_close != delete_on_close) { + set_delete_on_close_token(lck, tok); lck->delete_on_close = delete_on_close; + if (delete_on_close) { + SMB_ASSERT(lck->delete_token != NULL); + } lck->modified = True; } @@ -1105,9 +1230,11 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, data = (struct locking_data *)dbuf.dptr; shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data)); sharepath = dbuf.dptr + sizeof(*data) + - data->u.s.num_share_mode_entries*sizeof(*shares); + data->u.s.num_share_mode_entries*sizeof(*shares) + + data->u.s.delete_token_size; fname = dbuf.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares) + + data->u.s.delete_token_size + strlen(sharepath) + 1; for (i=0;iu.s.num_share_mode_entries;i++) { -- cgit From 466230e5a10c2175535f7224df644fa6d09607e6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Feb 2006 21:29:49 +0000 Subject: r13294: Fix basic delete on close tests - don't forget to tell the data struct how big the token is... :-). Jeremy. (This used to be commit f259de8b69f94ae8b5f4553180f245234bffd397) --- source3/locking/locking.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e558c6d74f..666988b541 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -558,6 +558,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) struct locking_data *data; ssize_t offset; ssize_t sp_len; + uint32 delete_token_size; result.dptr = NULL; result.dsize = 0; @@ -573,10 +574,12 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) } sp_len = strlen(lck->servicepath); + delete_token_size = (lck->delete_token ? + (8 + (lck->delete_token->ngroups*4)) : 0); result.dsize = sizeof(*data) + lck->num_share_modes * sizeof(struct share_mode_entry) + - (lck->delete_token ? (8 + (lck->delete_token->ngroups*4)) : 0) + + delete_token_size + sp_len + 1 + strlen(lck->filename) + 1; result.dptr = talloc_size(lck, result.dsize); @@ -590,10 +593,12 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) data->u.s.num_share_mode_entries = lck->num_share_modes; data->u.s.delete_on_close = lck->delete_on_close; data->u.s.initial_delete_on_close = lck->initial_delete_on_close; - DEBUG(10, ("unparse_share_modes: del: %d, initial del %d, num: %d\n", - data->u.s.delete_on_close, - data->u.s.initial_delete_on_close, - data->u.s.num_share_mode_entries)); + data->u.s.delete_token_size = delete_token_size; + DEBUG(10, ("unparse_share_modes: del: %d, initial del %d, tok = %u, num: %d\n", + data->u.s.delete_on_close, + data->u.s.initial_delete_on_close, + (unsigned int)data->u.s.delete_token_size, + data->u.s.num_share_mode_entries)); memcpy(result.dptr + sizeof(*data), lck->share_modes, sizeof(struct share_mode_entry)*lck->num_share_modes); offset = sizeof(*data) + -- cgit From 40d3c7ebb22bae6f486e8c60c3bb0494d2d397d9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 4 Feb 2006 06:31:04 +0000 Subject: r13329: Fix libsmbsharemodes.so to work with the stored delete token. Less trouble than I thought plus it didn't need an interface change (thank goodness !). Jeremy. (This used to be commit dbe2572d1c713f46b0d1d0c405f88456c9336297) --- source3/locking/locking.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 666988b541..9a707f80a4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -44,24 +44,6 @@ uint16 global_smbpid; /* the locking database handle */ static TDB_CONTEXT *tdb; -struct locking_data { - union { - struct { - int num_share_mode_entries; - BOOL delete_on_close; - BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */ - uint32 delete_token_size; /* Only valid if either of - the two previous fields - are True. */ - } s; - struct share_mode_entry dummy; /* Needed for alignment. */ - } u; - /* the following two entries are implicit - struct share_mode_entry modes[num_share_mode_entries]; - char file_name[]; - */ -}; - /**************************************************************************** Debugging aid :-). ****************************************************************************/ -- cgit From 30e47fdfe2fa7e5fee18718a09a094a7474b3a1b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Feb 2006 18:18:51 +0000 Subject: r13412: Don't use arbitrary uint32 size for uid and gid storage. Use correct system size. Fixed a bug that was accidentally introduced by use of uint32 - uid was stored twice, not uid and gid. Jeremy. (This used to be commit 89db006997588c6523ce8f2470d67f3136042256) --- source3/locking/locking.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 9a707f80a4..d157c30c82 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -457,13 +457,12 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) /* Get any delete token. */ if (data->u.s.delete_token_size) { - /* Each uid/gid is stored as a 4 byte value. */ - uint32 val; - uint32 *p = (uint32 *)(dbuf.dptr + sizeof(*data) + + char *p = dbuf.dptr + sizeof(*data) + (lck->num_share_modes * - sizeof(struct share_mode_entry))); + sizeof(struct share_mode_entry)); - if ((data->u.s.delete_token_size < 8) || (data->u.s.delete_token_size % 4) != 0) { + if ((data->u.s.delete_token_size < sizeof(uid_t) + sizeof(gid_t)) || + ((data->u.s.delete_token_size - sizeof(uid_t)) % sizeof(gid_t)) != 0) { DEBUG(0, ("parse_share_modes: invalid token size %d\n", data->u.s.delete_token_size)); smb_panic("parse_share_modes: invalid token size\n"); @@ -475,14 +474,16 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) } /* Copy out the uid and gid. */ - memcpy(&val, p++, 4); - lck->delete_token->uid = (uid_t)val; - memcpy(&val, p++, 4); - lck->delete_token->gid = (gid_t)val; + memcpy(&lck->delete_token->uid, p, sizeof(uid_t)); + p += sizeof(uid_t); + memcpy(&lck->delete_token->gid, p, sizeof(gid_t)); + p += sizeof(gid_t); /* Any supplementary groups ? */ - lck->delete_token->ngroups = (data->u.s.delete_token_size > 8) ? - ((data->u.s.delete_token_size - 8)/4) : 0; + lck->delete_token->ngroups = (data->u.s.delete_token_size > (sizeof(uid_t) + sizeof(gid_t))) ? + ((data->u.s.delete_token_size - + (sizeof(uid_t) + sizeof(gid_t)))/sizeof(gid_t)) : 0; + if (lck->delete_token->ngroups) { /* Make this a talloc child of lck->delete_token. */ lck->delete_token->groups = TALLOC_ARRAY(lck->delete_token, gid_t, @@ -492,8 +493,8 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) } for (i = 0; i < lck->delete_token->ngroups; i++) { - memcpy(&val, p++, 4); - lck->delete_token->groups[i] = (gid_t)val; + memcpy(&lck->delete_token->groups[i], p, sizeof(gid_t)); + p += sizeof(gid_t); } } @@ -557,7 +558,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) sp_len = strlen(lck->servicepath); delete_token_size = (lck->delete_token ? - (8 + (lck->delete_token->ngroups*4)) : 0); + (sizeof(uid_t) + sizeof(gid_t) + (lck->delete_token->ngroups*sizeof(gid_t))) : 0); result.dsize = sizeof(*data) + lck->num_share_modes * sizeof(struct share_mode_entry) + @@ -588,20 +589,18 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) /* Store any delete on close token. */ if (lck->delete_token) { - uint32 val; - uint32 *p = (uint32 *)(result.dptr + offset); + char *p = result.dptr + offset; - val = (uint32)lck->delete_token->uid; - memcpy(p++, &val, 4); + memcpy(p, &lck->delete_token->uid, sizeof(uid_t)); + p += sizeof(uid_t); - val = (uint32)lck->delete_token->uid; - memcpy(p++, &val, 4); + memcpy(p, &lck->delete_token->gid, sizeof(gid_t)); for (i = 0; i < lck->delete_token->ngroups; i++) { - val = (uint32)lck->delete_token->groups[i]; - memcpy(p++, &val, 4); + memcpy(p, &lck->delete_token->groups[i], sizeof(gid_t)); + p += sizeof(gid_t); } - offset = ((char *)p - result.dptr); + offset = p - result.dptr; } safe_strcpy(result.dptr + offset, lck->servicepath, -- cgit From fb5362c069b5b6548478b2217a0519c56d856705 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 20 Feb 2006 17:59:58 +0000 Subject: r13571: Replace all calls to talloc_free() with thye TALLOC_FREE() macro which sets the freed pointer to NULL. (This used to be commit b65be8874a2efe5a4b167448960a4fcf6bd995e2) --- source3/locking/locking.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d157c30c82..076f8a4969 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -681,7 +681,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, if (tdb_chainlock(tdb, key) != 0) { DEBUG(3, ("Could not lock share entry\n")); - talloc_free(lck); + TALLOC_FREE(lck); return NULL; } @@ -697,20 +697,20 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, if (lck->fresh) { if (fname == NULL || servicepath == NULL) { - talloc_free(lck); + TALLOC_FREE(lck); return NULL; } lck->filename = talloc_strdup(lck, fname); lck->servicepath = talloc_strdup(lck, servicepath); if (lck->filename == NULL || lck->servicepath == NULL) { DEBUG(0, ("talloc failed\n")); - talloc_free(lck); + TALLOC_FREE(lck); return NULL; } } else { if (!parse_share_modes(data, lck)) { DEBUG(0, ("Could not parse share modes\n")); - talloc_free(lck); + TALLOC_FREE(lck); SAFE_FREE(data.dptr); return NULL; } @@ -814,7 +814,7 @@ BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) return False; } result = lck->delete_on_close; - talloc_free(lck); + TALLOC_FREE(lck); return result; } @@ -1142,7 +1142,7 @@ void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok { /* Ensure there's no token. */ if (lck->delete_token) { - talloc_free(lck->delete_token); /* Also deletes groups... */ + TALLOC_FREE(lck->delete_token); /* Also deletes groups... */ lck->delete_token = NULL; } @@ -1195,7 +1195,7 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE lck->modified = True; } - talloc_free(lck); + TALLOC_FREE(lck); return True; } -- cgit From 894358a8f3e338b339b6c37233edef794b312087 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Mar 2006 06:31:04 +0000 Subject: r13915: Fixed a very interesting class of realloc() bugs found by Coverity. realloc can return NULL in one of two cases - (1) the realloc failed, (2) realloc succeeded but the new size requested was zero, in which case this is identical to a free() call. The error paths dealing with these two cases should be different, but mostly weren't. Secondly the standard idiom for dealing with realloc when you know the new size is non-zero is the following : tmp = realloc(p, size); if (!tmp) { SAFE_FREE(p); return error; } else { p = tmp; } However, there were *many* *many* places in Samba where we were using the old (broken) idiom of : p = realloc(p, size) if (!p) { return error; } which will leak the memory pointed to by p on realloc fail. This commit (hopefully) fixes all these cases by moving to a standard idiom of : p = SMB_REALLOC(p, size) if (!p) { return error; } Where if the realloc returns null due to the realloc failing or size == 0 we *guarentee* that the storage pointed to by p has been freed. This allows me to remove a lot of code that was dealing with the standard (more verbose) method that required a tmp pointer. This is almost always what you want. When a realloc fails you never usually want the old memory, you want to free it and get into your error processing asap. For the 11 remaining cases where we really do need to keep the old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR, which can be used as follows : tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size); if (!tmp) { SAFE_FREE(p); return error; } else { p = tmp; } SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the pointer p, even on size == 0 or realloc fail. All this is done by a hidden extra argument to Realloc(), BOOL free_old_on_error which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR macros (and their array counterparts). It remains to be seen what this will do to our Coverity bug count :-). Jeremy. (This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0) --- source3/locking/brlock.c | 7 ++----- source3/locking/posix.c | 17 ++++++----------- 2 files changed, 8 insertions(+), 16 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 25a1ed5e2f..8af6effb19 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -354,7 +354,6 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, TDB_DATA kbuf, dbuf; int count, i; struct lock_struct lock, *locks; - char *tp; NTSTATUS status = NT_STATUS_OK; *my_lock_ctx = False; @@ -401,12 +400,10 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, } /* no conflicts - add it to the list of locks */ - tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(*locks)); - if (!tp) { + dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(*locks)); + if (!dbuf.dptr) { status = NT_STATUS_NO_MEMORY; goto fail; - } else { - dbuf.dptr = tp; } memcpy(dbuf.dptr + dbuf.dsize, &lock, sizeof(lock)); dbuf.dsize += sizeof(lock); diff --git a/source3/locking/posix.c b/source3/locking/posix.c index c63992adc5..4b69047a3c 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -99,20 +99,17 @@ static BOOL add_fd_to_close_entry(files_struct *fsp) { TDB_DATA kbuf = locking_key_fsp(fsp); TDB_DATA dbuf; - char *tp; dbuf.dptr = NULL; dbuf.dsize = 0; dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); - if (!tp) { + dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); + if (!dbuf.dptr) { DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n")); - SAFE_FREE(dbuf.dptr); return False; - } else - dbuf.dptr = tp; + } memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int)); dbuf.dsize += sizeof(int); @@ -358,7 +355,6 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s TDB_DATA kbuf = locking_key_fsp(fsp); TDB_DATA dbuf; struct posix_lock pl; - char *tp; dbuf.dptr = NULL; dbuf.dsize = 0; @@ -376,12 +372,11 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s pl.size = size; pl.lock_type = lock_type; - tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock)); - if (!tp) { + dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock)); + if (!dbuf.dptr) { DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); goto fail; - } else - dbuf.dptr = tp; + } memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock)); dbuf.dsize += sizeof(struct posix_lock); -- cgit From d6eebce490cfa7b17f9ca2779744db2924f1d165 Mon Sep 17 00:00:00 2001 From: James Peach Date: Wed, 15 Mar 2006 05:49:32 +0000 Subject: r14428: Call fill_share_mode_entry with NO_OPLOCK instead of 0. (This used to be commit a39cbaa699d111264c2c9dda49a6e4f42acd3fb8) --- source3/locking/locking.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 076f8a4969..5cb1f71555 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -982,7 +982,7 @@ BOOL del_share_mode(struct share_mode_lock *lck, files_struct *fsp) { struct share_mode_entry entry, *e; - fill_share_mode_entry(&entry, fsp, 0, 0); + fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK); e = find_share_mode_entry(lck, &entry); if (e == NULL) { @@ -1018,7 +1018,7 @@ BOOL remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp) { struct share_mode_entry entry, *e; - fill_share_mode_entry(&entry, fsp, 0, 0); + fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK); e = find_share_mode_entry(lck, &entry); if (e == NULL) { @@ -1039,7 +1039,7 @@ BOOL downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp) { struct share_mode_entry entry, *e; - fill_share_mode_entry(&entry, fsp, 0, 0); + fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK); e = find_share_mode_entry(lck, &entry); if (e == NULL) { -- cgit From 7f57dc61cbf2f421ad9af82164ca0e03c72c5949 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 25 Mar 2006 01:35:43 +0000 Subject: r14703: Clarify the return codes for the POSIX locking case. This was confusing. Jeremy. (This used to be commit bc1a605a39e58a7dbdcd4d132345e957e3ed9d5e) --- source3/locking/posix.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 4b69047a3c..07246474f3 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -644,15 +644,19 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, /**************************************************************************** Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and - broken NFS implementations. + broken NFS implementations. Returns True if we got the lock or the region + is unlocked in the F_GETLK case, False otherwise. ****************************************************************************/ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { - int ret; + BOOL ret; DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type)); + /* In the F_GETLK case this returns True if the region + was locked, False if unlocked. */ + ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { -- cgit From 81d4f40bbe202e5dae3d4d1070b02edf16a9f62e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 29 Mar 2006 22:19:01 +0000 Subject: r14763: Add a new tuning parameter, open files database hash size, this allows us to experiment with ensuring the tdb hash size for our open files and locking db are appropriately sized. Make the hash size larger by default (10007 instead of 1049) and make the locking db hash size the same as the open file db hash size. Jeremy. (This used to be commit e7225f7e813423c3e2a94af6a9d7ce8a1b50a166) --- source3/locking/brlock.c | 6 ++++-- source3/locking/locking.c | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 8af6effb19..5078515b3e 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -289,8 +289,10 @@ void brl_init(int read_only) { if (tdb) return; - tdb = tdb_open_log(lock_path("brlock.tdb"), 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 ); + tdb = tdb_open_log(lock_path("brlock.tdb"), + lp_open_files_db_hash_size(), + TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 ); if (!tdb) { DEBUG(0,("Failed to open byte range locking database\n")); return; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 5cb1f71555..0ecc90c794 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -301,7 +301,8 @@ BOOL locking_init(int read_only) return True; tdb = tdb_open_log(lock_path("locking.tdb"), - SMB_OPEN_DATABASE_TDB_HASH_SIZE, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), + lp_open_files_db_hash_size(), + TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); -- cgit From 22dbd67708f1651a2341d70ce576fac360affccf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Apr 2006 15:33:04 +0000 Subject: r15018: Merge Volker's ipc/trans2/nttrans changes over into 3.0. Also merge the new POSIX lock code - this is not enabled unless -DDEVELOPER is defined. This doesn't yet map onto underlying system POSIX locks. Updates vfs to allow lock queries. Jeremy. (This used to be commit 08e52ead03304ff04229e1bfe544ff40e2564fc7) --- source3/locking/brlock.c | 1300 ++++++++++++++++++++++++++++++++++----------- source3/locking/locking.c | 305 +++++++---- source3/locking/posix.c | 91 +++- 3 files changed, 1247 insertions(+), 449 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 5078515b3e..b95bb895cc 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -52,6 +52,7 @@ struct lock_struct { br_off size; int fnum; enum brl_type lock_type; + enum brl_flavour lock_flav; }; /* The key used in the brlock database. */ @@ -65,6 +66,26 @@ struct lock_key { static TDB_CONTEXT *tdb; +/**************************************************************************** + Debug info at level 10 for lock struct. +****************************************************************************/ + +static void print_lock_struct(unsigned int i, struct lock_struct *pls) +{ + DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %u, ", + i, + (unsigned int)pls->context.smbpid, + (unsigned int)pls->context.tid, + (unsigned int)procid_to_pid(&pls->context.pid) )); + + DEBUG(10,("start = %.0f, size = %.0f, fnum = %d, %s %s\n", + (double)pls->start, + (double)pls->size, + pls->fnum, + lock_type_name(pls->lock_type), + lock_flav_name(pls->lock_flav) )); +} + /**************************************************************************** Create a locking key - ensuring zero filled for pad purposes. ****************************************************************************/ @@ -86,8 +107,8 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) See if two locking contexts are equal. ****************************************************************************/ -static BOOL brl_same_context(struct lock_context *ctx1, - struct lock_context *ctx2) +static BOOL brl_same_context(const struct lock_context *ctx1, + const struct lock_context *ctx2) { return (procid_equal(&ctx1->pid, &ctx2->pid) && (ctx1->smbpid == ctx2->smbpid) && @@ -98,8 +119,8 @@ static BOOL brl_same_context(struct lock_context *ctx1, See if lck1 and lck2 overlap. ****************************************************************************/ -static BOOL brl_overlap(struct lock_struct *lck1, - struct lock_struct *lck2) +static BOOL brl_overlap(const struct lock_struct *lck1, + const struct lock_struct *lck2) { /* this extra check is not redundent - it copes with locks that go beyond the end of 64 bit file space */ @@ -120,12 +141,14 @@ static BOOL brl_overlap(struct lock_struct *lck1, See if lock2 can be added when lock1 is in place. ****************************************************************************/ -static BOOL brl_conflict(struct lock_struct *lck1, - struct lock_struct *lck2) +static BOOL brl_conflict(const struct lock_struct *lck1, + const struct lock_struct *lck2) { + /* Ignore PENDING locks. */ if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) return False; + /* Read locks never conflict. */ if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) { return False; } @@ -138,9 +161,42 @@ static BOOL brl_conflict(struct lock_struct *lck1, return brl_overlap(lck1, lck2); } +/**************************************************************************** + See if lock2 can be added when lock1 is in place - when both locks are POSIX + flavour. POSIX locks ignore fnum - they only care about dev/ino which we + know already match. +****************************************************************************/ + +static BOOL brl_conflict_posix(const struct lock_struct *lck1, + const struct lock_struct *lck2) +{ +#if defined(DEVELOPER) + SMB_ASSERT(lck1->lock_flav == POSIX_LOCK); + SMB_ASSERT(lck2->lock_flav == POSIX_LOCK); +#endif + + /* Ignore PENDING locks. */ + if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) + return False; + + /* Read locks never conflict. */ + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) { + return False; + } + + /* Locks on the same context con't conflict. Ignore fnum. */ + if (brl_same_context(&lck1->context, &lck2->context)) { + return False; + } + + /* One is read, the other write, or the context is different, + do they overlap ? */ + return brl_overlap(lck1, lck2); +} + #if ZERO_ZERO -static BOOL brl_conflict1(struct lock_struct *lck1, - struct lock_struct *lck2) +static BOOL brl_conflict1(const struct lock_struct *lck1, + const struct lock_struct *lck2) { if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) return False; @@ -169,10 +225,11 @@ static BOOL brl_conflict1(struct lock_struct *lck1, /**************************************************************************** Check to see if this lock conflicts, but ignore our own locks on the - same fnum only. + same fnum only. This is the read/write lock check code path. + This is never used in the POSIX lock case. ****************************************************************************/ -static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck2) +static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock_struct *lck2) { if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) return False; @@ -180,6 +237,12 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) return False; + /* POSIX flavour locks never conflict here - this is only called + in the read/write path. */ + + if (lck1->lock_flav == POSIX_LOCK && lck2->lock_flav == POSIX_LOCK) + return False; + /* * Incoming WRITE locks conflict with existing READ locks even * if the context is the same. JRA. See LOCKTEST7 in smbtorture. @@ -200,7 +263,7 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck app depends on this ? ****************************************************************************/ -static NTSTATUS brl_lock_failed(struct lock_struct *lock) +static NTSTATUS brl_lock_failed(const struct lock_struct *lock) { static struct lock_struct last_lock_failure; @@ -222,146 +285,432 @@ static NTSTATUS brl_lock_failed(struct lock_struct *lock) return NT_STATUS_LOCK_NOT_GRANTED; } -#if DONT_DO_THIS - /* doing this traversal could kill solaris machines under high load (tridge) */ - /* delete any dead locks */ - /**************************************************************************** - Delete a record if it is for a dead process, if check_self is true, then - delete any records belonging to this pid also (there shouldn't be any). + Open up the brlock.tdb database. ****************************************************************************/ -static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +void brl_init(int read_only) { - struct lock_struct *locks; - int count, i; - BOOL check_self = *(BOOL *)state; - pid_t mypid = sys_getpid(); - - tdb_chainlock(tdb, kbuf); + if (tdb) { + return; + } + tdb = tdb_open_log(lock_path("brlock.tdb"), + lp_open_files_db_hash_size(), + TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 ); + if (!tdb) { + DEBUG(0,("Failed to open byte range locking database %s\n", + lock_path("brlock.tdb"))); + return; + } +} - locks = (struct lock_struct *)dbuf.dptr; +/**************************************************************************** + Close down the brlock.tdb database. +****************************************************************************/ - count = dbuf.dsize / sizeof(*locks); - for (i=0; icontext.pid)) { +#if ZERO_ZERO +/**************************************************************************** + Compare two locks for sorting. +****************************************************************************/ - DEBUG(0,("brlock : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n", - (unsigned int)lock->context.pid )); +static int lock_compare(const struct lock_struct *lck1, + const struct lock_struct *lck2) +{ + if (lck1->start != lck2->start) { + return (lck1->start - lck2->start); + } + if (lck2->size != lck1->size) { + return ((int)lck1->size - (int)lck2->size); + } + return 0; +} +#endif - } else if (process_exists(&lock->context.pid)) { +/**************************************************************************** + Lock a range of bytes - Windows lock semantics. +****************************************************************************/ - DEBUG(10,("brlock : delete_fn. pid %u exists.\n", (unsigned int)lock->context.pid )); - continue; +static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, + const struct lock_struct *plock, + BOOL *my_lock_ctx) +{ + unsigned int i; + files_struct *fsp = br_lck->fsp; + struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + + for (i=0; i < br_lck->num_locks; i++) { + /* Do any Windows or POSIX locks conflict ? */ + if (brl_conflict(&locks[i], plock)) { + NTSTATUS status = brl_lock_failed(plock);; + /* Did we block ourselves ? */ + if (brl_same_context(&locks[i].context, &plock->context)) { + *my_lock_ctx = True; + } + return status; + } +#if ZERO_ZERO + if (plock->start == 0 && plock->size == 0 && + locks[i].size == 0) { + break; } +#endif + } - DEBUG(10,("brlock : delete_fn. Deleting record for process %u\n", - (unsigned int)lock->context.pid )); + /* We can get the Windows lock, now see if it needs to + be mapped into a lower level POSIX one, and if so can + we get it ? We tell the lower lock layer about the + lock type so it can cope with the difference between + Windows "stacking" locks and POSIX "flat" ones. */ - if (count > 1 && i < count-1) { - memmove(&locks[i], &locks[i+1], - sizeof(*locks)*((count-1) - i)); + if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) { + if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, WINDOWS_LOCK)) { + if (errno == EACCES || errno == EAGAIN) { + return NT_STATUS_FILE_LOCK_CONFLICT; + } else { + return map_nt_error_from_unix(errno); + } } - count--; - i--; } - if (count == 0) { - tdb_delete(tdb, kbuf); - } else if (count < (dbuf.dsize / sizeof(*locks))) { - dbuf.dsize = count * sizeof(*locks); - tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); + /* no conflicts - add it to the list of locks */ + locks = (struct lock_struct *)SMB_REALLOC(locks, (br_lck->num_locks + 1) * sizeof(*locks)); + if (!locks) { + return NT_STATUS_NO_MEMORY; } - tdb_chainunlock(tdb, kbuf); - return 0; + memcpy(&locks[br_lck->num_locks], plock, sizeof(struct lock_struct)); + br_lck->num_locks += 1; + br_lck->lock_data = (void *)locks; + br_lck->modified = True; + + return NT_STATUS_OK; } -#endif /**************************************************************************** - Open up the brlock.tdb database. + Cope with POSIX range splits and merges. ****************************************************************************/ -void brl_init(int read_only) +static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, + const struct lock_struct *ex, + const struct lock_struct *plock, + BOOL *lock_was_added) { - if (tdb) - return; - tdb = tdb_open_log(lock_path("brlock.tdb"), - lp_open_files_db_hash_size(), - TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 ); - if (!tdb) { - DEBUG(0,("Failed to open byte range locking database\n")); - return; + BOOL lock_types_differ = (ex->lock_type != plock->lock_type); + + /* We can't merge non-conflicting locks on different context - ignore fnum. */ + + if (!brl_same_context(&ex->context, &plock->context)) { + /* Just copy. */ + memcpy(&lck_arr[0], ex, sizeof(struct lock_struct)); + return 1; } -#if DONT_DO_THIS - /* doing this traversal could kill solaris machines under high load (tridge) */ - /* delete any dead locks */ - if (!read_only) { - BOOL check_self = False; - tdb_traverse(tdb, delete_fn, &check_self); + /* We now know we have the same context. */ + + /* Did we overlap ? */ + +/********************************************* + +---------+ + | ex | + +---------+ + +-------+ + | plock | + +-------+ +OR.... + +---------+ + | ex | + +---------+ +**********************************************/ + + if ( (ex->start >= (plock->start + plock->size)) || + (plock->start >= (ex->start + ex->size))) { + /* No overlap with this lock - copy existing. */ + memcpy(&lck_arr[0], ex, sizeof(struct lock_struct)); + return 1; } -#endif + +/********************************************* + +---------+ + | ex | + +---------+ + +---------------------------+ + | plock | -> replace with plock. + +---------------------------+ +**********************************************/ + + if ( (ex->start >= plock->start) && + (ex->start + ex->size <= plock->start + plock->size) ) { + memcpy(&lck_arr[0], plock, sizeof(struct lock_struct)); + *lock_was_added = True; + return 1; + } + +/********************************************* + +---------------+ + | ex | + +---------------+ + +---------------+ + | plock | + +---------------+ +BECOMES.... + +---------------+-------+ + | plock | ex | - different lock types. + +---------------+-------+ +OR.... + +-----------------------+ + | ex | - same lock type. + +-----------------------+ +**********************************************/ + + if ( (ex->start >= plock->start) && + (ex->start < plock->start + plock->size) && + (ex->start + ex->size > plock->start + plock->size) ) { + + *lock_was_added = True; + + /* If the lock types are the same, we merge, if different, we + add the new lock before the old. */ + + if (lock_types_differ) { + /* Add new. */ + memcpy(&lck_arr[0], plock, sizeof(struct lock_struct)); + memcpy(&lck_arr[1], ex, sizeof(struct lock_struct)); + /* Adjust existing start and size. */ + lck_arr[1].start = plock->start + plock->size; + lck_arr[1].size = (ex->start + ex->size) - (plock->start + plock->size); + return 2; + } else { + /* Merge. */ + memcpy(&lck_arr[0], plock, sizeof(struct lock_struct)); + /* Set new start and size. */ + lck_arr[0].start = plock->start; + lck_arr[0].size = (ex->start + ex->size) - plock->start; + return 1; + } + } + +/********************************************* + +---------------+ + | ex | + +---------------+ + +---------------+ + | plock | + +---------------+ +BECOMES.... + +-------+---------------+ + | ex | plock | - different lock types + +-------+---------------+ + +OR + +-----------------------+ + | ex | - same lock type. + +-----------------------+ + +**********************************************/ + + if ( (ex->start < plock->start) && + (ex->start + ex->size > plock->start) && + (ex->start + ex->size <= plock->start + plock->size) ) { + + *lock_was_added = True; + + /* If the lock types are the same, we merge, if different, we + add the new lock after the old. */ + + if (lock_types_differ) { + memcpy(&lck_arr[0], ex, sizeof(struct lock_struct)); + memcpy(&lck_arr[1], plock, sizeof(struct lock_struct)); + /* Adjust existing size. */ + lck_arr[0].size = plock->start - ex->start; + return 2; + } else { + /* Merge. */ + memcpy(&lck_arr[0], ex, sizeof(struct lock_struct)); + /* Adjust existing size. */ + lck_arr[0].size = (plock->start + plock->size) - ex->start; + return 1; + } + } + +/********************************************* + +---------------------------+ + | ex | + +---------------------------+ + +---------+ + | plock | + +---------+ +BECOMES..... + +-------+---------+---------+ + | ex | plock | ex | - different lock types. + +-------+---------+---------+ +OR + +---------------------------+ + | ex | - same lock type. + +---------------------------+ +**********************************************/ + + if ( (ex->start < plock->start) && (ex->start + ex->size > plock->start + plock->size) ) { + *lock_was_added = True; + + if (lock_types_differ) { + + /* We have to split ex into two locks here. */ + + memcpy(&lck_arr[0], ex, sizeof(struct lock_struct)); + memcpy(&lck_arr[1], plock, sizeof(struct lock_struct)); + memcpy(&lck_arr[2], ex, sizeof(struct lock_struct)); + + /* Adjust first existing size. */ + lck_arr[0].size = plock->start - ex->start; + + /* Adjust second existing start and size. */ + lck_arr[2].start = plock->start + plock->size; + lck_arr[2].size = (ex->start + ex->size) - (plock->start + plock->size); + return 3; + } else { + /* Just eat plock. */ + memcpy(&lck_arr[0], ex, sizeof(struct lock_struct)); + return 1; + } + } + + /* Never get here. */ + smb_panic("brlock_posix_split_merge\n"); + /* Notreached. */ + abort(); } /**************************************************************************** - Close down the brlock.tdb database. + Lock a range of bytes - POSIX lock semantics. + We must cope with range splits and merges. ****************************************************************************/ -void brl_shutdown(int read_only) +static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, + const struct lock_struct *plock, + BOOL *my_lock_ctx) { - if (!tdb) - return; + unsigned int i, count; + struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct lock_struct *tp; + files_struct *fsp = br_lck->fsp; + BOOL lock_was_added = False; + + /* No zero-zero locks for POSIX. */ + if (plock->start == 0 && plock->size == 0) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* Don't allow 64-bit lock wrap. */ + if (plock->start + plock->size < plock->start || + plock->start + plock->size < plock->size) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* The worst case scenario here is we have to split an + existing POSIX lock range into two, and add our lock, + so we need at most 2 more entries. */ + + tp = SMB_MALLOC_ARRAY(struct lock_struct, (br_lck->num_locks + 2)); + if (!tp) { + return NT_STATUS_NO_MEMORY; + } + + count = 0; + for (i=0; i < br_lck->num_locks; i++) { + if (locks[i].lock_flav == WINDOWS_LOCK) { + /* Do any Windows flavour locks conflict ? */ + if (brl_conflict(&locks[i], plock)) { + /* Did we block ourselves ? */ + if (brl_same_context(&locks[i].context, &plock->context)) { + *my_lock_ctx = True; + } + /* No games with error messages. */ + SAFE_FREE(tp); + return NT_STATUS_FILE_LOCK_CONFLICT; + } + /* Just copy the Windows lock into the new array. */ + memcpy(&tp[count], &locks[i], sizeof(struct lock_struct)); + count++; + } else { + /* POSIX conflict semantics are different. */ + if (brl_conflict_posix(&locks[i], plock)) { + /* Can't block ourselves with POSIX locks. */ + /* No games with error messages. */ + SAFE_FREE(tp); + return NT_STATUS_FILE_LOCK_CONFLICT; + } + + /* Work out overlaps. */ + count += brlock_posix_split_merge(&tp[count], &locks[i], plock, &lock_was_added); + } + } + + /* We can get the POSIX lock, now see if it needs to + be mapped into a lower level POSIX one, and if so can + we get it ? We well the lower lock layer about the + lock type so it can cope with the difference between + Windows "stacking" locks and POSIX "flat" ones. */ + +#if 0 + /* FIXME - this call doesn't work correctly yet for POSIX locks... */ -#if DONT_DO_THIS - /* doing this traversal could kill solaris machines under high load (tridge) */ - /* delete any dead locks */ - if (!read_only) { - BOOL check_self = True; - tdb_traverse(tdb, delete_fn, &check_self); + if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) { + + + if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, POSIX_LOCK)) { + if (errno == EACCES || errno == EAGAIN) { + SAFE_FREE(tp); + return NT_STATUS_FILE_LOCK_CONFLICT; + } else { + SAFE_FREE(tp); + return map_nt_error_from_unix(errno); + } + } } #endif - tdb_close(tdb); -} + if (!lock_was_added) { + memcpy(&tp[count], plock, sizeof(struct lock_struct)); + count++; + } -#if ZERO_ZERO -/**************************************************************************** -compare two locks for sorting -****************************************************************************/ -static int lock_compare(struct lock_struct *lck1, - struct lock_struct *lck2) -{ - if (lck1->start != lck2->start) return (lck1->start - lck2->start); - if (lck2->size != lck1->size) { - return ((int)lck1->size - (int)lck2->size); + /* Realloc so we don't leak entries per lock call. */ + tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks)); + if (!tp) { + return NT_STATUS_NO_MEMORY; } - return 0; + br_lck->num_locks = count; + br_lck->lock_data = (void *)tp; + br_lck->modified = True; + return NT_STATUS_OK; } -#endif /**************************************************************************** Lock a range of bytes. ****************************************************************************/ -NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, - uint16 smbpid, struct process_id pid, uint16 tid, - br_off start, br_off size, - enum brl_type lock_type, BOOL *my_lock_ctx) +NTSTATUS brl_lock(struct byte_range_lock *br_lck, + uint16 smbpid, + struct process_id pid, + br_off start, + br_off size, + enum brl_type lock_type, + enum brl_flavour lock_flav, + BOOL *my_lock_ctx) { - TDB_DATA kbuf, dbuf; - int count, i; - struct lock_struct lock, *locks; - NTSTATUS status = NT_STATUS_OK; + NTSTATUS ret; + struct lock_struct lock; *my_lock_ctx = False; - kbuf = locking_key(dev,ino); - - dbuf.dptr = NULL; #if !ZERO_ZERO if (start == 0 && size == 0) { @@ -369,66 +718,27 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, } #endif - tdb_chainlock(tdb, kbuf); - dbuf = tdb_fetch(tdb, kbuf); - lock.context.smbpid = smbpid; lock.context.pid = pid; - lock.context.tid = tid; + lock.context.tid = br_lck->fsp->conn->cnum; lock.start = start; lock.size = size; - lock.fnum = fnum; + lock.fnum = br_lck->fsp->fnum; lock.lock_type = lock_type; + lock.lock_flav = lock_flav; - if (dbuf.dptr) { - /* there are existing locks - make sure they don't conflict */ - locks = (struct lock_struct *)dbuf.dptr; - count = dbuf.dsize / sizeof(*locks); - for (i=0; ilock_data, (size_t)br_lck->num_locks, sizeof(lock), lock_compare); #endif - if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) { - status = NT_STATUS_INTERNAL_DB_CORRUPTION; - goto fail; - } - - SAFE_FREE(dbuf.dptr); - tdb_chainunlock(tdb, kbuf); - return NT_STATUS_OK; - - fail: - - SAFE_FREE(dbuf.dptr); - tdb_chainunlock(tdb, kbuf); - return status; + return ret; } /**************************************************************************** @@ -445,260 +755,532 @@ static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pe } /**************************************************************************** - Unlock a range of bytes. + Unlock a range of bytes - Windows semantics. ****************************************************************************/ -BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, - uint16 smbpid, struct process_id pid, uint16 tid, - br_off start, br_off size, - BOOL remove_pending_locks_only, - void (*pre_unlock_fn)(void *), - void *pre_unlock_data) +static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock_struct *plock) { - TDB_DATA kbuf, dbuf; - int count, i, j; - struct lock_struct *locks; - struct lock_context context; + unsigned int i, j; + struct lock_struct *lock = NULL; + struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; - kbuf = locking_key(dev,ino); +#if ZERO_ZERO + for (i = 0; i < br_lck->num_locks; i++) { + lock = &locks[i]; - dbuf.dptr = NULL; + if (lock->lock_type == WRITE_LOCK && + brl_same_context(&lock->context, &plock->context) && + lock->fnum == plock->fnum && + lock->lock_flav == WINDOWS_LOCK && + lock->start == plock->start && + lock->size == plock->size) { - tdb_chainlock(tdb, kbuf); - dbuf = tdb_fetch(tdb, kbuf); + /* found it - delete it */ + if (i < br_lck->num_locks - 1) { + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((br_lck->num_locks-1) - i)); + } - if (!dbuf.dptr) { - DEBUG(10,("brl_unlock: tdb_fetch failed !\n")); - goto fail; + br_lck->num_locks -= 1; + br_lck->modified = True; + return True; + } } +#endif - context.smbpid = smbpid; - context.pid = pid; - context.tid = tid; + for (i = 0; i < br_lck->num_locks; i++) { + lock = &locks[i]; - /* there are existing locks - find a match */ - locks = (struct lock_struct *)dbuf.dptr; - count = dbuf.dsize / sizeof(*locks); + /* Only remove our own locks that match in start, size, and flavour. */ + if (brl_same_context(&lock->context, &plock->context) && + lock->fnum == plock->fnum && + lock->lock_flav == WINDOWS_LOCK && + lock->start == plock->start && + lock->size == plock->size ) { + break; + } + } -#if ZERO_ZERO - for (i=0; inum_locks) { + /* we didn't find it */ + return False; + } - if (lock->lock_type == WRITE_LOCK && - brl_same_context(&lock->context, &context) && - lock->fnum == fnum && - lock->start == start && - lock->size == size) { + /* Unlock any POSIX regions. */ + if(lp_posix_locking(br_lck->fsp->conn->cnum)) { + release_posix_lock(br_lck->fsp, plock->start, plock->size); + } - if (pre_unlock_fn) - (*pre_unlock_fn)(pre_unlock_data); + /* Send unlock messages to any pending waiters that overlap. */ + for (j=0; j < br_lck->num_locks; j++) { + struct lock_struct *pend_lock = &locks[j]; - /* found it - delete it */ - if (count == 1) { - tdb_delete(tdb, kbuf); - } else { - if (i < count-1) { - memmove(&locks[i], &locks[i+1], - sizeof(*locks)*((count-1) - i)); - } - dbuf.dsize -= sizeof(*locks); - tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); - } + /* Ignore non-pending locks. */ + if (pend_lock->lock_type != PENDING_LOCK) { + continue; + } - SAFE_FREE(dbuf.dptr); - tdb_chainunlock(tdb, kbuf); - return True; + /* We could send specific lock info here... */ + if (brl_pending_overlap(lock, pend_lock)) { + DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", + procid_str_static(&pend_lock->context.pid ))); + + become_root(); + message_send_pid(pend_lock->context.pid, + MSG_SMB_UNLOCK, + NULL, 0, True); + unbecome_root(); } } -#endif - locks = (struct lock_struct *)dbuf.dptr; - count = dbuf.dsize / sizeof(*locks); - for (i=0; inum_locks - 1) { + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((br_lck->num_locks-1) - i)); + } - if (brl_same_context(&lock->context, &context) && - lock->fnum == fnum && - lock->start == start && - lock->size == size) { + br_lck->num_locks -= 1; + br_lck->modified = True; + return True; +} + +/**************************************************************************** + Unlock a range of bytes - POSIX semantics. +****************************************************************************/ - if (remove_pending_locks_only && lock->lock_type != PENDING_LOCK) - continue; +static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_struct *plock) +{ + unsigned int i, j, count; + struct lock_struct *lock = NULL; + struct lock_struct *tp; + struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + BOOL overlap_found = False; + + /* No zero-zero locks for POSIX. */ + if (plock->start == 0 && plock->size == 0) { + return False; + } - if (lock->lock_type != PENDING_LOCK) { + /* Don't allow 64-bit lock wrap. */ + if (plock->start + plock->size < plock->start || + plock->start + plock->size < plock->size) { + DEBUG(10,("brl_unlock_posix: lock wrap\n")); + return False; + } - /* Do any POSIX unlocks needed. */ - if (pre_unlock_fn) - (*pre_unlock_fn)(pre_unlock_data); + /* The worst case scenario here is we have to split an + existing POSIX lock range into two, so we need at most + 1 more entry. */ - /* Send unlock messages to any pending waiters that overlap. */ - for (j=0; jnum_locks + 1)); + if (!tp) { + DEBUG(10,("brl_unlock_posix: malloc fail\n")); + return False; + } - /* Ignore non-pending locks. */ - if (pend_lock->lock_type != PENDING_LOCK) - continue; + count = 0; + for (i = 0; i < br_lck->num_locks; i++) { + struct lock_struct tmp_lock[3]; + BOOL lock_was_added = False; + unsigned int tmp_count; - /* We could send specific lock info here... */ - if (brl_pending_overlap(lock, pend_lock)) { - DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", - procid_str_static(&pend_lock->context.pid ))); + lock = &locks[i]; - message_send_pid(pend_lock->context.pid, - MSG_SMB_UNLOCK, - NULL, 0, True); - } - } - } + /* Only remove our own locks - ignore fnum. */ + if (lock->lock_type == PENDING_LOCK || + !brl_same_context(&lock->context, &plock->context)) { + memcpy(&tp[count], lock, sizeof(struct lock_struct)); + count++; + continue; + } - /* found it - delete it */ - if (count == 1) { - tdb_delete(tdb, kbuf); + /* Work out overlaps. */ + tmp_count = brlock_posix_split_merge(&tmp_lock[0], &locks[i], plock, &lock_was_added); + + if (tmp_count == 1) { + /* Ether the locks didn't overlap, or the unlock completely + overlapped this lock. If it didn't overlap, then there's + no change in the locks. */ + if (tmp_lock[0].lock_type != UNLOCK_LOCK) { + SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type); + /* No change in this lock. */ + memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct)); + count++; } else { - if (i < count-1) { - memmove(&locks[i], &locks[i+1], - sizeof(*locks)*((count-1) - i)); - } - dbuf.dsize -= sizeof(*locks); - tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); + SMB_ASSERT(tmp_lock[0].lock_type == UNLOCK_LOCK); + overlap_found = True; } + continue; + } else if (tmp_count == 2) { + /* The unlock overlapped an existing lock. Copy the truncated + lock into the lock array. */ + if (tmp_lock[0].lock_type != UNLOCK_LOCK) { + SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type); + SMB_ASSERT(tmp_lock[1].lock_type == UNLOCK_LOCK); + memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct)); + } else { + SMB_ASSERT(tmp_lock[0].lock_type == UNLOCK_LOCK); + SMB_ASSERT(tmp_lock[1].lock_type == locks[i].lock_type); + memcpy(&tp[count], &tmp_lock[1], sizeof(struct lock_struct)); + } + count++; + overlap_found = True; + continue; + } else { + /* tmp_count == 3 - (we split a lock range in two). */ + SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type); + SMB_ASSERT(tmp_lock[1].lock_type == UNLOCK_LOCK); + SMB_ASSERT(tmp_lock[2].lock_type != locks[i].lock_type); + + memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct)); + count++; + memcpy(&tp[count], &tmp_lock[2], sizeof(struct lock_struct)); + count++; + overlap_found = True; + /* Optimisation... */ + /* We know we're finished here as we can't overlap any + more POSIX locks. Copy the rest of the lock array. */ + if (i < br_lck->num_locks - 1) { + memcpy(&tp[count], &locks[i+1], + sizeof(*locks)*((br_lck->num_locks-1) - i)); + count += ((br_lck->num_locks-1) - i); + } + break; + } + } - SAFE_FREE(dbuf.dptr); - tdb_chainunlock(tdb, kbuf); - return True; + if (!overlap_found) { + /* Just ignore - no change. */ + SAFE_FREE(tp); + DEBUG(10,("brl_unlock_posix: No overlap - unlocked.\n")); + return True; + } + +#if 0 + /* FIXME - this call doesn't work correctly yet for POSIX locks... */ + + /* Unlock any POSIX regions. */ + if(lp_posix_locking(br_lck->fsp->conn->cnum)) { + release_posix_lock(br_lck->fsp, plock->start, plock->size); + } +#endif + + /* Realloc so we don't leak entries per unlock call. */ + if (count) { + tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks)); + if (!tp) { + DEBUG(10,("brl_unlock_posix: realloc fail\n")); + return False; } + } else { + /* We deleted the last lock. */ + SAFE_FREE(tp); + tp = NULL; } - /* we didn't find it */ + br_lck->num_locks = count; + br_lck->lock_data = (void *)tp; + br_lck->modified = True; - fail: - SAFE_FREE(dbuf.dptr); - tdb_chainunlock(tdb, kbuf); - return False; -} + /* Send unlock messages to any pending waiters that overlap. */ + locks = tp; + for (j=0; j < br_lck->num_locks; j++) { + struct lock_struct *pend_lock = &locks[j]; + + /* Ignore non-pending locks. */ + if (pend_lock->lock_type != PENDING_LOCK) { + continue; + } + + /* We could send specific lock info here... */ + if (brl_pending_overlap(lock, pend_lock)) { + DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", + procid_str_static(&pend_lock->context.pid ))); + + become_root(); + message_send_pid(pend_lock->context.pid, + MSG_SMB_UNLOCK, + NULL, 0, True); + unbecome_root(); + } + } + + return True; +} /**************************************************************************** - Test if we could add a lock if we wanted to. + Unlock a range of bytes. ****************************************************************************/ -BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, - uint16 smbpid, struct process_id pid, uint16 tid, - br_off start, br_off size, - enum brl_type lock_type) +BOOL brl_unlock(struct byte_range_lock *br_lck, + uint16 smbpid, + struct process_id pid, + br_off start, + br_off size, + enum brl_flavour lock_flav) { - TDB_DATA kbuf, dbuf; - int count, i; - struct lock_struct lock, *locks; + struct lock_struct lock; - kbuf = locking_key(dev,ino); + lock.context.smbpid = smbpid; + lock.context.pid = pid; + lock.context.tid = br_lck->fsp->conn->cnum; + lock.start = start; + lock.size = size; + lock.fnum = br_lck->fsp->fnum; + lock.lock_type = UNLOCK_LOCK; + lock.lock_flav = lock_flav; + + if (lock_flav == WINDOWS_LOCK) { + return brl_unlock_windows(br_lck, &lock); + } else { + return brl_unlock_posix(br_lck, &lock); + } +} - dbuf.dptr = NULL; +/**************************************************************************** + Test if we could add a lock if we wanted to. + Returns True if the region required is currently unlocked, False if locked. +****************************************************************************/ - dbuf = tdb_fetch(tdb, kbuf); +BOOL brl_locktest(struct byte_range_lock *br_lck, + uint16 smbpid, + struct process_id pid, + br_off start, + br_off size, + enum brl_type lock_type, + enum brl_flavour lock_flav) +{ + BOOL ret = True; + unsigned int i; + struct lock_struct lock; + struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + files_struct *fsp = br_lck->fsp; lock.context.smbpid = smbpid; lock.context.pid = pid; - lock.context.tid = tid; + lock.context.tid = br_lck->fsp->conn->cnum; lock.start = start; lock.size = size; - lock.fnum = fnum; + lock.fnum = fsp->fnum; lock.lock_type = lock_type; - - if (dbuf.dptr) { - /* there are existing locks - make sure they don't conflict */ - locks = (struct lock_struct *)dbuf.dptr; - count = dbuf.dsize / sizeof(*locks); - for (i=0; inum_locks; i++) { + /* + * Our own locks don't conflict. + */ + if (brl_conflict_other(&locks[i], &lock)) { + return False; } } + /* + * There is no lock held by an SMB daemon, check to + * see if there is a POSIX lock from a UNIX or NFS process. + * This only conflicts with Windows locks, not POSIX locks. + */ + + if(lp_posix_locking(fsp->conn->cnum) && (lock_flav == WINDOWS_LOCK)) { + ret = is_posix_locked(fsp, &start, &size, &lock_type, WINDOWS_LOCK); + + DEBUG(10,("brl_locktest: posix start=%.0f len=%.0f %s for fnum %d file %s\n", + (double)start, (double)size, ret ? "locked" : "unlocked", + fsp->fnum, fsp->fsp_name )); + + /* We need to return the inverse of is_posix_locked. */ + ret = !ret; + } + /* no conflicts - we could have added it */ - SAFE_FREE(dbuf.dptr); - return True; + return ret; +} - fail: - SAFE_FREE(dbuf.dptr); - return False; +/**************************************************************************** + Query for existing locks. +****************************************************************************/ + +NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, + uint16 *psmbpid, + struct process_id pid, + br_off *pstart, + br_off *psize, + enum brl_type *plock_type, + enum brl_flavour lock_flav) +{ + unsigned int i; + struct lock_struct lock; + struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + files_struct *fsp = br_lck->fsp; + + lock.context.smbpid = *psmbpid; + lock.context.pid = pid; + lock.context.tid = br_lck->fsp->conn->cnum; + lock.start = *pstart; + lock.size = *psize; + lock.fnum = fsp->fnum; + lock.lock_type = *plock_type; + lock.lock_flav = lock_flav; + + /* Make sure existing locks don't conflict */ + for (i=0; i < br_lck->num_locks; i++) { + struct lock_struct *exlock = &locks[i]; + BOOL conflict = False; + + if (exlock->lock_flav == WINDOWS_LOCK) { + conflict = brl_conflict(exlock, &lock); + } else { + conflict = brl_conflict_posix(exlock, &lock); + } + + if (conflict) { + *psmbpid = exlock->context.smbpid; + *pstart = exlock->start; + *psize = exlock->size; + *plock_type = exlock->lock_type; + return NT_STATUS_LOCK_NOT_GRANTED; + } + } + + /* + * There is no lock held by an SMB daemon, check to + * see if there is a POSIX lock from a UNIX or NFS process. + */ + + if(lp_posix_locking(fsp->conn->cnum)) { + BOOL ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK); + + DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for fnum %d file %s\n", + (double)*pstart, (double)*psize, ret ? "locked" : "unlocked", + fsp->fnum, fsp->fsp_name )); + + if (ret) { + /* Hmmm. No clue what to set smbpid to - use -1. */ + *psmbpid = 0xFFFF; + return NT_STATUS_LOCK_NOT_GRANTED; + } + } + + return NT_STATUS_OK; } + /**************************************************************************** - Remove any locks associated with a open file. + Remove a particular pending lock. ****************************************************************************/ -void brl_close(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, int tid, int fnum) +BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck, + uint16 smbpid, + struct process_id pid, + br_off start, + br_off size, + enum brl_flavour lock_flav) { - TDB_DATA kbuf, dbuf; - int count, i, j, dcount=0; - struct lock_struct *locks; + unsigned int i; + struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct lock_context context; + + context.smbpid = smbpid; + context.pid = pid; + context.tid = br_lck->fsp->conn->cnum; + + for (i = 0; i < br_lck->num_locks; i++) { + struct lock_struct *lock = &locks[i]; + + /* For pending locks we *always* care about the fnum. */ + if (brl_same_context(&lock->context, &context) && + lock->fnum == br_lck->fsp->fnum && + lock->lock_type == PENDING_LOCK && + lock->lock_flav == lock_flav && + lock->start == start && + lock->size == size) { + break; + } + } - kbuf = locking_key(dev,ino); + if (i == br_lck->num_locks) { + /* Didn't find it. */ + return False; + } - dbuf.dptr = NULL; + if (i < br_lck->num_locks - 1) { + /* Found this particular pending lock - delete it */ + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((br_lck->num_locks-1) - i)); + } - tdb_chainlock(tdb, kbuf); - dbuf = tdb_fetch(tdb, kbuf); + br_lck->num_locks -= 1; + br_lck->modified = True; + return True; +} - if (!dbuf.dptr) goto fail; - /* there are existing locks - remove any for this fnum */ - locks = (struct lock_struct *)dbuf.dptr; - count = dbuf.dsize / sizeof(*locks); +/**************************************************************************** + Remove any locks associated with a open file. +****************************************************************************/ + +void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid) +{ + files_struct *fsp = br_lck->fsp; + uint16 tid = fsp->conn->cnum; + int fnum = fsp->fnum; + unsigned int i, j, dcount=0; + struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + + /* Remove any existing locks for this fnum (or any fnum if they're POSIX). */ - for (i=0; inum_locks; i++) { struct lock_struct *lock = &locks[i]; + BOOL del_this_lock = False; - if (lock->context.tid == tid && - procid_equal(&lock->context.pid, &pid) && - lock->fnum == fnum) { + if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid)) { + if ((lock->lock_flav == WINDOWS_LOCK) && (lock->fnum == fnum)) { + del_this_lock = True; + } else if (lock->lock_flav == POSIX_LOCK) { + del_this_lock = True; + } + } + if (del_this_lock) { /* Send unlock messages to any pending waiters that overlap. */ - for (j=0; jnum_locks; j++) { struct lock_struct *pend_lock = &locks[j]; /* Ignore our own or non-pending locks. */ - if (pend_lock->lock_type != PENDING_LOCK) + if (pend_lock->lock_type != PENDING_LOCK) { continue; + } + /* Optimisation - don't send to this fnum as we're + closing it. */ if (pend_lock->context.tid == tid && procid_equal(&pend_lock->context.pid, &pid) && - pend_lock->fnum == fnum) + pend_lock->fnum == fnum) { continue; + } /* We could send specific lock info here... */ - if (brl_pending_overlap(lock, pend_lock)) + if (brl_pending_overlap(lock, pend_lock)) { + become_root(); message_send_pid(pend_lock->context.pid, MSG_SMB_UNLOCK, NULL, 0, True); + unbecome_root(); + } } /* found it - delete it */ - if (count > 1 && i < count-1) { + if (br_lck->num_locks > 1 && i < br_lck->num_locks - 1) { memmove(&locks[i], &locks[i+1], - sizeof(*locks)*((count-1) - i)); + sizeof(*locks)*((br_lck->num_locks-1) - i)); } - count--; + br_lck->num_locks--; + br_lck->modified = True; i--; dcount++; } } - - if (count == 0) { - tdb_delete(tdb, kbuf); - } else if (count < (dbuf.dsize / sizeof(*locks))) { - dbuf.dsize -= dcount * sizeof(*locks); - tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); - } - - /* we didn't find it */ - fail: - SAFE_FREE(dbuf.dptr); - tdb_chainunlock(tdb, kbuf); } /**************************************************************************** @@ -718,9 +1300,11 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st key = (struct lock_key *)kbuf.dptr; for (i=0;idevice, key->inode, + traverse_callback(key->device, + key->inode, locks[i].context.pid, locks[i].lock_type, + locks[i].lock_flav, locks[i].start, locks[i].size); } @@ -733,6 +1317,92 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st int brl_forall(BRLOCK_FN(fn)) { - if (!tdb) return 0; + if (!tdb) { + return 0; + } return tdb_traverse(tdb, traverse_fn, (void *)fn); } + +/******************************************************************* + Store a potentially modified set of byte range lock data back into + the database. + Unlock the record. +********************************************************************/ + +static int byte_range_lock_destructor(void *p) +{ + struct byte_range_lock *br_lck = + talloc_get_type_abort(p, struct byte_range_lock); + TDB_DATA key = locking_key(br_lck->fsp->dev, br_lck->fsp->inode); + + if (!br_lck->modified) { + goto done; + } + + if (br_lck->num_locks == 0) { + /* No locks - delete this entry. */ + if (tdb_delete(tdb, key) == -1) { + smb_panic("Could not delete byte range lock entry\n"); + } + } else { + TDB_DATA data; + data.dptr = br_lck->lock_data; + data.dsize = br_lck->num_locks * sizeof(struct lock_struct); + + if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) { + smb_panic("Could not store byte range mode entry\n"); + } + } + + done: + + SAFE_FREE(br_lck->lock_data); + tdb_chainunlock(tdb, key); + return 0; +} + +/******************************************************************* + Fetch a set of byte range lock data from the database. + Leave the record locked. +********************************************************************/ + +struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, + files_struct *fsp) +{ + TDB_DATA key = locking_key(fsp->dev, fsp->inode); + TDB_DATA data; + struct byte_range_lock *br_lck; + + br_lck = TALLOC_P(mem_ctx, struct byte_range_lock); + if (br_lck == NULL) { + return NULL; + } + + br_lck->fsp = fsp; + br_lck->num_locks = 0; + br_lck->modified = False; + + if (tdb_chainlock(tdb, key) != 0) { + DEBUG(3, ("Could not lock byte range lock entry\n")); + TALLOC_FREE(br_lck); + return NULL; + } + + talloc_set_destructor(br_lck, byte_range_lock_destructor); + + data = tdb_fetch(tdb, key); + br_lck->lock_data = (void *)data.dptr; + br_lck->num_locks = data.dsize / sizeof(struct lock_struct); + + if (DEBUGLEVEL >= 10) { + unsigned int i; + struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + DEBUG(10,("brl_get_locks: %u current locks on dev=%.0f, inode=%.0f\n", + br_lck->num_locks, + (double)fsp->dev, (double)fsp->inode )); + for( i = 0; i < br_lck->num_locks; i++) { + print_lock_struct(i, &locks[i]); + } + } + return br_lck; +} diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 0ecc90c794..0b3f625d03 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. Locking functions Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 1992-2000 + Copyright (C) Jeremy Allison 1992-2006 Copyright (C) Volker Lendecke 2005 This program is free software; you can redistribute it and/or modify @@ -33,6 +33,7 @@ rewrtten completely to use new tdb code. Tridge, Dec '99 Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000. + Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006. */ #include "includes.h" @@ -45,120 +46,179 @@ uint16 global_smbpid; static TDB_CONTEXT *tdb; /**************************************************************************** - Debugging aid :-). + Debugging aids :-). ****************************************************************************/ -static const char *lock_type_name(enum brl_type lock_type) +const char *lock_type_name(enum brl_type lock_type) { - return (lock_type == READ_LOCK) ? "READ" : "WRITE"; + switch (lock_type) { + case READ_LOCK: + return "READ"; + case WRITE_LOCK: + return "WRITE"; + case PENDING_LOCK: + return "PENDING"; + default: + return "other"; + } +} + +const char *lock_flav_name(enum brl_flavour lock_flav) +{ + return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK"; } /**************************************************************************** Utility function called to see if a file region is locked. + Called in the read/write codepath. ****************************************************************************/ -BOOL is_locked(files_struct *fsp,connection_struct *conn, - SMB_BIG_UINT count,SMB_BIG_UINT offset, - enum brl_type lock_type) +BOOL is_locked(files_struct *fsp, + SMB_BIG_UINT count, + SMB_BIG_UINT offset, + enum brl_type lock_type) { - int snum = SNUM(conn); + int snum = SNUM(fsp->conn); int strict_locking = lp_strict_locking(snum); - BOOL ret; + enum brl_flavour lock_flav = lp_posix_cifsu_locktype(); + BOOL ret = True; - if (count == 0) - return(False); + if (count == 0) { + return False; + } - if (!lp_locking(snum) || !strict_locking) - return(False); + if (!lp_locking(snum) || !strict_locking) { + return False; + } if (strict_locking == Auto) { if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) { DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name )); - ret = 0; + ret = False; } else if ((fsp->oplock_type == LEVEL_II_OPLOCK) && (lock_type == READ_LOCK)) { DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); - ret = 0; + ret = False; } else { - ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, procid_self(), conn->cnum, - offset, count, lock_type); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + if (!br_lck) { + return False; + } + ret = !brl_locktest(br_lck, + global_smbpid, + procid_self(), + offset, + count, + lock_type, + lock_flav); + TALLOC_FREE(br_lck); } } else { - ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, procid_self(), conn->cnum, - offset, count, lock_type); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + if (!br_lck) { + return False; + } + ret = !brl_locktest(br_lck, + global_smbpid, + procid_self(), + offset, + count, + lock_type, + lock_flav); + TALLOC_FREE(br_lck); } - DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n", + DEBUG(10,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n", + lock_flav_name(lock_flav), (double)offset, (double)count, ret ? "locked" : "unlocked", - fsp->fsp_name )); + fsp->fnum, fsp->fsp_name )); - /* - * There is no lock held by an SMB daemon, check to - * see if there is a POSIX lock from a UNIX or NFS process. - */ + return ret; +} - if(!ret && lp_posix_locking(snum)) { - ret = is_posix_locked(fsp, offset, count, lock_type); +/**************************************************************************** + Find out if a lock could be granted - return who is blocking us if we can't. +****************************************************************************/ + +NTSTATUS query_lock(files_struct *fsp, + uint16 *psmbpid, + SMB_BIG_UINT *pcount, + SMB_BIG_UINT *poffset, + enum brl_type *plock_type, + enum brl_flavour lock_flav) +{ + struct byte_range_lock *br_lck = NULL; + NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED; - DEBUG(10,("is_locked: posix start=%.0f len=%.0f %s for file %s\n", - (double)offset, (double)count, ret ? "locked" : "unlocked", - fsp->fsp_name )); + if (!OPEN_FSP(fsp) || !fsp->can_lock) { + return NT_STATUS_INVALID_HANDLE; } - return ret; + if (!lp_locking(SNUM(fsp->conn))) { + return NT_STATUS_OK; + } + + br_lck = brl_get_locks(NULL, fsp); + if (!br_lck) { + return NT_STATUS_NO_MEMORY; + } + + status = brl_lockquery(br_lck, + psmbpid, + procid_self(), + poffset, + pcount, + plock_type, + lock_flav); + + TALLOC_FREE(br_lck); + return status; } /**************************************************************************** Utility function called by locking requests. ****************************************************************************/ -static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, - SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx) +NTSTATUS do_lock(files_struct *fsp, + uint16 lock_pid, + SMB_BIG_UINT count, + SMB_BIG_UINT offset, + enum brl_type lock_type, + enum brl_flavour lock_flav, + BOOL *my_lock_ctx) { + struct byte_range_lock *br_lck = NULL; NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED; - if (!lp_locking(SNUM(conn))) + if (!OPEN_FSP(fsp) || !fsp->can_lock) { + return NT_STATUS_INVALID_HANDLE; + } + + if (!lp_locking(SNUM(fsp->conn))) { return NT_STATUS_OK; + } /* NOTE! 0 byte long ranges ARE allowed and should be stored */ - DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n", - lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name )); - - if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - status = brl_lock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, procid_self(), conn->cnum, - offset, count, - lock_type, my_lock_ctx); - - if (NT_STATUS_IS_OK(status) && lp_posix_locking(SNUM(conn))) { - - /* - * Try and get a POSIX lock on this range. - * Note that this is ok if it is a read lock - * overlapping on a different fd. JRA. - */ - - if (!set_posix_lock(fsp, offset, count, lock_type)) { - if (errno == EACCES || errno == EAGAIN) - status = NT_STATUS_FILE_LOCK_CONFLICT; - else - status = map_nt_error_from_unix(errno); - - /* - * We failed to map - we must now remove the brl - * lock entry. - */ - (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, procid_self(), conn->cnum, - offset, count, False, - NULL, NULL); - } - } + DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f requested for fnum %d file %s\n", + lock_flav_name(lock_flav), lock_type_name(lock_type), + (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); + + br_lck = brl_get_locks(NULL, fsp); + if (!br_lck) { + return NT_STATUS_NO_MEMORY; } + status = brl_lock(br_lck, + lock_pid, + procid_self(), + offset, + count, + lock_type, + lock_flav, + my_lock_ctx); + + TALLOC_FREE(br_lck); return status; } @@ -169,20 +229,33 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p it, we need this. JRA. ****************************************************************************/ -NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid, - SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx) +NTSTATUS do_lock_spin(files_struct *fsp, + uint16 lock_pid, + SMB_BIG_UINT count, + SMB_BIG_UINT offset, + enum brl_type lock_type, + enum brl_flavour lock_flav, + BOOL *my_lock_ctx) { int j, maxj = lp_lock_spin_count(); int sleeptime = lp_lock_sleep_time(); NTSTATUS status, ret; - if (maxj <= 0) + if (maxj <= 0) { maxj = 1; + } ret = NT_STATUS_OK; /* to keep dumb compilers happy */ for (j = 0; j < maxj; j++) { - status = do_lock(fsp, conn, lock_pid, count, offset, lock_type, my_lock_ctx); + status = do_lock(fsp, + lock_pid, + count, + offset, + lock_type, + lock_flav, + my_lock_ctx); + if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { return status; @@ -191,72 +264,66 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid if (j == 0) { ret = status; /* Don't spin if we blocked ourselves. */ - if (*my_lock_ctx) + if (*my_lock_ctx) { return ret; + } + + /* Only spin for Windows locks. */ + if (lock_flav == POSIX_LOCK) { + return ret; + } } - if (sleeptime) + + if (sleeptime) { sys_usleep(sleeptime); + } } return ret; } -/* Struct passed to brl_unlock. */ -struct posix_unlock_data_struct { - files_struct *fsp; - SMB_BIG_UINT offset; - SMB_BIG_UINT count; -}; - -/**************************************************************************** - Function passed to brl_unlock to allow POSIX unlock to be done first. -****************************************************************************/ - -static void posix_unlock(void *pre_data) -{ - struct posix_unlock_data_struct *pdata = (struct posix_unlock_data_struct *)pre_data; - - if (lp_posix_locking(SNUM(pdata->fsp->conn))) - release_posix_lock(pdata->fsp, pdata->offset, pdata->count); -} - /**************************************************************************** Utility function called by unlocking requests. ****************************************************************************/ -NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, - SMB_BIG_UINT count,SMB_BIG_UINT offset) +NTSTATUS do_unlock(files_struct *fsp, + uint16 lock_pid, + SMB_BIG_UINT count, + SMB_BIG_UINT offset, + enum brl_flavour lock_flav) { BOOL ok = False; - struct posix_unlock_data_struct posix_data; + struct byte_range_lock *br_lck = NULL; - if (!lp_locking(SNUM(conn))) + if (!lp_locking(SNUM(fsp->conn))) { return NT_STATUS_OK; + } - if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) { + if (!OPEN_FSP(fsp) || !fsp->can_lock) { return NT_STATUS_INVALID_HANDLE; } - DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", - (double)offset, (double)count, fsp->fsp_name )); + DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n", + (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - /* - * Remove the existing lock record from the tdb lockdb - * before looking at POSIX locks. If this record doesn't - * match then don't bother looking to remove POSIX locks. - */ - - posix_data.fsp = fsp; - posix_data.offset = offset; - posix_data.count = count; + br_lck = brl_get_locks(NULL, fsp); + if (!br_lck) { + return NT_STATUS_NO_MEMORY; + } - ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, procid_self(), conn->cnum, offset, count, - False, posix_unlock, (void *)&posix_data); + ok = brl_unlock(br_lck, + lock_pid, + procid_self(), + offset, + count, + lock_flav); + TALLOC_FREE(br_lck); + if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); return NT_STATUS_RANGE_NOT_LOCKED; } + return NT_STATUS_OK; } @@ -266,6 +333,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, void locking_close_file(files_struct *fsp) { + struct byte_range_lock *br_lck; struct process_id pid = procid_self(); if (!lp_locking(SNUM(fsp->conn))) @@ -275,13 +343,14 @@ void locking_close_file(files_struct *fsp) * Just release all the brl locks, no need to release individually. */ - brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); + br_lck = brl_get_locks(NULL,fsp); + if (br_lck) { + brl_close_fnum(br_lck, pid); + TALLOC_FREE(br_lck); + } if(lp_posix_locking(SNUM(fsp->conn))) { - - /* - * Release all the POSIX locks. - */ + /* Release all the POSIX locks.*/ posix_locking_close_file(fsp); } diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 07246474f3..e7075c57a6 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -644,8 +644,7 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, /**************************************************************************** Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and - broken NFS implementations. Returns True if we got the lock or the region - is unlocked in the F_GETLK case, False otherwise. + broken NFS implementations. ****************************************************************************/ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) @@ -654,9 +653,6 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type)); - /* In the F_GETLK case this returns True if the region - was locked, False if unlocked. */ - ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { @@ -686,39 +682,97 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF } DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed")); + return ret; +} + +/**************************************************************************** + Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and + broken NFS implementations. +****************************************************************************/ +static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype) +{ + pid_t pid; + BOOL ret; + + DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n", + fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype)); + + ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); + + if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { + + DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n", + (double)*poffset,(double)*pcount)); + DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); + DEBUG(0,("on 32 bit NFS mounted file systems.\n")); + + /* + * If the offset is > 0x7FFFFFFF then this will cause problems on + * 32 bit NFS mounted filesystems. Just ignore it. + */ + + if (*poffset & ~((SMB_OFF_T)0x7fffffff)) { + DEBUG(0,("Offset greater than 31 bits. Returning success.\n")); + return True; + } + + if (*pcount & ~((SMB_OFF_T)0x7fffffff)) { + /* 32 bit NFS file system, retry with smaller offset */ + DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); + errno = 0; + *pcount &= 0x7fffffff; + ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); + } + } + + DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed")); return ret; } + /**************************************************************************** POSIX function to see if a file region is locked. Returns True if the region is locked, False otherwise. ****************************************************************************/ -BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) +BOOL is_posix_locked(files_struct *fsp, + SMB_BIG_UINT *pu_offset, + SMB_BIG_UINT *pu_count, + enum brl_type *plock_type, + enum brl_flavour lock_flav) { SMB_OFF_T offset; SMB_OFF_T count; - int posix_lock_type = map_posix_lock_type(fsp,lock_type); + int posix_lock_type = map_posix_lock_type(fsp,*plock_type); DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); + fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) )); /* * If the requested lock won't fit in the POSIX range, we will * never set it, so presume it is not locked. */ - if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) + if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) { return False; + } - /* - * Note that most UNIX's can *test* for a write lock on - * a read-only fd, just not *set* a write lock on a read-only - * fd. So we don't need to use map_lock_type here. - */ + if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) { + return False; + } - return posix_fcntl_lock(fsp,SMB_F_GETLK,offset,count,posix_lock_type); + if (posix_lock_type == F_UNLCK) { + return False; + } + + if (lock_flav == POSIX_LOCK) { + /* Only POSIX lock queries need to know the details. */ + *pu_offset = (SMB_BIG_UINT)offset; + *pu_count = (SMB_BIG_UINT)count; + *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK; + } + return True; } /* @@ -958,9 +1012,14 @@ lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size, /**************************************************************************** POSIX function to acquire a lock. Returns True if the lock could be granted, False if not. + TODO -- Fix POSIX lock flavour semantics. ****************************************************************************/ -BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type) +BOOL set_posix_lock(files_struct *fsp, + SMB_BIG_UINT u_offset, + SMB_BIG_UINT u_count, + enum brl_type lock_type, + enum brl_flavour lock_flav) { SMB_OFF_T offset; SMB_OFF_T count; -- cgit From 423352b90e5e3bb89db96ae43798db395ef818ee Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Apr 2006 23:29:47 +0000 Subject: r15026: Fix warning until POSIX locking finished. Jeremy. (This used to be commit 15f39a4c720e9645f941742310b6c6d7d7fc96d5) --- source3/locking/brlock.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index b95bb895cc..5d64e66448 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -601,7 +601,6 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, unsigned int i, count; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; struct lock_struct *tp; - files_struct *fsp = br_lck->fsp; BOOL lock_was_added = False; /* No zero-zero locks for POSIX. */ @@ -664,7 +663,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, /* FIXME - this call doesn't work correctly yet for POSIX locks... */ if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) { - + files_struct *fsp = br_lck->fsp; if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, POSIX_LOCK)) { if (errno == EACCES || errno == EAGAIN) { -- cgit From fdd55885da4e3270c9bb5c4a682c1cd980a6040a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Apr 2006 23:00:58 +0000 Subject: r15060: The brlock code gets called a lot. Ensure we keep the key around while we're using it - saves many calls to locking_key() (now deleted). Jeremy. (This used to be commit 2f8b527dcf4a36fbb933ce79c720c0425de76b4a) --- source3/locking/brlock.c | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 5d64e66448..60c94c2b98 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -55,13 +55,6 @@ struct lock_struct { enum brl_flavour lock_flav; }; -/* The key used in the brlock database. */ - -struct lock_key { - SMB_DEV_T device; - SMB_INO_T inode; -}; - /* The open brlock.tdb database. */ static TDB_CONTEXT *tdb; @@ -86,23 +79,6 @@ static void print_lock_struct(unsigned int i, struct lock_struct *pls) lock_flav_name(pls->lock_flav) )); } -/**************************************************************************** - Create a locking key - ensuring zero filled for pad purposes. -****************************************************************************/ - -static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) -{ - static struct lock_key key; - TDB_DATA kbuf; - - memset(&key, '\0', sizeof(key)); - key.device = dev; - key.inode = inode; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); - return kbuf; -} - /**************************************************************************** See if two locking contexts are equal. ****************************************************************************/ @@ -1332,7 +1308,10 @@ static int byte_range_lock_destructor(void *p) { struct byte_range_lock *br_lck = talloc_get_type_abort(p, struct byte_range_lock); - TDB_DATA key = locking_key(br_lck->fsp->dev, br_lck->fsp->inode); + TDB_DATA key; + + key.dptr = (char *)&br_lck->key; + key.dsize = sizeof(struct lock_key); if (!br_lck->modified) { goto done; @@ -1355,8 +1334,8 @@ static int byte_range_lock_destructor(void *p) done: - SAFE_FREE(br_lck->lock_data); tdb_chainunlock(tdb, key); + SAFE_FREE(br_lck->lock_data); return 0; } @@ -1368,11 +1347,10 @@ static int byte_range_lock_destructor(void *p) struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp) { - TDB_DATA key = locking_key(fsp->dev, fsp->inode); + TDB_DATA key; TDB_DATA data; - struct byte_range_lock *br_lck; + struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock); - br_lck = TALLOC_P(mem_ctx, struct byte_range_lock); if (br_lck == NULL) { return NULL; } @@ -1380,6 +1358,12 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, br_lck->fsp = fsp; br_lck->num_locks = 0; br_lck->modified = False; + memset(&br_lck->key, '\0', sizeof(struct lock_key)); + br_lck->key.device = fsp->dev; + br_lck->key.inode = fsp->inode; + + key.dptr = (char *)&br_lck->key; + key.dsize = sizeof(struct lock_key); if (tdb_chainlock(tdb, key) != 0) { DEBUG(3, ("Could not lock byte range lock entry\n")); -- cgit From 713eaf1d67d9ef967fb4526113e2a3ba3dd5e229 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Apr 2006 22:22:54 +0000 Subject: r15083: Using talloc with destructors is nice and all, but in this case it's in a performace critical path and it *hurts* us. Go back to plain malloc/free with an explicit destructor call. Jeremy. (This used to be commit 1c99aed563c29e1b3d70939878af747a0660bfec) --- source3/locking/brlock.c | 14 +++++--------- source3/locking/locking.c | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 21 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 60c94c2b98..e6f0dd1c72 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1304,10 +1304,8 @@ int brl_forall(BRLOCK_FN(fn)) Unlock the record. ********************************************************************/ -static int byte_range_lock_destructor(void *p) +int byte_range_lock_destructor(struct byte_range_lock *br_lck) { - struct byte_range_lock *br_lck = - talloc_get_type_abort(p, struct byte_range_lock); TDB_DATA key; key.dptr = (char *)&br_lck->key; @@ -1336,6 +1334,7 @@ static int byte_range_lock_destructor(void *p) tdb_chainunlock(tdb, key); SAFE_FREE(br_lck->lock_data); + SAFE_FREE(br_lck); return 0; } @@ -1344,12 +1343,11 @@ static int byte_range_lock_destructor(void *p) Leave the record locked. ********************************************************************/ -struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, - files_struct *fsp) +struct byte_range_lock *brl_get_locks(files_struct *fsp) { TDB_DATA key; TDB_DATA data; - struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock); + struct byte_range_lock *br_lck = SMB_MALLOC_P(struct byte_range_lock); if (br_lck == NULL) { return NULL; @@ -1367,12 +1365,10 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, if (tdb_chainlock(tdb, key) != 0) { DEBUG(3, ("Could not lock byte range lock entry\n")); - TALLOC_FREE(br_lck); + SAFE_FREE(br_lck); return NULL; } - talloc_set_destructor(br_lck, byte_range_lock_destructor); - data = tdb_fetch(tdb, key); br_lck->lock_data = (void *)data.dptr; br_lck->num_locks = data.dsize / sizeof(struct lock_struct); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 0b3f625d03..2b6023c0c4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -100,7 +100,7 @@ BOOL is_locked(files_struct *fsp, DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); ret = False; } else { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(fsp); if (!br_lck) { return False; } @@ -111,10 +111,10 @@ BOOL is_locked(files_struct *fsp, count, lock_type, lock_flav); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); } } else { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(fsp); if (!br_lck) { return False; } @@ -125,7 +125,7 @@ BOOL is_locked(files_struct *fsp, count, lock_type, lock_flav); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); } DEBUG(10,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n", @@ -158,7 +158,7 @@ NTSTATUS query_lock(files_struct *fsp, return NT_STATUS_OK; } - br_lck = brl_get_locks(NULL, fsp); + br_lck = brl_get_locks(fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -171,7 +171,7 @@ NTSTATUS query_lock(files_struct *fsp, plock_type, lock_flav); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); return status; } @@ -204,7 +204,7 @@ NTSTATUS do_lock(files_struct *fsp, lock_flav_name(lock_flav), lock_type_name(lock_type), (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - br_lck = brl_get_locks(NULL, fsp); + br_lck = brl_get_locks(fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -218,7 +218,7 @@ NTSTATUS do_lock(files_struct *fsp, lock_flav, my_lock_ctx); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); return status; } @@ -305,7 +305,7 @@ NTSTATUS do_unlock(files_struct *fsp, DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n", (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - br_lck = brl_get_locks(NULL, fsp); + br_lck = brl_get_locks(fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -317,7 +317,7 @@ NTSTATUS do_unlock(files_struct *fsp, count, lock_flav); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); @@ -343,10 +343,10 @@ void locking_close_file(files_struct *fsp) * Just release all the brl locks, no need to release individually. */ - br_lck = brl_get_locks(NULL,fsp); + br_lck = brl_get_locks(fsp); if (br_lck) { brl_close_fnum(br_lck, pid); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); } if(lp_posix_locking(SNUM(fsp->conn))) { -- cgit From f353704bbf6240d0c402fc4166119a5016eb640c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 25 Apr 2006 21:36:35 +0000 Subject: r15255: Add return statement after abort to placate fussy compilers. Closes #3721. (This used to be commit ab5a55ec8b27146fccba97f320d649bb19bc6f11) --- source3/locking/brlock.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index e6f0dd1c72..0b7aeb1c00 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -563,6 +563,8 @@ OR smb_panic("brlock_posix_split_merge\n"); /* Notreached. */ abort(); + /* Keep some compilers happy. */ + return 0; } /**************************************************************************** -- cgit From f93da6d684312994a10827b36de7a72c7288ed7e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Apr 2006 11:02:46 +0000 Subject: r15269: Fix incorrect boolean in assert to make POSIX lock tests pass with CIFSFS. Jeremy. (This used to be commit 89b604285ebe77b7cc2e0d5593117c0c5dc5ed1c) --- source3/locking/brlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 0b7aeb1c00..0233d60df6 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -907,7 +907,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s /* tmp_count == 3 - (we split a lock range in two). */ SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type); SMB_ASSERT(tmp_lock[1].lock_type == UNLOCK_LOCK); - SMB_ASSERT(tmp_lock[2].lock_type != locks[i].lock_type); + SMB_ASSERT(tmp_lock[2].lock_type == locks[i].lock_type); memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct)); count++; -- cgit From 6eb1187765b617128c3e698d02127f2690779580 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 May 2006 02:14:09 +0000 Subject: r15402: Fix for bug #3587. Dead entries can be left in the locking db. Make this db self-cleaning on first read of entry after open, and also on smbstatus -b call. Needs more testing when I get back from Boston but passes valgrind at first look. Jeremy. (This used to be commit c66531096325848d1476054df5d53ad05c2ffc83) --- source3/locking/brlock.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 0233d60df6..b9d401cad6 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1269,13 +1269,62 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st { struct lock_struct *locks; struct lock_key *key; - int i; + unsigned int i; + unsigned int num_locks = 0; + unsigned int num_valid_entries = 0; BRLOCK_FN(traverse_callback) = (BRLOCK_FN_CAST())state; locks = (struct lock_struct *)dbuf.dptr; key = (struct lock_key *)kbuf.dptr; + num_locks = dbuf.dsize/sizeof(*locks); + + /* Ensure the lock db is clean of invalid processes. */ + + for (i = 0; i < num_locks; i++) { + struct lock_struct *lock_data = &locks[i]; + if (!process_exists(lock_data->context.pid)) { + /* This process no longer exists - mark this + entry as invalid by zeroing it. */ + ZERO_STRUCTP(lock_data); + } else { + num_valid_entries++; + } + } + + if (num_valid_entries != num_locks) { + struct lock_struct *new_lock_data = NULL; + + if (num_valid_entries) { + new_lock_data = SMB_MALLOC_ARRAY(struct lock_struct, num_valid_entries); + if (!new_lock_data) { + DEBUG(3, ("malloc fail\n")); + return 0; + } + num_valid_entries = 0; + for (i = 0; i < num_locks; i++) { + struct lock_struct *lock_data = &locks[i]; + if (lock_data->context.smbpid && + lock_data->context.tid) { + /* Valid (nonzero) entry - copy it. */ + memcpy(&new_lock_data[num_valid_entries], + lock_data, sizeof(struct lock_struct)); + num_valid_entries++; + } + } + } + SAFE_FREE(dbuf.dptr); + dbuf.dptr = (void *)new_lock_data; + dbuf.dsize = (num_valid_entries) * sizeof(*locks); + + if (dbuf.dsize) { + tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE); + } else { + tdb_delete(ttdb, kbuf); + } + } + for (i=0;idevice, key->inode, @@ -1375,6 +1424,58 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp) br_lck->lock_data = (void *)data.dptr; br_lck->num_locks = data.dsize / sizeof(struct lock_struct); + if (!fsp->lockdb_clean) { + + /* This is the first time we've accessed this. */ + /* Go through and ensure all entries exist - remove any that don't. */ + /* Makes the lockdb self cleaning at low cost. */ + unsigned int num_valid_entries = 0; + unsigned int i; + + for (i = 0; i < br_lck->num_locks; i++) { + struct lock_struct *lock_data = &((struct lock_struct *)br_lck->lock_data)[i]; + if (!process_exists(lock_data->context.pid)) { + /* This process no longer exists - mark this + entry as invalid by zeroing it. */ + ZERO_STRUCTP(lock_data); + } else { + num_valid_entries++; + } + } + + if (num_valid_entries != br_lck->num_locks) { + struct lock_struct *new_lock_data = NULL; + + if (num_valid_entries) { + new_lock_data = SMB_MALLOC_ARRAY(struct lock_struct, num_valid_entries); + if (!new_lock_data) { + DEBUG(3, ("malloc fail\n")); + tdb_chainunlock(tdb, key); + SAFE_FREE(br_lck->lock_data); + SAFE_FREE(br_lck); + return NULL; + } + num_valid_entries = 0; + for (i = 0; i < br_lck->num_locks; i++) { + struct lock_struct *lock_data = &((struct lock_struct *)br_lck->lock_data)[i]; + if (lock_data->context.smbpid && + lock_data->context.tid) { + /* Valid (nonzero) entry - copy it. */ + memcpy(&new_lock_data[num_valid_entries], + lock_data, sizeof(struct lock_struct)); + num_valid_entries++; + } + } + } + SAFE_FREE(br_lck->lock_data); + br_lck->lock_data = (void *)new_lock_data; + br_lck->num_locks = num_valid_entries; + } + + /* Mark the lockdb as "clean" as seen from this open file. */ + fsp->lockdb_clean = True; + } + if (DEBUGLEVEL >= 10) { unsigned int i; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; -- cgit From fca8766ee18b812e95203810b6a2a5b6c9de5f30 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 May 2006 16:07:21 +0000 Subject: r15419: Never write the same function twice :-). In a traversal function we must copy the data before modifying. Jeremy. (This used to be commit ef4c70f58edf15dc93b22f2c80e15113ee2a46df) --- source3/locking/brlock.c | 122 +++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 62 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index b9d401cad6..574552e9e2 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1261,28 +1261,16 @@ void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid) } /**************************************************************************** - Traverse the whole database with this function, calling traverse_callback - on each lock. + Ensure this set of lock entries is valid. ****************************************************************************/ -static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +static BOOL validate_lock_entries(unsigned int *pnum_entries, struct lock_struct **pplocks) { - struct lock_struct *locks; - struct lock_key *key; unsigned int i; - unsigned int num_locks = 0; unsigned int num_valid_entries = 0; + struct lock_struct *locks = *pplocks; - BRLOCK_FN(traverse_callback) = (BRLOCK_FN_CAST())state; - - locks = (struct lock_struct *)dbuf.dptr; - key = (struct lock_key *)kbuf.dptr; - - num_locks = dbuf.dsize/sizeof(*locks); - - /* Ensure the lock db is clean of invalid processes. */ - - for (i = 0; i < num_locks; i++) { + for (i = 0; i < *pnum_entries; i++) { struct lock_struct *lock_data = &locks[i]; if (!process_exists(lock_data->context.pid)) { /* This process no longer exists - mark this @@ -1293,17 +1281,18 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st } } - if (num_valid_entries != num_locks) { + if (num_valid_entries != *pnum_entries) { struct lock_struct *new_lock_data = NULL; if (num_valid_entries) { new_lock_data = SMB_MALLOC_ARRAY(struct lock_struct, num_valid_entries); if (!new_lock_data) { DEBUG(3, ("malloc fail\n")); - return 0; + return False; } + num_valid_entries = 0; - for (i = 0; i < num_locks; i++) { + for (i = 0; i < *pnum_entries; i++) { struct lock_struct *lock_data = &locks[i]; if (lock_data->context.smbpid && lock_data->context.tid) { @@ -1314,9 +1303,51 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st } } } - SAFE_FREE(dbuf.dptr); - dbuf.dptr = (void *)new_lock_data; - dbuf.dsize = (num_valid_entries) * sizeof(*locks); + + SAFE_FREE(*pplocks); + *pplocks = new_lock_data; + *pnum_entries = num_valid_entries; + } + + return True; +} + +/**************************************************************************** + Traverse the whole database with this function, calling traverse_callback + on each lock. +****************************************************************************/ + +static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +{ + struct lock_struct *locks; + struct lock_key *key; + unsigned int i; + unsigned int num_locks = 0; + unsigned int orig_num_locks = 0; + + BRLOCK_FN(traverse_callback) = (BRLOCK_FN_CAST())state; + + /* In a traverse function we must make a copy of + dbuf before modifying it. */ + + locks = (struct lock_struct *)memdup(dbuf.dptr, dbuf.dsize); + if (!locks) { + return -1; /* Terminate traversal. */ + } + + key = (struct lock_key *)kbuf.dptr; + orig_num_locks = num_locks = dbuf.dsize/sizeof(*locks); + + /* Ensure the lock db is clean of entries from invalid processes. */ + + if (!validate_lock_entries(&num_locks, &locks)) { + SAFE_FREE(locks); + return -1; /* Terminate traversal */ + } + + if (orig_num_locks != num_locks) { + dbuf.dptr = (void *)locks; + dbuf.dsize = num_locks * sizeof(*locks); if (dbuf.dsize) { tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE); @@ -1325,7 +1356,7 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st } } - for (i=0;idevice, key->inode, locks[i].context.pid, @@ -1334,6 +1365,8 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st locks[i].start, locks[i].size); } + + SAFE_FREE(locks); return 0; } @@ -1429,47 +1462,12 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp) /* This is the first time we've accessed this. */ /* Go through and ensure all entries exist - remove any that don't. */ /* Makes the lockdb self cleaning at low cost. */ - unsigned int num_valid_entries = 0; - unsigned int i; - - for (i = 0; i < br_lck->num_locks; i++) { - struct lock_struct *lock_data = &((struct lock_struct *)br_lck->lock_data)[i]; - if (!process_exists(lock_data->context.pid)) { - /* This process no longer exists - mark this - entry as invalid by zeroing it. */ - ZERO_STRUCTP(lock_data); - } else { - num_valid_entries++; - } - } - if (num_valid_entries != br_lck->num_locks) { - struct lock_struct *new_lock_data = NULL; - - if (num_valid_entries) { - new_lock_data = SMB_MALLOC_ARRAY(struct lock_struct, num_valid_entries); - if (!new_lock_data) { - DEBUG(3, ("malloc fail\n")); - tdb_chainunlock(tdb, key); - SAFE_FREE(br_lck->lock_data); - SAFE_FREE(br_lck); - return NULL; - } - num_valid_entries = 0; - for (i = 0; i < br_lck->num_locks; i++) { - struct lock_struct *lock_data = &((struct lock_struct *)br_lck->lock_data)[i]; - if (lock_data->context.smbpid && - lock_data->context.tid) { - /* Valid (nonzero) entry - copy it. */ - memcpy(&new_lock_data[num_valid_entries], - lock_data, sizeof(struct lock_struct)); - num_valid_entries++; - } - } - } + if (!validate_lock_entries(&br_lck->num_locks, (struct lock_struct **)&br_lck->lock_data)) { + tdb_chainunlock(tdb, key); SAFE_FREE(br_lck->lock_data); - br_lck->lock_data = (void *)new_lock_data; - br_lck->num_locks = num_valid_entries; + SAFE_FREE(br_lck); + return NULL; } /* Mark the lockdb as "clean" as seen from this open file. */ -- cgit From cc9ea93456e594432e203e6d2d2f4dbcaac9a3dd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 May 2006 23:15:53 +0000 Subject: r15668: DOS or FCB opens share one share mode entry from different fsp pointers. Ensure we cope with this to pass Samba4 DENY tests (we used to pass these, there must have been a regression with newer code). We now pass them. Jeremy (This used to be commit fd6fa1d4eaf61783df74ee2da50d331477f06998) --- source3/locking/locking.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 2b6023c0c4..2766b257be 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -927,7 +927,7 @@ static void fill_share_mode_entry(struct share_mode_entry *e, e->op_type = op_type; e->time.tv_sec = fsp->open_time.tv_sec; e->time.tv_usec = fsp->open_time.tv_usec; - e->share_file_id = fsp->file_id; + e->share_file_id = fsp->fh->file_id; e->dev = fsp->dev; e->inode = fsp->inode; } @@ -986,28 +986,19 @@ void add_deferred_open(struct share_mode_lock *lck, uint16 mid, /******************************************************************* Check if two share mode entries are identical, ignoring oplock - and mid info and desired_access. + and mid info and desired_access. (Removed paranoia test - it's + not automatically a logic error if they are identical. JRA.) ********************************************************************/ static BOOL share_modes_identical(struct share_mode_entry *e1, struct share_mode_entry *e2) { -#if 1 /* JRA PARANOIA TEST - REMOVE LATER */ - if (procid_equal(&e1->pid, &e2->pid) && - e1->share_file_id == e2->share_file_id && - e1->dev == e2->dev && - e1->inode == e2->inode && - (e1->share_access) != (e2->share_access)) { - DEBUG(0,("PANIC: share_modes_identical: share_mode " - "mismatch (e1 = 0x%x, e2 = 0x%x). Logic error.\n", - (unsigned int)e1->share_access, - (unsigned int)e2->share_access )); - smb_panic("PANIC: share_modes_identical logic error.\n"); - } -#endif + /* We used to check for e1->share_access == e2->share_access here + as well as the other fields but 2 different DOS or FCB opens + sharing the same share mode entry may validly differ in + fsp->share_access field. */ return (procid_equal(&e1->pid, &e2->pid) && - (e1->share_access) == (e2->share_access) && e1->dev == e2->dev && e1->inode == e2->inode && e1->share_file_id == e2->share_file_id ); -- cgit From 6a026d56185f56dc9bf5ae8e5c1d33a0ce32562b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 May 2006 00:22:07 +0000 Subject: r15670: Fix valgrind-spotted issue in BASE-DELETE test. We were forgetting to increment after copying the primary group gid. Jeremy (This used to be commit 31d16c434e1ee94691f013ed0b31d9f26baeb2cb) --- source3/locking/locking.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 2766b257be..a532a90d0d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -665,6 +665,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) p += sizeof(uid_t); memcpy(p, &lck->delete_token->gid, sizeof(gid_t)); + p += sizeof(gid_t); for (i = 0; i < lck->delete_token->ngroups; i++) { memcpy(p, &lck->delete_token->groups[i], sizeof(gid_t)); -- cgit From 0a1ca7fa3d19f46c4bcb0c80c78a619c90fe5f2a Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 29 May 2006 23:54:53 +0000 Subject: r15943: Update misleading DEBUG statements and comments that refer to open_file_shared. (This used to be commit 784126edff942d1c2f79f7c9feb59980426f331e) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index a532a90d0d..b536844319 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1116,7 +1116,7 @@ BOOL downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp) /**************************************************************************** Deal with the internal needs of setting the delete on close flag. Note that as the tdb locking is recursive, it is safe to call this from within - open_file_shared. JRA. + open_file_ntcreate. JRA. ****************************************************************************/ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, -- cgit From c115570b857cff15c929cf80ad3c8f32272818d5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jun 2006 01:35:08 +0000 Subject: r16281: Start fixing up gcc4 -O6 warnings on an x86_64 box. size_t != unsigned int in a format string. Jeremy. (This used to be commit c49ad9200bf3fdd8b9404d93182c2e04e662190a) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index b536844319..0ffb937432 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -846,7 +846,7 @@ BOOL rename_share_filename(struct share_mode_lock *lck, SDEV_T_VAL(frm,0,lck->dev); SINO_T_VAL(frm,8,lck->ino); - DEBUG(10,("rename_share_filename: msg_len = %d\n", msg_len )); + DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len )); safe_strcpy(&frm[16], lck->servicepath, sp_len); safe_strcpy(&frm[16 + sp_len + 1], lck->filename, fn_len); -- cgit From a90026e7a68398a7f9c38dc3cd1dad193466b8af Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jun 2006 22:29:53 +0000 Subject: r16307: Make sure we know we must pass a valid pointer here. Klocwork #1129. Jeremy. (This used to be commit e8d86362ba8762a5e4180e7320f5ac8bb37c203d) --- source3/locking/posix.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index e7075c57a6..4a5f59b622 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -454,9 +454,8 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T entry->start == start && entry->size == size) { - /* Make a copy if requested. */ - if (pl) - *pl = *entry; + /* Make a copy */ + *pl = *entry; /* Found it - delete it. */ if (count == 1) { -- cgit From 54ea3c23e3bfd25008198e85fdcc1f48b0325eab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Jun 2006 02:31:12 +0000 Subject: r16435: Add in the uid info that Jerry needs into the share_mode struct. Allows us to know the unix uid of the opener of the file/directory. Needed for info level queries on open files. Jeremy. (This used to be commit d929323d6f513902381369d77bcd7b714346d713) --- source3/locking/locking.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 0ffb937432..01f12bbb58 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -443,13 +443,13 @@ char *share_mode_str(int num, struct share_mode_entry *e) slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s " "pid = %s, share_access = 0x%x, private_options = 0x%x, " "access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, " - "dev = 0x%x, inode = %.0f", + "uid = %u, dev = 0x%x, inode = %.0f", num, e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "", procid_str_static(&e->pid), e->share_access, e->private_options, e->access_mask, e->op_mid, e->op_type, e->share_file_id, - (unsigned int)e->dev, (double)e->inode ); + (unsigned int)e->uid, (unsigned int)e->dev, (double)e->inode ); return share_str; } @@ -917,7 +917,7 @@ BOOL is_unused_share_mode_entry(const struct share_mode_entry *e) static void fill_share_mode_entry(struct share_mode_entry *e, files_struct *fsp, - uint16 mid, uint16 op_type) + uid_t uid, uint16 mid, uint16 op_type) { ZERO_STRUCTP(e); e->pid = procid_self(); @@ -928,9 +928,10 @@ static void fill_share_mode_entry(struct share_mode_entry *e, e->op_type = op_type; e->time.tv_sec = fsp->open_time.tv_sec; e->time.tv_usec = fsp->open_time.tv_usec; - e->share_file_id = fsp->fh->file_id; e->dev = fsp->dev; e->inode = fsp->inode; + e->share_file_id = fsp->fh->file_id; + e->uid = (uint32)uid; } static void fill_deferred_open_entry(struct share_mode_entry *e, @@ -945,6 +946,7 @@ static void fill_deferred_open_entry(struct share_mode_entry *e, e->time.tv_usec = request_time.tv_usec; e->dev = dev; e->inode = ino; + e->uid = (uint32)-1; } static void add_share_mode_entry(struct share_mode_lock *lck, @@ -969,10 +971,10 @@ static void add_share_mode_entry(struct share_mode_lock *lck, } void set_share_mode(struct share_mode_lock *lck, files_struct *fsp, - uint16 mid, uint16 op_type) + uid_t uid, uint16 mid, uint16 op_type) { struct share_mode_entry entry; - fill_share_mode_entry(&entry, fsp, mid, op_type); + fill_share_mode_entry(&entry, fsp, uid, mid, op_type); add_share_mode_entry(lck, &entry); } @@ -1044,7 +1046,8 @@ BOOL del_share_mode(struct share_mode_lock *lck, files_struct *fsp) { struct share_mode_entry entry, *e; - fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK); + /* Don't care about the pid owner being correct here - just a search. */ + fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK); e = find_share_mode_entry(lck, &entry); if (e == NULL) { @@ -1080,7 +1083,8 @@ BOOL remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp) { struct share_mode_entry entry, *e; - fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK); + /* Don't care about the pid owner being correct here - just a search. */ + fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK); e = find_share_mode_entry(lck, &entry); if (e == NULL) { @@ -1101,7 +1105,8 @@ BOOL downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp) { struct share_mode_entry entry, *e; - fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK); + /* Don't care about the pid owner being correct here - just a search. */ + fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK); e = find_share_mode_entry(lck, &entry); if (e == NULL) { -- cgit From cc1457beb00faa6869e2472e305b4e97c0995ea3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Jun 2006 22:33:10 +0000 Subject: r16661: Fix from jason@ncac.gwu.edu for bug #3875, bad cast warning. Jeremy. (This used to be commit d60e6e0abc17361fe180d6723b970552dc377741) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 01f12bbb58..9d3ca95601 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1274,7 +1274,7 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, const char *sharepath; const char *fname; int i; - void (*traverse_callback)(struct share_mode_entry *, const char *, const char *) = state; + LOCKING_FN(traverse_callback) = (LOCKING_FN_CAST())state; /* Ensure this is a locking_key record. */ if (kbuf.dsize != sizeof(struct locking_key)) -- cgit From fbdcf2663b56007a438ac4f0d8d82436b1bfe688 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Jul 2006 18:01:26 +0000 Subject: r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need to do the upper layer directories but this is what everyone is waiting for.... Jeremy. (This used to be commit 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8) --- source3/locking/brlock.c | 304 ++++++---- source3/locking/locking.c | 87 ++- source3/locking/posix.c | 1419 ++++++++++++++++++++++----------------------- 3 files changed, 925 insertions(+), 885 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 574552e9e2..9c8a7a17ee 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -32,29 +32,6 @@ #define ZERO_ZERO 0 -/* This contains elements that differentiate locks. The smbpid is a - client supplied pid, and is essentially the locking context for - this client */ - -struct lock_context { - uint16 smbpid; - uint16 tid; - struct process_id pid; -}; - -/* The data in brlock records is an unsorted linear array of these - records. It is unnecessary to store the count as tdb provides the - size of the record */ - -struct lock_struct { - struct lock_context context; - br_off start; - br_off size; - int fnum; - enum brl_type lock_type; - enum brl_flavour lock_flav; -}; - /* The open brlock.tdb database. */ static TDB_CONTEXT *tdb; @@ -83,7 +60,7 @@ static void print_lock_struct(unsigned int i, struct lock_struct *pls) See if two locking contexts are equal. ****************************************************************************/ -static BOOL brl_same_context(const struct lock_context *ctx1, +BOOL brl_same_context(const struct lock_context *ctx1, const struct lock_context *ctx2) { return (procid_equal(&ctx1->pid, &ctx2->pid) && @@ -343,13 +320,19 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, /* We can get the Windows lock, now see if it needs to be mapped into a lower level POSIX one, and if so can - we get it ? We tell the lower lock layer about the - lock type so it can cope with the difference between - Windows "stacking" locks and POSIX "flat" ones. */ + we get it ? */ if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) { - if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, WINDOWS_LOCK)) { - if (errno == EACCES || errno == EAGAIN) { + int errno_ret; + if (!set_posix_lock_windows_flavour(fsp, + plock->start, + plock->size, + plock->lock_type, + &plock->context, + locks, + br_lck->num_locks, + &errno_ret)) { + if (errno_ret == EACCES || errno_ret == EAGAIN) { return NT_STATUS_FILE_LOCK_CONFLICT; } else { return map_nt_error_from_unix(errno); @@ -375,9 +358,9 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, Cope with POSIX range splits and merges. ****************************************************************************/ -static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, - const struct lock_struct *ex, - const struct lock_struct *plock, +static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, /* Output array. */ + const struct lock_struct *ex, /* existing lock. */ + const struct lock_struct *plock, /* proposed lock. */ BOOL *lock_was_added) { BOOL lock_types_differ = (ex->lock_type != plock->lock_type); @@ -398,26 +381,26 @@ static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, +---------+ | ex | +---------+ - +-------+ - | plock | - +-------+ + +-------+ + | plock | + +-------+ OR.... +---------+ | ex | +---------+ **********************************************/ - if ( (ex->start >= (plock->start + plock->size)) || - (plock->start >= (ex->start + ex->size))) { + if ( (ex->start > (plock->start + plock->size)) || + (plock->start > (ex->start + ex->size))) { /* No overlap with this lock - copy existing. */ memcpy(&lck_arr[0], ex, sizeof(struct lock_struct)); return 1; } /********************************************* - +---------+ - | ex | - +---------+ + +---------------------------+ + | ex | + +---------------------------+ +---------------------------+ | plock | -> replace with plock. +---------------------------+ @@ -431,24 +414,32 @@ OR.... } /********************************************* - +---------------+ - | ex | - +---------------+ + +-----------------------+ + | ex | + +-----------------------+ +---------------+ | plock | +---------------+ +OR.... + +-------+ + | ex | + +-------+ + +---------------+ + | plock | + +---------------+ + BECOMES.... +---------------+-------+ | plock | ex | - different lock types. +---------------+-------+ -OR.... +OR.... (merge) +-----------------------+ | ex | - same lock type. +-----------------------+ **********************************************/ if ( (ex->start >= plock->start) && - (ex->start < plock->start + plock->size) && + (ex->start <= plock->start + plock->size) && (ex->start + ex->size > plock->start + plock->size) ) { *lock_was_added = True; @@ -475,9 +466,16 @@ OR.... } /********************************************* - +---------------+ - | ex | - +---------------+ + +-----------------------+ + | ex | + +-----------------------+ + +---------------+ + | plock | + +---------------+ +OR.... + +-------+ + | ex | + +-------+ +---------------+ | plock | +---------------+ @@ -486,7 +484,7 @@ BECOMES.... | ex | plock | - different lock types +-------+---------------+ -OR +OR.... (merge) +-----------------------+ | ex | - same lock type. +-----------------------+ @@ -494,7 +492,7 @@ OR **********************************************/ if ( (ex->start < plock->start) && - (ex->start + ex->size > plock->start) && + (ex->start + ex->size >= plock->start) && (ex->start + ex->size <= plock->start + plock->size) ) { *lock_was_added = True; @@ -631,20 +629,28 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, } } + if (!lock_was_added) { + memcpy(&tp[count], plock, sizeof(struct lock_struct)); + count++; + } + /* We can get the POSIX lock, now see if it needs to be mapped into a lower level POSIX one, and if so can - we get it ? We well the lower lock layer about the - lock type so it can cope with the difference between - Windows "stacking" locks and POSIX "flat" ones. */ + we get it ? */ -#if 0 - /* FIXME - this call doesn't work correctly yet for POSIX locks... */ + if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(br_lck->fsp->conn))) { + int errno_ret; - if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) { - files_struct *fsp = br_lck->fsp; + /* The lower layer just needs to attempt to + get the system POSIX lock. We've weeded out + any conflicts above. */ - if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, POSIX_LOCK)) { - if (errno == EACCES || errno == EAGAIN) { + if (!set_posix_lock_posix_flavour(br_lck->fsp, + plock->start, + plock->size, + plock->lock_type, + &errno_ret)) { + if (errno_ret == EACCES || errno_ret == EAGAIN) { SAFE_FREE(tp); return NT_STATUS_FILE_LOCK_CONFLICT; } else { @@ -653,12 +659,6 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, } } } -#endif - - if (!lock_was_added) { - memcpy(&tp[count], plock, sizeof(struct lock_struct)); - count++; - } /* Realloc so we don't leak entries per lock call. */ tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks)); @@ -676,7 +676,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, ****************************************************************************/ NTSTATUS brl_lock(struct byte_range_lock *br_lck, - uint16 smbpid, + uint32 smbpid, struct process_id pid, br_off start, br_off size, @@ -740,8 +740,12 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock unsigned int i, j; struct lock_struct *lock = NULL; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */ #if ZERO_ZERO + /* Delete write locks by preference... The lock list + is sorted in the zero zero case. */ + for (i = 0; i < br_lck->num_locks; i++) { lock = &locks[i]; @@ -753,16 +757,15 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock lock->size == plock->size) { /* found it - delete it */ - if (i < br_lck->num_locks - 1) { - memmove(&locks[i], &locks[i+1], - sizeof(*locks)*((br_lck->num_locks-1) - i)); - } - - br_lck->num_locks -= 1; - br_lck->modified = True; - return True; + deleted_lock_type = lock->lock_type; + break; } } + + if (i != br_lck->num_locks) { + /* We found it - don't search again. */ + goto unlock_continue; + } #endif for (i = 0; i < br_lck->num_locks; i++) { @@ -774,6 +777,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock lock->lock_flav == WINDOWS_LOCK && lock->start == plock->start && lock->size == plock->size ) { + deleted_lock_type = lock->lock_type; break; } } @@ -783,9 +787,28 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock return False; } - /* Unlock any POSIX regions. */ +#if ZERO_ZERO + unlock_continue: +#endif + + /* Actually delete the lock. */ + if (i < br_lck->num_locks - 1) { + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((br_lck->num_locks-1) - i)); + } + + br_lck->num_locks -= 1; + br_lck->modified = True; + + /* Unlock the underlying POSIX regions. */ if(lp_posix_locking(br_lck->fsp->conn->cnum)) { - release_posix_lock(br_lck->fsp, plock->start, plock->size); + release_posix_lock_windows_flavour(br_lck->fsp, + plock->start, + plock->size, + deleted_lock_type, + &plock->context, + locks, + br_lck->num_locks); } /* Send unlock messages to any pending waiters that overlap. */ @@ -810,14 +833,6 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock } } - /* Actually delete the lock. */ - if (i < br_lck->num_locks - 1) { - memmove(&locks[i], &locks[i+1], - sizeof(*locks)*((br_lck->num_locks-1) - i)); - } - - br_lck->num_locks -= 1; - br_lck->modified = True; return True; } @@ -895,13 +910,18 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type); SMB_ASSERT(tmp_lock[1].lock_type == UNLOCK_LOCK); memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct)); + if (tmp_lock[0].size != locks[i].size) { + overlap_found = True; + } } else { SMB_ASSERT(tmp_lock[0].lock_type == UNLOCK_LOCK); SMB_ASSERT(tmp_lock[1].lock_type == locks[i].lock_type); memcpy(&tp[count], &tmp_lock[1], sizeof(struct lock_struct)); + if (tmp_lock[1].start != locks[i].start) { + overlap_found = True; + } } count++; - overlap_found = True; continue; } else { /* tmp_count == 3 - (we split a lock range in two). */ @@ -933,14 +953,15 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s return True; } -#if 0 - /* FIXME - this call doesn't work correctly yet for POSIX locks... */ - /* Unlock any POSIX regions. */ if(lp_posix_locking(br_lck->fsp->conn->cnum)) { - release_posix_lock(br_lck->fsp, plock->start, plock->size); + release_posix_lock_posix_flavour(br_lck->fsp, + plock->start, + plock->size, + &plock->context, + tp, + count); } -#endif /* Realloc so we don't leak entries per unlock call. */ if (count) { @@ -991,7 +1012,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s ****************************************************************************/ BOOL brl_unlock(struct byte_range_lock *br_lck, - uint16 smbpid, + uint32 smbpid, struct process_id pid, br_off start, br_off size, @@ -1021,7 +1042,7 @@ BOOL brl_unlock(struct byte_range_lock *br_lck, ****************************************************************************/ BOOL brl_locktest(struct byte_range_lock *br_lck, - uint16 smbpid, + uint32 smbpid, struct process_id pid, br_off start, br_off size, @@ -1079,7 +1100,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck, ****************************************************************************/ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, - uint16 *psmbpid, + uint32 *psmbpid, struct process_id pid, br_off *pstart, br_off *psize, @@ -1148,7 +1169,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, ****************************************************************************/ BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck, - uint16 smbpid, + uint32 smbpid, struct process_id pid, br_off start, br_off size, @@ -1192,18 +1213,75 @@ BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck, return True; } - /**************************************************************************** Remove any locks associated with a open file. + We return True if this process owns any other Windows locks on this + fd and so we should not immediately close the fd. ****************************************************************************/ -void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid) +void brl_close_fnum(struct byte_range_lock *br_lck) { files_struct *fsp = br_lck->fsp; uint16 tid = fsp->conn->cnum; int fnum = fsp->fnum; unsigned int i, j, dcount=0; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct process_id pid = procid_self(); + BOOL unlock_individually = False; + + if(lp_posix_locking(fsp->conn->cnum) && !lp_posix_cifsu_locktype()) { + + /* Check if there are any Windows locks associated with this dev/ino + pair that are not this fnum. If so we need to call unlock on each + one in order to release the system POSIX locks correctly. */ + + for (i=0; i < br_lck->num_locks; i++) { + struct lock_struct *lock = &locks[i]; + + if (!procid_equal(&lock->context.pid, &pid)) { + continue; + } + + if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) { + continue; /* Ignore pending. */ + } + + if (lock->context.tid != tid || lock->fnum != fnum) { + unlock_individually = True; + break; + } + } + + if (unlock_individually) { + struct lock_struct *locks_copy; + + /* Copy the current lock array. */ + locks_copy = TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); + if (!locks_copy) { + DEBUG(0,("brl_close_fnum: talloc fail.\n")); + } + + for (i=0; i < br_lck->num_locks; i++) { + struct lock_struct *lock = &locks_copy[i]; + + if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid) && + (lock->fnum == fnum)) { + brl_unlock(br_lck, + lock->context.smbpid, + pid, + lock->start, + lock->size, + lock->lock_flav); + } + } + return; + } + } + + /* We can bulk delete - any POSIX locks will be removed when the fd closes. */ + + /* Zero any lock reference count on this dev/ino pair. */ + zero_windows_lock_ref_count(fsp); /* Remove any existing locks for this fnum (or any fnum if they're POSIX). */ @@ -1346,7 +1424,7 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st } if (orig_num_locks != num_locks) { - dbuf.dptr = (void *)locks; + dbuf.dptr = (char *)locks; dbuf.dsize = num_locks * sizeof(*locks); if (dbuf.dsize) { @@ -1388,8 +1466,10 @@ int brl_forall(BRLOCK_FN(fn)) Unlock the record. ********************************************************************/ -int byte_range_lock_destructor(struct byte_range_lock *br_lck) +static int byte_range_lock_destructor(void *p) { + struct byte_range_lock *br_lck = + talloc_get_type_abort(p, struct byte_range_lock); TDB_DATA key; key.dptr = (char *)&br_lck->key; @@ -1406,7 +1486,7 @@ int byte_range_lock_destructor(struct byte_range_lock *br_lck) } } else { TDB_DATA data; - data.dptr = br_lck->lock_data; + data.dptr = (char *)br_lck->lock_data; data.dsize = br_lck->num_locks * sizeof(struct lock_struct); if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) { @@ -1418,20 +1498,21 @@ int byte_range_lock_destructor(struct byte_range_lock *br_lck) tdb_chainunlock(tdb, key); SAFE_FREE(br_lck->lock_data); - SAFE_FREE(br_lck); return 0; } /******************************************************************* Fetch a set of byte range lock data from the database. Leave the record locked. + TALLOC_FREE(brl) will release the lock in the destructor. ********************************************************************/ -struct byte_range_lock *brl_get_locks(files_struct *fsp) +struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, + files_struct *fsp) { TDB_DATA key; TDB_DATA data; - struct byte_range_lock *br_lck = SMB_MALLOC_P(struct byte_range_lock); + struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock); if (br_lck == NULL) { return NULL; @@ -1449,10 +1530,12 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp) if (tdb_chainlock(tdb, key) != 0) { DEBUG(3, ("Could not lock byte range lock entry\n")); - SAFE_FREE(br_lck); + TALLOC_FREE(br_lck); return NULL; } + talloc_set_destructor(br_lck, byte_range_lock_destructor); + data = tdb_fetch(tdb, key); br_lck->lock_data = (void *)data.dptr; br_lck->num_locks = data.dsize / sizeof(struct lock_struct); @@ -1463,13 +1546,22 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp) /* Go through and ensure all entries exist - remove any that don't. */ /* Makes the lockdb self cleaning at low cost. */ - if (!validate_lock_entries(&br_lck->num_locks, (struct lock_struct **)&br_lck->lock_data)) { - tdb_chainunlock(tdb, key); + struct lock_struct *locks = + (struct lock_struct *)br_lck->lock_data; + + if (!validate_lock_entries(&br_lck->num_locks, &locks)) { SAFE_FREE(br_lck->lock_data); - SAFE_FREE(br_lck); + TALLOC_FREE(br_lck); return NULL; } + /* + * validate_lock_entries might have changed locks. We can't + * use a direct pointer here because otherwise gcc warnes + * about strict aliasing rules being violated. + */ + br_lck->lock_data = locks; + /* Mark the lockdb as "clean" as seen from this open file. */ fsp->lockdb_clean = True; } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 9d3ca95601..ac50c9b648 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -37,7 +37,6 @@ */ #include "includes.h" -uint16 global_smbpid; #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING @@ -74,6 +73,7 @@ const char *lock_flav_name(enum brl_flavour lock_flav) ****************************************************************************/ BOOL is_locked(files_struct *fsp, + uint32 smbpid, SMB_BIG_UINT count, SMB_BIG_UINT offset, enum brl_type lock_type) @@ -100,32 +100,32 @@ BOOL is_locked(files_struct *fsp, DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); ret = False; } else { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { return False; } ret = !brl_locktest(br_lck, - global_smbpid, + smbpid, procid_self(), offset, count, lock_type, lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } } else { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { return False; } ret = !brl_locktest(br_lck, - global_smbpid, + smbpid, procid_self(), offset, count, lock_type, lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } DEBUG(10,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n", @@ -141,7 +141,7 @@ BOOL is_locked(files_struct *fsp, ****************************************************************************/ NTSTATUS query_lock(files_struct *fsp, - uint16 *psmbpid, + uint32 *psmbpid, SMB_BIG_UINT *pcount, SMB_BIG_UINT *poffset, enum brl_type *plock_type, @@ -150,15 +150,15 @@ NTSTATUS query_lock(files_struct *fsp, struct byte_range_lock *br_lck = NULL; NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED; - if (!OPEN_FSP(fsp) || !fsp->can_lock) { - return NT_STATUS_INVALID_HANDLE; + if (!fsp->can_lock) { + return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } if (!lp_locking(SNUM(fsp->conn))) { return NT_STATUS_OK; } - br_lck = brl_get_locks(fsp); + br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -171,7 +171,7 @@ NTSTATUS query_lock(files_struct *fsp, plock_type, lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); return status; } @@ -180,7 +180,7 @@ NTSTATUS query_lock(files_struct *fsp, ****************************************************************************/ NTSTATUS do_lock(files_struct *fsp, - uint16 lock_pid, + uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, enum brl_type lock_type, @@ -190,8 +190,8 @@ NTSTATUS do_lock(files_struct *fsp, struct byte_range_lock *br_lck = NULL; NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED; - if (!OPEN_FSP(fsp) || !fsp->can_lock) { - return NT_STATUS_INVALID_HANDLE; + if (!fsp->can_lock) { + return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } if (!lp_locking(SNUM(fsp->conn))) { @@ -204,7 +204,7 @@ NTSTATUS do_lock(files_struct *fsp, lock_flav_name(lock_flav), lock_type_name(lock_type), (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - br_lck = brl_get_locks(fsp); + br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -218,7 +218,7 @@ NTSTATUS do_lock(files_struct *fsp, lock_flav, my_lock_ctx); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); return status; } @@ -230,7 +230,7 @@ NTSTATUS do_lock(files_struct *fsp, ****************************************************************************/ NTSTATUS do_lock_spin(files_struct *fsp, - uint16 lock_pid, + uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, enum brl_type lock_type, @@ -286,7 +286,7 @@ NTSTATUS do_lock_spin(files_struct *fsp, ****************************************************************************/ NTSTATUS do_unlock(files_struct *fsp, - uint16 lock_pid, + uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, enum brl_flavour lock_flav) @@ -294,18 +294,18 @@ NTSTATUS do_unlock(files_struct *fsp, BOOL ok = False; struct byte_range_lock *br_lck = NULL; - if (!lp_locking(SNUM(fsp->conn))) { - return NT_STATUS_OK; + if (!fsp->can_lock) { + return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } - if (!OPEN_FSP(fsp) || !fsp->can_lock) { - return NT_STATUS_INVALID_HANDLE; + if (!lp_locking(SNUM(fsp->conn))) { + return NT_STATUS_OK; } DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n", (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - br_lck = brl_get_locks(fsp); + br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -317,7 +317,7 @@ NTSTATUS do_unlock(files_struct *fsp, count, lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); @@ -334,25 +334,15 @@ NTSTATUS do_unlock(files_struct *fsp, void locking_close_file(files_struct *fsp) { struct byte_range_lock *br_lck; - struct process_id pid = procid_self(); - if (!lp_locking(SNUM(fsp->conn))) + if (!lp_locking(SNUM(fsp->conn))) { return; - - /* - * Just release all the brl locks, no need to release individually. - */ - - br_lck = brl_get_locks(fsp); - if (br_lck) { - brl_close_fnum(br_lck, pid); - byte_range_lock_destructor(br_lck); } - if(lp_posix_locking(SNUM(fsp->conn))) { - /* Release all the POSIX locks.*/ - posix_locking_close_file(fsp); - + br_lck = brl_get_locks(NULL,fsp); + if (br_lck) { + brl_close_fnum(br_lck); + TALLOC_FREE(br_lck); } } @@ -516,9 +506,10 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) smb_panic("PANIC: parse_share_modes: buffer too short.\n"); } - lck->share_modes = talloc_memdup(lck, dbuf.dptr+sizeof(*data), - lck->num_share_modes * - sizeof(struct share_mode_entry)); + lck->share_modes = (struct share_mode_entry *) + talloc_memdup(lck, dbuf.dptr+sizeof(*data), + lck->num_share_modes * + sizeof(struct share_mode_entry)); if (lck->share_modes == NULL) { smb_panic("talloc failed\n"); @@ -635,7 +626,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) delete_token_size + sp_len + 1 + strlen(lck->filename) + 1; - result.dptr = talloc_size(lck, result.dsize); + result.dptr = TALLOC_ARRAY(lck, char, result.dsize); if (result.dptr == NULL) { smb_panic("talloc failed\n"); @@ -838,7 +829,7 @@ BOOL rename_share_filename(struct share_mode_lock *lck, msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + fn_len + 1; /* Set up the name changed message. */ - frm = TALLOC(lck, msg_len); + frm = TALLOC_ARRAY(lck, char, msg_len); if (!frm) { return False; } @@ -862,9 +853,9 @@ BOOL rename_share_filename(struct share_mode_lock *lck, continue; } - DEBUG(10,("rename_share_filename: sending rename message to pid %u " + DEBUG(10,("rename_share_filename: sending rename message to pid %s " "dev %x, inode %.0f sharepath %s newname %s\n", - (unsigned int)procid_to_pid(&se->pid), + procid_str_static(&se->pid), (unsigned int)lck->dev, (double)lck->ino, lck->servicepath, lck->filename )); @@ -1305,5 +1296,5 @@ int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, { if (tdb == NULL) return 0; - return tdb_traverse(tdb, traverse_fn, fn); + return tdb_traverse(tdb, traverse_fn, (void *)fn); } diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 4a5f59b622..59b62170e8 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. Locking functions - Copyright (C) Jeremy Allison 1992-2000 + Copyright (C) Jeremy Allison 1992-2006 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 @@ -27,753 +27,694 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING -/* - * The POSIX locking database handle. - */ - -static TDB_CONTEXT *posix_lock_tdb; - /* * The pending close database handle. */ static TDB_CONTEXT *posix_pending_close_tdb; -/* - * The data in POSIX lock records is an unsorted linear array of these - * records. It is unnecessary to store the count as tdb provides the - * size of the record. - */ - -struct posix_lock { - int fd; - SMB_OFF_T start; - SMB_OFF_T size; - int lock_type; -}; - -/* - * The data in POSIX pending close records is an unsorted linear array of int - * records. It is unnecessary to store the count as tdb provides the - * size of the record. - */ - -/* The key used in both the POSIX databases. */ - -struct posix_lock_key { - SMB_DEV_T device; - SMB_INO_T inode; -}; +/**************************************************************************** + First - the functions that deal with the underlying system locks - these + functions are used no matter if we're mapping CIFS Windows locks or CIFS + POSIX locks onto POSIX. +****************************************************************************/ -/******************************************************************* - Form a static locking key for a dev/inode pair. -******************************************************************/ +/**************************************************************************** + Utility function to map a lock type correctly depending on the open + mode of a file. +****************************************************************************/ -static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) +static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) { - static struct posix_lock_key key; - TDB_DATA kbuf; + if((lock_type == WRITE_LOCK) && !fsp->can_write) { + /* + * Many UNIX's cannot get a write lock on a file opened read-only. + * Win32 locking semantics allow this. + * Do the best we can and attempt a read-only lock. + */ + DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n")); + return F_RDLCK; + } - memset(&key, '\0', sizeof(key)); - key.device = dev; - key.inode = inode; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); - return kbuf; + /* + * This return should be the most normal, as we attempt + * to always open files read/write. + */ + + return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK; } -/******************************************************************* - Convenience function to get a key from an fsp. -******************************************************************/ +/**************************************************************************** + Debugging aid :-). +****************************************************************************/ -static TDB_DATA locking_key_fsp(files_struct *fsp) +static const char *posix_lock_type_name(int lock_type) { - return locking_key(fsp->dev, fsp->inode); + return (lock_type == F_RDLCK) ? "READ" : "WRITE"; } /**************************************************************************** - Add an fd to the pending close tdb. + Check to see if the given unsigned lock range is within the possible POSIX + range. Modifies the given args to be in range if possible, just returns + False if not. ****************************************************************************/ -static BOOL add_fd_to_close_entry(files_struct *fsp) +static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, + SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) { - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; + SMB_OFF_T offset = (SMB_OFF_T)u_offset; + SMB_OFF_T count = (SMB_OFF_T)u_count; - dbuf.dptr = NULL; - dbuf.dsize = 0; + /* + * For the type of system we are, attempt to + * find the maximum positive lock offset as an SMB_OFF_T. + */ - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); +#if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */ - dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); - if (!dbuf.dptr) { - DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n")); + SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET); + +#elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) + + /* + * In this case SMB_OFF_T is 64 bits, + * and the underlying system can handle 64 bit signed locks. + */ + + SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); + SMB_OFF_T mask = (mask2<<1); + SMB_OFF_T max_positive_lock_offset = ~mask; + +#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * In this case either SMB_OFF_T is 32 bits, + * or the underlying system cannot handle 64 bit signed locks. + * All offsets & counts must be 2^31 or less. + */ + + SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF; + +#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * POSIX locks of length zero mean lock to end-of-file. + * Win32 locks of length zero are point probes. Ignore + * any Win32 locks of length zero. JRA. + */ + + if (count == (SMB_OFF_T)0) { + DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n")); return False; } - memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int)); - dbuf.dsize += sizeof(int); + /* + * If the given offset was > max_positive_lock_offset then we cannot map this at all + * ignore this lock. + */ - if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n")); + if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) { + DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n", + (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) )); + return False; } - SAFE_FREE(dbuf.dptr); + /* + * We must truncate the count to less than max_positive_lock_offset. + */ + + if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) { + count = max_positive_lock_offset; + } + + /* + * Truncate count to end at max lock offset. + */ + + if (offset + count < 0 || offset + count > max_positive_lock_offset) { + count = max_positive_lock_offset - offset; + } + + /* + * If we ate all the count, ignore this lock. + */ + + if (count == 0) { + DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n", + (double)u_offset, (double)u_count )); + return False; + } + + /* + * The mapping was successful. + */ + + DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n", + (double)offset, (double)count )); + + *offset_out = offset; + *count_out = count; + return True; } /**************************************************************************** - Remove all fd entries for a specific dev/inode pair from the tdb. + Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and + broken NFS implementations. ****************************************************************************/ -static void delete_close_entries(files_struct *fsp) +static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { - TDB_DATA kbuf = locking_key_fsp(fsp); + BOOL ret; - if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) - DEBUG(0,("delete_close_entries: tdb_delete fail !\n")); -} + DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type)); -/**************************************************************************** - Get the array of POSIX pending close records for an open fsp. Caller must - free. Returns number of entries. -****************************************************************************/ + ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); -static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - size_t count = 0; + if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { - *entries = NULL; - dbuf.dptr = NULL; + DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", + (double)offset,(double)count)); + DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); + DEBUG(0,("on 32 bit NFS mounted file systems.\n")); - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + /* + * If the offset is > 0x7FFFFFFF then this will cause problems on + * 32 bit NFS mounted filesystems. Just ignore it. + */ - if (!dbuf.dptr) { - return 0; - } + if (offset & ~((SMB_OFF_T)0x7fffffff)) { + DEBUG(0,("Offset greater than 31 bits. Returning success.\n")); + return True; + } - *entries = (int *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(int)); + if (count & ~((SMB_OFF_T)0x7fffffff)) { + /* 32 bit NFS file system, retry with smaller offset */ + DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); + errno = 0; + count &= 0x7fffffff; + ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); + } + } - return count; + DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed")); + return ret; } /**************************************************************************** - Get the array of POSIX locks for an fsp. Caller must free. Returns - number of entries. + Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and + broken NFS implementations. ****************************************************************************/ -static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries) +static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype) { - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - size_t count = 0; + pid_t pid; + BOOL ret; - *entries = NULL; + DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n", + fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype)); - dbuf.dptr = NULL; + ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); - dbuf = tdb_fetch(posix_lock_tdb, kbuf); + if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { - if (!dbuf.dptr) { - return 0; - } + DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n", + (double)*poffset,(double)*pcount)); + DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); + DEBUG(0,("on 32 bit NFS mounted file systems.\n")); - *entries = (struct posix_lock *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); + /* + * If the offset is > 0x7FFFFFFF then this will cause problems on + * 32 bit NFS mounted filesystems. Just ignore it. + */ - return count; + if (*poffset & ~((SMB_OFF_T)0x7fffffff)) { + DEBUG(0,("Offset greater than 31 bits. Returning success.\n")); + return True; + } + + if (*pcount & ~((SMB_OFF_T)0x7fffffff)) { + /* 32 bit NFS file system, retry with smaller offset */ + DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); + errno = 0; + *pcount &= 0x7fffffff; + ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); + } + } + + DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed")); + return ret; } /**************************************************************************** - Deal with pending closes needed by POSIX locking support. - Note that posix_locking_close_file() is expected to have been called - to delete all locks on this fsp before this function is called. + POSIX function to see if a file region is locked. Returns True if the + region is locked, False otherwise. ****************************************************************************/ -int fd_close_posix(struct connection_struct *conn, files_struct *fsp) +BOOL is_posix_locked(files_struct *fsp, + SMB_BIG_UINT *pu_offset, + SMB_BIG_UINT *pu_count, + enum brl_type *plock_type, + enum brl_flavour lock_flav) { - int saved_errno = 0; - int ret; - size_t count, i; - struct posix_lock *entries = NULL; - int *fd_array = NULL; - BOOL locks_on_other_fds = False; - - if (!lp_posix_locking(SNUM(conn))) { - /* - * No POSIX to worry about, just close. - */ - ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); - fsp->fh->fd = -1; - return ret; - } - - /* - * Get the number of outstanding POSIX locks on this dev/inode pair. - */ + SMB_OFF_T offset; + SMB_OFF_T count; + int posix_lock_type = map_posix_lock_type(fsp,*plock_type); - count = get_posix_lock_entries(fsp, &entries); + DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", + fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) )); /* - * Check if there are any outstanding locks belonging to - * other fd's. This should never be the case if posix_locking_close_file() - * has been called first, but it never hurts to be *sure*. + * If the requested lock won't fit in the POSIX range, we will + * never set it, so presume it is not locked. */ - for (i = 0; i < count; i++) { - if (entries[i].fd != fsp->fh->fd) { - locks_on_other_fds = True; - break; - } + if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) { + return False; } - if (locks_on_other_fds) { - - /* - * There are outstanding locks on this dev/inode pair on other fds. - * Add our fd to the pending close tdb and set fsp->fh->fd to -1. - */ - - if (!add_fd_to_close_entry(fsp)) { - SAFE_FREE(entries); - return -1; - } + if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) { + return False; + } - SAFE_FREE(entries); - fsp->fh->fd = -1; - return 0; + if (posix_lock_type == F_UNLCK) { + return False; } - SAFE_FREE(entries); + if (lock_flav == POSIX_LOCK) { + /* Only POSIX lock queries need to know the details. */ + *pu_offset = (SMB_BIG_UINT)offset; + *pu_count = (SMB_BIG_UINT)count; + *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK; + } + return True; +} - /* - * No outstanding POSIX locks. Get the pending close fd's - * from the tdb and close them all. - */ +/**************************************************************************** + Next - the functions that deal with in memory database storing representations + of either Windows CIFS locks or POSIX CIFS locks. +****************************************************************************/ - count = get_posix_pending_close_entries(fsp, &fd_array); +/* The key used in the in-memory POSIX databases. */ - if (count) { - DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); +struct lock_ref_count_key { + SMB_DEV_T device; + SMB_INO_T inode; + char r; +}; - for(i = 0; i < count; i++) { - if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) { - saved_errno = errno; - } - } +struct fd_key { + SMB_DEV_T device; + SMB_INO_T inode; +}; - /* - * Delete all fd's stored in the tdb - * for this dev/inode pair. - */ +/******************************************************************* + Form a static locking key for a dev/inode pair for the fd array. +******************************************************************/ - delete_close_entries(fsp); - } +static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode) +{ + static struct fd_key key; + TDB_DATA kbuf; - SAFE_FREE(fd_array); + memset(&key, '\0', sizeof(key)); + key.device = dev; + key.inode = inode; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + return kbuf; +} - /* - * Finally close the fd associated with this fsp. - */ +/******************************************************************* + Form a static locking key for a dev/inode pair for the lock ref count +******************************************************************/ - ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); +static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode) +{ + static struct lock_ref_count_key key; + TDB_DATA kbuf; - if (saved_errno != 0) { - errno = saved_errno; - ret = -1; - } + memset(&key, '\0', sizeof(key)); + key.device = dev; + key.inode = inode; + key.r = 'r'; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + return kbuf; +} - fsp->fh->fd = -1; +/******************************************************************* + Convenience function to get an fd_array key from an fsp. +******************************************************************/ - return ret; +static TDB_DATA fd_array_key_fsp(files_struct *fsp) +{ + return fd_array_key(fsp->dev, fsp->inode); } -/**************************************************************************** - Debugging aid :-). -****************************************************************************/ +/******************************************************************* + Convenience function to get a lock ref count key from an fsp. +******************************************************************/ -static const char *posix_lock_type_name(int lock_type) +static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp) { - return (lock_type == F_RDLCK) ? "READ" : "WRITE"; + return locking_ref_count_key(fsp->dev, fsp->inode); } -/**************************************************************************** - Delete a POSIX lock entry by index number. Used if the tdb add succeeds, but - then the POSIX fcntl lock fails. -****************************************************************************/ +/******************************************************************* + Create the in-memory POSIX lock databases. +********************************************************************/ -static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry) +BOOL posix_locking_init(int read_only) { - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - struct posix_lock *locks; - size_t count; - - dbuf.dptr = NULL; + if (posix_pending_close_tdb) { + return True; + } - dbuf = tdb_fetch(posix_lock_tdb, kbuf); - - if (!dbuf.dptr) { - DEBUG(10,("delete_posix_lock_entry_by_index: tdb_fetch failed !\n")); - goto fail; + if (!posix_pending_close_tdb) { + posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); } - - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); - locks = (struct posix_lock *)dbuf.dptr; - - if (count == 1) { - tdb_delete(posix_lock_tdb, kbuf); - } else { - if (entry < count-1) { - memmove(&locks[entry], &locks[entry+1], sizeof(struct posix_lock)*((count-1) - entry)); - } - dbuf.dsize -= sizeof(struct posix_lock); - tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); + if (!posix_pending_close_tdb) { + DEBUG(0,("Failed to open POSIX pending close database.\n")); + return False; } - SAFE_FREE(dbuf.dptr); + return True; +} + +/******************************************************************* + Delete the in-memory POSIX lock databases. +********************************************************************/ +BOOL posix_locking_end(void) +{ + if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) { + return False; + } return True; +} - fail: +/**************************************************************************** + Next - the functions that deal with storing fd's that have outstanding + POSIX locks when closed. +****************************************************************************/ - SAFE_FREE(dbuf.dptr); - return False; -} +/**************************************************************************** + The records in posix_pending_close_tdb are composed of an array of ints + keyed by dev/ino pair. + The first int is a reference count of the number of outstanding locks on + all open fd's on this dev/ino pair. Any subsequent ints are the fd's that + were open on this dev/ino pair that should have been closed, but can't as + the lock ref count is non zero. +****************************************************************************/ /**************************************************************************** - Add an entry into the POSIX locking tdb. We return the index number of the - added lock (used in case we need to delete *exactly* this entry). Returns - False on fail, True on success. + Keep a reference count of the number of Windows locks open on this dev/ino + pair. Creates entry if it doesn't exist. ****************************************************************************/ -static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *pentry_num) +static void increment_windows_lock_ref_count(files_struct *fsp) { - TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); TDB_DATA dbuf; - struct posix_lock pl; - - dbuf.dptr = NULL; - dbuf.dsize = 0; + int lock_ref_count; - dbuf = tdb_fetch(posix_lock_tdb, kbuf); + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + if (dbuf.dptr == NULL) { + dbuf.dptr = (char *)SMB_MALLOC_P(int); + if (!dbuf.dptr) { + smb_panic("increment_windows_lock_ref_count: malloc fail.\n"); + } + memset(dbuf.dptr, '\0', sizeof(int)); + dbuf.dsize = sizeof(int); + } - *pentry_num = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + lock_ref_count++; + memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); + + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("increment_windows_lock_ref_count: tdb_store_fail.\n"); + } + SAFE_FREE(dbuf.dptr); - /* - * Add new record. - */ + DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n", + fsp->fsp_name, lock_ref_count )); +} - pl.fd = fsp->fh->fd; - pl.start = start; - pl.size = size; - pl.lock_type = lock_type; +static void decrement_windows_lock_ref_count(files_struct *fsp) +{ + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + TDB_DATA dbuf; + int lock_ref_count; - dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock)); + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); if (!dbuf.dptr) { - DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); - goto fail; + smb_panic("decrement_windows_lock_ref_count: logic error.\n"); } - memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock)); - dbuf.dsize += sizeof(struct posix_lock); + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + lock_ref_count--; + memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); - if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name)); - goto fail; + if (lock_ref_count < 0) { + smb_panic("decrement_windows_lock_ref_count: lock_count logic error.\n"); } + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("decrement_windows_lock_ref_count: tdb_store_fail.\n"); + } SAFE_FREE(dbuf.dptr); - DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n", - fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, - (double)fsp->dev, (double)fsp->inode )); - - return True; - - fail: - - SAFE_FREE(dbuf.dptr); - return False; -} - -/**************************************************************************** - Calculate if locks have any overlap at all. -****************************************************************************/ - -static BOOL does_lock_overlap(SMB_OFF_T start1, SMB_OFF_T size1, SMB_OFF_T start2, SMB_OFF_T size2) -{ - if (start1 >= start2 && start1 <= start2 + size2) - return True; - - if (start1 < start2 && start1 + size1 > start2) - return True; - - return False; + DEBUG(10,("decrement_windows_lock_ref_count for file now %s = %d\n", + fsp->fsp_name, lock_ref_count )); } /**************************************************************************** - Delete an entry from the POSIX locking tdb. Returns a copy of the entry being - deleted and the number of records that are overlapped by this one, or -1 on error. + Ensure the lock ref count is zero. ****************************************************************************/ -static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl) +void zero_windows_lock_ref_count(files_struct *fsp) { - TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); TDB_DATA dbuf; - struct posix_lock *locks; - size_t i, count; - BOOL found = False; - int num_overlapping_records = 0; - - dbuf.dptr = NULL; - - dbuf = tdb_fetch(posix_lock_tdb, kbuf); + int lock_ref_count; + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); if (!dbuf.dptr) { - DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n")); - goto fail; + return; } - /* There are existing locks - find a match. */ - locks = (struct posix_lock *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); - - /* - * Search for and delete the first record that matches the - * unlock criteria. - */ - - for (i=0; ifd == fsp->fh->fd && - entry->start == start && - entry->size == size) { - - /* Make a copy */ - *pl = *entry; - - /* Found it - delete it. */ - if (count == 1) { - tdb_delete(posix_lock_tdb, kbuf); - } else { - if (i < count-1) { - memmove(&locks[i], &locks[i+1], sizeof(struct posix_lock)*((count-1) - i)); - } - dbuf.dsize -= sizeof(struct posix_lock); - tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); - } - count--; - found = True; - break; - } + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + if (lock_ref_count < 0) { + smb_panic("zero_windows_lock_ref_count: lock_count logic error.\n"); } - if (!found) - goto fail; - - /* - * Count the number of entries that are - * overlapped by this unlock request. - */ - - for (i = 0; i < count; i++) { - struct posix_lock *entry = &locks[i]; - - if (fsp->fh->fd == entry->fd && - does_lock_overlap( start, size, entry->start, entry->size)) - num_overlapping_records++; + lock_ref_count = 0; + memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); + + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("zero_windows_lock_ref_count: tdb_store_fail.\n"); } - - DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", - posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, - (unsigned int)num_overlapping_records )); - SAFE_FREE(dbuf.dptr); - return num_overlapping_records; - - fail: - - SAFE_FREE(dbuf.dptr); - return -1; + DEBUG(10,("zero_windows_lock_ref_count for file now %s = %d\n", + fsp->fsp_name, lock_ref_count )); } /**************************************************************************** - Utility function to map a lock type correctly depending on the open - mode of a file. + Fetch the lock ref count. ****************************************************************************/ -static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) +static int get_windows_lock_ref_count(files_struct *fsp) { - if((lock_type == WRITE_LOCK) && !fsp->can_write) { - /* - * Many UNIX's cannot get a write lock on a file opened read-only. - * Win32 locking semantics allow this. - * Do the best we can and attempt a read-only lock. - */ - DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n")); - return F_RDLCK; - } -#if 0 - /* We no longer open files write-only. */ - else if((lock_type == READ_LOCK) && !fsp->can_read) { - /* - * Ditto for read locks on write only files. - */ - DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n")); - return F_WRLCK; - } -#endif + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + TDB_DATA dbuf; + int lock_ref_count; - /* - * This return should be the most normal, as we attempt - * to always open files read/write. - */ + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + if (!dbuf.dptr) { + lock_ref_count = 0; + } else { + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + } - return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK; + DEBUG(10,("get_windows_lock_count for file %s = %d\n", + fsp->fsp_name, lock_ref_count )); + return lock_ref_count; } /**************************************************************************** - Check to see if the given unsigned lock range is within the possible POSIX - range. Modifies the given args to be in range if possible, just returns - False if not. + Delete a lock_ref_count entry. ****************************************************************************/ -static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, - SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) +static void delete_windows_lock_ref_count(files_struct *fsp) { - SMB_OFF_T offset = (SMB_OFF_T)u_offset; - SMB_OFF_T count = (SMB_OFF_T)u_count; - - /* - * For the type of system we are, attempt to - * find the maximum positive lock offset as an SMB_OFF_T. - */ - -#if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */ - - SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET); - -#elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); - /* - * In this case SMB_OFF_T is 64 bits, - * and the underlying system can handle 64 bit signed locks. - */ - - SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); - SMB_OFF_T mask = (mask2<<1); - SMB_OFF_T max_positive_lock_offset = ~mask; - -#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + /* Not a bug if it doesn't exist - no locks were ever granted. */ + tdb_delete(posix_pending_close_tdb, kbuf); + DEBUG(10,("delete_windows_lock_ref_count for file %s\n", fsp->fsp_name)); +} - /* - * In this case either SMB_OFF_T is 32 bits, - * or the underlying system cannot handle 64 bit signed locks. - * All offsets & counts must be 2^31 or less. - */ +/**************************************************************************** + Add an fd to the pending close tdb. +****************************************************************************/ - SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF; +static void add_fd_to_close_entry(files_struct *fsp) +{ + TDB_DATA kbuf = fd_array_key_fsp(fsp); + TDB_DATA dbuf; -#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + dbuf.dptr = NULL; + dbuf.dsize = 0; - /* - * POSIX locks of length zero mean lock to end-of-file. - * Win32 locks of length zero are point probes. Ignore - * any Win32 locks of length zero. JRA. - */ + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - if (count == (SMB_OFF_T)0) { - DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n")); - return False; + dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); + if (!dbuf.dptr) { + smb_panic("add_fd_to_close_entry: Realloc fail !\n"); } - /* - * If the given offset was > max_positive_lock_offset then we cannot map this at all - * ignore this lock. - */ + memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int)); + dbuf.dsize += sizeof(int); - if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) { - DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n", - (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) )); - return False; + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("add_fd_to_close_entry: tdb_store_fail.\n"); } - /* - * We must truncate the count to less than max_positive_lock_offset. - */ - - if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) - count = max_positive_lock_offset; + DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n", + fsp->fh->fd, fsp->fsp_name )); - /* - * Truncate count to end at max lock offset. - */ + SAFE_FREE(dbuf.dptr); +} - if (offset + count < 0 || offset + count > max_positive_lock_offset) - count = max_positive_lock_offset - offset; +/**************************************************************************** + Remove all fd entries for a specific dev/inode pair from the tdb. +****************************************************************************/ - /* - * If we ate all the count, ignore this lock. - */ +static void delete_close_entries(files_struct *fsp) +{ + TDB_DATA kbuf = fd_array_key_fsp(fsp); - if (count == 0) { - DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n", - (double)u_offset, (double)u_count )); - return False; + if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) { + smb_panic("delete_close_entries: tdb_delete fail !\n"); } - - /* - * The mapping was successful. - */ - - DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n", - (double)offset, (double)count )); - - *offset_out = offset; - *count_out = count; - - return True; } /**************************************************************************** - Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and - broken NFS implementations. + Get the array of POSIX pending close records for an open fsp. Caller must + free. Returns number of entries. ****************************************************************************/ -static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) { - BOOL ret; - - DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type)); - - ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); - - if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { - - DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", - (double)offset,(double)count)); - DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); - DEBUG(0,("on 32 bit NFS mounted file systems.\n")); + TDB_DATA kbuf = fd_array_key_fsp(fsp); + TDB_DATA dbuf; + size_t count = 0; - /* - * If the offset is > 0x7FFFFFFF then this will cause problems on - * 32 bit NFS mounted filesystems. Just ignore it. - */ + *entries = NULL; + dbuf.dptr = NULL; - if (offset & ~((SMB_OFF_T)0x7fffffff)) { - DEBUG(0,("Offset greater than 31 bits. Returning success.\n")); - return True; - } + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - if (count & ~((SMB_OFF_T)0x7fffffff)) { - /* 32 bit NFS file system, retry with smaller offset */ - DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); - errno = 0; - count &= 0x7fffffff; - ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); - } + if (!dbuf.dptr) { + return 0; } - DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed")); - return ret; + *entries = (int *)dbuf.dptr; + count = (size_t)(dbuf.dsize / sizeof(int)); + + return count; } /**************************************************************************** - Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and - broken NFS implementations. + Deal with pending closes needed by POSIX locking support. + Note that posix_locking_close_file() is expected to have been called + to delete all locks on this fsp before this function is called. ****************************************************************************/ -static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype) +int fd_close_posix(struct connection_struct *conn, files_struct *fsp) { - pid_t pid; - BOOL ret; - - DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n", - fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype)); - - ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); + int saved_errno = 0; + int ret; + int *fd_array = NULL; + size_t count, i; - if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { + if (!lp_locking(SNUM(fsp->conn)) || !lp_posix_locking(SNUM(conn)) || lp_posix_cifsu_locktype()) { + /* + * No locking or POSIX to worry about or we want POSIX semantics + * which will lose all locks on all fd's open on this dev/inode, + * just close. + */ + ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); + fsp->fh->fd = -1; + return ret; + } - DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n", - (double)*poffset,(double)*pcount)); - DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); - DEBUG(0,("on 32 bit NFS mounted file systems.\n")); + if (get_windows_lock_ref_count(fsp)) { /* - * If the offset is > 0x7FFFFFFF then this will cause problems on - * 32 bit NFS mounted filesystems. Just ignore it. + * There are outstanding locks on this dev/inode pair on other fds. + * Add our fd to the pending close tdb and set fsp->fh->fd to -1. */ - if (*poffset & ~((SMB_OFF_T)0x7fffffff)) { - DEBUG(0,("Offset greater than 31 bits. Returning success.\n")); - return True; - } - - if (*pcount & ~((SMB_OFF_T)0x7fffffff)) { - /* 32 bit NFS file system, retry with smaller offset */ - DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); - errno = 0; - *pcount &= 0x7fffffff; - ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); - } + add_fd_to_close_entry(fsp); + fsp->fh->fd = -1; + return 0; } - DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed")); - return ret; -} + /* + * No outstanding locks. Get the pending close fd's + * from the tdb and close them all. + */ + count = get_posix_pending_close_entries(fsp, &fd_array); -/**************************************************************************** - POSIX function to see if a file region is locked. Returns True if the - region is locked, False otherwise. -****************************************************************************/ + if (count) { + DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); -BOOL is_posix_locked(files_struct *fsp, - SMB_BIG_UINT *pu_offset, - SMB_BIG_UINT *pu_count, - enum brl_type *plock_type, - enum brl_flavour lock_flav) -{ - SMB_OFF_T offset; - SMB_OFF_T count; - int posix_lock_type = map_posix_lock_type(fsp,*plock_type); + for(i = 0; i < count; i++) { + if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) { + saved_errno = errno; + } + } - DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) )); + /* + * Delete all fd's stored in the tdb + * for this dev/inode pair. + */ + + delete_close_entries(fsp); + } + + SAFE_FREE(fd_array); + + /* Don't need a lock ref count on this dev/ino anymore. */ + delete_windows_lock_ref_count(fsp); /* - * If the requested lock won't fit in the POSIX range, we will - * never set it, so presume it is not locked. + * Finally close the fd associated with this fsp. */ - if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) { - return False; - } + ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); - if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) { - return False; - } + if (saved_errno != 0) { + errno = saved_errno; + ret = -1; + } - if (posix_lock_type == F_UNLCK) { - return False; - } + fsp->fh->fd = -1; - if (lock_flav == POSIX_LOCK) { - /* Only POSIX lock queries need to know the details. */ - *pu_offset = (SMB_BIG_UINT)offset; - *pu_count = (SMB_BIG_UINT)count; - *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK; - } - return True; + return ret; } +/**************************************************************************** + Next - the functions that deal with the mapping CIFS Windows locks onto + the underlying system POSIX locks. +****************************************************************************/ + /* * Structure used when splitting a lock range * into a POSIX lock range. Doubly linked list. @@ -792,22 +733,14 @@ struct lock_list { understand it :-). ****************************************************************************/ -static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhead, files_struct *fsp) +static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, + struct lock_list *lhead, + const struct lock_context *lock_ctx, /* Lock context lhead belongs to. */ + files_struct *fsp, + const struct lock_struct *plocks, + int num_locks) { - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - struct posix_lock *locks; - size_t num_locks, i; - - dbuf.dptr = NULL; - - dbuf = tdb_fetch(posix_lock_tdb, kbuf); - - if (!dbuf.dptr) - return lhead; - - locks = (struct posix_lock *)dbuf.dptr; - num_locks = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); + int i; /* * Check the current lock list on this dev/inode pair. @@ -818,10 +751,19 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea (double)lhead->start, (double)lhead->size )); for (i=0; ilock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) { + continue; + } + + /* Ignore locks not owned by this process. */ + if (!procid_equal(&lock->context.pid, &lock_ctx->pid)) { + continue; + } + /* * Walk the lock list, checking for overlaps. Note that * the lock list can expand within this loop if the current @@ -830,13 +772,13 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea for (l_curr = lhead; l_curr;) { - DEBUG(10,("posix_lock_list: lock: fd=%d: start=%.0f,size=%.0f:type=%s", lock->fd, + DEBUG(10,("posix_lock_list: lock: fnum=%d: start=%.0f,size=%.0f:type=%s", lock->fnum, (double)lock->start, (double)lock->size, posix_lock_type_name(lock->lock_type) )); if ( (l_curr->start >= (lock->start + lock->size)) || (lock->start >= (l_curr->start + l_curr->size))) { - /* No overlap with this lock - leave this range alone. */ + /* No overlap with existing lock - leave this range alone. */ /********************************************* +---------+ | l_curr | @@ -850,7 +792,7 @@ OR.... +---------+ **********************************************/ - DEBUG(10,("no overlap case.\n" )); + DEBUG(10,(" no overlap case.\n" )); l_curr = l_curr->next; @@ -858,8 +800,8 @@ OR.... (l_curr->start + l_curr->size <= lock->start + lock->size) ) { /* - * This unlock is completely overlapped by this existing lock range - * and thus should have no effect (not be unlocked). Delete it from the list. + * This range is completely overlapped by this existing lock range + * and thus should have no effect. Delete it from the list. */ /********************************************* +---------+ @@ -872,11 +814,12 @@ OR.... /* Save the next pointer */ struct lock_list *ul_next = l_curr->next; - DEBUG(10,("delete case.\n" )); + DEBUG(10,(" delete case.\n" )); DLIST_REMOVE(lhead, l_curr); - if(lhead == NULL) + if(lhead == NULL) { break; /* No more list... */ + } l_curr = ul_next; @@ -885,7 +828,7 @@ OR.... (l_curr->start + l_curr->size > lock->start + lock->size) ) { /* - * This unlock overlaps the existing lock range at the high end. + * This range overlaps the existing lock range at the high end. * Truncate by moving start to existing range end and reducing size. */ /********************************************* @@ -904,7 +847,7 @@ BECOMES.... l_curr->size = (l_curr->start + l_curr->size) - (lock->start + lock->size); l_curr->start = lock->start + lock->size; - DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n", + DEBUG(10,(" truncate high case: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size )); l_curr = l_curr->next; @@ -914,7 +857,7 @@ BECOMES.... (l_curr->start + l_curr->size <= lock->start + lock->size) ) { /* - * This unlock overlaps the existing lock range at the low end. + * This range overlaps the existing lock range at the low end. * Truncate by reducing size. */ /********************************************* @@ -932,7 +875,7 @@ BECOMES.... l_curr->size = lock->start - l_curr->start; - DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n", + DEBUG(10,(" truncate low case: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size )); l_curr = l_curr->next; @@ -940,10 +883,10 @@ BECOMES.... } else if ( (l_curr->start < lock->start) && (l_curr->start + l_curr->size > lock->start + lock->size) ) { /* - * Worst case scenario. Unlock request completely overlaps an existing + * Worst case scenario. Range completely overlaps an existing * lock range. Split the request into two, push the new (upper) request - * into the dlink list, and continue with the entry after ul_new (as we - * know that ul_new will not overlap with this lock). + * into the dlink list, and continue with the entry after l_new (as we + * know that l_new will not overlap with this lock). */ /********************************************* +---------------------------+ @@ -971,7 +914,7 @@ BECOMES..... /* Truncate the l_curr. */ l_curr->size = lock->start - l_curr->start; - DEBUG(10,("split case: curr: start=%.0f,size=%.0f \ + DEBUG(10,(" split case: curr: start=%.0f,size=%.0f \ new: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size, (double)l_new->start, (double)l_new->size )); @@ -1003,34 +946,33 @@ lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size, } /* end for ( l_curr = lhead; l_curr;) */ } /* end for (i=0; ifsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); /* @@ -1038,8 +980,9 @@ BOOL set_posix_lock(files_struct *fsp, * pretend it was successful. */ - if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { return True; + } /* * Windows is very strange. It allows read locks to be overlayed @@ -1056,19 +999,16 @@ BOOL set_posix_lock(files_struct *fsp, * READ LOCK: start =0, len = 10 - OK * * Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but - * would leave a single read lock over the 0-14 region. In order to - * re-create Windows semantics mapped to POSIX locks, we create multiple TDB - * entries, one for each overlayed lock request. We are guarenteed by the brlock - * semantics that if a write lock is added, then it will be first in the array. + * would leave a single read lock over the 0-14 region. */ if ((l_ctx = talloc_init("set_posix_lock")) == NULL) { - DEBUG(0,("set_posix_lock: unable to init talloc context.\n")); + DEBUG(0,("set_posix_lock_windows_flavour: unable to init talloc context.\n")); return True; /* Not a fatal error. */ } if ((ll = TALLOC_P(l_ctx, struct lock_list)) == NULL) { - DEBUG(0,("set_posix_lock: unable to talloc unlock list.\n")); + DEBUG(0,("set_posix_lock_windows_flavour: unable to talloc unlock list.\n")); talloc_destroy(l_ctx); return True; /* Not a fatal error. */ } @@ -1092,19 +1032,12 @@ BOOL set_posix_lock(files_struct *fsp, * POSIX locks. */ - llist = posix_lock_list(l_ctx, llist, fsp); - - /* - * Now we have the list of ranges to lock it is safe to add the - * entry into the POSIX lock tdb. We take note of the entry we - * added here in case we have to remove it on POSIX lock fail. - */ - - if (!add_posix_lock_entry(fsp,offset,count,posix_lock_type,&entry_num)) { - DEBUG(0,("set_posix_lock: Unable to create posix lock entry !\n")); - talloc_destroy(l_ctx); - return False; - } + llist = posix_lock_list(l_ctx, + llist, + lock_ctx, /* Lock context llist belongs to. */ + fsp, + plocks, + num_locks); /* * Add the POSIX locks on the list of ranges returned. @@ -1116,11 +1049,12 @@ BOOL set_posix_lock(files_struct *fsp, offset = ll->start; count = ll->size; - DEBUG(5,("set_posix_lock: Real lock: Type = %s: offset = %.0f, count = %.0f\n", + DEBUG(5,("set_posix_lock_windows_flavour: Real lock: Type = %s: offset = %.0f, count = %.0f\n", posix_lock_type_name(posix_lock_type), (double)offset, (double)count )); if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) { - DEBUG(5,("set_posix_lock: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n", + *errno_ret = errno; + DEBUG(5,("set_posix_lock_windows_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n", posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) )); ret = False; break; @@ -1137,17 +1071,14 @@ BOOL set_posix_lock(files_struct *fsp, offset = ll->start; count = ll->size; - DEBUG(5,("set_posix_lock: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n", + DEBUG(5,("set_posix_lock_windows_flavour: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n", posix_lock_type_name(posix_lock_type), (double)offset, (double)count )); posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK); } - - /* - * Remove the tdb entry for this lock. - */ - - delete_posix_lock_entry_by_index(fsp,entry_num); + } else { + /* Remember the number of Windows locks we have on this dev/ino pair. */ + increment_windows_lock_ref_count(fsp); } talloc_destroy(l_ctx); @@ -1159,7 +1090,13 @@ BOOL set_posix_lock(files_struct *fsp, lock could be released, False if not. ****************************************************************************/ -BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) +BOOL release_posix_lock_windows_flavour(files_struct *fsp, + SMB_BIG_UINT u_offset, + SMB_BIG_UINT u_count, + enum brl_type deleted_lock_type, + const struct lock_context *lock_ctx, + const struct lock_struct *plocks, + int num_locks) { SMB_OFF_T offset; SMB_OFF_T count; @@ -1167,10 +1104,8 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u TALLOC_CTX *ul_ctx = NULL; struct lock_list *ulist = NULL; struct lock_list *ul = NULL; - struct posix_lock deleted_lock; - int num_overlapped_entries; - DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", + DEBUG(5,("release_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f\n", fsp->fsp_name, (double)u_offset, (double)u_count )); /* @@ -1178,43 +1113,20 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u * pretend it was successful. */ - if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { return True; - - /* - * We treat this as one unlock request for POSIX accounting purposes even - * if it may later be split into multiple smaller POSIX unlock ranges. - * num_overlapped_entries is the number of existing locks that have any - * overlap with this unlock request. - */ - - num_overlapped_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock); - - if (num_overlapped_entries == -1) { - smb_panic("release_posix_lock: unable find entry to delete !\n"); } - /* - * If num_overlapped_entries is > 0, and the lock_type we just deleted from the tdb was - * a POSIX write lock, then before doing the unlock we need to downgrade - * the POSIX lock to a read lock. This allows any overlapping read locks - * to be atomically maintained. - */ - - if (num_overlapped_entries > 0 && deleted_lock.lock_type == F_WRLCK) { - if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) { - DEBUG(0,("release_posix_lock: downgrade of lock failed with error %s !\n", strerror(errno) )); - return False; - } - } + /* Remember the number of Windows locks we have on this dev/ino pair. */ + decrement_windows_lock_ref_count(fsp); if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) { - DEBUG(0,("release_posix_lock: unable to init talloc context.\n")); + DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n")); return True; /* Not a fatal error. */ } if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) { - DEBUG(0,("release_posix_lock: unable to talloc unlock list.\n")); + DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n")); talloc_destroy(ul_ctx); return True; /* Not a fatal error. */ } @@ -1239,7 +1151,33 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u * unlocks are performed. */ - ulist = posix_lock_list(ul_ctx, ulist, fsp); + ulist = posix_lock_list(ul_ctx, + ulist, + lock_ctx, /* Lock context ulist belongs to. */ + fsp, + plocks, + num_locks); + + /* + * If there were any overlapped entries (list is > 1 or size or start have changed), + * and the lock_type we just deleted from + * the upper layer tdb was a write lock, then before doing the unlock we need to downgrade + * the POSIX lock to a read lock. This allows any overlapping read locks + * to be atomically maintained. + */ + + if (deleted_lock_type == WRITE_LOCK && + (!ulist || ulist->next != NULL || ulist->start != offset || ulist->size != count)) { + + DEBUG(5,("release_posix_lock_windows_flavour: downgrading lock to READ: offset = %.0f, count = %.0f\n", + (double)offset, (double)count )); + + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) { + DEBUG(0,("release_posix_lock_windows_flavour: downgrade of lock failed with error %s !\n", strerror(errno) )); + talloc_destroy(ul_ctx); + return False; + } + } /* * Release the POSIX locks on the list of ranges returned. @@ -1249,129 +1187,148 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u offset = ulist->start; count = ulist->size; - DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n", + DEBUG(5,("release_posix_lock_windows_flavour: Real unlock: offset = %.0f, count = %.0f\n", (double)offset, (double)count )); - if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) { ret = False; + } } talloc_destroy(ul_ctx); - return ret; } /**************************************************************************** - Remove all lock entries for a specific dev/inode pair from the tdb. + Next - the functions that deal with mapping CIFS POSIX locks onto + the underlying system POSIX locks. ****************************************************************************/ -static void delete_posix_lock_entries(files_struct *fsp) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - - if (tdb_delete(posix_lock_tdb, kbuf) == -1) - DEBUG(0,("delete_close_entries: tdb_delete fail !\n")); -} - /**************************************************************************** - Debug function. + POSIX function to acquire a lock. Returns True if the + lock could be granted, False if not. + As POSIX locks don't stack or conflict (they just overwrite) + we can map the requested lock directly onto a system one. We + know it doesn't conflict with locks on other contexts as the + upper layer would have refused it. ****************************************************************************/ -static void dump_entry(struct posix_lock *pl) +BOOL set_posix_lock_posix_flavour(files_struct *fsp, + SMB_BIG_UINT u_offset, + SMB_BIG_UINT u_count, + enum brl_type lock_type, + int *errno_ret) { - DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n", - (double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd )); + SMB_OFF_T offset; + SMB_OFF_T count; + int posix_lock_type = map_posix_lock_type(fsp,lock_type); + + DEBUG(5,("set_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n", + fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); + + /* + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. + */ + + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { + return True; + } + + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) { + *errno_ret = errno; + DEBUG(5,("set_posix_lock_posix_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n", + posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) )); + return False; + } + return True; } /**************************************************************************** - Remove any locks on this fd. Called from file_close(). + POSIX function to release a lock. Returns True if the + lock could be released, False if not. + We are given a complete lock state from the upper layer which is what the lock + state should be after the unlock has already been done, so what + we do is punch out holes in the unlock range where locks owned by this process + have a different lock context. ****************************************************************************/ -void posix_locking_close_file(files_struct *fsp) +BOOL release_posix_lock_posix_flavour(files_struct *fsp, + SMB_BIG_UINT u_offset, + SMB_BIG_UINT u_count, + const struct lock_context *lock_ctx, + const struct lock_struct *plocks, + int num_locks) { - struct posix_lock *entries = NULL; - size_t count, i; + BOOL ret = True; + SMB_OFF_T offset; + SMB_OFF_T count; + TALLOC_CTX *ul_ctx = NULL; + struct lock_list *ulist = NULL; + struct lock_list *ul = NULL; + + DEBUG(5,("release_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f\n", + fsp->fsp_name, (double)u_offset, (double)u_count )); /* - * Optimization for the common case where we are the only - * opener of a file. If all fd entries are our own, we don't - * need to explicitly release all the locks via the POSIX functions, - * we can just remove all the entries in the tdb and allow the - * close to remove the real locks. + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. */ - count = get_posix_lock_entries(fsp, &entries); - - if (count == 0) { - DEBUG(10,("posix_locking_close_file: file %s has no outstanding locks.\n", fsp->fsp_name )); - return; + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { + return True; } - for (i = 0; i < count; i++) { - if (entries[i].fd != fsp->fh->fd ) - break; - - dump_entry(&entries[i]); + if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) { + DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n")); + return False; } - if (i == count) { - /* All locks are ours. */ - DEBUG(10,("posix_locking_close_file: file %s has %u outstanding locks, but all on one fd.\n", - fsp->fsp_name, (unsigned int)count )); - SAFE_FREE(entries); - delete_posix_lock_entries(fsp); - return; + if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) { + DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n")); + talloc_destroy(ul_ctx); + return False; } /* - * Difficult case. We need to delete all our locks, whilst leaving - * all other POSIX locks in place. + * Create the initial list entry containing the + * lock we want to remove. */ - for (i = 0; i < count; i++) { - struct posix_lock *pl = &entries[i]; - if (pl->fd == fsp->fh->fd) - release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size ); - } - SAFE_FREE(entries); -} + ZERO_STRUCTP(ul); + ul->start = offset; + ul->size = count; -/******************************************************************* - Create the in-memory POSIX lock databases. -********************************************************************/ + DLIST_ADD(ulist, ul); -BOOL posix_locking_init(int read_only) -{ - if (posix_lock_tdb && posix_pending_close_tdb) - return True; - - if (!posix_lock_tdb) - posix_lock_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); - if (!posix_lock_tdb) { - DEBUG(0,("Failed to open POSIX byte range locking database.\n")); - return False; - } - if (!posix_pending_close_tdb) - posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); - if (!posix_pending_close_tdb) { - DEBUG(0,("Failed to open POSIX pending close database.\n")); - return False; - } + /* + * Walk the given array creating a linked list + * of unlock requests. + */ - return True; -} + ulist = posix_lock_list(ul_ctx, + ulist, + lock_ctx, /* Lock context ulist belongs to. */ + fsp, + plocks, + num_locks); -/******************************************************************* - Delete the in-memory POSIX lock databases. -********************************************************************/ + /* + * Release the POSIX locks on the list of ranges returned. + */ -BOOL posix_locking_end(void) -{ - if (posix_lock_tdb && tdb_close(posix_lock_tdb) != 0) - return False; - if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) - return False; + for(; ulist; ulist = ulist->next) { + offset = ulist->start; + count = ulist->size; + + DEBUG(5,("release_posix_lock_posix_flavour: Real unlock: offset = %.0f, count = %.0f\n", + (double)offset, (double)count )); + + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) { + ret = False; + } + } + + talloc_destroy(ul_ctx); return True; } -- cgit From 297df32751fbc64a053700241dae2ac9c0fc4968 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Jul 2006 06:56:43 +0000 Subject: r16973: Fix subtle logic error in lock ref counting found by cifsfs client code. Jeremy. (This used to be commit 53094435d89088124041d57078c21a12e761e2bf) --- source3/locking/brlock.c | 8 ++++---- source3/locking/posix.c | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 9c8a7a17ee..eb325fe053 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1229,7 +1229,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) struct process_id pid = procid_self(); BOOL unlock_individually = False; - if(lp_posix_locking(fsp->conn->cnum) && !lp_posix_cifsu_locktype()) { + if(lp_posix_locking(fsp->conn->cnum)) { /* Check if there are any Windows locks associated with this dev/ino pair that are not this fnum. If so we need to call unlock on each @@ -1280,9 +1280,6 @@ void brl_close_fnum(struct byte_range_lock *br_lck) /* We can bulk delete - any POSIX locks will be removed when the fd closes. */ - /* Zero any lock reference count on this dev/ino pair. */ - zero_windows_lock_ref_count(fsp); - /* Remove any existing locks for this fnum (or any fnum if they're POSIX). */ for (i=0; i < br_lck->num_locks; i++) { @@ -1336,6 +1333,9 @@ void brl_close_fnum(struct byte_range_lock *br_lck) dcount++; } } + + /* Reduce the lock reference count on this dev/ino pair. */ + reduce_windows_lock_ref_count(fsp, dcount); } /**************************************************************************** diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 59b62170e8..10845f9575 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -492,10 +492,10 @@ static void decrement_windows_lock_ref_count(files_struct *fsp) } /**************************************************************************** - Ensure the lock ref count is zero. + Bulk delete - subtract as many locks as we've just deleted. ****************************************************************************/ -void zero_windows_lock_ref_count(files_struct *fsp) +void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount) { TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); TDB_DATA dbuf; @@ -507,19 +507,19 @@ void zero_windows_lock_ref_count(files_struct *fsp) } memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + lock_ref_count -= dcount; + if (lock_ref_count < 0) { - smb_panic("zero_windows_lock_ref_count: lock_count logic error.\n"); + smb_panic("reduce_windows_lock_ref_count: lock_count logic error.\n"); } - - lock_ref_count = 0; memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - smb_panic("zero_windows_lock_ref_count: tdb_store_fail.\n"); + smb_panic("reduce_windows_lock_ref_count: tdb_store_fail.\n"); } SAFE_FREE(dbuf.dptr); - DEBUG(10,("zero_windows_lock_ref_count for file now %s = %d\n", + DEBUG(10,("reduce_windows_lock_ref_count for file now %s = %d\n", fsp->fsp_name, lock_ref_count )); } -- cgit From 17222261895b8c82eb5458bc66dab6712930d5a3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Jul 2006 16:32:02 +0000 Subject: r16987: Fix the logic errors in ref-counting Windows locks. Hopefully will fix the build farm. Still a few errors in RAW-LOCK to look at though... Jeremy. (This used to be commit edd72d37de570fdad09f7ee983b5b22a1613e558) --- source3/locking/brlock.c | 8 ++++++-- source3/locking/posix.c | 15 ++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index eb325fe053..e99d4ab900 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1225,6 +1225,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) uint16 tid = fsp->conn->cnum; int fnum = fsp->fnum; unsigned int i, j, dcount=0; + int num_deleted_windows_locks = 0; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; struct process_id pid = procid_self(); BOOL unlock_individually = False; @@ -1289,6 +1290,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid)) { if ((lock->lock_flav == WINDOWS_LOCK) && (lock->fnum == fnum)) { del_this_lock = True; + num_deleted_windows_locks++; } else if (lock->lock_flav == POSIX_LOCK) { del_this_lock = True; } @@ -1334,8 +1336,10 @@ void brl_close_fnum(struct byte_range_lock *br_lck) } } - /* Reduce the lock reference count on this dev/ino pair. */ - reduce_windows_lock_ref_count(fsp, dcount); + if (num_deleted_windows_locks) { + /* Reduce the Windows lock reference count on this dev/ino pair. */ + reduce_windows_lock_ref_count(fsp, num_deleted_windows_locks); + } } /**************************************************************************** diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 10845f9575..475ab61a2f 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -981,6 +981,7 @@ BOOL set_posix_lock_windows_flavour(files_struct *fsp, */ if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { + increment_windows_lock_ref_count(fsp); return True; } @@ -1004,13 +1005,13 @@ BOOL set_posix_lock_windows_flavour(files_struct *fsp, if ((l_ctx = talloc_init("set_posix_lock")) == NULL) { DEBUG(0,("set_posix_lock_windows_flavour: unable to init talloc context.\n")); - return True; /* Not a fatal error. */ + return False; } if ((ll = TALLOC_P(l_ctx, struct lock_list)) == NULL) { DEBUG(0,("set_posix_lock_windows_flavour: unable to talloc unlock list.\n")); talloc_destroy(l_ctx); - return True; /* Not a fatal error. */ + return False; } /* @@ -1108,6 +1109,9 @@ BOOL release_posix_lock_windows_flavour(files_struct *fsp, DEBUG(5,("release_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f\n", fsp->fsp_name, (double)u_offset, (double)u_count )); + /* Remember the number of Windows locks we have on this dev/ino pair. */ + decrement_windows_lock_ref_count(fsp); + /* * If the requested lock won't fit in the POSIX range, we will * pretend it was successful. @@ -1117,18 +1121,15 @@ BOOL release_posix_lock_windows_flavour(files_struct *fsp, return True; } - /* Remember the number of Windows locks we have on this dev/ino pair. */ - decrement_windows_lock_ref_count(fsp); - if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) { DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n")); - return True; /* Not a fatal error. */ + return False; } if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) { DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n")); talloc_destroy(ul_ctx); - return True; /* Not a fatal error. */ + return False; } /* -- cgit From 8dbe2651d3c390250f6c959be4475b7ab3d22137 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Jul 2006 19:23:45 +0000 Subject: r16992: Fix bug #3922 reported by jason@ncac.gwu.edu, correctly look at the return code. Jeremy. (This used to be commit f11933b3ac91c6fbacd6b410f4d2c0d400df23ee) --- source3/locking/posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 475ab61a2f..9d5c42a1bc 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -1331,5 +1331,5 @@ BOOL release_posix_lock_posix_flavour(files_struct *fsp, } talloc_destroy(ul_ctx); - return True; + return ret; } -- cgit From 75a2f4dbc895f4f43564941a8478257f4e75ea22 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Jul 2006 21:57:54 +0000 Subject: r17000: Allow CIFS POSIX locks to coexist with Windows locks. We shouldn't allow this on the same smbd, but the cifsfs client negotiates POSIX locks then sends Windows ones. Doh ! Can't fix shipped client code.... Jeremy. (This used to be commit 2f8cabe98d3776cb0bdf6b4ef1490fe0119e260a) --- source3/locking/posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 9d5c42a1bc..9a50f55c09 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -642,7 +642,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) int *fd_array = NULL; size_t count, i; - if (!lp_locking(SNUM(fsp->conn)) || !lp_posix_locking(SNUM(conn)) || lp_posix_cifsu_locktype()) { + if (!lp_locking(SNUM(fsp->conn)) || !lp_posix_locking(SNUM(conn))) { /* * No locking or POSIX to worry about or we want POSIX semantics * which will lose all locks on all fd's open on this dev/inode, -- cgit From d22d540c326f4964566f1c3dcb72df7986782215 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Jul 2006 23:23:39 +0000 Subject: r17041: Trying to track down a *big* memory leak in the new lock code. Fix a small one first.... (easy to valgrind). Jeremy (This used to be commit 43d24fbd41ed745a5b21514b526e655663c509ee) --- source3/locking/brlock.c | 2 +- source3/locking/posix.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index e99d4ab900..376c2e30ba 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1259,7 +1259,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) /* Copy the current lock array. */ locks_copy = TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); if (!locks_copy) { - DEBUG(0,("brl_close_fnum: talloc fail.\n")); + smb_panic("brl_close_fnum: talloc fail.\n"); } for (i=0; i < br_lck->num_locks; i++) { diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 9a50f55c09..586de5745b 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -539,6 +539,7 @@ static int get_windows_lock_ref_count(files_struct *fsp) } else { memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); } + SAFE_FREE(dbuf.dptr); DEBUG(10,("get_windows_lock_count for file %s = %d\n", fsp->fsp_name, lock_ref_count )); -- cgit From ad673ea988cdfe2b596f128e616f7cd57fedf33d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 15 Jul 2006 00:05:47 +0000 Subject: r17043: Fix memleak when processing CIFS POSIX lock/unlock requests. Maybe the Linux kernel OOM killer will be kinder to smbd now :-). Back to tdbtorture tests on cifsfs. Jeremy. (This used to be commit 1201383e7ab2413795a395491af0a4d3877b1c8b) --- source3/locking/brlock.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 376c2e30ba..c048ef3005 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -666,6 +666,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, return NT_STATUS_NO_MEMORY; } br_lck->num_locks = count; + SAFE_FREE(br_lck->lock_data); br_lck->lock_data = (void *)tp; br_lck->modified = True; return NT_STATUS_OK; @@ -977,6 +978,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s } br_lck->num_locks = count; + SAFE_FREE(br_lck->lock_data); br_lck->lock_data = (void *)tp; br_lck->modified = True; @@ -1052,7 +1054,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck, BOOL ret = True; unsigned int i; struct lock_struct lock; - struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + const struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; files_struct *fsp = br_lck->fsp; lock.context.smbpid = smbpid; @@ -1109,7 +1111,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, { unsigned int i; struct lock_struct lock; - struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + const struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; files_struct *fsp = br_lck->fsp; lock.context.smbpid = *psmbpid; @@ -1123,7 +1125,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, /* Make sure existing locks don't conflict */ for (i=0; i < br_lck->num_locks; i++) { - struct lock_struct *exlock = &locks[i]; + const struct lock_struct *exlock = &locks[i]; BOOL conflict = False; if (exlock->lock_flav == WINDOWS_LOCK) { @@ -1163,7 +1165,6 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, return NT_STATUS_OK; } - /**************************************************************************** Remove a particular pending lock. ****************************************************************************/ -- cgit From 354e444ee3dcd5745d94d299edef4726941efb8f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 15 Jul 2006 00:34:08 +0000 Subject: r17046: Ensure we're using the right pointers ... Jeremy. (This used to be commit a8df1863bf2817a82a55c816ba1f685828c5b6ec) --- source3/locking/brlock.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index c048ef3005..9edac7203b 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -723,7 +723,7 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, Check if an unlock overlaps a pending lock. ****************************************************************************/ -static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pend_lock) +static BOOL brl_pending_overlap(const struct lock_struct *lock, const struct lock_struct *pend_lock) { if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start)) return True; @@ -739,7 +739,6 @@ static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pe static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock_struct *plock) { unsigned int i, j; - struct lock_struct *lock = NULL; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */ @@ -748,7 +747,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock is sorted in the zero zero case. */ for (i = 0; i < br_lck->num_locks; i++) { - lock = &locks[i]; + struct lock_struct *lock = &locks[i]; if (lock->lock_type == WRITE_LOCK && brl_same_context(&lock->context, &plock->context) && @@ -770,7 +769,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock #endif for (i = 0; i < br_lck->num_locks; i++) { - lock = &locks[i]; + struct lock_struct *lock = &locks[i]; /* Only remove our own locks that match in start, size, and flavour. */ if (brl_same_context(&lock->context, &plock->context) && @@ -822,7 +821,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock } /* We could send specific lock info here... */ - if (brl_pending_overlap(lock, pend_lock)) { + if (brl_pending_overlap(plock, pend_lock)) { DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", procid_str_static(&pend_lock->context.pid ))); @@ -844,7 +843,6 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_struct *plock) { unsigned int i, j, count; - struct lock_struct *lock = NULL; struct lock_struct *tp; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; BOOL overlap_found = False; @@ -873,12 +871,11 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s count = 0; for (i = 0; i < br_lck->num_locks; i++) { + struct lock_struct *lock = &locks[i]; struct lock_struct tmp_lock[3]; BOOL lock_was_added = False; unsigned int tmp_count; - lock = &locks[i]; - /* Only remove our own locks - ignore fnum. */ if (lock->lock_type == PENDING_LOCK || !brl_same_context(&lock->context, &plock->context)) { @@ -979,11 +976,10 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s br_lck->num_locks = count; SAFE_FREE(br_lck->lock_data); - br_lck->lock_data = (void *)tp; + locks = br_lck->lock_data = (void *)tp; br_lck->modified = True; /* Send unlock messages to any pending waiters that overlap. */ - locks = tp; for (j=0; j < br_lck->num_locks; j++) { struct lock_struct *pend_lock = &locks[j]; @@ -994,7 +990,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s } /* We could send specific lock info here... */ - if (brl_pending_overlap(lock, pend_lock)) { + if (brl_pending_overlap(plock, pend_lock)) { DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", procid_str_static(&pend_lock->context.pid ))); -- cgit From e1da1fcf12164f50f3462c90f0bb785d18c59b0b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Jul 2006 21:09:02 +0000 Subject: r17098: Samba3 now cleanly passes Samba4 RAW-LOCK torture test. Phew - that was painful :-). But what it means is that we now implement lock cancels and I can add lock cancels into POSIX lock handling which will fix the fast/slow system call issue with cifsfs ! Jeremy. (This used to be commit f1a9cf075b87c76c032d19da0168424c90f6cb3c) --- source3/locking/brlock.c | 57 +++++++++++--------------- source3/locking/locking.c | 102 +++++++++++++++++++++------------------------- 2 files changed, 70 insertions(+), 89 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 9edac7203b..f251ff57ec 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -211,30 +211,34 @@ static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock } /**************************************************************************** - Amazingly enough, w2k3 "remembers" whether the last lock failure + Amazingly enough, w2k3 "remembers" whether the last lock failure on a fnum is the same as this one and changes its error code. I wonder if any app depends on this ? ****************************************************************************/ -static NTSTATUS brl_lock_failed(const struct lock_struct *lock) +static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, int32 lock_timeout) { - static struct lock_struct last_lock_failure; - - if (brl_same_context(&lock->context, &last_lock_failure.context) && - lock->fnum == last_lock_failure.fnum && - lock->start == last_lock_failure.start && - lock->size == last_lock_failure.size) { - return NT_STATUS_FILE_LOCK_CONFLICT; - } - last_lock_failure = *lock; - if (lock->start >= 0xEF000000 && - (lock->start >> 63) == 0) { + if (lock->start >= 0xEF000000 && (lock->start >> 63) == 0) { /* amazing the little things you learn with a test suite. Locks beyond this offset (as a 64 bit number!) always generate the conflict error code, unless the top bit is set */ + if (lock_timeout == 0) { + fsp->last_lock_failure = *lock; + } + return NT_STATUS_FILE_LOCK_CONFLICT; + } + + if (procid_equal(&lock->context.pid, &fsp->last_lock_failure.context.pid) && + lock->context.tid == fsp->last_lock_failure.context.tid && + lock->fnum == fsp->last_lock_failure.fnum && + lock->start == fsp->last_lock_failure.start) { return NT_STATUS_FILE_LOCK_CONFLICT; } + + if (lock_timeout == 0) { + fsp->last_lock_failure = *lock; + } return NT_STATUS_LOCK_NOT_GRANTED; } @@ -293,8 +297,7 @@ static int lock_compare(const struct lock_struct *lck1, ****************************************************************************/ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, - const struct lock_struct *plock, - BOOL *my_lock_ctx) + const struct lock_struct *plock, int32 lock_timeout) { unsigned int i; files_struct *fsp = br_lck->fsp; @@ -303,12 +306,7 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, for (i=0; i < br_lck->num_locks; i++) { /* Do any Windows or POSIX locks conflict ? */ if (brl_conflict(&locks[i], plock)) { - NTSTATUS status = brl_lock_failed(plock);; - /* Did we block ourselves ? */ - if (brl_same_context(&locks[i].context, &plock->context)) { - *my_lock_ctx = True; - } - return status; + return brl_lock_failed(fsp,plock,lock_timeout); } #if ZERO_ZERO if (plock->start == 0 && plock->size == 0 && @@ -571,8 +569,7 @@ OR ****************************************************************************/ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, - const struct lock_struct *plock, - BOOL *my_lock_ctx) + const struct lock_struct *plock) { unsigned int i, count; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; @@ -604,10 +601,6 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, if (locks[i].lock_flav == WINDOWS_LOCK) { /* Do any Windows flavour locks conflict ? */ if (brl_conflict(&locks[i], plock)) { - /* Did we block ourselves ? */ - if (brl_same_context(&locks[i].context, &plock->context)) { - *my_lock_ctx = True; - } /* No games with error messages. */ SAFE_FREE(tp); return NT_STATUS_FILE_LOCK_CONFLICT; @@ -683,13 +676,11 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, br_off size, enum brl_type lock_type, enum brl_flavour lock_flav, - BOOL *my_lock_ctx) + int32 lock_timeout) { NTSTATUS ret; struct lock_struct lock; - *my_lock_ctx = False; - #if !ZERO_ZERO if (start == 0 && size == 0) { DEBUG(0,("client sent 0/0 lock - please report this\n")); @@ -706,9 +697,9 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, lock.lock_flav = lock_flav; if (lock_flav == WINDOWS_LOCK) { - ret = brl_lock_windows(br_lck, &lock, my_lock_ctx); + ret = brl_lock_windows(br_lck, &lock, lock_timeout); } else { - ret = brl_lock_posix(br_lck, &lock, my_lock_ctx); + ret = brl_lock_posix(br_lck, &lock); } #if ZERO_ZERO @@ -1165,7 +1156,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, Remove a particular pending lock. ****************************************************************************/ -BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck, +BOOL brl_lock_cancel(struct byte_range_lock *br_lck, uint32 smbpid, struct process_id pid, br_off start, diff --git a/source3/locking/locking.c b/source3/locking/locking.c index ac50c9b648..cd1d9547f3 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -185,7 +185,7 @@ NTSTATUS do_lock(files_struct *fsp, SMB_BIG_UINT offset, enum brl_type lock_type, enum brl_flavour lock_flav, - BOOL *my_lock_ctx) + int32 lock_timeout) { struct byte_range_lock *br_lck = NULL; NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED; @@ -216,76 +216,63 @@ NTSTATUS do_lock(files_struct *fsp, count, lock_type, lock_flav, - my_lock_ctx); + lock_timeout); TALLOC_FREE(br_lck); return status; } /**************************************************************************** - Utility function called by locking requests. This is *DISGUSTING*. It also - appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000 - is so slow on the locking tests...... ? This is the reason. Much though I hate - it, we need this. JRA. + Utility function called by unlocking requests. ****************************************************************************/ -NTSTATUS do_lock_spin(files_struct *fsp, +NTSTATUS do_unlock(files_struct *fsp, uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, - enum brl_type lock_type, - enum brl_flavour lock_flav, - BOOL *my_lock_ctx) + enum brl_flavour lock_flav) { - int j, maxj = lp_lock_spin_count(); - int sleeptime = lp_lock_sleep_time(); - NTSTATUS status, ret; - - if (maxj <= 0) { - maxj = 1; + BOOL ok = False; + struct byte_range_lock *br_lck = NULL; + + if (!fsp->can_lock) { + return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } + + if (!lp_locking(SNUM(fsp->conn))) { + return NT_STATUS_OK; + } + + DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n", + (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - ret = NT_STATUS_OK; /* to keep dumb compilers happy */ - - for (j = 0; j < maxj; j++) { - status = do_lock(fsp, - lock_pid, - count, - offset, - lock_type, - lock_flav, - my_lock_ctx); - - if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) && - !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { - return status; - } - /* if we do fail then return the first error code we got */ - if (j == 0) { - ret = status; - /* Don't spin if we blocked ourselves. */ - if (*my_lock_ctx) { - return ret; - } + br_lck = brl_get_locks(NULL, fsp); + if (!br_lck) { + return NT_STATUS_NO_MEMORY; + } - /* Only spin for Windows locks. */ - if (lock_flav == POSIX_LOCK) { - return ret; - } - } + ok = brl_unlock(br_lck, + lock_pid, + procid_self(), + offset, + count, + lock_flav); + + TALLOC_FREE(br_lck); - if (sleeptime) { - sys_usleep(sleeptime); - } + if (!ok) { + DEBUG(10,("do_unlock: returning ERRlock.\n" )); + return NT_STATUS_RANGE_NOT_LOCKED; } - return ret; + + return NT_STATUS_OK; } /**************************************************************************** - Utility function called by unlocking requests. + Cancel any pending blocked locks. ****************************************************************************/ -NTSTATUS do_unlock(files_struct *fsp, +NTSTATUS do_lock_cancel(files_struct *fsp, uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, @@ -295,14 +282,15 @@ NTSTATUS do_unlock(files_struct *fsp, struct byte_range_lock *br_lck = NULL; if (!fsp->can_lock) { - return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; + return fsp->is_directory ? + NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } if (!lp_locking(SNUM(fsp->conn))) { - return NT_STATUS_OK; + return NT_STATUS_DOS(ERRDOS, ERRcancelviolation); } - - DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n", + + DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for fnum %d file %s\n", (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); br_lck = brl_get_locks(NULL, fsp); @@ -310,7 +298,7 @@ NTSTATUS do_unlock(files_struct *fsp, return NT_STATUS_NO_MEMORY; } - ok = brl_unlock(br_lck, + ok = brl_lock_cancel(br_lck, lock_pid, procid_self(), offset, @@ -320,8 +308,8 @@ NTSTATUS do_unlock(files_struct *fsp, TALLOC_FREE(br_lck); if (!ok) { - DEBUG(10,("do_unlock: returning ERRlock.\n" )); - return NT_STATUS_RANGE_NOT_LOCKED; + DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" )); + return NT_STATUS_DOS(ERRDOS, ERRcancelviolation); } return NT_STATUS_OK; @@ -340,7 +328,9 @@ void locking_close_file(files_struct *fsp) } br_lck = brl_get_locks(NULL,fsp); + if (br_lck) { + cancel_pending_lock_requests_by_fid(fsp, br_lck); brl_close_fnum(br_lck); TALLOC_FREE(br_lck); } -- cgit From b737f26764cce935d9482335ece11c71a96720f4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Jul 2006 01:05:51 +0000 Subject: r17105: Fix the race Volker found - we had a non-locked region between detecting a pending lock was needed and when we added the blocking lock record. Make sure that we hold the lock over all this period. Removed the old code for doing blocking locks on SMB requests that never block (the old SMBlock and friends). Discovered something interesting about the strange NT_STATUS_FILE_LOCK_CONFLICT return. If we asked for a lock with zero timeout, and we got an error of NT_STATUS_FILE_LOCK_CONFLICT, treat it as though it was a blocking lock with a timeout of 150 - 300ms. This only happens when timeout is sent as zero and can be seen quite clearly in ethereal. This is the real replacement for old do_lock_spin() code. Re-worked the blocking lock select timeout to correctly use milliseconds instead of the old second level resolution (far too coarse for this work). Jeremy. (This used to be commit b81d6d1ae95a3d3e449dde629884b565eac289d9) --- source3/locking/brlock.c | 14 +++++++------- source3/locking/locking.c | 22 ++++++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index f251ff57ec..20bb4314b6 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -216,14 +216,14 @@ static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock app depends on this ? ****************************************************************************/ -static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, int32 lock_timeout) +static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, BOOL blocking_lock) { if (lock->start >= 0xEF000000 && (lock->start >> 63) == 0) { /* amazing the little things you learn with a test suite. Locks beyond this offset (as a 64 bit number!) always generate the conflict error code, unless the top bit is set */ - if (lock_timeout == 0) { + if (!blocking_lock) { fsp->last_lock_failure = *lock; } return NT_STATUS_FILE_LOCK_CONFLICT; @@ -236,7 +236,7 @@ static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *loc return NT_STATUS_FILE_LOCK_CONFLICT; } - if (lock_timeout == 0) { + if (!blocking_lock) { fsp->last_lock_failure = *lock; } return NT_STATUS_LOCK_NOT_GRANTED; @@ -297,7 +297,7 @@ static int lock_compare(const struct lock_struct *lck1, ****************************************************************************/ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, - const struct lock_struct *plock, int32 lock_timeout) + const struct lock_struct *plock, BOOL blocking_lock) { unsigned int i; files_struct *fsp = br_lck->fsp; @@ -306,7 +306,7 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, for (i=0; i < br_lck->num_locks; i++) { /* Do any Windows or POSIX locks conflict ? */ if (brl_conflict(&locks[i], plock)) { - return brl_lock_failed(fsp,plock,lock_timeout); + return brl_lock_failed(fsp,plock,blocking_lock); } #if ZERO_ZERO if (plock->start == 0 && plock->size == 0 && @@ -676,7 +676,7 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, br_off size, enum brl_type lock_type, enum brl_flavour lock_flav, - int32 lock_timeout) + BOOL blocking_lock) { NTSTATUS ret; struct lock_struct lock; @@ -697,7 +697,7 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, lock.lock_flav = lock_flav; if (lock_flav == WINDOWS_LOCK) { - ret = brl_lock_windows(br_lck, &lock, lock_timeout); + ret = brl_lock_windows(br_lck, &lock, blocking_lock); } else { ret = brl_lock_posix(br_lck, &lock); } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index cd1d9547f3..a7cadd3a40 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -179,23 +179,25 @@ NTSTATUS query_lock(files_struct *fsp, Utility function called by locking requests. ****************************************************************************/ -NTSTATUS do_lock(files_struct *fsp, +struct byte_range_lock *do_lock(files_struct *fsp, uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, enum brl_type lock_type, enum brl_flavour lock_flav, - int32 lock_timeout) + BOOL blocking_lock, + NTSTATUS *perr) { struct byte_range_lock *br_lck = NULL; - NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED; if (!fsp->can_lock) { - return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; + *perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; + return NULL; } if (!lp_locking(SNUM(fsp->conn))) { - return NT_STATUS_OK; + *perr = NT_STATUS_OK; + return NULL; } /* NOTE! 0 byte long ranges ARE allowed and should be stored */ @@ -206,20 +208,20 @@ NTSTATUS do_lock(files_struct *fsp, br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { - return NT_STATUS_NO_MEMORY; + *perr = NT_STATUS_NO_MEMORY; + return NULL; } - status = brl_lock(br_lck, + *perr = brl_lock(br_lck, lock_pid, procid_self(), offset, count, lock_type, lock_flav, - lock_timeout); + blocking_lock); - TALLOC_FREE(br_lck); - return status; + return br_lck; } /**************************************************************************** -- cgit From e0c68d0a1d591e4285746a8af70040448752a735 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 21 Jul 2006 14:13:30 +0000 Subject: r17177: Get rid of a global variable by adding a private data pointer to share_mode_forall(). Volker (This used to be commit f97f6cedffdc4d10afcac90a163b93a801acf514) --- source3/locking/locking.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index a7cadd3a40..3cbf318007 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1249,15 +1249,23 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE return True; } +struct forall_state { + void (*fn)(const struct share_mode_entry *entry, + const char *sharepath, + const char *fname, + void *private_data); + void *private_data; +}; + static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, - void *state) + void *_state) { + struct forall_state *state = (struct forall_state *)_state; struct locking_data *data; struct share_mode_entry *shares; const char *sharepath; const char *fname; int i; - LOCKING_FN(traverse_callback) = (LOCKING_FN_CAST())state; /* Ensure this is a locking_key record. */ if (kbuf.dsize != sizeof(struct locking_key)) @@ -1274,7 +1282,8 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, strlen(sharepath) + 1; for (i=0;iu.s.num_share_mode_entries;i++) { - traverse_callback(&shares[i], sharepath, fname); + state->fn(&shares[i], sharepath, fname, + state->private_data); } return 0; } @@ -1284,9 +1293,17 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, share mode system. ********************************************************************/ -int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, const char *)) +int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, + const char *, void *), + void *private_data) { + struct forall_state state; + if (tdb == NULL) return 0; - return tdb_traverse(tdb, traverse_fn, (void *)fn); + + state.fn = fn; + state.private_data = private_data; + + return tdb_traverse(tdb, traverse_fn, (void *)&state); } -- cgit From 7f5f781fe90c16f5d6b70962d45ed2a8e8c641d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Jul 2006 22:02:54 +0000 Subject: r17181: Fix the build farm RAW-READ bug. When making a copy of the lock array in order to delete them individually it's also important to make a copy of the *size* of this array. Otherwise the unlock decrements the termination index of your for loop :-). Doh ! Big thanks to Volker for showing me how to set up the build farm to track this one down. This is not a 3.0.23a issue. Jeremy. (This used to be commit 2c82a159ae6a4cc83989f2b453508358db516d67) --- source3/locking/brlock.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 20bb4314b6..07e4b4c16b 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1243,14 +1243,16 @@ void brl_close_fnum(struct byte_range_lock *br_lck) if (unlock_individually) { struct lock_struct *locks_copy; + unsigned int num_locks_copy; /* Copy the current lock array. */ locks_copy = TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); if (!locks_copy) { smb_panic("brl_close_fnum: talloc fail.\n"); } + num_locks_copy = br_lck->num_locks; - for (i=0; i < br_lck->num_locks; i++) { + for (i=0; i < num_locks_copy; i++) { struct lock_struct *lock = &locks_copy[i]; if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid) && -- cgit From 54cdd1dfe23219c3cc9c772b78fbd40e144957c6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Jul 2006 15:23:46 +0000 Subject: r17276: Don't change the POSIX lock ref count if posix locking = no. Jeremy. (This used to be commit 42dec2192c1261090f2fac7a123c384f5c133587) --- source3/locking/brlock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 07e4b4c16b..5ce8a3730b 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1326,8 +1326,8 @@ void brl_close_fnum(struct byte_range_lock *br_lck) } } - if (num_deleted_windows_locks) { - /* Reduce the Windows lock reference count on this dev/ino pair. */ + if(lp_posix_locking(fsp->conn->cnum) && num_deleted_windows_locks) { + /* Reduce the Windows lock POSIX reference count on this dev/ino pair. */ reduce_windows_lock_ref_count(fsp, num_deleted_windows_locks); } } -- cgit From d30bcf9c485eb0447cbae56318c4134e490693c5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 27 Jul 2006 17:23:57 +0000 Subject: r17279: conn->cnum is the tid we've given to the client. This has nothing to do with our internal share number. Funny that it worked at all :-) Volker (This used to be commit afa6e9094604afe1ef929cd936fbfa07b5473fd2) --- source3/locking/brlock.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 5ce8a3730b..031836ecdf 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -792,7 +792,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock br_lck->modified = True; /* Unlock the underlying POSIX regions. */ - if(lp_posix_locking(br_lck->fsp->conn->cnum)) { + if(lp_posix_locking(SNUM(br_lck->fsp->conn))) { release_posix_lock_windows_flavour(br_lck->fsp, plock->start, plock->size, @@ -943,7 +943,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s } /* Unlock any POSIX regions. */ - if(lp_posix_locking(br_lck->fsp->conn->cnum)) { + if(lp_posix_locking(SNUM(br_lck->fsp->conn))) { release_posix_lock_posix_flavour(br_lck->fsp, plock->start, plock->size, @@ -1069,7 +1069,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck, * This only conflicts with Windows locks, not POSIX locks. */ - if(lp_posix_locking(fsp->conn->cnum) && (lock_flav == WINDOWS_LOCK)) { + if(lp_posix_locking(SNUM(fsp->conn)) && (lock_flav == WINDOWS_LOCK)) { ret = is_posix_locked(fsp, &start, &size, &lock_type, WINDOWS_LOCK); DEBUG(10,("brl_locktest: posix start=%.0f len=%.0f %s for fnum %d file %s\n", @@ -1135,7 +1135,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, * see if there is a POSIX lock from a UNIX or NFS process. */ - if(lp_posix_locking(fsp->conn->cnum)) { + if(lp_posix_locking(SNUM(fsp->conn))) { BOOL ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK); DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for fnum %d file %s\n", @@ -1218,7 +1218,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) struct process_id pid = procid_self(); BOOL unlock_individually = False; - if(lp_posix_locking(fsp->conn->cnum)) { + if(lp_posix_locking(SNUM(fsp->conn))) { /* Check if there are any Windows locks associated with this dev/ino pair that are not this fnum. If so we need to call unlock on each @@ -1326,7 +1326,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) } } - if(lp_posix_locking(fsp->conn->cnum) && num_deleted_windows_locks) { + if(lp_posix_locking(SNUM(fsp->conn)) && num_deleted_windows_locks) { /* Reduce the Windows lock POSIX reference count on this dev/ino pair. */ reduce_windows_lock_ref_count(fsp, num_deleted_windows_locks); } -- cgit From a093a76dc14303fd1c42fb2c0b87faf3748815e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Jul 2006 22:42:39 +0000 Subject: r17293: After the results from the cluster tests in Germany, fix the messaging code to call the efficient calls : save_re_uid() set_effective_uid(0); messaging_op restore_re_uid(); instead of using heavyweight become_root()/unbecome_root() pairs around all messaging code. Fixup the messaging code to ensure sec_init() is called (only once) so that non-root processes still work when sending messages. This is a lighter weight solution to become_root()/unbecome_root() (which swaps all the supplemental groups) and should be more efficient. I will migrate all server code over to using this (a similar technique should be used in the passdb backend where needed). Jeremy. (This used to be commit 4ace291278d9a44f5c577bdd3b282c1231e543df) --- source3/locking/brlock.c | 6 ------ source3/locking/locking.c | 2 -- 2 files changed, 8 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 031836ecdf..4a36d938ad 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -816,11 +816,9 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", procid_str_static(&pend_lock->context.pid ))); - become_root(); message_send_pid(pend_lock->context.pid, MSG_SMB_UNLOCK, NULL, 0, True); - unbecome_root(); } } @@ -985,11 +983,9 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", procid_str_static(&pend_lock->context.pid ))); - become_root(); message_send_pid(pend_lock->context.pid, MSG_SMB_UNLOCK, NULL, 0, True); - unbecome_root(); } } @@ -1306,11 +1302,9 @@ void brl_close_fnum(struct byte_range_lock *br_lck) /* We could send specific lock info here... */ if (brl_pending_overlap(lock, pend_lock)) { - become_root(); message_send_pid(pend_lock->context.pid, MSG_SMB_UNLOCK, NULL, 0, True); - unbecome_root(); } } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 3cbf318007..3879d40cba 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -851,10 +851,8 @@ BOOL rename_share_filename(struct share_mode_lock *lck, (unsigned int)lck->dev, (double)lck->ino, lck->servicepath, lck->filename )); - become_root(); message_send_pid(se->pid, MSG_SMB_FILE_RENAME, frm, msg_len, True); - unbecome_root(); } return True; -- cgit From 2c6030415e0b1f421ea6e85fe6ffe7389ee7a941 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 29 Jul 2006 19:14:24 +0000 Subject: r17314: Optimisation for POSIX locking. If we're downgrading a POSIX lock (applying a read-lock) and we overlap pending read locks then send them an unlock message, we may have allowed them to proceed. Jeremy. (This used to be commit a7a0b6ba50f4cf7c5a0a29809fdff9e1266a29e7) --- source3/locking/brlock.c | 95 ++++++++++++++++++++++++++++++++--------------- source3/locking/locking.c | 6 ++- 2 files changed, 70 insertions(+), 31 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 4a36d938ad..568c80f3ee 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -98,7 +98,7 @@ static BOOL brl_conflict(const struct lock_struct *lck1, const struct lock_struct *lck2) { /* Ignore PENDING locks. */ - if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) + if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type)) return False; /* Read locks never conflict. */ @@ -129,7 +129,7 @@ static BOOL brl_conflict_posix(const struct lock_struct *lck1, #endif /* Ignore PENDING locks. */ - if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) + if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type)) return False; /* Read locks never conflict. */ @@ -151,7 +151,7 @@ static BOOL brl_conflict_posix(const struct lock_struct *lck1, static BOOL brl_conflict1(const struct lock_struct *lck1, const struct lock_struct *lck2) { - if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) + if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type)) return False; if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) { @@ -184,7 +184,7 @@ static BOOL brl_conflict1(const struct lock_struct *lck1, static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock_struct *lck2) { - if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK ) + if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type)) return False; if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) @@ -210,6 +210,19 @@ static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock return brl_overlap(lck1, lck2); } +/**************************************************************************** + Check if an unlock overlaps a pending lock. +****************************************************************************/ + +static BOOL brl_pending_overlap(const struct lock_struct *lock, const struct lock_struct *pend_lock) +{ + if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start)) + return True; + if ((lock->start >= pend_lock->start) && (lock->start <= pend_lock->start + pend_lock->size)) + return True; + return False; +} + /**************************************************************************** Amazingly enough, w2k3 "remembers" whether the last lock failure on a fnum is the same as this one and changes its error code. I wonder if any @@ -320,7 +333,7 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, be mapped into a lower level POSIX one, and if so can we get it ? */ - if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) { + if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(SNUM(fsp->conn))) { int errno_ret; if (!set_posix_lock_windows_flavour(fsp, plock->start, @@ -575,6 +588,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; struct lock_struct *tp; BOOL lock_was_added = False; + BOOL signal_pending_read = False; /* No zero-zero locks for POSIX. */ if (plock->start == 0 && plock->size == 0) { @@ -598,19 +612,28 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, count = 0; for (i=0; i < br_lck->num_locks; i++) { - if (locks[i].lock_flav == WINDOWS_LOCK) { + struct lock_struct *curr_lock = &locks[i]; + + /* If we have a pending read lock, a lock downgrade should + trigger a lock re-evaluation. */ + if (curr_lock->lock_type == PENDING_READ_LOCK && + brl_pending_overlap(plock, curr_lock)) { + signal_pending_read = True; + } + + if (curr_lock->lock_flav == WINDOWS_LOCK) { /* Do any Windows flavour locks conflict ? */ - if (brl_conflict(&locks[i], plock)) { + if (brl_conflict(curr_lock, plock)) { /* No games with error messages. */ SAFE_FREE(tp); return NT_STATUS_FILE_LOCK_CONFLICT; } /* Just copy the Windows lock into the new array. */ - memcpy(&tp[count], &locks[i], sizeof(struct lock_struct)); + memcpy(&tp[count], curr_lock, sizeof(struct lock_struct)); count++; } else { /* POSIX conflict semantics are different. */ - if (brl_conflict_posix(&locks[i], plock)) { + if (brl_conflict_posix(curr_lock, plock)) { /* Can't block ourselves with POSIX locks. */ /* No games with error messages. */ SAFE_FREE(tp); @@ -618,7 +641,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, } /* Work out overlaps. */ - count += brlock_posix_split_merge(&tp[count], &locks[i], plock, &lock_was_added); + count += brlock_posix_split_merge(&tp[count], curr_lock, plock, &lock_was_added); } } @@ -631,7 +654,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, be mapped into a lower level POSIX one, and if so can we get it ? */ - if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(br_lck->fsp->conn))) { + if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(SNUM(br_lck->fsp->conn))) { int errno_ret; /* The lower layer just needs to attempt to @@ -661,7 +684,34 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, br_lck->num_locks = count; SAFE_FREE(br_lck->lock_data); br_lck->lock_data = (void *)tp; + locks = tp; br_lck->modified = True; + + /* A successful downgrade from write to read lock can trigger a lock + re-evalutation where waiting readers can now proceed. */ + + if (signal_pending_read) { + /* Send unlock messages to any pending read waiters that overlap. */ + for (i=0; i < br_lck->num_locks; i++) { + struct lock_struct *pend_lock = &locks[i]; + + /* Ignore non-pending locks. */ + if (!IS_PENDING_LOCK(pend_lock->lock_type)) { + continue; + } + + if (pend_lock->lock_type == PENDING_READ_LOCK && + brl_pending_overlap(plock, pend_lock)) { + DEBUG(10,("brl_lock_posix: sending unlock message to pid %s\n", + procid_str_static(&pend_lock->context.pid ))); + + message_send_pid(pend_lock->context.pid, + MSG_SMB_UNLOCK, + NULL, 0, True); + } + } + } + return NT_STATUS_OK; } @@ -710,19 +760,6 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, return ret; } -/**************************************************************************** - Check if an unlock overlaps a pending lock. -****************************************************************************/ - -static BOOL brl_pending_overlap(const struct lock_struct *lock, const struct lock_struct *pend_lock) -{ - if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start)) - return True; - if ((lock->start >= pend_lock->start) && (lock->start <= pend_lock->start + pend_lock->size)) - return True; - return False; -} - /**************************************************************************** Unlock a range of bytes - Windows semantics. ****************************************************************************/ @@ -807,7 +844,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock struct lock_struct *pend_lock = &locks[j]; /* Ignore non-pending locks. */ - if (pend_lock->lock_type != PENDING_LOCK) { + if (!IS_PENDING_LOCK(pend_lock->lock_type)) { continue; } @@ -866,7 +903,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s unsigned int tmp_count; /* Only remove our own locks - ignore fnum. */ - if (lock->lock_type == PENDING_LOCK || + if (IS_PENDING_LOCK(lock->lock_type) || !brl_same_context(&lock->context, &plock->context)) { memcpy(&tp[count], lock, sizeof(struct lock_struct)); count++; @@ -974,7 +1011,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s struct lock_struct *pend_lock = &locks[j]; /* Ignore non-pending locks. */ - if (pend_lock->lock_type != PENDING_LOCK) { + if (!IS_PENDING_LOCK(pend_lock->lock_type)) { continue; } @@ -1173,7 +1210,7 @@ BOOL brl_lock_cancel(struct byte_range_lock *br_lck, /* For pending locks we *always* care about the fnum. */ if (brl_same_context(&lock->context, &context) && lock->fnum == br_lck->fsp->fnum && - lock->lock_type == PENDING_LOCK && + IS_PENDING_LOCK(lock->lock_type) && lock->lock_flav == lock_flav && lock->start == start && lock->size == size) { @@ -1288,7 +1325,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) struct lock_struct *pend_lock = &locks[j]; /* Ignore our own or non-pending locks. */ - if (pend_lock->lock_type != PENDING_LOCK) { + if (!IS_PENDING_LOCK(pend_lock->lock_type)) { continue; } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 3879d40cba..4cd6b436c3 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -55,8 +55,10 @@ const char *lock_type_name(enum brl_type lock_type) return "READ"; case WRITE_LOCK: return "WRITE"; - case PENDING_LOCK: - return "PENDING"; + case PENDING_READ_LOCK: + return "PENDING_READ"; + case PENDING_WRITE_LOCK: + return "PENDING_WRITE"; default: return "other"; } -- cgit From 49001a5b1b07e9a24e5f7efa0dfd880772bdb435 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Jul 2006 20:58:02 +0000 Subject: r17346: Add optimisation vl needs for the cluster code where we don't get the chainlock when getting the byte range lock record read-only. Jeremy. (This used to be commit fcd798ca0c1b76adb2bcda4a99c40c7aacb0addb) --- source3/locking/brlock.c | 45 +++++++++++++++++++++++++++++++++++++-------- source3/locking/locking.c | 6 +++--- 2 files changed, 40 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 568c80f3ee..fd41f75e62 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1500,6 +1500,10 @@ static int byte_range_lock_destructor(void *p) key.dptr = (char *)&br_lck->key; key.dsize = sizeof(struct lock_key); + if (br_lck->read_only) { + SMB_ASSERT(!br_lck->modified); + } + if (!br_lck->modified) { goto done; } @@ -1521,7 +1525,9 @@ static int byte_range_lock_destructor(void *p) done: - tdb_chainunlock(tdb, key); + if (!br_lck->read_only) { + tdb_chainunlock(tdb, key); + } SAFE_FREE(br_lck->lock_data); return 0; } @@ -1532,8 +1538,8 @@ static int byte_range_lock_destructor(void *p) TALLOC_FREE(brl) will release the lock in the destructor. ********************************************************************/ -struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, - files_struct *fsp) +static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, + files_struct *fsp, BOOL read_only) { TDB_DATA key; TDB_DATA data; @@ -1553,10 +1559,21 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, key.dptr = (char *)&br_lck->key; key.dsize = sizeof(struct lock_key); - if (tdb_chainlock(tdb, key) != 0) { - DEBUG(3, ("Could not lock byte range lock entry\n")); - TALLOC_FREE(br_lck); - return NULL; + if (!fsp->lockdb_clean) { + /* We must be read/write to clean + the dead entries. */ + read_only = False; + } + + if (read_only) { + br_lck->read_only = True; + } else { + if (tdb_chainlock(tdb, key) != 0) { + DEBUG(3, ("Could not lock byte range lock entry\n")); + TALLOC_FREE(br_lck); + return NULL; + } + br_lck->read_only = False; } talloc_set_destructor(br_lck, byte_range_lock_destructor); @@ -1594,7 +1611,7 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, if (DEBUGLEVEL >= 10) { unsigned int i; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; - DEBUG(10,("brl_get_locks: %u current locks on dev=%.0f, inode=%.0f\n", + DEBUG(10,("brl_get_locks_internal: %u current locks on dev=%.0f, inode=%.0f\n", br_lck->num_locks, (double)fsp->dev, (double)fsp->inode )); for( i = 0; i < br_lck->num_locks; i++) { @@ -1603,3 +1620,15 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, } return br_lck; } + +struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, + files_struct *fsp) +{ + return brl_get_locks_internal(mem_ctx, fsp, False); +} + +struct byte_range_lock *brl_get_locks_readonly(TALLOC_CTX *mem_ctx, + files_struct *fsp) +{ + return brl_get_locks_internal(mem_ctx, fsp, True); +} diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4cd6b436c3..8dd7fafd3b 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -102,7 +102,7 @@ BOOL is_locked(files_struct *fsp, DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); ret = False; } else { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks_readonly(NULL, fsp); if (!br_lck) { return False; } @@ -116,7 +116,7 @@ BOOL is_locked(files_struct *fsp, TALLOC_FREE(br_lck); } } else { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks_readonly(NULL, fsp); if (!br_lck) { return False; } @@ -160,7 +160,7 @@ NTSTATUS query_lock(files_struct *fsp, return NT_STATUS_OK; } - br_lck = brl_get_locks(NULL, fsp); + br_lck = brl_get_locks_readonly(NULL, fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } -- cgit From 70660495b349cde6245731870d6337eb2800a8ed Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 8 Aug 2006 09:56:38 +0000 Subject: r17452: Some C++ warnings (This used to be commit e4b8c79a9d6f7323953121887af4f482d04a9228) --- source3/locking/brlock.c | 5 +++-- source3/locking/posix.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index fd41f75e62..9229d6e6e8 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1002,7 +1002,8 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s br_lck->num_locks = count; SAFE_FREE(br_lck->lock_data); - locks = br_lck->lock_data = (void *)tp; + locks = tp; + br_lck->lock_data = (void *)tp; br_lck->modified = True; /* Send unlock messages to any pending waiters that overlap. */ @@ -1279,7 +1280,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) unsigned int num_locks_copy; /* Copy the current lock array. */ - locks_copy = TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); + locks_copy = (struct lock_struct *)TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); if (!locks_copy) { smb_panic("brl_close_fnum: talloc fail.\n"); } diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 586de5745b..8e27d4523b 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -573,7 +573,7 @@ static void add_fd_to_close_entry(files_struct *fsp) dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); + dbuf.dptr = (char *)SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); if (!dbuf.dptr) { smb_panic("add_fd_to_close_entry: Realloc fail !\n"); } -- cgit From 3bc4fd1bb9bfbd0e0efd89d47c50bf798e5a1481 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 Aug 2006 19:14:25 +0000 Subject: r17924: Get rid of warnings now that talloc is merged. Destructors now take a pointer to the "real" destroyed object as an argument. Volker (This used to be commit 70edd716ef0ccb218fe18d1233bd30abe46b62bf) --- source3/locking/brlock.c | 4 +--- source3/locking/locking.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 9229d6e6e8..00cbed6b84 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1492,10 +1492,8 @@ int brl_forall(BRLOCK_FN(fn)) Unlock the record. ********************************************************************/ -static int byte_range_lock_destructor(void *p) +static int byte_range_lock_destructor(struct byte_range_lock *br_lck) { - struct byte_range_lock *br_lck = - talloc_get_type_abort(p, struct byte_range_lock); TDB_DATA key; key.dptr = (char *)&br_lck->key; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8dd7fafd3b..371f1b474c 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -672,10 +672,8 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) return result; } -static int share_mode_lock_destructor(void *p) +static int share_mode_lock_destructor(struct share_mode_lock *lck) { - struct share_mode_lock *lck = - talloc_get_type_abort(p, struct share_mode_lock); TDB_DATA key = locking_key(lck->dev, lck->ino); TDB_DATA data; -- cgit From 8f553d8d3cbdf372ddbcbdaab48ef16296d3872c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 4 Oct 2006 20:51:17 +0000 Subject: r19078: talloc_strdup can fail (This used to be commit 2b3b9ce2a122ec5fd945728c117c321087d85203) --- source3/locking/locking.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 371f1b474c..fbe22f4e1d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -562,12 +562,18 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) (lck->num_share_modes * sizeof(struct share_mode_entry)) + data->u.s.delete_token_size ); + if (lck->servicepath == NULL) { + smb_panic("talloc_strdup failed\n"); + } lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + (lck->num_share_modes * sizeof(struct share_mode_entry)) + data->u.s.delete_token_size + strlen(lck->servicepath) + 1 ); + if (lck->filename == NULL) { + smb_panic("talloc_strdup failed\n"); + } /* * Ensure that each entry has a real process attached. -- cgit From b6b84f98c0420f45c498b025d9edbeb7f830205a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 11 Nov 2006 17:05:11 +0000 Subject: r19668: Convert the locking params to use struct share_param instead of snum (This used to be commit 609dbec600048718b86cd1ecdc2ce49bbdeb803c) --- source3/locking/brlock.c | 16 ++++++++-------- source3/locking/locking.c | 15 +++++++-------- source3/locking/posix.c | 2 +- 3 files changed, 16 insertions(+), 17 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 00cbed6b84..872ed2bbea 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -333,7 +333,7 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, be mapped into a lower level POSIX one, and if so can we get it ? */ - if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(SNUM(fsp->conn))) { + if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(fsp->conn->params)) { int errno_ret; if (!set_posix_lock_windows_flavour(fsp, plock->start, @@ -654,7 +654,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, be mapped into a lower level POSIX one, and if so can we get it ? */ - if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(SNUM(br_lck->fsp->conn))) { + if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(br_lck->fsp->conn->params)) { int errno_ret; /* The lower layer just needs to attempt to @@ -829,7 +829,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock br_lck->modified = True; /* Unlock the underlying POSIX regions. */ - if(lp_posix_locking(SNUM(br_lck->fsp->conn))) { + if(lp_posix_locking(br_lck->fsp->conn->params)) { release_posix_lock_windows_flavour(br_lck->fsp, plock->start, plock->size, @@ -978,7 +978,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s } /* Unlock any POSIX regions. */ - if(lp_posix_locking(SNUM(br_lck->fsp->conn))) { + if(lp_posix_locking(br_lck->fsp->conn->params)) { release_posix_lock_posix_flavour(br_lck->fsp, plock->start, plock->size, @@ -1103,7 +1103,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck, * This only conflicts with Windows locks, not POSIX locks. */ - if(lp_posix_locking(SNUM(fsp->conn)) && (lock_flav == WINDOWS_LOCK)) { + if(lp_posix_locking(fsp->conn->params) && (lock_flav == WINDOWS_LOCK)) { ret = is_posix_locked(fsp, &start, &size, &lock_type, WINDOWS_LOCK); DEBUG(10,("brl_locktest: posix start=%.0f len=%.0f %s for fnum %d file %s\n", @@ -1169,7 +1169,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, * see if there is a POSIX lock from a UNIX or NFS process. */ - if(lp_posix_locking(SNUM(fsp->conn))) { + if(lp_posix_locking(fsp->conn->params)) { BOOL ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK); DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for fnum %d file %s\n", @@ -1252,7 +1252,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) struct process_id pid = procid_self(); BOOL unlock_individually = False; - if(lp_posix_locking(SNUM(fsp->conn))) { + if(lp_posix_locking(fsp->conn->params)) { /* Check if there are any Windows locks associated with this dev/ino pair that are not this fnum. If so we need to call unlock on each @@ -1358,7 +1358,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) } } - if(lp_posix_locking(SNUM(fsp->conn)) && num_deleted_windows_locks) { + if(lp_posix_locking(fsp->conn->params) && num_deleted_windows_locks) { /* Reduce the Windows lock POSIX reference count on this dev/ino pair. */ reduce_windows_lock_ref_count(fsp, num_deleted_windows_locks); } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index fbe22f4e1d..13c7724656 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -80,8 +80,7 @@ BOOL is_locked(files_struct *fsp, SMB_BIG_UINT offset, enum brl_type lock_type) { - int snum = SNUM(fsp->conn); - int strict_locking = lp_strict_locking(snum); + int strict_locking = lp_strict_locking(fsp->conn->params); enum brl_flavour lock_flav = lp_posix_cifsu_locktype(); BOOL ret = True; @@ -89,7 +88,7 @@ BOOL is_locked(files_struct *fsp, return False; } - if (!lp_locking(snum) || !strict_locking) { + if (!lp_locking(fsp->conn->params) || !strict_locking) { return False; } @@ -156,7 +155,7 @@ NTSTATUS query_lock(files_struct *fsp, return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } - if (!lp_locking(SNUM(fsp->conn))) { + if (!lp_locking(fsp->conn->params)) { return NT_STATUS_OK; } @@ -197,7 +196,7 @@ struct byte_range_lock *do_lock(files_struct *fsp, return NULL; } - if (!lp_locking(SNUM(fsp->conn))) { + if (!lp_locking(fsp->conn->params)) { *perr = NT_STATUS_OK; return NULL; } @@ -243,7 +242,7 @@ NTSTATUS do_unlock(files_struct *fsp, return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } - if (!lp_locking(SNUM(fsp->conn))) { + if (!lp_locking(fsp->conn->params)) { return NT_STATUS_OK; } @@ -290,7 +289,7 @@ NTSTATUS do_lock_cancel(files_struct *fsp, NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } - if (!lp_locking(SNUM(fsp->conn))) { + if (!lp_locking(fsp->conn->params)) { return NT_STATUS_DOS(ERRDOS, ERRcancelviolation); } @@ -327,7 +326,7 @@ void locking_close_file(files_struct *fsp) { struct byte_range_lock *br_lck; - if (!lp_locking(SNUM(fsp->conn))) { + if (!lp_locking(fsp->conn->params)) { return; } diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 8e27d4523b..806018da81 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -643,7 +643,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) int *fd_array = NULL; size_t count, i; - if (!lp_locking(SNUM(fsp->conn)) || !lp_posix_locking(SNUM(conn))) { + if (!lp_locking(fsp->conn->params) || !lp_posix_locking(conn->params)) { /* * No locking or POSIX to worry about or we want POSIX semantics * which will lose all locks on all fd's open on this dev/inode, -- cgit From fd37f98158161406229b728a7c767121a30e254f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Jan 2007 06:19:24 +0000 Subject: r20873: Some correctness fixes w.r.t. Samba4 torture BASE-DELETE. Allow us to correctly refuse to set delete on close on a non-empty directory. There are still some delete-on-close wrinkles to be fixed, but I understand how to do that better now. I'll fix this tomorrow. Jeremy. (This used to be commit 029635885825a5562e7974a6f5675cce3bf1b5dc) --- source3/locking/locking.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 13c7724656..111fc98bbe 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1152,6 +1152,46 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, return NT_STATUS_ACCESS_DENIED; } + /* Don't allow delete on close for non-empty directories. */ + if (fsp->is_directory) { + long offset = 0; + NTSTATUS status; + SMB_STRUCT_STAT st; + struct dptr_struct *dirptr; + const char *name; + + status = dptr_create(fsp->conn, + fsp->fsp_name, + False, + True, + 0, + "*", + True, + 0, + &dirptr); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* Read 3 entries. Ignore first 2 (they're . and .. ) */ + name = dptr_ReadDirName(dirptr, &offset, &st); + if (!name) { + dptr_CloseDir(dirptr); + return NT_STATUS_ACCESS_DENIED; + } + name = dptr_ReadDirName(dirptr, &offset, &st); + if (!name) { + dptr_CloseDir(dirptr); + return NT_STATUS_ACCESS_DENIED; + } + name = dptr_ReadDirName(dirptr, &offset, &st); + dptr_CloseDir(dirptr); + if (name) { + DEBUG(10,("can_set_delete_on_close: got name %s - can't delete\n", name )); + return NT_STATUS_DIRECTORY_NOT_EMPTY; + } + } + return NT_STATUS_OK; } -- cgit From c9a14ea19f812d86266bfa9e6ce8b32f7b4ff19f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Jan 2007 21:51:52 +0000 Subject: r20883: W00t! I now understand how "delete on close" really works - even with the strange "initial delete on close" semantics. The "initial delete on close" flag isn't committed to the share mode db until the handle is closed, and is discarded if any real "delete on close" was set. This allows me to remove the "initial_delete_on_close" flag from the share db, and move it into a BOOL in files_struct. Warning ! You must do a make clean after this. Cope with the wrinkle in directory delete on close which is done differently from files. We now pass all Samba4 smbtortute BASE-DELETE tests except for the one checking that files can't be created in a directory which has the delete on close set (possibly expensive to fix). Jeremy. (This used to be commit f2df77a1497958c1ea791f1d2f4446b5fc3389b3) --- source3/locking/locking.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 111fc98bbe..56d18a63ef 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -473,14 +473,11 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) data = (struct locking_data *)dbuf.dptr; lck->delete_on_close = data->u.s.delete_on_close; - lck->initial_delete_on_close = data->u.s.initial_delete_on_close; lck->num_share_modes = data->u.s.num_share_mode_entries; DEBUG(10, ("parse_share_modes: delete_on_close: %d, " - "initial_delete_on_close: %d, " "num_share_modes: %d\n", lck->delete_on_close, - lck->initial_delete_on_close, lck->num_share_modes)); if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { @@ -635,11 +632,9 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) ZERO_STRUCTP(data); data->u.s.num_share_mode_entries = lck->num_share_modes; data->u.s.delete_on_close = lck->delete_on_close; - data->u.s.initial_delete_on_close = lck->initial_delete_on_close; data->u.s.delete_token_size = delete_token_size; - DEBUG(10, ("unparse_share_modes: del: %d, initial del %d, tok = %u, num: %d\n", + DEBUG(10, ("unparse_share_modes: del: %d, tok = %u, num: %d\n", data->u.s.delete_on_close, - data->u.s.initial_delete_on_close, (unsigned int)data->u.s.delete_token_size, data->u.s.num_share_mode_entries)); memcpy(result.dptr + sizeof(*data), lck->share_modes, @@ -734,7 +729,6 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, lck->share_modes = NULL; lck->delete_token = NULL; lck->delete_on_close = False; - lck->initial_delete_on_close = False; lck->fresh = False; lck->modified = False; @@ -1251,11 +1245,22 @@ void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok changed the delete on close flag. This will be noticed in the close code, the last closer will delete the file if flag is set. - Note that setting this to any value clears the initial_delete_on_close flag. - If delete_on_close is True this makes a copy of any UNIX_USER_TOKEN into the - lck entry. + This makes a copy of any UNIX_USER_TOKEN into the + lck entry. This function is used when the lock is already granted. ****************************************************************************/ +void set_delete_on_close_lck(struct share_mode_lock *lck, BOOL delete_on_close, UNIX_USER_TOKEN *tok) +{ + if (lck->delete_on_close != delete_on_close) { + set_delete_on_close_token(lck, tok); + lck->delete_on_close = delete_on_close; + if (delete_on_close) { + SMB_ASSERT(lck->delete_token != NULL); + } + lck->modified = True; + } +} + BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKEN *tok) { struct share_mode_lock *lck; @@ -1274,19 +1279,7 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE return False; } - if (lck->delete_on_close != delete_on_close) { - set_delete_on_close_token(lck, tok); - lck->delete_on_close = delete_on_close; - if (delete_on_close) { - SMB_ASSERT(lck->delete_token != NULL); - } - lck->modified = True; - } - - if (lck->initial_delete_on_close) { - lck->initial_delete_on_close = False; - lck->modified = True; - } + set_delete_on_close_lck(lck, delete_on_close, tok); TALLOC_FREE(lck); return True; -- cgit From aacd16e7c4bea5018560eea09d55f2a6473be84d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Jan 2007 21:46:12 +0000 Subject: r20916: Add in the delete on close final fix - but only enabled with -DDEVELOPER. Jeremy. (This used to be commit 7f817067a70930ee3502ea3373173e0c23733253) --- source3/locking/locking.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 56d18a63ef..d2e8b7ef59 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1281,6 +1281,10 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE set_delete_on_close_lck(lck, delete_on_close, tok); + if (fsp->is_directory) { + send_stat_cache_delete_message(fsp->fsp_name); + } + TALLOC_FREE(lck); return True; } -- cgit From 7a5fa7f12ec439ef5a4af29aa86498f799b6b9a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Feb 2007 21:05:34 +0000 Subject: r21191: Add in the POSIX open/mkdir/unlink calls. Move more error code returns to NTSTATUS. Client test code to follow... See if this passes the build-farm before I add it into 3.0.25. Jeremy. (This used to be commit 83dbbdff345fa9e427c9579183f4380004bf3dd7) --- source3/locking/locking.c | 9 ++++++--- source3/locking/posix.c | 14 +++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d2e8b7ef59..39cc991b5f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -81,7 +81,7 @@ BOOL is_locked(files_struct *fsp, enum brl_type lock_type) { int strict_locking = lp_strict_locking(fsp->conn->params); - enum brl_flavour lock_flav = lp_posix_cifsu_locktype(); + enum brl_flavour lock_flav = lp_posix_cifsu_locktype(fsp); BOOL ret = True; if (count == 0) { @@ -426,13 +426,14 @@ char *share_mode_str(int num, struct share_mode_entry *e) slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s " "pid = %s, share_access = 0x%x, private_options = 0x%x, " "access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, " - "uid = %u, dev = 0x%x, inode = %.0f", + "uid = %u, flags = %u, dev = 0x%x, inode = %.0f", num, e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "", procid_str_static(&e->pid), e->share_access, e->private_options, e->access_mask, e->op_mid, e->op_type, e->share_file_id, - (unsigned int)e->uid, (unsigned int)e->dev, (double)e->inode ); + (unsigned int)e->uid, (unsigned int)e->flags, + (unsigned int)e->dev, (double)e->inode ); return share_str; } @@ -912,6 +913,7 @@ static void fill_share_mode_entry(struct share_mode_entry *e, e->inode = fsp->inode; e->share_file_id = fsp->fh->file_id; e->uid = (uint32)uid; + e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0; } static void fill_deferred_open_entry(struct share_mode_entry *e, @@ -927,6 +929,7 @@ static void fill_deferred_open_entry(struct share_mode_entry *e, e->dev = dev; e->inode = ino; e->uid = (uint32)-1; + e->flags = 0; } static void add_share_mode_entry(struct share_mode_lock *lck, diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 806018da81..62804eb8e3 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -636,7 +636,7 @@ static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) to delete all locks on this fsp before this function is called. ****************************************************************************/ -int fd_close_posix(struct connection_struct *conn, files_struct *fsp) +NTSTATUS fd_close_posix(struct connection_struct *conn, files_struct *fsp) { int saved_errno = 0; int ret; @@ -651,7 +651,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) */ ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); fsp->fh->fd = -1; - return ret; + return map_nt_error_from_unix(errno); } if (get_windows_lock_ref_count(fsp)) { @@ -663,7 +663,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) add_fd_to_close_entry(fsp); fsp->fh->fd = -1; - return 0; + return NT_STATUS_OK; } /* @@ -701,14 +701,18 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); - if (saved_errno != 0) { + if (ret == 0 && saved_errno != 0) { errno = saved_errno; ret = -1; } fsp->fh->fd = -1; - return ret; + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + + return NT_STATUS_OK; } /**************************************************************************** -- cgit From 86e5659abac9938e7ac0cea989ca33e807b3e181 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Feb 2007 02:03:39 +0000 Subject: r21257: Better fix for bug #4188 : Windows Vista RC1 and RC2 can't delete directory on Samba share based on work by Joe Meadows . Jeremy. (This used to be commit 2dab8928769938ab79da7b7ce2d165fc388f9b00) --- source3/locking/locking.c | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 39cc991b5f..ffac43aff5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1151,42 +1151,7 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, /* Don't allow delete on close for non-empty directories. */ if (fsp->is_directory) { - long offset = 0; - NTSTATUS status; - SMB_STRUCT_STAT st; - struct dptr_struct *dirptr; - const char *name; - - status = dptr_create(fsp->conn, - fsp->fsp_name, - False, - True, - 0, - "*", - True, - 0, - &dirptr); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* Read 3 entries. Ignore first 2 (they're . and .. ) */ - name = dptr_ReadDirName(dirptr, &offset, &st); - if (!name) { - dptr_CloseDir(dirptr); - return NT_STATUS_ACCESS_DENIED; - } - name = dptr_ReadDirName(dirptr, &offset, &st); - if (!name) { - dptr_CloseDir(dirptr); - return NT_STATUS_ACCESS_DENIED; - } - name = dptr_ReadDirName(dirptr, &offset, &st); - dptr_CloseDir(dirptr); - if (name) { - DEBUG(10,("can_set_delete_on_close: got name %s - can't delete\n", name )); - return NT_STATUS_DIRECTORY_NOT_EMPTY; - } + return can_delete_directory(fsp->conn, fsp->fsp_name); } return NT_STATUS_OK; -- cgit From 242927bd5cae1d2ab8739b1c424e702ab97726b5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 Mar 2007 20:09:27 +0000 Subject: r21706: get_delete_on_close_flag() is the perfect candidate for tdb_parse_record() (This used to be commit b73685d20751ac343faab79332552cd7ee92d831) --- source3/locking/locking.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index ffac43aff5..7326ea08c0 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -858,15 +858,29 @@ BOOL rename_share_filename(struct share_mode_lock *lck, return True; } -BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) +static int pull_delete_on_close_flag(TDB_DATA key, TDB_DATA dbuf, + void *private_data) { - BOOL result; - struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, NULL, NULL); - if (!lck) { - return False; + BOOL *result = (BOOL *)private_data; + struct locking_data *data; + + if (dbuf.dsize < sizeof(struct locking_data)) { + smb_panic("PANIC: parse_share_modes: buffer too short.\n"); } - result = lck->delete_on_close; - TALLOC_FREE(lck); + + data = (struct locking_data *)dbuf.dptr; + + *result = data->u.s.delete_on_close; + return 0; +} + +BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) +{ + TDB_DATA key = locking_key(dev, inode); + BOOL result = False; + + tdb_parse_record(tdb, key, pull_delete_on_close_flag, + (void *)&result); return result; } -- cgit From 94a1b230f3323e55fa23f20b464964eaac643882 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 Mar 2007 10:40:18 +0000 Subject: r21723: Make use of the per-hashchain "freelists" (This used to be commit f3421ae4cfa263c0e7a8e934b40342ee9885d239) --- source3/locking/brlock.c | 3 +++ source3/locking/locking.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 872ed2bbea..76a4039d82 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -273,6 +273,9 @@ void brl_init(int read_only) lock_path("brlock.tdb"))); return; } + + /* Activate the per-hashchain freelist */ + tdb_set_max_dead(tdb, 5); } /**************************************************************************** diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 7326ea08c0..6c4e896a2a 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -363,6 +363,9 @@ BOOL locking_init(int read_only) return False; } + /* Activate the per-hashchain freelist */ + tdb_set_max_dead(tdb, 5); + if (!posix_locking_init(read_only)) return False; -- cgit From 640ab28d78dac5c2bcee8b641c8971fcbcd87dfa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Mar 2007 21:59:51 +0000 Subject: r21724: Optimization pointed out by Volker. If we don't have any outstanding locks or blocking locks then we don't need to read the lock db. on close. Jeremy. (This used to be commit 1b063496f93f78347a6e67549bde54c845499a7d) --- source3/locking/locking.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 6c4e896a2a..304932cf32 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -222,6 +222,12 @@ struct byte_range_lock *do_lock(files_struct *fsp, lock_flav, blocking_lock); + /* blocking ie. pending, locks also count here, + * as this is an efficiency counter to avoid checking + * the lock db. on close. JRA. */ + + fsp->current_lock_count++; + return br_lck; } @@ -268,6 +274,9 @@ NTSTATUS do_unlock(files_struct *fsp, return NT_STATUS_RANGE_NOT_LOCKED; } + SMB_ASSERT(fsp->current_lock_count > 0); + fsp->current_lock_count--; + return NT_STATUS_OK; } @@ -315,6 +324,9 @@ NTSTATUS do_lock_cancel(files_struct *fsp, return NT_STATUS_DOS(ERRDOS, ERRcancelviolation); } + SMB_ASSERT(fsp->current_lock_count > 0); + fsp->current_lock_count++; + return NT_STATUS_OK; } @@ -330,6 +342,14 @@ void locking_close_file(files_struct *fsp) return; } + /* If we have not outstanding locks or pending + * locks then we don't need to look in the lock db. + */ + + if (fsp->current_lock_count == 0) { + return; + } + br_lck = brl_get_locks(NULL,fsp); if (br_lck) { -- cgit From cda247e9d44f42115929411de3f810ae859134a0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Mar 2007 22:14:09 +0000 Subject: r21726: Fix stupid cut-n-paste typo. Thanks to volker for being on the ball..... :-). Jeremy. (This used to be commit 84ed7bcbe6dc14b18a7e913b153c82da1856a835) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 304932cf32..37e6dbc4e5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -325,7 +325,7 @@ NTSTATUS do_lock_cancel(files_struct *fsp, } SMB_ASSERT(fsp->current_lock_count > 0); - fsp->current_lock_count++; + fsp->current_lock_count--; return NT_STATUS_OK; } -- cgit From bc2b6436d0f5f3e9ffdfaeb7f1b32996a83d5478 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Mar 2007 09:35:51 +0000 Subject: r22009: change TDB_DATA from char * to unsigned char * and fix all compiler warnings in the users metze (This used to be commit 3a28443079c141a6ce8182c65b56ca210e34f37f) --- source3/locking/brlock.c | 8 ++++---- source3/locking/locking.c | 20 ++++++++++---------- source3/locking/posix.c | 8 ++++---- 3 files changed, 18 insertions(+), 18 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 76a4039d82..899e211ffc 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1453,7 +1453,7 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st } if (orig_num_locks != num_locks) { - dbuf.dptr = (char *)locks; + dbuf.dptr = (uint8 *)locks; dbuf.dsize = num_locks * sizeof(*locks); if (dbuf.dsize) { @@ -1499,7 +1499,7 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) { TDB_DATA key; - key.dptr = (char *)&br_lck->key; + key.dptr = (uint8 *)&br_lck->key; key.dsize = sizeof(struct lock_key); if (br_lck->read_only) { @@ -1517,7 +1517,7 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) } } else { TDB_DATA data; - data.dptr = (char *)br_lck->lock_data; + data.dptr = (uint8 *)br_lck->lock_data; data.dsize = br_lck->num_locks * sizeof(struct lock_struct); if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) { @@ -1558,7 +1558,7 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, br_lck->key.device = fsp->dev; br_lck->key.inode = fsp->inode; - key.dptr = (char *)&br_lck->key; + key.dptr = (uint8 *)&br_lck->key; key.dsize = sizeof(struct lock_key); if (!fsp->lockdb_clean) { diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 37e6dbc4e5..dc1d607155 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -433,7 +433,7 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) memset(&key, '\0', sizeof(key)); key.dev = dev; key.ino = inode; - kbuf.dptr = (char *)&key; + kbuf.dptr = (uint8 *)&key; kbuf.dsize = sizeof(key); return kbuf; } @@ -532,7 +532,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) /* Get any delete token. */ if (data->u.s.delete_token_size) { - char *p = dbuf.dptr + sizeof(*data) + + uint8 *p = dbuf.dptr + sizeof(*data) + (lck->num_share_modes * sizeof(struct share_mode_entry)); @@ -578,7 +578,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) } /* Save off the associated service path and filename. */ - lck->servicepath = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + + lck->servicepath = talloc_strdup(lck, (const char *)dbuf.dptr + sizeof(*data) + (lck->num_share_modes * sizeof(struct share_mode_entry)) + data->u.s.delete_token_size ); @@ -586,7 +586,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) smb_panic("talloc_strdup failed\n"); } - lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + + lck->filename = talloc_strdup(lck, (const char *)dbuf.dptr + sizeof(*data) + (lck->num_share_modes * sizeof(struct share_mode_entry)) + data->u.s.delete_token_size + @@ -646,7 +646,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) delete_token_size + sp_len + 1 + strlen(lck->filename) + 1; - result.dptr = TALLOC_ARRAY(lck, char, result.dsize); + result.dptr = TALLOC_ARRAY(lck, uint8, result.dsize); if (result.dptr == NULL) { smb_panic("talloc failed\n"); @@ -668,7 +668,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) /* Store any delete on close token. */ if (lck->delete_token) { - char *p = result.dptr + offset; + uint8 *p = result.dptr + offset; memcpy(p, &lck->delete_token->uid, sizeof(uid_t)); p += sizeof(uid_t); @@ -683,10 +683,10 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) offset = p - result.dptr; } - safe_strcpy(result.dptr + offset, lck->servicepath, + safe_strcpy((char *)result.dptr + offset, lck->servicepath, result.dsize - offset - 1); offset += sp_len + 1; - safe_strcpy(result.dptr + offset, lck->filename, + safe_strcpy((char *)result.dptr + offset, lck->filename, result.dsize - offset - 1); if (DEBUGLEVEL >= 10) { @@ -1318,10 +1318,10 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, data = (struct locking_data *)dbuf.dptr; shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data)); - sharepath = dbuf.dptr + sizeof(*data) + + sharepath = (const char *)dbuf.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares) + data->u.s.delete_token_size; - fname = dbuf.dptr + sizeof(*data) + + fname = (const char *)dbuf.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares) + data->u.s.delete_token_size + strlen(sharepath) + 1; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 62804eb8e3..8bb7f605e3 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -340,7 +340,7 @@ static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode) memset(&key, '\0', sizeof(key)); key.device = dev; key.inode = inode; - kbuf.dptr = (char *)&key; + kbuf.dptr = (uint8 *)&key; kbuf.dsize = sizeof(key); return kbuf; } @@ -358,7 +358,7 @@ static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode) key.device = dev; key.inode = inode; key.r = 'r'; - kbuf.dptr = (char *)&key; + kbuf.dptr = (uint8 *)&key; kbuf.dsize = sizeof(key); return kbuf; } @@ -442,7 +442,7 @@ static void increment_windows_lock_ref_count(files_struct *fsp) dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); if (dbuf.dptr == NULL) { - dbuf.dptr = (char *)SMB_MALLOC_P(int); + dbuf.dptr = (uint8 *)SMB_MALLOC_P(int); if (!dbuf.dptr) { smb_panic("increment_windows_lock_ref_count: malloc fail.\n"); } @@ -573,7 +573,7 @@ static void add_fd_to_close_entry(files_struct *fsp) dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - dbuf.dptr = (char *)SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); + dbuf.dptr = (uint8 *)SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); if (!dbuf.dptr) { smb_panic("add_fd_to_close_entry: Realloc fail !\n"); } -- cgit From 12ba88574bf91bdcc4447bfc3d429b799064bfd9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Apr 2007 23:18:41 +0000 Subject: r22542: Move over to using the _strict varients of the talloc calls. No functional changes. Looks bigger than it is :-). Jeremy. (This used to be commit f6fa3080fee1b20df9f1968500840a88cf0ee592) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index dc1d607155..c548d6eecb 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -521,7 +521,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) } lck->share_modes = (struct share_mode_entry *) - talloc_memdup(lck, dbuf.dptr+sizeof(*data), + TALLOC_MEMDUP(lck, dbuf.dptr+sizeof(*data), lck->num_share_modes * sizeof(struct share_mode_entry)); -- cgit From 79de0ad9463a5cd64978beae37df79fbb4f74632 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Apr 2007 01:34:28 +0000 Subject: r22588: Make all uses of TALLOC_MEMDUP consistent. Jeremy. (This used to be commit 8ad13718af0ba1fcb10a6f1631b1ed3cb8d11175) --- source3/locking/brlock.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 899e211ffc..6dd3ac6ea1 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1283,10 +1283,15 @@ void brl_close_fnum(struct byte_range_lock *br_lck) unsigned int num_locks_copy; /* Copy the current lock array. */ - locks_copy = (struct lock_struct *)TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); - if (!locks_copy) { - smb_panic("brl_close_fnum: talloc fail.\n"); + if (br_lck->num_locks) { + locks_copy = (struct lock_struct *)TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); + if (!locks_copy) { + smb_panic("brl_close_fnum: talloc fail.\n"); + } + } else { + locks_copy = NULL; } + num_locks_copy = br_lck->num_locks; for (i=0; i < num_locks_copy; i++) { -- cgit From 1bcee2679d66f98932d800d6c88b70aeb7691b82 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 5 May 2007 20:43:06 +0000 Subject: r22688: Change lock_data in struct byte_range_lock from void * to struct lock_struct * (This used to be commit 8e0e278961ebf2fa4301874d522636699ace1b9b) --- source3/locking/brlock.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 6dd3ac6ea1..88f993e14b 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -317,7 +317,7 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, { unsigned int i; files_struct *fsp = br_lck->fsp; - struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct lock_struct *locks = br_lck->lock_data; for (i=0; i < br_lck->num_locks; i++) { /* Do any Windows or POSIX locks conflict ? */ @@ -362,7 +362,7 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, memcpy(&locks[br_lck->num_locks], plock, sizeof(struct lock_struct)); br_lck->num_locks += 1; - br_lck->lock_data = (void *)locks; + br_lck->lock_data = locks; br_lck->modified = True; return NT_STATUS_OK; @@ -588,7 +588,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, const struct lock_struct *plock) { unsigned int i, count; - struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct lock_struct *locks = br_lck->lock_data; struct lock_struct *tp; BOOL lock_was_added = False; BOOL signal_pending_read = False; @@ -686,7 +686,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, } br_lck->num_locks = count; SAFE_FREE(br_lck->lock_data); - br_lck->lock_data = (void *)tp; + br_lck->lock_data = tp; locks = tp; br_lck->modified = True; @@ -770,7 +770,7 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock_struct *plock) { unsigned int i, j; - struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct lock_struct *locks = br_lck->lock_data; enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */ #if ZERO_ZERO @@ -873,7 +873,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s { unsigned int i, j, count; struct lock_struct *tp; - struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct lock_struct *locks = br_lck->lock_data; BOOL overlap_found = False; /* No zero-zero locks for POSIX. */ @@ -1006,7 +1006,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s br_lck->num_locks = count; SAFE_FREE(br_lck->lock_data); locks = tp; - br_lck->lock_data = (void *)tp; + br_lck->lock_data = tp; br_lck->modified = True; /* Send unlock messages to any pending waiters that overlap. */ @@ -1078,7 +1078,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck, BOOL ret = True; unsigned int i; struct lock_struct lock; - const struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + const struct lock_struct *locks = br_lck->lock_data; files_struct *fsp = br_lck->fsp; lock.context.smbpid = smbpid; @@ -1135,7 +1135,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, { unsigned int i; struct lock_struct lock; - const struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + const struct lock_struct *locks = br_lck->lock_data; files_struct *fsp = br_lck->fsp; lock.context.smbpid = *psmbpid; @@ -1201,7 +1201,7 @@ BOOL brl_lock_cancel(struct byte_range_lock *br_lck, enum brl_flavour lock_flav) { unsigned int i; - struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct lock_struct *locks = br_lck->lock_data; struct lock_context context; context.smbpid = smbpid; @@ -1251,7 +1251,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) int fnum = fsp->fnum; unsigned int i, j, dcount=0; int num_deleted_windows_locks = 0; - struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct lock_struct *locks = br_lck->lock_data; struct process_id pid = procid_self(); BOOL unlock_individually = False; @@ -1586,7 +1586,7 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, talloc_set_destructor(br_lck, byte_range_lock_destructor); data = tdb_fetch(tdb, key); - br_lck->lock_data = (void *)data.dptr; + br_lck->lock_data = (struct lock_struct *)data.dptr; br_lck->num_locks = data.dsize / sizeof(struct lock_struct); if (!fsp->lockdb_clean) { @@ -1595,29 +1595,20 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, /* Go through and ensure all entries exist - remove any that don't. */ /* Makes the lockdb self cleaning at low cost. */ - struct lock_struct *locks = - (struct lock_struct *)br_lck->lock_data; - - if (!validate_lock_entries(&br_lck->num_locks, &locks)) { + if (!validate_lock_entries(&br_lck->num_locks, + &br_lck->lock_data)) { SAFE_FREE(br_lck->lock_data); TALLOC_FREE(br_lck); return NULL; } - /* - * validate_lock_entries might have changed locks. We can't - * use a direct pointer here because otherwise gcc warnes - * about strict aliasing rules being violated. - */ - br_lck->lock_data = locks; - /* Mark the lockdb as "clean" as seen from this open file. */ fsp->lockdb_clean = True; } if (DEBUGLEVEL >= 10) { unsigned int i; - struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct lock_struct *locks = br_lck->lock_data; DEBUG(10,("brl_get_locks_internal: %u current locks on dev=%.0f, inode=%.0f\n", br_lck->num_locks, (double)fsp->dev, (double)fsp->inode )); -- cgit From e6383f47629368d9dd4e803f17566a24e9d7359e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 7 May 2007 09:35:35 +0000 Subject: r22736: Start to merge the low-hanging fruit from the now 7000-line cluster patch. This changes "struct process_id" to "struct server_id", keeping both is just too much hassle. No functional change (I hope ;-)) Volker (This used to be commit 0ad4b1226c9d91b72136310d3bbb640d2c5d67b8) --- source3/locking/brlock.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 88f993e14b..c3a3ce1cb6 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -724,7 +724,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, NTSTATUS brl_lock(struct byte_range_lock *br_lck, uint32 smbpid, - struct process_id pid, + struct server_id pid, br_off start, br_off size, enum brl_type lock_type, @@ -1039,7 +1039,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s BOOL brl_unlock(struct byte_range_lock *br_lck, uint32 smbpid, - struct process_id pid, + struct server_id pid, br_off start, br_off size, enum brl_flavour lock_flav) @@ -1069,7 +1069,7 @@ BOOL brl_unlock(struct byte_range_lock *br_lck, BOOL brl_locktest(struct byte_range_lock *br_lck, uint32 smbpid, - struct process_id pid, + struct server_id pid, br_off start, br_off size, enum brl_type lock_type, @@ -1127,7 +1127,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck, NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, uint32 *psmbpid, - struct process_id pid, + struct server_id pid, br_off *pstart, br_off *psize, enum brl_type *plock_type, @@ -1195,7 +1195,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, BOOL brl_lock_cancel(struct byte_range_lock *br_lck, uint32 smbpid, - struct process_id pid, + struct server_id pid, br_off start, br_off size, enum brl_flavour lock_flav) @@ -1252,7 +1252,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck) unsigned int i, j, dcount=0; int num_deleted_windows_locks = 0; struct lock_struct *locks = br_lck->lock_data; - struct process_id pid = procid_self(); + struct server_id pid = procid_self(); BOOL unlock_individually = False; if(lp_posix_locking(fsp->conn->params)) { -- cgit From b92064fcfd804b861e2f5125078812d83b9120a6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 14 May 2007 13:01:28 +0000 Subject: r22846: Chunk one to replace message_send_pid with messaging_send: Deep inside locking/locking.c we have to send retry messages to timed lock holders. The majority of this patch passes a "struct messaging_context" down there. No functional change, survives make test. (This used to be commit bbb508414683eeddd2ee0d2d36fe620118180bbb) --- source3/locking/brlock.c | 51 ++++++++++++++++++++++++++--------------------- source3/locking/locking.c | 26 +++++++++++++++--------- 2 files changed, 45 insertions(+), 32 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index c3a3ce1cb6..d48c746161 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -584,8 +584,9 @@ OR We must cope with range splits and merges. ****************************************************************************/ -static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, - const struct lock_struct *plock) +static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx, + struct byte_range_lock *br_lck, + const struct lock_struct *plock) { unsigned int i, count; struct lock_struct *locks = br_lck->lock_data; @@ -708,9 +709,8 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, DEBUG(10,("brl_lock_posix: sending unlock message to pid %s\n", procid_str_static(&pend_lock->context.pid ))); - message_send_pid(pend_lock->context.pid, - MSG_SMB_UNLOCK, - NULL, 0, True); + messaging_send(msg_ctx, pend_lock->context.pid, + MSG_SMB_UNLOCK, &data_blob_null); } } } @@ -722,7 +722,8 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, Lock a range of bytes. ****************************************************************************/ -NTSTATUS brl_lock(struct byte_range_lock *br_lck, +NTSTATUS brl_lock(struct messaging_context *msg_ctx, + struct byte_range_lock *br_lck, uint32 smbpid, struct server_id pid, br_off start, @@ -752,7 +753,7 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, if (lock_flav == WINDOWS_LOCK) { ret = brl_lock_windows(br_lck, &lock, blocking_lock); } else { - ret = brl_lock_posix(br_lck, &lock); + ret = brl_lock_posix(msg_ctx, br_lck, &lock); } #if ZERO_ZERO @@ -767,7 +768,9 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, Unlock a range of bytes - Windows semantics. ****************************************************************************/ -static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock_struct *plock) +static BOOL brl_unlock_windows(struct messaging_context *msg_ctx, + struct byte_range_lock *br_lck, + const struct lock_struct *plock) { unsigned int i, j; struct lock_struct *locks = br_lck->lock_data; @@ -856,9 +859,8 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", procid_str_static(&pend_lock->context.pid ))); - message_send_pid(pend_lock->context.pid, - MSG_SMB_UNLOCK, - NULL, 0, True); + messaging_send(msg_ctx, pend_lock->context.pid, + MSG_SMB_UNLOCK, &data_blob_null); } } @@ -869,7 +871,9 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock Unlock a range of bytes - POSIX semantics. ****************************************************************************/ -static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_struct *plock) +static BOOL brl_unlock_posix(struct messaging_context *msg_ctx, + struct byte_range_lock *br_lck, + const struct lock_struct *plock) { unsigned int i, j, count; struct lock_struct *tp; @@ -1024,9 +1028,8 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", procid_str_static(&pend_lock->context.pid ))); - message_send_pid(pend_lock->context.pid, - MSG_SMB_UNLOCK, - NULL, 0, True); + messaging_send(msg_ctx, pend_lock->context.pid, + MSG_SMB_UNLOCK, &data_blob_null); } } @@ -1037,7 +1040,8 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s Unlock a range of bytes. ****************************************************************************/ -BOOL brl_unlock(struct byte_range_lock *br_lck, +BOOL brl_unlock(struct messaging_context *msg_ctx, + struct byte_range_lock *br_lck, uint32 smbpid, struct server_id pid, br_off start, @@ -1056,9 +1060,9 @@ BOOL brl_unlock(struct byte_range_lock *br_lck, lock.lock_flav = lock_flav; if (lock_flav == WINDOWS_LOCK) { - return brl_unlock_windows(br_lck, &lock); + return brl_unlock_windows(msg_ctx, br_lck, &lock); } else { - return brl_unlock_posix(br_lck, &lock); + return brl_unlock_posix(msg_ctx, br_lck, &lock); } } @@ -1244,7 +1248,8 @@ BOOL brl_lock_cancel(struct byte_range_lock *br_lck, fd and so we should not immediately close the fd. ****************************************************************************/ -void brl_close_fnum(struct byte_range_lock *br_lck) +void brl_close_fnum(struct messaging_context *msg_ctx, + struct byte_range_lock *br_lck) { files_struct *fsp = br_lck->fsp; uint16 tid = fsp->conn->cnum; @@ -1299,7 +1304,8 @@ void brl_close_fnum(struct byte_range_lock *br_lck) if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid) && (lock->fnum == fnum)) { - brl_unlock(br_lck, + brl_unlock(msg_ctx, + br_lck, lock->context.smbpid, pid, lock->start, @@ -1348,9 +1354,8 @@ void brl_close_fnum(struct byte_range_lock *br_lck) /* We could send specific lock info here... */ if (brl_pending_overlap(lock, pend_lock)) { - message_send_pid(pend_lock->context.pid, - MSG_SMB_UNLOCK, - NULL, 0, True); + messaging_send(msg_ctx, pend_lock->context.pid, + MSG_SMB_UNLOCK, &data_blob_null); } } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index c548d6eecb..28a7fab97d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -180,7 +180,8 @@ NTSTATUS query_lock(files_struct *fsp, Utility function called by locking requests. ****************************************************************************/ -struct byte_range_lock *do_lock(files_struct *fsp, +struct byte_range_lock *do_lock(struct messaging_context *msg_ctx, + files_struct *fsp, uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, @@ -213,7 +214,8 @@ struct byte_range_lock *do_lock(files_struct *fsp, return NULL; } - *perr = brl_lock(br_lck, + *perr = brl_lock(msg_ctx, + br_lck, lock_pid, procid_self(), offset, @@ -235,7 +237,8 @@ struct byte_range_lock *do_lock(files_struct *fsp, Utility function called by unlocking requests. ****************************************************************************/ -NTSTATUS do_unlock(files_struct *fsp, +NTSTATUS do_unlock(struct messaging_context *msg_ctx, + files_struct *fsp, uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, @@ -260,7 +263,8 @@ NTSTATUS do_unlock(files_struct *fsp, return NT_STATUS_NO_MEMORY; } - ok = brl_unlock(br_lck, + ok = brl_unlock(msg_ctx, + br_lck, lock_pid, procid_self(), offset, @@ -334,7 +338,8 @@ NTSTATUS do_lock_cancel(files_struct *fsp, Remove any locks on this fd. Called from file_close(). ****************************************************************************/ -void locking_close_file(files_struct *fsp) +void locking_close_file(struct messaging_context *msg_ctx, + files_struct *fsp) { struct byte_range_lock *br_lck; @@ -354,7 +359,7 @@ void locking_close_file(files_struct *fsp) if (br_lck) { cancel_pending_lock_requests_by_fid(fsp, br_lck); - brl_close_fnum(br_lck); + brl_close_fnum(msg_ctx, br_lck); TALLOC_FREE(br_lck); } } @@ -805,7 +810,8 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, Based on an initial code idea from SATOH Fumiyasu ********************************************************************/ -BOOL rename_share_filename(struct share_mode_lock *lck, +BOOL rename_share_filename(struct messaging_context *msg_ctx, + struct share_mode_lock *lck, const char *servicepath, const char *newname) { @@ -814,6 +820,7 @@ BOOL rename_share_filename(struct share_mode_lock *lck, size_t msg_len; char *frm = NULL; int i; + DATA_BLOB msg; if (!lck) { return False; @@ -857,6 +864,8 @@ BOOL rename_share_filename(struct share_mode_lock *lck, safe_strcpy(&frm[16], lck->servicepath, sp_len); safe_strcpy(&frm[16 + sp_len + 1], lck->filename, fn_len); + msg = data_blob_const(frm, msg_len); + /* Send the messages. */ for (i=0; inum_share_modes; i++) { struct share_mode_entry *se = &lck->share_modes[i]; @@ -874,8 +883,7 @@ BOOL rename_share_filename(struct share_mode_lock *lck, (unsigned int)lck->dev, (double)lck->ino, lck->servicepath, lck->filename )); - message_send_pid(se->pid, MSG_SMB_FILE_RENAME, - frm, msg_len, True); + messaging_send(msg_ctx, se->pid, MSG_SMB_FILE_RENAME, &msg); } return True; -- cgit From 01a7017d7b0e0cbc3b0923c43b7fe3f0b01aac0b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 May 2007 20:57:12 +0000 Subject: r23014: For all branches, ensure that if we're blocked on a POSIX lock we know nothing about that we retry the lock every 10 seconds instead of waiting for the standard select timeout. This is how we used to (and are supposed to) work. Jeremy. (This used to be commit fa18fc25a50cf13c687ae88e7e5e2dda1120e017) --- source3/locking/brlock.c | 25 ++++++++++++++++++++++--- source3/locking/locking.c | 6 ++++-- 2 files changed, 26 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index d48c746161..f3e4042d8a 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -313,7 +313,7 @@ static int lock_compare(const struct lock_struct *lck1, ****************************************************************************/ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, - const struct lock_struct *plock, BOOL blocking_lock) + struct lock_struct *plock, BOOL blocking_lock) { unsigned int i; files_struct *fsp = br_lck->fsp; @@ -322,6 +322,8 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, for (i=0; i < br_lck->num_locks; i++) { /* Do any Windows or POSIX locks conflict ? */ if (brl_conflict(&locks[i], plock)) { + /* Remember who blocked us. */ + plock->context.smbpid = locks[i].context.smbpid; return brl_lock_failed(fsp,plock,blocking_lock); } #if ZERO_ZERO @@ -346,6 +348,10 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, locks, br_lck->num_locks, &errno_ret)) { + + /* We don't know who blocked us. */ + plock->context.smbpid = 0xFFFFFFFF; + if (errno_ret == EACCES || errno_ret == EAGAIN) { return NT_STATUS_FILE_LOCK_CONFLICT; } else { @@ -586,7 +592,7 @@ OR static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx, struct byte_range_lock *br_lck, - const struct lock_struct *plock) + struct lock_struct *plock) { unsigned int i, count; struct lock_struct *locks = br_lck->lock_data; @@ -630,6 +636,8 @@ static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx, if (brl_conflict(curr_lock, plock)) { /* No games with error messages. */ SAFE_FREE(tp); + /* Remember who blocked us. */ + plock->context.smbpid = curr_lock->context.smbpid; return NT_STATUS_FILE_LOCK_CONFLICT; } /* Just copy the Windows lock into the new array. */ @@ -641,6 +649,8 @@ static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx, /* Can't block ourselves with POSIX locks. */ /* No games with error messages. */ SAFE_FREE(tp); + /* Remember who blocked us. */ + plock->context.smbpid = curr_lock->context.smbpid; return NT_STATUS_FILE_LOCK_CONFLICT; } @@ -670,6 +680,10 @@ static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx, plock->size, plock->lock_type, &errno_ret)) { + + /* We don't know who blocked us. */ + plock->context.smbpid = 0xFFFFFFFF; + if (errno_ret == EACCES || errno_ret == EAGAIN) { SAFE_FREE(tp); return NT_STATUS_FILE_LOCK_CONFLICT; @@ -730,7 +744,8 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx, br_off size, enum brl_type lock_type, enum brl_flavour lock_flav, - BOOL blocking_lock) + BOOL blocking_lock, + uint32 *psmbpid) { NTSTATUS ret; struct lock_struct lock; @@ -761,6 +776,10 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx, qsort(br_lck->lock_data, (size_t)br_lck->num_locks, sizeof(lock), lock_compare); #endif + /* If we're returning an error, return who blocked us. */ + if (!NT_STATUS_IS_OK(ret) && psmbpid) { + *psmbpid = lock.context.smbpid; + } return ret; } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 28a7fab97d..56ff3b9790 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -188,7 +188,8 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx, enum brl_type lock_type, enum brl_flavour lock_flav, BOOL blocking_lock, - NTSTATUS *perr) + NTSTATUS *perr, + uint32 *plock_pid) { struct byte_range_lock *br_lck = NULL; @@ -222,7 +223,8 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx, count, lock_type, lock_flav, - blocking_lock); + blocking_lock, + plock_pid); /* blocking ie. pending, locks also count here, * as this is an efficiency counter to avoid checking -- cgit From 38daf36d124fbec74afba3a834481001d8000bc6 Mon Sep 17 00:00:00 2001 From: James Peach Date: Wed, 23 May 2007 20:38:14 +0000 Subject: r23096: Make the lock failure message prettier. (This used to be commit 853f41edb8b23d7fdfaba9c4bb37dc27af92a982) --- source3/locking/posix.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 8bb7f605e3..338ee0416b 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -195,8 +195,8 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count)); - DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); - DEBUG(0,("on 32 bit NFS mounted file systems.\n")); + DEBUGADD(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); + DEBUGADD(0,("on 32 bit NFS mounted file systems.\n")); /* * If the offset is > 0x7FFFFFFF then this will cause problems on @@ -240,8 +240,8 @@ static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)*poffset,(double)*pcount)); - DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); - DEBUG(0,("on 32 bit NFS mounted file systems.\n")); + DEBUGADD(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); + DEBUGADD(0,("on 32 bit NFS mounted file systems.\n")); /* * If the offset is > 0x7FFFFFFF then this will cause problems on -- cgit From dbfd6bf8c8cc9945c4ba7e22ac44b1f33f9c7ce6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 May 2007 21:32:10 +0000 Subject: r23100: Implement the delete on close semantics I've just tested for in Samba4 smbtorture. Fix rename on an open file handle. Needed for 3.0.25a. Jeremy. (This used to be commit a301467d5f645dada27093ddfd74890b88bb4ce8) --- source3/locking/locking.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 56ff3b9790..17c6d3e9c3 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1001,10 +1001,13 @@ static void add_share_mode_entry(struct share_mode_lock *lck, } void set_share_mode(struct share_mode_lock *lck, files_struct *fsp, - uid_t uid, uint16 mid, uint16 op_type) + uid_t uid, uint16 mid, uint16 op_type, BOOL initial_delete_on_close_allowed) { struct share_mode_entry entry; fill_share_mode_entry(&entry, fsp, uid, mid, op_type); + if (initial_delete_on_close_allowed) { + entry.flags |= SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE; + } add_share_mode_entry(lck, &entry); } @@ -1204,6 +1207,22 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, return NT_STATUS_OK; } +/**************************************************************************** + Do we have an open file handle that created this entry ? +****************************************************************************/ + +BOOL can_set_initial_delete_on_close(const struct share_mode_lock *lck) +{ + int i; + + for (i=0; inum_share_modes; i++) { + if (lck->share_modes[i].flags & SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE) { + return True; + } + } + return False; +} + /************************************************************************* Return a talloced copy of a UNIX_USER_TOKEN. NULL on fail. (Should this be in locking.c.... ?). @@ -1304,6 +1323,31 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE return True; } +/**************************************************************************** + Sets the allow initial delete on close flag for this share mode. +****************************************************************************/ + +BOOL set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct *fsp, BOOL delete_on_close) +{ + struct share_mode_entry entry, *e; + + /* Don't care about the pid owner being correct here - just a search. */ + fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK); + + e = find_share_mode_entry(lck, &entry); + if (e == NULL) { + return False; + } + + if (delete_on_close) { + e->flags |= SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE; + } else { + e->flags &= ~SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE; + } + lck->modified = True; + return True; +} + struct forall_state { void (*fn)(const struct share_mode_entry *entry, const char *sharepath, -- cgit From 4db33293ab50de99484122e7050e33c5f97980a5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 May 2007 09:29:26 +0000 Subject: r23162: Make use of messaging_send_buf (This used to be commit 3f8186fe85a897b104cd825a005333259d6d008b) --- source3/locking/locking.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 17c6d3e9c3..aacb056c07 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -822,7 +822,6 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, size_t msg_len; char *frm = NULL; int i; - DATA_BLOB msg; if (!lck) { return False; @@ -866,8 +865,6 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, safe_strcpy(&frm[16], lck->servicepath, sp_len); safe_strcpy(&frm[16 + sp_len + 1], lck->filename, fn_len); - msg = data_blob_const(frm, msg_len); - /* Send the messages. */ for (i=0; inum_share_modes; i++) { struct share_mode_entry *se = &lck->share_modes[i]; @@ -885,7 +882,8 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, (unsigned int)lck->dev, (double)lck->ino, lck->servicepath, lck->filename )); - messaging_send(msg_ctx, se->pid, MSG_SMB_FILE_RENAME, &msg); + messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME, + (uint8 *)frm, msg_len); } return True; -- cgit From 6e5c23728cb290b8defe165fb3a0815521229328 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 May 2007 09:57:05 +0000 Subject: r23163: Convert locking.tdb to dbwrap (This used to be commit afe90224bf151acf6c7be8974408f79cfd459dbf) --- source3/locking/locking.c | 200 +++++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 91 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index aacb056c07..f83467ad83 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -42,7 +42,7 @@ #define DBGC_CLASS DBGC_LOCKING /* the locking database handle */ -static TDB_CONTEXT *tdb; +static struct db_context *lock_db; /**************************************************************************** Debugging aids :-). @@ -376,23 +376,21 @@ BOOL locking_init(int read_only) { brl_init(read_only); - if (tdb) + if (lock_db) return True; - tdb = tdb_open_log(lock_path("locking.tdb"), - lp_open_files_db_hash_size(), - TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), - read_only?O_RDONLY:O_RDWR|O_CREAT, - 0644); + lock_db = db_open(NULL, lock_path("locking.tdb"), + lp_open_files_db_hash_size(), + TDB_DEFAULT + |(read_only?0x0:TDB_CLEAR_IF_FIRST) + |TDB_VOLATILE, + read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); - if (!tdb) { + if (!lock_db) { DEBUG(0,("ERROR: Failed to initialise locking database\n")); return False; } - /* Activate the per-hashchain freelist */ - tdb_set_max_dead(tdb, 5); - if (!posix_locking_init(read_only)) return False; @@ -407,15 +405,11 @@ BOOL locking_init(int read_only) BOOL locking_end(void) { - BOOL ret = True; - brl_shutdown(open_read_only); - if (tdb) { - if (tdb_close(tdb) != 0) - ret = False; + if (lock_db) { + TALLOC_FREE(lock_db); } - - return ret; + return True; } /******************************************************************* @@ -705,11 +699,11 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) static int share_mode_lock_destructor(struct share_mode_lock *lck) { - TDB_DATA key = locking_key(lck->dev, lck->ino); + NTSTATUS status; TDB_DATA data; if (!lck->modified) { - goto done; + return 0; } data = unparse_share_modes(lck); @@ -717,38 +711,34 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck) if (data.dptr == NULL) { if (!lck->fresh) { /* There has been an entry before, delete it */ - if (tdb_delete(tdb, key) == -1) { + + status = lck->record->delete_rec(lck->record); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("delete_rec returned %s\n", + nt_errstr(status))); smb_panic("Could not delete share entry\n"); } } goto done; } - if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) { + status = lck->record->store(lck->record, data, TDB_REPLACE); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("store returned %s\n", nt_errstr(status))); smb_panic("Could not store share mode entry\n"); } done: - tdb_chainunlock(tdb, key); return 0; } -struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, - SMB_DEV_T dev, SMB_INO_T ino, - const char *servicepath, - const char *fname) +static BOOL fill_share_mode_lock(struct share_mode_lock *lck, + SMB_DEV_T dev, SMB_INO_T ino, + const char *servicepath, + const char *fname, + TDB_DATA share_mode_data) { - struct share_mode_lock *lck; - TDB_DATA key = locking_key(dev, ino); - TDB_DATA data; - - lck = TALLOC_P(mem_ctx, struct share_mode_lock); - if (lck == NULL) { - DEBUG(0, ("talloc failed\n")); - return NULL; - } - /* Ensure we set every field here as the destructor must be valid even if parse_share_modes fails. */ @@ -763,44 +753,86 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, lck->fresh = False; lck->modified = False; - if (tdb_chainlock(tdb, key) != 0) { - DEBUG(3, ("Could not lock share entry\n")); - TALLOC_FREE(lck); - return NULL; - } - - /* We must set the destructor immediately after the chainlock - ensure the lock is cleaned up on any of the error return - paths below. */ - - talloc_set_destructor(lck, share_mode_lock_destructor); - - data = tdb_fetch(tdb, key); - lck->fresh = (data.dptr == NULL); + lck->fresh = (share_mode_data.dptr == NULL); if (lck->fresh) { - if (fname == NULL || servicepath == NULL) { - TALLOC_FREE(lck); - return NULL; + return False; } lck->filename = talloc_strdup(lck, fname); lck->servicepath = talloc_strdup(lck, servicepath); if (lck->filename == NULL || lck->servicepath == NULL) { DEBUG(0, ("talloc failed\n")); - TALLOC_FREE(lck); - return NULL; + return False; } } else { - if (!parse_share_modes(data, lck)) { + if (!parse_share_modes(share_mode_data, lck)) { DEBUG(0, ("Could not parse share modes\n")); - TALLOC_FREE(lck); - SAFE_FREE(data.dptr); - return NULL; + return False; } } - SAFE_FREE(data.dptr); + return True; +} + +struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, + SMB_DEV_T dev, SMB_INO_T ino, + const char *servicepath, + const char *fname) +{ + struct share_mode_lock *lck; + TDB_DATA key = locking_key(dev, ino); + + if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + if (!(lck->record = lock_db->fetch_locked(lock_db, lck, key))) { + DEBUG(3, ("Could not lock share entry\n")); + TALLOC_FREE(lck); + return NULL; + } + + if (!fill_share_mode_lock(lck, dev, ino, servicepath, fname, + lck->record->value)) { + DEBUG(3, ("fill_share_mode_lock failed\n")); + TALLOC_FREE(lck); + return NULL; + } + + talloc_set_destructor(lck, share_mode_lock_destructor); + + return lck; +} + +struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, + SMB_DEV_T dev, SMB_INO_T ino, + const char *servicepath, + const char *fname) +{ + struct share_mode_lock *lck; + TDB_DATA key = locking_key(dev, ino); + TDB_DATA data; + + if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + if (lock_db->fetch(lock_db, lck, key, &data) == -1) { + DEBUG(3, ("Could not fetch share entry\n")); + TALLOC_FREE(lck); + return NULL; + } + + if (!fill_share_mode_lock(lck, dev, ino, servicepath, fname, data)) { + DEBUG(3, ("fill_share_mode_lock failed\n")); + TALLOC_FREE(lck); + return NULL; + } + + TALLOC_FREE(data.dptr); return lck; } @@ -889,29 +921,16 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, return True; } -static int pull_delete_on_close_flag(TDB_DATA key, TDB_DATA dbuf, - void *private_data) -{ - BOOL *result = (BOOL *)private_data; - struct locking_data *data; - - if (dbuf.dsize < sizeof(struct locking_data)) { - smb_panic("PANIC: parse_share_modes: buffer too short.\n"); - } - - data = (struct locking_data *)dbuf.dptr; - - *result = data->u.s.delete_on_close; - return 0; -} - BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) { - TDB_DATA key = locking_key(dev, inode); - BOOL result = False; - - tdb_parse_record(tdb, key, pull_delete_on_close_flag, - (void *)&result); + BOOL result; + struct share_mode_lock *lck; + + if (!(lck = fetch_share_mode_unlocked(NULL, dev, inode, NULL, NULL))) { + return False; + } + result = lck->delete_on_close; + TALLOC_FREE(lck); return result; } @@ -1354,8 +1373,7 @@ struct forall_state { void *private_data; }; -static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, - void *_state) +static int traverse_fn(struct db_record *rec, void *_state) { struct forall_state *state = (struct forall_state *)_state; struct locking_data *data; @@ -1365,15 +1383,15 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, int i; /* Ensure this is a locking_key record. */ - if (kbuf.dsize != sizeof(struct locking_key)) + if (rec->key.dsize != sizeof(struct locking_key)) return 0; - data = (struct locking_data *)dbuf.dptr; - shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data)); - sharepath = (const char *)dbuf.dptr + sizeof(*data) + + data = (struct locking_data *)rec->value.dptr; + shares = (struct share_mode_entry *)(rec->value.dptr + sizeof(*data)); + sharepath = (const char *)rec->value.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares) + data->u.s.delete_token_size; - fname = (const char *)dbuf.dptr + sizeof(*data) + + fname = (const char *)rec->value.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares) + data->u.s.delete_token_size + strlen(sharepath) + 1; @@ -1396,11 +1414,11 @@ int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, { struct forall_state state; - if (tdb == NULL) + if (lock_db == NULL) return 0; state.fn = fn; state.private_data = private_data; - return tdb_traverse(tdb, traverse_fn, (void *)&state); + return lock_db->traverse(lock_db, traverse_fn, (void *)&state); } -- cgit From 1e6af7084bafe29021b0ad2ee49c3bbf90e350ca Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 May 2007 10:25:23 +0000 Subject: r23164: Minor cosmetic checkin (This used to be commit 8de1ac9fadb1b0dcac28eef32f7826e9e3a7eca4) --- source3/locking/locking.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f83467ad83..cc6957b4e3 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -382,8 +382,8 @@ BOOL locking_init(int read_only) lock_db = db_open(NULL, lock_path("locking.tdb"), lp_open_files_db_hash_size(), TDB_DEFAULT - |(read_only?0x0:TDB_CLEAR_IF_FIRST) - |TDB_VOLATILE, + |TDB_VOLATILE + |(read_only?0x0:TDB_CLEAR_IF_FIRST), read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); if (!lock_db) { -- cgit From 40a3b796ceac468b887b981422680a8139142a07 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 May 2007 10:35:14 +0000 Subject: r23165: Convert brlock.tdb to dbwrap (This used to be commit 84f9885cf8cc57dcf3c2738d6b245de314890a41) --- source3/locking/brlock.c | 89 +++++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 38 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index f3e4042d8a..d8dcc6f642 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -34,7 +34,7 @@ /* The open brlock.tdb database. */ -static TDB_CONTEXT *tdb; +static struct db_context *brlock_db; /**************************************************************************** Debug info at level 10 for lock struct. @@ -261,21 +261,20 @@ static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *loc void brl_init(int read_only) { - if (tdb) { + if (brlock_db) { return; } - tdb = tdb_open_log(lock_path("brlock.tdb"), - lp_open_files_db_hash_size(), - TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 ); - if (!tdb) { + brlock_db = db_open(NULL, lock_path("brlock.tdb"), + lp_open_files_db_hash_size(), + TDB_DEFAULT + |TDB_VOLATILE + |(read_only?0x0:TDB_CLEAR_IF_FIRST), + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 ); + if (!brlock_db) { DEBUG(0,("Failed to open byte range locking database %s\n", lock_path("brlock.tdb"))); return; } - - /* Activate the per-hashchain freelist */ - tdb_set_max_dead(tdb, 5); } /**************************************************************************** @@ -284,10 +283,10 @@ void brl_init(int read_only) void brl_shutdown(int read_only) { - if (!tdb) { + if (!brlock_db) { return; } - tdb_close(tdb); + TALLOC_FREE(brlock_db); } #if ZERO_ZERO @@ -1453,7 +1452,7 @@ static BOOL validate_lock_entries(unsigned int *pnum_entries, struct lock_struct on each lock. ****************************************************************************/ -static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +static int traverse_fn(struct db_record *rec, void *state) { struct lock_struct *locks; struct lock_key *key; @@ -1466,13 +1465,14 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st /* In a traverse function we must make a copy of dbuf before modifying it. */ - locks = (struct lock_struct *)memdup(dbuf.dptr, dbuf.dsize); + locks = (struct lock_struct *)memdup(rec->value.dptr, + rec->value.dsize); if (!locks) { return -1; /* Terminate traversal. */ } - key = (struct lock_key *)kbuf.dptr; - orig_num_locks = num_locks = dbuf.dsize/sizeof(*locks); + key = (struct lock_key *)rec->key.dptr; + orig_num_locks = num_locks = rec->value.dsize/sizeof(*locks); /* Ensure the lock db is clean of entries from invalid processes. */ @@ -1482,13 +1482,10 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st } if (orig_num_locks != num_locks) { - dbuf.dptr = (uint8 *)locks; - dbuf.dsize = num_locks * sizeof(*locks); - - if (dbuf.dsize) { - tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE); + if (rec->value.dsize) { + rec->store(rec, rec->value, TDB_REPLACE); } else { - tdb_delete(ttdb, kbuf); + rec->delete_rec(rec); } } @@ -1512,10 +1509,10 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st int brl_forall(BRLOCK_FN(fn)) { - if (!tdb) { + if (!brlock_db) { return 0; } - return tdb_traverse(tdb, traverse_fn, (void *)fn); + return brlock_db->traverse(brlock_db, traverse_fn, (void *)fn); } /******************************************************************* @@ -1541,25 +1538,31 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) if (br_lck->num_locks == 0) { /* No locks - delete this entry. */ - if (tdb_delete(tdb, key) == -1) { + NTSTATUS status = br_lck->record->delete_rec(br_lck->record); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("delete_rec returned %s\n", + nt_errstr(status))); smb_panic("Could not delete byte range lock entry\n"); } } else { TDB_DATA data; + NTSTATUS status; + data.dptr = (uint8 *)br_lck->lock_data; data.dsize = br_lck->num_locks * sizeof(struct lock_struct); - if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) { + status = br_lck->record->store(br_lck->record, data, + TDB_REPLACE); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("store returned %s\n", nt_errstr(status))); smb_panic("Could not store byte range mode entry\n"); } } done: - if (!br_lck->read_only) { - tdb_chainunlock(tdb, key); - } SAFE_FREE(br_lck->lock_data); + TALLOC_FREE(br_lck->record); return 0; } @@ -1572,8 +1575,7 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, files_struct *fsp, BOOL read_only) { - TDB_DATA key; - TDB_DATA data; + TDB_DATA key, data; struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock); if (br_lck == NULL) { @@ -1597,22 +1599,33 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, } if (read_only) { - br_lck->read_only = True; - } else { - if (tdb_chainlock(tdb, key) != 0) { + if (brlock_db->fetch(brlock_db, br_lck, key, &data) == -1) { + DEBUG(3, ("Could not fetch byte range lock record\n")); + TALLOC_FREE(br_lck); + return NULL; + } + br_lck->record = NULL; + } + else { + br_lck->record = brlock_db->fetch_locked(brlock_db, br_lck, key); + + if (br_lck->record == NULL) { DEBUG(3, ("Could not lock byte range lock entry\n")); TALLOC_FREE(br_lck); return NULL; } - br_lck->read_only = False; + + data = br_lck->record->value; } + br_lck->read_only = read_only; + talloc_set_destructor(br_lck, byte_range_lock_destructor); - data = tdb_fetch(tdb, key); - br_lck->lock_data = (struct lock_struct *)data.dptr; br_lck->num_locks = data.dsize / sizeof(struct lock_struct); - + br_lck->lock_data = SMB_MALLOC_ARRAY(struct lock_struct, br_lck->num_locks); + memcpy(br_lck->lock_data, data.dptr, data.dsize); + if (!fsp->lockdb_clean) { /* This is the first time we've accessed this. */ -- cgit From 8c57860cc79f37296785b4f7ae67fd5a8a543e39 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 May 2007 17:12:08 +0000 Subject: r23169: Merge 535 of Tridge's bzr tree: store the right data after cleaning lock records. This fixes RAW-BENCH-LOCK after a recovery on a cluster (This used to be commit 3da3086dbf594fbdc4cfabf78f8d3ea1df4dc8ce) --- source3/locking/brlock.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index d8dcc6f642..8e2f7ce41a 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1482,8 +1482,11 @@ static int traverse_fn(struct db_record *rec, void *state) } if (orig_num_locks != num_locks) { - if (rec->value.dsize) { - rec->store(rec, rec->value, TDB_REPLACE); + if (num_locks) { + TDB_DATA data; + data.dptr = (uint8_t *)locks; + data.dsize = num_locks*sizeof(struct lock_struct); + rec->store(rec, data, TDB_REPLACE); } else { rec->delete_rec(rec); } -- cgit From e8156439f24137b5418baad20a7f00f6949cfe29 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 09:30:34 +0000 Subject: r23183: Check in a change made by Tridge: This replaces the internal explicit dev/ino file id representation by a "struct file_id". This is necessary as cluster file systems and NFS don't necessarily assign the same device number to the shared file system. With this structure in place we can now easily add different schemes to map a file to a unique 64-bit device node. Jeremy, you might note that I did not change the external interface of smb_share_modes.c. Volker (This used to be commit 9b10dbbd5de8813fc15ebbb6be9b18010ffe8139) --- source3/locking/brlock.c | 20 +++++------ source3/locking/locking.c | 86 +++++++++++++++++++---------------------------- source3/locking/posix.c | 26 +++++--------- 3 files changed, 52 insertions(+), 80 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 8e2f7ce41a..a37afbddd5 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1455,7 +1455,7 @@ static BOOL validate_lock_entries(unsigned int *pnum_entries, struct lock_struct static int traverse_fn(struct db_record *rec, void *state) { struct lock_struct *locks; - struct lock_key *key; + struct file_id *key; unsigned int i; unsigned int num_locks = 0; unsigned int orig_num_locks = 0; @@ -1471,7 +1471,7 @@ static int traverse_fn(struct db_record *rec, void *state) return -1; /* Terminate traversal. */ } - key = (struct lock_key *)rec->key.dptr; + key = (struct file_id *)rec->key.dptr; orig_num_locks = num_locks = rec->value.dsize/sizeof(*locks); /* Ensure the lock db is clean of entries from invalid processes. */ @@ -1493,8 +1493,7 @@ static int traverse_fn(struct db_record *rec, void *state) } for ( i=0; idevice, - key->inode, + traverse_callback(*key, locks[i].context.pid, locks[i].lock_type, locks[i].lock_flav, @@ -1529,7 +1528,7 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) TDB_DATA key; key.dptr = (uint8 *)&br_lck->key; - key.dsize = sizeof(struct lock_key); + key.dsize = sizeof(struct file_id); if (br_lck->read_only) { SMB_ASSERT(!br_lck->modified); @@ -1588,12 +1587,11 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, br_lck->fsp = fsp; br_lck->num_locks = 0; br_lck->modified = False; - memset(&br_lck->key, '\0', sizeof(struct lock_key)); - br_lck->key.device = fsp->dev; - br_lck->key.inode = fsp->inode; + memset(&br_lck->key, '\0', sizeof(struct file_id)); + br_lck->key = fsp->file_id; key.dptr = (uint8 *)&br_lck->key; - key.dsize = sizeof(struct lock_key); + key.dsize = sizeof(struct file_id); if (!fsp->lockdb_clean) { /* We must be read/write to clean @@ -1649,9 +1647,9 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, if (DEBUGLEVEL >= 10) { unsigned int i; struct lock_struct *locks = br_lck->lock_data; - DEBUG(10,("brl_get_locks_internal: %u current locks on dev=%.0f, inode=%.0f\n", + DEBUG(10,("brl_get_locks_internal: %u current locks on file_id %s\n", br_lck->num_locks, - (double)fsp->dev, (double)fsp->inode )); + file_id_static_string(&fsp->file_id))); for( i = 0; i < br_lck->num_locks; i++) { print_lock_struct(i, &locks[i]); } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index cc6957b4e3..c02304addf 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -416,24 +416,11 @@ BOOL locking_end(void) Form a static locking key for a dev/inode pair. ******************************************************************/ -/* key and data records in the tdb locking database */ -struct locking_key { - SMB_DEV_T dev; - SMB_INO_T ino; -}; - -/******************************************************************* - Form a static locking key for a dev/inode pair. -******************************************************************/ - -static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) +static TDB_DATA locking_key(struct file_id id) { - static struct locking_key key; + static struct file_id key; TDB_DATA kbuf; - - memset(&key, '\0', sizeof(key)); - key.dev = dev; - key.ino = inode; + key = id; kbuf.dptr = (uint8 *)&key; kbuf.dsize = sizeof(key); return kbuf; @@ -449,15 +436,15 @@ char *share_mode_str(int num, struct share_mode_entry *e) slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s " "pid = %s, share_access = 0x%x, private_options = 0x%x, " - "access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, " - "uid = %u, flags = %u, dev = 0x%x, inode = %.0f", + "access_mask = 0x%x, mid = 0x%x, type= 0x%x, gen_id = %lu, " + "uid = %u, flags = %u, file_id %s", num, e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "", procid_str_static(&e->pid), e->share_access, e->private_options, e->access_mask, e->op_mid, e->op_type, e->share_file_id, (unsigned int)e->uid, (unsigned int)e->flags, - (unsigned int)e->dev, (double)e->inode ); + file_id_static_string(&e->id)); return share_str; } @@ -734,7 +721,7 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck) } static BOOL fill_share_mode_lock(struct share_mode_lock *lck, - SMB_DEV_T dev, SMB_INO_T ino, + struct file_id id, const char *servicepath, const char *fname, TDB_DATA share_mode_data) @@ -744,8 +731,7 @@ static BOOL fill_share_mode_lock(struct share_mode_lock *lck, lck->servicepath = NULL; lck->filename = NULL; - lck->dev = dev; - lck->ino = ino; + lck->id = id; lck->num_share_modes = 0; lck->share_modes = NULL; lck->delete_token = NULL; @@ -776,12 +762,15 @@ static BOOL fill_share_mode_lock(struct share_mode_lock *lck, } struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, - SMB_DEV_T dev, SMB_INO_T ino, + struct file_id id, const char *servicepath, const char *fname) { struct share_mode_lock *lck; - TDB_DATA key = locking_key(dev, ino); + TDB_DATA key; + + key.dptr = (unsigned char *)&id; + key.dsize = sizeof(id); if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) { DEBUG(0, ("talloc failed\n")); @@ -794,7 +783,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, return NULL; } - if (!fill_share_mode_lock(lck, dev, ino, servicepath, fname, + if (!fill_share_mode_lock(lck, id, servicepath, fname, lck->record->value)) { DEBUG(3, ("fill_share_mode_lock failed\n")); TALLOC_FREE(lck); @@ -807,12 +796,12 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, } struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, - SMB_DEV_T dev, SMB_INO_T ino, + struct file_id id, const char *servicepath, const char *fname) { struct share_mode_lock *lck; - TDB_DATA key = locking_key(dev, ino); + TDB_DATA key = locking_key(id); TDB_DATA data; if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) { @@ -826,7 +815,7 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, return NULL; } - if (!fill_share_mode_lock(lck, dev, ino, servicepath, fname, data)) { + if (!fill_share_mode_lock(lck, id, servicepath, fname, data)) { DEBUG(3, ("fill_share_mode_lock failed\n")); TALLOC_FREE(lck); return NULL; @@ -889,8 +878,7 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, return False; } - SDEV_T_VAL(frm,0,lck->dev); - SINO_T_VAL(frm,8,lck->ino); + push_file_id_16(frm, &lck->id); DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len )); @@ -909,10 +897,10 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, } DEBUG(10,("rename_share_filename: sending rename message to pid %s " - "dev %x, inode %.0f sharepath %s newname %s\n", - procid_str_static(&se->pid), - (unsigned int)lck->dev, (double)lck->ino, - lck->servicepath, lck->filename )); + "file_id %s sharepath %s newname %s\n", + procid_str_static(&se->pid), + file_id_static_string(&lck->id), + lck->servicepath, lck->filename )); messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME, (uint8 *)frm, msg_len); @@ -921,12 +909,12 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, return True; } -BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) +BOOL get_delete_on_close_flag(struct file_id id) { BOOL result; struct share_mode_lock *lck; - if (!(lck = fetch_share_mode_unlocked(NULL, dev, inode, NULL, NULL))) { + if (!(lck = fetch_share_mode_unlocked(NULL, id, NULL, NULL))) { return False; } result = lck->delete_on_close; @@ -973,16 +961,15 @@ static void fill_share_mode_entry(struct share_mode_entry *e, e->op_type = op_type; e->time.tv_sec = fsp->open_time.tv_sec; e->time.tv_usec = fsp->open_time.tv_usec; - e->dev = fsp->dev; - e->inode = fsp->inode; - e->share_file_id = fsp->fh->file_id; + e->id = fsp->file_id; + e->share_file_id = fsp->fh->gen_id; e->uid = (uint32)uid; e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0; } static void fill_deferred_open_entry(struct share_mode_entry *e, const struct timeval request_time, - SMB_DEV_T dev, SMB_INO_T ino, uint16 mid) + struct file_id id, uint16 mid) { ZERO_STRUCTP(e); e->pid = procid_self(); @@ -990,8 +977,7 @@ static void fill_deferred_open_entry(struct share_mode_entry *e, e->op_type = DEFERRED_OPEN_ENTRY; e->time.tv_sec = request_time.tv_sec; e->time.tv_usec = request_time.tv_usec; - e->dev = dev; - e->inode = ino; + e->id = id; e->uid = (uint32)-1; e->flags = 0; } @@ -1030,10 +1016,10 @@ void set_share_mode(struct share_mode_lock *lck, files_struct *fsp, void add_deferred_open(struct share_mode_lock *lck, uint16 mid, struct timeval request_time, - SMB_DEV_T dev, SMB_INO_T ino) + struct file_id id) { struct share_mode_entry entry; - fill_deferred_open_entry(&entry, request_time, dev, ino, mid); + fill_deferred_open_entry(&entry, request_time, id, mid); add_share_mode_entry(lck, &entry); } @@ -1052,8 +1038,7 @@ static BOOL share_modes_identical(struct share_mode_entry *e1, fsp->share_access field. */ return (procid_equal(&e1->pid, &e2->pid) && - e1->dev == e2->dev && - e1->inode == e2->inode && + file_id_equal(&e1->id, &e2->id) && e1->share_file_id == e2->share_file_id ); } @@ -1062,8 +1047,7 @@ static BOOL deferred_open_identical(struct share_mode_entry *e1, { return (procid_equal(&e1->pid, &e2->pid) && (e1->op_mid == e2->op_mid) && - (e1->dev == e2->dev) && - (e1->inode == e2->inode)); + file_id_equal(&e1->id, &e2->id)); } static struct share_mode_entry *find_share_mode_entry(struct share_mode_lock *lck, @@ -1114,7 +1098,7 @@ void del_deferred_open_entry(struct share_mode_lock *lck, uint16 mid) struct share_mode_entry entry, *e; fill_deferred_open_entry(&entry, timeval_zero(), - lck->dev, lck->ino, mid); + lck->id, mid); e = find_share_mode_entry(lck, &entry); if (e == NULL) { @@ -1325,7 +1309,7 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE return True; } - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { return False; } @@ -1383,7 +1367,7 @@ static int traverse_fn(struct db_record *rec, void *_state) int i; /* Ensure this is a locking_key record. */ - if (rec->key.dsize != sizeof(struct locking_key)) + if (rec->key.dsize != sizeof(struct file_id)) return 0; data = (struct locking_data *)rec->value.dptr; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 338ee0416b..73fc2c7bd0 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -318,28 +318,19 @@ BOOL is_posix_locked(files_struct *fsp, /* The key used in the in-memory POSIX databases. */ struct lock_ref_count_key { - SMB_DEV_T device; - SMB_INO_T inode; + struct file_id id; char r; }; -struct fd_key { - SMB_DEV_T device; - SMB_INO_T inode; -}; - /******************************************************************* Form a static locking key for a dev/inode pair for the fd array. ******************************************************************/ -static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode) +static TDB_DATA fd_array_key(struct file_id id) { - static struct fd_key key; + static struct file_id key; TDB_DATA kbuf; - - memset(&key, '\0', sizeof(key)); - key.device = dev; - key.inode = inode; + key = id; kbuf.dptr = (uint8 *)&key; kbuf.dsize = sizeof(key); return kbuf; @@ -349,14 +340,13 @@ static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode) Form a static locking key for a dev/inode pair for the lock ref count ******************************************************************/ -static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode) +static TDB_DATA locking_ref_count_key(struct file_id id) { static struct lock_ref_count_key key; TDB_DATA kbuf; memset(&key, '\0', sizeof(key)); - key.device = dev; - key.inode = inode; + key.id = id; key.r = 'r'; kbuf.dptr = (uint8 *)&key; kbuf.dsize = sizeof(key); @@ -369,7 +359,7 @@ static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode) static TDB_DATA fd_array_key_fsp(files_struct *fsp) { - return fd_array_key(fsp->dev, fsp->inode); + return fd_array_key(fsp->file_id); } /******************************************************************* @@ -378,7 +368,7 @@ static TDB_DATA fd_array_key_fsp(files_struct *fsp) static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp) { - return locking_ref_count_key(fsp->dev, fsp->inode); + return locking_ref_count_key(fsp->file_id); } /******************************************************************* -- cgit From d3ed91d9e1f3ba9f3d5093b3607dd563b37c27ed Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 13:26:44 +0000 Subject: r23195: Add void *private_data to brl_forall (This used to be commit c91b2bdc160d76bf0b0770fe7f92cbc7124d6c3c) --- source3/locking/brlock.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index a37afbddd5..b51076bf43 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1447,6 +1447,15 @@ static BOOL validate_lock_entries(unsigned int *pnum_entries, struct lock_struct return True; } +struct brl_forall_cb { + void (*fn)(struct file_id id, struct server_id pid, + enum brl_type lock_type, + enum brl_flavour lock_flav, + br_off start, br_off size, + void *private_data); + void *private_data; +}; + /**************************************************************************** Traverse the whole database with this function, calling traverse_callback on each lock. @@ -1454,14 +1463,13 @@ static BOOL validate_lock_entries(unsigned int *pnum_entries, struct lock_struct static int traverse_fn(struct db_record *rec, void *state) { + struct brl_forall_cb *cb = (struct brl_forall_cb *)state; struct lock_struct *locks; struct file_id *key; unsigned int i; unsigned int num_locks = 0; unsigned int orig_num_locks = 0; - BRLOCK_FN(traverse_callback) = (BRLOCK_FN_CAST())state; - /* In a traverse function we must make a copy of dbuf before modifying it. */ @@ -1493,12 +1501,13 @@ static int traverse_fn(struct db_record *rec, void *state) } for ( i=0; ifn(*key, + locks[i].context.pid, + locks[i].lock_type, + locks[i].lock_flav, + locks[i].start, + locks[i].size, + cb->private_data); } SAFE_FREE(locks); @@ -1509,12 +1518,21 @@ static int traverse_fn(struct db_record *rec, void *state) Call the specified function on each lock in the database. ********************************************************************/ -int brl_forall(BRLOCK_FN(fn)) +int brl_forall(void (*fn)(struct file_id id, struct server_id pid, + enum brl_type lock_type, + enum brl_flavour lock_flav, + br_off start, br_off size, + void *private_data), + void *private_data) { + struct brl_forall_cb cb; + if (!brlock_db) { return 0; } - return brlock_db->traverse(brlock_db, traverse_fn, (void *)fn); + cb.fn = fn; + cb.private_data = private_data; + return brlock_db->traverse(brlock_db, traverse_fn, &cb); } /******************************************************************* -- cgit From 3f5742e20b30010ef88e19b6ee41c6b071258aee Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 14:49:19 +0000 Subject: r23204: Add MSG_SMB_BRL_VALIDATE. Tridge, this is a bit different from your bzr branch, please check if it fulfils your needs. Two changes: The validation is not done inside the brlock.c traverse_fn, it's done as a separate routine. Secondly, this patch does not call the checker routines in smbcontrol directly but depends on a running smbd. (This used to be commit 7e39d77c1f90d9025cab08918385d140e20ca25b) --- source3/locking/brlock.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index b51076bf43..a50d4faa52 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1686,3 +1686,109 @@ struct byte_range_lock *brl_get_locks_readonly(TALLOC_CTX *mem_ctx, { return brl_get_locks_internal(mem_ctx, fsp, True); } + +struct brl_revalidate_state { + ssize_t array_size; + uint32 num_pids; + struct server_id *pids; +}; + +/* + * Collect PIDs of all processes with pending entries + */ + +static void brl_revalidate_collect(struct file_id id, struct server_id pid, + enum brl_type lock_type, + enum brl_flavour lock_flav, + br_off start, br_off size, + void *private_data) +{ + struct brl_revalidate_state *state = + (struct brl_revalidate_state *)private_data; + + if (!IS_PENDING_LOCK(lock_type)) { + return; + } + + add_to_large_array(state, sizeof(pid), (void *)&pid, + &state->pids, &state->num_pids, + &state->array_size); +} + +/* + * qsort callback to sort the processes + */ + +static int compare_procids(const void *p1, const void *p2) +{ + const struct server_id *i1 = (struct server_id *)i1; + const struct server_id *i2 = (struct server_id *)i2; + + if (i1->pid < i2->pid) return -1; + if (i2->pid > i2->pid) return 1; + return 0; +} + +/* + * Send a MSG_SMB_UNLOCK message to all processes with pending byte range + * locks so that they retry. Mainly used in the cluster code after a node has + * died. + * + * Done in two steps to avoid double-sends: First we collect all entries in an + * array, then qsort that array and only send to non-dupes. + */ + +static void brl_revalidate(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct brl_revalidate_state *state; + uint32 i; + struct server_id last_pid; + + if (!(state = TALLOC_ZERO_P(NULL, struct brl_revalidate_state))) { + DEBUG(0, ("talloc failed\n")); + return; + } + + brl_forall(brl_revalidate_collect, state); + + if (state->array_size == -1) { + DEBUG(0, ("talloc failed\n")); + goto done; + } + + if (state->num_pids == 0) { + goto done; + } + + qsort(state->pids, state->num_pids, sizeof(state->pids[0]), + compare_procids); + + ZERO_STRUCT(last_pid); + + for (i=0; inum_pids; i++) { + if (procid_equal(&last_pid, &state->pids[i])) { + /* + * We've seen that one already + */ + continue; + } + + messaging_send(msg_ctx, state->pids[i], MSG_SMB_UNLOCK, + &data_blob_null); + last_pid = state->pids[i]; + } + + done: + TALLOC_FREE(state); + return; +} + +void brl_register_msgs(struct messaging_context *msg_ctx) +{ + messaging_register(msg_ctx, NULL, MSG_SMB_BRL_VALIDATE, + brl_revalidate); +} -- cgit From 48e0c62053d84b8493b3b04bfd1898cee122097e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 18:32:49 +0000 Subject: r23222: share_mode_forall() is only for counting and status display stuff, so traverse_read is enough here (This used to be commit 40991badef046233326815e50097aa7f493790e8) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index c02304addf..47566e0393 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1404,5 +1404,5 @@ int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, state.fn = fn; state.private_data = private_data; - return lock_db->traverse(lock_db, traverse_fn, (void *)&state); + return lock_db->traverse_read(lock_db, traverse_fn, (void *)&state); } -- cgit From 86f0e0b3de0f5a32f44bef614f6859209d81f1a1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 3 Jun 2007 19:56:41 +0000 Subject: r23316: Ouch... This would not have run in production without cluster code anyway. (This used to be commit ca1d0ff03d038372d5886ff1aa409494721142f4) --- source3/locking/brlock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index a50d4faa52..6713530738 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1721,8 +1721,8 @@ static void brl_revalidate_collect(struct file_id id, struct server_id pid, static int compare_procids(const void *p1, const void *p2) { - const struct server_id *i1 = (struct server_id *)i1; - const struct server_id *i2 = (struct server_id *)i2; + const struct server_id *i1 = (struct server_id *)p1; + const struct server_id *i2 = (struct server_id *)p2; if (i1->pid < i2->pid) return -1; if (i2->pid > i2->pid) return 1; -- cgit From 184eb775ffdd6f8afa8822a889b754e5e7050e45 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 14 Jun 2007 12:03:46 +0000 Subject: r23486: Ok, this time with a hopefully successful make test in the right place: Remove two local variables (This used to be commit 575e594e936c3cb197945063309f0b424dcdefc8) --- source3/locking/locking.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 47566e0393..8070f4b9b3 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -844,10 +844,6 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, char *frm = NULL; int i; - if (!lck) { - return False; - } - DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n", servicepath, newname)); -- cgit From b1ce226af8b61ad7e3c37860a59c6715012e738b Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 15 Jun 2007 21:58:49 +0000 Subject: r23510: Tidy calls to smb_panic by removing trailing newlines. Print the failed expression in SMB_ASSERT. (This used to be commit 171dc060e2a576d724eed1ca65636bdafffd7713) --- source3/locking/brlock.c | 10 +++++----- source3/locking/locking.c | 24 ++++++++++++------------ source3/locking/posix.c | 22 +++++++++++----------- 3 files changed, 28 insertions(+), 28 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 6713530738..e0cc4eec1e 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -577,9 +577,9 @@ OR } /* Never get here. */ - smb_panic("brlock_posix_split_merge\n"); + smb_panic("brlock_posix_split_merge"); /* Notreached. */ - abort(); + /* Keep some compilers happy. */ return 0; } @@ -1309,7 +1309,7 @@ void brl_close_fnum(struct messaging_context *msg_ctx, if (br_lck->num_locks) { locks_copy = (struct lock_struct *)TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); if (!locks_copy) { - smb_panic("brl_close_fnum: talloc fail.\n"); + smb_panic("brl_close_fnum: talloc failed"); } } else { locks_copy = NULL; @@ -1562,7 +1562,7 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("delete_rec returned %s\n", nt_errstr(status))); - smb_panic("Could not delete byte range lock entry\n"); + smb_panic("Could not delete byte range lock entry"); } } else { TDB_DATA data; @@ -1575,7 +1575,7 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("store returned %s\n", nt_errstr(status))); - smb_panic("Could not store byte range mode entry\n"); + smb_panic("Could not store byte range mode entry"); } } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8070f4b9b3..6f7d2d53c6 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -479,7 +479,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) int i; if (dbuf.dsize < sizeof(struct locking_data)) { - smb_panic("PANIC: parse_share_modes: buffer too short.\n"); + smb_panic("parse_share_modes: buffer too short"); } data = (struct locking_data *)dbuf.dptr; @@ -495,7 +495,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { DEBUG(0, ("invalid number of share modes: %d\n", lck->num_share_modes)); - smb_panic("PANIC: invalid number of share modes"); + smb_panic("parse_share_modes: invalid number of share modes"); } lck->share_modes = NULL; @@ -505,7 +505,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) if (dbuf.dsize < (sizeof(struct locking_data) + (lck->num_share_modes * sizeof(struct share_mode_entry)))) { - smb_panic("PANIC: parse_share_modes: buffer too short.\n"); + smb_panic("parse_share_modes: buffer too short"); } lck->share_modes = (struct share_mode_entry *) @@ -514,7 +514,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) sizeof(struct share_mode_entry)); if (lck->share_modes == NULL) { - smb_panic("talloc failed\n"); + smb_panic("parse_share_modes: talloc failed"); } } @@ -528,12 +528,12 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) ((data->u.s.delete_token_size - sizeof(uid_t)) % sizeof(gid_t)) != 0) { DEBUG(0, ("parse_share_modes: invalid token size %d\n", data->u.s.delete_token_size)); - smb_panic("parse_share_modes: invalid token size\n"); + smb_panic("parse_share_modes: invalid token size"); } lck->delete_token = TALLOC_P(lck, UNIX_USER_TOKEN); if (!lck->delete_token) { - smb_panic("talloc failed\n"); + smb_panic("parse_share_modes: talloc failed"); } /* Copy out the uid and gid. */ @@ -552,7 +552,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) lck->delete_token->groups = TALLOC_ARRAY(lck->delete_token, gid_t, lck->delete_token->ngroups); if (!lck->delete_token) { - smb_panic("talloc failed\n"); + smb_panic("parse_share_modes: talloc failed"); } for (i = 0; i < lck->delete_token->ngroups; i++) { @@ -571,7 +571,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) sizeof(struct share_mode_entry)) + data->u.s.delete_token_size ); if (lck->servicepath == NULL) { - smb_panic("talloc_strdup failed\n"); + smb_panic("parse_share_modes: talloc_strdup failed"); } lck->filename = talloc_strdup(lck, (const char *)dbuf.dptr + sizeof(*data) + @@ -580,7 +580,7 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) data->u.s.delete_token_size + strlen(lck->servicepath) + 1 ); if (lck->filename == NULL) { - smb_panic("talloc_strdup failed\n"); + smb_panic("parse_share_modes: talloc_strdup failed"); } /* @@ -637,7 +637,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) result.dptr = TALLOC_ARRAY(lck, uint8, result.dsize); if (result.dptr == NULL) { - smb_panic("talloc failed\n"); + smb_panic("talloc failed"); } data = (struct locking_data *)result.dptr; @@ -703,7 +703,7 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck) if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("delete_rec returned %s\n", nt_errstr(status))); - smb_panic("Could not delete share entry\n"); + smb_panic("could not delete share entry"); } } goto done; @@ -712,7 +712,7 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck) status = lck->record->store(lck->record, data, TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("store returned %s\n", nt_errstr(status))); - smb_panic("Could not store share mode entry\n"); + smb_panic("could not store share mode entry"); } done: diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 73fc2c7bd0..0b38d289d8 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -434,7 +434,7 @@ static void increment_windows_lock_ref_count(files_struct *fsp) if (dbuf.dptr == NULL) { dbuf.dptr = (uint8 *)SMB_MALLOC_P(int); if (!dbuf.dptr) { - smb_panic("increment_windows_lock_ref_count: malloc fail.\n"); + smb_panic("increment_windows_lock_ref_count: malloc fail"); } memset(dbuf.dptr, '\0', sizeof(int)); dbuf.dsize = sizeof(int); @@ -445,7 +445,7 @@ static void increment_windows_lock_ref_count(files_struct *fsp) memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - smb_panic("increment_windows_lock_ref_count: tdb_store_fail.\n"); + smb_panic("increment_windows_lock_ref_count: tdb_store_fail"); } SAFE_FREE(dbuf.dptr); @@ -461,7 +461,7 @@ static void decrement_windows_lock_ref_count(files_struct *fsp) dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); if (!dbuf.dptr) { - smb_panic("decrement_windows_lock_ref_count: logic error.\n"); + smb_panic("decrement_windows_lock_ref_count: logic error"); } memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); @@ -469,11 +469,11 @@ static void decrement_windows_lock_ref_count(files_struct *fsp) memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); if (lock_ref_count < 0) { - smb_panic("decrement_windows_lock_ref_count: lock_count logic error.\n"); + smb_panic("decrement_windows_lock_ref_count: lock_count logic error"); } if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - smb_panic("decrement_windows_lock_ref_count: tdb_store_fail.\n"); + smb_panic("decrement_windows_lock_ref_count: tdb_store_fail"); } SAFE_FREE(dbuf.dptr); @@ -500,12 +500,12 @@ void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount) lock_ref_count -= dcount; if (lock_ref_count < 0) { - smb_panic("reduce_windows_lock_ref_count: lock_count logic error.\n"); + smb_panic("reduce_windows_lock_ref_count: lock_count logic error"); } memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - smb_panic("reduce_windows_lock_ref_count: tdb_store_fail.\n"); + smb_panic("reduce_windows_lock_ref_count: tdb_store_fail"); } SAFE_FREE(dbuf.dptr); @@ -565,14 +565,14 @@ static void add_fd_to_close_entry(files_struct *fsp) dbuf.dptr = (uint8 *)SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); if (!dbuf.dptr) { - smb_panic("add_fd_to_close_entry: Realloc fail !\n"); + smb_panic("add_fd_to_close_entry: SMB_REALLOC failed"); } memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int)); dbuf.dsize += sizeof(int); if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - smb_panic("add_fd_to_close_entry: tdb_store_fail.\n"); + smb_panic("add_fd_to_close_entry: tdb_store_fail"); } DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n", @@ -590,7 +590,7 @@ static void delete_close_entries(files_struct *fsp) TDB_DATA kbuf = fd_array_key_fsp(fsp); if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) { - smb_panic("delete_close_entries: tdb_delete fail !\n"); + smb_panic("delete_close_entries: tdb_delete failed"); } } @@ -934,7 +934,7 @@ new: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size, pstring msg; slprintf(msg, sizeof(msg)-1, "logic flaw in cases: l_curr: start = %.0f, size = %.0f : \ -lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size, (double)lock->start, (double)lock->size ); +lock: start = %.0f, size = %.0f", (double)l_curr->start, (double)l_curr->size, (double)lock->start, (double)lock->size ); smb_panic(msg); } -- cgit From 9dee722b09b86622513f5d1b7ecab4dbf0787645 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 16 Jun 2007 01:04:22 +0000 Subject: r23516: Fix bug found & fixed by Doug Rudoff (doug_rudoff@isilon.com) - when cleaning up invalid locks make sure we mark the lck struct as modified so it'll get saved back correctly (that was the original intent). Jeremy. (This used to be commit cbf0829abcc3689edd7ab225054dfc79d43c6309) --- source3/locking/brlock.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index e0cc4eec1e..202fab36cc 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1646,6 +1646,7 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, memcpy(br_lck->lock_data, data.dptr, data.dsize); if (!fsp->lockdb_clean) { + int orig_num_locks = br_lck->num_locks; /* This is the first time we've accessed this. */ /* Go through and ensure all entries exist - remove any that don't. */ @@ -1658,6 +1659,11 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, return NULL; } + /* Ensure invalid locks are cleaned up in the destructor. */ + if (orig_num_locks != br_lck->num_locks) { + br_lck->modified = True; + } + /* Mark the lockdb as "clean" as seen from this open file. */ fsp->lockdb_clean = True; } -- cgit From 4ff7e6dbc92d77ccaa1805d03486e19b72ec7d26 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 9 Jul 2007 07:51:39 +0000 Subject: r23755: Fix Coverity id 384 (This used to be commit ebb410ca1e08d6f062154c9f8b3970682c6eeebd) --- source3/locking/brlock.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 202fab36cc..9b8dcfd15e 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1642,7 +1642,13 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, talloc_set_destructor(br_lck, byte_range_lock_destructor); br_lck->num_locks = data.dsize / sizeof(struct lock_struct); - br_lck->lock_data = SMB_MALLOC_ARRAY(struct lock_struct, br_lck->num_locks); + if (!(br_lck->lock_data = SMB_MALLOC_ARRAY( + struct lock_struct, br_lck->num_locks))) { + DEBUG(0, ("malloc failed\n")); + TALLOC_FREE(br_lck); + return NULL; + } + memcpy(br_lck->lock_data, data.dptr, data.dsize); if (!fsp->lockdb_clean) { -- cgit From 014a596f426721fcf15014a735051d951b186208 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 9 Jul 2007 08:45:14 +0000 Subject: r23759: Fix make test -- sorry (This used to be commit cbbc70604e815f4ffd25d040ca0a4ef58e651523) --- source3/locking/brlock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 9b8dcfd15e..9b90d87ff0 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1642,8 +1642,8 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, talloc_set_destructor(br_lck, byte_range_lock_destructor); br_lck->num_locks = data.dsize / sizeof(struct lock_struct); - if (!(br_lck->lock_data = SMB_MALLOC_ARRAY( - struct lock_struct, br_lck->num_locks))) { + br_lck->lock_data = SMB_MALLOC_ARRAY(struct lock_struct, br_lck->num_locks); + if ((br_lck->num_locks != 0) && (br_lck->lock_data == NULL)) { DEBUG(0, ("malloc failed\n")); TALLOC_FREE(br_lck); return NULL; -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/locking/brlock.c | 2 +- source3/locking/locking.c | 2 +- source3/locking/posix.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 9b90d87ff0..2a6299a563 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -8,7 +8,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 6f7d2d53c6..31679c158d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 0b38d289d8..22091bc0ea 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/locking/brlock.c | 3 +-- source3/locking/locking.c | 3 +-- source3/locking/posix.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 2a6299a563..228a30b7af 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -17,8 +17,7 @@ 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. + along with this program. If not, see . */ /* This module implements a tdb based byte range locking service, diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 31679c158d..c7fb572b1d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . Revision History: diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 22091bc0ea..606f208673 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . Revision History: -- cgit From c9da49790e67b6840c4cfa6daddfffbbe643d140 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 16 Jul 2007 07:40:30 +0000 Subject: r23882: Fix Coverity id 389 -- finally (I hope) (This used to be commit 9b8f2d8bd144700306819480bcb260d2c20969ae) --- source3/locking/brlock.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 228a30b7af..252728ced3 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1641,14 +1641,18 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, talloc_set_destructor(br_lck, byte_range_lock_destructor); br_lck->num_locks = data.dsize / sizeof(struct lock_struct); - br_lck->lock_data = SMB_MALLOC_ARRAY(struct lock_struct, br_lck->num_locks); - if ((br_lck->num_locks != 0) && (br_lck->lock_data == NULL)) { - DEBUG(0, ("malloc failed\n")); - TALLOC_FREE(br_lck); - return NULL; - } - memcpy(br_lck->lock_data, data.dptr, data.dsize); + if (br_lck->num_locks != 0) { + br_lck->lock_data = SMB_MALLOC_ARRAY(struct lock_struct, + br_lck->num_locks); + if (br_lck->lock_data == NULL) { + DEBUG(0, ("malloc failed\n")); + TALLOC_FREE(br_lck); + return NULL; + } + + memcpy(br_lck->lock_data, data.dptr, data.dsize); + } if (!fsp->lockdb_clean) { int orig_num_locks = br_lck->num_locks; -- cgit From 476c30b9ce38eec8985447fdcd1d3ece97370704 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 16 Jul 2007 08:23:20 +0000 Subject: r23885: Fix make test on opi. (This used to be commit b2adb28808fe25d420bc12834ca8bc70779bb653) --- source3/locking/brlock.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 252728ced3..41a7b9ea4a 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1637,6 +1637,7 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, } br_lck->read_only = read_only; + br_lck->lock_data = NULL; talloc_set_destructor(br_lck, byte_range_lock_destructor); -- cgit From 44b9493418558fca03b1888a693ba516b3711e17 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 00:50:48 +0000 Subject: r23908: Fix bug with interaction of optimization with POSIX locking. We can't do lock counts with POSIX, so stop counting if we get a POSIX lock request. Jeremy. (This used to be commit a48e4a29e6774e5e72b9b361a17207b053474521) --- source3/locking/locking.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index c7fb572b1d..8692001f44 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -40,6 +40,8 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING +#define NO_LOCKING_COUNT (-1) + /* the locking database handle */ static struct db_context *lock_db; @@ -225,11 +227,19 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx, blocking_lock, plock_pid); - /* blocking ie. pending, locks also count here, - * as this is an efficiency counter to avoid checking - * the lock db. on close. JRA. */ + if (lock_flav == WINDOWS_LOCK && + fsp->current_lock_count != NO_LOCKING_COUNT) { + /* blocking ie. pending, locks also count here, + * as this is an efficiency counter to avoid checking + * the lock db. on close. JRA. */ - fsp->current_lock_count++; + fsp->current_lock_count++; + } else { + /* Notice that this has had a POSIX lock request. + * We can't count locks after this so forget them. + */ + fsp->current_lock_count = NO_LOCKING_COUNT; + } return br_lck; } @@ -279,8 +289,11 @@ NTSTATUS do_unlock(struct messaging_context *msg_ctx, return NT_STATUS_RANGE_NOT_LOCKED; } - SMB_ASSERT(fsp->current_lock_count > 0); - fsp->current_lock_count--; + if (lock_flav == WINDOWS_LOCK && + fsp->current_lock_count != NO_LOCKING_COUNT) { + SMB_ASSERT(fsp->current_lock_count > 0); + fsp->current_lock_count--; + } return NT_STATUS_OK; } @@ -329,8 +342,11 @@ NTSTATUS do_lock_cancel(files_struct *fsp, return NT_STATUS_DOS(ERRDOS, ERRcancelviolation); } - SMB_ASSERT(fsp->current_lock_count > 0); - fsp->current_lock_count--; + if (lock_flav == WINDOWS_LOCK && + fsp->current_lock_count != NO_LOCKING_COUNT) { + SMB_ASSERT(fsp->current_lock_count > 0); + fsp->current_lock_count--; + } return NT_STATUS_OK; } -- cgit From 070215ef131245eb386837c666c1884c2556a456 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2007 14:03:46 +0000 Subject: r23956: merge from 3_2-ctdb-tridge: fixed a bug with dead share mode entries jra: please tell me if it's ok to merge this to 3_2_0. metze (This used to be commit 044ac6afa7a36b352f4cb203879af082d4726417) --- source3/locking/locking.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8692001f44..e4d06b8bfd 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -937,6 +937,14 @@ BOOL is_valid_share_mode_entry(const struct share_mode_entry *e) { int num_props = 0; + if (e->op_type == UNUSED_SHARE_MODE_ENTRY) { + /* cope with dead entries from the process not + existing. These should not be considered valid, + otherwise we end up doing zero timeout sharing + violation */ + return False; + } + num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0); num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0); num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0); -- cgit From 63fcb7a2fd0064121ec71c913d32102b7de6dc6f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 24 Jul 2007 11:50:54 +0000 Subject: r24034: Print the full cluster pid in print_lock_struct (This used to be commit ff1996ce4b0edfee90758c85ea0ac653877a1b9f) --- source3/locking/brlock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 41a7b9ea4a..e79b531776 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -41,11 +41,11 @@ static struct db_context *brlock_db; static void print_lock_struct(unsigned int i, struct lock_struct *pls) { - DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %u, ", + DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %s, ", i, (unsigned int)pls->context.smbpid, (unsigned int)pls->context.tid, - (unsigned int)procid_to_pid(&pls->context.pid) )); + procid_str_static(&pls->context.pid) )); DEBUG(10,("start = %.0f, size = %.0f, fnum = %d, %s %s\n", (double)pls->start, -- cgit From b352a4532afe91cbf885e6cf99a7e1971c05ad1d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 1 Aug 2007 13:39:25 +0000 Subject: r24117: use locking_key() instead of forming the TDB_DATA key by hand metze (This used to be commit a7449e4ab390b3c1d9d5a0bbc466f71de17918e0) --- source3/locking/locking.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e4d06b8bfd..d79d73099b 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -782,10 +782,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, const char *fname) { struct share_mode_lock *lck; - TDB_DATA key; - - key.dptr = (unsigned char *)&id; - key.dsize = sizeof(id); + TDB_DATA key = locking_key(id); if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) { DEBUG(0, ("talloc failed\n")); -- cgit From 28210588edc39eb2b6cd237f11b488fa4d6b6985 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Aug 2007 11:28:04 +0000 Subject: r24266: Remove the "open files database hash size" parameter This has been superseded by the "tdb_hashsize:" parameter (This used to be commit df40d336afd256f05a0ec3724cc2096fb7114d81) --- source3/locking/brlock.c | 3 +-- source3/locking/locking.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index e79b531776..4e15670b04 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -263,8 +263,7 @@ void brl_init(int read_only) if (brlock_db) { return; } - brlock_db = db_open(NULL, lock_path("brlock.tdb"), - lp_open_files_db_hash_size(), + brlock_db = db_open(NULL, lock_path("brlock.tdb"), 0, TDB_DEFAULT |TDB_VOLATILE |(read_only?0x0:TDB_CLEAR_IF_FIRST), diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d79d73099b..7f1f8f41e1 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -394,8 +394,7 @@ BOOL locking_init(int read_only) if (lock_db) return True; - lock_db = db_open(NULL, lock_path("locking.tdb"), - lp_open_files_db_hash_size(), + lock_db = db_open(NULL, lock_path("locking.tdb"), 0, TDB_DEFAULT |TDB_VOLATILE |(read_only?0x0:TDB_CLEAR_IF_FIRST), -- cgit From 8bab4bdc5dc73f460034d366495705c68eef5347 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 20 Aug 2007 07:59:22 +0000 Subject: r24571: Only look at errno if the close call actually failed Patch from Ofir Azoulay -- thanks (This used to be commit 888e657d758173c0eb4b68059d6fb5ae45b2b2ed) --- source3/locking/posix.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 606f208673..f7d70504b1 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -640,7 +640,10 @@ NTSTATUS fd_close_posix(struct connection_struct *conn, files_struct *fsp) */ ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); fsp->fh->fd = -1; - return map_nt_error_from_unix(errno); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + return NT_STATUS_OK; } if (get_windows_lock_ref_count(fsp)) { -- cgit From 4ee8b2937d48308c6089fb539fdbd8625dfde360 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 10 Sep 2007 10:56:07 +0000 Subject: r25055: Add file_id_string_tos This removes file_id_string_static and file_id_string_static2 (This used to be commit 638c848c9afe374feb30e34c494f89b2a6c64f7b) --- source3/locking/brlock.c | 2 +- source3/locking/locking.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 4e15670b04..c148fa33f3 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1682,7 +1682,7 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, struct lock_struct *locks = br_lck->lock_data; DEBUG(10,("brl_get_locks_internal: %u current locks on file_id %s\n", br_lck->num_locks, - file_id_static_string(&fsp->file_id))); + file_id_string_tos(&fsp->file_id))); for( i = 0; i < br_lck->num_locks; i++) { print_lock_struct(i, &locks[i]); } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 7f1f8f41e1..4d6265cc7c 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -458,7 +458,7 @@ char *share_mode_str(int num, struct share_mode_entry *e) e->share_access, e->private_options, e->access_mask, e->op_mid, e->op_type, e->share_file_id, (unsigned int)e->uid, (unsigned int)e->flags, - file_id_static_string(&e->id)); + file_id_string_tos(&e->id)); return share_str; } @@ -906,7 +906,7 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, DEBUG(10,("rename_share_filename: sending rename message to pid %s " "file_id %s sharepath %s newname %s\n", procid_str_static(&se->pid), - file_id_static_string(&lck->id), + file_id_string_tos(&lck->id), lck->servicepath, lck->filename )); messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME, -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/locking/brlock.c | 56 +++++++++++++++++++++++------------------------ source3/locking/locking.c | 52 +++++++++++++++++++++---------------------- source3/locking/posix.c | 30 ++++++++++++------------- 3 files changed, 69 insertions(+), 69 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index c148fa33f3..f821761cd7 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -59,7 +59,7 @@ static void print_lock_struct(unsigned int i, struct lock_struct *pls) See if two locking contexts are equal. ****************************************************************************/ -BOOL brl_same_context(const struct lock_context *ctx1, +bool brl_same_context(const struct lock_context *ctx1, const struct lock_context *ctx2) { return (procid_equal(&ctx1->pid, &ctx2->pid) && @@ -71,7 +71,7 @@ BOOL brl_same_context(const struct lock_context *ctx1, See if lck1 and lck2 overlap. ****************************************************************************/ -static BOOL brl_overlap(const struct lock_struct *lck1, +static bool brl_overlap(const struct lock_struct *lck1, const struct lock_struct *lck2) { /* this extra check is not redundent - it copes with locks @@ -93,7 +93,7 @@ static BOOL brl_overlap(const struct lock_struct *lck1, See if lock2 can be added when lock1 is in place. ****************************************************************************/ -static BOOL brl_conflict(const struct lock_struct *lck1, +static bool brl_conflict(const struct lock_struct *lck1, const struct lock_struct *lck2) { /* Ignore PENDING locks. */ @@ -119,7 +119,7 @@ static BOOL brl_conflict(const struct lock_struct *lck1, know already match. ****************************************************************************/ -static BOOL brl_conflict_posix(const struct lock_struct *lck1, +static bool brl_conflict_posix(const struct lock_struct *lck1, const struct lock_struct *lck2) { #if defined(DEVELOPER) @@ -147,7 +147,7 @@ static BOOL brl_conflict_posix(const struct lock_struct *lck1, } #if ZERO_ZERO -static BOOL brl_conflict1(const struct lock_struct *lck1, +static bool brl_conflict1(const struct lock_struct *lck1, const struct lock_struct *lck2) { if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type)) @@ -181,7 +181,7 @@ static BOOL brl_conflict1(const struct lock_struct *lck1, This is never used in the POSIX lock case. ****************************************************************************/ -static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock_struct *lck2) +static bool brl_conflict_other(const struct lock_struct *lck1, const struct lock_struct *lck2) { if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type)) return False; @@ -213,7 +213,7 @@ static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock Check if an unlock overlaps a pending lock. ****************************************************************************/ -static BOOL brl_pending_overlap(const struct lock_struct *lock, const struct lock_struct *pend_lock) +static bool brl_pending_overlap(const struct lock_struct *lock, const struct lock_struct *pend_lock) { if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start)) return True; @@ -228,7 +228,7 @@ static BOOL brl_pending_overlap(const struct lock_struct *lock, const struct loc app depends on this ? ****************************************************************************/ -static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, BOOL blocking_lock) +static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, bool blocking_lock) { if (lock->start >= 0xEF000000 && (lock->start >> 63) == 0) { /* amazing the little things you learn with a test @@ -310,7 +310,7 @@ static int lock_compare(const struct lock_struct *lck1, ****************************************************************************/ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, - struct lock_struct *plock, BOOL blocking_lock) + struct lock_struct *plock, bool blocking_lock) { unsigned int i; files_struct *fsp = br_lck->fsp; @@ -378,9 +378,9 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, /* Output array. */ const struct lock_struct *ex, /* existing lock. */ const struct lock_struct *plock, /* proposed lock. */ - BOOL *lock_was_added) + bool *lock_was_added) { - BOOL lock_types_differ = (ex->lock_type != plock->lock_type); + bool lock_types_differ = (ex->lock_type != plock->lock_type); /* We can't merge non-conflicting locks on different context - ignore fnum. */ @@ -594,8 +594,8 @@ static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx, unsigned int i, count; struct lock_struct *locks = br_lck->lock_data; struct lock_struct *tp; - BOOL lock_was_added = False; - BOOL signal_pending_read = False; + bool lock_was_added = False; + bool signal_pending_read = False; /* No zero-zero locks for POSIX. */ if (plock->start == 0 && plock->size == 0) { @@ -741,7 +741,7 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx, br_off size, enum brl_type lock_type, enum brl_flavour lock_flav, - BOOL blocking_lock, + bool blocking_lock, uint32 *psmbpid) { NTSTATUS ret; @@ -784,7 +784,7 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx, Unlock a range of bytes - Windows semantics. ****************************************************************************/ -static BOOL brl_unlock_windows(struct messaging_context *msg_ctx, +static bool brl_unlock_windows(struct messaging_context *msg_ctx, struct byte_range_lock *br_lck, const struct lock_struct *plock) { @@ -887,14 +887,14 @@ static BOOL brl_unlock_windows(struct messaging_context *msg_ctx, Unlock a range of bytes - POSIX semantics. ****************************************************************************/ -static BOOL brl_unlock_posix(struct messaging_context *msg_ctx, +static bool brl_unlock_posix(struct messaging_context *msg_ctx, struct byte_range_lock *br_lck, const struct lock_struct *plock) { unsigned int i, j, count; struct lock_struct *tp; struct lock_struct *locks = br_lck->lock_data; - BOOL overlap_found = False; + bool overlap_found = False; /* No zero-zero locks for POSIX. */ if (plock->start == 0 && plock->size == 0) { @@ -922,7 +922,7 @@ static BOOL brl_unlock_posix(struct messaging_context *msg_ctx, for (i = 0; i < br_lck->num_locks; i++) { struct lock_struct *lock = &locks[i]; struct lock_struct tmp_lock[3]; - BOOL lock_was_added = False; + bool lock_was_added = False; unsigned int tmp_count; /* Only remove our own locks - ignore fnum. */ @@ -1056,7 +1056,7 @@ static BOOL brl_unlock_posix(struct messaging_context *msg_ctx, Unlock a range of bytes. ****************************************************************************/ -BOOL brl_unlock(struct messaging_context *msg_ctx, +bool brl_unlock(struct messaging_context *msg_ctx, struct byte_range_lock *br_lck, uint32 smbpid, struct server_id pid, @@ -1087,7 +1087,7 @@ BOOL brl_unlock(struct messaging_context *msg_ctx, Returns True if the region required is currently unlocked, False if locked. ****************************************************************************/ -BOOL brl_locktest(struct byte_range_lock *br_lck, +bool brl_locktest(struct byte_range_lock *br_lck, uint32 smbpid, struct server_id pid, br_off start, @@ -1095,7 +1095,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck, enum brl_type lock_type, enum brl_flavour lock_flav) { - BOOL ret = True; + bool ret = True; unsigned int i; struct lock_struct lock; const struct lock_struct *locks = br_lck->lock_data; @@ -1170,7 +1170,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, /* Make sure existing locks don't conflict */ for (i=0; i < br_lck->num_locks; i++) { const struct lock_struct *exlock = &locks[i]; - BOOL conflict = False; + bool conflict = False; if (exlock->lock_flav == WINDOWS_LOCK) { conflict = brl_conflict(exlock, &lock); @@ -1193,7 +1193,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, */ if(lp_posix_locking(fsp->conn->params)) { - BOOL ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK); + bool ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK); DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for fnum %d file %s\n", (double)*pstart, (double)*psize, ret ? "locked" : "unlocked", @@ -1213,7 +1213,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, Remove a particular pending lock. ****************************************************************************/ -BOOL brl_lock_cancel(struct byte_range_lock *br_lck, +bool brl_lock_cancel(struct byte_range_lock *br_lck, uint32 smbpid, struct server_id pid, br_off start, @@ -1274,7 +1274,7 @@ void brl_close_fnum(struct messaging_context *msg_ctx, int num_deleted_windows_locks = 0; struct lock_struct *locks = br_lck->lock_data; struct server_id pid = procid_self(); - BOOL unlock_individually = False; + bool unlock_individually = False; if(lp_posix_locking(fsp->conn->params)) { @@ -1339,7 +1339,7 @@ void brl_close_fnum(struct messaging_context *msg_ctx, for (i=0; i < br_lck->num_locks; i++) { struct lock_struct *lock = &locks[i]; - BOOL del_this_lock = False; + bool del_this_lock = False; if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid)) { if ((lock->lock_flav == WINDOWS_LOCK) && (lock->fnum == fnum)) { @@ -1397,7 +1397,7 @@ void brl_close_fnum(struct messaging_context *msg_ctx, Ensure this set of lock entries is valid. ****************************************************************************/ -static BOOL validate_lock_entries(unsigned int *pnum_entries, struct lock_struct **pplocks) +static bool validate_lock_entries(unsigned int *pnum_entries, struct lock_struct **pplocks) { unsigned int i; unsigned int num_valid_entries = 0; @@ -1591,7 +1591,7 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) ********************************************************************/ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, - files_struct *fsp, BOOL read_only) + files_struct *fsp, bool read_only) { TDB_DATA key, data; struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4d6265cc7c..aae297e031 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -75,7 +75,7 @@ const char *lock_flav_name(enum brl_flavour lock_flav) Called in the read/write codepath. ****************************************************************************/ -BOOL is_locked(files_struct *fsp, +bool is_locked(files_struct *fsp, uint32 smbpid, SMB_BIG_UINT count, SMB_BIG_UINT offset, @@ -83,7 +83,7 @@ BOOL is_locked(files_struct *fsp, { int strict_locking = lp_strict_locking(fsp->conn->params); enum brl_flavour lock_flav = lp_posix_cifsu_locktype(fsp); - BOOL ret = True; + bool ret = True; if (count == 0) { return False; @@ -188,7 +188,7 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx, SMB_BIG_UINT offset, enum brl_type lock_type, enum brl_flavour lock_flav, - BOOL blocking_lock, + bool blocking_lock, NTSTATUS *perr, uint32 *plock_pid) { @@ -255,7 +255,7 @@ NTSTATUS do_unlock(struct messaging_context *msg_ctx, SMB_BIG_UINT offset, enum brl_flavour lock_flav) { - BOOL ok = False; + bool ok = False; struct byte_range_lock *br_lck = NULL; if (!fsp->can_lock) { @@ -308,7 +308,7 @@ NTSTATUS do_lock_cancel(files_struct *fsp, SMB_BIG_UINT offset, enum brl_flavour lock_flav) { - BOOL ok = False; + bool ok = False; struct byte_range_lock *br_lck = NULL; if (!fsp->can_lock) { @@ -387,7 +387,7 @@ void locking_close_file(struct messaging_context *msg_ctx, static int open_read_only; -BOOL locking_init(int read_only) +bool locking_init(int read_only) { brl_init(read_only); @@ -417,7 +417,7 @@ BOOL locking_init(int read_only) Deinitialize the share_mode management. ******************************************************************/ -BOOL locking_end(void) +bool locking_end(void) { brl_shutdown(open_read_only); if (lock_db) { @@ -487,7 +487,7 @@ static void print_share_mode_table(struct locking_data *data) Get all share mode entries for a dev/inode pair. ********************************************************************/ -static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) +static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) { struct locking_data *data; int i; @@ -734,7 +734,7 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck) return 0; } -static BOOL fill_share_mode_lock(struct share_mode_lock *lck, +static bool fill_share_mode_lock(struct share_mode_lock *lck, struct file_id id, const char *servicepath, const char *fname, @@ -844,7 +844,7 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, Based on an initial code idea from SATOH Fumiyasu ********************************************************************/ -BOOL rename_share_filename(struct messaging_context *msg_ctx, +bool rename_share_filename(struct messaging_context *msg_ctx, struct share_mode_lock *lck, const char *servicepath, const char *newname) @@ -916,9 +916,9 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, return True; } -BOOL get_delete_on_close_flag(struct file_id id) +bool get_delete_on_close_flag(struct file_id id) { - BOOL result; + bool result; struct share_mode_lock *lck; if (!(lck = fetch_share_mode_unlocked(NULL, id, NULL, NULL))) { @@ -929,7 +929,7 @@ BOOL get_delete_on_close_flag(struct file_id id) return result; } -BOOL is_valid_share_mode_entry(const struct share_mode_entry *e) +bool is_valid_share_mode_entry(const struct share_mode_entry *e) { int num_props = 0; @@ -949,12 +949,12 @@ BOOL is_valid_share_mode_entry(const struct share_mode_entry *e) return (num_props != 0); } -BOOL is_deferred_open_entry(const struct share_mode_entry *e) +bool is_deferred_open_entry(const struct share_mode_entry *e) { return (e->op_type == DEFERRED_OPEN_ENTRY); } -BOOL is_unused_share_mode_entry(const struct share_mode_entry *e) +bool is_unused_share_mode_entry(const struct share_mode_entry *e) { return (e->op_type == UNUSED_SHARE_MODE_ENTRY); } @@ -1019,7 +1019,7 @@ static void add_share_mode_entry(struct share_mode_lock *lck, } void set_share_mode(struct share_mode_lock *lck, files_struct *fsp, - uid_t uid, uint16 mid, uint16 op_type, BOOL initial_delete_on_close_allowed) + uid_t uid, uint16 mid, uint16 op_type, bool initial_delete_on_close_allowed) { struct share_mode_entry entry; fill_share_mode_entry(&entry, fsp, uid, mid, op_type); @@ -1044,7 +1044,7 @@ void add_deferred_open(struct share_mode_lock *lck, uint16 mid, not automatically a logic error if they are identical. JRA.) ********************************************************************/ -static BOOL share_modes_identical(struct share_mode_entry *e1, +static bool share_modes_identical(struct share_mode_entry *e1, struct share_mode_entry *e2) { /* We used to check for e1->share_access == e2->share_access here @@ -1057,7 +1057,7 @@ static BOOL share_modes_identical(struct share_mode_entry *e1, e1->share_file_id == e2->share_file_id ); } -static BOOL deferred_open_identical(struct share_mode_entry *e1, +static bool deferred_open_identical(struct share_mode_entry *e1, struct share_mode_entry *e2) { return (procid_equal(&e1->pid, &e2->pid) && @@ -1091,7 +1091,7 @@ static struct share_mode_entry *find_share_mode_entry(struct share_mode_lock *lc entries left. ********************************************************************/ -BOOL del_share_mode(struct share_mode_lock *lck, files_struct *fsp) +bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp) { struct share_mode_entry entry, *e; @@ -1128,7 +1128,7 @@ void del_deferred_open_entry(struct share_mode_lock *lck, uint16 mid) Remove an oplock mid and mode entry from a share mode. ********************************************************************/ -BOOL remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp) +bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp) { struct share_mode_entry entry, *e; @@ -1150,7 +1150,7 @@ BOOL remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp) Downgrade a oplock type from exclusive to level II. ********************************************************************/ -BOOL downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp) +bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp) { struct share_mode_entry entry, *e; @@ -1173,7 +1173,7 @@ BOOL downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp) open_file_ntcreate. JRA. ****************************************************************************/ -NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, +NTSTATUS can_set_delete_on_close(files_struct *fsp, bool delete_on_close, uint32 dosmode) { if (!delete_on_close) { @@ -1227,7 +1227,7 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, Do we have an open file handle that created this entry ? ****************************************************************************/ -BOOL can_set_initial_delete_on_close(const struct share_mode_lock *lck) +bool can_set_initial_delete_on_close(const struct share_mode_lock *lck) { int i; @@ -1299,7 +1299,7 @@ void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok lck entry. This function is used when the lock is already granted. ****************************************************************************/ -void set_delete_on_close_lck(struct share_mode_lock *lck, BOOL delete_on_close, UNIX_USER_TOKEN *tok) +void set_delete_on_close_lck(struct share_mode_lock *lck, bool delete_on_close, UNIX_USER_TOKEN *tok) { if (lck->delete_on_close != delete_on_close) { set_delete_on_close_token(lck, tok); @@ -1311,7 +1311,7 @@ void set_delete_on_close_lck(struct share_mode_lock *lck, BOOL delete_on_close, } } -BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKEN *tok) +bool set_delete_on_close(files_struct *fsp, bool delete_on_close, UNIX_USER_TOKEN *tok) { struct share_mode_lock *lck; @@ -1343,7 +1343,7 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE Sets the allow initial delete on close flag for this share mode. ****************************************************************************/ -BOOL set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct *fsp, BOOL delete_on_close) +bool set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct *fsp, bool delete_on_close) { struct share_mode_entry entry, *e; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index f7d70504b1..135e204f01 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -78,7 +78,7 @@ static const char *posix_lock_type_name(int lock_type) False if not. ****************************************************************************/ -static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, +static bool posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) { SMB_OFF_T offset = (SMB_OFF_T)u_offset; @@ -182,9 +182,9 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, broken NFS implementations. ****************************************************************************/ -static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +static bool posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { - BOOL ret; + bool ret; DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type)); @@ -225,10 +225,10 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF broken NFS implementations. ****************************************************************************/ -static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype) +static bool posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype) { pid_t pid; - BOOL ret; + bool ret; DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n", fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype)); @@ -270,7 +270,7 @@ static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T region is locked, False otherwise. ****************************************************************************/ -BOOL is_posix_locked(files_struct *fsp, +bool is_posix_locked(files_struct *fsp, SMB_BIG_UINT *pu_offset, SMB_BIG_UINT *pu_count, enum brl_type *plock_type, @@ -374,7 +374,7 @@ static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp) Create the in-memory POSIX lock databases. ********************************************************************/ -BOOL posix_locking_init(int read_only) +bool posix_locking_init(int read_only) { if (posix_pending_close_tdb) { return True; @@ -396,7 +396,7 @@ BOOL posix_locking_init(int read_only) Delete the in-memory POSIX lock databases. ********************************************************************/ -BOOL posix_locking_end(void) +bool posix_locking_end(void) { if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) { return False; @@ -951,7 +951,7 @@ lock: start = %.0f, size = %.0f", (double)l_curr->start, (double)l_curr->size, ( lock could be granted, False if not. ****************************************************************************/ -BOOL set_posix_lock_windows_flavour(files_struct *fsp, +bool set_posix_lock_windows_flavour(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type, @@ -963,7 +963,7 @@ BOOL set_posix_lock_windows_flavour(files_struct *fsp, SMB_OFF_T offset; SMB_OFF_T count; int posix_lock_type = map_posix_lock_type(fsp,lock_type); - BOOL ret = True; + bool ret = True; size_t lock_count; TALLOC_CTX *l_ctx = NULL; struct lock_list *llist = NULL; @@ -1088,7 +1088,7 @@ BOOL set_posix_lock_windows_flavour(files_struct *fsp, lock could be released, False if not. ****************************************************************************/ -BOOL release_posix_lock_windows_flavour(files_struct *fsp, +bool release_posix_lock_windows_flavour(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type deleted_lock_type, @@ -1098,7 +1098,7 @@ BOOL release_posix_lock_windows_flavour(files_struct *fsp, { SMB_OFF_T offset; SMB_OFF_T count; - BOOL ret = True; + bool ret = True; TALLOC_CTX *ul_ctx = NULL; struct lock_list *ulist = NULL; struct lock_list *ul = NULL; @@ -1211,7 +1211,7 @@ BOOL release_posix_lock_windows_flavour(files_struct *fsp, upper layer would have refused it. ****************************************************************************/ -BOOL set_posix_lock_posix_flavour(files_struct *fsp, +bool set_posix_lock_posix_flavour(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type, @@ -1251,14 +1251,14 @@ BOOL set_posix_lock_posix_flavour(files_struct *fsp, have a different lock context. ****************************************************************************/ -BOOL release_posix_lock_posix_flavour(files_struct *fsp, +bool release_posix_lock_posix_flavour(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, const struct lock_context *lock_ctx, const struct lock_struct *plocks, int num_locks) { - BOOL ret = True; + bool ret = True; SMB_OFF_T offset; SMB_OFF_T count; TALLOC_CTX *ul_ctx = NULL; -- cgit From acb829ecc3b9af3f141425ecac032a7c722a1815 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Nov 2007 18:27:26 -0800 Subject: Add MAX_DNS_NAME_LENGTH, remove more pstrings. Jeremy. (This used to be commit a1725f4ff7ed375808c78ac661b539557748d0a5) --- source3/locking/locking.c | 18 +++++++++--------- source3/locking/posix.c | 7 +++++-- 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index aae297e031..8d511e9d8f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -444,11 +444,9 @@ static TDB_DATA locking_key(struct file_id id) Print out a share mode. ********************************************************************/ -char *share_mode_str(int num, struct share_mode_entry *e) +char *share_mode_str(TALLOC_CTX *ctx, int num, struct share_mode_entry *e) { - static pstring share_str; - - slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s " + return talloc_asprintf(ctx, "share_mode_entry[%d]: %s " "pid = %s, share_access = 0x%x, private_options = 0x%x, " "access_mask = 0x%x, mid = 0x%x, type= 0x%x, gen_id = %lu, " "uid = %u, flags = %u, file_id %s", @@ -459,8 +457,6 @@ char *share_mode_str(int num, struct share_mode_entry *e) e->access_mask, e->op_mid, e->op_type, e->share_file_id, (unsigned int)e->uid, (unsigned int)e->flags, file_id_string_tos(&e->id)); - - return share_str; } /******************************************************************* @@ -476,10 +472,12 @@ static void print_share_mode_table(struct locking_data *data) for (i = 0; i < num_share_modes; i++) { struct share_mode_entry entry; + char *str = share_mode_str(NULL, i, &entry); memcpy(&entry, &shares[i], sizeof(struct share_mode_entry)); DEBUG(10,("print_share_mode_table: %s\n", - share_mode_str(i, &entry))); + str ? str : "")); + TALLOC_FREE(str); } } @@ -603,14 +601,16 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) for (i = 0; i < lck->num_share_modes; i++) { struct share_mode_entry *entry_p = &lck->share_modes[i]; + char *str = share_mode_str(NULL, i, entry_p); DEBUG(10,("parse_share_modes: %s\n", - share_mode_str(i, entry_p) )); + str ? str : "")); if (!process_exists(entry_p->pid)) { DEBUG(10,("parse_share_modes: deleted %s\n", - share_mode_str(i, entry_p) )); + str ? str : "")); entry_p->op_type = UNUSED_SHARE_MODE_ENTRY; lck->modified = True; } + TALLOC_FREE(str); } return True; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 135e204f01..37cfa04373 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -933,9 +933,12 @@ new: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size, * This logic case should never happen. Ensure this is the * case by forcing an abort.... Remove in production. */ - pstring msg; + char *msg = NULL; - slprintf(msg, sizeof(msg)-1, "logic flaw in cases: l_curr: start = %.0f, size = %.0f : \ + /* Don't check if alloc succeeds here - we're + * forcing a core dump anyway. */ + + asprintf(&msg, "logic flaw in cases: l_curr: start = %.0f, size = %.0f : \ lock: start = %.0f, size = %.0f", (double)l_curr->start, (double)l_curr->size, (double)lock->start, (double)lock->size ); smb_panic(msg); -- cgit From 3546d5c099981fede0b29136b3d92145a988a558 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 18 Nov 2007 14:24:54 +0100 Subject: Fix a valgrind error (This used to be commit b82120f9b7f5aad83d8b4ece0261e9693eedca0c) --- source3/locking/locking.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8d511e9d8f..0cedff36e4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -472,11 +472,12 @@ static void print_share_mode_table(struct locking_data *data) for (i = 0; i < num_share_modes; i++) { struct share_mode_entry entry; - char *str = share_mode_str(NULL, i, &entry); + char *str; memcpy(&entry, &shares[i], sizeof(struct share_mode_entry)); - DEBUG(10,("print_share_mode_table: %s\n", - str ? str : "")); + str = share_mode_str(NULL, i, &entry); + + DEBUG(10,("print_share_mode_table: %s\n", str ? str : "")); TALLOC_FREE(str); } } -- cgit From 815aec8241b2da93a193eb8d3b3adbfdef5c1d90 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 18 Nov 2007 14:45:19 +0100 Subject: Add a comment (This used to be commit 144014096a41de293ce7ec15f82681a469dd3aa1) --- source3/locking/locking.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 0cedff36e4..eb7531d9a0 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -474,8 +474,14 @@ static void print_share_mode_table(struct locking_data *data) struct share_mode_entry entry; char *str; + /* + * We need to memcpy the entry here due to alignment + * restrictions that are not met when directly accessing + * shares[i] + */ + memcpy(&entry, &shares[i], sizeof(struct share_mode_entry)); - str = share_mode_str(NULL, i, &entry); + str = share_mode_str(talloc_tos(), i, &entry); DEBUG(10,("print_share_mode_table: %s\n", str ? str : "")); TALLOC_FREE(str); -- cgit From f4fe725ff173a173307b364939284b05c3d69a91 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Dec 2007 20:30:53 +0100 Subject: Remove two statics (This used to be commit 8ee502e1e59960fd8db037f0adf1171b2a18cec5) --- source3/locking/posix.c | 56 +++++++++++++++---------------------------------- 1 file changed, 17 insertions(+), 39 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 37cfa04373..7669b140f6 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -321,35 +321,17 @@ struct lock_ref_count_key { char r; }; -/******************************************************************* - Form a static locking key for a dev/inode pair for the fd array. -******************************************************************/ - -static TDB_DATA fd_array_key(struct file_id id) -{ - static struct file_id key; - TDB_DATA kbuf; - key = id; - kbuf.dptr = (uint8 *)&key; - kbuf.dsize = sizeof(key); - return kbuf; -} - /******************************************************************* Form a static locking key for a dev/inode pair for the lock ref count ******************************************************************/ -static TDB_DATA locking_ref_count_key(struct file_id id) +static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp, + struct lock_ref_count_key *tmp) { - static struct lock_ref_count_key key; - TDB_DATA kbuf; - - memset(&key, '\0', sizeof(key)); - key.id = id; - key.r = 'r'; - kbuf.dptr = (uint8 *)&key; - kbuf.dsize = sizeof(key); - return kbuf; + ZERO_STRUCTP(tmp); + tmp->id = fsp->file_id; + tmp->r = 'r'; + return make_tdb_data((uint8_t *)tmp, sizeof(*tmp)); } /******************************************************************* @@ -358,16 +340,7 @@ static TDB_DATA locking_ref_count_key(struct file_id id) static TDB_DATA fd_array_key_fsp(files_struct *fsp) { - return fd_array_key(fsp->file_id); -} - -/******************************************************************* - Convenience function to get a lock ref count key from an fsp. -******************************************************************/ - -static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp) -{ - return locking_ref_count_key(fsp->file_id); + return make_tdb_data((uint8 *)&fsp->file_id, sizeof(fsp->file_id)); } /******************************************************************* @@ -425,7 +398,8 @@ bool posix_locking_end(void) static void increment_windows_lock_ref_count(files_struct *fsp) { - TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + struct lock_ref_count_key tmp; + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp, &tmp); TDB_DATA dbuf; int lock_ref_count; @@ -454,7 +428,8 @@ static void increment_windows_lock_ref_count(files_struct *fsp) static void decrement_windows_lock_ref_count(files_struct *fsp) { - TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + struct lock_ref_count_key tmp; + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp, &tmp); TDB_DATA dbuf; int lock_ref_count; @@ -486,7 +461,8 @@ static void decrement_windows_lock_ref_count(files_struct *fsp) void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount) { - TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + struct lock_ref_count_key tmp; + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp, &tmp); TDB_DATA dbuf; int lock_ref_count; @@ -518,7 +494,8 @@ void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount) static int get_windows_lock_ref_count(files_struct *fsp) { - TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + struct lock_ref_count_key tmp; + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp, &tmp); TDB_DATA dbuf; int lock_ref_count; @@ -541,7 +518,8 @@ static int get_windows_lock_ref_count(files_struct *fsp) static void delete_windows_lock_ref_count(files_struct *fsp) { - TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + struct lock_ref_count_key tmp; + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp, &tmp); /* Not a bug if it doesn't exist - no locks were ever granted. */ tdb_delete(posix_pending_close_tdb, kbuf); -- cgit From 0527d3758ad7522995e1e1cc85a3c1b9ee22de52 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Dec 2007 20:41:24 +0100 Subject: Remove a static (This used to be commit 1f317f471af72f8bbc6c9fdd3e79a27c59e6fb6e) --- source3/locking/locking.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index eb7531d9a0..296323f7da 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -430,14 +430,10 @@ bool locking_end(void) Form a static locking key for a dev/inode pair. ******************************************************************/ -static TDB_DATA locking_key(struct file_id id) +static TDB_DATA locking_key(const struct file_id *id, struct file_id *tmp) { - static struct file_id key; - TDB_DATA kbuf; - key = id; - kbuf.dptr = (uint8 *)&key; - kbuf.dsize = sizeof(key); - return kbuf; + *tmp = *id; + return make_tdb_data((const uint8_t *)tmp, sizeof(*tmp)); } /******************************************************************* @@ -783,12 +779,13 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, } struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, - struct file_id id, + const struct file_id id, const char *servicepath, const char *fname) { struct share_mode_lock *lck; - TDB_DATA key = locking_key(id); + struct file_id tmp; + TDB_DATA key = locking_key(&id, &tmp); if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) { DEBUG(0, ("talloc failed\n")); @@ -814,12 +811,13 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, } struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, - struct file_id id, + const struct file_id id, const char *servicepath, const char *fname) { struct share_mode_lock *lck; - TDB_DATA key = locking_key(id); + struct file_id tmp; + TDB_DATA key = locking_key(&id, &tmp); TDB_DATA data; if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) { -- cgit From d60fac2a5a789680b6dd9f05ab15a3033ec2887c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Dec 2007 20:53:22 +0100 Subject: Tiny simplifications locking.c:open_read_only was unused don't export the silly boolean flag locking_init(bool read_only) (This used to be commit 2f3c865707010bc7c463a02782dbee3dc2479da1) --- source3/locking/brlock.c | 7 ++----- source3/locking/locking.c | 24 ++++++++++++++---------- source3/locking/posix.c | 2 +- 3 files changed, 17 insertions(+), 16 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index f821761cd7..eb42d081fe 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -258,7 +258,7 @@ static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *loc Open up the brlock.tdb database. ****************************************************************************/ -void brl_init(int read_only) +void brl_init(bool read_only) { if (brlock_db) { return; @@ -279,11 +279,8 @@ void brl_init(int read_only) Close down the brlock.tdb database. ****************************************************************************/ -void brl_shutdown(int read_only) +void brl_shutdown(void) { - if (!brlock_db) { - return; - } TALLOC_FREE(brlock_db); } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 296323f7da..dab21e53b3 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -385,9 +385,7 @@ void locking_close_file(struct messaging_context *msg_ctx, Initialise the locking functions. ****************************************************************************/ -static int open_read_only; - -bool locking_init(int read_only) +static bool locking_init_internal(bool read_only) { brl_init(read_only); @@ -408,22 +406,28 @@ bool locking_init(int read_only) if (!posix_locking_init(read_only)) return False; - open_read_only = read_only; - return True; } +bool locking_init(void) +{ + return locking_init_internal(false); +} + +bool locking_init_readonly(void) +{ + return locking_init_internal(true); +} + /******************************************************************* Deinitialize the share_mode management. ******************************************************************/ bool locking_end(void) { - brl_shutdown(open_read_only); - if (lock_db) { - TALLOC_FREE(lock_db); - } - return True; + brl_shutdown(); + TALLOC_FREE(lock_db); + return true; } /******************************************************************* diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 7669b140f6..4b0b91bd19 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -347,7 +347,7 @@ static TDB_DATA fd_array_key_fsp(files_struct *fsp) Create the in-memory POSIX lock databases. ********************************************************************/ -bool posix_locking_init(int read_only) +bool posix_locking_init(bool read_only) { if (posix_pending_close_tdb) { return True; -- cgit From a347ff84bcc86a54327e2bb15640c4540de44bfb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 10 Dec 2007 21:36:28 +0100 Subject: Convert the posix_pending_close_db to dbwrap_rbt (This used to be commit 841f4ccbfb5f79ac4f447342e9dd6ef73cacbc65) --- source3/locking/posix.c | 256 ++++++++++++++++++++++++------------------------ 1 file changed, 130 insertions(+), 126 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 4b0b91bd19..aef5c1784f 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -30,7 +30,7 @@ * The pending close database handle. */ -static TDB_CONTEXT *posix_pending_close_tdb; +static struct db_context *posix_pending_close_db; /**************************************************************************** First - the functions that deal with the underlying system locks - these @@ -349,20 +349,18 @@ static TDB_DATA fd_array_key_fsp(files_struct *fsp) bool posix_locking_init(bool read_only) { - if (posix_pending_close_tdb) { - return True; - } - - if (!posix_pending_close_tdb) { - posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); + if (posix_pending_close_db != NULL) { + return true; } - if (!posix_pending_close_tdb) { + + posix_pending_close_db = db_open_rbt(NULL); + + if (posix_pending_close_db == NULL) { DEBUG(0,("Failed to open POSIX pending close database.\n")); - return False; + return false; } - return True; + return true; } /******************************************************************* @@ -371,10 +369,11 @@ bool posix_locking_init(bool read_only) bool posix_locking_end(void) { - if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) { - return False; - } - return True; + /* + * Shouldn't we close all fd's here? + */ + TALLOC_FREE(posix_pending_close_db); + return true; } /**************************************************************************** @@ -399,60 +398,33 @@ bool posix_locking_end(void) static void increment_windows_lock_ref_count(files_struct *fsp) { struct lock_ref_count_key tmp; - TDB_DATA kbuf = locking_ref_count_key_fsp(fsp, &tmp); - TDB_DATA dbuf; - int lock_ref_count; - - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - if (dbuf.dptr == NULL) { - dbuf.dptr = (uint8 *)SMB_MALLOC_P(int); - if (!dbuf.dptr) { - smb_panic("increment_windows_lock_ref_count: malloc fail"); - } - memset(dbuf.dptr, '\0', sizeof(int)); - dbuf.dsize = sizeof(int); - } + struct db_record *rec; + int lock_ref_count = 0; + NTSTATUS status; - memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); - lock_ref_count++; - memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); - - if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - smb_panic("increment_windows_lock_ref_count: tdb_store_fail"); - } - SAFE_FREE(dbuf.dptr); - - DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n", - fsp->fsp_name, lock_ref_count )); -} + rec = posix_pending_close_db->fetch_locked( + posix_pending_close_db, talloc_tos(), + locking_ref_count_key_fsp(fsp, &tmp)); -static void decrement_windows_lock_ref_count(files_struct *fsp) -{ - struct lock_ref_count_key tmp; - TDB_DATA kbuf = locking_ref_count_key_fsp(fsp, &tmp); - TDB_DATA dbuf; - int lock_ref_count; + SMB_ASSERT(rec != NULL); - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - if (!dbuf.dptr) { - smb_panic("decrement_windows_lock_ref_count: logic error"); + if (rec->value.dptr != NULL) { + SMB_ASSERT(rec->value.dsize == sizeof(lock_ref_count)); + memcpy(&lock_ref_count, rec->value.dptr, + sizeof(lock_ref_count)); } - memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); - lock_ref_count--; - memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); + lock_ref_count++; - if (lock_ref_count < 0) { - smb_panic("decrement_windows_lock_ref_count: lock_count logic error"); - } + status = rec->store(rec, make_tdb_data((uint8 *)&lock_ref_count, + sizeof(lock_ref_count)), 0); - if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - smb_panic("decrement_windows_lock_ref_count: tdb_store_fail"); - } - SAFE_FREE(dbuf.dptr); + SMB_ASSERT(NT_STATUS_IS_OK(status)); + + TALLOC_FREE(rec); - DEBUG(10,("decrement_windows_lock_ref_count for file now %s = %d\n", - fsp->fsp_name, lock_ref_count )); + DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n", + fsp->fsp_name, lock_ref_count )); } /**************************************************************************** @@ -462,30 +434,38 @@ static void decrement_windows_lock_ref_count(files_struct *fsp) void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount) { struct lock_ref_count_key tmp; - TDB_DATA kbuf = locking_ref_count_key_fsp(fsp, &tmp); - TDB_DATA dbuf; - int lock_ref_count; + struct db_record *rec; + int lock_ref_count = 0; + NTSTATUS status; - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - if (!dbuf.dptr) { - return; - } + rec = posix_pending_close_db->fetch_locked( + posix_pending_close_db, talloc_tos(), + locking_ref_count_key_fsp(fsp, &tmp)); + + SMB_ASSERT((rec != NULL) + && (rec->value.dptr != NULL) + && (rec->value.dsize == sizeof(lock_ref_count))); + + memcpy(&lock_ref_count, rec->value.dptr, sizeof(lock_ref_count)); + + SMB_ASSERT(lock_ref_count > 0); - memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); lock_ref_count -= dcount; - if (lock_ref_count < 0) { - smb_panic("reduce_windows_lock_ref_count: lock_count logic error"); - } - memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); - - if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - smb_panic("reduce_windows_lock_ref_count: tdb_store_fail"); - } - SAFE_FREE(dbuf.dptr); + status = rec->store(rec, make_tdb_data((uint8 *)&lock_ref_count, + sizeof(lock_ref_count)), 0); + + SMB_ASSERT(NT_STATUS_IS_OK(status)); + + TALLOC_FREE(rec); DEBUG(10,("reduce_windows_lock_ref_count for file now %s = %d\n", - fsp->fsp_name, lock_ref_count )); + fsp->fsp_name, lock_ref_count )); +} + +static void decrement_windows_lock_ref_count(files_struct *fsp) +{ + reduce_windows_lock_ref_count(fsp, 1); } /**************************************************************************** @@ -495,20 +475,25 @@ void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount) static int get_windows_lock_ref_count(files_struct *fsp) { struct lock_ref_count_key tmp; - TDB_DATA kbuf = locking_ref_count_key_fsp(fsp, &tmp); TDB_DATA dbuf; - int lock_ref_count; + int res; + int lock_ref_count = 0; - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - if (!dbuf.dptr) { - lock_ref_count = 0; - } else { - memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + res = posix_pending_close_db->fetch( + posix_pending_close_db, talloc_tos(), + locking_ref_count_key_fsp(fsp, &tmp), &dbuf); + + SMB_ASSERT(res == 0); + + if (dbuf.dsize != 0) { + SMB_ASSERT(dbuf.dsize == sizeof(lock_ref_count)); + memcpy(&lock_ref_count, dbuf.dptr, sizeof(lock_ref_count)); + TALLOC_FREE(dbuf.dptr); } - SAFE_FREE(dbuf.dptr); DEBUG(10,("get_windows_lock_count for file %s = %d\n", - fsp->fsp_name, lock_ref_count )); + fsp->fsp_name, lock_ref_count )); + return lock_ref_count; } @@ -519,11 +504,21 @@ static int get_windows_lock_ref_count(files_struct *fsp) static void delete_windows_lock_ref_count(files_struct *fsp) { struct lock_ref_count_key tmp; - TDB_DATA kbuf = locking_ref_count_key_fsp(fsp, &tmp); + struct db_record *rec; + + rec = posix_pending_close_db->fetch_locked( + posix_pending_close_db, talloc_tos(), + locking_ref_count_key_fsp(fsp, &tmp)); + + SMB_ASSERT(rec != NULL); /* Not a bug if it doesn't exist - no locks were ever granted. */ - tdb_delete(posix_pending_close_tdb, kbuf); - DEBUG(10,("delete_windows_lock_ref_count for file %s\n", fsp->fsp_name)); + + rec->delete_rec(rec); + TALLOC_FREE(rec); + + DEBUG(10,("delete_windows_lock_ref_count for file %s\n", + fsp->fsp_name)); } /**************************************************************************** @@ -532,30 +527,35 @@ static void delete_windows_lock_ref_count(files_struct *fsp) static void add_fd_to_close_entry(files_struct *fsp) { - TDB_DATA kbuf = fd_array_key_fsp(fsp); - TDB_DATA dbuf; + struct db_record *rec; + uint8_t *new_data; + NTSTATUS status; - dbuf.dptr = NULL; - dbuf.dsize = 0; + rec = posix_pending_close_db->fetch_locked( + posix_pending_close_db, talloc_tos(), + fd_array_key_fsp(fsp)); - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + SMB_ASSERT(rec != NULL); - dbuf.dptr = (uint8 *)SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); - if (!dbuf.dptr) { - smb_panic("add_fd_to_close_entry: SMB_REALLOC failed"); - } + new_data = TALLOC_ARRAY( + rec, uint8_t, rec->value.dsize + sizeof(fsp->fh->fd)); - memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int)); - dbuf.dsize += sizeof(int); + SMB_ASSERT(new_data != NULL); - if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - smb_panic("add_fd_to_close_entry: tdb_store_fail"); - } + memcpy(new_data, rec->value.dptr, rec->value.dsize); + memcpy(new_data + rec->value.dsize, + &fsp->fh->fd, sizeof(fsp->fh->fd)); - DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n", - fsp->fh->fd, fsp->fsp_name )); + status = rec->store( + rec, make_tdb_data(new_data, + rec->value.dsize + sizeof(fsp->fh->fd)), 0); + + SMB_ASSERT(NT_STATUS_IS_OK(status)); - SAFE_FREE(dbuf.dptr); + TALLOC_FREE(rec); + + DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n", + fsp->fh->fd, fsp->fsp_name )); } /**************************************************************************** @@ -564,37 +564,41 @@ static void add_fd_to_close_entry(files_struct *fsp) static void delete_close_entries(files_struct *fsp) { - TDB_DATA kbuf = fd_array_key_fsp(fsp); + struct db_record *rec; - if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) { - smb_panic("delete_close_entries: tdb_delete failed"); - } + rec = posix_pending_close_db->fetch_locked( + posix_pending_close_db, talloc_tos(), + fd_array_key_fsp(fsp)); + + SMB_ASSERT(rec != NULL); + rec->delete_rec(rec); + TALLOC_FREE(rec); } /**************************************************************************** - Get the array of POSIX pending close records for an open fsp. Caller must - free. Returns number of entries. + Get the array of POSIX pending close records for an open fsp. Returns number + of entries. ****************************************************************************/ -static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) +static size_t get_posix_pending_close_entries(TALLOC_CTX *mem_ctx, + files_struct *fsp, int **entries) { - TDB_DATA kbuf = fd_array_key_fsp(fsp); TDB_DATA dbuf; - size_t count = 0; + int res; - *entries = NULL; - dbuf.dptr = NULL; + res = posix_pending_close_db->fetch( + posix_pending_close_db, mem_ctx, fd_array_key_fsp(fsp), + &dbuf); - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + SMB_ASSERT(res == 0); - if (!dbuf.dptr) { + if (dbuf.dsize == 0) { + *entries = NULL; return 0; } *entries = (int *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(int)); - - return count; + return (size_t)(dbuf.dsize / sizeof(int)); } /**************************************************************************** @@ -641,7 +645,7 @@ NTSTATUS fd_close_posix(struct connection_struct *conn, files_struct *fsp) * from the tdb and close them all. */ - count = get_posix_pending_close_entries(fsp, &fd_array); + count = get_posix_pending_close_entries(talloc_tos(), fsp, &fd_array); if (count) { DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); @@ -660,7 +664,7 @@ NTSTATUS fd_close_posix(struct connection_struct *conn, files_struct *fsp) delete_close_entries(fsp); } - SAFE_FREE(fd_array); + TALLOC_FREE(fd_array); /* Don't need a lock ref count on this dev/ino anymore. */ delete_windows_lock_ref_count(fsp); -- cgit From 4773973300d9b4c6d46bdeefd57d200378f6cec3 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 22 Dec 2007 01:49:29 +0100 Subject: Remove redundant connection_struct from fd_close_posix() parameter list. Michael (This used to be commit f3365b74ac016eaee1e82eef769dd618af5df201) --- source3/locking/posix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index aef5c1784f..207ee57ce1 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -607,14 +607,14 @@ static size_t get_posix_pending_close_entries(TALLOC_CTX *mem_ctx, to delete all locks on this fsp before this function is called. ****************************************************************************/ -NTSTATUS fd_close_posix(struct connection_struct *conn, files_struct *fsp) +NTSTATUS fd_close_posix(struct files_struct *fsp) { int saved_errno = 0; int ret; int *fd_array = NULL; size_t count, i; - if (!lp_locking(fsp->conn->params) || !lp_posix_locking(conn->params)) { + if (!lp_locking(fsp->conn->params) || !lp_posix_locking(fsp->conn->params)) { /* * No locking or POSIX to worry about or we want POSIX semantics * which will lose all locks on all fd's open on this dev/inode, -- cgit From a8d2664fec3867cc40894531615a9a2d8036fa25 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 4 Jan 2008 23:27:14 +0100 Subject: allocate share_mode_str only when needed (This used to be commit a98693bfa7bfe72ffa164d21b3e9636e268708aa) --- source3/locking/locking.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index dab21e53b3..270c6d2261 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -608,7 +608,10 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) for (i = 0; i < lck->num_share_modes; i++) { struct share_mode_entry *entry_p = &lck->share_modes[i]; - char *str = share_mode_str(NULL, i, entry_p); + char *str = NULL; + if (DEBUGLEVEL >= 10) { + str = share_mode_str(NULL, i, entry_p); + } DEBUG(10,("parse_share_modes: %s\n", str ? str : "")); if (!process_exists(entry_p->pid)) { -- cgit From edd30e716fb5133b269ef82358e95d187a107870 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 16:38:23 +0100 Subject: Remove redundant parameter fd from SMB_VFS_LOCK(). Michael (This used to be commit 4f3ab2c406072e0b43581057e7e785e8ad454cfa) --- source3/locking/posix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 207ee57ce1..9f84e7380f 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -188,7 +188,7 @@ static bool posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type)); - ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); + ret = SMB_VFS_LOCK(fsp, op, offset, count, type); if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { @@ -212,7 +212,7 @@ static bool posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); errno = 0; count &= 0x7fffffff; - ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); + ret = SMB_VFS_LOCK(fsp, op, offset, count, type); } } -- cgit From fa6d7b42f1c85004a7c7ece4822277e8e23f32f5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 7 Jan 2008 12:57:10 +0100 Subject: Do not talloc_strdup filename and servicepath (This used to be commit 66be770993acf4e1673e9615bcddb21768c33e62) --- source3/locking/locking.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 270c6d2261..2ec8cd2938 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -585,22 +585,14 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) } /* Save off the associated service path and filename. */ - lck->servicepath = talloc_strdup(lck, (const char *)dbuf.dptr + sizeof(*data) + - (lck->num_share_modes * - sizeof(struct share_mode_entry)) + - data->u.s.delete_token_size ); - if (lck->servicepath == NULL) { - smb_panic("parse_share_modes: talloc_strdup failed"); - } - - lck->filename = talloc_strdup(lck, (const char *)dbuf.dptr + sizeof(*data) + - (lck->num_share_modes * - sizeof(struct share_mode_entry)) + - data->u.s.delete_token_size + - strlen(lck->servicepath) + 1 ); - if (lck->filename == NULL) { - smb_panic("parse_share_modes: talloc_strdup failed"); - } + lck->servicepath = (const char *)dbuf.dptr + sizeof(*data) + + (lck->num_share_modes * sizeof(struct share_mode_entry)) + + data->u.s.delete_token_size; + + lck->filename = (const char *)dbuf.dptr + sizeof(*data) + + (lck->num_share_modes * sizeof(struct share_mode_entry)) + + data->u.s.delete_token_size + + strlen(lck->servicepath) + 1; /* * Ensure that each entry has a real process attached. -- cgit From f7bf4cb3f17b5356b93c4ec89c300ad5dc20d2bc Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 22:18:50 +0100 Subject: Remove redundant parameter fd from SMB_VFS_GETLOCK(). Michael (This used to be commit ee5a20becdcdb20d7012732b324c6938fab44f67) --- source3/locking/posix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 9f84e7380f..1b88c472b0 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -233,7 +233,7 @@ static bool posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n", fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype)); - ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); + ret = SMB_VFS_GETLOCK(fsp, poffset, pcount, ptype, &pid); if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { @@ -257,7 +257,7 @@ static bool posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); errno = 0; *pcount &= 0x7fffffff; - ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); + ret = SMB_VFS_GETLOCK(fsp,poffset,pcount,ptype,&pid); } } -- cgit From 3cc3b9e1879d3d9714ac2914364418a140e8389c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 6 Jan 2008 14:21:25 +0100 Subject: use talloc_tos in a few more places (This used to be commit 65dd869bea351010c67f02046ae4134bdada1a4c) --- source3/locking/locking.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 2ec8cd2938..ce7ba8fa66 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -925,7 +925,7 @@ bool get_delete_on_close_flag(struct file_id id) bool result; struct share_mode_lock *lck; - if (!(lck = fetch_share_mode_unlocked(NULL, id, NULL, NULL))) { + if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id, NULL, NULL))) { return False; } result = lck->delete_on_close; @@ -1328,7 +1328,7 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, UNIX_USER_TOKE return True; } - lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); if (lck == NULL) { return False; } -- cgit From 5ddb2abf7611a93960056075ea56f992329c3678 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 6 Jan 2008 16:15:45 +0100 Subject: Some more talloc_tos() (This used to be commit 444e35e7df1f13fc285183da8fb41b30ad99a3fa) --- source3/locking/locking.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index ce7ba8fa66..113b994bc7 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -102,7 +102,7 @@ bool is_locked(files_struct *fsp, DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); ret = False; } else { - struct byte_range_lock *br_lck = brl_get_locks_readonly(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks_readonly(talloc_tos(), fsp); if (!br_lck) { return False; } @@ -116,7 +116,7 @@ bool is_locked(files_struct *fsp, TALLOC_FREE(br_lck); } } else { - struct byte_range_lock *br_lck = brl_get_locks_readonly(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks_readonly(talloc_tos(), fsp); if (!br_lck) { return False; } @@ -160,7 +160,7 @@ NTSTATUS query_lock(files_struct *fsp, return NT_STATUS_OK; } - br_lck = brl_get_locks_readonly(NULL, fsp); + br_lck = brl_get_locks_readonly(talloc_tos(), fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -210,7 +210,7 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx, lock_flav_name(lock_flav), lock_type_name(lock_type), (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - br_lck = brl_get_locks(NULL, fsp); + br_lck = brl_get_locks(talloc_tos(), fsp); if (!br_lck) { *perr = NT_STATUS_NO_MEMORY; return NULL; @@ -269,7 +269,7 @@ NTSTATUS do_unlock(struct messaging_context *msg_ctx, DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n", (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - br_lck = brl_get_locks(NULL, fsp); + br_lck = brl_get_locks(talloc_tos(), fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -323,7 +323,7 @@ NTSTATUS do_lock_cancel(files_struct *fsp, DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for fnum %d file %s\n", (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - br_lck = brl_get_locks(NULL, fsp); + br_lck = brl_get_locks(talloc_tos(), fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -372,7 +372,7 @@ void locking_close_file(struct messaging_context *msg_ctx, return; } - br_lck = brl_get_locks(NULL,fsp); + br_lck = brl_get_locks(talloc_tos(),fsp); if (br_lck) { cancel_pending_lock_requests_by_fid(fsp, br_lck); -- cgit From 5a8bbc64cc7327facb2a3d136b9c9a3e15a1903a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 12 Jan 2008 23:05:23 +0100 Subject: Trivial simplification (This used to be commit 616bc34744487450edd47e212a29c0f57eabb722) --- source3/locking/locking.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 113b994bc7..bae4518575 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1281,11 +1281,7 @@ static UNIX_USER_TOKEN *copy_unix_token(TALLOC_CTX *ctx, UNIX_USER_TOKEN *tok) void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok) { - /* Ensure there's no token. */ - if (lck->delete_token) { - TALLOC_FREE(lck->delete_token); /* Also deletes groups... */ - lck->delete_token = NULL; - } + TALLOC_FREE(lck->delete_token); /* Also deletes groups... */ /* Copy the new token (can be NULL). */ lck->delete_token = copy_unix_token(lck, tok); -- cgit From 8d464d470a534d2914eca7287aedaa4205478ca3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 12 Jan 2008 23:06:33 +0100 Subject: Don't early delete the share mode tdb data We now refer directly to the file name in the tdb data, so don't delete it. (This used to be commit 71de4946cf00cf8b7bb2f2d92832166bee12e84a) --- source3/locking/locking.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index bae4518575..513bb31d9d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -836,8 +836,6 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, return NULL; } - TALLOC_FREE(data.dptr); - return lck; } -- cgit From 68694369fc96354452979b07425f3f48c4f73bbe Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 16 Jan 2008 12:09:48 +0300 Subject: Merge CTDB-related fixes from samba-ctdb 3.0 branch (http://samba.org/~tridge/3_0-ctdb) Signed-off-by: Alexander Bokovoy (This used to be commit 0c8e23afbbb2d081fc23908bafcad04650bfacea) --- source3/locking/brlock.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index eb42d081fe..4191871bb1 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -41,11 +41,11 @@ static struct db_context *brlock_db; static void print_lock_struct(unsigned int i, struct lock_struct *pls) { - DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %s, ", + DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %u, ", i, (unsigned int)pls->context.smbpid, (unsigned int)pls->context.tid, - procid_str_static(&pls->context.pid) )); + (unsigned int)procid_to_pid(&pls->context.pid) )); DEBUG(10,("start = %.0f, size = %.0f, fnum = %d, %s %s\n", (double)pls->start, @@ -263,10 +263,9 @@ void brl_init(bool read_only) if (brlock_db) { return; } - brlock_db = db_open(NULL, lock_path("brlock.tdb"), 0, - TDB_DEFAULT - |TDB_VOLATILE - |(read_only?0x0:TDB_CLEAR_IF_FIRST), + brlock_db = db_open(NULL, lock_path("brlock.tdb"), + lp_open_files_db_hash_size(), + TDB_DEFAULT | TDB_CLEAR_IF_FIRST, read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 ); if (!brlock_db) { DEBUG(0,("Failed to open byte range locking database %s\n", @@ -1495,14 +1494,16 @@ static int traverse_fn(struct db_record *rec, void *state) } } - for ( i=0; ifn(*key, - locks[i].context.pid, - locks[i].lock_type, - locks[i].lock_flav, - locks[i].start, - locks[i].size, - cb->private_data); + if (cb->fn) { + for ( i=0; ifn(*key, + locks[i].context.pid, + locks[i].lock_type, + locks[i].lock_flav, + locks[i].start, + locks[i].size, + cb->private_data); + } } SAFE_FREE(locks); -- cgit From 33f3eeaa00974860dfc45962d5fd34cf05396c76 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 17:35:25 +0100 Subject: Fix some "set but never used" warnings (This used to be commit 4a6dadc5178f4861e9c032321939db3b639734b5) --- source3/locking/brlock.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 4191871bb1..341d00f3fe 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1539,11 +1539,6 @@ int brl_forall(void (*fn)(struct file_id id, struct server_id pid, static int byte_range_lock_destructor(struct byte_range_lock *br_lck) { - TDB_DATA key; - - key.dptr = (uint8 *)&br_lck->key; - key.dsize = sizeof(struct file_id); - if (br_lck->read_only) { SMB_ASSERT(!br_lck->modified); } -- cgit From 170995493376e926b7b30791286598ad6b7af4a4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 17 Mar 2008 14:40:07 +0100 Subject: Merge leftovers of 0e1a86bc845 in 3-0-ctdb (This used to be commit 64b1625f8e3bca43504871747bef6631e1b18f44) --- source3/locking/brlock.c | 2 +- source3/locking/locking.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 341d00f3fe..940dfbff8f 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -265,7 +265,7 @@ void brl_init(bool read_only) } brlock_db = db_open(NULL, lock_path("brlock.tdb"), lp_open_files_db_hash_size(), - TDB_DEFAULT | TDB_CLEAR_IF_FIRST, + TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST, read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 ); if (!brlock_db) { DEBUG(0,("Failed to open byte range locking database %s\n", diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 513bb31d9d..782e10fb7c 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -392,10 +392,9 @@ static bool locking_init_internal(bool read_only) if (lock_db) return True; - lock_db = db_open(NULL, lock_path("locking.tdb"), 0, - TDB_DEFAULT - |TDB_VOLATILE - |(read_only?0x0:TDB_CLEAR_IF_FIRST), + lock_db = db_open(NULL, lock_path("locking.tdb"), + lp_open_files_db_hash_size(), + TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST, read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); if (!lock_db) { -- cgit From 2ccf50256e31bd7b9da0f7a7c223bebca5bca062 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 12 Mar 2008 15:32:47 +0100 Subject: locking: store the write time in the locking.tdb This is needed to implement the strange write time update logic later. We need to store 2 time timestamps to distinguish between the time the file system had before the first client opened the file and a forced timestamp update. metze (This used to be commit 6aaa2ce0eeb46f6735ec984a2e7aadde7a7f456d) --- source3/locking/locking.c | 96 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 14 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 782e10fb7c..8d8c0347a5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -503,12 +503,20 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) data = (struct locking_data *)dbuf.dptr; lck->delete_on_close = data->u.s.delete_on_close; + lck->old_write_time = data->u.s.old_write_time; + lck->changed_write_time = data->u.s.changed_write_time; lck->num_share_modes = data->u.s.num_share_mode_entries; - DEBUG(10, ("parse_share_modes: delete_on_close: %d, " - "num_share_modes: %d\n", - lck->delete_on_close, - lck->num_share_modes)); + DEBUG(10, ("parse_share_modes: delete_on_close: %d, owrt: %s, " + "cwrt: %s, tok: %u, num_share_modes: %d\n", + lck->delete_on_close, + timestring(debug_ctx(), + convert_timespec_to_time_t(lck->old_write_time)), + timestring(debug_ctx(), + convert_timespec_to_time_t( + lck->changed_write_time)), + (unsigned int)data->u.s.delete_token_size, + lck->num_share_modes)); if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { DEBUG(0, ("invalid number of share modes: %d\n", @@ -659,11 +667,20 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) ZERO_STRUCTP(data); data->u.s.num_share_mode_entries = lck->num_share_modes; data->u.s.delete_on_close = lck->delete_on_close; + data->u.s.old_write_time = lck->old_write_time; + data->u.s.changed_write_time = lck->changed_write_time; data->u.s.delete_token_size = delete_token_size; - DEBUG(10, ("unparse_share_modes: del: %d, tok = %u, num: %d\n", - data->u.s.delete_on_close, - (unsigned int)data->u.s.delete_token_size, - data->u.s.num_share_mode_entries)); + + DEBUG(10,("unparse_share_modes: del: %d, owrt: %s cwrt: %s, tok: %u, " + "num: %d\n", data->u.s.delete_on_close, + timestring(debug_ctx(), + convert_timespec_to_time_t(lck->old_write_time)), + timestring(debug_ctx(), + convert_timespec_to_time_t( + lck->changed_write_time)), + (unsigned int)data->u.s.delete_token_size, + data->u.s.num_share_mode_entries)); + memcpy(result.dptr + sizeof(*data), lck->share_modes, sizeof(struct share_mode_entry)*lck->num_share_modes); offset = sizeof(*data) + @@ -739,7 +756,8 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, struct file_id id, const char *servicepath, const char *fname, - TDB_DATA share_mode_data) + TDB_DATA share_mode_data, + const struct timespec *old_write_time) { /* Ensure we set every field here as the destructor must be valid even if parse_share_modes fails. */ @@ -751,13 +769,16 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, lck->share_modes = NULL; lck->delete_token = NULL; lck->delete_on_close = False; + ZERO_STRUCT(lck->old_write_time); + ZERO_STRUCT(lck->changed_write_time); lck->fresh = False; lck->modified = False; lck->fresh = (share_mode_data.dptr == NULL); if (lck->fresh) { - if (fname == NULL || servicepath == NULL) { + if (fname == NULL || servicepath == NULL + || old_write_time == NULL) { return False; } lck->filename = talloc_strdup(lck, fname); @@ -766,6 +787,7 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, DEBUG(0, ("talloc failed\n")); return False; } + lck->old_write_time = *old_write_time; } else { if (!parse_share_modes(share_mode_data, lck)) { DEBUG(0, ("Could not parse share modes\n")); @@ -779,7 +801,8 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, const struct file_id id, const char *servicepath, - const char *fname) + const char *fname, + const struct timespec *old_write_time) { struct share_mode_lock *lck; struct file_id tmp; @@ -797,7 +820,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, } if (!fill_share_mode_lock(lck, id, servicepath, fname, - lck->record->value)) { + lck->record->value, old_write_time)) { DEBUG(3, ("fill_share_mode_lock failed\n")); TALLOC_FREE(lck); return NULL; @@ -829,7 +852,7 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, return NULL; } - if (!fill_share_mode_lock(lck, id, servicepath, fname, data)) { + if (!fill_share_mode_lock(lck, id, servicepath, fname, data, NULL)) { DEBUG(3, ("fill_share_mode_lock failed\n")); TALLOC_FREE(lck); return NULL; @@ -917,6 +940,26 @@ bool rename_share_filename(struct messaging_context *msg_ctx, return True; } +struct timespec get_write_time(struct file_id id) +{ + struct timespec result; + struct share_mode_lock *lck; + + ZERO_STRUCT(result); + + if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id, NULL, NULL))) { + return result; + } + result = lck->changed_write_time; + + if (null_timespec(result)) { + result = lck->old_write_time; + } + + TALLOC_FREE(lck); + return result; +} + bool get_delete_on_close_flag(struct file_id id) { bool result; @@ -1321,7 +1364,8 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, UNIX_USER_TOKE return True; } - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, + NULL); if (lck == NULL) { return False; } @@ -1361,6 +1405,30 @@ bool set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct return True; } +bool set_write_time(struct file_id fileid, struct timespec write_time, + bool overwrite) +{ + struct share_mode_lock *lck; + + DEBUG(5,("set_write_time: %s overwrite=%d id=%s\n", + timestring(debug_ctx(), + convert_timespec_to_time_t(write_time)), + overwrite, file_id_string_tos(&fileid))); + + lck = get_share_mode_lock(NULL, fileid, NULL, NULL, NULL); + if (lck == NULL) { + return False; + } + + if (overwrite || null_timespec(lck->changed_write_time)) { + lck->modified = True; + lck->changed_write_time = write_time; + } + + TALLOC_FREE(lck); + return True; +} + struct forall_state { void (*fn)(const struct share_mode_entry *entry, const char *sharepath, -- cgit From 851cadba51b00b326c5f040f23f95932aec53105 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Apr 2008 11:40:23 +0200 Subject: locking: combine get_delete_on_close_flag() and get_write_time() into get_file_infos() This means we need to fetch the record only once. metze (This used to be commit 4130b873291d39e363184fe4e38dc1f24ebe5056) --- source3/locking/locking.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 8d8c0347a5..5faebef1fe 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -940,37 +940,40 @@ bool rename_share_filename(struct messaging_context *msg_ctx, return True; } -struct timespec get_write_time(struct file_id id) +void get_file_infos(struct file_id id, + bool *delete_on_close, + struct timespec *write_time) { - struct timespec result; struct share_mode_lock *lck; - ZERO_STRUCT(result); + if (delete_on_close) { + *delete_on_close = false; + } + + if (write_time) { + ZERO_STRUCTP(write_time); + } if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id, NULL, NULL))) { - return result; + return; } - result = lck->changed_write_time; - if (null_timespec(result)) { - result = lck->old_write_time; + if (delete_on_close) { + *delete_on_close = lck->delete_on_close; } - TALLOC_FREE(lck); - return result; -} + if (write_time) { + struct timespec wt; -bool get_delete_on_close_flag(struct file_id id) -{ - bool result; - struct share_mode_lock *lck; - - if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id, NULL, NULL))) { - return False; + wt = lck->changed_write_time; + if (null_timespec(wt)) { + wt = lck->old_write_time; + } + + *write_time = wt; } - result = lck->delete_on_close; + TALLOC_FREE(lck); - return result; } bool is_valid_share_mode_entry(const struct share_mode_entry *e) -- cgit From e76ec752be503338c0a26be34f8d0fb4fbeb5fe6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Apr 2008 17:23:48 -0700 Subject: Quieten valgrind message on make valgrindtest. This doesn't seem to be valid (vl - feel free to confirm). Jeremy. (This used to be commit 43b0254d93540eeaddaa32d76dd9271f4dc2ebff) --- source3/locking/brlock.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/locking') diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 940dfbff8f..032aaa56b6 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -749,6 +749,11 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx, } #endif +#ifdef DEVELOPER + /* Quieten valgrind on test. */ + memset(&lock, '\0', sizeof(lock)); +#endif + lock.context.smbpid = smbpid; lock.context.pid = pid; lock.context.tid = br_lck->fsp->conn->cnum; -- cgit From 3756467db6a661be91f4aeb484000e993e4a9a4c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2008 12:18:33 +0100 Subject: Move the posix pending close functionality down into the VFS layer. This hides the pending close fds from the outside. Call order of SMB_VFS_CLOSE is reversed. Originally, it was: fd_close -> fd_close_posix -> SMB_VFS_CLOSE -> close And now it is: fd_close -> SMB_VFS_CLOSE -> fd_close_posix -> close This is in preparation of removing the fd parameter from the SMB_VFS_CLOSE function. But it is also the right place for the pending close calls anyways. Michael (This used to be commit 3cf56b124a2886c6260455bba4bf77d08e9a4f77) --- source3/locking/posix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 1b88c472b0..f42d1ec6f8 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -620,7 +620,7 @@ NTSTATUS fd_close_posix(struct files_struct *fsp) * which will lose all locks on all fd's open on this dev/inode, * just close. */ - ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); + ret = close(fsp->fh->fd); fsp->fh->fd = -1; if (ret == -1) { return map_nt_error_from_unix(errno); @@ -651,7 +651,7 @@ NTSTATUS fd_close_posix(struct files_struct *fsp) DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); for(i = 0; i < count; i++) { - if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) { + if (close(fd_array[i]) == -1) { saved_errno = errno; } } @@ -673,7 +673,7 @@ NTSTATUS fd_close_posix(struct files_struct *fsp) * Finally close the fd associated with this fsp. */ - ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); + ret = close(fsp->fh->fd); if (ret == 0 && saved_errno != 0) { errno = saved_errno; -- cgit From 96e9e83ee021db69179fe924144e6ba3dea1b73d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2008 13:03:16 +0100 Subject: Don't modify the fsp in fd_close_posix() anymore. Now that it is inside the vfs layer, this function should not alter the fsp (i.e. set fsp->fh->fd = -1) anymore. That belongs above the vfs layer. Michael (This used to be commit df264bf3e00d7d77afcf55e54d2669b9ffa9af4a) --- source3/locking/posix.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index f42d1ec6f8..844a86e863 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -621,7 +621,6 @@ NTSTATUS fd_close_posix(struct files_struct *fsp) * just close. */ ret = close(fsp->fh->fd); - fsp->fh->fd = -1; if (ret == -1) { return map_nt_error_from_unix(errno); } @@ -636,7 +635,6 @@ NTSTATUS fd_close_posix(struct files_struct *fsp) */ add_fd_to_close_entry(fsp); - fsp->fh->fd = -1; return NT_STATUS_OK; } @@ -680,8 +678,6 @@ NTSTATUS fd_close_posix(struct files_struct *fsp) ret = -1; } - fsp->fh->fd = -1; - if (ret == -1) { return map_nt_error_from_unix(errno); } -- cgit From 2f8dde9ec8110557c23df6ea66913a7d39425415 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2008 13:28:28 +0100 Subject: Change fd_close_posix() to return int instead of NTSTATUS. The errno is handed up through the VFS layer to the callers. Michael (This used to be commit d928e6648d61cf2d3c1b77db440efb835b729a84) --- source3/locking/posix.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 844a86e863..aedc12dede 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -607,7 +607,7 @@ static size_t get_posix_pending_close_entries(TALLOC_CTX *mem_ctx, to delete all locks on this fsp before this function is called. ****************************************************************************/ -NTSTATUS fd_close_posix(struct files_struct *fsp) +int fd_close_posix(struct files_struct *fsp) { int saved_errno = 0; int ret; @@ -620,11 +620,7 @@ NTSTATUS fd_close_posix(struct files_struct *fsp) * which will lose all locks on all fd's open on this dev/inode, * just close. */ - ret = close(fsp->fh->fd); - if (ret == -1) { - return map_nt_error_from_unix(errno); - } - return NT_STATUS_OK; + return close(fsp->fh->fd); } if (get_windows_lock_ref_count(fsp)) { @@ -635,7 +631,7 @@ NTSTATUS fd_close_posix(struct files_struct *fsp) */ add_fd_to_close_entry(fsp); - return NT_STATUS_OK; + return 0; } /* @@ -678,11 +674,7 @@ NTSTATUS fd_close_posix(struct files_struct *fsp) ret = -1; } - if (ret == -1) { - return map_nt_error_from_unix(errno); - } - - return NT_STATUS_OK; + return ret; } /**************************************************************************** -- cgit From 8c9060240eec82d750904d8b07fd38b168a84bea Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2008 13:41:46 +0100 Subject: Slight reformatting of fd_close_posix(), while I'm at it. Wrap lines and remove trailing space. Michael (This used to be commit 74ed53a115b2063d4d5c8572af8f1302bc658882) --- source3/locking/posix.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/posix.c b/source3/locking/posix.c index aedc12dede..32e1ee9fbf 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -614,7 +614,9 @@ int fd_close_posix(struct files_struct *fsp) int *fd_array = NULL; size_t count, i; - if (!lp_locking(fsp->conn->params) || !lp_posix_locking(fsp->conn->params)) { + if (!lp_locking(fsp->conn->params) || + !lp_posix_locking(fsp->conn->params)) + { /* * No locking or POSIX to worry about or we want POSIX semantics * which will lose all locks on all fd's open on this dev/inode, @@ -626,8 +628,9 @@ int fd_close_posix(struct files_struct *fsp) if (get_windows_lock_ref_count(fsp)) { /* - * There are outstanding locks on this dev/inode pair on other fds. - * Add our fd to the pending close tdb and set fsp->fh->fd to -1. + * There are outstanding locks on this dev/inode pair on + * other fds. Add our fd to the pending close tdb and set + * fsp->fh->fd to -1. */ add_fd_to_close_entry(fsp); @@ -642,7 +645,8 @@ int fd_close_posix(struct files_struct *fsp) count = get_posix_pending_close_entries(talloc_tos(), fsp, &fd_array); if (count) { - DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); + DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", + (unsigned int)count)); for(i = 0; i < count; i++) { if (close(fd_array[i]) == -1) { @@ -672,7 +676,7 @@ int fd_close_posix(struct files_struct *fsp) if (ret == 0 && saved_errno != 0) { errno = saved_errno; ret = -1; - } + } return ret; } -- cgit From b430b382202858a6c52c1cacbb91910b2dd7e16c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 May 2008 17:22:10 -0700 Subject: Remove the "stat_open()" function, flag, and all associated code. It was only being (correctly) used in the can_read/can_write checks for hide unreadable/unwritable and this is more properly done using the functions in smbd/file_access.c. Preparing to do NT access checks on all file access. Jeremy. (This used to be commit 6bfb06ad95963ae2acb67c4694a98282d3b29faa) --- source3/locking/locking.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 5faebef1fe..17131d9194 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1363,10 +1363,6 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, UNIX_USER_TOKE delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); - if (fsp->is_stat) { - return True; - } - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, NULL); if (lck == NULL) { -- cgit From 6811dc3fc236e62f042e43efa500cc55346c29d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 May 2008 11:23:59 -0700 Subject: Allow server manager to close open files selected by id. Jeremy. (This used to be commit 7eeed8bb41059ec2bddedb6a71deddeec7f33af2) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 17131d9194..accd3f7014 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -443,7 +443,7 @@ static TDB_DATA locking_key(const struct file_id *id, struct file_id *tmp) Print out a share mode. ********************************************************************/ -char *share_mode_str(TALLOC_CTX *ctx, int num, struct share_mode_entry *e) +char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e) { return talloc_asprintf(ctx, "share_mode_entry[%d]: %s " "pid = %s, share_access = 0x%x, private_options = 0x%x, " -- cgit From ae923dbd4e4e5cba35b36ad353a943b826e2a2c5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 4 Jul 2008 09:28:04 +0200 Subject: Fix alignment problems on sparc, bug 5512 Patch successfully tested by Christoph Kaegi , thanks. (cherry picked from commit 9f8df16f476c49da85000b7365c8a6e33b8b71fc) (This used to be commit 82ed19ff64fc815a8ca9fbd7d3331671ecf5d12b) --- source3/locking/locking.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index accd3f7014..ca61a886a6 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -493,19 +493,19 @@ static void print_share_mode_table(struct locking_data *data) static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) { - struct locking_data *data; + struct locking_data data; int i; if (dbuf.dsize < sizeof(struct locking_data)) { smb_panic("parse_share_modes: buffer too short"); } - data = (struct locking_data *)dbuf.dptr; + memcpy(&data, dbuf.dptr, sizeof(data)); - lck->delete_on_close = data->u.s.delete_on_close; - lck->old_write_time = data->u.s.old_write_time; - lck->changed_write_time = data->u.s.changed_write_time; - lck->num_share_modes = data->u.s.num_share_mode_entries; + lck->delete_on_close = data.u.s.delete_on_close; + lck->old_write_time = data.u.s.old_write_time; + lck->changed_write_time = data.u.s.changed_write_time; + lck->num_share_modes = data.u.s.num_share_mode_entries; DEBUG(10, ("parse_share_modes: delete_on_close: %d, owrt: %s, " "cwrt: %s, tok: %u, num_share_modes: %d\n", @@ -515,7 +515,7 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) timestring(debug_ctx(), convert_timespec_to_time_t( lck->changed_write_time)), - (unsigned int)data->u.s.delete_token_size, + (unsigned int)data.u.s.delete_token_size, lck->num_share_modes)); if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { @@ -535,7 +535,8 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) } lck->share_modes = (struct share_mode_entry *) - TALLOC_MEMDUP(lck, dbuf.dptr+sizeof(*data), + TALLOC_MEMDUP(lck, + dbuf.dptr+sizeof(struct locking_data), lck->num_share_modes * sizeof(struct share_mode_entry)); @@ -545,15 +546,15 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) } /* Get any delete token. */ - if (data->u.s.delete_token_size) { - uint8 *p = dbuf.dptr + sizeof(*data) + + if (data.u.s.delete_token_size) { + uint8 *p = dbuf.dptr + sizeof(struct locking_data) + (lck->num_share_modes * sizeof(struct share_mode_entry)); - if ((data->u.s.delete_token_size < sizeof(uid_t) + sizeof(gid_t)) || - ((data->u.s.delete_token_size - sizeof(uid_t)) % sizeof(gid_t)) != 0) { + if ((data.u.s.delete_token_size < sizeof(uid_t) + sizeof(gid_t)) || + ((data.u.s.delete_token_size - sizeof(uid_t)) % sizeof(gid_t)) != 0) { DEBUG(0, ("parse_share_modes: invalid token size %d\n", - data->u.s.delete_token_size)); + data.u.s.delete_token_size)); smb_panic("parse_share_modes: invalid token size"); } @@ -569,8 +570,8 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) p += sizeof(gid_t); /* Any supplementary groups ? */ - lck->delete_token->ngroups = (data->u.s.delete_token_size > (sizeof(uid_t) + sizeof(gid_t))) ? - ((data->u.s.delete_token_size - + lck->delete_token->ngroups = (data.u.s.delete_token_size > (sizeof(uid_t) + sizeof(gid_t))) ? + ((data.u.s.delete_token_size - (sizeof(uid_t) + sizeof(gid_t)))/sizeof(gid_t)) : 0; if (lck->delete_token->ngroups) { @@ -592,13 +593,13 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) } /* Save off the associated service path and filename. */ - lck->servicepath = (const char *)dbuf.dptr + sizeof(*data) + + lck->servicepath = (const char *)dbuf.dptr + sizeof(struct locking_data) + (lck->num_share_modes * sizeof(struct share_mode_entry)) + - data->u.s.delete_token_size; + data.u.s.delete_token_size; - lck->filename = (const char *)dbuf.dptr + sizeof(*data) + + lck->filename = (const char *)dbuf.dptr + sizeof(struct locking_data) + (lck->num_share_modes * sizeof(struct share_mode_entry)) + - data->u.s.delete_token_size + + data.u.s.delete_token_size + strlen(lck->servicepath) + 1; /* -- cgit From 405b072431db3f3f8f16e4e0d2f2b1b2f1c71286 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 2008 19:00:48 -0700 Subject: Write times code update. Ok, here's the fix for the write times breakage with the new tests in S4 smbtorture. The key is keeping in the share mode struct the "old_file_time" as the real write time, set by all the write and allocation calls, and the "changed_write_time" as the "sticky" write time - set by the SET_FILE_TIME calls. We can set them independently (although I kept the optimization of not setting the "old_file_time" is a "changed_write_time" was already set, as we'll never see it. This allows us to update the write time immediately on the SMBwrite truncate case, SET_END_OF_FILE and SET_ALLOCATION_SIZE calls, whilst still have the 2 second delay on the "normal" SMBwrite, SMBwriteX calls. I think in a subsequent patch I'd like to change the name of these from "old_file_time" to "write_time" and "changed_write_time" to "sticky_write_time" to make this clearer. I think I also fixed a bug in Metze's original code in that once a write timestamp had been set from a "normal" SMBwriteX call the fsp->update_write_time_triggered variable was set and then never reset - thus meaning the write timestamp would never get updated again on subsequent SMBwriteX's. The new code checks the update_write_time_event event instead, and doesn't update is there's an event already scheduled. Metze especially, please check this over for your understanding. Jeremy. (This used to be commit 6f20585419046c4aca1f7d6c863cf79eb6ae53b0) --- source3/locking/locking.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index ca61a886a6..f1f9278668 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1405,22 +1405,21 @@ bool set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct return True; } -bool set_write_time(struct file_id fileid, struct timespec write_time, - bool overwrite) +bool set_sticky_write_time(struct file_id fileid, struct timespec write_time) { struct share_mode_lock *lck; - DEBUG(5,("set_write_time: %s overwrite=%d id=%s\n", + DEBUG(5,("set_sticky_write_time: %s id=%s\n", timestring(debug_ctx(), convert_timespec_to_time_t(write_time)), - overwrite, file_id_string_tos(&fileid))); + file_id_string_tos(&fileid))); lck = get_share_mode_lock(NULL, fileid, NULL, NULL, NULL); if (lck == NULL) { return False; } - if (overwrite || null_timespec(lck->changed_write_time)) { + if (timespec_compare(&lck->changed_write_time, &write_time) != 0) { lck->modified = True; lck->changed_write_time = write_time; } @@ -1429,6 +1428,30 @@ bool set_write_time(struct file_id fileid, struct timespec write_time, return True; } +bool set_write_time(struct file_id fileid, struct timespec write_time) +{ + struct share_mode_lock *lck; + + DEBUG(5,("set_sticky_write_time: %s id=%s\n", + timestring(debug_ctx(), + convert_timespec_to_time_t(write_time)), + file_id_string_tos(&fileid))); + + lck = get_share_mode_lock(NULL, fileid, NULL, NULL, NULL); + if (lck == NULL) { + return False; + } + + if (timespec_compare(&lck->old_write_time, &write_time) != 0) { + lck->modified = True; + lck->old_write_time = write_time; + } + + TALLOC_FREE(lck); + return True; +} + + struct forall_state { void (*fn)(const struct share_mode_entry *entry, const char *sharepath, -- cgit From e76cb70444a4cff5725cd0b9918b8af1f2857db2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 2008 20:37:00 -0700 Subject: Fix debug message to show correct function name. Jeremy. (This used to be commit 079c75ef3c169c7a5d81bcaa0b70b6e0df2c464d) --- source3/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/locking') diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f1f9278668..368ab1687c 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1432,7 +1432,7 @@ bool set_write_time(struct file_id fileid, struct timespec write_time) { struct share_mode_lock *lck; - DEBUG(5,("set_sticky_write_time: %s id=%s\n", + DEBUG(5,("set_write_time: %s id=%s\n", timestring(debug_ctx(), convert_timespec_to_time_t(write_time)), file_id_string_tos(&fileid))); -- cgit