Fix for very subtle POSIX lock interaction race condition found by
authorJeremy Allison <jra@samba.org>
Fri, 4 Apr 2003 20:38:25 +0000 (20:38 +0000)
committerJeremy Allison <jra@samba.org>
Fri, 4 Apr 2003 20:38:25 +0000 (20:38 +0000)
Herb. We need to unlock POSIX locks before notifying pending lock
processes.
Jeremy.
(This used to be commit eb861e9d0fd79bbd9401ced8e55fe603c2aa7c1e)

source3/locking/brlock.c
source3/locking/locking.c
source3/smbd/blocking.c

index 4cd885f1a6507d4345742bb581efd5535ee08bc6..20d76c9c7926eec9079d075fb2f725e67a40d92d 100644 (file)
@@ -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; j<count; j++) {
                                        struct lock_struct *pend_lock = &locks[j];
index 651f905e15de6b4ff7071413ebfd63e9654bdfe7..1b40187ac4621c6ea7eb89f32c0bf7e42958785e 100644 (file)
@@ -132,7 +132,8 @@ 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, 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;
 }
 
index 581ce43f9118e7ac000bd664a57d7d359955d284..2802fbb151295530b251bf541aa2a4ff39c7efe1 100644 (file)
@@ -523,7 +523,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
 
       brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
                blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum,
-               blr->offset, blr->count, True);
+               blr->offset, blr->count, True, NULL, NULL);
 
       free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
       blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
@@ -554,7 +554,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
       blocking_lock_reply_error(blr,NT_STATUS_CANCELLED);
       brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
                blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum,
-               blr->offset, blr->count, True);
+               blr->offset, blr->count, True, NULL, NULL);
       free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
       blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
       continue;
@@ -651,7 +651,7 @@ void process_blocking_lock_queue(time_t t)
 
       brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
                blr->lock_pid, sys_getpid(), conn->cnum,
-               blr->offset, blr->count, True);
+               blr->offset, blr->count, True, NULL, NULL);
 
       blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
       free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
@@ -669,7 +669,7 @@ void process_blocking_lock_queue(time_t t)
 
       brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
                blr->lock_pid, sys_getpid(), conn->cnum,
-               blr->offset, blr->count, True);
+               blr->offset, blr->count, True, NULL, NULL);
 
       free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
       blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
@@ -685,7 +685,7 @@ void process_blocking_lock_queue(time_t t)
 
       brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
                blr->lock_pid, sys_getpid(), conn->cnum,
-               blr->offset, blr->count, True);
+               blr->offset, blr->count, True, NULL, NULL);
 
       free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
       blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
@@ -703,7 +703,7 @@ void process_blocking_lock_queue(time_t t)
 
       brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
                blr->lock_pid, sys_getpid(), conn->cnum,
-               blr->offset, blr->count, True);
+               blr->offset, blr->count, True, NULL, NULL);
 
       free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
       blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));