s3:vlp: fix build on OS X
[Samba.git] / source3 / smbd / blocking.c
blob3a45a275aa8c0281a133bf18d67996c50f415c6b
1 /*
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/>.
20 #include "includes.h"
21 #include "smbd/smbd.h"
22 #include "smbd/globals.h"
23 #include "messages.h"
25 #undef DBGC_CLASS
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,
33 void *private_data,
34 uint32_t msg_type,
35 struct server_id server_id,
36 DATA_BLOB *data);
38 void brl_timeout_fn(struct event_context *event_ctx,
39 struct timed_event *te,
40 struct timeval now,
41 void *private_data)
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);
49 } else {
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
55 * root */
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)) {
68 return *tv2;
70 if (timeval_is_zero(tv2)) {
71 return *tv1;
73 return timeval_min(tv1, tv2);
76 /****************************************************************************
77 After a change to blocking_lock_queue, recalculate the timed_event for the
78 next processing.
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);
103 continue;
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"));
111 return True;
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
119 (default 5 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);
133 if (DEBUGLVL(10)) {
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,
143 NULL, next_timeout,
144 brl_timeout_fn, sconn);
145 if (sconn->smb1.locks.brl_timeout == NULL) {
146 return False;
149 return True;
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,
159 files_struct *fsp,
160 int lock_timeout,
161 int lock_num,
162 uint64_t smblctx,
163 enum brl_type lock_type,
164 enum brl_flavour lock_flav,
165 uint64_t offset,
166 uint64_t count,
167 uint64_t blocking_smblctx)
169 struct smbd_server_connection *sconn = req->sconn;
170 struct blocking_lock_record *blr;
171 NTSTATUS status;
173 if (req->smb2req) {
174 return push_blocking_lock_request_smb2(br_lck,
175 req,
176 fsp,
177 lock_timeout,
178 lock_num,
179 smblctx,
180 lock_type,
181 lock_flav,
182 offset,
183 count,
184 blocking_smblctx);
187 if(req_is_in_chain(req)) {
188 DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n"));
189 return False;
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);
198 if (blr == NULL) {
199 DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
200 return False;
203 blr->next = NULL;
204 blr->prev = NULL;
206 blr->fsp = fsp;
207 if (lock_timeout == -1) {
208 blr->expire_time.tv_sec = 0;
209 blr->expire_time.tv_usec = 0; /* Never expire. */
210 } else {
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;
219 blr->count = count;
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,
226 br_lck,
227 smblctx,
228 messaging_server_id(req->sconn->msg_ctx),
229 offset,
230 count,
231 lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
232 blr->lock_flav,
233 True,
234 NULL,
235 blr);
237 if (!NT_STATUS_IS_OK(status)) {
238 DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
239 TALLOC_FREE(blr);
240 return False;
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)));
262 return True;
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,
286 (char *)req->outbuf,
287 true, req->seqnum+1,
288 IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
289 &req->pcd)) {
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;
312 if (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
336 obtained first.
337 *****************************************************************************/
339 static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS status)
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;
344 uint64_t smblctx;
345 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
346 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
347 uint8_t *data;
348 int i;
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--) {
365 bool err;
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,
377 fsp,
378 smblctx,
379 count,
380 offset,
381 WINDOWS_LOCK);
384 generic_blocking_lock_error(blr, status);
387 /****************************************************************************
388 Return a lock fail error.
389 *****************************************************************************/
391 static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
393 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
395 switch(blr->req->cmd) {
396 case SMBlockingX:
397 reply_lockingX_error(blr, status);
398 break;
399 case SMBtrans2:
400 case SMBtranss2:
401 reply_nterror(blr->req, status);
404 * construct_reply_common has done us the favor to pre-fill
405 * the command field with SMBtranss2 which is wrong :-)
407 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
409 if (!srv_send_smb(blr->req->sconn,
410 (char *)blr->req->outbuf,
411 true, blr->req->seqnum+1,
412 IS_CONN_ENCRYPTED(blr->fsp->conn),
413 NULL)) {
414 exit_server_cleanly("blocking_lock_reply_error: "
415 "srv_send_smb failed.");
417 TALLOC_FREE(blr->req->outbuf);
418 break;
419 default:
420 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
421 exit_server("PANIC - unknown type on blocking lock queue");
425 /****************************************************************************
426 Attempt to finish off getting all pending blocking locks for a lockingX call.
427 Returns True if we want to be removed from the list.
428 *****************************************************************************/
430 static bool process_lockingX(struct blocking_lock_record *blr)
432 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
433 files_struct *fsp = blr->fsp;
434 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
435 uint16 num_locks = SVAL(blr->req->vwv+7, 0);
436 uint64_t count = (uint64_t)0, offset = (uint64_t)0;
437 uint64_t smblctx;
438 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
439 uint8_t *data;
440 NTSTATUS status = NT_STATUS_OK;
442 data = discard_const_p(uint8_t, blr->req->buf)
443 + ((large_file_format ? 20 : 10)*num_ulocks);
446 * Data now points at the beginning of the list
447 * of smb_lkrng structs.
450 for(; blr->lock_num < num_locks; blr->lock_num++) {
451 struct byte_range_lock *br_lck = NULL;
452 bool err;
454 smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
455 count = get_lock_count( data, blr->lock_num, large_file_format);
456 offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
459 * We know err cannot be set as if it was the lock
460 * request would never have been queued. JRA.
462 errno = 0;
463 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
464 fsp,
465 smblctx,
466 count,
467 offset,
468 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
469 READ_LOCK : WRITE_LOCK),
470 WINDOWS_LOCK,
471 True,
472 &status,
473 &blr->blocking_smblctx,
474 blr);
476 TALLOC_FREE(br_lck);
478 if (NT_STATUS_IS_ERR(status)) {
479 break;
483 if(blr->lock_num == num_locks) {
485 * Success - we got all the locks.
488 DEBUG(3,("process_lockingX file = %s, %s, type=%d "
489 "num_locks=%d\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
490 (unsigned int)locktype, num_locks));
492 reply_lockingX_success(blr);
493 return True;
496 if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
497 !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
499 * We have other than a "can't get lock"
500 * error. Free any locks we had and return an error.
501 * Return True so we get dequeued.
503 blocking_lock_reply_error(blr, status);
504 return True;
508 * Still can't get all the locks - keep waiting.
511 DEBUG(10, ("process_lockingX: only got %d locks of %d needed for "
512 "file %s, %s. Waiting....\n",
513 blr->lock_num, num_locks, fsp_str_dbg(fsp),
514 fsp_fnum_dbg(fsp)));
516 return False;
519 /****************************************************************************
520 Attempt to get the posix lock request from a SMBtrans2 call.
521 Returns True if we want to be removed from the list.
522 *****************************************************************************/
524 static bool process_trans2(struct blocking_lock_record *blr)
526 char params[2];
527 NTSTATUS status;
528 struct byte_range_lock *br_lck = do_lock(
529 blr->fsp->conn->sconn->msg_ctx,
530 blr->fsp,
531 blr->smblctx,
532 blr->count,
533 blr->offset,
534 blr->lock_type,
535 blr->lock_flav,
536 True,
537 &status,
538 &blr->blocking_smblctx,
539 blr);
540 TALLOC_FREE(br_lck);
542 if (!NT_STATUS_IS_OK(status)) {
543 if (ERROR_WAS_LOCK_DENIED(status)) {
544 /* Still can't get the lock, just keep waiting. */
545 return False;
548 * We have other than a "can't get lock"
549 * error. Send an error and return True so we get dequeued.
551 blocking_lock_reply_error(blr, status);
552 return True;
555 /* We finally got the lock, return success. */
557 SSVAL(params,0,0);
558 /* Fake up max_data_bytes here - we know it fits. */
559 send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff);
560 return True;
564 /****************************************************************************
565 Process a blocking lock SMB.
566 Returns True if we want to be removed from the list.
567 *****************************************************************************/
569 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
571 switch(blr->req->cmd) {
572 case SMBlockingX:
573 return process_lockingX(blr);
574 case SMBtrans2:
575 case SMBtranss2:
576 return process_trans2(blr);
577 default:
578 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
579 exit_server("PANIC - unknown type on blocking lock queue");
581 return False; /* Keep compiler happy. */
584 /****************************************************************************
585 Cancel entries by fnum from the blocking lock pending queue.
586 Called when a file is closed.
587 *****************************************************************************/
589 void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp,
590 struct byte_range_lock *br_lck,
591 enum file_close_type close_type)
593 struct smbd_server_connection *sconn = fsp->conn->sconn;
594 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
596 if (sconn->using_smb2) {
597 cancel_pending_lock_requests_by_fid_smb2(fsp,
598 br_lck,
599 close_type);
600 return;
603 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
604 unsigned char locktype = 0;
606 next = blr->next;
607 if (blr->fsp->fnum != fsp->fnum) {
608 continue;
611 if (blr->req->cmd == SMBlockingX) {
612 locktype = CVAL(blr->req->vwv+3, 0);
615 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
616 "request type %d for file %s, %s\n",
617 blr->req->cmd, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
619 blr_cancelled = blocking_lock_cancel_smb1(fsp,
620 blr->smblctx,
621 blr->offset,
622 blr->count,
623 blr->lock_flav,
624 locktype,
625 NT_STATUS_RANGE_NOT_LOCKED);
627 SMB_ASSERT(blr_cancelled == blr);
629 brl_lock_cancel(br_lck,
630 blr->smblctx,
631 messaging_server_id(sconn->msg_ctx),
632 blr->offset,
633 blr->count,
634 blr->lock_flav,
635 blr);
637 /* We're closing the file fsp here, so ensure
638 * we don't have a dangling pointer. */
639 blr->fsp = NULL;
643 /****************************************************************************
644 Delete entries by mid from the blocking lock pending queue. Always send reply.
645 Only called from the SMB1 cancel code.
646 *****************************************************************************/
648 void remove_pending_lock_requests_by_mid_smb1(
649 struct smbd_server_connection *sconn, uint64_t mid)
651 struct blocking_lock_record *blr, *next = NULL;
653 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
654 files_struct *fsp;
655 struct byte_range_lock *br_lck;
657 next = blr->next;
659 if (blr->req->mid != mid) {
660 continue;
663 fsp = blr->fsp;
664 br_lck = brl_get_locks(talloc_tos(), fsp);
666 if (br_lck) {
667 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
668 "removing request type %d for file %s, %s\n",
669 blr->req->cmd, fsp_str_dbg(fsp),
670 fsp_fnum_dbg(fsp)));
672 brl_lock_cancel(br_lck,
673 blr->smblctx,
674 messaging_server_id(sconn->msg_ctx),
675 blr->offset,
676 blr->count,
677 blr->lock_flav,
678 blr);
679 TALLOC_FREE(br_lck);
682 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
683 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
684 TALLOC_FREE(blr);
688 /****************************************************************************
689 Is this mid a blocking lock request on the queue ?
690 Currently only called from the SMB1 unix extensions POSIX lock code.
691 *****************************************************************************/
693 bool blocking_lock_was_deferred_smb1(
694 struct smbd_server_connection *sconn, uint64_t mid)
696 struct blocking_lock_record *blr, *next = NULL;
698 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
699 next = blr->next;
700 if(blr->req->mid == mid) {
701 return True;
704 return False;
707 /****************************************************************************
708 Set a flag as an unlock request affects one of our pending locks.
709 *****************************************************************************/
711 static void received_unlock_msg(struct messaging_context *msg,
712 void *private_data,
713 uint32_t msg_type,
714 struct server_id server_id,
715 DATA_BLOB *data)
717 struct smbd_server_connection *sconn =
718 talloc_get_type_abort(private_data,
719 struct smbd_server_connection);
721 DEBUG(10,("received_unlock_msg\n"));
722 process_blocking_lock_queue(sconn);
725 /****************************************************************************
726 Process the blocking lock queue. Note that this is only called as root.
727 *****************************************************************************/
729 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
731 struct timeval tv_curr = timeval_current();
732 struct blocking_lock_record *blr, *next = NULL;
734 if (sconn->using_smb2) {
735 process_blocking_lock_queue_smb2(sconn, tv_curr);
736 return;
740 * Go through the queue and see if we can get any of the locks.
743 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
745 next = blr->next;
748 * Go through the remaining locks and try and obtain them.
749 * The call returns True if all locks were obtained successfully
750 * and False if we still need to wait.
753 DEBUG(10, ("Processing BLR = %p\n", blr));
755 /* We use set_current_service so connections with
756 * pending locks are not marked as idle.
759 set_current_service(blr->fsp->conn,
760 SVAL(blr->req->inbuf,smb_flg),
761 false);
763 if(blocking_lock_record_process(blr)) {
764 struct byte_range_lock *br_lck = brl_get_locks(
765 talloc_tos(), blr->fsp);
767 DEBUG(10, ("BLR_process returned true: cancelling and "
768 "removing lock. BLR = %p\n", blr));
770 if (br_lck) {
771 brl_lock_cancel(br_lck,
772 blr->smblctx,
773 messaging_server_id(sconn->msg_ctx),
774 blr->offset,
775 blr->count,
776 blr->lock_flav,
777 blr);
778 TALLOC_FREE(br_lck);
781 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
782 TALLOC_FREE(blr);
783 continue;
787 * We couldn't get the locks for this record on the list.
788 * If the time has expired, return a lock error.
791 if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
792 struct byte_range_lock *br_lck = brl_get_locks(
793 talloc_tos(), blr->fsp);
795 DEBUG(10, ("Lock timed out! BLR = %p\n", blr));
798 * Lock expired - throw away all previously
799 * obtained locks and return lock error.
802 if (br_lck) {
803 DEBUG(5,("process_blocking_lock_queue: "
804 "pending lock for %s, file %s "
805 "timed out.\n", fsp_fnum_dbg(blr->fsp),
806 fsp_str_dbg(blr->fsp)));
808 brl_lock_cancel(br_lck,
809 blr->smblctx,
810 messaging_server_id(sconn->msg_ctx),
811 blr->offset,
812 blr->count,
813 blr->lock_flav,
814 blr);
815 TALLOC_FREE(br_lck);
818 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
819 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
820 TALLOC_FREE(blr);
824 recalc_brl_timeout(sconn);
827 /****************************************************************************
828 Handle a cancel message. Lock already moved onto the cancel queue.
829 *****************************************************************************/
831 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
833 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
834 void *private_data,
835 uint32_t msg_type,
836 struct server_id server_id,
837 DATA_BLOB *data)
839 NTSTATUS err;
840 const char *msg = (const char *)data->data;
841 struct blocking_lock_record *blr;
842 struct smbd_server_connection *sconn =
843 talloc_get_type_abort(private_data,
844 struct smbd_server_connection);
846 if (data->data == NULL) {
847 smb_panic("process_blocking_lock_cancel_message: null msg");
850 if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
851 DEBUG(0, ("process_blocking_lock_cancel_message: "
852 "Got invalid msg len %d\n", (int)data->length));
853 smb_panic("process_blocking_lock_cancel_message: bad msg");
856 memcpy(&blr, msg, sizeof(blr));
857 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
859 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
860 nt_errstr(err) ));
862 blocking_lock_reply_error(blr, err);
863 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
864 TALLOC_FREE(blr);
867 /****************************************************************************
868 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
869 Returns the blocking_lock_record that is being cancelled.
870 Only called from the SMB1 code.
871 *****************************************************************************/
873 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
874 uint64_t smblctx,
875 uint64_t offset,
876 uint64_t count,
877 enum brl_flavour lock_flav,
878 unsigned char locktype,
879 NTSTATUS err)
881 struct smbd_server_connection *sconn = fsp->conn->sconn;
882 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
883 struct blocking_lock_record *blr;
885 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
886 /* Register our message. */
887 messaging_register(sconn->msg_ctx, sconn,
888 MSG_SMB_BLOCKING_LOCK_CANCEL,
889 process_blocking_lock_cancel_message);
891 sconn->smb1.locks.blocking_lock_cancel_state = True;
894 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
895 if (fsp == blr->fsp &&
896 smblctx == blr->smblctx &&
897 offset == blr->offset &&
898 count == blr->count &&
899 lock_flav == blr->lock_flav) {
900 break;
904 if (!blr) {
905 return NULL;
908 /* Check the flags are right. */
909 if (blr->req->cmd == SMBlockingX &&
910 (locktype & LOCKING_ANDX_LARGE_FILES) !=
911 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
912 return NULL;
915 /* Move to cancelled queue. */
916 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
917 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
919 /* Create the message. */
920 memcpy(msg, &blr, sizeof(blr));
921 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
923 messaging_send_buf(sconn->msg_ctx, messaging_server_id(sconn->msg_ctx),
924 MSG_SMB_BLOCKING_LOCK_CANCEL,
925 (uint8 *)&msg, sizeof(msg));
927 return blr;