VERSION: Bump version up to 4.9.2...
[Samba.git] / source3 / smbd / blocking.c
blobc281aae619de4416d5f72d2c3659a4dd84b7dcc2
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));
139 * brl_timeout_fn() calls change_to_root_user()
140 * so we can use sconn->root_ev_ctx.
142 sconn->smb1.locks.brl_timeout = tevent_add_timer(sconn->root_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);
236 if (!NT_STATUS_IS_OK(status)) {
237 DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
238 TALLOC_FREE(blr);
239 return False;
242 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd);
243 blr->req = talloc_move(blr, &req);
245 DLIST_ADD_END(sconn->smb1.locks.blocking_lock_queue, blr);
246 recalc_brl_timeout(sconn);
248 /* Ensure we'll receive messages when this is unlocked. */
249 if (!sconn->smb1.locks.blocking_lock_unlock_state) {
250 messaging_register(sconn->msg_ctx, sconn,
251 MSG_SMB_UNLOCK, received_unlock_msg);
252 sconn->smb1.locks.blocking_lock_unlock_state = true;
255 DEBUG(3,("push_blocking_lock_request: lock request blocked with "
256 "expiry time (%u sec. %u usec) (+%d msec) for %s, name = %s\n",
257 (unsigned int)blr->expire_time.tv_sec,
258 (unsigned int)blr->expire_time.tv_usec, lock_timeout,
259 fsp_fnum_dbg(blr->fsp), fsp_str_dbg(blr->fsp)));
261 return True;
264 /****************************************************************************
265 Return a lockingX success SMB.
266 *****************************************************************************/
268 static void reply_lockingX_success(struct blocking_lock_record *blr)
270 struct smb_request *req = blr->req;
272 reply_outbuf(req, 2, 0);
273 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
274 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
277 * As this message is a lockingX call we must handle
278 * any following chained message correctly.
279 * This is normally handled in construct_reply(),
280 * but as that calls switch_message, we can't use
281 * that here and must set up the chain info manually.
284 if (!srv_send_smb(req->xconn,
285 (char *)req->outbuf,
286 true, req->seqnum+1,
287 IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
288 &req->pcd)) {
289 exit_server_cleanly("construct_reply: srv_send_smb failed.");
292 TALLOC_FREE(req->outbuf);
295 /****************************************************************************
296 Return a generic lock fail error blocking call.
297 *****************************************************************************/
299 static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
301 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
302 FILE_LOCK_CONFLICT! (tridge) */
303 if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
304 status = NT_STATUS_FILE_LOCK_CONFLICT;
307 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
308 /* Store the last lock error. */
309 files_struct *fsp = blr->fsp;
311 if (fsp) {
312 fsp->last_lock_failure.context.smblctx = blr->smblctx;
313 fsp->last_lock_failure.context.tid = fsp->conn->cnum;
314 fsp->last_lock_failure.context.pid =
315 messaging_server_id(fsp->conn->sconn->msg_ctx);
316 fsp->last_lock_failure.start = blr->offset;
317 fsp->last_lock_failure.size = blr->count;
318 fsp->last_lock_failure.fnum = fsp->fnum;
319 fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
320 fsp->last_lock_failure.lock_flav = blr->lock_flav;
324 reply_nterror(blr->req, status);
325 if (!srv_send_smb(blr->req->xconn, (char *)blr->req->outbuf,
326 true, blr->req->seqnum+1,
327 blr->req->encrypted, NULL)) {
328 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
330 TALLOC_FREE(blr->req->outbuf);
333 /****************************************************************************
334 Return a lock fail error for a lockingX call. Undo all the locks we have
335 obtained first.
336 *****************************************************************************/
338 static void undo_locks_obtained(struct blocking_lock_record *blr)
340 files_struct *fsp = blr->fsp;
341 uint16_t num_ulocks = SVAL(blr->req->vwv+6, 0);
342 uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
343 uint64_t smblctx;
344 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
345 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
346 uint8_t *data;
347 int i;
349 data = discard_const_p(uint8_t, blr->req->buf)
350 + ((large_file_format ? 20 : 10)*num_ulocks);
353 * Data now points at the beginning of the list
354 * of smb_lkrng structs.
358 * Ensure we don't do a remove on the lock that just failed,
359 * as under POSIX rules, if we have a lock already there, we
360 * will delete it (and we shouldn't) .....
363 for(i = blr->lock_num - 1; i >= 0; i--) {
365 smblctx = get_lock_pid( data, i, large_file_format);
366 count = get_lock_count( data, i, large_file_format);
367 offset = get_lock_offset( data, i, large_file_format);
370 * We know err cannot be set as if it was the lock
371 * request would never have been queued. JRA.
374 do_unlock(fsp->conn->sconn->msg_ctx,
375 fsp,
376 smblctx,
377 count,
378 offset,
379 WINDOWS_LOCK);
383 /****************************************************************************
384 Return a lock fail error.
385 *****************************************************************************/
387 static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
389 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
391 switch(blr->req->cmd) {
392 case SMBlockingX:
394 * This code can be called during the rundown of a
395 * file after it was already closed. In that case,
396 * blr->fsp==NULL and we do not need to undo any
397 * locks, they are already gone.
399 if (blr->fsp != NULL) {
400 undo_locks_obtained(blr);
402 generic_blocking_lock_error(blr, status);
403 break;
404 case SMBtrans2:
405 case SMBtranss2:
406 reply_nterror(blr->req, status);
409 * construct_reply_common has done us the favor to pre-fill
410 * the command field with SMBtranss2 which is wrong :-)
412 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
414 if (!srv_send_smb(blr->req->xconn,
415 (char *)blr->req->outbuf,
416 true, blr->req->seqnum+1,
417 IS_CONN_ENCRYPTED(blr->fsp->conn),
418 NULL)) {
419 exit_server_cleanly("blocking_lock_reply_error: "
420 "srv_send_smb failed.");
422 TALLOC_FREE(blr->req->outbuf);
423 break;
424 default:
425 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
426 exit_server("PANIC - unknown type on blocking lock queue");
430 /****************************************************************************
431 Utility function that returns true if a lock timed out.
432 *****************************************************************************/
434 static bool lock_timed_out(const struct blocking_lock_record *blr)
436 struct timeval tv_curr;
438 if (timeval_is_zero(&blr->expire_time)) {
439 return false; /* Never times out. */
442 tv_curr = timeval_current();
443 if (timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
444 return true;
446 return false;
449 /****************************************************************************
450 Attempt to finish off getting all pending blocking locks for a lockingX call.
451 Returns True if we want to be removed from the list.
452 *****************************************************************************/
454 static bool process_lockingX(struct blocking_lock_record *blr)
456 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
457 files_struct *fsp = blr->fsp;
458 uint16_t num_ulocks = SVAL(blr->req->vwv+6, 0);
459 uint16_t num_locks = SVAL(blr->req->vwv+7, 0);
460 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
461 uint8_t *data;
462 NTSTATUS status = NT_STATUS_OK;
463 bool lock_timeout = lock_timed_out(blr);
465 data = discard_const_p(uint8_t, blr->req->buf)
466 + ((large_file_format ? 20 : 10)*num_ulocks);
469 * Data now points at the beginning of the list
470 * of smb_lkrng structs.
473 for(; blr->lock_num < num_locks; blr->lock_num++) {
474 struct byte_range_lock *br_lck = NULL;
477 * Ensure the blr record gets updated with
478 * any lock we might end up blocked on.
481 blr->smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
482 blr->count = get_lock_count( data, blr->lock_num, large_file_format);
483 blr->offset = get_lock_offset( data, blr->lock_num, large_file_format);
486 * We know err cannot be set as if it was the lock
487 * request would never have been queued. JRA.
489 errno = 0;
490 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
491 fsp,
492 blr->smblctx,
493 blr->count,
494 blr->offset,
495 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
496 READ_LOCK : WRITE_LOCK),
497 WINDOWS_LOCK,
498 True,
499 &status,
500 &blr->blocking_smblctx);
502 if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
504 * If we didn't timeout, but still need to wait,
505 * re-add the pending lock entry whilst holding
506 * the brlock db lock.
508 NTSTATUS status1 =
509 brl_lock(blr->fsp->conn->sconn->msg_ctx,
510 br_lck,
511 blr->smblctx,
512 messaging_server_id(
513 blr->fsp->conn->sconn->msg_ctx),
514 blr->offset,
515 blr->count,
516 blr->lock_type == READ_LOCK ?
517 PENDING_READ_LOCK :
518 PENDING_WRITE_LOCK,
519 blr->lock_flav,
520 true, /* Blocking lock. */
521 NULL);
523 if (!NT_STATUS_IS_OK(status1)) {
524 DEBUG(0,("failed to add PENDING_LOCK "
525 "record.\n"));
529 TALLOC_FREE(br_lck);
531 if (NT_STATUS_IS_ERR(status)) {
532 break;
536 if(blr->lock_num == num_locks) {
538 * Success - we got all the locks.
541 DEBUG(3,("process_lockingX file = %s, %s, type=%d "
542 "num_locks=%d\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
543 (unsigned int)locktype, num_locks));
545 reply_lockingX_success(blr);
546 return True;
549 if (!ERROR_WAS_LOCK_DENIED(status)) {
551 * We have other than a "can't get lock"
552 * error. Free any locks we had and return an error.
553 * Return True so we get dequeued.
555 blocking_lock_reply_error(blr, status);
556 return True;
560 * Return an error to the client if we timed out.
562 if (lock_timeout) {
563 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
564 return true;
568 * Still can't get all the locks - keep waiting.
571 DEBUG(10, ("process_lockingX: only got %d locks of %d needed for "
572 "file %s, %s. Waiting....\n",
573 blr->lock_num, num_locks, fsp_str_dbg(fsp),
574 fsp_fnum_dbg(fsp)));
576 return False;
579 /****************************************************************************
580 Attempt to get the posix lock request from a SMBtrans2 call.
581 Returns True if we want to be removed from the list.
582 *****************************************************************************/
584 static bool process_trans2(struct blocking_lock_record *blr)
586 char params[2];
587 NTSTATUS status;
588 bool lock_timeout = lock_timed_out(blr);
590 struct byte_range_lock *br_lck = do_lock(
591 blr->fsp->conn->sconn->msg_ctx,
592 blr->fsp,
593 blr->smblctx,
594 blr->count,
595 blr->offset,
596 blr->lock_type,
597 blr->lock_flav,
598 True,
599 &status,
600 &blr->blocking_smblctx);
601 if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
603 * If we didn't timeout, but still need to wait,
604 * re-add the pending lock entry whilst holding
605 * the brlock db lock.
607 NTSTATUS status1 =
608 brl_lock(blr->fsp->conn->sconn->msg_ctx,
609 br_lck,
610 blr->smblctx,
611 messaging_server_id(
612 blr->fsp->conn->sconn->msg_ctx),
613 blr->offset,
614 blr->count,
615 blr->lock_type == READ_LOCK ?
616 PENDING_READ_LOCK :
617 PENDING_WRITE_LOCK,
618 blr->lock_flav,
619 true, /* Blocking lock. */
620 NULL);
622 if (!NT_STATUS_IS_OK(status1)) {
623 DEBUG(0,("failed to add PENDING_LOCK record.\n"));
627 TALLOC_FREE(br_lck);
629 if (!NT_STATUS_IS_OK(status)) {
630 if (ERROR_WAS_LOCK_DENIED(status)) {
631 if (lock_timeout) {
633 * Return an error if we timed out
634 * and return true to get dequeued.
636 blocking_lock_reply_error(blr,
637 NT_STATUS_FILE_LOCK_CONFLICT);
638 return true;
640 /* Still can't get the lock, just keep waiting. */
641 return False;
644 * We have other than a "can't get lock"
645 * error. Send an error and return True so we get dequeued.
647 blocking_lock_reply_error(blr, status);
648 return True;
651 /* We finally got the lock, return success. */
653 SSVAL(params,0,0);
654 /* Fake up max_data_bytes here - we know it fits. */
655 send_trans2_replies(blr->fsp->conn, blr->req, NT_STATUS_OK, params, 2, NULL, 0, 0xffff);
656 return True;
660 /****************************************************************************
661 Process a blocking lock SMB.
662 Returns True if we want to be removed from the list.
663 *****************************************************************************/
665 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
667 switch(blr->req->cmd) {
668 case SMBlockingX:
669 return process_lockingX(blr);
670 case SMBtrans2:
671 case SMBtranss2:
672 return process_trans2(blr);
673 default:
674 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
675 exit_server("PANIC - unknown type on blocking lock queue");
677 return False; /* Keep compiler happy. */
680 /****************************************************************************
681 Cancel entries by fnum from the blocking lock pending queue.
682 Called when a file is closed.
683 *****************************************************************************/
685 void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp,
686 struct byte_range_lock *br_lck,
687 enum file_close_type close_type)
689 struct smbd_server_connection *sconn = fsp->conn->sconn;
690 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
692 if (sconn->using_smb2) {
693 cancel_pending_lock_requests_by_fid_smb2(fsp,
694 br_lck,
695 close_type);
696 return;
699 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
700 unsigned char locktype = 0;
702 next = blr->next;
703 if (blr->fsp->fnum != fsp->fnum) {
704 continue;
707 if (blr->req->cmd == SMBlockingX) {
708 locktype = CVAL(blr->req->vwv+3, 0);
711 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
712 "request type %d for file %s, %s\n",
713 blr->req->cmd, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
715 blr_cancelled = blocking_lock_cancel_smb1(fsp,
716 blr->smblctx,
717 blr->offset,
718 blr->count,
719 blr->lock_flav,
720 locktype,
721 NT_STATUS_RANGE_NOT_LOCKED);
723 SMB_ASSERT(blr_cancelled == blr);
725 brl_lock_cancel(br_lck,
726 blr->smblctx,
727 messaging_server_id(sconn->msg_ctx),
728 blr->offset,
729 blr->count,
730 blr->lock_flav);
732 /* We're closing the file fsp here, so ensure
733 * we don't have a dangling pointer. */
734 blr->fsp = NULL;
738 /****************************************************************************
739 Delete entries by mid from the blocking lock pending queue. Always send reply.
740 Only called from the SMB1 cancel code.
741 *****************************************************************************/
743 void remove_pending_lock_requests_by_mid_smb1(
744 struct smbd_server_connection *sconn, uint64_t mid)
746 struct blocking_lock_record *blr, *next = NULL;
748 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
749 files_struct *fsp;
750 struct byte_range_lock *br_lck;
752 next = blr->next;
754 if (blr->req->mid != mid) {
755 continue;
758 fsp = blr->fsp;
759 br_lck = brl_get_locks(talloc_tos(), fsp);
761 if (br_lck) {
762 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
763 "removing request type %d for file %s, %s\n",
764 blr->req->cmd, fsp_str_dbg(fsp),
765 fsp_fnum_dbg(fsp)));
767 brl_lock_cancel(br_lck,
768 blr->smblctx,
769 messaging_server_id(sconn->msg_ctx),
770 blr->offset,
771 blr->count,
772 blr->lock_flav);
773 TALLOC_FREE(br_lck);
776 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
777 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
778 TALLOC_FREE(blr);
782 /****************************************************************************
783 Is this mid a blocking lock request on the queue ?
784 Currently only called from the SMB1 unix extensions POSIX lock code.
785 *****************************************************************************/
787 bool blocking_lock_was_deferred_smb1(
788 struct smbd_server_connection *sconn, uint64_t mid)
790 struct blocking_lock_record *blr, *next = NULL;
792 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
793 next = blr->next;
794 if(blr->req->mid == mid) {
795 return True;
798 return False;
801 /****************************************************************************
802 Set a flag as an unlock request affects one of our pending locks.
803 *****************************************************************************/
805 static void received_unlock_msg(struct messaging_context *msg,
806 void *private_data,
807 uint32_t msg_type,
808 struct server_id server_id,
809 DATA_BLOB *data)
811 struct smbd_server_connection *sconn =
812 talloc_get_type_abort(private_data,
813 struct smbd_server_connection);
815 DEBUG(10,("received_unlock_msg\n"));
816 process_blocking_lock_queue(sconn);
819 /****************************************************************************
820 Process the blocking lock queue. Note that this is only called as root.
821 *****************************************************************************/
823 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
825 struct blocking_lock_record *blr, *next = NULL;
827 if (sconn->using_smb2) {
828 process_blocking_lock_queue_smb2(sconn, timeval_current());
829 return;
833 * Go through the queue and see if we can get any of the locks.
836 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
837 struct byte_range_lock *br_lck = NULL;
839 next = blr->next;
842 * Go through the remaining locks and try and obtain them.
843 * The call returns True if all locks were obtained successfully
844 * and False if we still need to wait.
847 DEBUG(10, ("Processing BLR = %p\n", blr));
850 * Connections with pending locks are not marked as idle.
852 blr->fsp->conn->lastused_count++;
855 * Remove the pending lock we're waiting on.
856 * If we need to keep waiting blocking_lock_record_process()
857 * will re-add it.
860 br_lck = brl_get_locks(talloc_tos(), blr->fsp);
861 if (br_lck) {
862 brl_lock_cancel(br_lck,
863 blr->smblctx,
864 messaging_server_id(sconn->msg_ctx),
865 blr->offset,
866 blr->count,
867 blr->lock_flav);
869 TALLOC_FREE(br_lck);
871 if(!blocking_lock_record_process(blr)) {
872 DEBUG(10, ("still waiting for lock. BLR = %p\n", blr));
873 continue;
876 DEBUG(10, ("BLR_process returned true: removing BLR = %p\n",
877 blr));
879 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
880 TALLOC_FREE(blr);
883 recalc_brl_timeout(sconn);
886 /****************************************************************************
887 Handle a cancel message. Lock already moved onto the cancel queue.
888 *****************************************************************************/
890 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
892 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
893 void *private_data,
894 uint32_t msg_type,
895 struct server_id server_id,
896 DATA_BLOB *data)
898 NTSTATUS err;
899 const char *msg = (const char *)data->data;
900 struct blocking_lock_record *blr;
901 struct smbd_server_connection *sconn =
902 talloc_get_type_abort(private_data,
903 struct smbd_server_connection);
905 if (data->data == NULL) {
906 smb_panic("process_blocking_lock_cancel_message: null msg");
909 if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
910 DEBUG(0, ("process_blocking_lock_cancel_message: "
911 "Got invalid msg len %d\n", (int)data->length));
912 smb_panic("process_blocking_lock_cancel_message: bad msg");
915 memcpy(&blr, msg, sizeof(blr));
916 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
918 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
919 nt_errstr(err) ));
921 blocking_lock_reply_error(blr, err);
922 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
923 TALLOC_FREE(blr);
926 /****************************************************************************
927 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
928 Returns the blocking_lock_record that is being cancelled.
929 Only called from the SMB1 code.
930 *****************************************************************************/
932 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
933 uint64_t smblctx,
934 uint64_t offset,
935 uint64_t count,
936 enum brl_flavour lock_flav,
937 unsigned char locktype,
938 NTSTATUS err)
940 struct smbd_server_connection *sconn = fsp->conn->sconn;
941 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
942 struct blocking_lock_record *blr;
944 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
945 /* Register our message. */
946 messaging_register(sconn->msg_ctx, sconn,
947 MSG_SMB_BLOCKING_LOCK_CANCEL,
948 process_blocking_lock_cancel_message);
950 sconn->smb1.locks.blocking_lock_cancel_state = True;
953 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
954 if (fsp == blr->fsp &&
955 smblctx == blr->smblctx &&
956 offset == blr->offset &&
957 count == blr->count &&
958 lock_flav == blr->lock_flav) {
959 break;
963 if (!blr) {
964 return NULL;
967 /* Check the flags are right. */
968 if (blr->req->cmd == SMBlockingX &&
969 (locktype & LOCKING_ANDX_LARGE_FILES) !=
970 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
971 return NULL;
974 /* Move to cancelled queue. */
975 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
976 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
978 /* Create the message. */
979 memcpy(msg, &blr, sizeof(blr));
980 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
982 messaging_send_buf(sconn->msg_ctx, messaging_server_id(sconn->msg_ctx),
983 MSG_SMB_BLOCKING_LOCK_CANCEL,
984 (uint8_t *)&msg, sizeof(msg));
986 return blr;