summaryrefslogtreecommitdiff
path: root/source3/locking/locking.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/locking/locking.c')
-rw-r--r--source3/locking/locking.c66
1 files changed, 49 insertions, 17 deletions
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) {