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/globals.h"
22 #include "librpc/gen_ndr/messaging.h"
25 #define DBGC_CLASS DBGC_LOCKING
27 /****************************************************************************
28 Determine if this is a secondary element of a chained SMB.
29 **************************************************************************/
31 static void received_unlock_msg(struct messaging_context
*msg
,
34 struct server_id server_id
,
37 void brl_timeout_fn(struct event_context
*event_ctx
,
38 struct timed_event
*te
,
42 struct smbd_server_connection
*sconn
= talloc_get_type_abort(
43 private_data
, struct smbd_server_connection
);
45 if (sconn
->using_smb2
) {
46 SMB_ASSERT(sconn
->smb2
.locks
.brl_timeout
== te
);
47 TALLOC_FREE(sconn
->smb2
.locks
.brl_timeout
);
49 SMB_ASSERT(sconn
->smb1
.locks
.brl_timeout
== te
);
50 TALLOC_FREE(sconn
->smb1
.locks
.brl_timeout
);
53 change_to_root_user(); /* TODO: Possibly run all timed events as
56 process_blocking_lock_queue(sconn
);
59 /****************************************************************************
60 We need a version of timeval_min that treats zero timval as infinite.
61 ****************************************************************************/
63 struct timeval
timeval_brl_min(const struct timeval
*tv1
,
64 const struct timeval
*tv2
)
66 if (timeval_is_zero(tv1
)) {
69 if (timeval_is_zero(tv2
)) {
72 return timeval_min(tv1
, tv2
);
75 /****************************************************************************
76 After a change to blocking_lock_queue, recalculate the timed_event for the
78 ****************************************************************************/
80 static bool recalc_brl_timeout(struct smbd_server_connection
*sconn
)
82 struct blocking_lock_record
*blr
;
83 struct timeval next_timeout
;
84 int max_brl_timeout
= lp_parm_int(-1, "brl", "recalctime", 5);
86 TALLOC_FREE(sconn
->smb1
.locks
.brl_timeout
);
88 next_timeout
= timeval_zero();
90 for (blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= blr
->next
) {
91 if (timeval_is_zero(&blr
->expire_time
)) {
93 * If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is
94 * a POSIX lock, so calculate a timeout of
95 * 10 seconds into the future.
97 if (blr
->blocking_smblctx
== 0xFFFFFFFFFFFFFFFFLL
) {
98 struct timeval psx_to
= timeval_current_ofs(10, 0);
99 next_timeout
= timeval_brl_min(&next_timeout
, &psx_to
);
105 next_timeout
= timeval_brl_min(&next_timeout
, &blr
->expire_time
);
108 if (timeval_is_zero(&next_timeout
)) {
109 DEBUG(10, ("Next timeout = Infinite.\n"));
114 to account for unclean shutdowns by clients we need a
115 maximum timeout that we use for checking pending locks. If
116 we have any pending locks at all, then check if the pending
117 lock can continue at least every brl:recalctime seconds
120 This saves us needing to do a message_send_all() in the
121 SIGCHLD handler in the parent daemon. That
122 message_send_all() caused O(n^2) work to be done when IP
123 failovers happened in clustered Samba, which could make the
124 entire system unusable for many minutes.
127 if (max_brl_timeout
> 0) {
128 struct timeval min_to
= timeval_current_ofs(max_brl_timeout
, 0);
129 next_timeout
= timeval_min(&next_timeout
, &min_to
);
133 struct timeval cur
, from_now
;
135 cur
= timeval_current();
136 from_now
= timeval_until(&cur
, &next_timeout
);
137 DEBUG(10, ("Next timeout = %d.%d seconds from now.\n",
138 (int)from_now
.tv_sec
, (int)from_now
.tv_usec
));
141 sconn
->smb1
.locks
.brl_timeout
= event_add_timed(smbd_event_context(),
143 brl_timeout_fn
, sconn
);
144 if (sconn
->smb1
.locks
.brl_timeout
== NULL
) {
152 /****************************************************************************
153 Function to push a blocking lock request onto the lock queue.
154 ****************************************************************************/
156 bool push_blocking_lock_request( struct byte_range_lock
*br_lck
,
157 struct smb_request
*req
,
162 enum brl_type lock_type
,
163 enum brl_flavour lock_flav
,
166 uint64_t blocking_smblctx
)
168 struct smbd_server_connection
*sconn
= req
->sconn
;
169 struct blocking_lock_record
*blr
;
173 return push_blocking_lock_request_smb2(br_lck
,
186 if(req_is_in_chain(req
)) {
187 DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n"));
192 * Now queue an entry on the blocking lock queue. We setup
193 * the expiration time here.
196 blr
= talloc(NULL
, struct blocking_lock_record
);
198 DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
206 if (lock_timeout
== -1) {
207 blr
->expire_time
.tv_sec
= 0;
208 blr
->expire_time
.tv_usec
= 0; /* Never expire. */
210 blr
->expire_time
= timeval_current_ofs(lock_timeout
/1000,
211 (lock_timeout
% 1000) * 1000);
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
,
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
, NULL
,
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 reply_outbuf(blr
->req
, 2, 0);
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 chain_reply(blr
->req
);
282 TALLOC_FREE(blr
->req
->outbuf
);
285 /****************************************************************************
286 Return a generic lock fail error blocking call.
287 *****************************************************************************/
289 static void generic_blocking_lock_error(struct blocking_lock_record
*blr
, NTSTATUS status
)
291 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
292 FILE_LOCK_CONFLICT! (tridge) */
293 if (NT_STATUS_EQUAL(status
, NT_STATUS_LOCK_NOT_GRANTED
)) {
294 status
= NT_STATUS_FILE_LOCK_CONFLICT
;
297 if (NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
298 /* Store the last lock error. */
299 files_struct
*fsp
= blr
->fsp
;
302 fsp
->last_lock_failure
.context
.smblctx
= blr
->smblctx
;
303 fsp
->last_lock_failure
.context
.tid
= fsp
->conn
->cnum
;
304 fsp
->last_lock_failure
.context
.pid
= procid_self();
305 fsp
->last_lock_failure
.start
= blr
->offset
;
306 fsp
->last_lock_failure
.size
= blr
->count
;
307 fsp
->last_lock_failure
.fnum
= fsp
->fnum
;
308 fsp
->last_lock_failure
.lock_type
= READ_LOCK
; /* Don't care. */
309 fsp
->last_lock_failure
.lock_flav
= blr
->lock_flav
;
313 reply_nterror(blr
->req
, status
);
314 if (!srv_send_smb(smbd_server_fd(), (char *)blr
->req
->outbuf
,
315 true, blr
->req
->seqnum
+1,
316 blr
->req
->encrypted
, NULL
)) {
317 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
319 TALLOC_FREE(blr
->req
->outbuf
);
322 /****************************************************************************
323 Return a lock fail error for a lockingX call. Undo all the locks we have
325 *****************************************************************************/
327 static void reply_lockingX_error(struct blocking_lock_record
*blr
, NTSTATUS status
)
329 files_struct
*fsp
= blr
->fsp
;
330 uint16 num_ulocks
= SVAL(blr
->req
->vwv
+6, 0);
331 uint64_t count
= (uint64_t)0, offset
= (uint64_t) 0;
333 unsigned char locktype
= CVAL(blr
->req
->vwv
+3, 0);
334 bool large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
);
338 data
= (uint8_t *)blr
->req
->buf
339 + ((large_file_format
? 20 : 10)*num_ulocks
);
342 * Data now points at the beginning of the list
343 * of smb_lkrng structs.
347 * Ensure we don't do a remove on the lock that just failed,
348 * as under POSIX rules, if we have a lock already there, we
349 * will delete it (and we shouldn't) .....
352 for(i
= blr
->lock_num
- 1; i
>= 0; i
--) {
355 smblctx
= get_lock_pid( data
, i
, large_file_format
);
356 count
= get_lock_count( data
, i
, large_file_format
);
357 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
360 * We know err cannot be set as if it was the lock
361 * request would never have been queued. JRA.
364 do_unlock(fsp
->conn
->sconn
->msg_ctx
,
372 generic_blocking_lock_error(blr
, status
);
375 /****************************************************************************
376 Return a lock fail error.
377 *****************************************************************************/
379 static void blocking_lock_reply_error(struct blocking_lock_record
*blr
, NTSTATUS status
)
381 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status
), blr
));
383 switch(blr
->req
->cmd
) {
385 reply_lockingX_error(blr
, status
);
389 reply_nterror(blr
->req
, status
);
392 * construct_reply_common has done us the favor to pre-fill
393 * the command field with SMBtranss2 which is wrong :-)
395 SCVAL(blr
->req
->outbuf
,smb_com
,SMBtrans2
);
397 if (!srv_send_smb(smbd_server_fd(),
398 (char *)blr
->req
->outbuf
,
399 true, blr
->req
->seqnum
+1,
400 IS_CONN_ENCRYPTED(blr
->fsp
->conn
),
402 exit_server_cleanly("blocking_lock_reply_error: "
403 "srv_send_smb failed.");
405 TALLOC_FREE(blr
->req
->outbuf
);
408 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
409 exit_server("PANIC - unknown type on blocking lock queue");
413 /****************************************************************************
414 Attempt to finish off getting all pending blocking locks for a lockingX call.
415 Returns True if we want to be removed from the list.
416 *****************************************************************************/
418 static bool process_lockingX(struct blocking_lock_record
*blr
)
420 unsigned char locktype
= CVAL(blr
->req
->vwv
+3, 0);
421 files_struct
*fsp
= blr
->fsp
;
422 uint16 num_ulocks
= SVAL(blr
->req
->vwv
+6, 0);
423 uint16 num_locks
= SVAL(blr
->req
->vwv
+7, 0);
424 uint64_t count
= (uint64_t)0, offset
= (uint64_t)0;
426 bool large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
);
428 NTSTATUS status
= NT_STATUS_OK
;
430 data
= (uint8_t *)blr
->req
->buf
431 + ((large_file_format
? 20 : 10)*num_ulocks
);
434 * Data now points at the beginning of the list
435 * of smb_lkrng structs.
438 for(; blr
->lock_num
< num_locks
; blr
->lock_num
++) {
439 struct byte_range_lock
*br_lck
= NULL
;
442 smblctx
= get_lock_pid( data
, blr
->lock_num
, large_file_format
);
443 count
= get_lock_count( data
, blr
->lock_num
, large_file_format
);
444 offset
= get_lock_offset( data
, blr
->lock_num
, large_file_format
, &err
);
447 * We know err cannot be set as if it was the lock
448 * request would never have been queued. JRA.
451 br_lck
= do_lock(fsp
->conn
->sconn
->msg_ctx
,
456 ((locktype
& LOCKING_ANDX_SHARED_LOCK
) ?
457 READ_LOCK
: WRITE_LOCK
),
461 &blr
->blocking_smblctx
,
466 if (NT_STATUS_IS_ERR(status
)) {
471 if(blr
->lock_num
== num_locks
) {
473 * Success - we got all the locks.
476 DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d "
477 "num_locks=%d\n", fsp_str_dbg(fsp
), fsp
->fnum
,
478 (unsigned int)locktype
, num_locks
));
480 reply_lockingX_success(blr
);
484 if (!NT_STATUS_EQUAL(status
,NT_STATUS_LOCK_NOT_GRANTED
) &&
485 !NT_STATUS_EQUAL(status
,NT_STATUS_FILE_LOCK_CONFLICT
)) {
487 * We have other than a "can't get lock"
488 * error. Free any locks we had and return an error.
489 * Return True so we get dequeued.
491 blocking_lock_reply_error(blr
, status
);
496 * Still can't get all the locks - keep waiting.
499 DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
501 blr
->lock_num
, num_locks
, fsp_str_dbg(fsp
), fsp
->fnum
));
506 /****************************************************************************
507 Attempt to get the posix lock request from a SMBtrans2 call.
508 Returns True if we want to be removed from the list.
509 *****************************************************************************/
511 static bool process_trans2(struct blocking_lock_record
*blr
)
515 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
524 &blr
->blocking_smblctx
,
528 if (!NT_STATUS_IS_OK(status
)) {
529 if (ERROR_WAS_LOCK_DENIED(status
)) {
530 /* Still can't get the lock, just keep waiting. */
534 * We have other than a "can't get lock"
535 * error. Send an error and return True so we get dequeued.
537 blocking_lock_reply_error(blr
, status
);
541 /* We finally got the lock, return success. */
544 /* Fake up max_data_bytes here - we know it fits. */
545 send_trans2_replies(blr
->fsp
->conn
, blr
->req
, params
, 2, NULL
, 0, 0xffff);
550 /****************************************************************************
551 Process a blocking lock SMB.
552 Returns True if we want to be removed from the list.
553 *****************************************************************************/
555 static bool blocking_lock_record_process(struct blocking_lock_record
*blr
)
557 switch(blr
->req
->cmd
) {
559 return process_lockingX(blr
);
562 return process_trans2(blr
);
564 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
565 exit_server("PANIC - unknown type on blocking lock queue");
567 return False
; /* Keep compiler happy. */
570 /****************************************************************************
571 Cancel entries by fnum from the blocking lock pending queue.
572 Called when a file is closed.
573 *****************************************************************************/
575 void cancel_pending_lock_requests_by_fid(files_struct
*fsp
,
576 struct byte_range_lock
*br_lck
,
577 enum file_close_type close_type
)
579 struct smbd_server_connection
*sconn
= fsp
->conn
->sconn
;
580 struct blocking_lock_record
*blr
, *blr_cancelled
, *next
= NULL
;
582 if (sconn
->using_smb2
) {
583 cancel_pending_lock_requests_by_fid_smb2(fsp
,
589 for(blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= next
) {
590 unsigned char locktype
= 0;
593 if (blr
->fsp
->fnum
!= fsp
->fnum
) {
597 if (blr
->req
->cmd
== SMBlockingX
) {
598 locktype
= CVAL(blr
->req
->vwv
+3, 0);
601 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
602 "request type %d for file %s fnum = %d\n",
603 blr
->req
->cmd
, fsp_str_dbg(fsp
), fsp
->fnum
));
605 blr_cancelled
= blocking_lock_cancel_smb1(fsp
,
611 NT_STATUS_RANGE_NOT_LOCKED
);
613 SMB_ASSERT(blr_cancelled
== blr
);
615 brl_lock_cancel(br_lck
,
623 /* We're closing the file fsp here, so ensure
624 * we don't have a dangling pointer. */
629 /****************************************************************************
630 Delete entries by mid from the blocking lock pending queue. Always send reply.
631 Only called from the SMB1 cancel code.
632 *****************************************************************************/
634 void remove_pending_lock_requests_by_mid_smb1(
635 struct smbd_server_connection
*sconn
, uint64_t mid
)
637 struct blocking_lock_record
*blr
, *next
= NULL
;
639 for(blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= next
) {
641 struct byte_range_lock
*br_lck
;
645 if (blr
->req
->mid
!= mid
) {
650 br_lck
= brl_get_locks(talloc_tos(), fsp
);
653 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
654 "removing request type %d for file %s fnum "
655 "= %d\n", blr
->req
->cmd
, fsp_str_dbg(fsp
),
658 brl_lock_cancel(br_lck
,
668 blocking_lock_reply_error(blr
,NT_STATUS_FILE_LOCK_CONFLICT
);
669 DLIST_REMOVE(sconn
->smb1
.locks
.blocking_lock_queue
, blr
);
674 /****************************************************************************
675 Is this mid a blocking lock request on the queue ?
676 Currently only called from the SMB1 unix extensions POSIX lock code.
677 *****************************************************************************/
679 bool blocking_lock_was_deferred_smb1(
680 struct smbd_server_connection
*sconn
, uint64_t mid
)
682 struct blocking_lock_record
*blr
, *next
= NULL
;
684 for(blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= next
) {
686 if(blr
->req
->mid
== mid
) {
693 /****************************************************************************
694 Set a flag as an unlock request affects one of our pending locks.
695 *****************************************************************************/
697 static void received_unlock_msg(struct messaging_context
*msg
,
700 struct server_id server_id
,
703 DEBUG(10,("received_unlock_msg\n"));
704 process_blocking_lock_queue(smbd_server_conn
);
707 /****************************************************************************
708 Process the blocking lock queue. Note that this is only called as root.
709 *****************************************************************************/
711 void process_blocking_lock_queue(struct smbd_server_connection
*sconn
)
713 struct timeval tv_curr
= timeval_current();
714 struct blocking_lock_record
*blr
, *next
= NULL
;
716 if (sconn
->using_smb2
) {
717 process_blocking_lock_queue_smb2(sconn
, tv_curr
);
722 * Go through the queue and see if we can get any of the locks.
725 for (blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= next
) {
730 * Go through the remaining locks and try and obtain them.
731 * The call returns True if all locks were obtained successfully
732 * and False if we still need to wait.
735 DEBUG(10, ("Processing BLR = %p\n", blr
));
737 /* We use set_current_service so connections with
738 * pending locks are not marked as idle.
741 set_current_service(blr
->fsp
->conn
,
742 SVAL(blr
->req
->inbuf
,smb_flg
),
745 if(blocking_lock_record_process(blr
)) {
746 struct byte_range_lock
*br_lck
= brl_get_locks(
747 talloc_tos(), blr
->fsp
);
749 DEBUG(10, ("BLR_process returned true: cancelling and "
750 "removing lock. BLR = %p\n", blr
));
753 brl_lock_cancel(br_lck
,
763 DLIST_REMOVE(sconn
->smb1
.locks
.blocking_lock_queue
, blr
);
769 * We couldn't get the locks for this record on the list.
770 * If the time has expired, return a lock error.
773 if (!timeval_is_zero(&blr
->expire_time
) && timeval_compare(&blr
->expire_time
, &tv_curr
) <= 0) {
774 struct byte_range_lock
*br_lck
= brl_get_locks(
775 talloc_tos(), blr
->fsp
);
777 DEBUG(10, ("Lock timed out! BLR = %p\n", blr
));
780 * Lock expired - throw away all previously
781 * obtained locks and return lock error.
785 DEBUG(5,("process_blocking_lock_queue: "
786 "pending lock fnum = %d for file %s "
787 "timed out.\n", blr
->fsp
->fnum
,
788 fsp_str_dbg(blr
->fsp
)));
790 brl_lock_cancel(br_lck
,
800 blocking_lock_reply_error(blr
,NT_STATUS_FILE_LOCK_CONFLICT
);
801 DLIST_REMOVE(sconn
->smb1
.locks
.blocking_lock_queue
, blr
);
806 recalc_brl_timeout(sconn
);
809 /****************************************************************************
810 Handle a cancel message. Lock already moved onto the cancel queue.
811 *****************************************************************************/
813 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
815 static void process_blocking_lock_cancel_message(struct messaging_context
*ctx
,
818 struct server_id server_id
,
821 struct smbd_server_connection
*sconn
= smbd_server_conn
;
823 const char *msg
= (const char *)data
->data
;
824 struct blocking_lock_record
*blr
;
826 if (data
->data
== NULL
) {
827 smb_panic("process_blocking_lock_cancel_message: null msg");
830 if (data
->length
!= MSG_BLOCKING_LOCK_CANCEL_SIZE
) {
831 DEBUG(0, ("process_blocking_lock_cancel_message: "
832 "Got invalid msg len %d\n", (int)data
->length
));
833 smb_panic("process_blocking_lock_cancel_message: bad msg");
836 memcpy(&blr
, msg
, sizeof(blr
));
837 memcpy(&err
, &msg
[sizeof(blr
)], sizeof(NTSTATUS
));
839 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
842 blocking_lock_reply_error(blr
, err
);
843 DLIST_REMOVE(sconn
->smb1
.locks
.blocking_lock_cancelled_queue
, blr
);
847 /****************************************************************************
848 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
849 Returns the blocking_lock_record that is being cancelled.
850 Only called from the SMB1 code.
851 *****************************************************************************/
853 struct blocking_lock_record
*blocking_lock_cancel_smb1(files_struct
*fsp
,
857 enum brl_flavour lock_flav
,
858 unsigned char locktype
,
861 struct smbd_server_connection
*sconn
= fsp
->conn
->sconn
;
862 char msg
[MSG_BLOCKING_LOCK_CANCEL_SIZE
];
863 struct blocking_lock_record
*blr
;
865 if (!sconn
->smb1
.locks
.blocking_lock_cancel_state
) {
866 /* Register our message. */
867 messaging_register(smbd_messaging_context(), NULL
,
868 MSG_SMB_BLOCKING_LOCK_CANCEL
,
869 process_blocking_lock_cancel_message
);
871 sconn
->smb1
.locks
.blocking_lock_cancel_state
= True
;
874 for (blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= blr
->next
) {
875 if (fsp
== blr
->fsp
&&
876 smblctx
== blr
->smblctx
&&
877 offset
== blr
->offset
&&
878 count
== blr
->count
&&
879 lock_flav
== blr
->lock_flav
) {
888 /* Check the flags are right. */
889 if (blr
->req
->cmd
== SMBlockingX
&&
890 (locktype
& LOCKING_ANDX_LARGE_FILES
) !=
891 (CVAL(blr
->req
->vwv
+3, 0) & LOCKING_ANDX_LARGE_FILES
)) {
895 /* Move to cancelled queue. */
896 DLIST_REMOVE(sconn
->smb1
.locks
.blocking_lock_queue
, blr
);
897 DLIST_ADD(sconn
->smb1
.locks
.blocking_lock_cancelled_queue
, blr
);
899 /* Create the message. */
900 memcpy(msg
, &blr
, sizeof(blr
));
901 memcpy(&msg
[sizeof(blr
)], &err
, sizeof(NTSTATUS
));
903 messaging_send_buf(smbd_messaging_context(), procid_self(),
904 MSG_SMB_BLOCKING_LOCK_CANCEL
,
905 (uint8
*)&msg
, sizeof(msg
));