s3: Enable statvfs usage on NetBSD
[Samba/gebeck_regimport.git] / source3 / smbd / blocking.c
blob6496e4350544ff0adc43a9f44d18ed2e64ba3a17
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 fnum = %d, name = %s\n",
258 (unsigned int)blr->expire_time.tv_sec,
259 (unsigned int)blr->expire_time.tv_usec, lock_timeout,
260 blr->fsp->fnum, 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);
276 * As this message is a lockingX call we must handle
277 * any following chained message correctly.
278 * This is normally handled in construct_reply(),
279 * but as that calls switch_message, we can't use
280 * that here and must set up the chain info manually.
283 chain_reply(req);
284 TALLOC_FREE(req->outbuf);
287 /****************************************************************************
288 Return a generic lock fail error blocking call.
289 *****************************************************************************/
291 static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
293 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
294 FILE_LOCK_CONFLICT! (tridge) */
295 if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
296 status = NT_STATUS_FILE_LOCK_CONFLICT;
299 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
300 /* Store the last lock error. */
301 files_struct *fsp = blr->fsp;
303 if (fsp) {
304 fsp->last_lock_failure.context.smblctx = blr->smblctx;
305 fsp->last_lock_failure.context.tid = fsp->conn->cnum;
306 fsp->last_lock_failure.context.pid =
307 messaging_server_id(fsp->conn->sconn->msg_ctx);
308 fsp->last_lock_failure.start = blr->offset;
309 fsp->last_lock_failure.size = blr->count;
310 fsp->last_lock_failure.fnum = fsp->fnum;
311 fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
312 fsp->last_lock_failure.lock_flav = blr->lock_flav;
316 reply_nterror(blr->req, status);
317 if (!srv_send_smb(blr->req->sconn, (char *)blr->req->outbuf,
318 true, blr->req->seqnum+1,
319 blr->req->encrypted, NULL)) {
320 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
322 TALLOC_FREE(blr->req->outbuf);
325 /****************************************************************************
326 Return a lock fail error for a lockingX call. Undo all the locks we have
327 obtained first.
328 *****************************************************************************/
330 static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS status)
332 files_struct *fsp = blr->fsp;
333 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
334 uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
335 uint64_t smblctx;
336 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
337 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
338 uint8_t *data;
339 int i;
341 data = discard_const_p(uint8_t, blr->req->buf)
342 + ((large_file_format ? 20 : 10)*num_ulocks);
345 * Data now points at the beginning of the list
346 * of smb_lkrng structs.
350 * Ensure we don't do a remove on the lock that just failed,
351 * as under POSIX rules, if we have a lock already there, we
352 * will delete it (and we shouldn't) .....
355 for(i = blr->lock_num - 1; i >= 0; i--) {
356 bool err;
358 smblctx = get_lock_pid( data, i, large_file_format);
359 count = get_lock_count( data, i, large_file_format);
360 offset = get_lock_offset( data, i, large_file_format, &err);
363 * We know err cannot be set as if it was the lock
364 * request would never have been queued. JRA.
367 do_unlock(fsp->conn->sconn->msg_ctx,
368 fsp,
369 smblctx,
370 count,
371 offset,
372 WINDOWS_LOCK);
375 generic_blocking_lock_error(blr, status);
378 /****************************************************************************
379 Return a lock fail error.
380 *****************************************************************************/
382 static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
384 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
386 switch(blr->req->cmd) {
387 case SMBlockingX:
388 reply_lockingX_error(blr, status);
389 break;
390 case SMBtrans2:
391 case SMBtranss2:
392 reply_nterror(blr->req, status);
395 * construct_reply_common has done us the favor to pre-fill
396 * the command field with SMBtranss2 which is wrong :-)
398 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
400 if (!srv_send_smb(blr->req->sconn,
401 (char *)blr->req->outbuf,
402 true, blr->req->seqnum+1,
403 IS_CONN_ENCRYPTED(blr->fsp->conn),
404 NULL)) {
405 exit_server_cleanly("blocking_lock_reply_error: "
406 "srv_send_smb failed.");
408 TALLOC_FREE(blr->req->outbuf);
409 break;
410 default:
411 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
412 exit_server("PANIC - unknown type on blocking lock queue");
416 /****************************************************************************
417 Attempt to finish off getting all pending blocking locks for a lockingX call.
418 Returns True if we want to be removed from the list.
419 *****************************************************************************/
421 static bool process_lockingX(struct blocking_lock_record *blr)
423 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
424 files_struct *fsp = blr->fsp;
425 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
426 uint16 num_locks = SVAL(blr->req->vwv+7, 0);
427 uint64_t count = (uint64_t)0, offset = (uint64_t)0;
428 uint64_t smblctx;
429 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
430 uint8_t *data;
431 NTSTATUS status = NT_STATUS_OK;
433 data = discard_const_p(uint8_t, blr->req->buf)
434 + ((large_file_format ? 20 : 10)*num_ulocks);
437 * Data now points at the beginning of the list
438 * of smb_lkrng structs.
441 for(; blr->lock_num < num_locks; blr->lock_num++) {
442 struct byte_range_lock *br_lck = NULL;
443 bool err;
445 smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
446 count = get_lock_count( data, blr->lock_num, large_file_format);
447 offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
450 * We know err cannot be set as if it was the lock
451 * request would never have been queued. JRA.
453 errno = 0;
454 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
455 fsp,
456 smblctx,
457 count,
458 offset,
459 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
460 READ_LOCK : WRITE_LOCK),
461 WINDOWS_LOCK,
462 True,
463 &status,
464 &blr->blocking_smblctx,
465 blr);
467 TALLOC_FREE(br_lck);
469 if (NT_STATUS_IS_ERR(status)) {
470 break;
474 if(blr->lock_num == num_locks) {
476 * Success - we got all the locks.
479 DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d "
480 "num_locks=%d\n", fsp_str_dbg(fsp), fsp->fnum,
481 (unsigned int)locktype, num_locks));
483 reply_lockingX_success(blr);
484 return True;
487 if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
488 !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
490 * We have other than a "can't get lock"
491 * error. Free any locks we had and return an error.
492 * Return True so we get dequeued.
494 blocking_lock_reply_error(blr, status);
495 return True;
499 * Still can't get all the locks - keep waiting.
502 DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
503 Waiting....\n",
504 blr->lock_num, num_locks, fsp_str_dbg(fsp), fsp->fnum));
506 return False;
509 /****************************************************************************
510 Attempt to get the posix lock request from a SMBtrans2 call.
511 Returns True if we want to be removed from the list.
512 *****************************************************************************/
514 static bool process_trans2(struct blocking_lock_record *blr)
516 char params[2];
517 NTSTATUS status;
518 struct byte_range_lock *br_lck = do_lock(
519 blr->fsp->conn->sconn->msg_ctx,
520 blr->fsp,
521 blr->smblctx,
522 blr->count,
523 blr->offset,
524 blr->lock_type,
525 blr->lock_flav,
526 True,
527 &status,
528 &blr->blocking_smblctx,
529 blr);
530 TALLOC_FREE(br_lck);
532 if (!NT_STATUS_IS_OK(status)) {
533 if (ERROR_WAS_LOCK_DENIED(status)) {
534 /* Still can't get the lock, just keep waiting. */
535 return False;
538 * We have other than a "can't get lock"
539 * error. Send an error and return True so we get dequeued.
541 blocking_lock_reply_error(blr, status);
542 return True;
545 /* We finally got the lock, return success. */
547 SSVAL(params,0,0);
548 /* Fake up max_data_bytes here - we know it fits. */
549 send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff);
550 return True;
554 /****************************************************************************
555 Process a blocking lock SMB.
556 Returns True if we want to be removed from the list.
557 *****************************************************************************/
559 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
561 switch(blr->req->cmd) {
562 case SMBlockingX:
563 return process_lockingX(blr);
564 case SMBtrans2:
565 case SMBtranss2:
566 return process_trans2(blr);
567 default:
568 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
569 exit_server("PANIC - unknown type on blocking lock queue");
571 return False; /* Keep compiler happy. */
574 /****************************************************************************
575 Cancel entries by fnum from the blocking lock pending queue.
576 Called when a file is closed.
577 *****************************************************************************/
579 void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp,
580 struct byte_range_lock *br_lck,
581 enum file_close_type close_type)
583 struct smbd_server_connection *sconn = fsp->conn->sconn;
584 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
586 if (sconn->using_smb2) {
587 cancel_pending_lock_requests_by_fid_smb2(fsp,
588 br_lck,
589 close_type);
590 return;
593 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
594 unsigned char locktype = 0;
596 next = blr->next;
597 if (blr->fsp->fnum != fsp->fnum) {
598 continue;
601 if (blr->req->cmd == SMBlockingX) {
602 locktype = CVAL(blr->req->vwv+3, 0);
605 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
606 "request type %d for file %s fnum = %d\n",
607 blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum));
609 blr_cancelled = blocking_lock_cancel_smb1(fsp,
610 blr->smblctx,
611 blr->offset,
612 blr->count,
613 blr->lock_flav,
614 locktype,
615 NT_STATUS_RANGE_NOT_LOCKED);
617 SMB_ASSERT(blr_cancelled == blr);
619 brl_lock_cancel(br_lck,
620 blr->smblctx,
621 messaging_server_id(sconn->msg_ctx),
622 blr->offset,
623 blr->count,
624 blr->lock_flav,
625 blr);
627 /* We're closing the file fsp here, so ensure
628 * we don't have a dangling pointer. */
629 blr->fsp = NULL;
633 /****************************************************************************
634 Delete entries by mid from the blocking lock pending queue. Always send reply.
635 Only called from the SMB1 cancel code.
636 *****************************************************************************/
638 void remove_pending_lock_requests_by_mid_smb1(
639 struct smbd_server_connection *sconn, uint64_t mid)
641 struct blocking_lock_record *blr, *next = NULL;
643 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
644 files_struct *fsp;
645 struct byte_range_lock *br_lck;
647 next = blr->next;
649 if (blr->req->mid != mid) {
650 continue;
653 fsp = blr->fsp;
654 br_lck = brl_get_locks(talloc_tos(), fsp);
656 if (br_lck) {
657 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
658 "removing request type %d for file %s fnum "
659 "= %d\n", blr->req->cmd, fsp_str_dbg(fsp),
660 fsp->fnum ));
662 brl_lock_cancel(br_lck,
663 blr->smblctx,
664 messaging_server_id(sconn->msg_ctx),
665 blr->offset,
666 blr->count,
667 blr->lock_flav,
668 blr);
669 TALLOC_FREE(br_lck);
672 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
673 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
674 TALLOC_FREE(blr);
678 /****************************************************************************
679 Is this mid a blocking lock request on the queue ?
680 Currently only called from the SMB1 unix extensions POSIX lock code.
681 *****************************************************************************/
683 bool blocking_lock_was_deferred_smb1(
684 struct smbd_server_connection *sconn, uint64_t mid)
686 struct blocking_lock_record *blr, *next = NULL;
688 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
689 next = blr->next;
690 if(blr->req->mid == mid) {
691 return True;
694 return False;
697 /****************************************************************************
698 Set a flag as an unlock request affects one of our pending locks.
699 *****************************************************************************/
701 static void received_unlock_msg(struct messaging_context *msg,
702 void *private_data,
703 uint32_t msg_type,
704 struct server_id server_id,
705 DATA_BLOB *data)
707 struct smbd_server_connection *sconn =
708 talloc_get_type_abort(private_data,
709 struct smbd_server_connection);
711 DEBUG(10,("received_unlock_msg\n"));
712 process_blocking_lock_queue(sconn);
715 /****************************************************************************
716 Process the blocking lock queue. Note that this is only called as root.
717 *****************************************************************************/
719 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
721 struct timeval tv_curr = timeval_current();
722 struct blocking_lock_record *blr, *next = NULL;
724 if (sconn->using_smb2) {
725 process_blocking_lock_queue_smb2(sconn, tv_curr);
726 return;
730 * Go through the queue and see if we can get any of the locks.
733 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
735 next = blr->next;
738 * Go through the remaining locks and try and obtain them.
739 * The call returns True if all locks were obtained successfully
740 * and False if we still need to wait.
743 DEBUG(10, ("Processing BLR = %p\n", blr));
745 /* We use set_current_service so connections with
746 * pending locks are not marked as idle.
749 set_current_service(blr->fsp->conn,
750 SVAL(blr->req->inbuf,smb_flg),
751 false);
753 if(blocking_lock_record_process(blr)) {
754 struct byte_range_lock *br_lck = brl_get_locks(
755 talloc_tos(), blr->fsp);
757 DEBUG(10, ("BLR_process returned true: cancelling and "
758 "removing lock. BLR = %p\n", blr));
760 if (br_lck) {
761 brl_lock_cancel(br_lck,
762 blr->smblctx,
763 messaging_server_id(sconn->msg_ctx),
764 blr->offset,
765 blr->count,
766 blr->lock_flav,
767 blr);
768 TALLOC_FREE(br_lck);
771 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
772 TALLOC_FREE(blr);
773 continue;
777 * We couldn't get the locks for this record on the list.
778 * If the time has expired, return a lock error.
781 if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
782 struct byte_range_lock *br_lck = brl_get_locks(
783 talloc_tos(), blr->fsp);
785 DEBUG(10, ("Lock timed out! BLR = %p\n", blr));
788 * Lock expired - throw away all previously
789 * obtained locks and return lock error.
792 if (br_lck) {
793 DEBUG(5,("process_blocking_lock_queue: "
794 "pending lock fnum = %d for file %s "
795 "timed out.\n", blr->fsp->fnum,
796 fsp_str_dbg(blr->fsp)));
798 brl_lock_cancel(br_lck,
799 blr->smblctx,
800 messaging_server_id(sconn->msg_ctx),
801 blr->offset,
802 blr->count,
803 blr->lock_flav,
804 blr);
805 TALLOC_FREE(br_lck);
808 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
809 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
810 TALLOC_FREE(blr);
814 recalc_brl_timeout(sconn);
817 /****************************************************************************
818 Handle a cancel message. Lock already moved onto the cancel queue.
819 *****************************************************************************/
821 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
823 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
824 void *private_data,
825 uint32_t msg_type,
826 struct server_id server_id,
827 DATA_BLOB *data)
829 NTSTATUS err;
830 const char *msg = (const char *)data->data;
831 struct blocking_lock_record *blr;
832 struct smbd_server_connection *sconn =
833 talloc_get_type_abort(private_data,
834 struct smbd_server_connection);
836 if (data->data == NULL) {
837 smb_panic("process_blocking_lock_cancel_message: null msg");
840 if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
841 DEBUG(0, ("process_blocking_lock_cancel_message: "
842 "Got invalid msg len %d\n", (int)data->length));
843 smb_panic("process_blocking_lock_cancel_message: bad msg");
846 memcpy(&blr, msg, sizeof(blr));
847 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
849 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
850 nt_errstr(err) ));
852 blocking_lock_reply_error(blr, err);
853 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
854 TALLOC_FREE(blr);
857 /****************************************************************************
858 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
859 Returns the blocking_lock_record that is being cancelled.
860 Only called from the SMB1 code.
861 *****************************************************************************/
863 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
864 uint64_t smblctx,
865 uint64_t offset,
866 uint64_t count,
867 enum brl_flavour lock_flav,
868 unsigned char locktype,
869 NTSTATUS err)
871 struct smbd_server_connection *sconn = fsp->conn->sconn;
872 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
873 struct blocking_lock_record *blr;
875 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
876 /* Register our message. */
877 messaging_register(sconn->msg_ctx, sconn,
878 MSG_SMB_BLOCKING_LOCK_CANCEL,
879 process_blocking_lock_cancel_message);
881 sconn->smb1.locks.blocking_lock_cancel_state = True;
884 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
885 if (fsp == blr->fsp &&
886 smblctx == blr->smblctx &&
887 offset == blr->offset &&
888 count == blr->count &&
889 lock_flav == blr->lock_flav) {
890 break;
894 if (!blr) {
895 return NULL;
898 /* Check the flags are right. */
899 if (blr->req->cmd == SMBlockingX &&
900 (locktype & LOCKING_ANDX_LARGE_FILES) !=
901 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
902 return NULL;
905 /* Move to cancelled queue. */
906 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
907 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
909 /* Create the message. */
910 memcpy(msg, &blr, sizeof(blr));
911 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
913 messaging_send_buf(sconn->msg_ctx, messaging_server_id(sconn->msg_ctx),
914 MSG_SMB_BLOCKING_LOCK_CANCEL,
915 (uint8 *)&msg, sizeof(msg));
917 return blr;