auth: Make sure that creds_out is initialized with NULL.
[Samba.git] / source3 / smbd / blocking.c
blob71320841fba130ad014c6d77b53e35aa962f3d82
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 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;
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);
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) {
394 case SMBlockingX:
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);
405 break;
406 case SMBtrans2:
407 case SMBtranss2:
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),
420 NULL)) {
421 exit_server_cleanly("blocking_lock_reply_error: "
422 "srv_send_smb failed.");
424 TALLOC_FREE(blr->req->outbuf);
425 break;
426 default:
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 Utility function that returns true if a lock timed out.
434 *****************************************************************************/
436 static bool lock_timed_out(const struct blocking_lock_record *blr)
438 struct timeval tv_curr;
440 if (timeval_is_zero(&blr->expire_time)) {
441 return false; /* Never times out. */
444 tv_curr = timeval_current();
445 if (timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
446 return true;
448 return false;
451 /****************************************************************************
452 Attempt to finish off getting all pending blocking locks for a lockingX call.
453 Returns True if we want to be removed from the list.
454 *****************************************************************************/
456 static bool process_lockingX(struct blocking_lock_record *blr)
458 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
459 files_struct *fsp = blr->fsp;
460 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
461 uint16 num_locks = SVAL(blr->req->vwv+7, 0);
462 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
463 uint8_t *data;
464 NTSTATUS status = NT_STATUS_OK;
465 bool lock_timeout = lock_timed_out(blr);
467 data = discard_const_p(uint8_t, blr->req->buf)
468 + ((large_file_format ? 20 : 10)*num_ulocks);
471 * Data now points at the beginning of the list
472 * of smb_lkrng structs.
475 for(; blr->lock_num < num_locks; blr->lock_num++) {
476 struct byte_range_lock *br_lck = NULL;
477 bool err;
480 * Ensure the blr record gets updated with
481 * any lock we might end up blocked on.
484 blr->smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
485 blr->count = get_lock_count( data, blr->lock_num, large_file_format);
486 blr->offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
489 * We know err cannot be set as if it was the lock
490 * request would never have been queued. JRA.
492 errno = 0;
493 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
494 fsp,
495 blr->smblctx,
496 blr->count,
497 blr->offset,
498 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
499 READ_LOCK : WRITE_LOCK),
500 WINDOWS_LOCK,
501 True,
502 &status,
503 &blr->blocking_smblctx,
504 blr);
506 if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
508 * If we didn't timeout, but still need to wait,
509 * re-add the pending lock entry whilst holding
510 * the brlock db lock.
512 NTSTATUS status1 =
513 brl_lock(blr->fsp->conn->sconn->msg_ctx,
514 br_lck,
515 blr->smblctx,
516 messaging_server_id(
517 blr->fsp->conn->sconn->msg_ctx),
518 blr->offset,
519 blr->count,
520 blr->lock_type == READ_LOCK ?
521 PENDING_READ_LOCK :
522 PENDING_WRITE_LOCK,
523 blr->lock_flav,
524 true, /* Blocking lock. */
525 NULL,
526 blr);
528 if (!NT_STATUS_IS_OK(status1)) {
529 DEBUG(0,("failed to add PENDING_LOCK "
530 "record.\n"));
534 TALLOC_FREE(br_lck);
536 if (NT_STATUS_IS_ERR(status)) {
537 break;
541 if(blr->lock_num == num_locks) {
543 * Success - we got all the locks.
546 DEBUG(3,("process_lockingX file = %s, %s, type=%d "
547 "num_locks=%d\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
548 (unsigned int)locktype, num_locks));
550 reply_lockingX_success(blr);
551 return True;
554 if (!ERROR_WAS_LOCK_DENIED(status)) {
556 * We have other than a "can't get lock"
557 * error. Free any locks we had and return an error.
558 * Return True so we get dequeued.
560 blocking_lock_reply_error(blr, status);
561 return True;
565 * Return an error to the client if we timed out.
567 if (lock_timeout) {
568 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
569 return true;
573 * Still can't get all the locks - keep waiting.
576 DEBUG(10, ("process_lockingX: only got %d locks of %d needed for "
577 "file %s, %s. Waiting....\n",
578 blr->lock_num, num_locks, fsp_str_dbg(fsp),
579 fsp_fnum_dbg(fsp)));
581 return False;
584 /****************************************************************************
585 Attempt to get the posix lock request from a SMBtrans2 call.
586 Returns True if we want to be removed from the list.
587 *****************************************************************************/
589 static bool process_trans2(struct blocking_lock_record *blr)
591 char params[2];
592 NTSTATUS status;
593 bool lock_timeout = lock_timed_out(blr);
595 struct byte_range_lock *br_lck = do_lock(
596 blr->fsp->conn->sconn->msg_ctx,
597 blr->fsp,
598 blr->smblctx,
599 blr->count,
600 blr->offset,
601 blr->lock_type,
602 blr->lock_flav,
603 True,
604 &status,
605 &blr->blocking_smblctx,
606 blr);
607 if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
609 * If we didn't timeout, but still need to wait,
610 * re-add the pending lock entry whilst holding
611 * the brlock db lock.
613 NTSTATUS status1 =
614 brl_lock(blr->fsp->conn->sconn->msg_ctx,
615 br_lck,
616 blr->smblctx,
617 messaging_server_id(
618 blr->fsp->conn->sconn->msg_ctx),
619 blr->offset,
620 blr->count,
621 blr->lock_type == READ_LOCK ?
622 PENDING_READ_LOCK :
623 PENDING_WRITE_LOCK,
624 blr->lock_flav,
625 true, /* Blocking lock. */
626 NULL,
627 blr);
629 if (!NT_STATUS_IS_OK(status1)) {
630 DEBUG(0,("failed to add PENDING_LOCK record.\n"));
634 TALLOC_FREE(br_lck);
636 if (!NT_STATUS_IS_OK(status)) {
637 if (ERROR_WAS_LOCK_DENIED(status)) {
638 if (lock_timeout) {
640 * Return an error if we timed out
641 * and return true to get dequeued.
643 blocking_lock_reply_error(blr,
644 NT_STATUS_FILE_LOCK_CONFLICT);
645 return true;
647 /* Still can't get the lock, just keep waiting. */
648 return False;
651 * We have other than a "can't get lock"
652 * error. Send an error and return True so we get dequeued.
654 blocking_lock_reply_error(blr, status);
655 return True;
658 /* We finally got the lock, return success. */
660 SSVAL(params,0,0);
661 /* Fake up max_data_bytes here - we know it fits. */
662 send_trans2_replies(blr->fsp->conn, blr->req, NT_STATUS_OK, params, 2, NULL, 0, 0xffff);
663 return True;
667 /****************************************************************************
668 Process a blocking lock SMB.
669 Returns True if we want to be removed from the list.
670 *****************************************************************************/
672 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
674 switch(blr->req->cmd) {
675 case SMBlockingX:
676 return process_lockingX(blr);
677 case SMBtrans2:
678 case SMBtranss2:
679 return process_trans2(blr);
680 default:
681 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
682 exit_server("PANIC - unknown type on blocking lock queue");
684 return False; /* Keep compiler happy. */
687 /****************************************************************************
688 Cancel entries by fnum from the blocking lock pending queue.
689 Called when a file is closed.
690 *****************************************************************************/
692 void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp,
693 struct byte_range_lock *br_lck,
694 enum file_close_type close_type)
696 struct smbd_server_connection *sconn = fsp->conn->sconn;
697 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
699 if (sconn->using_smb2) {
700 cancel_pending_lock_requests_by_fid_smb2(fsp,
701 br_lck,
702 close_type);
703 return;
706 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
707 unsigned char locktype = 0;
709 next = blr->next;
710 if (blr->fsp->fnum != fsp->fnum) {
711 continue;
714 if (blr->req->cmd == SMBlockingX) {
715 locktype = CVAL(blr->req->vwv+3, 0);
718 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
719 "request type %d for file %s, %s\n",
720 blr->req->cmd, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
722 blr_cancelled = blocking_lock_cancel_smb1(fsp,
723 blr->smblctx,
724 blr->offset,
725 blr->count,
726 blr->lock_flav,
727 locktype,
728 NT_STATUS_RANGE_NOT_LOCKED);
730 SMB_ASSERT(blr_cancelled == blr);
732 brl_lock_cancel(br_lck,
733 blr->smblctx,
734 messaging_server_id(sconn->msg_ctx),
735 blr->offset,
736 blr->count,
737 blr->lock_flav,
738 blr);
740 /* We're closing the file fsp here, so ensure
741 * we don't have a dangling pointer. */
742 blr->fsp = NULL;
746 /****************************************************************************
747 Delete entries by mid from the blocking lock pending queue. Always send reply.
748 Only called from the SMB1 cancel code.
749 *****************************************************************************/
751 void remove_pending_lock_requests_by_mid_smb1(
752 struct smbd_server_connection *sconn, uint64_t mid)
754 struct blocking_lock_record *blr, *next = NULL;
756 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
757 files_struct *fsp;
758 struct byte_range_lock *br_lck;
760 next = blr->next;
762 if (blr->req->mid != mid) {
763 continue;
766 fsp = blr->fsp;
767 br_lck = brl_get_locks(talloc_tos(), fsp);
769 if (br_lck) {
770 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
771 "removing request type %d for file %s, %s\n",
772 blr->req->cmd, fsp_str_dbg(fsp),
773 fsp_fnum_dbg(fsp)));
775 brl_lock_cancel(br_lck,
776 blr->smblctx,
777 messaging_server_id(sconn->msg_ctx),
778 blr->offset,
779 blr->count,
780 blr->lock_flav,
781 blr);
782 TALLOC_FREE(br_lck);
785 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
786 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
787 TALLOC_FREE(blr);
791 /****************************************************************************
792 Is this mid a blocking lock request on the queue ?
793 Currently only called from the SMB1 unix extensions POSIX lock code.
794 *****************************************************************************/
796 bool blocking_lock_was_deferred_smb1(
797 struct smbd_server_connection *sconn, uint64_t mid)
799 struct blocking_lock_record *blr, *next = NULL;
801 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
802 next = blr->next;
803 if(blr->req->mid == mid) {
804 return True;
807 return False;
810 /****************************************************************************
811 Set a flag as an unlock request affects one of our pending locks.
812 *****************************************************************************/
814 static void received_unlock_msg(struct messaging_context *msg,
815 void *private_data,
816 uint32_t msg_type,
817 struct server_id server_id,
818 DATA_BLOB *data)
820 struct smbd_server_connection *sconn =
821 talloc_get_type_abort(private_data,
822 struct smbd_server_connection);
824 DEBUG(10,("received_unlock_msg\n"));
825 process_blocking_lock_queue(sconn);
828 /****************************************************************************
829 Process the blocking lock queue. Note that this is only called as root.
830 *****************************************************************************/
832 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
834 struct blocking_lock_record *blr, *next = NULL;
836 if (sconn->using_smb2) {
837 process_blocking_lock_queue_smb2(sconn, timeval_current());
838 return;
842 * Go through the queue and see if we can get any of the locks.
845 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
846 struct byte_range_lock *br_lck = NULL;
848 next = blr->next;
851 * Go through the remaining locks and try and obtain them.
852 * The call returns True if all locks were obtained successfully
853 * and False if we still need to wait.
856 DEBUG(10, ("Processing BLR = %p\n", blr));
858 /* We use set_current_service so connections with
859 * pending locks are not marked as idle.
862 set_current_service(blr->fsp->conn,
863 SVAL(blr->req->inbuf,smb_flg),
864 false);
867 * Remove the pending lock we're waiting on.
868 * If we need to keep waiting blocking_lock_record_process()
869 * will re-add it.
872 br_lck = brl_get_locks(talloc_tos(), blr->fsp);
873 if (br_lck) {
874 brl_lock_cancel(br_lck,
875 blr->smblctx,
876 messaging_server_id(sconn->msg_ctx),
877 blr->offset,
878 blr->count,
879 blr->lock_flav,
880 blr);
882 TALLOC_FREE(br_lck);
884 if(!blocking_lock_record_process(blr)) {
885 DEBUG(10, ("still waiting for lock. BLR = %p\n", blr));
886 continue;
889 DEBUG(10, ("BLR_process returned true: removing BLR = %p\n",
890 blr));
892 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
893 TALLOC_FREE(blr);
896 recalc_brl_timeout(sconn);
899 /****************************************************************************
900 Handle a cancel message. Lock already moved onto the cancel queue.
901 *****************************************************************************/
903 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
905 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
906 void *private_data,
907 uint32_t msg_type,
908 struct server_id server_id,
909 DATA_BLOB *data)
911 NTSTATUS err;
912 const char *msg = (const char *)data->data;
913 struct blocking_lock_record *blr;
914 struct smbd_server_connection *sconn =
915 talloc_get_type_abort(private_data,
916 struct smbd_server_connection);
918 if (data->data == NULL) {
919 smb_panic("process_blocking_lock_cancel_message: null msg");
922 if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
923 DEBUG(0, ("process_blocking_lock_cancel_message: "
924 "Got invalid msg len %d\n", (int)data->length));
925 smb_panic("process_blocking_lock_cancel_message: bad msg");
928 memcpy(&blr, msg, sizeof(blr));
929 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
931 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
932 nt_errstr(err) ));
934 blocking_lock_reply_error(blr, err);
935 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
936 TALLOC_FREE(blr);
939 /****************************************************************************
940 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
941 Returns the blocking_lock_record that is being cancelled.
942 Only called from the SMB1 code.
943 *****************************************************************************/
945 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
946 uint64_t smblctx,
947 uint64_t offset,
948 uint64_t count,
949 enum brl_flavour lock_flav,
950 unsigned char locktype,
951 NTSTATUS err)
953 struct smbd_server_connection *sconn = fsp->conn->sconn;
954 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
955 struct blocking_lock_record *blr;
957 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
958 /* Register our message. */
959 messaging_register(sconn->msg_ctx, sconn,
960 MSG_SMB_BLOCKING_LOCK_CANCEL,
961 process_blocking_lock_cancel_message);
963 sconn->smb1.locks.blocking_lock_cancel_state = True;
966 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
967 if (fsp == blr->fsp &&
968 smblctx == blr->smblctx &&
969 offset == blr->offset &&
970 count == blr->count &&
971 lock_flav == blr->lock_flav) {
972 break;
976 if (!blr) {
977 return NULL;
980 /* Check the flags are right. */
981 if (blr->req->cmd == SMBlockingX &&
982 (locktype & LOCKING_ANDX_LARGE_FILES) !=
983 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
984 return NULL;
987 /* Move to cancelled queue. */
988 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
989 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
991 /* Create the message. */
992 memcpy(msg, &blr, sizeof(blr));
993 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
995 messaging_send_buf(sconn->msg_ctx, messaging_server_id(sconn->msg_ctx),
996 MSG_SMB_BLOCKING_LOCK_CANCEL,
997 (uint8 *)&msg, sizeof(msg));
999 return blr;