summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2003-04-04 20:38:12 +0000
committerJeremy Allison <jra@samba.org>2003-04-04 20:38:12 +0000
commit34226f1bd4d90ffe0f324277b11bbc4f2b575740 (patch)
treea44e535e8b42a27ce10ea0219198f65e6d77a9c2
parent4127c455c8fd446ab952de37fabbd7d8ef20847a (diff)
downloadsamba-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.c13
-rw-r--r--source3/locking/locking.c36
-rw-r--r--source3/smbd/blocking.c12
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));