diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/blocking.c | 107 | ||||
-rw-r--r-- | source3/smbd/reply.c | 18 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 3 |
3 files changed, 75 insertions, 53 deletions
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 33aa748cdc..42849931f3 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -24,26 +24,6 @@ #define DBGC_CLASS DBGC_LOCKING /**************************************************************************** - This is the structure to queue to implement blocking locks. - notify. It consists of the requesting SMB and the expiry time. -*****************************************************************************/ - -struct blocking_lock_record { - struct blocking_lock_record *next; - struct blocking_lock_record *prev; - files_struct *fsp; - struct timeval expire_time; - int lock_num; - uint64_t offset; - uint64_t count; - uint32_t lock_pid; - uint32_t blocking_pid; /* PID that blocks us. */ - enum brl_flavour lock_flav; - enum brl_type lock_type; - struct smb_request *req; -}; - -/**************************************************************************** Determine if this is a secondary element of a chained SMB. **************************************************************************/ @@ -52,7 +32,6 @@ static void received_unlock_msg(struct messaging_context *msg, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data); -static void process_blocking_lock_queue(void); static void brl_timeout_fn(struct event_context *event_ctx, struct timed_event *te, @@ -82,14 +61,14 @@ static bool recalc_brl_timeout(void) next_timeout = timeval_zero(); - for (brl = blocking_lock_queue; brl; brl = brl->next) { - if (timeval_is_zero(&brl->expire_time)) { + for (blr = blocking_lock_queue; blr; blr = blr->next) { + if (timeval_is_zero(&blr->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) { + if (blr->blocking_pid == 0xFFFFFFFF) { struct timeval psx_to = timeval_current_ofs(10, 0); next_timeout = timeval_min(&next_timeout, &psx_to); } @@ -98,18 +77,28 @@ static bool recalc_brl_timeout(void) } if (timeval_is_zero(&next_timeout)) { - next_timeout = brl->expire_time; + next_timeout = blr->expire_time; } else { next_timeout = timeval_min(&next_timeout, - &brl->expire_time); + &blr->expire_time); } } if (timeval_is_zero(&next_timeout)) { + DEBUG(10, ("Next timeout = Infinite.\n")); return True; } + if (DEBUGLVL(10)) { + struct timeval cur, from_now; + + cur = timeval_current(); + from_now = timeval_until(&cur, &next_timeout); + DEBUG(10, ("Next timeout = %d.%d seconds from now.\n", + (int)from_now.tv_sec, (int)from_now.tv_usec)); + } + if (!(brl_timeout = event_add_timed(smbd_event_context(), NULL, next_timeout, brl_timeout_fn, NULL))) { @@ -173,9 +162,13 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, blr->lock_type = lock_type; blr->offset = offset; blr->count = count; + + /* Specific brl_lock() implementations can fill this in. */ + blr->blr_private = NULL; /* Add a pending lock record for this. */ - status = brl_lock(smbd_messaging_context(), br_lck, + status = brl_lock(smbd_messaging_context(), + br_lck, lock_pid, procid_self(), offset, @@ -183,11 +176,11 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK, blr->lock_flav, lock_timeout ? True : False, /* blocking_lock. */ - NULL); + NULL, + blr); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); - DLIST_REMOVE(blocking_lock_queue, blr); TALLOC_FREE(blr); return False; } @@ -332,6 +325,8 @@ static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS stat static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status) { + DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr)); + switch(blr->req->cmd) { case SMBlockingX: reply_lockingX_error(blr, status); @@ -409,7 +404,8 @@ static bool process_lockingX(struct blocking_lock_record *blr) WINDOWS_LOCK, True, &status, - &blr->blocking_pid); + &blr->blocking_pid, + blr); TALLOC_FREE(br_lck); @@ -470,7 +466,8 @@ static bool process_trans2(struct blocking_lock_record *blr) blr->lock_flav, True, &status, - &blr->blocking_pid); + &blr->blocking_pid, + blr); TALLOC_FREE(br_lck); if (!NT_STATUS_IS_OK(status)) { @@ -521,7 +518,7 @@ static bool blocking_lock_record_process(struct blocking_lock_record *blr) void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck) { - struct blocking_lock_record *blr, *next = NULL; + struct blocking_lock_record *blr, *blr_cancelled, *next = NULL; for(blr = blocking_lock_queue; blr; blr = next) { unsigned char locktype = 0; @@ -539,14 +536,7 @@ void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lo "request type %d for file %s fnum = %d\n", blr->req->cmd, fsp->fsp_name, fsp->fnum)); - brl_lock_cancel(br_lck, - blr->lock_pid, - procid_self(), - blr->offset, - blr->count, - blr->lock_flav); - - blocking_lock_cancel(fsp, + blr_cancelled = blocking_lock_cancel(fsp, blr->lock_pid, blr->offset, blr->count, @@ -554,6 +544,16 @@ void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lo locktype, NT_STATUS_RANGE_NOT_LOCKED); + SMB_ASSERT(blr_cancelled == blr); + + brl_lock_cancel(br_lck, + blr->lock_pid, + procid_self(), + blr->offset, + blr->count, + blr->lock_flav, + blr); + /* We're closing the file fsp here, so ensure * we don't have a dangling pointer. */ blr->fsp = NULL; @@ -592,7 +592,8 @@ void remove_pending_lock_requests_by_mid(int mid) procid_self(), blr->offset, blr->count, - blr->lock_flav); + blr->lock_flav, + blr); TALLOC_FREE(br_lck); } @@ -637,7 +638,7 @@ static void received_unlock_msg(struct messaging_context *msg, Process the blocking lock queue. Note that this is only called as root. *****************************************************************************/ -static void process_blocking_lock_queue(void) +void process_blocking_lock_queue(void) { struct timeval tv_curr = timeval_current(); struct blocking_lock_record *blr, *next = NULL; @@ -657,17 +658,23 @@ static void process_blocking_lock_queue(void) * and False if we still need to wait. */ + DEBUG(10, ("Processing BLR = %p\n", blr)); + if(blocking_lock_record_process(blr)) { struct byte_range_lock *br_lck = brl_get_locks( talloc_tos(), blr->fsp); + DEBUG(10, ("BLR_process returned true: cancelling and " + "removing lock. BLR = %p\n", blr)); + if (br_lck) { brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), blr->offset, blr->count, - blr->lock_flav); + blr->lock_flav, + blr); TALLOC_FREE(br_lck); } @@ -686,6 +693,8 @@ static void process_blocking_lock_queue(void) struct byte_range_lock *br_lck = brl_get_locks( talloc_tos(), blr->fsp); + DEBUG(10, ("Lock timed out! BLR = %p\n", blr)); + /* * Lock expired - throw away all previously * obtained locks and return lock error. @@ -702,7 +711,8 @@ static void process_blocking_lock_queue(void) procid_self(), blr->offset, blr->count, - blr->lock_flav); + blr->lock_flav, + blr); TALLOC_FREE(br_lck); } @@ -757,9 +767,10 @@ static void process_blocking_lock_cancel_message(struct messaging_context *ctx, /**************************************************************************** Send ourselves a blocking lock cancelled message. Handled asynchronously above. + Returns the blocking_lock_record that is being cancelled. *****************************************************************************/ -bool blocking_lock_cancel(files_struct *fsp, +struct blocking_lock_record *blocking_lock_cancel(files_struct *fsp, uint32 lock_pid, uint64_t offset, uint64_t count, @@ -790,14 +801,14 @@ bool blocking_lock_cancel(files_struct *fsp, } if (!blr) { - return False; + return NULL; } /* Check the flags are right. */ if (blr->req->cmd == SMBlockingX && (locktype & LOCKING_ANDX_LARGE_FILES) != (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) { - return False; + return NULL; } /* Move to cancelled queue. */ @@ -812,5 +823,5 @@ bool blocking_lock_cancel(files_struct *fsp, MSG_SMB_BLOCKING_LOCK_CANCEL, (uint8 *)&msg, sizeof(msg)); - return True; + return blr; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 256160c402..1ed5e7229e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3040,6 +3040,7 @@ void reply_lockread(struct smb_request *req) WINDOWS_LOCK, False, /* Non-blocking lock. */ &status, + NULL, NULL); TALLOC_FREE(br_lck); @@ -4514,6 +4515,7 @@ void reply_lock(struct smb_request *req) WINDOWS_LOCK, False, /* Non-blocking lock. */ &status, + NULL, NULL); TALLOC_FREE(br_lck); @@ -6904,6 +6906,9 @@ void reply_lockingX(struct smb_request *req) offset, WINDOWS_LOCK); + DEBUG(10, ("reply_lockingX: unlock returned %s\n", + nt_errstr(status))); + if (NT_STATUS_V(status)) { END_PROFILE(SMBlockingX); reply_nterror(req, status); @@ -6945,19 +6950,22 @@ void reply_lockingX(struct smb_request *req) fsp->fsp_name, (int)lock_timeout )); if (locktype & LOCKING_ANDX_CANCEL_LOCK) { + struct blocking_lock_record *blr; + if (lp_blocking_locks(SNUM(conn))) { /* Schedule a message to ourselves to remove the blocking lock record and return the right error. */ - if (!blocking_lock_cancel(fsp, + blr = blocking_lock_cancel(fsp, lock_pid, offset, count, WINDOWS_LOCK, locktype, - NT_STATUS_FILE_LOCK_CONFLICT)) { + NT_STATUS_FILE_LOCK_CONFLICT); + if (blr == NULL) { END_PROFILE(SMBlockingX); reply_nterror( req, @@ -6972,7 +6980,8 @@ void reply_lockingX(struct smb_request *req) lock_pid, count, offset, - WINDOWS_LOCK); + WINDOWS_LOCK, + blr); } else { bool blocking_lock = lock_timeout ? True : False; bool defer_lock = False; @@ -6988,7 +6997,8 @@ void reply_lockingX(struct smb_request *req) WINDOWS_LOCK, blocking_lock, &status, - &block_smbpid); + &block_smbpid, + NULL); if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* Windows internal resolution for blocking locks seems diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cea066e97f..759e520866 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5628,7 +5628,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, POSIX_LOCK, blocking_lock, &status, - &block_smbpid); + &block_smbpid, + NULL); if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* |