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 static void received_unlock_msg(struct messaging_context *msg,
31 struct server_id server_id,
34 void brl_timeout_fn(struct tevent_context *event_ctx,
35 struct tevent_timer *te,
39 struct smbd_server_connection *sconn = talloc_get_type_abort(
40 private_data, struct smbd_server_connection);
42 if (sconn->using_smb2) {
43 SMB_ASSERT(sconn->smb2.locks.brl_timeout == te);
44 TALLOC_FREE(sconn->smb2.locks.brl_timeout);
46 SMB_ASSERT(sconn->smb1.locks.brl_timeout == te);
47 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
50 process_blocking_lock_queue(sconn);
53 /****************************************************************************
54 We need a version of timeval_min that treats zero timval as infinite.
55 ****************************************************************************/
57 struct timeval timeval_brl_min(const struct timeval *tv1,
58 const struct timeval *tv2)
60 if (timeval_is_zero(tv1)) {
63 if (timeval_is_zero(tv2)) {
66 return timeval_min(tv1, tv2);
69 /****************************************************************************
70 After a change to blocking_lock_queue, recalculate the timed_event for the
72 ****************************************************************************/
74 static bool recalc_brl_timeout(struct smbd_server_connection *sconn)
76 struct blocking_lock_record *blr;
77 struct timeval next_timeout;
78 int max_brl_timeout = lp_parm_int(-1, "brl", "recalctime", 5);
80 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
82 next_timeout = timeval_zero();
84 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
85 if (timeval_is_zero(&blr->expire_time)) {
87 * If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is
88 * a POSIX lock, so calculate a timeout of
89 * 10 seconds into the future.
91 if (blr->blocking_smblctx == 0xFFFFFFFFFFFFFFFFLL) {
92 struct timeval psx_to = timeval_current_ofs(10, 0);
93 next_timeout = timeval_brl_min(&next_timeout, &psx_to);
99 next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time);
102 if (timeval_is_zero(&next_timeout)) {
103 DEBUG(10, ("Next timeout = Infinite.\n"));
108 to account for unclean shutdowns by clients we need a
109 maximum timeout that we use for checking pending locks. If
110 we have any pending locks at all, then check if the pending
111 lock can continue at least every brl:recalctime seconds
114 This saves us needing to do a message_send_all() in the
115 SIGCHLD handler in the parent daemon. That
116 message_send_all() caused O(n^2) work to be done when IP
117 failovers happened in clustered Samba, which could make the
118 entire system unusable for many minutes.
121 if (max_brl_timeout > 0) {
122 struct timeval min_to = timeval_current_ofs(max_brl_timeout, 0);
123 next_timeout = timeval_min(&next_timeout, &min_to);
127 struct timeval cur, from_now;
129 cur = timeval_current();
130 from_now = timeval_until(&cur, &next_timeout);
131 DEBUG(10, ("Next timeout = %d.%d seconds from now.\n",
132 (int)from_now.tv_sec, (int)from_now.tv_usec));
136 * brl_timeout_fn() calls change_to_root_user()
137 * so we can use sconn->root_ev_ctx.
139 sconn->smb1.locks.brl_timeout = tevent_add_timer(sconn->root_ev_ctx,
141 brl_timeout_fn, sconn);
142 if (sconn->smb1.locks.brl_timeout == NULL) {
150 /****************************************************************************
151 Function to push a blocking lock request onto the lock queue.
152 ****************************************************************************/
154 bool push_blocking_lock_request( struct byte_range_lock *br_lck,
155 struct smb_request *req,
160 enum brl_type lock_type,
161 enum brl_flavour lock_flav,
164 uint64_t blocking_smblctx)
166 struct smbd_server_connection *sconn = req->sconn;
167 struct blocking_lock_record *blr;
171 return push_blocking_lock_request_smb2(br_lck,
184 if(req_is_in_chain(req)) {
185 DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n"));
190 * Now queue an entry on the blocking lock queue. We setup
191 * the expiration time here.
194 blr = talloc(NULL, struct blocking_lock_record);
196 DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
204 if (lock_timeout == -1) {
205 blr->expire_time.tv_sec = 0;
206 blr->expire_time.tv_usec = 0; /* Never expire. */
208 blr->expire_time = timeval_current_ofs_msec(lock_timeout);
210 blr->lock_num = lock_num;
211 blr->smblctx = smblctx;
212 blr->blocking_smblctx = blocking_smblctx;
213 blr->lock_flav = lock_flav;
214 blr->lock_type = lock_type;
215 blr->offset = offset;
218 /* Specific brl_lock() implementations can fill this in. */
219 blr->blr_private = NULL;
221 /* Add a pending lock record for this. */
222 status = brl_lock(req->sconn->msg_ctx,
225 messaging_server_id(req->sconn->msg_ctx),
228 lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
233 if (!NT_STATUS_IS_OK(status)) {
234 DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
239 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd);
240 blr->req = talloc_move(blr, &req);
242 DLIST_ADD_END(sconn->smb1.locks.blocking_lock_queue, blr);
243 recalc_brl_timeout(sconn);
245 /* Ensure we'll receive messages when this is unlocked. */
246 if (!sconn->smb1.locks.blocking_lock_unlock_state) {
247 messaging_register(sconn->msg_ctx, sconn,
248 MSG_SMB_UNLOCK, received_unlock_msg);
249 sconn->smb1.locks.blocking_lock_unlock_state = true;
252 DEBUG(3,("push_blocking_lock_request: lock request blocked with "
253 "expiry time (%u sec. %u usec) (+%d msec) for %s, name = %s\n",
254 (unsigned int)blr->expire_time.tv_sec,
255 (unsigned int)blr->expire_time.tv_usec, lock_timeout,
256 fsp_fnum_dbg(blr->fsp), fsp_str_dbg(blr->fsp)));
261 /****************************************************************************
262 Return a lockingX success SMB.
263 *****************************************************************************/
265 static void reply_lockingX_success(struct blocking_lock_record *blr)
267 struct smb_request *req = blr->req;
269 reply_outbuf(req, 2, 0);
270 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
271 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
274 * As this message is a lockingX call we must handle
275 * any following chained message correctly.
276 * This is normally handled in construct_reply(),
277 * but as that calls switch_message, we can't use
278 * that here and must set up the chain info manually.
281 if (!srv_send_smb(req->xconn,
284 IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
286 exit_server_cleanly("construct_reply: srv_send_smb failed.");
289 TALLOC_FREE(req->outbuf);
292 /****************************************************************************
293 Return a generic lock fail error blocking call.
294 *****************************************************************************/
296 static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
298 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
299 FILE_LOCK_CONFLICT! (tridge) */
300 if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
301 status = NT_STATUS_FILE_LOCK_CONFLICT;
304 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
305 /* Store the last lock error. */
306 files_struct *fsp = blr->fsp;
309 fsp->last_lock_failure.context.smblctx = blr->smblctx;
310 fsp->last_lock_failure.context.tid = fsp->conn->cnum;
311 fsp->last_lock_failure.context.pid =
312 messaging_server_id(fsp->conn->sconn->msg_ctx);
313 fsp->last_lock_failure.start = blr->offset;
314 fsp->last_lock_failure.size = blr->count;
315 fsp->last_lock_failure.fnum = fsp->fnum;
316 fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
317 fsp->last_lock_failure.lock_flav = blr->lock_flav;
321 reply_nterror(blr->req, status);
322 if (!srv_send_smb(blr->req->xconn, (char *)blr->req->outbuf,
323 true, blr->req->seqnum+1,
324 blr->req->encrypted, NULL)) {
325 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
327 TALLOC_FREE(blr->req->outbuf);
330 /****************************************************************************
331 Return a lock fail error for a lockingX call. Undo all the locks we have
333 *****************************************************************************/
335 static void undo_locks_obtained(struct blocking_lock_record *blr)
337 files_struct *fsp = blr->fsp;
338 uint16_t num_ulocks = SVAL(blr->req->vwv+6, 0);
339 uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
341 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
342 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
346 data = discard_const_p(uint8_t, blr->req->buf)
347 + ((large_file_format ? 20 : 10)*num_ulocks);
350 * Data now points at the beginning of the list
351 * of smb_lkrng structs.
355 * Ensure we don't do a remove on the lock that just failed,
356 * as under POSIX rules, if we have a lock already there, we
357 * will delete it (and we shouldn't) .....
360 for(i = blr->lock_num - 1; i >= 0; i--) {
362 smblctx = get_lock_pid( data, i, large_file_format);
363 count = get_lock_count( data, i, large_file_format);
364 offset = get_lock_offset( data, i, large_file_format);
367 * We know err cannot be set as if it was the lock
368 * request would never have been queued. JRA.
371 do_unlock(fsp->conn->sconn->msg_ctx,
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) {
391 * This code can be called during the rundown of a
392 * file after it was already closed. In that case,
393 * blr->fsp==NULL and we do not need to undo any
394 * locks, they are already gone.
396 if (blr->fsp != NULL) {
397 undo_locks_obtained(blr);
399 generic_blocking_lock_error(blr, status);
403 reply_nterror(blr->req, status);
406 * construct_reply_common has done us the favor to pre-fill
407 * the command field with SMBtranss2 which is wrong :-)
409 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
411 if (!srv_send_smb(blr->req->xconn,
412 (char *)blr->req->outbuf,
413 true, blr->req->seqnum+1,
414 IS_CONN_ENCRYPTED(blr->fsp->conn),
416 exit_server_cleanly("blocking_lock_reply_error: "
417 "srv_send_smb failed.");
419 TALLOC_FREE(blr->req->outbuf);
422 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
423 exit_server("PANIC - unknown type on blocking lock queue");
427 /****************************************************************************
428 Utility function that returns true if a lock timed out.
429 *****************************************************************************/
431 static bool lock_timed_out(const struct blocking_lock_record *blr)
433 struct timeval tv_curr;
435 if (timeval_is_zero(&blr->expire_time)) {
436 return false; /* Never times out. */
439 tv_curr = timeval_current();
440 if (timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
446 /****************************************************************************
447 Attempt to finish off getting all pending blocking locks for a lockingX call.
448 Returns True if we want to be removed from the list.
449 *****************************************************************************/
451 static bool process_lockingX(struct blocking_lock_record *blr)
453 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
454 files_struct *fsp = blr->fsp;
455 uint16_t num_ulocks = SVAL(blr->req->vwv+6, 0);
456 uint16_t num_locks = SVAL(blr->req->vwv+7, 0);
457 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
459 NTSTATUS status = NT_STATUS_OK;
460 bool lock_timeout = lock_timed_out(blr);
462 data = discard_const_p(uint8_t, blr->req->buf)
463 + ((large_file_format ? 20 : 10)*num_ulocks);
466 * Data now points at the beginning of the list
467 * of smb_lkrng structs.
470 for(; blr->lock_num < num_locks; blr->lock_num++) {
471 struct byte_range_lock *br_lck = NULL;
474 * Ensure the blr record gets updated with
475 * any lock we might end up blocked on.
478 blr->smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
479 blr->count = get_lock_count( data, blr->lock_num, large_file_format);
480 blr->offset = get_lock_offset( data, blr->lock_num, large_file_format);
483 * We know err cannot be set as if it was the lock
484 * request would never have been queued. JRA.
487 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
492 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
493 READ_LOCK : WRITE_LOCK),
497 &blr->blocking_smblctx);
499 if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
501 * If we didn't timeout, but still need to wait,
502 * re-add the pending lock entry whilst holding
503 * the brlock db lock.
506 brl_lock(blr->fsp->conn->sconn->msg_ctx,
510 blr->fsp->conn->sconn->msg_ctx),
513 blr->lock_type == READ_LOCK ?
517 true, /* Blocking lock. */
520 if (!NT_STATUS_IS_OK(status1)) {
521 DEBUG(0,("failed to add PENDING_LOCK "
528 if (NT_STATUS_IS_ERR(status)) {
533 if(blr->lock_num == num_locks) {
535 * Success - we got all the locks.
538 DEBUG(3,("process_lockingX file = %s, %s, type=%d "
539 "num_locks=%d\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
540 (unsigned int)locktype, num_locks));
542 reply_lockingX_success(blr);
546 if (!ERROR_WAS_LOCK_DENIED(status)) {
548 * We have other than a "can't get lock"
549 * error. Free any locks we had and return an error.
550 * Return True so we get dequeued.
552 blocking_lock_reply_error(blr, status);
557 * Return an error to the client if we timed out.
560 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
565 * Still can't get all the locks - keep waiting.
568 DEBUG(10, ("process_lockingX: only got %d locks of %d needed for "
569 "file %s, %s. Waiting....\n",
570 blr->lock_num, num_locks, fsp_str_dbg(fsp),
576 /****************************************************************************
577 Attempt to get the posix lock request from a SMBtrans2 call.
578 Returns True if we want to be removed from the list.
579 *****************************************************************************/
581 static bool process_trans2(struct blocking_lock_record *blr)
585 bool lock_timeout = lock_timed_out(blr);
587 struct byte_range_lock *br_lck = do_lock(
588 blr->fsp->conn->sconn->msg_ctx,
597 &blr->blocking_smblctx);
598 if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
600 * If we didn't timeout, but still need to wait,
601 * re-add the pending lock entry whilst holding
602 * the brlock db lock.
605 brl_lock(blr->fsp->conn->sconn->msg_ctx,
609 blr->fsp->conn->sconn->msg_ctx),
612 blr->lock_type == READ_LOCK ?
616 true, /* Blocking lock. */
619 if (!NT_STATUS_IS_OK(status1)) {
620 DEBUG(0,("failed to add PENDING_LOCK record.\n"));
626 if (!NT_STATUS_IS_OK(status)) {
627 if (ERROR_WAS_LOCK_DENIED(status)) {
630 * Return an error if we timed out
631 * and return true to get dequeued.
633 blocking_lock_reply_error(blr,
634 NT_STATUS_FILE_LOCK_CONFLICT);
637 /* Still can't get the lock, just keep waiting. */
641 * We have other than a "can't get lock"
642 * error. Send an error and return True so we get dequeued.
644 blocking_lock_reply_error(blr, status);
648 /* We finally got the lock, return success. */
651 /* Fake up max_data_bytes here - we know it fits. */
652 send_trans2_replies(blr->fsp->conn, blr->req, NT_STATUS_OK, params, 2, NULL, 0, 0xffff);
657 /****************************************************************************
658 Process a blocking lock SMB.
659 Returns True if we want to be removed from the list.
660 *****************************************************************************/
662 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
664 switch(blr->req->cmd) {
666 return process_lockingX(blr);
669 return process_trans2(blr);
671 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
672 exit_server("PANIC - unknown type on blocking lock queue");
674 return False; /* Keep compiler happy. */
677 /****************************************************************************
678 Cancel entries by fnum from the blocking lock pending queue.
679 Called when a file is closed.
680 *****************************************************************************/
682 void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp,
683 struct byte_range_lock *br_lck,
684 enum file_close_type close_type)
686 struct smbd_server_connection *sconn = fsp->conn->sconn;
687 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
689 if (sconn->using_smb2) {
690 cancel_pending_lock_requests_by_fid_smb2(fsp,
696 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
697 unsigned char locktype = 0;
700 if (blr->fsp->fnum != fsp->fnum) {
704 if (blr->req->cmd == SMBlockingX) {
705 locktype = CVAL(blr->req->vwv+3, 0);
708 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
709 "request type %d for file %s, %s\n",
710 blr->req->cmd, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
712 blr_cancelled = blocking_lock_cancel_smb1(fsp,
718 NT_STATUS_RANGE_NOT_LOCKED);
720 SMB_ASSERT(blr_cancelled == blr);
722 brl_lock_cancel(br_lck,
724 messaging_server_id(sconn->msg_ctx),
729 /* We're closing the file fsp here, so ensure
730 * we don't have a dangling pointer. */
735 /****************************************************************************
736 Delete entries by mid from the blocking lock pending queue. Always send reply.
737 Only called from the SMB1 cancel code.
738 *****************************************************************************/
740 void remove_pending_lock_requests_by_mid_smb1(
741 struct smbd_server_connection *sconn, uint64_t mid)
743 struct blocking_lock_record *blr, *next = NULL;
745 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
747 struct byte_range_lock *br_lck;
751 if (blr->req->mid != mid) {
756 br_lck = brl_get_locks(talloc_tos(), fsp);
759 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
760 "removing request type %d for file %s, %s\n",
761 blr->req->cmd, fsp_str_dbg(fsp),
764 brl_lock_cancel(br_lck,
766 messaging_server_id(sconn->msg_ctx),
773 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
774 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
779 /****************************************************************************
780 Is this mid a blocking lock request on the queue ?
781 Currently only called from the SMB1 unix extensions POSIX lock code.
782 *****************************************************************************/
784 bool blocking_lock_was_deferred_smb1(
785 struct smbd_server_connection *sconn, uint64_t mid)
787 struct blocking_lock_record *blr, *next = NULL;
789 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
791 if(blr->req->mid == mid) {
798 /****************************************************************************
799 Set a flag as an unlock request affects one of our pending locks.
800 *****************************************************************************/
802 static void received_unlock_msg(struct messaging_context *msg,
805 struct server_id server_id,
808 struct smbd_server_connection *sconn =
809 talloc_get_type_abort(private_data,
810 struct smbd_server_connection);
812 DEBUG(10,("received_unlock_msg\n"));
813 process_blocking_lock_queue(sconn);
816 /****************************************************************************
817 Process the blocking lock queue. Note that this is only called as root.
818 *****************************************************************************/
820 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
822 struct blocking_lock_record *blr, *next = NULL;
824 if (sconn->using_smb2) {
825 process_blocking_lock_queue_smb2(sconn, timeval_current());
830 * Go through the queue and see if we can get any of the locks.
833 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
834 struct byte_range_lock *br_lck = NULL;
839 * Go through the remaining locks and try and obtain them.
840 * The call returns True if all locks were obtained successfully
841 * and False if we still need to wait.
844 DEBUG(10, ("Processing BLR = %p\n", blr));
847 * Connections with pending locks are not marked as idle.
849 blr->fsp->conn->lastused_count++;
852 * Remove the pending lock we're waiting on.
853 * If we need to keep waiting blocking_lock_record_process()
857 br_lck = brl_get_locks(talloc_tos(), blr->fsp);
859 brl_lock_cancel(br_lck,
861 messaging_server_id(sconn->msg_ctx),
868 if(!blocking_lock_record_process(blr)) {
869 DEBUG(10, ("still waiting for lock. BLR = %p\n", blr));
873 DEBUG(10, ("BLR_process returned true: removing BLR = %p\n",
876 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
880 recalc_brl_timeout(sconn);
883 /****************************************************************************
884 Handle a cancel message. Lock already moved onto the cancel queue.
885 *****************************************************************************/
887 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
889 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
892 struct server_id server_id,
896 const char *msg = (const char *)data->data;
897 struct blocking_lock_record *blr;
898 struct smbd_server_connection *sconn =
899 talloc_get_type_abort(private_data,
900 struct smbd_server_connection);
902 if (data->data == NULL) {
903 smb_panic("process_blocking_lock_cancel_message: null msg");
906 if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
907 DEBUG(0, ("process_blocking_lock_cancel_message: "
908 "Got invalid msg len %d\n", (int)data->length));
909 smb_panic("process_blocking_lock_cancel_message: bad msg");
912 memcpy(&blr, msg, sizeof(blr));
913 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
915 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
918 blocking_lock_reply_error(blr, err);
919 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
923 /****************************************************************************
924 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
925 Returns the blocking_lock_record that is being cancelled.
926 Only called from the SMB1 code.
927 *****************************************************************************/
929 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
933 enum brl_flavour lock_flav,
934 unsigned char locktype,
937 struct smbd_server_connection *sconn = fsp->conn->sconn;
938 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
939 struct blocking_lock_record *blr;
941 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
942 /* Register our message. */
943 messaging_register(sconn->msg_ctx, sconn,
944 MSG_SMB_BLOCKING_LOCK_CANCEL,
945 process_blocking_lock_cancel_message);
947 sconn->smb1.locks.blocking_lock_cancel_state = True;
950 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
951 if (fsp == blr->fsp &&
952 smblctx == blr->smblctx &&
953 offset == blr->offset &&
954 count == blr->count &&
955 lock_flav == blr->lock_flav) {
964 /* Check the flags are right. */
965 if (blr->req->cmd == SMBlockingX &&
966 (locktype & LOCKING_ANDX_LARGE_FILES) !=
967 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
971 /* Move to cancelled queue. */
972 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
973 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
975 /* Create the message. */
976 memcpy(msg, &blr, sizeof(blr));
977 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
979 messaging_send_buf(sconn->msg_ctx, messaging_server_id(sconn->msg_ctx),
980 MSG_SMB_BLOCKING_LOCK_CANCEL,
981 (uint8_t *)&msg, sizeof(msg));