source: branches/samba-3.5.x/source3/smbd/blocking.c@ 742

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

Samba Server 3.5: update branche to 3.5.18

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