source: trunk/server/source3/smbd/blocking.c@ 745

Last change on this file since 745 was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

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