mirror of
https://github.com/samba-team/samba.git
synced 2025-01-27 14:04:05 +03:00
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 commit is contained in:
parent
60979d59b4
commit
eb861e9d0f
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user