47ac4cc4021bd5f1de6e79f43c0f7e635cbd3e89
[Samba.git] / source3 / smbd / blocking.c
blob47ac4cc4021bd5f1de6e79f43c0f7e635cbd3e89
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 static void received_unlock_msg(struct messaging_context *msg,
29 void *private_data,
30 uint32_t msg_type,
31 struct server_id server_id,
32 DATA_BLOB *data);
34 void brl_timeout_fn(struct tevent_context *event_ctx,
35 struct tevent_timer *te,
36 struct timeval now,
37 void *private_data)
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);
45 } else {
46 SMB_ASSERT(sconn->smb1.locks.brl_timeout == te);
47 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
50 change_to_root_user(); /* TODO: Possibly run all timed events as
51 * root */
53 process_blocking_lock_queue(sconn);
56 /****************************************************************************
57 We need a version of timeval_min that treats zero timval as infinite.
58 ****************************************************************************/
60 struct timeval timeval_brl_min(const struct timeval *tv1,
61 const struct timeval *tv2)
63 if (timeval_is_zero(tv1)) {
64 return *tv2;
66 if (timeval_is_zero(tv2)) {
67 return *tv1;
69 return timeval_min(tv1, tv2);
72 /****************************************************************************
73 After a change to blocking_lock_queue, recalculate the timed_event for the
74 next processing.
75 ****************************************************************************/
77 static bool recalc_brl_timeout(struct smbd_server_connection *sconn)
79 struct blocking_lock_record *blr;
80 struct timeval next_timeout;
81 int max_brl_timeout = lp_parm_int(-1, "brl", "recalctime", 5);
83 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
85 next_timeout = timeval_zero();
87 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
88 if (timeval_is_zero(&blr->expire_time)) {
90 * If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is
91 * a POSIX lock, so calculate a timeout of
92 * 10 seconds into the future.
94 if (blr->blocking_smblctx == 0xFFFFFFFFFFFFFFFFLL) {
95 struct timeval psx_to = timeval_current_ofs(10, 0);
96 next_timeout = timeval_brl_min(&next_timeout, &psx_to);
99 continue;
102 next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time);
105 if (timeval_is_zero(&next_timeout)) {
106 DEBUG(10, ("Next timeout = Infinite.\n"));
107 return True;
111 to account for unclean shutdowns by clients we need a
112 maximum timeout that we use for checking pending locks. If
113 we have any pending locks at all, then check if the pending
114 lock can continue at least every brl:recalctime seconds
115 (default 5 seconds).
117 This saves us needing to do a message_send_all() in the
118 SIGCHLD handler in the parent daemon. That
119 message_send_all() caused O(n^2) work to be done when IP
120 failovers happened in clustered Samba, which could make the
121 entire system unusable for many minutes.
124 if (max_brl_timeout > 0) {
125 struct timeval min_to = timeval_current_ofs(max_brl_timeout, 0);
126 next_timeout = timeval_min(&next_timeout, &min_to);
129 if (DEBUGLVL(10)) {
130 struct timeval cur, from_now;
132 cur = timeval_current();
133 from_now = timeval_until(&cur, &next_timeout);
134 DEBUG(10, ("Next timeout = %d.%d seconds from now.\n",
135 (int)from_now.tv_sec, (int)from_now.tv_usec));
138 sconn->smb1.locks.brl_timeout = tevent_add_timer(sconn->ev_ctx,
139 NULL, next_timeout,
140 brl_timeout_fn, sconn);
141 if (sconn->smb1.locks.brl_timeout == NULL) {
142 return False;
145 return True;
149 /****************************************************************************
150 Function to push a blocking lock request onto the lock queue.
151 ****************************************************************************/
153 bool push_blocking_lock_request( struct byte_range_lock *br_lck,
154 struct smb_request *req,
155 files_struct *fsp,
156 int lock_timeout,
157 int lock_num,
158 uint64_t smblctx,
159 enum brl_type lock_type,
160 enum brl_flavour lock_flav,
161 uint64_t offset,
162 uint64_t count,
163 uint64_t blocking_smblctx)
165 struct smbd_server_connection *sconn = req->sconn;
166 struct blocking_lock_record *blr;
167 NTSTATUS status;
169 if (req->smb2req) {
170 return push_blocking_lock_request_smb2(br_lck,
171 req,
172 fsp,
173 lock_timeout,
174 lock_num,
175 smblctx,
176 lock_type,
177 lock_flav,
178 offset,
179 count,
180 blocking_smblctx);
183 if(req_is_in_chain(req)) {
184 DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n"));
185 return False;
189 * Now queue an entry on the blocking lock queue. We setup
190 * the expiration time here.
193 blr = talloc(NULL, struct blocking_lock_record);
194 if (blr == NULL) {
195 DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
196 return False;
199 blr->next = NULL;
200 blr->prev = NULL;
202 blr->fsp = fsp;
203 if (lock_timeout == -1) {
204 blr->expire_time.tv_sec = 0;
205 blr->expire_time.tv_usec = 0; /* Never expire. */
206 } else {
207 blr->expire_time = timeval_current_ofs_msec(lock_timeout);
209 blr->lock_num = lock_num;
210 blr->smblctx = smblctx;
211 blr->blocking_smblctx = blocking_smblctx;
212 blr->lock_flav = lock_flav;
213 blr->lock_type = lock_type;
214 blr->offset = offset;
215 blr->count = count;
217 /* Specific brl_lock() implementations can fill this in. */
218 blr->blr_private = NULL;
220 /* Add a pending lock record for this. */
221 status = brl_lock(req->sconn->msg_ctx,
222 br_lck,
223 smblctx,
224 messaging_server_id(req->sconn->msg_ctx),
225 offset,
226 count,
227 lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
228 blr->lock_flav,
229 True,
230 NULL);
232 if (!NT_STATUS_IS_OK(status)) {
233 DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
234 TALLOC_FREE(blr);
235 return False;
238 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd);
239 blr->req = talloc_move(blr, &req);
241 DLIST_ADD_END(sconn->smb1.locks.blocking_lock_queue, blr, struct blocking_lock_record *);
242 recalc_brl_timeout(sconn);
244 /* Ensure we'll receive messages when this is unlocked. */
245 if (!sconn->smb1.locks.blocking_lock_unlock_state) {
246 messaging_register(sconn->msg_ctx, sconn,
247 MSG_SMB_UNLOCK, received_unlock_msg);
248 sconn->smb1.locks.blocking_lock_unlock_state = true;
251 DEBUG(3,("push_blocking_lock_request: lock request blocked with "
252 "expiry time (%u sec. %u usec) (+%d msec) for %s, name = %s\n",
253 (unsigned int)blr->expire_time.tv_sec,
254 (unsigned int)blr->expire_time.tv_usec, lock_timeout,
255 fsp_fnum_dbg(blr->fsp), fsp_str_dbg(blr->fsp)));
257 return True;
260 /****************************************************************************
261 Return a lockingX success SMB.
262 *****************************************************************************/
264 static void reply_lockingX_success(struct blocking_lock_record *blr)
266 struct smb_request *req = blr->req;
268 reply_outbuf(req, 2, 0);
269 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
270 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
273 * As this message is a lockingX call we must handle
274 * any following chained message correctly.
275 * This is normally handled in construct_reply(),
276 * but as that calls switch_message, we can't use
277 * that here and must set up the chain info manually.
280 if (!srv_send_smb(req->sconn,
281 (char *)req->outbuf,
282 true, req->seqnum+1,
283 IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
284 &req->pcd)) {
285 exit_server_cleanly("construct_reply: srv_send_smb failed.");
288 TALLOC_FREE(req->outbuf);
291 /****************************************************************************
292 Return a generic lock fail error blocking call.
293 *****************************************************************************/
295 static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
297 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
298 FILE_LOCK_CONFLICT! (tridge) */
299 if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
300 status = NT_STATUS_FILE_LOCK_CONFLICT;
303 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
304 /* Store the last lock error. */
305 files_struct *fsp = blr->fsp;
307 if (fsp) {
308 fsp->last_lock_failure.context.smblctx = blr->smblctx;
309 fsp->last_lock_failure.context.tid = fsp->conn->cnum;
310 fsp->last_lock_failure.context.pid =
311 messaging_server_id(fsp->conn->sconn->msg_ctx);
312 fsp->last_lock_failure.start = blr->offset;
313 fsp->last_lock_failure.size = blr->count;
314 fsp->last_lock_failure.fnum = fsp->fnum;
315 fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
316 fsp->last_lock_failure.lock_flav = blr->lock_flav;
320 reply_nterror(blr->req, status);
321 if (!srv_send_smb(blr->req->sconn, (char *)blr->req->outbuf,
322 true, blr->req->seqnum+1,
323 blr->req->encrypted, NULL)) {
324 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
326 TALLOC_FREE(blr->req->outbuf);
329 /****************************************************************************
330 Return a lock fail error for a lockingX call. Undo all the locks we have
331 obtained first.
332 *****************************************************************************/
334 static void undo_locks_obtained(struct blocking_lock_record *blr)
336 files_struct *fsp = blr->fsp;
337 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
338 uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
339 uint64_t smblctx;
340 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
341 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
342 uint8_t *data;
343 int i;
345 data = discard_const_p(uint8_t, blr->req->buf)
346 + ((large_file_format ? 20 : 10)*num_ulocks);
349 * Data now points at the beginning of the list
350 * of smb_lkrng structs.
354 * Ensure we don't do a remove on the lock that just failed,
355 * as under POSIX rules, if we have a lock already there, we
356 * will delete it (and we shouldn't) .....
359 for(i = blr->lock_num - 1; i >= 0; i--) {
360 bool err;
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, &err);
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,
372 fsp,
373 smblctx,
374 count,
375 offset,
376 WINDOWS_LOCK);
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) {
389 case SMBlockingX:
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);
400 break;
401 case SMBtrans2:
402 case SMBtranss2:
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->sconn,
412 (char *)blr->req->outbuf,
413 true, blr->req->seqnum+1,
414 IS_CONN_ENCRYPTED(blr->fsp->conn),
415 NULL)) {
416 exit_server_cleanly("blocking_lock_reply_error: "
417 "srv_send_smb failed.");
419 TALLOC_FREE(blr->req->outbuf);
420 break;
421 default:
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) {
441 return true;
443 return false;
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 num_ulocks = SVAL(blr->req->vwv+6, 0);
456 uint16 num_locks = SVAL(blr->req->vwv+7, 0);
457 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
458 uint8_t *data;
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;
472 bool err;
475 * Ensure the blr record gets updated with
476 * any lock we might end up blocked on.
479 blr->smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
480 blr->count = get_lock_count( data, blr->lock_num, large_file_format);
481 blr->offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
484 * We know err cannot be set as if it was the lock
485 * request would never have been queued. JRA.
487 errno = 0;
488 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
489 fsp,
490 blr->smblctx,
491 blr->count,
492 blr->offset,
493 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
494 READ_LOCK : WRITE_LOCK),
495 WINDOWS_LOCK,
496 True,
497 &status,
498 &blr->blocking_smblctx);
500 if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
502 * If we didn't timeout, but still need to wait,
503 * re-add the pending lock entry whilst holding
504 * the brlock db lock.
506 NTSTATUS status1 =
507 brl_lock(blr->fsp->conn->sconn->msg_ctx,
508 br_lck,
509 blr->smblctx,
510 messaging_server_id(
511 blr->fsp->conn->sconn->msg_ctx),
512 blr->offset,
513 blr->count,
514 blr->lock_type == READ_LOCK ?
515 PENDING_READ_LOCK :
516 PENDING_WRITE_LOCK,
517 blr->lock_flav,
518 true, /* Blocking lock. */
519 NULL);
521 if (!NT_STATUS_IS_OK(status1)) {
522 DEBUG(0,("failed to add PENDING_LOCK "
523 "record.\n"));
527 TALLOC_FREE(br_lck);
529 if (NT_STATUS_IS_ERR(status)) {
530 break;
534 if(blr->lock_num == num_locks) {
536 * Success - we got all the locks.
539 DEBUG(3,("process_lockingX file = %s, %s, type=%d "
540 "num_locks=%d\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
541 (unsigned int)locktype, num_locks));
543 reply_lockingX_success(blr);
544 return True;
547 if (!ERROR_WAS_LOCK_DENIED(status)) {
549 * We have other than a "can't get lock"
550 * error. Free any locks we had and return an error.
551 * Return True so we get dequeued.
553 blocking_lock_reply_error(blr, status);
554 return True;
558 * Return an error to the client if we timed out.
560 if (lock_timeout) {
561 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
562 return true;
566 * Still can't get all the locks - keep waiting.
569 DEBUG(10, ("process_lockingX: only got %d locks of %d needed for "
570 "file %s, %s. Waiting....\n",
571 blr->lock_num, num_locks, fsp_str_dbg(fsp),
572 fsp_fnum_dbg(fsp)));
574 return False;
577 /****************************************************************************
578 Attempt to get the posix lock request from a SMBtrans2 call.
579 Returns True if we want to be removed from the list.
580 *****************************************************************************/
582 static bool process_trans2(struct blocking_lock_record *blr)
584 char params[2];
585 NTSTATUS status;
586 bool lock_timeout = lock_timed_out(blr);
588 struct byte_range_lock *br_lck = do_lock(
589 blr->fsp->conn->sconn->msg_ctx,
590 blr->fsp,
591 blr->smblctx,
592 blr->count,
593 blr->offset,
594 blr->lock_type,
595 blr->lock_flav,
596 True,
597 &status,
598 &blr->blocking_smblctx);
599 if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
601 * If we didn't timeout, but still need to wait,
602 * re-add the pending lock entry whilst holding
603 * the brlock db lock.
605 NTSTATUS status1 =
606 brl_lock(blr->fsp->conn->sconn->msg_ctx,
607 br_lck,
608 blr->smblctx,
609 messaging_server_id(
610 blr->fsp->conn->sconn->msg_ctx),
611 blr->offset,
612 blr->count,
613 blr->lock_type == READ_LOCK ?
614 PENDING_READ_LOCK :
615 PENDING_WRITE_LOCK,
616 blr->lock_flav,
617 true, /* Blocking lock. */
618 NULL);
620 if (!NT_STATUS_IS_OK(status1)) {
621 DEBUG(0,("failed to add PENDING_LOCK record.\n"));
625 TALLOC_FREE(br_lck);
627 if (!NT_STATUS_IS_OK(status)) {
628 if (ERROR_WAS_LOCK_DENIED(status)) {
629 if (lock_timeout) {
631 * Return an error if we timed out
632 * and return true to get dequeued.
634 blocking_lock_reply_error(blr,
635 NT_STATUS_FILE_LOCK_CONFLICT);
636 return true;
638 /* Still can't get the lock, just keep waiting. */
639 return False;
642 * We have other than a "can't get lock"
643 * error. Send an error and return True so we get dequeued.
645 blocking_lock_reply_error(blr, status);
646 return True;
649 /* We finally got the lock, return success. */
651 SSVAL(params,0,0);
652 /* Fake up max_data_bytes here - we know it fits. */
653 send_trans2_replies(blr->fsp->conn, blr->req, NT_STATUS_OK, params, 2, NULL, 0, 0xffff);
654 return True;
658 /****************************************************************************
659 Process a blocking lock SMB.
660 Returns True if we want to be removed from the list.
661 *****************************************************************************/
663 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
665 switch(blr->req->cmd) {
666 case SMBlockingX:
667 return process_lockingX(blr);
668 case SMBtrans2:
669 case SMBtranss2:
670 return process_trans2(blr);
671 default:
672 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
673 exit_server("PANIC - unknown type on blocking lock queue");
675 return False; /* Keep compiler happy. */
678 /****************************************************************************
679 Cancel entries by fnum from the blocking lock pending queue.
680 Called when a file is closed.
681 *****************************************************************************/
683 void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp,
684 struct byte_range_lock *br_lck,
685 enum file_close_type close_type)
687 struct smbd_server_connection *sconn = fsp->conn->sconn;
688 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
690 if (sconn->using_smb2) {
691 cancel_pending_lock_requests_by_fid_smb2(fsp,
692 br_lck,
693 close_type);
694 return;
697 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
698 unsigned char locktype = 0;
700 next = blr->next;
701 if (blr->fsp->fnum != fsp->fnum) {
702 continue;
705 if (blr->req->cmd == SMBlockingX) {
706 locktype = CVAL(blr->req->vwv+3, 0);
709 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
710 "request type %d for file %s, %s\n",
711 blr->req->cmd, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
713 blr_cancelled = blocking_lock_cancel_smb1(fsp,
714 blr->smblctx,
715 blr->offset,
716 blr->count,
717 blr->lock_flav,
718 locktype,
719 NT_STATUS_RANGE_NOT_LOCKED);
721 SMB_ASSERT(blr_cancelled == blr);
723 brl_lock_cancel(br_lck,
724 blr->smblctx,
725 messaging_server_id(sconn->msg_ctx),
726 blr->offset,
727 blr->count,
728 blr->lock_flav);
730 /* We're closing the file fsp here, so ensure
731 * we don't have a dangling pointer. */
732 blr->fsp = NULL;
736 /****************************************************************************
737 Delete entries by mid from the blocking lock pending queue. Always send reply.
738 Only called from the SMB1 cancel code.
739 *****************************************************************************/
741 void remove_pending_lock_requests_by_mid_smb1(
742 struct smbd_server_connection *sconn, uint64_t mid)
744 struct blocking_lock_record *blr, *next = NULL;
746 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
747 files_struct *fsp;
748 struct byte_range_lock *br_lck;
750 next = blr->next;
752 if (blr->req->mid != mid) {
753 continue;
756 fsp = blr->fsp;
757 br_lck = brl_get_locks(talloc_tos(), fsp);
759 if (br_lck) {
760 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
761 "removing request type %d for file %s, %s\n",
762 blr->req->cmd, fsp_str_dbg(fsp),
763 fsp_fnum_dbg(fsp)));
765 brl_lock_cancel(br_lck,
766 blr->smblctx,
767 messaging_server_id(sconn->msg_ctx),
768 blr->offset,
769 blr->count,
770 blr->lock_flav);
771 TALLOC_FREE(br_lck);
774 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
775 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
776 TALLOC_FREE(blr);
780 /****************************************************************************
781 Is this mid a blocking lock request on the queue ?
782 Currently only called from the SMB1 unix extensions POSIX lock code.
783 *****************************************************************************/
785 bool blocking_lock_was_deferred_smb1(
786 struct smbd_server_connection *sconn, uint64_t mid)
788 struct blocking_lock_record *blr, *next = NULL;
790 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
791 next = blr->next;
792 if(blr->req->mid == mid) {
793 return True;
796 return False;
799 /****************************************************************************
800 Set a flag as an unlock request affects one of our pending locks.
801 *****************************************************************************/
803 static void received_unlock_msg(struct messaging_context *msg,
804 void *private_data,
805 uint32_t msg_type,
806 struct server_id server_id,
807 DATA_BLOB *data)
809 struct smbd_server_connection *sconn =
810 talloc_get_type_abort(private_data,
811 struct smbd_server_connection);
813 DEBUG(10,("received_unlock_msg\n"));
814 process_blocking_lock_queue(sconn);
817 /****************************************************************************
818 Process the blocking lock queue. Note that this is only called as root.
819 *****************************************************************************/
821 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
823 struct blocking_lock_record *blr, *next = NULL;
825 if (sconn->using_smb2) {
826 process_blocking_lock_queue_smb2(sconn, timeval_current());
827 return;
831 * Go through the queue and see if we can get any of the locks.
834 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
835 struct byte_range_lock *br_lck = NULL;
837 next = blr->next;
840 * Go through the remaining locks and try and obtain them.
841 * The call returns True if all locks were obtained successfully
842 * and False if we still need to wait.
845 DEBUG(10, ("Processing BLR = %p\n", blr));
847 /* We use set_current_service so connections with
848 * pending locks are not marked as idle.
851 set_current_service(blr->fsp->conn,
852 SVAL(blr->req->inbuf,smb_flg),
853 false);
856 * Remove the pending lock we're waiting on.
857 * If we need to keep waiting blocking_lock_record_process()
858 * will re-add it.
861 br_lck = brl_get_locks(talloc_tos(), blr->fsp);
862 if (br_lck) {
863 brl_lock_cancel(br_lck,
864 blr->smblctx,
865 messaging_server_id(sconn->msg_ctx),
866 blr->offset,
867 blr->count,
868 blr->lock_flav);
870 TALLOC_FREE(br_lck);
872 if(!blocking_lock_record_process(blr)) {
873 DEBUG(10, ("still waiting for lock. BLR = %p\n", blr));
874 continue;
877 DEBUG(10, ("BLR_process returned true: removing BLR = %p\n",
878 blr));
880 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
881 TALLOC_FREE(blr);
884 recalc_brl_timeout(sconn);
887 /****************************************************************************
888 Handle a cancel message. Lock already moved onto the cancel queue.
889 *****************************************************************************/
891 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
893 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
894 void *private_data,
895 uint32_t msg_type,
896 struct server_id server_id,
897 DATA_BLOB *data)
899 NTSTATUS err;
900 const char *msg = (const char *)data->data;
901 struct blocking_lock_record *blr;
902 struct smbd_server_connection *sconn =
903 talloc_get_type_abort(private_data,
904 struct smbd_server_connection);
906 if (data->data == NULL) {
907 smb_panic("process_blocking_lock_cancel_message: null msg");
910 if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
911 DEBUG(0, ("process_blocking_lock_cancel_message: "
912 "Got invalid msg len %d\n", (int)data->length));
913 smb_panic("process_blocking_lock_cancel_message: bad msg");
916 memcpy(&blr, msg, sizeof(blr));
917 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
919 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
920 nt_errstr(err) ));
922 blocking_lock_reply_error(blr, err);
923 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
924 TALLOC_FREE(blr);
927 /****************************************************************************
928 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
929 Returns the blocking_lock_record that is being cancelled.
930 Only called from the SMB1 code.
931 *****************************************************************************/
933 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
934 uint64_t smblctx,
935 uint64_t offset,
936 uint64_t count,
937 enum brl_flavour lock_flav,
938 unsigned char locktype,
939 NTSTATUS err)
941 struct smbd_server_connection *sconn = fsp->conn->sconn;
942 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
943 struct blocking_lock_record *blr;
945 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
946 /* Register our message. */
947 messaging_register(sconn->msg_ctx, sconn,
948 MSG_SMB_BLOCKING_LOCK_CANCEL,
949 process_blocking_lock_cancel_message);
951 sconn->smb1.locks.blocking_lock_cancel_state = True;
954 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
955 if (fsp == blr->fsp &&
956 smblctx == blr->smblctx &&
957 offset == blr->offset &&
958 count == blr->count &&
959 lock_flav == blr->lock_flav) {
960 break;
964 if (!blr) {
965 return NULL;
968 /* Check the flags are right. */
969 if (blr->req->cmd == SMBlockingX &&
970 (locktype & LOCKING_ANDX_LARGE_FILES) !=
971 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
972 return NULL;
975 /* Move to cancelled queue. */
976 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
977 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
979 /* Create the message. */
980 memcpy(msg, &blr, sizeof(blr));
981 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
983 messaging_send_buf(sconn->msg_ctx, messaging_server_id(sconn->msg_ctx),
984 MSG_SMB_BLOCKING_LOCK_CANCEL,
985 (uint8 *)&msg, sizeof(msg));
987 return blr;