diff options
-rw-r--r-- | source3/include/proto.h | 1 | ||||
-rw-r--r-- | source3/include/smb.h | 9 | ||||
-rw-r--r-- | source3/locking/locking.c | 166 | ||||
-rw-r--r-- | source3/param/loadparm.c | 4 | ||||
-rw-r--r-- | source3/smbd/open.c | 3 |
5 files changed, 170 insertions, 13 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 215529f697..a02ea38bd9 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1357,6 +1357,7 @@ BOOL lp_map_hidden(int ); BOOL lp_map_archive(int ); BOOL lp_locking(int ); BOOL lp_strict_locking(int ); +BOOL lp_posix_locking(int ); BOOL lp_utmp(int ); BOOL lp_share_modes(int ); BOOL lp_oplocks(int ); diff --git a/source3/include/smb.h b/source3/include/smb.h index f57d108ee4..d8653538df 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -482,12 +482,13 @@ typedef struct files_struct mode_t mode; uint16 vuid; write_bmpx_struct *wbmpx_ptr; - write_cache *wcp; + write_cache *wcp; struct timeval open_time; - int share_mode; + int share_mode; time_t pending_modtime; - int oplock_type; - int sent_oplock_break; + int oplock_type; + int sent_oplock_break; + unsigned int num_posix_locks; BOOL open; BOOL can_lock; BOOL can_read; 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) { diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 5f948f78a4..a55018446d 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -342,6 +342,7 @@ typedef struct BOOL bMap_archive; BOOL bLocking; BOOL bStrictLocking; + BOOL bPosixLocking; #ifdef WITH_UTMP BOOL bUtmp; #endif @@ -454,6 +455,7 @@ static service sDefault = True, /* bMap_archive */ True, /* bLocking */ False, /* bStrictLocking */ + True, /* bPosixLocking */ #ifdef WITH_UTMP False, /* bUtmp */ #endif @@ -814,6 +816,7 @@ static struct parm_struct parm_table[] = {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL}, {"oplock break wait time",P_INTEGER,P_GLOBAL,&Globals.oplock_break_wait_time,NULL,NULL,FLAG_GLOBAL}, {"oplock contention limit",P_INTEGER,P_LOCAL,&sDefault.iOplockContentionLimit,NULL,NULL,FLAG_SHARE|FLAG_GLOBAL}, + {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL}, {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL}, {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL}, @@ -1420,6 +1423,7 @@ FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden) FN_LOCAL_BOOL(lp_map_archive,bMap_archive) FN_LOCAL_BOOL(lp_locking,bLocking) FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking) +FN_LOCAL_BOOL(lp_posix_locking,bPosixLocking) #ifdef WITH_UTMP FN_LOCAL_BOOL(lp_utmp,bUtmp) #endif diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 02832308c6..1c5a7e26e2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -165,6 +165,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->num_posix_locks = 0; fsp->is_directory = False; fsp->stat_open = False; fsp->directory_delete_on_close = False; @@ -738,6 +739,7 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->num_posix_locks = 0; fsp->is_directory = False; fsp->stat_open = True; fsp->directory_delete_on_close = False; @@ -851,6 +853,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->num_posix_locks = 0; fsp->is_directory = True; fsp->directory_delete_on_close = False; fsp->conn = conn; |