summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/include/smb.h9
-rw-r--r--source3/locking/locking.c166
-rw-r--r--source3/param/loadparm.c4
-rw-r--r--source3/smbd/open.c3
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;