examples/VFS: fix skel_transparent.c in reference to shadow_copy changes
[Samba/gebeck_regimport.git] / source3 / smbd / blocking.c
blobd9c1fb2d3b3a2e480dd9be54752fcd67dfb9f0c7
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 = event_add_timed(server_event_context(),
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 sconn_server_id(req->sconn),
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, NULL,
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 reply_outbuf(blr->req, 2, 0);
274 * As this message is a lockingX call we must handle
275 * any following chained message correctly.
276 * This is normally handled in construct_reply(),
277 * but as that calls switch_message, we can't use
278 * that here and must set up the chain info manually.
281 chain_reply(blr->req);
282 TALLOC_FREE(blr->req->outbuf);
285 /****************************************************************************
286 Return a generic lock fail error blocking call.
287 *****************************************************************************/
289 static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
291 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
292 FILE_LOCK_CONFLICT! (tridge) */
293 if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
294 status = NT_STATUS_FILE_LOCK_CONFLICT;
297 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
298 /* Store the last lock error. */
299 files_struct *fsp = blr->fsp;
301 if (fsp) {
302 fsp->last_lock_failure.context.smblctx = blr->smblctx;
303 fsp->last_lock_failure.context.tid = fsp->conn->cnum;
304 fsp->last_lock_failure.context.pid =
305 sconn_server_id(fsp->conn->sconn);
306 fsp->last_lock_failure.start = blr->offset;
307 fsp->last_lock_failure.size = blr->count;
308 fsp->last_lock_failure.fnum = fsp->fnum;
309 fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
310 fsp->last_lock_failure.lock_flav = blr->lock_flav;
314 reply_nterror(blr->req, status);
315 if (!srv_send_smb(blr->req->sconn, (char *)blr->req->outbuf,
316 true, blr->req->seqnum+1,
317 blr->req->encrypted, NULL)) {
318 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
320 TALLOC_FREE(blr->req->outbuf);
323 /****************************************************************************
324 Return a lock fail error for a lockingX call. Undo all the locks we have
325 obtained first.
326 *****************************************************************************/
328 static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS status)
330 files_struct *fsp = blr->fsp;
331 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
332 uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
333 uint64_t smblctx;
334 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
335 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
336 uint8_t *data;
337 int i;
339 data = discard_const_p(uint8_t, blr->req->buf)
340 + ((large_file_format ? 20 : 10)*num_ulocks);
343 * Data now points at the beginning of the list
344 * of smb_lkrng structs.
348 * Ensure we don't do a remove on the lock that just failed,
349 * as under POSIX rules, if we have a lock already there, we
350 * will delete it (and we shouldn't) .....
353 for(i = blr->lock_num - 1; i >= 0; i--) {
354 bool err;
356 smblctx = get_lock_pid( data, i, large_file_format);
357 count = get_lock_count( data, i, large_file_format);
358 offset = get_lock_offset( data, i, large_file_format, &err);
361 * We know err cannot be set as if it was the lock
362 * request would never have been queued. JRA.
365 do_unlock(fsp->conn->sconn->msg_ctx,
366 fsp,
367 smblctx,
368 count,
369 offset,
370 WINDOWS_LOCK);
373 generic_blocking_lock_error(blr, status);
376 /****************************************************************************
377 Return a lock fail error.
378 *****************************************************************************/
380 static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
382 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
384 switch(blr->req->cmd) {
385 case SMBlockingX:
386 reply_lockingX_error(blr, status);
387 break;
388 case SMBtrans2:
389 case SMBtranss2:
390 reply_nterror(blr->req, status);
393 * construct_reply_common has done us the favor to pre-fill
394 * the command field with SMBtranss2 which is wrong :-)
396 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
398 if (!srv_send_smb(blr->req->sconn,
399 (char *)blr->req->outbuf,
400 true, blr->req->seqnum+1,
401 IS_CONN_ENCRYPTED(blr->fsp->conn),
402 NULL)) {
403 exit_server_cleanly("blocking_lock_reply_error: "
404 "srv_send_smb failed.");
406 TALLOC_FREE(blr->req->outbuf);
407 break;
408 default:
409 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
410 exit_server("PANIC - unknown type on blocking lock queue");
414 /****************************************************************************
415 Attempt to finish off getting all pending blocking locks for a lockingX call.
416 Returns True if we want to be removed from the list.
417 *****************************************************************************/
419 static bool process_lockingX(struct blocking_lock_record *blr)
421 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
422 files_struct *fsp = blr->fsp;
423 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
424 uint16 num_locks = SVAL(blr->req->vwv+7, 0);
425 uint64_t count = (uint64_t)0, offset = (uint64_t)0;
426 uint64_t smblctx;
427 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
428 uint8_t *data;
429 NTSTATUS status = NT_STATUS_OK;
431 data = discard_const_p(uint8_t, blr->req->buf)
432 + ((large_file_format ? 20 : 10)*num_ulocks);
435 * Data now points at the beginning of the list
436 * of smb_lkrng structs.
439 for(; blr->lock_num < num_locks; blr->lock_num++) {
440 struct byte_range_lock *br_lck = NULL;
441 bool err;
443 smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
444 count = get_lock_count( data, blr->lock_num, large_file_format);
445 offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
448 * We know err cannot be set as if it was the lock
449 * request would never have been queued. JRA.
451 errno = 0;
452 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
453 fsp,
454 smblctx,
455 count,
456 offset,
457 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
458 READ_LOCK : WRITE_LOCK),
459 WINDOWS_LOCK,
460 True,
461 &status,
462 &blr->blocking_smblctx,
463 blr);
465 TALLOC_FREE(br_lck);
467 if (NT_STATUS_IS_ERR(status)) {
468 break;
472 if(blr->lock_num == num_locks) {
474 * Success - we got all the locks.
477 DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d "
478 "num_locks=%d\n", fsp_str_dbg(fsp), fsp->fnum,
479 (unsigned int)locktype, num_locks));
481 reply_lockingX_success(blr);
482 return True;
485 if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
486 !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
488 * We have other than a "can't get lock"
489 * error. Free any locks we had and return an error.
490 * Return True so we get dequeued.
492 blocking_lock_reply_error(blr, status);
493 return True;
497 * Still can't get all the locks - keep waiting.
500 DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
501 Waiting....\n",
502 blr->lock_num, num_locks, fsp_str_dbg(fsp), fsp->fnum));
504 return False;
507 /****************************************************************************
508 Attempt to get the posix lock request from a SMBtrans2 call.
509 Returns True if we want to be removed from the list.
510 *****************************************************************************/
512 static bool process_trans2(struct blocking_lock_record *blr)
514 char params[2];
515 NTSTATUS status;
516 struct byte_range_lock *br_lck = do_lock(
517 blr->fsp->conn->sconn->msg_ctx,
518 blr->fsp,
519 blr->smblctx,
520 blr->count,
521 blr->offset,
522 blr->lock_type,
523 blr->lock_flav,
524 True,
525 &status,
526 &blr->blocking_smblctx,
527 blr);
528 TALLOC_FREE(br_lck);
530 if (!NT_STATUS_IS_OK(status)) {
531 if (ERROR_WAS_LOCK_DENIED(status)) {
532 /* Still can't get the lock, just keep waiting. */
533 return False;
536 * We have other than a "can't get lock"
537 * error. Send an error and return True so we get dequeued.
539 blocking_lock_reply_error(blr, status);
540 return True;
543 /* We finally got the lock, return success. */
545 SSVAL(params,0,0);
546 /* Fake up max_data_bytes here - we know it fits. */
547 send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff);
548 return True;
552 /****************************************************************************
553 Process a blocking lock SMB.
554 Returns True if we want to be removed from the list.
555 *****************************************************************************/
557 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
559 switch(blr->req->cmd) {
560 case SMBlockingX:
561 return process_lockingX(blr);
562 case SMBtrans2:
563 case SMBtranss2:
564 return process_trans2(blr);
565 default:
566 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
567 exit_server("PANIC - unknown type on blocking lock queue");
569 return False; /* Keep compiler happy. */
572 /****************************************************************************
573 Cancel entries by fnum from the blocking lock pending queue.
574 Called when a file is closed.
575 *****************************************************************************/
577 void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp,
578 struct byte_range_lock *br_lck,
579 enum file_close_type close_type)
581 struct smbd_server_connection *sconn = fsp->conn->sconn;
582 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
584 if (sconn->using_smb2) {
585 cancel_pending_lock_requests_by_fid_smb2(fsp,
586 br_lck,
587 close_type);
588 return;
591 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
592 unsigned char locktype = 0;
594 next = blr->next;
595 if (blr->fsp->fnum != fsp->fnum) {
596 continue;
599 if (blr->req->cmd == SMBlockingX) {
600 locktype = CVAL(blr->req->vwv+3, 0);
603 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
604 "request type %d for file %s fnum = %d\n",
605 blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum));
607 blr_cancelled = blocking_lock_cancel_smb1(fsp,
608 blr->smblctx,
609 blr->offset,
610 blr->count,
611 blr->lock_flav,
612 locktype,
613 NT_STATUS_RANGE_NOT_LOCKED);
615 SMB_ASSERT(blr_cancelled == blr);
617 brl_lock_cancel(br_lck,
618 blr->smblctx,
619 sconn_server_id(sconn),
620 blr->offset,
621 blr->count,
622 blr->lock_flav,
623 blr);
625 /* We're closing the file fsp here, so ensure
626 * we don't have a dangling pointer. */
627 blr->fsp = NULL;
631 /****************************************************************************
632 Delete entries by mid from the blocking lock pending queue. Always send reply.
633 Only called from the SMB1 cancel code.
634 *****************************************************************************/
636 void remove_pending_lock_requests_by_mid_smb1(
637 struct smbd_server_connection *sconn, uint64_t mid)
639 struct blocking_lock_record *blr, *next = NULL;
641 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
642 files_struct *fsp;
643 struct byte_range_lock *br_lck;
645 next = blr->next;
647 if (blr->req->mid != mid) {
648 continue;
651 fsp = blr->fsp;
652 br_lck = brl_get_locks(talloc_tos(), fsp);
654 if (br_lck) {
655 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
656 "removing request type %d for file %s fnum "
657 "= %d\n", blr->req->cmd, fsp_str_dbg(fsp),
658 fsp->fnum ));
660 brl_lock_cancel(br_lck,
661 blr->smblctx,
662 sconn_server_id(sconn),
663 blr->offset,
664 blr->count,
665 blr->lock_flav,
666 blr);
667 TALLOC_FREE(br_lck);
670 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
671 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
672 TALLOC_FREE(blr);
676 /****************************************************************************
677 Is this mid a blocking lock request on the queue ?
678 Currently only called from the SMB1 unix extensions POSIX lock code.
679 *****************************************************************************/
681 bool blocking_lock_was_deferred_smb1(
682 struct smbd_server_connection *sconn, uint64_t mid)
684 struct blocking_lock_record *blr, *next = NULL;
686 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
687 next = blr->next;
688 if(blr->req->mid == mid) {
689 return True;
692 return False;
695 /****************************************************************************
696 Set a flag as an unlock request affects one of our pending locks.
697 *****************************************************************************/
699 static void received_unlock_msg(struct messaging_context *msg,
700 void *private_data,
701 uint32_t msg_type,
702 struct server_id server_id,
703 DATA_BLOB *data)
705 struct smbd_server_connection *sconn;
707 sconn = msg_ctx_to_sconn(msg);
708 if (sconn == NULL) {
709 DEBUG(1, ("could not find sconn\n"));
710 return;
713 DEBUG(10,("received_unlock_msg\n"));
714 process_blocking_lock_queue(sconn);
717 /****************************************************************************
718 Process the blocking lock queue. Note that this is only called as root.
719 *****************************************************************************/
721 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
723 struct timeval tv_curr = timeval_current();
724 struct blocking_lock_record *blr, *next = NULL;
726 if (sconn->using_smb2) {
727 process_blocking_lock_queue_smb2(sconn, tv_curr);
728 return;
732 * Go through the queue and see if we can get any of the locks.
735 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
737 next = blr->next;
740 * Go through the remaining locks and try and obtain them.
741 * The call returns True if all locks were obtained successfully
742 * and False if we still need to wait.
745 DEBUG(10, ("Processing BLR = %p\n", blr));
747 /* We use set_current_service so connections with
748 * pending locks are not marked as idle.
751 set_current_service(blr->fsp->conn,
752 SVAL(blr->req->inbuf,smb_flg),
753 false);
755 if(blocking_lock_record_process(blr)) {
756 struct byte_range_lock *br_lck = brl_get_locks(
757 talloc_tos(), blr->fsp);
759 DEBUG(10, ("BLR_process returned true: cancelling and "
760 "removing lock. BLR = %p\n", blr));
762 if (br_lck) {
763 brl_lock_cancel(br_lck,
764 blr->smblctx,
765 sconn_server_id(sconn),
766 blr->offset,
767 blr->count,
768 blr->lock_flav,
769 blr);
770 TALLOC_FREE(br_lck);
773 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
774 TALLOC_FREE(blr);
775 continue;
779 * We couldn't get the locks for this record on the list.
780 * If the time has expired, return a lock error.
783 if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
784 struct byte_range_lock *br_lck = brl_get_locks(
785 talloc_tos(), blr->fsp);
787 DEBUG(10, ("Lock timed out! BLR = %p\n", blr));
790 * Lock expired - throw away all previously
791 * obtained locks and return lock error.
794 if (br_lck) {
795 DEBUG(5,("process_blocking_lock_queue: "
796 "pending lock fnum = %d for file %s "
797 "timed out.\n", blr->fsp->fnum,
798 fsp_str_dbg(blr->fsp)));
800 brl_lock_cancel(br_lck,
801 blr->smblctx,
802 sconn_server_id(sconn),
803 blr->offset,
804 blr->count,
805 blr->lock_flav,
806 blr);
807 TALLOC_FREE(br_lck);
810 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
811 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
812 TALLOC_FREE(blr);
816 recalc_brl_timeout(sconn);
819 /****************************************************************************
820 Handle a cancel message. Lock already moved onto the cancel queue.
821 *****************************************************************************/
823 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
825 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
826 void *private_data,
827 uint32_t msg_type,
828 struct server_id server_id,
829 DATA_BLOB *data)
831 struct smbd_server_connection *sconn;
832 NTSTATUS err;
833 const char *msg = (const char *)data->data;
834 struct blocking_lock_record *blr;
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 sconn = msg_ctx_to_sconn(ctx);
847 if (sconn == NULL) {
848 DEBUG(1, ("could not find sconn\n"));
849 return;
852 memcpy(&blr, msg, sizeof(blr));
853 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
855 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
856 nt_errstr(err) ));
858 blocking_lock_reply_error(blr, err);
859 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
860 TALLOC_FREE(blr);
863 /****************************************************************************
864 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
865 Returns the blocking_lock_record that is being cancelled.
866 Only called from the SMB1 code.
867 *****************************************************************************/
869 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
870 uint64_t smblctx,
871 uint64_t offset,
872 uint64_t count,
873 enum brl_flavour lock_flav,
874 unsigned char locktype,
875 NTSTATUS err)
877 struct smbd_server_connection *sconn = fsp->conn->sconn;
878 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
879 struct blocking_lock_record *blr;
881 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
882 /* Register our message. */
883 messaging_register(sconn->msg_ctx, NULL,
884 MSG_SMB_BLOCKING_LOCK_CANCEL,
885 process_blocking_lock_cancel_message);
887 sconn->smb1.locks.blocking_lock_cancel_state = True;
890 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
891 if (fsp == blr->fsp &&
892 smblctx == blr->smblctx &&
893 offset == blr->offset &&
894 count == blr->count &&
895 lock_flav == blr->lock_flav) {
896 break;
900 if (!blr) {
901 return NULL;
904 /* Check the flags are right. */
905 if (blr->req->cmd == SMBlockingX &&
906 (locktype & LOCKING_ANDX_LARGE_FILES) !=
907 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
908 return NULL;
911 /* Move to cancelled queue. */
912 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
913 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
915 /* Create the message. */
916 memcpy(msg, &blr, sizeof(blr));
917 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
919 messaging_send_buf(sconn->msg_ctx, sconn_server_id(sconn),
920 MSG_SMB_BLOCKING_LOCK_CANCEL,
921 (uint8 *)&msg, sizeof(msg));
923 return blr;