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 %s, name = %s\n",
258 (unsigned int)blr
->expire_time
.tv_sec
,
259 (unsigned int)blr
->expire_time
.tv_usec
, lock_timeout
,
260 fsp_fnum_dbg(blr
->fsp
), 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.
285 if (!srv_send_smb(req
->sconn
,
288 IS_CONN_ENCRYPTED(req
->conn
)||req
->encrypted
,
290 exit_server_cleanly("construct_reply: srv_send_smb failed.");
293 TALLOC_FREE(req
->outbuf
);
296 /****************************************************************************
297 Return a generic lock fail error blocking call.
298 *****************************************************************************/
300 static void generic_blocking_lock_error(struct blocking_lock_record
*blr
, NTSTATUS status
)
302 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
303 FILE_LOCK_CONFLICT! (tridge) */
304 if (NT_STATUS_EQUAL(status
, NT_STATUS_LOCK_NOT_GRANTED
)) {
305 status
= NT_STATUS_FILE_LOCK_CONFLICT
;
308 if (NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
309 /* Store the last lock error. */
310 files_struct
*fsp
= blr
->fsp
;
313 fsp
->last_lock_failure
.context
.smblctx
= blr
->smblctx
;
314 fsp
->last_lock_failure
.context
.tid
= fsp
->conn
->cnum
;
315 fsp
->last_lock_failure
.context
.pid
=
316 messaging_server_id(fsp
->conn
->sconn
->msg_ctx
);
317 fsp
->last_lock_failure
.start
= blr
->offset
;
318 fsp
->last_lock_failure
.size
= blr
->count
;
319 fsp
->last_lock_failure
.fnum
= fsp
->fnum
;
320 fsp
->last_lock_failure
.lock_type
= READ_LOCK
; /* Don't care. */
321 fsp
->last_lock_failure
.lock_flav
= blr
->lock_flav
;
325 reply_nterror(blr
->req
, status
);
326 if (!srv_send_smb(blr
->req
->sconn
, (char *)blr
->req
->outbuf
,
327 true, blr
->req
->seqnum
+1,
328 blr
->req
->encrypted
, NULL
)) {
329 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
331 TALLOC_FREE(blr
->req
->outbuf
);
334 /****************************************************************************
335 Return a lock fail error for a lockingX call. Undo all the locks we have
337 *****************************************************************************/
339 static void undo_locks_obtained(struct blocking_lock_record
*blr
)
341 files_struct
*fsp
= blr
->fsp
;
342 uint16 num_ulocks
= SVAL(blr
->req
->vwv
+6, 0);
343 uint64_t count
= (uint64_t)0, offset
= (uint64_t) 0;
345 unsigned char locktype
= CVAL(blr
->req
->vwv
+3, 0);
346 bool large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
);
350 data
= discard_const_p(uint8_t, blr
->req
->buf
)
351 + ((large_file_format
? 20 : 10)*num_ulocks
);
354 * Data now points at the beginning of the list
355 * of smb_lkrng structs.
359 * Ensure we don't do a remove on the lock that just failed,
360 * as under POSIX rules, if we have a lock already there, we
361 * will delete it (and we shouldn't) .....
364 for(i
= blr
->lock_num
- 1; i
>= 0; i
--) {
367 smblctx
= get_lock_pid( data
, i
, large_file_format
);
368 count
= get_lock_count( data
, i
, large_file_format
);
369 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
372 * We know err cannot be set as if it was the lock
373 * request would never have been queued. JRA.
376 do_unlock(fsp
->conn
->sconn
->msg_ctx
,
385 /****************************************************************************
386 Return a lock fail error.
387 *****************************************************************************/
389 static void blocking_lock_reply_error(struct blocking_lock_record
*blr
, NTSTATUS status
)
391 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status
), blr
));
393 switch(blr
->req
->cmd
) {
396 * This code can be called during the rundown of a
397 * file after it was already closed. In that case,
398 * blr->fsp==NULL and we do not need to undo any
399 * locks, they are already gone.
401 if (blr
->fsp
!= NULL
) {
402 undo_locks_obtained(blr
);
404 generic_blocking_lock_error(blr
, status
);
408 reply_nterror(blr
->req
, status
);
411 * construct_reply_common has done us the favor to pre-fill
412 * the command field with SMBtranss2 which is wrong :-)
414 SCVAL(blr
->req
->outbuf
,smb_com
,SMBtrans2
);
416 if (!srv_send_smb(blr
->req
->sconn
,
417 (char *)blr
->req
->outbuf
,
418 true, blr
->req
->seqnum
+1,
419 IS_CONN_ENCRYPTED(blr
->fsp
->conn
),
421 exit_server_cleanly("blocking_lock_reply_error: "
422 "srv_send_smb failed.");
424 TALLOC_FREE(blr
->req
->outbuf
);
427 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
428 exit_server("PANIC - unknown type on blocking lock queue");
432 /****************************************************************************
433 Attempt to finish off getting all pending blocking locks for a lockingX call.
434 Returns True if we want to be removed from the list.
435 *****************************************************************************/
437 static bool process_lockingX(struct blocking_lock_record
*blr
)
439 unsigned char locktype
= CVAL(blr
->req
->vwv
+3, 0);
440 files_struct
*fsp
= blr
->fsp
;
441 uint16 num_ulocks
= SVAL(blr
->req
->vwv
+6, 0);
442 uint16 num_locks
= SVAL(blr
->req
->vwv
+7, 0);
443 uint64_t count
= (uint64_t)0, offset
= (uint64_t)0;
445 bool large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
);
447 NTSTATUS status
= NT_STATUS_OK
;
449 data
= discard_const_p(uint8_t, blr
->req
->buf
)
450 + ((large_file_format
? 20 : 10)*num_ulocks
);
453 * Data now points at the beginning of the list
454 * of smb_lkrng structs.
457 for(; blr
->lock_num
< num_locks
; blr
->lock_num
++) {
458 struct byte_range_lock
*br_lck
= NULL
;
461 smblctx
= get_lock_pid( data
, blr
->lock_num
, large_file_format
);
462 count
= get_lock_count( data
, blr
->lock_num
, large_file_format
);
463 offset
= get_lock_offset( data
, blr
->lock_num
, large_file_format
, &err
);
466 * We know err cannot be set as if it was the lock
467 * request would never have been queued. JRA.
470 br_lck
= do_lock(fsp
->conn
->sconn
->msg_ctx
,
475 ((locktype
& LOCKING_ANDX_SHARED_LOCK
) ?
476 READ_LOCK
: WRITE_LOCK
),
480 &blr
->blocking_smblctx
,
485 if (NT_STATUS_IS_ERR(status
)) {
490 if(blr
->lock_num
== num_locks
) {
492 * Success - we got all the locks.
495 DEBUG(3,("process_lockingX file = %s, %s, type=%d "
496 "num_locks=%d\n", fsp_str_dbg(fsp
), fsp_fnum_dbg(fsp
),
497 (unsigned int)locktype
, num_locks
));
499 reply_lockingX_success(blr
);
503 if (!NT_STATUS_EQUAL(status
,NT_STATUS_LOCK_NOT_GRANTED
) &&
504 !NT_STATUS_EQUAL(status
,NT_STATUS_FILE_LOCK_CONFLICT
)) {
506 * We have other than a "can't get lock"
507 * error. Free any locks we had and return an error.
508 * Return True so we get dequeued.
510 blocking_lock_reply_error(blr
, status
);
515 * Still can't get all the locks - keep waiting.
518 DEBUG(10, ("process_lockingX: only got %d locks of %d needed for "
519 "file %s, %s. Waiting....\n",
520 blr
->lock_num
, num_locks
, fsp_str_dbg(fsp
),
526 /****************************************************************************
527 Attempt to get the posix lock request from a SMBtrans2 call.
528 Returns True if we want to be removed from the list.
529 *****************************************************************************/
531 static bool process_trans2(struct blocking_lock_record
*blr
)
535 struct byte_range_lock
*br_lck
= do_lock(
536 blr
->fsp
->conn
->sconn
->msg_ctx
,
545 &blr
->blocking_smblctx
,
549 if (!NT_STATUS_IS_OK(status
)) {
550 if (ERROR_WAS_LOCK_DENIED(status
)) {
551 /* Still can't get the lock, just keep waiting. */
555 * We have other than a "can't get lock"
556 * error. Send an error and return True so we get dequeued.
558 blocking_lock_reply_error(blr
, status
);
562 /* We finally got the lock, return success. */
565 /* Fake up max_data_bytes here - we know it fits. */
566 send_trans2_replies(blr
->fsp
->conn
, blr
->req
, params
, 2, NULL
, 0, 0xffff);
571 /****************************************************************************
572 Process a blocking lock SMB.
573 Returns True if we want to be removed from the list.
574 *****************************************************************************/
576 static bool blocking_lock_record_process(struct blocking_lock_record
*blr
)
578 switch(blr
->req
->cmd
) {
580 return process_lockingX(blr
);
583 return process_trans2(blr
);
585 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
586 exit_server("PANIC - unknown type on blocking lock queue");
588 return False
; /* Keep compiler happy. */
591 /****************************************************************************
592 Cancel entries by fnum from the blocking lock pending queue.
593 Called when a file is closed.
594 *****************************************************************************/
596 void smbd_cancel_pending_lock_requests_by_fid(files_struct
*fsp
,
597 struct byte_range_lock
*br_lck
,
598 enum file_close_type close_type
)
600 struct smbd_server_connection
*sconn
= fsp
->conn
->sconn
;
601 struct blocking_lock_record
*blr
, *blr_cancelled
, *next
= NULL
;
603 if (sconn
->using_smb2
) {
604 cancel_pending_lock_requests_by_fid_smb2(fsp
,
610 for(blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= next
) {
611 unsigned char locktype
= 0;
614 if (blr
->fsp
->fnum
!= fsp
->fnum
) {
618 if (blr
->req
->cmd
== SMBlockingX
) {
619 locktype
= CVAL(blr
->req
->vwv
+3, 0);
622 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
623 "request type %d for file %s, %s\n",
624 blr
->req
->cmd
, fsp_str_dbg(fsp
), fsp_fnum_dbg(fsp
)));
626 blr_cancelled
= blocking_lock_cancel_smb1(fsp
,
632 NT_STATUS_RANGE_NOT_LOCKED
);
634 SMB_ASSERT(blr_cancelled
== blr
);
636 brl_lock_cancel(br_lck
,
638 messaging_server_id(sconn
->msg_ctx
),
644 /* We're closing the file fsp here, so ensure
645 * we don't have a dangling pointer. */
650 /****************************************************************************
651 Delete entries by mid from the blocking lock pending queue. Always send reply.
652 Only called from the SMB1 cancel code.
653 *****************************************************************************/
655 void remove_pending_lock_requests_by_mid_smb1(
656 struct smbd_server_connection
*sconn
, uint64_t mid
)
658 struct blocking_lock_record
*blr
, *next
= NULL
;
660 for(blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= next
) {
662 struct byte_range_lock
*br_lck
;
666 if (blr
->req
->mid
!= mid
) {
671 br_lck
= brl_get_locks(talloc_tos(), fsp
);
674 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
675 "removing request type %d for file %s, %s\n",
676 blr
->req
->cmd
, fsp_str_dbg(fsp
),
679 brl_lock_cancel(br_lck
,
681 messaging_server_id(sconn
->msg_ctx
),
689 blocking_lock_reply_error(blr
,NT_STATUS_FILE_LOCK_CONFLICT
);
690 DLIST_REMOVE(sconn
->smb1
.locks
.blocking_lock_queue
, blr
);
695 /****************************************************************************
696 Is this mid a blocking lock request on the queue ?
697 Currently only called from the SMB1 unix extensions POSIX lock code.
698 *****************************************************************************/
700 bool blocking_lock_was_deferred_smb1(
701 struct smbd_server_connection
*sconn
, uint64_t mid
)
703 struct blocking_lock_record
*blr
, *next
= NULL
;
705 for(blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= next
) {
707 if(blr
->req
->mid
== mid
) {
714 /****************************************************************************
715 Set a flag as an unlock request affects one of our pending locks.
716 *****************************************************************************/
718 static void received_unlock_msg(struct messaging_context
*msg
,
721 struct server_id server_id
,
724 struct smbd_server_connection
*sconn
=
725 talloc_get_type_abort(private_data
,
726 struct smbd_server_connection
);
728 DEBUG(10,("received_unlock_msg\n"));
729 process_blocking_lock_queue(sconn
);
732 /****************************************************************************
733 Process the blocking lock queue. Note that this is only called as root.
734 *****************************************************************************/
736 void process_blocking_lock_queue(struct smbd_server_connection
*sconn
)
738 struct timeval tv_curr
= timeval_current();
739 struct blocking_lock_record
*blr
, *next
= NULL
;
741 if (sconn
->using_smb2
) {
742 process_blocking_lock_queue_smb2(sconn
, tv_curr
);
747 * Go through the queue and see if we can get any of the locks.
750 for (blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= next
) {
755 * Go through the remaining locks and try and obtain them.
756 * The call returns True if all locks were obtained successfully
757 * and False if we still need to wait.
760 DEBUG(10, ("Processing BLR = %p\n", blr
));
762 /* We use set_current_service so connections with
763 * pending locks are not marked as idle.
766 set_current_service(blr
->fsp
->conn
,
767 SVAL(blr
->req
->inbuf
,smb_flg
),
770 if(blocking_lock_record_process(blr
)) {
771 struct byte_range_lock
*br_lck
= brl_get_locks(
772 talloc_tos(), blr
->fsp
);
774 DEBUG(10, ("BLR_process returned true: cancelling and "
775 "removing lock. BLR = %p\n", blr
));
778 brl_lock_cancel(br_lck
,
780 messaging_server_id(sconn
->msg_ctx
),
788 DLIST_REMOVE(sconn
->smb1
.locks
.blocking_lock_queue
, blr
);
794 * We couldn't get the locks for this record on the list.
795 * If the time has expired, return a lock error.
798 if (!timeval_is_zero(&blr
->expire_time
) && timeval_compare(&blr
->expire_time
, &tv_curr
) <= 0) {
799 struct byte_range_lock
*br_lck
= brl_get_locks(
800 talloc_tos(), blr
->fsp
);
802 DEBUG(10, ("Lock timed out! BLR = %p\n", blr
));
805 * Lock expired - throw away all previously
806 * obtained locks and return lock error.
810 DEBUG(5,("process_blocking_lock_queue: "
811 "pending lock for %s, file %s "
812 "timed out.\n", fsp_fnum_dbg(blr
->fsp
),
813 fsp_str_dbg(blr
->fsp
)));
815 brl_lock_cancel(br_lck
,
817 messaging_server_id(sconn
->msg_ctx
),
825 blocking_lock_reply_error(blr
,NT_STATUS_FILE_LOCK_CONFLICT
);
826 DLIST_REMOVE(sconn
->smb1
.locks
.blocking_lock_queue
, blr
);
831 recalc_brl_timeout(sconn
);
834 /****************************************************************************
835 Handle a cancel message. Lock already moved onto the cancel queue.
836 *****************************************************************************/
838 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
840 static void process_blocking_lock_cancel_message(struct messaging_context
*ctx
,
843 struct server_id server_id
,
847 const char *msg
= (const char *)data
->data
;
848 struct blocking_lock_record
*blr
;
849 struct smbd_server_connection
*sconn
=
850 talloc_get_type_abort(private_data
,
851 struct smbd_server_connection
);
853 if (data
->data
== NULL
) {
854 smb_panic("process_blocking_lock_cancel_message: null msg");
857 if (data
->length
!= MSG_BLOCKING_LOCK_CANCEL_SIZE
) {
858 DEBUG(0, ("process_blocking_lock_cancel_message: "
859 "Got invalid msg len %d\n", (int)data
->length
));
860 smb_panic("process_blocking_lock_cancel_message: bad msg");
863 memcpy(&blr
, msg
, sizeof(blr
));
864 memcpy(&err
, &msg
[sizeof(blr
)], sizeof(NTSTATUS
));
866 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
869 blocking_lock_reply_error(blr
, err
);
870 DLIST_REMOVE(sconn
->smb1
.locks
.blocking_lock_cancelled_queue
, blr
);
874 /****************************************************************************
875 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
876 Returns the blocking_lock_record that is being cancelled.
877 Only called from the SMB1 code.
878 *****************************************************************************/
880 struct blocking_lock_record
*blocking_lock_cancel_smb1(files_struct
*fsp
,
884 enum brl_flavour lock_flav
,
885 unsigned char locktype
,
888 struct smbd_server_connection
*sconn
= fsp
->conn
->sconn
;
889 char msg
[MSG_BLOCKING_LOCK_CANCEL_SIZE
];
890 struct blocking_lock_record
*blr
;
892 if (!sconn
->smb1
.locks
.blocking_lock_cancel_state
) {
893 /* Register our message. */
894 messaging_register(sconn
->msg_ctx
, sconn
,
895 MSG_SMB_BLOCKING_LOCK_CANCEL
,
896 process_blocking_lock_cancel_message
);
898 sconn
->smb1
.locks
.blocking_lock_cancel_state
= True
;
901 for (blr
= sconn
->smb1
.locks
.blocking_lock_queue
; blr
; blr
= blr
->next
) {
902 if (fsp
== blr
->fsp
&&
903 smblctx
== blr
->smblctx
&&
904 offset
== blr
->offset
&&
905 count
== blr
->count
&&
906 lock_flav
== blr
->lock_flav
) {
915 /* Check the flags are right. */
916 if (blr
->req
->cmd
== SMBlockingX
&&
917 (locktype
& LOCKING_ANDX_LARGE_FILES
) !=
918 (CVAL(blr
->req
->vwv
+3, 0) & LOCKING_ANDX_LARGE_FILES
)) {
922 /* Move to cancelled queue. */
923 DLIST_REMOVE(sconn
->smb1
.locks
.blocking_lock_queue
, blr
);
924 DLIST_ADD(sconn
->smb1
.locks
.blocking_lock_cancelled_queue
, blr
);
926 /* Create the message. */
927 memcpy(msg
, &blr
, sizeof(blr
));
928 memcpy(&msg
[sizeof(blr
)], &err
, sizeof(NTSTATUS
));
930 messaging_send_buf(sconn
->msg_ctx
, messaging_server_id(sconn
->msg_ctx
),
931 MSG_SMB_BLOCKING_LOCK_CANCEL
,
932 (uint8
*)&msg
, sizeof(msg
));