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"
26 #define DBGC_CLASS DBGC_LOCKING
28 /****************************************************************************
29 Determine if this is a secondary element of a chained SMB.
30 **************************************************************************/
32 static void received_unlock_msg(struct messaging_context *msg,
35 struct server_id server_id,
38 void brl_timeout_fn(struct event_context *event_ctx,
39 struct timed_event *te,
43 struct smbd_server_connection *sconn = talloc_get_type_abort(
44 private_data, struct smbd_server_connection);
46 if (sconn->using_smb2) {
47 SMB_ASSERT(sconn->smb2.locks.brl_timeout == te);
48 TALLOC_FREE(sconn->smb2.locks.brl_timeout);
50 SMB_ASSERT(sconn->smb1.locks.brl_timeout == te);
51 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
54 change_to_root_user(); /* TODO: Possibly run all timed events as
57 process_blocking_lock_queue(sconn);
60 /****************************************************************************
61 We need a version of timeval_min that treats zero timval as infinite.
62 ****************************************************************************/
64 struct timeval timeval_brl_min(const struct timeval *tv1,
65 const struct timeval *tv2)
67 if (timeval_is_zero(tv1)) {
70 if (timeval_is_zero(tv2)) {
73 return timeval_min(tv1, tv2);
76 /****************************************************************************
77 After a change to blocking_lock_queue, recalculate the timed_event for the
79 ****************************************************************************/
81 static bool recalc_brl_timeout(struct smbd_server_connection *sconn)
83 struct blocking_lock_record *blr;
84 struct timeval next_timeout;
85 int max_brl_timeout = lp_parm_int(-1, "brl", "recalctime", 5);
87 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
89 next_timeout = timeval_zero();
91 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
92 if (timeval_is_zero(&blr->expire_time)) {
94 * If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is
95 * a POSIX lock, so calculate a timeout of
96 * 10 seconds into the future.
98 if (blr->blocking_smblctx == 0xFFFFFFFFFFFFFFFFLL) {
99 struct timeval psx_to = timeval_current_ofs(10, 0);
100 next_timeout = timeval_brl_min(&next_timeout, &psx_to);
106 next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time);
109 if (timeval_is_zero(&next_timeout)) {
110 DEBUG(10, ("Next timeout = Infinite.\n"));
115 to account for unclean shutdowns by clients we need a
116 maximum timeout that we use for checking pending locks. If
117 we have any pending locks at all, then check if the pending
118 lock can continue at least every brl:recalctime seconds
121 This saves us needing to do a message_send_all() in the
122 SIGCHLD handler in the parent daemon. That
123 message_send_all() caused O(n^2) work to be done when IP
124 failovers happened in clustered Samba, which could make the
125 entire system unusable for many minutes.
128 if (max_brl_timeout > 0) {
129 struct timeval min_to = timeval_current_ofs(max_brl_timeout, 0);
130 next_timeout = timeval_min(&next_timeout, &min_to);
134 struct timeval cur, from_now;
136 cur = timeval_current();
137 from_now = timeval_until(&cur, &next_timeout);
138 DEBUG(10, ("Next timeout = %d.%d seconds from now.\n",
139 (int)from_now.tv_sec, (int)from_now.tv_usec));
142 sconn->smb1.locks.brl_timeout = tevent_add_timer(sconn->ev_ctx,
144 brl_timeout_fn, sconn);
145 if (sconn->smb1.locks.brl_timeout == NULL) {
153 /****************************************************************************
154 Function to push a blocking lock request onto the lock queue.
155 ****************************************************************************/
157 bool push_blocking_lock_request( struct byte_range_lock *br_lck,
158 struct smb_request *req,
163 enum brl_type lock_type,
164 enum brl_flavour lock_flav,
167 uint64_t blocking_smblctx)
169 struct smbd_server_connection *sconn = req->sconn;
170 struct blocking_lock_record *blr;
174 return push_blocking_lock_request_smb2(br_lck,
187 if(req_is_in_chain(req)) {
188 DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n"));
193 * Now queue an entry on the blocking lock queue. We setup
194 * the expiration time here.
197 blr = talloc(NULL, struct blocking_lock_record);
199 DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
207 if (lock_timeout == -1) {
208 blr->expire_time.tv_sec = 0;
209 blr->expire_time.tv_usec = 0; /* Never expire. */
211 blr->expire_time = timeval_current_ofs_msec(lock_timeout);
213 blr->lock_num = lock_num;
214 blr->smblctx = smblctx;
215 blr->blocking_smblctx = blocking_smblctx;
216 blr->lock_flav = lock_flav;
217 blr->lock_type = lock_type;
218 blr->offset = offset;
221 /* Specific brl_lock() implementations can fill this in. */
222 blr->blr_private = NULL;
224 /* Add a pending lock record for this. */
225 status = brl_lock(req->sconn->msg_ctx,
228 messaging_server_id(req->sconn->msg_ctx),
231 lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
237 if (!NT_STATUS_IS_OK(status)) {
238 DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
243 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd);
244 blr->req = talloc_move(blr, &req);
246 DLIST_ADD_END(sconn->smb1.locks.blocking_lock_queue, blr, struct blocking_lock_record *);
247 recalc_brl_timeout(sconn);
249 /* Ensure we'll receive messages when this is unlocked. */
250 if (!sconn->smb1.locks.blocking_lock_unlock_state) {
251 messaging_register(sconn->msg_ctx, sconn,
252 MSG_SMB_UNLOCK, received_unlock_msg);
253 sconn->smb1.locks.blocking_lock_unlock_state = true;
256 DEBUG(3,("push_blocking_lock_request: lock request blocked with "
257 "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n",
258 (unsigned int)blr->expire_time.tv_sec,
259 (unsigned int)blr->expire_time.tv_usec, lock_timeout,
260 blr->fsp->fnum, fsp_str_dbg(blr->fsp)));
265 /****************************************************************************
266 Return a lockingX success SMB.
267 *****************************************************************************/
269 static void reply_lockingX_success(struct blocking_lock_record *blr)
271 struct smb_request *req = blr->req;
273 reply_outbuf(req, 2, 0);
274 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
275 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
278 * As this message is a lockingX call we must handle
279 * any following chained message correctly.
280 * This is normally handled in construct_reply(),
281 * but as that calls switch_message, we can't use
282 * that here and must set up the chain info manually.
286 TALLOC_FREE(req->outbuf);
289 /****************************************************************************
290 Return a generic lock fail error blocking call.
291 *****************************************************************************/
293 static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
295 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
296 FILE_LOCK_CONFLICT! (tridge) */
297 if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
298 status = NT_STATUS_FILE_LOCK_CONFLICT;
301 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
302 /* Store the last lock error. */
303 files_struct *fsp = blr->fsp;
306 fsp->last_lock_failure.context.smblctx = blr->smblctx;
307 fsp->last_lock_failure.context.tid = fsp->conn->cnum;
308 fsp->last_lock_failure.context.pid =
309 messaging_server_id(fsp->conn->sconn->msg_ctx);
310 fsp->last_lock_failure.start = blr->offset;
311 fsp->last_lock_failure.size = blr->count;
312 fsp->last_lock_failure.fnum = fsp->fnum;
313 fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
314 fsp->last_lock_failure.lock_flav = blr->lock_flav;
318 reply_nterror(blr->req, status);
319 if (!srv_send_smb(blr->req->sconn, (char *)blr->req->outbuf,
320 true, blr->req->seqnum+1,
321 blr->req->encrypted, NULL)) {
322 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
324 TALLOC_FREE(blr->req->outbuf);
327 /****************************************************************************
328 Return a lock fail error for a lockingX call. Undo all the locks we have
330 *****************************************************************************/
332 static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS status)
334 files_struct *fsp = blr->fsp;
335 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
336 uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
338 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
339 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
343 data = discard_const_p(uint8_t, blr->req->buf)
344 + ((large_file_format ? 20 : 10)*num_ulocks);
347 * Data now points at the beginning of the list
348 * of smb_lkrng structs.
352 * Ensure we don't do a remove on the lock that just failed,
353 * as under POSIX rules, if we have a lock already there, we
354 * will delete it (and we shouldn't) .....
357 for(i = blr->lock_num - 1; i >= 0; i--) {
360 smblctx = get_lock_pid( data, i, large_file_format);
361 count = get_lock_count( data, i, large_file_format);
362 offset = get_lock_offset( data, i, large_file_format, &err);
365 * We know err cannot be set as if it was the lock
366 * request would never have been queued. JRA.
369 do_unlock(fsp->conn->sconn->msg_ctx,
377 generic_blocking_lock_error(blr, status);
380 /****************************************************************************
381 Return a lock fail error.
382 *****************************************************************************/
384 static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
386 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
388 switch(blr->req->cmd) {
390 reply_lockingX_error(blr, status);
394 reply_nterror(blr->req, status);
397 * construct_reply_common has done us the favor to pre-fill
398 * the command field with SMBtranss2 which is wrong :-)
400 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
402 if (!srv_send_smb(blr->req->sconn,
403 (char *)blr->req->outbuf,
404 true, blr->req->seqnum+1,
405 IS_CONN_ENCRYPTED(blr->fsp->conn),
407 exit_server_cleanly("blocking_lock_reply_error: "
408 "srv_send_smb failed.");
410 TALLOC_FREE(blr->req->outbuf);
413 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
414 exit_server("PANIC - unknown type on blocking lock queue");
418 /****************************************************************************
419 Attempt to finish off getting all pending blocking locks for a lockingX call.
420 Returns True if we want to be removed from the list.
421 *****************************************************************************/
423 static bool process_lockingX(struct blocking_lock_record *blr)
425 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
426 files_struct *fsp = blr->fsp;
427 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
428 uint16 num_locks = SVAL(blr->req->vwv+7, 0);
429 uint64_t count = (uint64_t)0, offset = (uint64_t)0;
431 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
433 NTSTATUS status = NT_STATUS_OK;
435 data = discard_const_p(uint8_t, blr->req->buf)
436 + ((large_file_format ? 20 : 10)*num_ulocks);
439 * Data now points at the beginning of the list
440 * of smb_lkrng structs.
443 for(; blr->lock_num < num_locks; blr->lock_num++) {
444 struct byte_range_lock *br_lck = NULL;
447 smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
448 count = get_lock_count( data, blr->lock_num, large_file_format);
449 offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
452 * We know err cannot be set as if it was the lock
453 * request would never have been queued. JRA.
456 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
461 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
462 READ_LOCK : WRITE_LOCK),
466 &blr->blocking_smblctx,
471 if (NT_STATUS_IS_ERR(status)) {
476 if(blr->lock_num == num_locks) {
478 * Success - we got all the locks.
481 DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d "
482 "num_locks=%d\n", fsp_str_dbg(fsp), fsp->fnum,
483 (unsigned int)locktype, num_locks));
485 reply_lockingX_success(blr);
489 if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
490 !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
492 * We have other than a "can't get lock"
493 * error. Free any locks we had and return an error.
494 * Return True so we get dequeued.
496 blocking_lock_reply_error(blr, status);
501 * Still can't get all the locks - keep waiting.
504 DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
506 blr->lock_num, num_locks, fsp_str_dbg(fsp), fsp->fnum));
511 /****************************************************************************
512 Attempt to get the posix lock request from a SMBtrans2 call.
513 Returns True if we want to be removed from the list.
514 *****************************************************************************/
516 static bool process_trans2(struct blocking_lock_record *blr)
520 struct byte_range_lock *br_lck = do_lock(
521 blr->fsp->conn->sconn->msg_ctx,
530 &blr->blocking_smblctx,
534 if (!NT_STATUS_IS_OK(status)) {
535 if (ERROR_WAS_LOCK_DENIED(status)) {
536 /* Still can't get the lock, just keep waiting. */
540 * We have other than a "can't get lock"
541 * error. Send an error and return True so we get dequeued.
543 blocking_lock_reply_error(blr, status);
547 /* We finally got the lock, return success. */
550 /* Fake up max_data_bytes here - we know it fits. */
551 send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff);
556 /****************************************************************************
557 Process a blocking lock SMB.
558 Returns True if we want to be removed from the list.
559 *****************************************************************************/
561 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
563 switch(blr->req->cmd) {
565 return process_lockingX(blr);
568 return process_trans2(blr);
570 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
571 exit_server("PANIC - unknown type on blocking lock queue");
573 return False; /* Keep compiler happy. */
576 /****************************************************************************
577 Cancel entries by fnum from the blocking lock pending queue.
578 Called when a file is closed.
579 *****************************************************************************/
581 void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp,
582 struct byte_range_lock *br_lck,
583 enum file_close_type close_type)
585 struct smbd_server_connection *sconn = fsp->conn->sconn;
586 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
588 if (sconn->using_smb2) {
589 cancel_pending_lock_requests_by_fid_smb2(fsp,
595 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
596 unsigned char locktype = 0;
599 if (blr->fsp->fnum != fsp->fnum) {
603 if (blr->req->cmd == SMBlockingX) {
604 locktype = CVAL(blr->req->vwv+3, 0);
607 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
608 "request type %d for file %s fnum = %d\n",
609 blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum));
611 blr_cancelled = blocking_lock_cancel_smb1(fsp,
617 NT_STATUS_RANGE_NOT_LOCKED);
619 SMB_ASSERT(blr_cancelled == blr);
621 brl_lock_cancel(br_lck,
623 messaging_server_id(sconn->msg_ctx),
629 /* We're closing the file fsp here, so ensure
630 * we don't have a dangling pointer. */
635 /****************************************************************************
636 Delete entries by mid from the blocking lock pending queue. Always send reply.
637 Only called from the SMB1 cancel code.
638 *****************************************************************************/
640 void remove_pending_lock_requests_by_mid_smb1(
641 struct smbd_server_connection *sconn, uint64_t mid)
643 struct blocking_lock_record *blr, *next = NULL;
645 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
647 struct byte_range_lock *br_lck;
651 if (blr->req->mid != mid) {
656 br_lck = brl_get_locks(talloc_tos(), fsp);
659 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
660 "removing request type %d for file %s fnum "
661 "= %d\n", blr->req->cmd, fsp_str_dbg(fsp),
664 brl_lock_cancel(br_lck,
666 messaging_server_id(sconn->msg_ctx),
674 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
675 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
680 /****************************************************************************
681 Is this mid a blocking lock request on the queue ?
682 Currently only called from the SMB1 unix extensions POSIX lock code.
683 *****************************************************************************/
685 bool blocking_lock_was_deferred_smb1(
686 struct smbd_server_connection *sconn, uint64_t mid)
688 struct blocking_lock_record *blr, *next = NULL;
690 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
692 if(blr->req->mid == mid) {
699 /****************************************************************************
700 Set a flag as an unlock request affects one of our pending locks.
701 *****************************************************************************/
703 static void received_unlock_msg(struct messaging_context *msg,
706 struct server_id server_id,
709 struct smbd_server_connection *sconn =
710 talloc_get_type_abort(private_data,
711 struct smbd_server_connection);
713 DEBUG(10,("received_unlock_msg\n"));
714 process_blocking_lock_queue(sconn);
717 /****************************************************************************
718 Process the blocking lock queue. Note that this is only called as root.
719 *****************************************************************************/
721 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
723 struct timeval tv_curr = timeval_current();
724 struct blocking_lock_record *blr, *next = NULL;
726 if (sconn->using_smb2) {
727 process_blocking_lock_queue_smb2(sconn, tv_curr);
732 * Go through the queue and see if we can get any of the locks.
735 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
740 * Go through the remaining locks and try and obtain them.
741 * The call returns True if all locks were obtained successfully
742 * and False if we still need to wait.
745 DEBUG(10, ("Processing BLR = %p\n", blr));
747 /* We use set_current_service so connections with
748 * pending locks are not marked as idle.
751 set_current_service(blr->fsp->conn,
752 SVAL(blr->req->inbuf,smb_flg),
755 if(blocking_lock_record_process(blr)) {
756 struct byte_range_lock *br_lck = brl_get_locks(
757 talloc_tos(), blr->fsp);
759 DEBUG(10, ("BLR_process returned true: cancelling and "
760 "removing lock. BLR = %p\n", blr));
763 brl_lock_cancel(br_lck,
765 messaging_server_id(sconn->msg_ctx),
773 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
779 * We couldn't get the locks for this record on the list.
780 * If the time has expired, return a lock error.
783 if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
784 struct byte_range_lock *br_lck = brl_get_locks(
785 talloc_tos(), blr->fsp);
787 DEBUG(10, ("Lock timed out! BLR = %p\n", blr));
790 * Lock expired - throw away all previously
791 * obtained locks and return lock error.
795 DEBUG(5,("process_blocking_lock_queue: "
796 "pending lock fnum = %d for file %s "
797 "timed out.\n", blr->fsp->fnum,
798 fsp_str_dbg(blr->fsp)));
800 brl_lock_cancel(br_lck,
802 messaging_server_id(sconn->msg_ctx),
810 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
811 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
816 recalc_brl_timeout(sconn);
819 /****************************************************************************
820 Handle a cancel message. Lock already moved onto the cancel queue.
821 *****************************************************************************/
823 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
825 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
828 struct server_id server_id,
832 const char *msg = (const char *)data->data;
833 struct blocking_lock_record *blr;
834 struct smbd_server_connection *sconn =
835 talloc_get_type_abort(private_data,
836 struct smbd_server_connection);
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 memcpy(&blr, msg, sizeof(blr));
849 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
851 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
854 blocking_lock_reply_error(blr, err);
855 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
859 /****************************************************************************
860 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
861 Returns the blocking_lock_record that is being cancelled.
862 Only called from the SMB1 code.
863 *****************************************************************************/
865 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
869 enum brl_flavour lock_flav,
870 unsigned char locktype,
873 struct smbd_server_connection *sconn = fsp->conn->sconn;
874 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
875 struct blocking_lock_record *blr;
877 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
878 /* Register our message. */
879 messaging_register(sconn->msg_ctx, sconn,
880 MSG_SMB_BLOCKING_LOCK_CANCEL,
881 process_blocking_lock_cancel_message);
883 sconn->smb1.locks.blocking_lock_cancel_state = True;
886 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
887 if (fsp == blr->fsp &&
888 smblctx == blr->smblctx &&
889 offset == blr->offset &&
890 count == blr->count &&
891 lock_flav == blr->lock_flav) {
900 /* Check the flags are right. */
901 if (blr->req->cmd == SMBlockingX &&
902 (locktype & LOCKING_ANDX_LARGE_FILES) !=
903 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
907 /* Move to cancelled queue. */
908 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
909 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
911 /* Create the message. */
912 memcpy(msg, &blr, sizeof(blr));
913 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
915 messaging_send_buf(sconn->msg_ctx, messaging_server_id(sconn->msg_ctx),
916 MSG_SMB_BLOCKING_LOCK_CANCEL,
917 (uint8 *)&msg, sizeof(msg));