2 Unix SMB/CIFS implementation.
3 Blocking Locking functions
4 Copyright (C) Jeremy Allison 1998-2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "smbd/smbd.h"
22 #include "smbd/globals.h"
23 #include "librpc/gen_ndr/messaging.h"
27 #define DBGC_CLASS DBGC_LOCKING
29 /****************************************************************************
30 Determine if this is a secondary element of a chained SMB.
31 **************************************************************************/
33 static void received_unlock_msg(struct messaging_context *msg,
36 struct server_id server_id,
39 void brl_timeout_fn(struct event_context *event_ctx,
40 struct timed_event *te,
44 struct smbd_server_connection *sconn = talloc_get_type_abort(
45 private_data, struct smbd_server_connection);
47 if (sconn->using_smb2) {
48 SMB_ASSERT(sconn->smb2.locks.brl_timeout == te);
49 TALLOC_FREE(sconn->smb2.locks.brl_timeout);
51 SMB_ASSERT(sconn->smb1.locks.brl_timeout == te);
52 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
55 change_to_root_user(); /* TODO: Possibly run all timed events as
58 process_blocking_lock_queue(sconn);
61 /****************************************************************************
62 We need a version of timeval_min that treats zero timval as infinite.
63 ****************************************************************************/
65 struct timeval timeval_brl_min(const struct timeval *tv1,
66 const struct timeval *tv2)
68 if (timeval_is_zero(tv1)) {
71 if (timeval_is_zero(tv2)) {
74 return timeval_min(tv1, tv2);
77 /****************************************************************************
78 After a change to blocking_lock_queue, recalculate the timed_event for the
80 ****************************************************************************/
82 static bool recalc_brl_timeout(struct smbd_server_connection *sconn)
84 struct blocking_lock_record *blr;
85 struct timeval next_timeout;
86 int max_brl_timeout = lp_parm_int(-1, "brl", "recalctime", 5);
88 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
90 next_timeout = timeval_zero();
92 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
93 if (timeval_is_zero(&blr->expire_time)) {
95 * If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is
96 * a POSIX lock, so calculate a timeout of
97 * 10 seconds into the future.
99 if (blr->blocking_smblctx == 0xFFFFFFFFFFFFFFFFLL) {
100 struct timeval psx_to = timeval_current_ofs(10, 0);
101 next_timeout = timeval_brl_min(&next_timeout, &psx_to);
107 next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time);
110 if (timeval_is_zero(&next_timeout)) {
111 DEBUG(10, ("Next timeout = Infinite.\n"));
116 to account for unclean shutdowns by clients we need a
117 maximum timeout that we use for checking pending locks. If
118 we have any pending locks at all, then check if the pending
119 lock can continue at least every brl:recalctime seconds
122 This saves us needing to do a message_send_all() in the
123 SIGCHLD handler in the parent daemon. That
124 message_send_all() caused O(n^2) work to be done when IP
125 failovers happened in clustered Samba, which could make the
126 entire system unusable for many minutes.
129 if (max_brl_timeout > 0) {
130 struct timeval min_to = timeval_current_ofs(max_brl_timeout, 0);
131 next_timeout = timeval_min(&next_timeout, &min_to);
135 struct timeval cur, from_now;
137 cur = timeval_current();
138 from_now = timeval_until(&cur, &next_timeout);
139 DEBUG(10, ("Next timeout = %d.%d seconds from now.\n",
140 (int)from_now.tv_sec, (int)from_now.tv_usec));
143 sconn->smb1.locks.brl_timeout = event_add_timed(smbd_event_context(),
145 brl_timeout_fn, sconn);
146 if (sconn->smb1.locks.brl_timeout == NULL) {
154 /****************************************************************************
155 Function to push a blocking lock request onto the lock queue.
156 ****************************************************************************/
158 bool push_blocking_lock_request( struct byte_range_lock *br_lck,
159 struct smb_request *req,
164 enum brl_type lock_type,
165 enum brl_flavour lock_flav,
168 uint64_t blocking_smblctx)
170 struct smbd_server_connection *sconn = req->sconn;
171 struct blocking_lock_record *blr;
175 return push_blocking_lock_request_smb2(br_lck,
188 if(req_is_in_chain(req)) {
189 DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n"));
194 * Now queue an entry on the blocking lock queue. We setup
195 * the expiration time here.
198 blr = talloc(NULL, struct blocking_lock_record);
200 DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
208 if (lock_timeout == -1) {
209 blr->expire_time.tv_sec = 0;
210 blr->expire_time.tv_usec = 0; /* Never expire. */
212 blr->expire_time = timeval_current_ofs(lock_timeout/1000,
213 (lock_timeout % 1000) * 1000);
215 blr->lock_num = lock_num;
216 blr->smblctx = smblctx;
217 blr->blocking_smblctx = blocking_smblctx;
218 blr->lock_flav = lock_flav;
219 blr->lock_type = lock_type;
220 blr->offset = offset;
223 /* Specific brl_lock() implementations can fill this in. */
224 blr->blr_private = NULL;
226 /* Add a pending lock record for this. */
227 status = brl_lock(req->sconn->msg_ctx,
230 sconn_server_id(req->sconn),
233 lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
239 if (!NT_STATUS_IS_OK(status)) {
240 DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
245 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd);
246 blr->req = talloc_move(blr, &req);
248 DLIST_ADD_END(sconn->smb1.locks.blocking_lock_queue, blr, struct blocking_lock_record *);
249 recalc_brl_timeout(sconn);
251 /* Ensure we'll receive messages when this is unlocked. */
252 if (!sconn->smb1.locks.blocking_lock_unlock_state) {
253 messaging_register(sconn->msg_ctx, NULL,
254 MSG_SMB_UNLOCK, received_unlock_msg);
255 sconn->smb1.locks.blocking_lock_unlock_state = true;
258 DEBUG(3,("push_blocking_lock_request: lock request blocked with "
259 "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n",
260 (unsigned int)blr->expire_time.tv_sec,
261 (unsigned int)blr->expire_time.tv_usec, lock_timeout,
262 blr->fsp->fnum, fsp_str_dbg(blr->fsp)));
267 /****************************************************************************
268 Return a lockingX success SMB.
269 *****************************************************************************/
271 static void reply_lockingX_success(struct blocking_lock_record *blr)
273 reply_outbuf(blr->req, 2, 0);
276 * As this message is a lockingX call we must handle
277 * any following chained message correctly.
278 * This is normally handled in construct_reply(),
279 * but as that calls switch_message, we can't use
280 * that here and must set up the chain info manually.
283 chain_reply(blr->req);
284 TALLOC_FREE(blr->req->outbuf);
287 /****************************************************************************
288 Return a generic lock fail error blocking call.
289 *****************************************************************************/
291 static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
293 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
294 FILE_LOCK_CONFLICT! (tridge) */
295 if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
296 status = NT_STATUS_FILE_LOCK_CONFLICT;
299 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
300 /* Store the last lock error. */
301 files_struct *fsp = blr->fsp;
304 fsp->last_lock_failure.context.smblctx = blr->smblctx;
305 fsp->last_lock_failure.context.tid = fsp->conn->cnum;
306 fsp->last_lock_failure.context.pid =
307 sconn_server_id(fsp->conn->sconn);
308 fsp->last_lock_failure.start = blr->offset;
309 fsp->last_lock_failure.size = blr->count;
310 fsp->last_lock_failure.fnum = fsp->fnum;
311 fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
312 fsp->last_lock_failure.lock_flav = blr->lock_flav;
316 reply_nterror(blr->req, status);
317 if (!srv_send_smb(blr->req->sconn, (char *)blr->req->outbuf,
318 true, blr->req->seqnum+1,
319 blr->req->encrypted, NULL)) {
320 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
322 TALLOC_FREE(blr->req->outbuf);
325 /****************************************************************************
326 Return a lock fail error for a lockingX call. Undo all the locks we have
328 *****************************************************************************/
330 static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS status)
332 files_struct *fsp = blr->fsp;
333 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
334 uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
336 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
337 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
341 data = (uint8_t *)blr->req->buf
342 + ((large_file_format ? 20 : 10)*num_ulocks);
345 * Data now points at the beginning of the list
346 * of smb_lkrng structs.
350 * Ensure we don't do a remove on the lock that just failed,
351 * as under POSIX rules, if we have a lock already there, we
352 * will delete it (and we shouldn't) .....
355 for(i = blr->lock_num - 1; i >= 0; i--) {
358 smblctx = get_lock_pid( data, i, large_file_format);
359 count = get_lock_count( data, i, large_file_format);
360 offset = get_lock_offset( data, i, large_file_format, &err);
363 * We know err cannot be set as if it was the lock
364 * request would never have been queued. JRA.
367 do_unlock(fsp->conn->sconn->msg_ctx,
375 generic_blocking_lock_error(blr, status);
378 /****************************************************************************
379 Return a lock fail error.
380 *****************************************************************************/
382 static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
384 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
386 switch(blr->req->cmd) {
388 reply_lockingX_error(blr, status);
392 reply_nterror(blr->req, status);
395 * construct_reply_common has done us the favor to pre-fill
396 * the command field with SMBtranss2 which is wrong :-)
398 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
400 if (!srv_send_smb(blr->req->sconn,
401 (char *)blr->req->outbuf,
402 true, blr->req->seqnum+1,
403 IS_CONN_ENCRYPTED(blr->fsp->conn),
405 exit_server_cleanly("blocking_lock_reply_error: "
406 "srv_send_smb failed.");
408 TALLOC_FREE(blr->req->outbuf);
411 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
412 exit_server("PANIC - unknown type on blocking lock queue");
416 /****************************************************************************
417 Attempt to finish off getting all pending blocking locks for a lockingX call.
418 Returns True if we want to be removed from the list.
419 *****************************************************************************/
421 static bool process_lockingX(struct blocking_lock_record *blr)
423 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
424 files_struct *fsp = blr->fsp;
425 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
426 uint16 num_locks = SVAL(blr->req->vwv+7, 0);
427 uint64_t count = (uint64_t)0, offset = (uint64_t)0;
429 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
431 NTSTATUS status = NT_STATUS_OK;
433 data = (uint8_t *)blr->req->buf
434 + ((large_file_format ? 20 : 10)*num_ulocks);
437 * Data now points at the beginning of the list
438 * of smb_lkrng structs.
441 for(; blr->lock_num < num_locks; blr->lock_num++) {
442 struct byte_range_lock *br_lck = NULL;
445 smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
446 count = get_lock_count( data, blr->lock_num, large_file_format);
447 offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
450 * We know err cannot be set as if it was the lock
451 * request would never have been queued. JRA.
454 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
459 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
460 READ_LOCK : WRITE_LOCK),
464 &blr->blocking_smblctx,
469 if (NT_STATUS_IS_ERR(status)) {
474 if(blr->lock_num == num_locks) {
476 * Success - we got all the locks.
479 DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d "
480 "num_locks=%d\n", fsp_str_dbg(fsp), fsp->fnum,
481 (unsigned int)locktype, num_locks));
483 reply_lockingX_success(blr);
487 if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
488 !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
490 * We have other than a "can't get lock"
491 * error. Free any locks we had and return an error.
492 * Return True so we get dequeued.
494 blocking_lock_reply_error(blr, status);
499 * Still can't get all the locks - keep waiting.
502 DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
504 blr->lock_num, num_locks, fsp_str_dbg(fsp), fsp->fnum));
509 /****************************************************************************
510 Attempt to get the posix lock request from a SMBtrans2 call.
511 Returns True if we want to be removed from the list.
512 *****************************************************************************/
514 static bool process_trans2(struct blocking_lock_record *blr)
518 struct byte_range_lock *br_lck = do_lock(
519 blr->fsp->conn->sconn->msg_ctx,
528 &blr->blocking_smblctx,
532 if (!NT_STATUS_IS_OK(status)) {
533 if (ERROR_WAS_LOCK_DENIED(status)) {
534 /* Still can't get the lock, just keep waiting. */
538 * We have other than a "can't get lock"
539 * error. Send an error and return True so we get dequeued.
541 blocking_lock_reply_error(blr, status);
545 /* We finally got the lock, return success. */
548 /* Fake up max_data_bytes here - we know it fits. */
549 send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff);
554 /****************************************************************************
555 Process a blocking lock SMB.
556 Returns True if we want to be removed from the list.
557 *****************************************************************************/
559 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
561 switch(blr->req->cmd) {
563 return process_lockingX(blr);
566 return process_trans2(blr);
568 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
569 exit_server("PANIC - unknown type on blocking lock queue");
571 return False; /* Keep compiler happy. */
574 /****************************************************************************
575 Cancel entries by fnum from the blocking lock pending queue.
576 Called when a file is closed.
577 *****************************************************************************/
579 void cancel_pending_lock_requests_by_fid(files_struct *fsp,
580 struct byte_range_lock *br_lck,
581 enum file_close_type close_type)
583 struct smbd_server_connection *sconn = fsp->conn->sconn;
584 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
586 if (sconn->using_smb2) {
587 cancel_pending_lock_requests_by_fid_smb2(fsp,
593 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
594 unsigned char locktype = 0;
597 if (blr->fsp->fnum != fsp->fnum) {
601 if (blr->req->cmd == SMBlockingX) {
602 locktype = CVAL(blr->req->vwv+3, 0);
605 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
606 "request type %d for file %s fnum = %d\n",
607 blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum));
609 blr_cancelled = blocking_lock_cancel_smb1(fsp,
615 NT_STATUS_RANGE_NOT_LOCKED);
617 SMB_ASSERT(blr_cancelled == blr);
619 brl_lock_cancel(br_lck,
621 sconn_server_id(sconn),
627 /* We're closing the file fsp here, so ensure
628 * we don't have a dangling pointer. */
633 /****************************************************************************
634 Delete entries by mid from the blocking lock pending queue. Always send reply.
635 Only called from the SMB1 cancel code.
636 *****************************************************************************/
638 void remove_pending_lock_requests_by_mid_smb1(
639 struct smbd_server_connection *sconn, uint64_t mid)
641 struct blocking_lock_record *blr, *next = NULL;
643 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
645 struct byte_range_lock *br_lck;
649 if (blr->req->mid != mid) {
654 br_lck = brl_get_locks(talloc_tos(), fsp);
657 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
658 "removing request type %d for file %s fnum "
659 "= %d\n", blr->req->cmd, fsp_str_dbg(fsp),
662 brl_lock_cancel(br_lck,
664 sconn_server_id(sconn),
672 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
673 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
678 /****************************************************************************
679 Is this mid a blocking lock request on the queue ?
680 Currently only called from the SMB1 unix extensions POSIX lock code.
681 *****************************************************************************/
683 bool blocking_lock_was_deferred_smb1(
684 struct smbd_server_connection *sconn, uint64_t mid)
686 struct blocking_lock_record *blr, *next = NULL;
688 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
690 if(blr->req->mid == mid) {
697 /****************************************************************************
698 Set a flag as an unlock request affects one of our pending locks.
699 *****************************************************************************/
701 static void received_unlock_msg(struct messaging_context *msg,
704 struct server_id server_id,
707 struct smbd_server_connection *sconn;
709 sconn = msg_ctx_to_sconn(msg);
711 DEBUG(1, ("could not find sconn\n"));
715 DEBUG(10,("received_unlock_msg\n"));
716 process_blocking_lock_queue(sconn);
719 /****************************************************************************
720 Process the blocking lock queue. Note that this is only called as root.
721 *****************************************************************************/
723 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
725 struct timeval tv_curr = timeval_current();
726 struct blocking_lock_record *blr, *next = NULL;
728 if (sconn->using_smb2) {
729 process_blocking_lock_queue_smb2(sconn, tv_curr);
734 * Go through the queue and see if we can get any of the locks.
737 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
742 * Go through the remaining locks and try and obtain them.
743 * The call returns True if all locks were obtained successfully
744 * and False if we still need to wait.
747 DEBUG(10, ("Processing BLR = %p\n", blr));
749 /* We use set_current_service so connections with
750 * pending locks are not marked as idle.
753 set_current_service(blr->fsp->conn,
754 SVAL(blr->req->inbuf,smb_flg),
757 if(blocking_lock_record_process(blr)) {
758 struct byte_range_lock *br_lck = brl_get_locks(
759 talloc_tos(), blr->fsp);
761 DEBUG(10, ("BLR_process returned true: cancelling and "
762 "removing lock. BLR = %p\n", blr));
765 brl_lock_cancel(br_lck,
767 sconn_server_id(sconn),
775 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
781 * We couldn't get the locks for this record on the list.
782 * If the time has expired, return a lock error.
785 if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
786 struct byte_range_lock *br_lck = brl_get_locks(
787 talloc_tos(), blr->fsp);
789 DEBUG(10, ("Lock timed out! BLR = %p\n", blr));
792 * Lock expired - throw away all previously
793 * obtained locks and return lock error.
797 DEBUG(5,("process_blocking_lock_queue: "
798 "pending lock fnum = %d for file %s "
799 "timed out.\n", blr->fsp->fnum,
800 fsp_str_dbg(blr->fsp)));
802 brl_lock_cancel(br_lck,
804 sconn_server_id(sconn),
812 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
813 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
818 recalc_brl_timeout(sconn);
821 /****************************************************************************
822 Handle a cancel message. Lock already moved onto the cancel queue.
823 *****************************************************************************/
825 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
827 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
830 struct server_id server_id,
833 struct smbd_server_connection *sconn;
835 const char *msg = (const char *)data->data;
836 struct blocking_lock_record *blr;
838 if (data->data == NULL) {
839 smb_panic("process_blocking_lock_cancel_message: null msg");
842 if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
843 DEBUG(0, ("process_blocking_lock_cancel_message: "
844 "Got invalid msg len %d\n", (int)data->length));
845 smb_panic("process_blocking_lock_cancel_message: bad msg");
848 sconn = msg_ctx_to_sconn(ctx);
850 DEBUG(1, ("could not find sconn\n"));
854 memcpy(&blr, msg, sizeof(blr));
855 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
857 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
860 blocking_lock_reply_error(blr, err);
861 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
865 /****************************************************************************
866 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
867 Returns the blocking_lock_record that is being cancelled.
868 Only called from the SMB1 code.
869 *****************************************************************************/
871 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
875 enum brl_flavour lock_flav,
876 unsigned char locktype,
879 struct smbd_server_connection *sconn = fsp->conn->sconn;
880 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
881 struct blocking_lock_record *blr;
883 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
884 /* Register our message. */
885 messaging_register(sconn->msg_ctx, NULL,
886 MSG_SMB_BLOCKING_LOCK_CANCEL,
887 process_blocking_lock_cancel_message);
889 sconn->smb1.locks.blocking_lock_cancel_state = True;
892 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
893 if (fsp == blr->fsp &&
894 smblctx == blr->smblctx &&
895 offset == blr->offset &&
896 count == blr->count &&
897 lock_flav == blr->lock_flav) {
906 /* Check the flags are right. */
907 if (blr->req->cmd == SMBlockingX &&
908 (locktype & LOCKING_ANDX_LARGE_FILES) !=
909 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
913 /* Move to cancelled queue. */
914 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
915 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
917 /* Create the message. */
918 memcpy(msg, &blr, sizeof(blr));
919 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
921 messaging_send_buf(sconn->msg_ctx, sconn_server_id(sconn),
922 MSG_SMB_BLOCKING_LOCK_CANCEL,
923 (uint8 *)&msg, sizeof(msg));