s3-rpc_client: move protos to cli_lsarpc.h
[Samba/ekacnet.git] / source3 / smbd / blocking.c
blobda14ce89c9a83e6e3a97000a83dae7f545929181
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/globals.h"
22 #include "librpc/gen_ndr/messaging.h"
24 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_LOCKING
27 /****************************************************************************
28 Determine if this is a secondary element of a chained SMB.
29 **************************************************************************/
31 static void received_unlock_msg(struct messaging_context *msg,
32 void *private_data,
33 uint32_t msg_type,
34 struct server_id server_id,
35 DATA_BLOB *data);
37 void brl_timeout_fn(struct event_context *event_ctx,
38 struct timed_event *te,
39 struct timeval now,
40 void *private_data)
42 struct smbd_server_connection *sconn = smbd_server_conn;
44 if (sconn->allow_smb2) {
45 SMB_ASSERT(sconn->smb2.locks.brl_timeout == te);
46 TALLOC_FREE(sconn->smb2.locks.brl_timeout);
47 } else {
48 SMB_ASSERT(sconn->smb1.locks.brl_timeout == te);
49 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
52 change_to_root_user(); /* TODO: Possibly run all timed events as
53 * root */
55 process_blocking_lock_queue();
58 /****************************************************************************
59 We need a version of timeval_min that treats zero timval as infinite.
60 ****************************************************************************/
62 struct timeval timeval_brl_min(const struct timeval *tv1,
63 const struct timeval *tv2)
65 if (timeval_is_zero(tv1)) {
66 return *tv2;
68 if (timeval_is_zero(tv2)) {
69 return *tv1;
71 return timeval_min(tv1, tv2);
74 /****************************************************************************
75 After a change to blocking_lock_queue, recalculate the timed_event for the
76 next processing.
77 ****************************************************************************/
79 static bool recalc_brl_timeout(void)
81 struct smbd_server_connection *sconn = smbd_server_conn;
82 struct blocking_lock_record *blr;
83 struct timeval next_timeout;
84 int max_brl_timeout = lp_parm_int(-1, "brl", "recalctime", 5);
86 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
88 next_timeout = timeval_zero();
90 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
91 if (timeval_is_zero(&blr->expire_time)) {
93 * If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is
94 * a POSIX lock, so calculate a timeout of
95 * 10 seconds into the future.
97 if (blr->blocking_smblctx == 0xFFFFFFFFFFFFFFFFLL) {
98 struct timeval psx_to = timeval_current_ofs(10, 0);
99 next_timeout = timeval_brl_min(&next_timeout, &psx_to);
102 continue;
105 next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time);
108 if (timeval_is_zero(&next_timeout)) {
109 DEBUG(10, ("Next timeout = Infinite.\n"));
110 return True;
114 to account for unclean shutdowns by clients we need a
115 maximum timeout that we use for checking pending locks. If
116 we have any pending locks at all, then check if the pending
117 lock can continue at least every brl:recalctime seconds
118 (default 5 seconds).
120 This saves us needing to do a message_send_all() in the
121 SIGCHLD handler in the parent daemon. That
122 message_send_all() caused O(n^2) work to be done when IP
123 failovers happened in clustered Samba, which could make the
124 entire system unusable for many minutes.
127 if (max_brl_timeout > 0) {
128 struct timeval min_to = timeval_current_ofs(max_brl_timeout, 0);
129 next_timeout = timeval_min(&next_timeout, &min_to);
132 if (DEBUGLVL(10)) {
133 struct timeval cur, from_now;
135 cur = timeval_current();
136 from_now = timeval_until(&cur, &next_timeout);
137 DEBUG(10, ("Next timeout = %d.%d seconds from now.\n",
138 (int)from_now.tv_sec, (int)from_now.tv_usec));
141 if (!(sconn->smb1.locks.brl_timeout = event_add_timed(smbd_event_context(), NULL,
142 next_timeout,
143 brl_timeout_fn, NULL))) {
144 return False;
147 return True;
151 /****************************************************************************
152 Function to push a blocking lock request onto the lock queue.
153 ****************************************************************************/
155 bool push_blocking_lock_request( struct byte_range_lock *br_lck,
156 struct smb_request *req,
157 files_struct *fsp,
158 int lock_timeout,
159 int lock_num,
160 uint64_t smblctx,
161 enum brl_type lock_type,
162 enum brl_flavour lock_flav,
163 uint64_t offset,
164 uint64_t count,
165 uint64_t blocking_smblctx)
167 struct smbd_server_connection *sconn = smbd_server_conn;
168 struct blocking_lock_record *blr;
169 NTSTATUS status;
171 if (req->smb2req) {
172 return push_blocking_lock_request_smb2(br_lck,
173 req,
174 fsp,
175 lock_timeout,
176 lock_num,
177 smblctx,
178 lock_type,
179 lock_flav,
180 offset,
181 count,
182 blocking_smblctx);
185 if(req_is_in_chain(req)) {
186 DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n"));
187 return False;
191 * Now queue an entry on the blocking lock queue. We setup
192 * the expiration time here.
195 blr = talloc(NULL, struct blocking_lock_record);
196 if (blr == NULL) {
197 DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
198 return False;
201 blr->next = NULL;
202 blr->prev = NULL;
204 blr->fsp = fsp;
205 if (lock_timeout == -1) {
206 blr->expire_time.tv_sec = 0;
207 blr->expire_time.tv_usec = 0; /* Never expire. */
208 } else {
209 blr->expire_time = timeval_current_ofs(lock_timeout/1000,
210 (lock_timeout % 1000) * 1000);
212 blr->lock_num = lock_num;
213 blr->smblctx = smblctx;
214 blr->blocking_smblctx = blocking_smblctx;
215 blr->lock_flav = lock_flav;
216 blr->lock_type = lock_type;
217 blr->offset = offset;
218 blr->count = count;
220 /* Specific brl_lock() implementations can fill this in. */
221 blr->blr_private = NULL;
223 /* Add a pending lock record for this. */
224 status = brl_lock(smbd_messaging_context(),
225 br_lck,
226 smblctx,
227 procid_self(),
228 offset,
229 count,
230 lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
231 blr->lock_flav,
232 True,
233 NULL,
234 blr);
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, struct blocking_lock_record *);
246 recalc_brl_timeout();
248 /* Ensure we'll receive messages when this is unlocked. */
249 if (!sconn->smb1.locks.blocking_lock_unlock_state) {
250 messaging_register(smbd_messaging_context(), NULL,
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 fnum = %d, name = %s\n",
257 (unsigned int)blr->expire_time.tv_sec,
258 (unsigned int)blr->expire_time.tv_usec, lock_timeout,
259 blr->fsp->fnum, 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 reply_outbuf(blr->req, 2, 0);
273 * As this message is a lockingX call we must handle
274 * any following chained message correctly.
275 * This is normally handled in construct_reply(),
276 * but as that calls switch_message, we can't use
277 * that here and must set up the chain info manually.
280 chain_reply(blr->req);
281 TALLOC_FREE(blr->req->outbuf);
284 /****************************************************************************
285 Return a generic lock fail error blocking call.
286 *****************************************************************************/
288 static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
290 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
291 FILE_LOCK_CONFLICT! (tridge) */
292 if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
293 status = NT_STATUS_FILE_LOCK_CONFLICT;
296 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
297 /* Store the last lock error. */
298 files_struct *fsp = blr->fsp;
300 if (fsp) {
301 fsp->last_lock_failure.context.smblctx = blr->smblctx;
302 fsp->last_lock_failure.context.tid = fsp->conn->cnum;
303 fsp->last_lock_failure.context.pid = procid_self();
304 fsp->last_lock_failure.start = blr->offset;
305 fsp->last_lock_failure.size = blr->count;
306 fsp->last_lock_failure.fnum = fsp->fnum;
307 fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
308 fsp->last_lock_failure.lock_flav = blr->lock_flav;
312 reply_nterror(blr->req, status);
313 if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf,
314 true, blr->req->seqnum+1,
315 blr->req->encrypted, NULL)) {
316 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
318 TALLOC_FREE(blr->req->outbuf);
321 /****************************************************************************
322 Return a lock fail error for a lockingX call. Undo all the locks we have
323 obtained first.
324 *****************************************************************************/
326 static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS status)
328 files_struct *fsp = blr->fsp;
329 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
330 uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
331 uint64_t smblctx;
332 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
333 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
334 uint8_t *data;
335 int i;
337 data = (uint8_t *)blr->req->buf
338 + ((large_file_format ? 20 : 10)*num_ulocks);
341 * Data now points at the beginning of the list
342 * of smb_lkrng structs.
346 * Ensure we don't do a remove on the lock that just failed,
347 * as under POSIX rules, if we have a lock already there, we
348 * will delete it (and we shouldn't) .....
351 for(i = blr->lock_num - 1; i >= 0; i--) {
352 bool err;
354 smblctx = get_lock_pid( data, i, large_file_format);
355 count = get_lock_count( data, i, large_file_format);
356 offset = get_lock_offset( data, i, large_file_format, &err);
359 * We know err cannot be set as if it was the lock
360 * request would never have been queued. JRA.
363 do_unlock(smbd_messaging_context(),
364 fsp,
365 smblctx,
366 count,
367 offset,
368 WINDOWS_LOCK);
371 generic_blocking_lock_error(blr, status);
374 /****************************************************************************
375 Return a lock fail error.
376 *****************************************************************************/
378 static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
380 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
382 switch(blr->req->cmd) {
383 case SMBlockingX:
384 reply_lockingX_error(blr, status);
385 break;
386 case SMBtrans2:
387 case SMBtranss2:
388 reply_nterror(blr->req, status);
391 * construct_reply_common has done us the favor to pre-fill
392 * the command field with SMBtranss2 which is wrong :-)
394 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
396 if (!srv_send_smb(smbd_server_fd(),
397 (char *)blr->req->outbuf,
398 true, blr->req->seqnum+1,
399 IS_CONN_ENCRYPTED(blr->fsp->conn),
400 NULL)) {
401 exit_server_cleanly("blocking_lock_reply_error: "
402 "srv_send_smb failed.");
404 TALLOC_FREE(blr->req->outbuf);
405 break;
406 default:
407 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
408 exit_server("PANIC - unknown type on blocking lock queue");
412 /****************************************************************************
413 Attempt to finish off getting all pending blocking locks for a lockingX call.
414 Returns True if we want to be removed from the list.
415 *****************************************************************************/
417 static bool process_lockingX(struct blocking_lock_record *blr)
419 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
420 files_struct *fsp = blr->fsp;
421 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
422 uint16 num_locks = SVAL(blr->req->vwv+7, 0);
423 uint64_t count = (uint64_t)0, offset = (uint64_t)0;
424 uint64_t smblctx;
425 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
426 uint8_t *data;
427 NTSTATUS status = NT_STATUS_OK;
429 data = (uint8_t *)blr->req->buf
430 + ((large_file_format ? 20 : 10)*num_ulocks);
433 * Data now points at the beginning of the list
434 * of smb_lkrng structs.
437 for(; blr->lock_num < num_locks; blr->lock_num++) {
438 struct byte_range_lock *br_lck = NULL;
439 bool err;
441 smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
442 count = get_lock_count( data, blr->lock_num, large_file_format);
443 offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
446 * We know err cannot be set as if it was the lock
447 * request would never have been queued. JRA.
449 errno = 0;
450 br_lck = do_lock(smbd_messaging_context(),
451 fsp,
452 smblctx,
453 count,
454 offset,
455 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
456 READ_LOCK : WRITE_LOCK),
457 WINDOWS_LOCK,
458 True,
459 &status,
460 &blr->blocking_smblctx,
461 blr);
463 TALLOC_FREE(br_lck);
465 if (NT_STATUS_IS_ERR(status)) {
466 break;
470 if(blr->lock_num == num_locks) {
472 * Success - we got all the locks.
475 DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d "
476 "num_locks=%d\n", fsp_str_dbg(fsp), fsp->fnum,
477 (unsigned int)locktype, num_locks));
479 reply_lockingX_success(blr);
480 return True;
483 if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
484 !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
486 * We have other than a "can't get lock"
487 * error. Free any locks we had and return an error.
488 * Return True so we get dequeued.
490 blocking_lock_reply_error(blr, status);
491 return True;
495 * Still can't get all the locks - keep waiting.
498 DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
499 Waiting....\n",
500 blr->lock_num, num_locks, fsp_str_dbg(fsp), fsp->fnum));
502 return False;
505 /****************************************************************************
506 Attempt to get the posix lock request from a SMBtrans2 call.
507 Returns True if we want to be removed from the list.
508 *****************************************************************************/
510 static bool process_trans2(struct blocking_lock_record *blr)
512 char params[2];
513 NTSTATUS status;
514 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
515 blr->fsp,
516 blr->smblctx,
517 blr->count,
518 blr->offset,
519 blr->lock_type,
520 blr->lock_flav,
521 True,
522 &status,
523 &blr->blocking_smblctx,
524 blr);
525 TALLOC_FREE(br_lck);
527 if (!NT_STATUS_IS_OK(status)) {
528 if (ERROR_WAS_LOCK_DENIED(status)) {
529 /* Still can't get the lock, just keep waiting. */
530 return False;
533 * We have other than a "can't get lock"
534 * error. Send an error and return True so we get dequeued.
536 blocking_lock_reply_error(blr, status);
537 return True;
540 /* We finally got the lock, return success. */
542 SSVAL(params,0,0);
543 /* Fake up max_data_bytes here - we know it fits. */
544 send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff);
545 return True;
549 /****************************************************************************
550 Process a blocking lock SMB.
551 Returns True if we want to be removed from the list.
552 *****************************************************************************/
554 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
556 switch(blr->req->cmd) {
557 case SMBlockingX:
558 return process_lockingX(blr);
559 case SMBtrans2:
560 case SMBtranss2:
561 return process_trans2(blr);
562 default:
563 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
564 exit_server("PANIC - unknown type on blocking lock queue");
566 return False; /* Keep compiler happy. */
569 /****************************************************************************
570 Cancel entries by fnum from the blocking lock pending queue.
571 Called when a file is closed.
572 *****************************************************************************/
574 void cancel_pending_lock_requests_by_fid(files_struct *fsp,
575 struct byte_range_lock *br_lck,
576 enum file_close_type close_type)
578 struct smbd_server_connection *sconn = smbd_server_conn;
579 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
581 if (sconn->allow_smb2) {
582 cancel_pending_lock_requests_by_fid_smb2(fsp,
583 br_lck,
584 close_type);
585 return;
588 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
589 unsigned char locktype = 0;
591 next = blr->next;
592 if (blr->fsp->fnum != fsp->fnum) {
593 continue;
596 if (blr->req->cmd == SMBlockingX) {
597 locktype = CVAL(blr->req->vwv+3, 0);
600 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
601 "request type %d for file %s fnum = %d\n",
602 blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum));
604 blr_cancelled = blocking_lock_cancel_smb1(fsp,
605 blr->smblctx,
606 blr->offset,
607 blr->count,
608 blr->lock_flav,
609 locktype,
610 NT_STATUS_RANGE_NOT_LOCKED);
612 SMB_ASSERT(blr_cancelled == blr);
614 brl_lock_cancel(br_lck,
615 blr->smblctx,
616 procid_self(),
617 blr->offset,
618 blr->count,
619 blr->lock_flav,
620 blr);
622 /* We're closing the file fsp here, so ensure
623 * we don't have a dangling pointer. */
624 blr->fsp = NULL;
628 /****************************************************************************
629 Delete entries by mid from the blocking lock pending queue. Always send reply.
630 Only called from the SMB1 cancel code.
631 *****************************************************************************/
633 void remove_pending_lock_requests_by_mid_smb1(uint64_t mid)
635 struct smbd_server_connection *sconn = smbd_server_conn;
636 struct blocking_lock_record *blr, *next = NULL;
638 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
639 files_struct *fsp;
640 struct byte_range_lock *br_lck;
642 next = blr->next;
644 if (blr->req->mid != mid) {
645 continue;
648 fsp = blr->fsp;
649 br_lck = brl_get_locks(talloc_tos(), fsp);
651 if (br_lck) {
652 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
653 "removing request type %d for file %s fnum "
654 "= %d\n", blr->req->cmd, fsp_str_dbg(fsp),
655 fsp->fnum ));
657 brl_lock_cancel(br_lck,
658 blr->smblctx,
659 procid_self(),
660 blr->offset,
661 blr->count,
662 blr->lock_flav,
663 blr);
664 TALLOC_FREE(br_lck);
667 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
668 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
669 TALLOC_FREE(blr);
673 /****************************************************************************
674 Is this mid a blocking lock request on the queue ?
675 Currently only called from the SMB1 unix extensions POSIX lock code.
676 *****************************************************************************/
678 bool blocking_lock_was_deferred_smb1(uint64_t mid)
680 struct smbd_server_connection *sconn = smbd_server_conn;
681 struct blocking_lock_record *blr, *next = NULL;
683 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
684 next = blr->next;
685 if(blr->req->mid == mid) {
686 return True;
689 return False;
692 /****************************************************************************
693 Set a flag as an unlock request affects one of our pending locks.
694 *****************************************************************************/
696 static void received_unlock_msg(struct messaging_context *msg,
697 void *private_data,
698 uint32_t msg_type,
699 struct server_id server_id,
700 DATA_BLOB *data)
702 DEBUG(10,("received_unlock_msg\n"));
703 process_blocking_lock_queue();
706 /****************************************************************************
707 Process the blocking lock queue. Note that this is only called as root.
708 *****************************************************************************/
710 void process_blocking_lock_queue(void)
712 struct smbd_server_connection *sconn = smbd_server_conn;
713 struct timeval tv_curr = timeval_current();
714 struct blocking_lock_record *blr, *next = NULL;
716 if (sconn->allow_smb2) {
717 process_blocking_lock_queue_smb2(tv_curr);
718 return;
722 * Go through the queue and see if we can get any of the locks.
725 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
727 next = blr->next;
730 * Go through the remaining locks and try and obtain them.
731 * The call returns True if all locks were obtained successfully
732 * and False if we still need to wait.
735 DEBUG(10, ("Processing BLR = %p\n", blr));
737 /* We use set_current_service so connections with
738 * pending locks are not marked as idle.
741 set_current_service(blr->fsp->conn,
742 SVAL(blr->req->inbuf,smb_flg),
743 false);
745 if(blocking_lock_record_process(blr)) {
746 struct byte_range_lock *br_lck = brl_get_locks(
747 talloc_tos(), blr->fsp);
749 DEBUG(10, ("BLR_process returned true: cancelling and "
750 "removing lock. BLR = %p\n", blr));
752 if (br_lck) {
753 brl_lock_cancel(br_lck,
754 blr->smblctx,
755 procid_self(),
756 blr->offset,
757 blr->count,
758 blr->lock_flav,
759 blr);
760 TALLOC_FREE(br_lck);
763 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
764 TALLOC_FREE(blr);
765 continue;
769 * We couldn't get the locks for this record on the list.
770 * If the time has expired, return a lock error.
773 if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
774 struct byte_range_lock *br_lck = brl_get_locks(
775 talloc_tos(), blr->fsp);
777 DEBUG(10, ("Lock timed out! BLR = %p\n", blr));
780 * Lock expired - throw away all previously
781 * obtained locks and return lock error.
784 if (br_lck) {
785 DEBUG(5,("process_blocking_lock_queue: "
786 "pending lock fnum = %d for file %s "
787 "timed out.\n", blr->fsp->fnum,
788 fsp_str_dbg(blr->fsp)));
790 brl_lock_cancel(br_lck,
791 blr->smblctx,
792 procid_self(),
793 blr->offset,
794 blr->count,
795 blr->lock_flav,
796 blr);
797 TALLOC_FREE(br_lck);
800 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
801 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
802 TALLOC_FREE(blr);
806 recalc_brl_timeout();
809 /****************************************************************************
810 Handle a cancel message. Lock already moved onto the cancel queue.
811 *****************************************************************************/
813 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
815 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
816 void *private_data,
817 uint32_t msg_type,
818 struct server_id server_id,
819 DATA_BLOB *data)
821 struct smbd_server_connection *sconn = smbd_server_conn;
822 NTSTATUS err;
823 const char *msg = (const char *)data->data;
824 struct blocking_lock_record *blr;
826 if (data->data == NULL) {
827 smb_panic("process_blocking_lock_cancel_message: null msg");
830 if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
831 DEBUG(0, ("process_blocking_lock_cancel_message: "
832 "Got invalid msg len %d\n", (int)data->length));
833 smb_panic("process_blocking_lock_cancel_message: bad msg");
836 memcpy(&blr, msg, sizeof(blr));
837 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
839 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
840 nt_errstr(err) ));
842 blocking_lock_reply_error(blr, err);
843 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
844 TALLOC_FREE(blr);
847 /****************************************************************************
848 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
849 Returns the blocking_lock_record that is being cancelled.
850 Only called from the SMB1 code.
851 *****************************************************************************/
853 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
854 uint64_t smblctx,
855 uint64_t offset,
856 uint64_t count,
857 enum brl_flavour lock_flav,
858 unsigned char locktype,
859 NTSTATUS err)
861 struct smbd_server_connection *sconn = smbd_server_conn;
862 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
863 struct blocking_lock_record *blr;
865 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
866 /* Register our message. */
867 messaging_register(smbd_messaging_context(), NULL,
868 MSG_SMB_BLOCKING_LOCK_CANCEL,
869 process_blocking_lock_cancel_message);
871 sconn->smb1.locks.blocking_lock_cancel_state = True;
874 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
875 if (fsp == blr->fsp &&
876 smblctx == blr->smblctx &&
877 offset == blr->offset &&
878 count == blr->count &&
879 lock_flav == blr->lock_flav) {
880 break;
884 if (!blr) {
885 return NULL;
888 /* Check the flags are right. */
889 if (blr->req->cmd == SMBlockingX &&
890 (locktype & LOCKING_ANDX_LARGE_FILES) !=
891 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
892 return NULL;
895 /* Move to cancelled queue. */
896 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
897 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
899 /* Create the message. */
900 memcpy(msg, &blr, sizeof(blr));
901 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
903 messaging_send_buf(smbd_messaging_context(), procid_self(),
904 MSG_SMB_BLOCKING_LOCK_CANCEL,
905 (uint8 *)&msg, sizeof(msg));
907 return blr;