diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/locking/brlock.c | 25 | ||||
-rw-r--r-- | source3/locking/locking.c | 6 | ||||
-rw-r--r-- | source3/smbd/blocking.c | 25 | ||||
-rw-r--r-- | source3/smbd/reply.c | 13 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 8 |
5 files changed, 62 insertions, 15 deletions
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index d48c746161..f3e4042d8a 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -313,7 +313,7 @@ static int lock_compare(const struct lock_struct *lck1, ****************************************************************************/ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, - const struct lock_struct *plock, BOOL blocking_lock) + struct lock_struct *plock, BOOL blocking_lock) { unsigned int i; files_struct *fsp = br_lck->fsp; @@ -322,6 +322,8 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, for (i=0; i < br_lck->num_locks; i++) { /* Do any Windows or POSIX locks conflict ? */ if (brl_conflict(&locks[i], plock)) { + /* Remember who blocked us. */ + plock->context.smbpid = locks[i].context.smbpid; return brl_lock_failed(fsp,plock,blocking_lock); } #if ZERO_ZERO @@ -346,6 +348,10 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, locks, br_lck->num_locks, &errno_ret)) { + + /* We don't know who blocked us. */ + plock->context.smbpid = 0xFFFFFFFF; + if (errno_ret == EACCES || errno_ret == EAGAIN) { return NT_STATUS_FILE_LOCK_CONFLICT; } else { @@ -586,7 +592,7 @@ OR static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx, struct byte_range_lock *br_lck, - const struct lock_struct *plock) + struct lock_struct *plock) { unsigned int i, count; struct lock_struct *locks = br_lck->lock_data; @@ -630,6 +636,8 @@ static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx, if (brl_conflict(curr_lock, plock)) { /* No games with error messages. */ SAFE_FREE(tp); + /* Remember who blocked us. */ + plock->context.smbpid = curr_lock->context.smbpid; return NT_STATUS_FILE_LOCK_CONFLICT; } /* Just copy the Windows lock into the new array. */ @@ -641,6 +649,8 @@ static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx, /* Can't block ourselves with POSIX locks. */ /* No games with error messages. */ SAFE_FREE(tp); + /* Remember who blocked us. */ + plock->context.smbpid = curr_lock->context.smbpid; return NT_STATUS_FILE_LOCK_CONFLICT; } @@ -670,6 +680,10 @@ static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx, plock->size, plock->lock_type, &errno_ret)) { + + /* We don't know who blocked us. */ + plock->context.smbpid = 0xFFFFFFFF; + if (errno_ret == EACCES || errno_ret == EAGAIN) { SAFE_FREE(tp); return NT_STATUS_FILE_LOCK_CONFLICT; @@ -730,7 +744,8 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx, br_off size, enum brl_type lock_type, enum brl_flavour lock_flav, - BOOL blocking_lock) + BOOL blocking_lock, + uint32 *psmbpid) { NTSTATUS ret; struct lock_struct lock; @@ -761,6 +776,10 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx, qsort(br_lck->lock_data, (size_t)br_lck->num_locks, sizeof(lock), lock_compare); #endif + /* If we're returning an error, return who blocked us. */ + if (!NT_STATUS_IS_OK(ret) && psmbpid) { + *psmbpid = lock.context.smbpid; + } return ret; } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 28a7fab97d..56ff3b9790 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -188,7 +188,8 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx, enum brl_type lock_type, enum brl_flavour lock_flav, BOOL blocking_lock, - NTSTATUS *perr) + NTSTATUS *perr, + uint32 *plock_pid) { struct byte_range_lock *br_lck = NULL; @@ -222,7 +223,8 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx, count, lock_type, lock_flav, - blocking_lock); + blocking_lock, + plock_pid); /* blocking ie. pending, locks also count here, * as this is an efficiency counter to avoid checking diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ae7b861f2b..43b2633b9a 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -39,6 +39,7 @@ typedef struct _blocking_lock_record { SMB_BIG_UINT offset; SMB_BIG_UINT count; uint32 lock_pid; + uint32 blocking_pid; /* PID that blocks us. */ enum brl_flavour lock_flav; enum brl_type lock_type; char *inbuf; @@ -108,6 +109,16 @@ static BOOL recalc_brl_timeout(void) for (brl = blocking_lock_queue; brl; brl = brl->next) { if (timeval_is_zero(&brl->expire_time)) { + /* + * If we're blocked on pid 0xFFFFFFFF this is + * a POSIX lock, so calculate a timeout of + * 10 seconds into the future. + */ + if (brl->blocking_pid == 0xFFFFFFFF) { + struct timeval psx_to = timeval_current_ofs(10, 0); + next_timeout = timeval_min(&next_timeout, &psx_to); + } + continue; } @@ -146,7 +157,9 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, uint32 lock_pid, enum brl_type lock_type, enum brl_flavour lock_flav, - SMB_BIG_UINT offset, SMB_BIG_UINT count) + SMB_BIG_UINT offset, + SMB_BIG_UINT count, + uint32 blocking_pid) { static BOOL set_lock_msg; blocking_lock_record *blr; @@ -187,6 +200,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, } blr->lock_num = lock_num; blr->lock_pid = lock_pid; + blr->blocking_pid = blocking_pid; blr->lock_flav = lock_flav; blr->lock_type = lock_type; blr->offset = offset; @@ -202,7 +216,8 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, count, lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK, blr->lock_flav, - lock_timeout ? True : False); /* blocking_lock. */ + lock_timeout ? True : False, /* blocking_lock. */ + NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); @@ -445,7 +460,8 @@ static BOOL process_lockingX(blocking_lock_record *blr) READ_LOCK : WRITE_LOCK), WINDOWS_LOCK, True, - &status); + &status, + &blr->blocking_pid); TALLOC_FREE(br_lck); @@ -506,7 +522,8 @@ static BOOL process_trans2(blocking_lock_record *blr) blr->lock_type, blr->lock_flav, True, - &status); + &status, + &blr->blocking_pid); TALLOC_FREE(br_lck); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c71c7b8bea..ec110e7b21 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2426,7 +2426,8 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length WRITE_LOCK, WINDOWS_LOCK, False, /* Non-blocking lock. */ - &status); + &status, + NULL); TALLOC_FREE(br_lck); if (NT_STATUS_V(status)) { @@ -3474,7 +3475,8 @@ int reply_lock(connection_struct *conn, WRITE_LOCK, WINDOWS_LOCK, False, /* Non-blocking lock. */ - &status); + &status, + NULL); TALLOC_FREE(br_lck); @@ -5575,6 +5577,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, BOOL blocking_lock = lock_timeout ? True : False; BOOL defer_lock = False; struct byte_range_lock *br_lck; + uint32 block_smbpid; br_lck = do_lock(smbd_messaging_context(), fsp, @@ -5584,7 +5587,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, lock_type, WINDOWS_LOCK, blocking_lock, - &status); + &status, + &block_smbpid); if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* Windows internal resolution for blocking locks seems @@ -5621,7 +5625,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, lock_type, WINDOWS_LOCK, offset, - count)) { + count, + block_smbpid)) { TALLOC_FREE(br_lck); END_PROFILE(SMBlockingX); return -1; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0730041899..63fd414e16 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4815,6 +4815,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, offset, POSIX_LOCK); } else { + uint32 block_smbpid; + struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(), fsp, lock_pid, @@ -4823,7 +4825,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, lock_type, POSIX_LOCK, blocking_lock, - &status); + &status, + &block_smbpid); if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* @@ -4840,7 +4843,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, lock_type, POSIX_LOCK, offset, - count)) { + count, + block_smbpid)) { TALLOC_FREE(br_lck); return status; } |