Revert "smbd: implement smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create...
[samba.git] / source3 / smbd / blocking.c
index 03f63689ed069c037bacab09f2ceb629ea3fe068..c281aae619de4416d5f72d2c3659a4dd84b7dcc2 100644 (file)
 */
 
 #include "includes.h"
+#include "smbd/smbd.h"
 #include "smbd/globals.h"
-#include "librpc/gen_ndr/messaging.h"
+#include "messages.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_LOCKING
 
-/****************************************************************************
- Determine if this is a secondary element of a chained SMB.
-  **************************************************************************/
-
 static void received_unlock_msg(struct messaging_context *msg,
                                void *private_data,
                                uint32_t msg_type,
                                struct server_id server_id,
                                DATA_BLOB *data);
 
-void brl_timeout_fn(struct event_context *event_ctx,
-                          struct timed_event *te,
+void brl_timeout_fn(struct tevent_context *event_ctx,
+                          struct tevent_timer *te,
                           struct timeval now,
                           void *private_data)
 {
@@ -110,7 +107,7 @@ static bool recalc_brl_timeout(struct smbd_server_connection *sconn)
                return True;
        }
 
-       /* 
+       /*
         to account for unclean shutdowns by clients we need a
         maximum timeout that we use for checking pending locks. If
         we have any pending locks at all, then check if the pending
@@ -138,9 +135,13 @@ static bool recalc_brl_timeout(struct smbd_server_connection *sconn)
                    (int)from_now.tv_sec, (int)from_now.tv_usec));
        }
 
-       sconn->smb1.locks.brl_timeout = event_add_timed(smbd_event_context(),
-                                                       NULL, next_timeout,
-                                                       brl_timeout_fn, sconn);
+       /*
+        * brl_timeout_fn() calls change_to_root_user()
+        * so we can use sconn->root_ev_ctx.
+        */
+       sconn->smb1.locks.brl_timeout = tevent_add_timer(sconn->root_ev_ctx,
+                                                        NULL, next_timeout,
+                                                        brl_timeout_fn, sconn);
        if (sconn->smb1.locks.brl_timeout == NULL) {
                return False;
        }
@@ -207,8 +208,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
                blr->expire_time.tv_sec = 0;
                blr->expire_time.tv_usec = 0; /* Never expire. */
        } else {
-               blr->expire_time = timeval_current_ofs(lock_timeout/1000,
-                                       (lock_timeout % 1000) * 1000);
+               blr->expire_time = timeval_current_ofs_msec(lock_timeout);
        }
        blr->lock_num = lock_num;
        blr->smblctx = smblctx;
@@ -217,7 +217,7 @@ 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;
 
@@ -225,14 +225,13 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
        status = brl_lock(req->sconn->msg_ctx,
                        br_lck,
                        smblctx,
-                       procid_self(),
+                       messaging_server_id(req->sconn->msg_ctx),
                        offset,
                        count,
                        lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
                        blr->lock_flav,
                        True,
-                       NULL,
-                       blr);
+                       NULL);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
@@ -243,21 +242,21 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
        SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd);
        blr->req = talloc_move(blr, &req);
 
-       DLIST_ADD_END(sconn->smb1.locks.blocking_lock_queue, blr, struct blocking_lock_record *);
+       DLIST_ADD_END(sconn->smb1.locks.blocking_lock_queue, blr);
        recalc_brl_timeout(sconn);
 
        /* Ensure we'll receive messages when this is unlocked. */
        if (!sconn->smb1.locks.blocking_lock_unlock_state) {
-               messaging_register(sconn->msg_ctx, NULL,
+               messaging_register(sconn->msg_ctx, sconn,
                                   MSG_SMB_UNLOCK, received_unlock_msg);
                sconn->smb1.locks.blocking_lock_unlock_state = true;
        }
 
        DEBUG(3,("push_blocking_lock_request: lock request blocked with "
-               "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n",
+               "expiry time (%u sec. %u usec) (+%d msec) for %s, name = %s\n",
                (unsigned int)blr->expire_time.tv_sec,
                (unsigned int)blr->expire_time.tv_usec, lock_timeout,
-               blr->fsp->fnum, fsp_str_dbg(blr->fsp)));
+               fsp_fnum_dbg(blr->fsp), fsp_str_dbg(blr->fsp)));
 
        return True;
 }
@@ -268,7 +267,11 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
 
 static void reply_lockingX_success(struct blocking_lock_record *blr)
 {
-       reply_outbuf(blr->req, 2, 0);
+       struct smb_request *req = blr->req;
+
+       reply_outbuf(req, 2, 0);
+       SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+       SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
 
        /*
         * As this message is a lockingX call we must handle
@@ -278,8 +281,15 @@ static void reply_lockingX_success(struct blocking_lock_record *blr)
         * that here and must set up the chain info manually.
         */
 
-       chain_reply(blr->req);
-       TALLOC_FREE(blr->req->outbuf);
+       if (!srv_send_smb(req->xconn,
+                       (char *)req->outbuf,
+                       true, req->seqnum+1,
+                       IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
+                       &req->pcd)) {
+               exit_server_cleanly("construct_reply: srv_send_smb failed.");
+       }
+
+       TALLOC_FREE(req->outbuf);
 }
 
 /****************************************************************************
@@ -301,7 +311,8 @@ static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTAT
                if (fsp) {
                        fsp->last_lock_failure.context.smblctx = blr->smblctx;
                        fsp->last_lock_failure.context.tid = fsp->conn->cnum;
-                       fsp->last_lock_failure.context.pid = procid_self();
+                       fsp->last_lock_failure.context.pid =
+                               messaging_server_id(fsp->conn->sconn->msg_ctx);
                        fsp->last_lock_failure.start = blr->offset;
                        fsp->last_lock_failure.size = blr->count;
                        fsp->last_lock_failure.fnum = fsp->fnum;
@@ -311,7 +322,7 @@ static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTAT
        }
 
        reply_nterror(blr->req, status);
-       if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf,
+       if (!srv_send_smb(blr->req->xconn, (char *)blr->req->outbuf,
                          true, blr->req->seqnum+1,
                          blr->req->encrypted, NULL)) {
                exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
@@ -320,14 +331,14 @@ static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTAT
 }
 
 /****************************************************************************
- Return a lock fail error for a lockingX call. Undo all the locks we have 
+ Return a lock fail error for a lockingX call. Undo all the locks we have
  obtained first.
 *****************************************************************************/
 
-static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS status)
+static void undo_locks_obtained(struct blocking_lock_record *blr)
 {
        files_struct *fsp = blr->fsp;
-       uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
+       uint16_t num_ulocks = SVAL(blr->req->vwv+6, 0);
        uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
        uint64_t smblctx;
        unsigned char locktype = CVAL(blr->req->vwv+3, 0);
@@ -335,10 +346,10 @@ static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS stat
        uint8_t *data;
        int i;
 
-       data = (uint8_t *)blr->req->buf
+       data = discard_const_p(uint8_t, blr->req->buf)
                + ((large_file_format ? 20 : 10)*num_ulocks);
 
-       /* 
+       /*
         * Data now points at the beginning of the list
         * of smb_lkrng structs.
         */
@@ -350,11 +361,10 @@ static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS stat
         */
 
        for(i = blr->lock_num - 1; i >= 0; i--) {
-               bool err;
 
                smblctx = get_lock_pid( data, i, large_file_format);
                count = get_lock_count( data, i, large_file_format);
-               offset = get_lock_offset( data, i, large_file_format, &err);
+               offset = get_lock_offset( data, i, large_file_format);
 
                /*
                 * We know err cannot be set as if it was the lock
@@ -368,8 +378,6 @@ static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS stat
                        offset,
                        WINDOWS_LOCK);
        }
-
-       generic_blocking_lock_error(blr, status);
 }
 
 /****************************************************************************
@@ -382,7 +390,16 @@ static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS
 
        switch(blr->req->cmd) {
        case SMBlockingX:
-               reply_lockingX_error(blr, status);
+               /*
+                * This code can be called during the rundown of a
+                * file after it was already closed. In that case,
+                * blr->fsp==NULL and we do not need to undo any
+                * locks, they are already gone.
+                */
+               if (blr->fsp != NULL) {
+                       undo_locks_obtained(blr);
+               }
+               generic_blocking_lock_error(blr, status);
                break;
        case SMBtrans2:
        case SMBtranss2:
@@ -394,7 +411,7 @@ static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS
                 */
                SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
 
-               if (!srv_send_smb(smbd_server_fd(),
+               if (!srv_send_smb(blr->req->xconn,
                                  (char *)blr->req->outbuf,
                                  true, blr->req->seqnum+1,
                                  IS_CONN_ENCRYPTED(blr->fsp->conn),
@@ -410,6 +427,25 @@ static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS
        }
 }
 
+/****************************************************************************
+ Utility function that returns true if a lock timed out.
+*****************************************************************************/
+
+static bool lock_timed_out(const struct blocking_lock_record *blr)
+{
+       struct timeval tv_curr;
+
+       if (timeval_is_zero(&blr->expire_time)) {
+               return false; /* Never times out. */
+       }
+
+       tv_curr = timeval_current();
+       if (timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
+               return true;
+       }
+       return false;
+}
+
 /****************************************************************************
  Attempt to finish off getting all pending blocking locks for a lockingX call.
  Returns True if we want to be removed from the list.
@@ -419,29 +455,32 @@ static bool process_lockingX(struct blocking_lock_record *blr)
 {
        unsigned char locktype = CVAL(blr->req->vwv+3, 0);
        files_struct *fsp = blr->fsp;
-       uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
-       uint16 num_locks = SVAL(blr->req->vwv+7, 0);
-       uint64_t count = (uint64_t)0, offset = (uint64_t)0;
-       uint64_t smblctx;
+       uint16_t num_ulocks = SVAL(blr->req->vwv+6, 0);
+       uint16_t num_locks = SVAL(blr->req->vwv+7, 0);
        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 = (uint8_t *)blr->req->buf
+       data = discard_const_p(uint8_t, blr->req->buf)
                + ((large_file_format ? 20 : 10)*num_ulocks);
 
-       /* 
+       /*
         * Data now points at the beginning of the list
         * of smb_lkrng structs.
         */
 
        for(; blr->lock_num < num_locks; blr->lock_num++) {
                struct byte_range_lock *br_lck = NULL;
-               bool err;
 
-               smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
-               count = get_lock_count( data, blr->lock_num, large_file_format);
-               offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
+               /*
+                * Ensure the blr record gets updated with
+                * any lock we might end up blocked on.
+                */
+
+               blr->smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
+               blr->count = get_lock_count( data, blr->lock_num, large_file_format);
+               blr->offset = get_lock_offset( data, blr->lock_num, large_file_format);
 
                /*
                 * We know err cannot be set as if it was the lock
@@ -450,16 +489,42 @@ static bool process_lockingX(struct blocking_lock_record *blr)
                errno = 0;
                br_lck = do_lock(fsp->conn->sconn->msg_ctx,
                                fsp,
-                               smblctx,
-                               count,
-                               offset,
+                               blr->smblctx,
+                               blr->count,
+                               blr->offset,
                                ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
                                        READ_LOCK : WRITE_LOCK),
                                WINDOWS_LOCK,
                                True,
                                &status,
-                               &blr->blocking_smblctx,
-                               blr);
+                               &blr->blocking_smblctx);
+
+               if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
+                       /*
+                        * If we didn't timeout, but still need to wait,
+                        * re-add the pending lock entry whilst holding
+                        * the brlock db lock.
+                        */
+                       NTSTATUS status1 =
+                               brl_lock(blr->fsp->conn->sconn->msg_ctx,
+                                       br_lck,
+                                       blr->smblctx,
+                                       messaging_server_id(
+                                               blr->fsp->conn->sconn->msg_ctx),
+                                       blr->offset,
+                                       blr->count,
+                                       blr->lock_type == READ_LOCK ?
+                                               PENDING_READ_LOCK :
+                                               PENDING_WRITE_LOCK,
+                                               blr->lock_flav,
+                                       true, /* Blocking lock. */
+                                       NULL);
+
+                       if (!NT_STATUS_IS_OK(status1)) {
+                               DEBUG(0,("failed to add PENDING_LOCK "
+                                       "record.\n"));
+                       }
+               }
 
                TALLOC_FREE(br_lck);
 
@@ -473,16 +538,15 @@ static bool process_lockingX(struct blocking_lock_record *blr)
                 * Success - we got all the locks.
                 */
 
-               DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d "
-                        "num_locks=%d\n", fsp_str_dbg(fsp), fsp->fnum,
+               DEBUG(3,("process_lockingX file = %s, %s, type=%d "
+                        "num_locks=%d\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
                         (unsigned int)locktype, num_locks));
 
                reply_lockingX_success(blr);
                return True;
        }
 
-       if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
-           !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
+       if (!ERROR_WAS_LOCK_DENIED(status)) {
                /*
                 * We have other than a "can't get lock"
                 * error. Free any locks we had and return an error.
@@ -492,13 +556,22 @@ static bool process_lockingX(struct blocking_lock_record *blr)
                return True;
        }
 
+       /*
+        * 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.
         */
 
-       DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
-Waiting....\n", 
-                blr->lock_num, num_locks, fsp_str_dbg(fsp), fsp->fnum));
+       DEBUG(10, ("process_lockingX: only got %d locks of %d needed for "
+                  "file %s, %s. Waiting....\n",
+                  blr->lock_num, num_locks, fsp_str_dbg(fsp),
+                  fsp_fnum_dbg(fsp)));
 
        return False;
 }
@@ -512,7 +585,10 @@ static bool process_trans2(struct blocking_lock_record *blr)
 {
        char params[2];
        NTSTATUS status;
-       struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
+       bool lock_timeout = lock_timed_out(blr);
+
+       struct byte_range_lock *br_lck = do_lock(
+                                               blr->fsp->conn->sconn->msg_ctx,
                                                blr->fsp,
                                                blr->smblctx,
                                                blr->count,
@@ -521,15 +597,49 @@ static bool process_trans2(struct blocking_lock_record *blr)
                                                blr->lock_flav,
                                                True,
                                                &status,
-                                               &blr->blocking_smblctx,
-                                               blr);
+                                               &blr->blocking_smblctx);
+       if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
+               /*
+                * If we didn't timeout, but still need to wait,
+                * re-add the pending lock entry whilst holding
+                * the brlock db lock.
+                */
+               NTSTATUS status1 =
+                       brl_lock(blr->fsp->conn->sconn->msg_ctx,
+                               br_lck,
+                               blr->smblctx,
+                               messaging_server_id(
+                                       blr->fsp->conn->sconn->msg_ctx),
+                               blr->offset,
+                               blr->count,
+                               blr->lock_type == READ_LOCK ?
+                                       PENDING_READ_LOCK :
+                                       PENDING_WRITE_LOCK,
+                               blr->lock_flav,
+                               true, /* Blocking lock. */
+                               NULL);
+
+               if (!NT_STATUS_IS_OK(status1)) {
+                       DEBUG(0,("failed to add PENDING_LOCK record.\n"));
+               }
+       }
+
        TALLOC_FREE(br_lck);
 
        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;
-               }       
+               }
                /*
                 * We have other than a "can't get lock"
                 * error. Send an error and return True so we get dequeued.
@@ -542,7 +652,7 @@ static bool process_trans2(struct blocking_lock_record *blr)
 
        SSVAL(params,0,0);
        /* Fake up max_data_bytes here - we know it fits. */
-       send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff);
+       send_trans2_replies(blr->fsp->conn, blr->req, NT_STATUS_OK, params, 2, NULL, 0, 0xffff);
        return True;
 }
 
@@ -572,9 +682,9 @@ static bool blocking_lock_record_process(struct blocking_lock_record *blr)
  Called when a file is closed.
 *****************************************************************************/
 
-void cancel_pending_lock_requests_by_fid(files_struct *fsp,
-                       struct byte_range_lock *br_lck,
-                       enum file_close_type close_type)
+void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp,
+                                             struct byte_range_lock *br_lck,
+                                             enum file_close_type close_type)
 {
        struct smbd_server_connection *sconn = fsp->conn->sconn;
        struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
@@ -599,8 +709,8 @@ void cancel_pending_lock_requests_by_fid(files_struct *fsp,
                }
 
                DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
-                          "request type %d for file %s fnum = %d\n",
-                          blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum));
+                          "request type %d for file %s, %s\n",
+                          blr->req->cmd, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
 
                blr_cancelled = blocking_lock_cancel_smb1(fsp,
                                     blr->smblctx,
@@ -614,11 +724,10 @@ void cancel_pending_lock_requests_by_fid(files_struct *fsp,
 
                brl_lock_cancel(br_lck,
                                blr->smblctx,
-                               procid_self(),
+                               messaging_server_id(sconn->msg_ctx),
                                blr->offset,
                                blr->count,
-                               blr->lock_flav,
-                               blr);
+                               blr->lock_flav);
 
                /* We're closing the file fsp here, so ensure
                 * we don't have a dangling pointer. */
@@ -651,17 +760,16 @@ void remove_pending_lock_requests_by_mid_smb1(
 
                if (br_lck) {
                        DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
-                                  "removing request type %d for file %s fnum "
-                                  "= %d\n", blr->req->cmd, fsp_str_dbg(fsp),
-                                  fsp->fnum ));
+                                  "removing request type %d for file %s, %s\n",
+                                  blr->req->cmd, fsp_str_dbg(fsp),
+                                  fsp_fnum_dbg(fsp)));
 
                        brl_lock_cancel(br_lck,
                                        blr->smblctx,
-                                       procid_self(),
+                                       messaging_server_id(sconn->msg_ctx),
                                        blr->offset,
                                        blr->count,
-                                       blr->lock_flav,
-                                       blr);
+                                       blr->lock_flav);
                        TALLOC_FREE(br_lck);
                }
 
@@ -700,8 +808,12 @@ static void received_unlock_msg(struct messaging_context *msg,
                                struct server_id server_id,
                                DATA_BLOB *data)
 {
+       struct smbd_server_connection *sconn =
+               talloc_get_type_abort(private_data,
+               struct smbd_server_connection);
+
        DEBUG(10,("received_unlock_msg\n"));
-       process_blocking_lock_queue(smbd_server_conn);
+       process_blocking_lock_queue(sconn);
 }
 
 /****************************************************************************
@@ -710,11 +822,10 @@ static void received_unlock_msg(struct messaging_context *msg,
 
 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
 {
-       struct timeval tv_curr = timeval_current();
        struct blocking_lock_record *blr, *next = NULL;
 
        if (sconn->using_smb2) {
-               process_blocking_lock_queue_smb2(sconn, tv_curr);
+               process_blocking_lock_queue_smb2(sconn, timeval_current());
                return;
        }
 
@@ -723,6 +834,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;
 
@@ -734,73 +846,38 @@ void process_blocking_lock_queue(struct smbd_server_connection *sconn)
 
                DEBUG(10, ("Processing BLR = %p\n", blr));
 
-               /* We use set_current_service so connections with
-                * pending locks are not marked as idle.
+               /*
+                * Connections with pending locks are not marked as idle.
                 */
-
-               set_current_service(blr->fsp->conn,
-                               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,
-                                       procid_self(),
-                                       blr->offset,
-                                       blr->count,
-                                       blr->lock_flav,
-                                       blr);
-                               TALLOC_FREE(br_lck);
-                       }
-
-                       DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
-                       TALLOC_FREE(blr);
-                       continue;
-               }
+               blr->fsp->conn->lastused_count++;
 
                /*
-                * We couldn't get the locks for this record on the list.
-                * If the time has expired, return a lock error.
+                * Remove the pending lock we're waiting on.
+                * If we need to keep waiting blocking_lock_record_process()
+                * will re-add it.
                 */
 
-               if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
-                       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.
-                        */
+               br_lck = brl_get_locks(talloc_tos(), blr->fsp);
+               if (br_lck) {
+                       brl_lock_cancel(br_lck,
+                               blr->smblctx,
+                               messaging_server_id(sconn->msg_ctx),
+                               blr->offset,
+                               blr->count,
+                               blr->lock_flav);
+               }
+               TALLOC_FREE(br_lck);
 
-                       if (br_lck) {
-                               DEBUG(5,("process_blocking_lock_queue: "
-                                        "pending lock fnum = %d for file %s "
-                                        "timed out.\n", blr->fsp->fnum,
-                                        fsp_str_dbg(blr->fsp)));
+               if(!blocking_lock_record_process(blr)) {
+                       DEBUG(10, ("still waiting for lock. BLR = %p\n", blr));
+                       continue;
+               }
 
-                               brl_lock_cancel(br_lck,
-                                       blr->smblctx,
-                                       procid_self(),
-                                       blr->offset,
-                                       blr->count,
-                                       blr->lock_flav,
-                                       blr);
-                               TALLOC_FREE(br_lck);
-                       }
+               DEBUG(10, ("BLR_process returned true: removing 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);
-               }
+               DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
+               TALLOC_FREE(blr);
        }
 
        recalc_brl_timeout(sconn);
@@ -818,10 +895,12 @@ static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
                                                 struct server_id server_id,
                                                 DATA_BLOB *data)
 {
-       struct smbd_server_connection *sconn = smbd_server_conn;
        NTSTATUS err;
        const char *msg = (const char *)data->data;
        struct blocking_lock_record *blr;
+       struct smbd_server_connection *sconn =
+               talloc_get_type_abort(private_data,
+               struct smbd_server_connection);
 
        if (data->data == NULL) {
                smb_panic("process_blocking_lock_cancel_message: null msg");
@@ -864,7 +943,7 @@ struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
 
        if (!sconn->smb1.locks.blocking_lock_cancel_state) {
                /* Register our message. */
-               messaging_register(smbd_messaging_context(), NULL,
+               messaging_register(sconn->msg_ctx, sconn,
                                   MSG_SMB_BLOCKING_LOCK_CANCEL,
                                   process_blocking_lock_cancel_message);
 
@@ -900,9 +979,9 @@ struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
        memcpy(msg, &blr, sizeof(blr));
        memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
 
-       messaging_send_buf(smbd_messaging_context(), procid_self(),
+       messaging_send_buf(sconn->msg_ctx, messaging_server_id(sconn->msg_ctx),
                           MSG_SMB_BLOCKING_LOCK_CANCEL,
-                          (uint8 *)&msg, sizeof(msg));
+                          (uint8_t *)&msg, sizeof(msg));
 
        return blr;
 }