From 01753e8409497f8f82dd637a0ad8402da9464d5c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Jul 2014 20:40:49 -0700 Subject: [PATCH] s3: smbd: Locking - treat lock timeout the same as any other error. Allows the special case in process_blocking_lock_queue() that talks back to the client to be removed. Bug #10684 - SMB1 blocking locks can fail notification on unlock, causing client timeout. https://bugzilla.samba.org/show_bug.cgi?id=10684 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit cc9de6eb091159a84228b988c49261c46c301233) --- source3/smbd/blocking.c | 91 +++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 53 deletions(-) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 303585069d4..b6edb65c236 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -464,6 +464,7 @@ static bool process_lockingX(struct blocking_lock_record *blr) bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); uint8_t *data; NTSTATUS status = NT_STATUS_OK; + bool lock_timeout = lock_timed_out(blr); data = discard_const_p(uint8_t, blr->req->buf) + ((large_file_format ? 20 : 10)*num_ulocks); @@ -530,6 +531,14 @@ static bool process_lockingX(struct blocking_lock_record *blr) } /* + * Return an error to the client if we timed out. + */ + if (lock_timeout) { + blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); + return true; + } + + /* * Still can't get all the locks - keep waiting. */ @@ -550,6 +559,8 @@ static bool process_trans2(struct blocking_lock_record *blr) { char params[2]; NTSTATUS status; + bool lock_timeout = lock_timed_out(blr); + struct byte_range_lock *br_lck = do_lock( blr->fsp->conn->sconn->msg_ctx, blr->fsp, @@ -566,6 +577,15 @@ static bool process_trans2(struct blocking_lock_record *blr) if (!NT_STATUS_IS_OK(status)) { if (ERROR_WAS_LOCK_DENIED(status)) { + if (lock_timeout) { + /* + * Return an error if we timed out + * and return true to get dequeued. + */ + blocking_lock_reply_error(blr, + NT_STATUS_FILE_LOCK_CONFLICT); + return true; + } /* Still can't get the lock, just keep waiting. */ return False; } @@ -765,6 +785,7 @@ void process_blocking_lock_queue(struct smbd_server_connection *sconn) */ for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) { + struct byte_range_lock *br_lck = NULL; next = blr->next; @@ -784,65 +805,29 @@ void process_blocking_lock_queue(struct smbd_server_connection *sconn) SVAL(blr->req->inbuf,smb_flg), false); - 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->smblctx, - messaging_server_id(sconn->msg_ctx), - blr->offset, - blr->count, - blr->lock_flav, - blr); - TALLOC_FREE(br_lck); - } - - DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr); - TALLOC_FREE(blr); + if(!blocking_lock_record_process(blr)) { + DEBUG(10, ("still waiting for lock. BLR = %p\n", blr)); continue; } - /* - * We couldn't get the locks for this record on the list. - * If the time has expired, return a lock error. - */ - - if (lock_timed_out(blr)) { - struct byte_range_lock *br_lck = brl_get_locks( - talloc_tos(), blr->fsp); - - DEBUG(10, ("Lock timed out! BLR = %p\n", blr)); + br_lck = brl_get_locks(talloc_tos(), blr->fsp); - /* - * Lock expired - throw away all previously - * obtained locks and return lock error. - */ - - if (br_lck) { - DEBUG(5,("process_blocking_lock_queue: " - "pending lock for %s, file %s " - "timed out.\n", fsp_fnum_dbg(blr->fsp), - fsp_str_dbg(blr->fsp))); - - brl_lock_cancel(br_lck, - blr->smblctx, - messaging_server_id(sconn->msg_ctx), - blr->offset, - blr->count, - blr->lock_flav, - blr); - TALLOC_FREE(br_lck); - } + DEBUG(10, ("BLR_process returned true: cancelling and " + "removing lock. BLR = %p\n", blr)); - blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); - DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr); - TALLOC_FREE(blr); + if (br_lck) { + brl_lock_cancel(br_lck, + blr->smblctx, + messaging_server_id(sconn->msg_ctx), + blr->offset, + blr->count, + blr->lock_flav, + blr); + TALLOC_FREE(br_lck); } + + DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr); + TALLOC_FREE(blr); } recalc_brl_timeout(sconn); -- 2.11.4.GIT