source: vendor/current/source3/smbd/blocking.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 27.5 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Blocking Locking functions
4 Copyright (C) Jeremy Allison 1998-2003
5
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.
10
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.
15
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/>.
18*/
19
20#include "includes.h"
21#include "smbd/smbd.h"
22#include "smbd/globals.h"
23#include "messages.h"
24
25#undef DBGC_CLASS
26#define DBGC_CLASS DBGC_LOCKING
27
28static void received_unlock_msg(struct messaging_context *msg,
29 void *private_data,
30 uint32_t msg_type,
31 struct server_id server_id,
32 DATA_BLOB *data);
33
34void brl_timeout_fn(struct tevent_context *event_ctx,
35 struct tevent_timer *te,
36 struct timeval now,
37 void *private_data)
38{
39 struct smbd_server_connection *sconn = talloc_get_type_abort(
40 private_data, struct smbd_server_connection);
41
42 if (sconn->using_smb2) {
43 SMB_ASSERT(sconn->smb2.locks.brl_timeout == te);
44 TALLOC_FREE(sconn->smb2.locks.brl_timeout);
45 } else {
46 SMB_ASSERT(sconn->smb1.locks.brl_timeout == te);
47 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
48 }
49
50 change_to_root_user(); /* TODO: Possibly run all timed events as
51 * root */
52
53 process_blocking_lock_queue(sconn);
54}
55
56/****************************************************************************
57 We need a version of timeval_min that treats zero timval as infinite.
58****************************************************************************/
59
60struct timeval timeval_brl_min(const struct timeval *tv1,
61 const struct timeval *tv2)
62{
63 if (timeval_is_zero(tv1)) {
64 return *tv2;
65 }
66 if (timeval_is_zero(tv2)) {
67 return *tv1;
68 }
69 return timeval_min(tv1, tv2);
70}
71
72/****************************************************************************
73 After a change to blocking_lock_queue, recalculate the timed_event for the
74 next processing.
75****************************************************************************/
76
77static bool recalc_brl_timeout(struct smbd_server_connection *sconn)
78{
79 struct blocking_lock_record *blr;
80 struct timeval next_timeout;
81 int max_brl_timeout = lp_parm_int(-1, "brl", "recalctime", 5);
82
83 TALLOC_FREE(sconn->smb1.locks.brl_timeout);
84
85 next_timeout = timeval_zero();
86
87 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
88 if (timeval_is_zero(&blr->expire_time)) {
89 /*
90 * If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is
91 * a POSIX lock, so calculate a timeout of
92 * 10 seconds into the future.
93 */
94 if (blr->blocking_smblctx == 0xFFFFFFFFFFFFFFFFLL) {
95 struct timeval psx_to = timeval_current_ofs(10, 0);
96 next_timeout = timeval_brl_min(&next_timeout, &psx_to);
97 }
98
99 continue;
100 }
101
102 next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time);
103 }
104
105 if (timeval_is_zero(&next_timeout)) {
106 DEBUG(10, ("Next timeout = Infinite.\n"));
107 return True;
108 }
109
110 /*
111 to account for unclean shutdowns by clients we need a
112 maximum timeout that we use for checking pending locks. If
113 we have any pending locks at all, then check if the pending
114 lock can continue at least every brl:recalctime seconds
115 (default 5 seconds).
116
117 This saves us needing to do a message_send_all() in the
118 SIGCHLD handler in the parent daemon. That
119 message_send_all() caused O(n^2) work to be done when IP
120 failovers happened in clustered Samba, which could make the
121 entire system unusable for many minutes.
122 */
123
124 if (max_brl_timeout > 0) {
125 struct timeval min_to = timeval_current_ofs(max_brl_timeout, 0);
126 next_timeout = timeval_min(&next_timeout, &min_to);
127 }
128
129 if (DEBUGLVL(10)) {
130 struct timeval cur, from_now;
131
132 cur = timeval_current();
133 from_now = timeval_until(&cur, &next_timeout);
134 DEBUG(10, ("Next timeout = %d.%d seconds from now.\n",
135 (int)from_now.tv_sec, (int)from_now.tv_usec));
136 }
137
138 sconn->smb1.locks.brl_timeout = tevent_add_timer(sconn->ev_ctx,
139 NULL, next_timeout,
140 brl_timeout_fn, sconn);
141 if (sconn->smb1.locks.brl_timeout == NULL) {
142 return False;
143 }
144
145 return True;
146}
147
148
149/****************************************************************************
150 Function to push a blocking lock request onto the lock queue.
151****************************************************************************/
152
153bool push_blocking_lock_request( struct byte_range_lock *br_lck,
154 struct smb_request *req,
155 files_struct *fsp,
156 int lock_timeout,
157 int lock_num,
158 uint64_t smblctx,
159 enum brl_type lock_type,
160 enum brl_flavour lock_flav,
161 uint64_t offset,
162 uint64_t count,
163 uint64_t blocking_smblctx)
164{
165 struct smbd_server_connection *sconn = req->sconn;
166 struct blocking_lock_record *blr;
167 NTSTATUS status;
168
169 if (req->smb2req) {
170 return push_blocking_lock_request_smb2(br_lck,
171 req,
172 fsp,
173 lock_timeout,
174 lock_num,
175 smblctx,
176 lock_type,
177 lock_flav,
178 offset,
179 count,
180 blocking_smblctx);
181 }
182
183 if(req_is_in_chain(req)) {
184 DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n"));
185 return False;
186 }
187
188 /*
189 * Now queue an entry on the blocking lock queue. We setup
190 * the expiration time here.
191 */
192
193 blr = talloc(NULL, struct blocking_lock_record);
194 if (blr == NULL) {
195 DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
196 return False;
197 }
198
199 blr->next = NULL;
200 blr->prev = NULL;
201
202 blr->fsp = fsp;
203 if (lock_timeout == -1) {
204 blr->expire_time.tv_sec = 0;
205 blr->expire_time.tv_usec = 0; /* Never expire. */
206 } else {
207 blr->expire_time = timeval_current_ofs_msec(lock_timeout);
208 }
209 blr->lock_num = lock_num;
210 blr->smblctx = smblctx;
211 blr->blocking_smblctx = blocking_smblctx;
212 blr->lock_flav = lock_flav;
213 blr->lock_type = lock_type;
214 blr->offset = offset;
215 blr->count = count;
216
217 /* Specific brl_lock() implementations can fill this in. */
218 blr->blr_private = NULL;
219
220 /* Add a pending lock record for this. */
221 status = brl_lock(req->sconn->msg_ctx,
222 br_lck,
223 smblctx,
224 messaging_server_id(req->sconn->msg_ctx),
225 offset,
226 count,
227 lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
228 blr->lock_flav,
229 True,
230 NULL);
231
232 if (!NT_STATUS_IS_OK(status)) {
233 DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
234 TALLOC_FREE(blr);
235 return False;
236 }
237
238 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd);
239 blr->req = talloc_move(blr, &req);
240
241 DLIST_ADD_END(sconn->smb1.locks.blocking_lock_queue, blr);
242 recalc_brl_timeout(sconn);
243
244 /* Ensure we'll receive messages when this is unlocked. */
245 if (!sconn->smb1.locks.blocking_lock_unlock_state) {
246 messaging_register(sconn->msg_ctx, sconn,
247 MSG_SMB_UNLOCK, received_unlock_msg);
248 sconn->smb1.locks.blocking_lock_unlock_state = true;
249 }
250
251 DEBUG(3,("push_blocking_lock_request: lock request blocked with "
252 "expiry time (%u sec. %u usec) (+%d msec) for %s, name = %s\n",
253 (unsigned int)blr->expire_time.tv_sec,
254 (unsigned int)blr->expire_time.tv_usec, lock_timeout,
255 fsp_fnum_dbg(blr->fsp), fsp_str_dbg(blr->fsp)));
256
257 return True;
258}
259
260/****************************************************************************
261 Return a lockingX success SMB.
262*****************************************************************************/
263
264static void reply_lockingX_success(struct blocking_lock_record *blr)
265{
266 struct smb_request *req = blr->req;
267
268 reply_outbuf(req, 2, 0);
269 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
270 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
271
272 /*
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.
278 */
279
280 if (!srv_send_smb(req->xconn,
281 (char *)req->outbuf,
282 true, req->seqnum+1,
283 IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
284 &req->pcd)) {
285 exit_server_cleanly("construct_reply: srv_send_smb failed.");
286 }
287
288 TALLOC_FREE(req->outbuf);
289}
290
291/****************************************************************************
292 Return a generic lock fail error blocking call.
293*****************************************************************************/
294
295static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
296{
297 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
298 FILE_LOCK_CONFLICT! (tridge) */
299 if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
300 status = NT_STATUS_FILE_LOCK_CONFLICT;
301 }
302
303 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
304 /* Store the last lock error. */
305 files_struct *fsp = blr->fsp;
306
307 if (fsp) {
308 fsp->last_lock_failure.context.smblctx = blr->smblctx;
309 fsp->last_lock_failure.context.tid = fsp->conn->cnum;
310 fsp->last_lock_failure.context.pid =
311 messaging_server_id(fsp->conn->sconn->msg_ctx);
312 fsp->last_lock_failure.start = blr->offset;
313 fsp->last_lock_failure.size = blr->count;
314 fsp->last_lock_failure.fnum = fsp->fnum;
315 fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
316 fsp->last_lock_failure.lock_flav = blr->lock_flav;
317 }
318 }
319
320 reply_nterror(blr->req, status);
321 if (!srv_send_smb(blr->req->xconn, (char *)blr->req->outbuf,
322 true, blr->req->seqnum+1,
323 blr->req->encrypted, NULL)) {
324 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
325 }
326 TALLOC_FREE(blr->req->outbuf);
327}
328
329/****************************************************************************
330 Return a lock fail error for a lockingX call. Undo all the locks we have
331 obtained first.
332*****************************************************************************/
333
334static void undo_locks_obtained(struct blocking_lock_record *blr)
335{
336 files_struct *fsp = blr->fsp;
337 uint16_t num_ulocks = SVAL(blr->req->vwv+6, 0);
338 uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
339 uint64_t smblctx;
340 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
341 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
342 uint8_t *data;
343 int i;
344
345 data = discard_const_p(uint8_t, blr->req->buf)
346 + ((large_file_format ? 20 : 10)*num_ulocks);
347
348 /*
349 * Data now points at the beginning of the list
350 * of smb_lkrng structs.
351 */
352
353 /*
354 * Ensure we don't do a remove on the lock that just failed,
355 * as under POSIX rules, if we have a lock already there, we
356 * will delete it (and we shouldn't) .....
357 */
358
359 for(i = blr->lock_num - 1; i >= 0; i--) {
360
361 smblctx = get_lock_pid( data, i, large_file_format);
362 count = get_lock_count( data, i, large_file_format);
363 offset = get_lock_offset( data, i, large_file_format);
364
365 /*
366 * We know err cannot be set as if it was the lock
367 * request would never have been queued. JRA.
368 */
369
370 do_unlock(fsp->conn->sconn->msg_ctx,
371 fsp,
372 smblctx,
373 count,
374 offset,
375 WINDOWS_LOCK);
376 }
377}
378
379/****************************************************************************
380 Return a lock fail error.
381*****************************************************************************/
382
383static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
384{
385 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
386
387 switch(blr->req->cmd) {
388 case SMBlockingX:
389 /*
390 * This code can be called during the rundown of a
391 * file after it was already closed. In that case,
392 * blr->fsp==NULL and we do not need to undo any
393 * locks, they are already gone.
394 */
395 if (blr->fsp != NULL) {
396 undo_locks_obtained(blr);
397 }
398 generic_blocking_lock_error(blr, status);
399 break;
400 case SMBtrans2:
401 case SMBtranss2:
402 reply_nterror(blr->req, status);
403
404 /*
405 * construct_reply_common has done us the favor to pre-fill
406 * the command field with SMBtranss2 which is wrong :-)
407 */
408 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
409
410 if (!srv_send_smb(blr->req->xconn,
411 (char *)blr->req->outbuf,
412 true, blr->req->seqnum+1,
413 IS_CONN_ENCRYPTED(blr->fsp->conn),
414 NULL)) {
415 exit_server_cleanly("blocking_lock_reply_error: "
416 "srv_send_smb failed.");
417 }
418 TALLOC_FREE(blr->req->outbuf);
419 break;
420 default:
421 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
422 exit_server("PANIC - unknown type on blocking lock queue");
423 }
424}
425
426/****************************************************************************
427 Utility function that returns true if a lock timed out.
428*****************************************************************************/
429
430static bool lock_timed_out(const struct blocking_lock_record *blr)
431{
432 struct timeval tv_curr;
433
434 if (timeval_is_zero(&blr->expire_time)) {
435 return false; /* Never times out. */
436 }
437
438 tv_curr = timeval_current();
439 if (timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
440 return true;
441 }
442 return false;
443}
444
445/****************************************************************************
446 Attempt to finish off getting all pending blocking locks for a lockingX call.
447 Returns True if we want to be removed from the list.
448*****************************************************************************/
449
450static bool process_lockingX(struct blocking_lock_record *blr)
451{
452 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
453 files_struct *fsp = blr->fsp;
454 uint16_t num_ulocks = SVAL(blr->req->vwv+6, 0);
455 uint16_t num_locks = SVAL(blr->req->vwv+7, 0);
456 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
457 uint8_t *data;
458 NTSTATUS status = NT_STATUS_OK;
459 bool lock_timeout = lock_timed_out(blr);
460
461 data = discard_const_p(uint8_t, blr->req->buf)
462 + ((large_file_format ? 20 : 10)*num_ulocks);
463
464 /*
465 * Data now points at the beginning of the list
466 * of smb_lkrng structs.
467 */
468
469 for(; blr->lock_num < num_locks; blr->lock_num++) {
470 struct byte_range_lock *br_lck = NULL;
471
472 /*
473 * Ensure the blr record gets updated with
474 * any lock we might end up blocked on.
475 */
476
477 blr->smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
478 blr->count = get_lock_count( data, blr->lock_num, large_file_format);
479 blr->offset = get_lock_offset( data, blr->lock_num, large_file_format);
480
481 /*
482 * We know err cannot be set as if it was the lock
483 * request would never have been queued. JRA.
484 */
485 errno = 0;
486 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
487 fsp,
488 blr->smblctx,
489 blr->count,
490 blr->offset,
491 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
492 READ_LOCK : WRITE_LOCK),
493 WINDOWS_LOCK,
494 True,
495 &status,
496 &blr->blocking_smblctx);
497
498 if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
499 /*
500 * If we didn't timeout, but still need to wait,
501 * re-add the pending lock entry whilst holding
502 * the brlock db lock.
503 */
504 NTSTATUS status1 =
505 brl_lock(blr->fsp->conn->sconn->msg_ctx,
506 br_lck,
507 blr->smblctx,
508 messaging_server_id(
509 blr->fsp->conn->sconn->msg_ctx),
510 blr->offset,
511 blr->count,
512 blr->lock_type == READ_LOCK ?
513 PENDING_READ_LOCK :
514 PENDING_WRITE_LOCK,
515 blr->lock_flav,
516 true, /* Blocking lock. */
517 NULL);
518
519 if (!NT_STATUS_IS_OK(status1)) {
520 DEBUG(0,("failed to add PENDING_LOCK "
521 "record.\n"));
522 }
523 }
524
525 TALLOC_FREE(br_lck);
526
527 if (NT_STATUS_IS_ERR(status)) {
528 break;
529 }
530 }
531
532 if(blr->lock_num == num_locks) {
533 /*
534 * Success - we got all the locks.
535 */
536
537 DEBUG(3,("process_lockingX file = %s, %s, type=%d "
538 "num_locks=%d\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
539 (unsigned int)locktype, num_locks));
540
541 reply_lockingX_success(blr);
542 return True;
543 }
544
545 if (!ERROR_WAS_LOCK_DENIED(status)) {
546 /*
547 * We have other than a "can't get lock"
548 * error. Free any locks we had and return an error.
549 * Return True so we get dequeued.
550 */
551 blocking_lock_reply_error(blr, status);
552 return True;
553 }
554
555 /*
556 * Return an error to the client if we timed out.
557 */
558 if (lock_timeout) {
559 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
560 return true;
561 }
562
563 /*
564 * Still can't get all the locks - keep waiting.
565 */
566
567 DEBUG(10, ("process_lockingX: only got %d locks of %d needed for "
568 "file %s, %s. Waiting....\n",
569 blr->lock_num, num_locks, fsp_str_dbg(fsp),
570 fsp_fnum_dbg(fsp)));
571
572 return False;
573}
574
575/****************************************************************************
576 Attempt to get the posix lock request from a SMBtrans2 call.
577 Returns True if we want to be removed from the list.
578*****************************************************************************/
579
580static bool process_trans2(struct blocking_lock_record *blr)
581{
582 char params[2];
583 NTSTATUS status;
584 bool lock_timeout = lock_timed_out(blr);
585
586 struct byte_range_lock *br_lck = do_lock(
587 blr->fsp->conn->sconn->msg_ctx,
588 blr->fsp,
589 blr->smblctx,
590 blr->count,
591 blr->offset,
592 blr->lock_type,
593 blr->lock_flav,
594 True,
595 &status,
596 &blr->blocking_smblctx);
597 if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
598 /*
599 * If we didn't timeout, but still need to wait,
600 * re-add the pending lock entry whilst holding
601 * the brlock db lock.
602 */
603 NTSTATUS status1 =
604 brl_lock(blr->fsp->conn->sconn->msg_ctx,
605 br_lck,
606 blr->smblctx,
607 messaging_server_id(
608 blr->fsp->conn->sconn->msg_ctx),
609 blr->offset,
610 blr->count,
611 blr->lock_type == READ_LOCK ?
612 PENDING_READ_LOCK :
613 PENDING_WRITE_LOCK,
614 blr->lock_flav,
615 true, /* Blocking lock. */
616 NULL);
617
618 if (!NT_STATUS_IS_OK(status1)) {
619 DEBUG(0,("failed to add PENDING_LOCK record.\n"));
620 }
621 }
622
623 TALLOC_FREE(br_lck);
624
625 if (!NT_STATUS_IS_OK(status)) {
626 if (ERROR_WAS_LOCK_DENIED(status)) {
627 if (lock_timeout) {
628 /*
629 * Return an error if we timed out
630 * and return true to get dequeued.
631 */
632 blocking_lock_reply_error(blr,
633 NT_STATUS_FILE_LOCK_CONFLICT);
634 return true;
635 }
636 /* Still can't get the lock, just keep waiting. */
637 return False;
638 }
639 /*
640 * We have other than a "can't get lock"
641 * error. Send an error and return True so we get dequeued.
642 */
643 blocking_lock_reply_error(blr, status);
644 return True;
645 }
646
647 /* We finally got the lock, return success. */
648
649 SSVAL(params,0,0);
650 /* Fake up max_data_bytes here - we know it fits. */
651 send_trans2_replies(blr->fsp->conn, blr->req, NT_STATUS_OK, params, 2, NULL, 0, 0xffff);
652 return True;
653}
654
655
656/****************************************************************************
657 Process a blocking lock SMB.
658 Returns True if we want to be removed from the list.
659*****************************************************************************/
660
661static bool blocking_lock_record_process(struct blocking_lock_record *blr)
662{
663 switch(blr->req->cmd) {
664 case SMBlockingX:
665 return process_lockingX(blr);
666 case SMBtrans2:
667 case SMBtranss2:
668 return process_trans2(blr);
669 default:
670 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
671 exit_server("PANIC - unknown type on blocking lock queue");
672 }
673 return False; /* Keep compiler happy. */
674}
675
676/****************************************************************************
677 Cancel entries by fnum from the blocking lock pending queue.
678 Called when a file is closed.
679*****************************************************************************/
680
681void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp,
682 struct byte_range_lock *br_lck,
683 enum file_close_type close_type)
684{
685 struct smbd_server_connection *sconn = fsp->conn->sconn;
686 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
687
688 if (sconn->using_smb2) {
689 cancel_pending_lock_requests_by_fid_smb2(fsp,
690 br_lck,
691 close_type);
692 return;
693 }
694
695 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
696 unsigned char locktype = 0;
697
698 next = blr->next;
699 if (blr->fsp->fnum != fsp->fnum) {
700 continue;
701 }
702
703 if (blr->req->cmd == SMBlockingX) {
704 locktype = CVAL(blr->req->vwv+3, 0);
705 }
706
707 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
708 "request type %d for file %s, %s\n",
709 blr->req->cmd, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
710
711 blr_cancelled = blocking_lock_cancel_smb1(fsp,
712 blr->smblctx,
713 blr->offset,
714 blr->count,
715 blr->lock_flav,
716 locktype,
717 NT_STATUS_RANGE_NOT_LOCKED);
718
719 SMB_ASSERT(blr_cancelled == blr);
720
721 brl_lock_cancel(br_lck,
722 blr->smblctx,
723 messaging_server_id(sconn->msg_ctx),
724 blr->offset,
725 blr->count,
726 blr->lock_flav);
727
728 /* We're closing the file fsp here, so ensure
729 * we don't have a dangling pointer. */
730 blr->fsp = NULL;
731 }
732}
733
734/****************************************************************************
735 Delete entries by mid from the blocking lock pending queue. Always send reply.
736 Only called from the SMB1 cancel code.
737*****************************************************************************/
738
739void remove_pending_lock_requests_by_mid_smb1(
740 struct smbd_server_connection *sconn, uint64_t mid)
741{
742 struct blocking_lock_record *blr, *next = NULL;
743
744 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
745 files_struct *fsp;
746 struct byte_range_lock *br_lck;
747
748 next = blr->next;
749
750 if (blr->req->mid != mid) {
751 continue;
752 }
753
754 fsp = blr->fsp;
755 br_lck = brl_get_locks(talloc_tos(), fsp);
756
757 if (br_lck) {
758 DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
759 "removing request type %d for file %s, %s\n",
760 blr->req->cmd, fsp_str_dbg(fsp),
761 fsp_fnum_dbg(fsp)));
762
763 brl_lock_cancel(br_lck,
764 blr->smblctx,
765 messaging_server_id(sconn->msg_ctx),
766 blr->offset,
767 blr->count,
768 blr->lock_flav);
769 TALLOC_FREE(br_lck);
770 }
771
772 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
773 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
774 TALLOC_FREE(blr);
775 }
776}
777
778/****************************************************************************
779 Is this mid a blocking lock request on the queue ?
780 Currently only called from the SMB1 unix extensions POSIX lock code.
781*****************************************************************************/
782
783bool blocking_lock_was_deferred_smb1(
784 struct smbd_server_connection *sconn, uint64_t mid)
785{
786 struct blocking_lock_record *blr, *next = NULL;
787
788 for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
789 next = blr->next;
790 if(blr->req->mid == mid) {
791 return True;
792 }
793 }
794 return False;
795}
796
797/****************************************************************************
798 Set a flag as an unlock request affects one of our pending locks.
799*****************************************************************************/
800
801static void received_unlock_msg(struct messaging_context *msg,
802 void *private_data,
803 uint32_t msg_type,
804 struct server_id server_id,
805 DATA_BLOB *data)
806{
807 struct smbd_server_connection *sconn =
808 talloc_get_type_abort(private_data,
809 struct smbd_server_connection);
810
811 DEBUG(10,("received_unlock_msg\n"));
812 process_blocking_lock_queue(sconn);
813}
814
815/****************************************************************************
816 Process the blocking lock queue. Note that this is only called as root.
817*****************************************************************************/
818
819void process_blocking_lock_queue(struct smbd_server_connection *sconn)
820{
821 struct blocking_lock_record *blr, *next = NULL;
822
823 if (sconn->using_smb2) {
824 process_blocking_lock_queue_smb2(sconn, timeval_current());
825 return;
826 }
827
828 /*
829 * Go through the queue and see if we can get any of the locks.
830 */
831
832 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
833 struct byte_range_lock *br_lck = NULL;
834
835 next = blr->next;
836
837 /*
838 * Go through the remaining locks and try and obtain them.
839 * The call returns True if all locks were obtained successfully
840 * and False if we still need to wait.
841 */
842
843 DEBUG(10, ("Processing BLR = %p\n", blr));
844
845 /* We use set_current_service so connections with
846 * pending locks are not marked as idle.
847 */
848
849 set_current_service(blr->fsp->conn,
850 SVAL(blr->req->inbuf,smb_flg),
851 false);
852
853 /*
854 * Remove the pending lock we're waiting on.
855 * If we need to keep waiting blocking_lock_record_process()
856 * will re-add it.
857 */
858
859 br_lck = brl_get_locks(talloc_tos(), blr->fsp);
860 if (br_lck) {
861 brl_lock_cancel(br_lck,
862 blr->smblctx,
863 messaging_server_id(sconn->msg_ctx),
864 blr->offset,
865 blr->count,
866 blr->lock_flav);
867 }
868 TALLOC_FREE(br_lck);
869
870 if(!blocking_lock_record_process(blr)) {
871 DEBUG(10, ("still waiting for lock. BLR = %p\n", blr));
872 continue;
873 }
874
875 DEBUG(10, ("BLR_process returned true: removing BLR = %p\n",
876 blr));
877
878 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
879 TALLOC_FREE(blr);
880 }
881
882 recalc_brl_timeout(sconn);
883}
884
885/****************************************************************************
886 Handle a cancel message. Lock already moved onto the cancel queue.
887*****************************************************************************/
888
889#define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
890
891static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
892 void *private_data,
893 uint32_t msg_type,
894 struct server_id server_id,
895 DATA_BLOB *data)
896{
897 NTSTATUS err;
898 const char *msg = (const char *)data->data;
899 struct blocking_lock_record *blr;
900 struct smbd_server_connection *sconn =
901 talloc_get_type_abort(private_data,
902 struct smbd_server_connection);
903
904 if (data->data == NULL) {
905 smb_panic("process_blocking_lock_cancel_message: null msg");
906 }
907
908 if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
909 DEBUG(0, ("process_blocking_lock_cancel_message: "
910 "Got invalid msg len %d\n", (int)data->length));
911 smb_panic("process_blocking_lock_cancel_message: bad msg");
912 }
913
914 memcpy(&blr, msg, sizeof(blr));
915 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
916
917 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
918 nt_errstr(err) ));
919
920 blocking_lock_reply_error(blr, err);
921 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
922 TALLOC_FREE(blr);
923}
924
925/****************************************************************************
926 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
927 Returns the blocking_lock_record that is being cancelled.
928 Only called from the SMB1 code.
929*****************************************************************************/
930
931struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
932 uint64_t smblctx,
933 uint64_t offset,
934 uint64_t count,
935 enum brl_flavour lock_flav,
936 unsigned char locktype,
937 NTSTATUS err)
938{
939 struct smbd_server_connection *sconn = fsp->conn->sconn;
940 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
941 struct blocking_lock_record *blr;
942
943 if (!sconn->smb1.locks.blocking_lock_cancel_state) {
944 /* Register our message. */
945 messaging_register(sconn->msg_ctx, sconn,
946 MSG_SMB_BLOCKING_LOCK_CANCEL,
947 process_blocking_lock_cancel_message);
948
949 sconn->smb1.locks.blocking_lock_cancel_state = True;
950 }
951
952 for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
953 if (fsp == blr->fsp &&
954 smblctx == blr->smblctx &&
955 offset == blr->offset &&
956 count == blr->count &&
957 lock_flav == blr->lock_flav) {
958 break;
959 }
960 }
961
962 if (!blr) {
963 return NULL;
964 }
965
966 /* Check the flags are right. */
967 if (blr->req->cmd == SMBlockingX &&
968 (locktype & LOCKING_ANDX_LARGE_FILES) !=
969 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
970 return NULL;
971 }
972
973 /* Move to cancelled queue. */
974 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
975 DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
976
977 /* Create the message. */
978 memcpy(msg, &blr, sizeof(blr));
979 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
980
981 messaging_send_buf(sconn->msg_ctx, messaging_server_id(sconn->msg_ctx),
982 MSG_SMB_BLOCKING_LOCK_CANCEL,
983 (uint8_t *)&msg, sizeof(msg));
984
985 return blr;
986}
Note: See TracBrowser for help on using the repository browser.