diff options
author | Jeremy Allison <jra@samba.org> | 2003-04-04 20:38:12 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2003-04-04 20:38:12 +0000 |
commit | 34226f1bd4d90ffe0f324277b11bbc4f2b575740 (patch) | |
tree | a44e535e8b42a27ce10ea0219198f65e6d77a9c2 | |
parent | 4127c455c8fd446ab952de37fabbd7d8ef20847a (diff) | |
download | samba-34226f1bd4d90ffe0f324277b11bbc4f2b575740.tar.gz samba-34226f1bd4d90ffe0f324277b11bbc4f2b575740.tar.bz2 samba-34226f1bd4d90ffe0f324277b11bbc4f2b575740.zip |
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)
-rw-r--r-- | source3/locking/brlock.c | 13 | ||||
-rw-r--r-- | source3/locking/locking.c | 36 | ||||
-rw-r--r-- | source3/smbd/blocking.c | 12 |
3 files changed, 46 insertions, 15 deletions
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; j<count; j++) { struct lock_struct *pend_lock = &locks[j]; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 651f905e15..1b40187ac4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -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; } diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 581ce43f91..2802fbb151 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -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)); |