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

Last change on this file since 737 was 429, checked in by Silvan Scherrer, 15 years ago

Samba 3.5.x: trunk update to 3.5.2

File size: 24.7 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 reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS status)
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 generic_blocking_lock_error(blr, status);
348}
349
350/****************************************************************************
351 Return a lock fail error.
352*****************************************************************************/
353
354static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
355{
356 DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
357
358 switch(blr->req->cmd) {
359 case SMBlockingX:
360 reply_lockingX_error(blr, status);
361 break;
362 case SMBtrans2:
363 case SMBtranss2:
364 reply_nterror(blr->req, status);
365
366 /*
367 * construct_reply_common has done us the favor to pre-fill
368 * the command field with SMBtranss2 which is wrong :-)
369 */
370 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
371
372 if (!srv_send_smb(smbd_server_fd(),
373 (char *)blr->req->outbuf,
374 true, blr->req->seqnum+1,
375 IS_CONN_ENCRYPTED(blr->fsp->conn),
376 NULL)) {
377 exit_server_cleanly("blocking_lock_reply_error: "
378 "srv_send_smb failed.");
379 }
380 TALLOC_FREE(blr->req->outbuf);
381 break;
382 default:
383 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
384 exit_server("PANIC - unknown type on blocking lock queue");
385 }
386}
387
388/****************************************************************************
389 Attempt to finish off getting all pending blocking locks for a lockingX call.
390 Returns True if we want to be removed from the list.
391*****************************************************************************/
392
393static bool process_lockingX(struct blocking_lock_record *blr)
394{
395 unsigned char locktype = CVAL(blr->req->vwv+3, 0);
396 files_struct *fsp = blr->fsp;
397 uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
398 uint16 num_locks = SVAL(blr->req->vwv+7, 0);
399 uint64_t count = (uint64_t)0, offset = (uint64_t)0;
400 uint32 lock_pid;
401 bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
402 uint8_t *data;
403 NTSTATUS status = NT_STATUS_OK;
404
405 data = (uint8_t *)blr->req->buf
406 + ((large_file_format ? 20 : 10)*num_ulocks);
407
408 /*
409 * Data now points at the beginning of the list
410 * of smb_lkrng structs.
411 */
412
413 for(; blr->lock_num < num_locks; blr->lock_num++) {
414 struct byte_range_lock *br_lck = NULL;
415 bool err;
416
417 lock_pid = get_lock_pid( data, blr->lock_num, large_file_format);
418 count = get_lock_count( data, blr->lock_num, large_file_format);
419 offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
420
421 /*
422 * We know err cannot be set as if it was the lock
423 * request would never have been queued. JRA.
424 */
425 errno = 0;
426 br_lck = do_lock(smbd_messaging_context(),
427 fsp,
428 lock_pid,
429 count,
430 offset,
431 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
432 READ_LOCK : WRITE_LOCK),
433 WINDOWS_LOCK,
434 True,
435 &status,
436 &blr->blocking_pid,
437 blr);
438
439 TALLOC_FREE(br_lck);
440
441 if (NT_STATUS_IS_ERR(status)) {
442 break;
443 }
444 }
445
446 if(blr->lock_num == num_locks) {
447 /*
448 * Success - we got all the locks.
449 */
450
451 DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d "
452 "num_locks=%d\n", fsp_str_dbg(fsp), fsp->fnum,
453 (unsigned int)locktype, num_locks));
454
455 reply_lockingX_success(blr);
456 return True;
457 }
458
459 if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
460 !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
461 /*
462 * We have other than a "can't get lock"
463 * error. Free any locks we had and return an error.
464 * Return True so we get dequeued.
465 */
466 blocking_lock_reply_error(blr, status);
467 return True;
468 }
469
470 /*
471 * Still can't get all the locks - keep waiting.
472 */
473
474 DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
475Waiting....\n",
476 blr->lock_num, num_locks, fsp_str_dbg(fsp), fsp->fnum));
477
478 return False;
479}
480
481/****************************************************************************
482 Attempt to get the posix lock request from a SMBtrans2 call.
483 Returns True if we want to be removed from the list.
484*****************************************************************************/
485
486static bool process_trans2(struct blocking_lock_record *blr)
487{
488 char params[2];
489 NTSTATUS status;
490 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
491 blr->fsp,
492 blr->lock_pid,
493 blr->count,
494 blr->offset,
495 blr->lock_type,
496 blr->lock_flav,
497 True,
498 &status,
499 &blr->blocking_pid,
500 blr);
501 TALLOC_FREE(br_lck);
502
503 if (!NT_STATUS_IS_OK(status)) {
504 if (ERROR_WAS_LOCK_DENIED(status)) {
505 /* Still can't get the lock, just keep waiting. */
506 return False;
507 }
508 /*
509 * We have other than a "can't get lock"
510 * error. Send an error and return True so we get dequeued.
511 */
512 blocking_lock_reply_error(blr, status);
513 return True;
514 }
515
516 /* We finally got the lock, return success. */
517
518 SSVAL(params,0,0);
519 /* Fake up max_data_bytes here - we know it fits. */
520 send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff);
521 return True;
522}
523
524
525/****************************************************************************
526 Process a blocking lock SMB.
527 Returns True if we want to be removed from the list.
528*****************************************************************************/
529
530static bool blocking_lock_record_process(struct blocking_lock_record *blr)
531{
532 switch(blr->req->cmd) {
533 case SMBlockingX:
534 return process_lockingX(blr);
535 case SMBtrans2:
536 case SMBtranss2:
537 return process_trans2(blr);
538 default:
539 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
540 exit_server("PANIC - unknown type on blocking lock queue");
541 }
542 return False; /* Keep compiler happy. */
543}
544
545/****************************************************************************
546 Cancel entries by fnum from the blocking lock pending queue.
547*****************************************************************************/
548
549void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck)
550{
551 struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
552
553 for(blr = blocking_lock_queue; blr; blr = next) {
554 unsigned char locktype = 0;
555
556 next = blr->next;
557 if (blr->fsp->fnum != fsp->fnum) {
558 continue;
559 }
560
561 if (blr->req->cmd == SMBlockingX) {
562 locktype = CVAL(blr->req->vwv+3, 0);
563 }
564
565 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
566 "request type %d for file %s fnum = %d\n",
567 blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum));
568
569 blr_cancelled = blocking_lock_cancel(fsp,
570 blr->lock_pid,
571 blr->offset,
572 blr->count,
573 blr->lock_flav,
574 locktype,
575 NT_STATUS_RANGE_NOT_LOCKED);
576
577 SMB_ASSERT(blr_cancelled == blr);
578
579 brl_lock_cancel(br_lck,
580 blr->lock_pid,
581 procid_self(),
582 blr->offset,
583 blr->count,
584 blr->lock_flav,
585 blr);
586
587 /* We're closing the file fsp here, so ensure
588 * we don't have a dangling pointer. */
589 blr->fsp = NULL;
590 }
591}
592
593/****************************************************************************
594 Delete entries by mid from the blocking lock pending queue. Always send reply.
595*****************************************************************************/
596
597void remove_pending_lock_requests_by_mid(int mid)
598{
599 struct blocking_lock_record *blr, *next = NULL;
600
601 for(blr = blocking_lock_queue; blr; blr = next) {
602 files_struct *fsp;
603 struct byte_range_lock *br_lck;
604
605 next = blr->next;
606
607 if (blr->req->mid != mid) {
608 continue;
609 }
610
611 fsp = blr->fsp;
612 br_lck = brl_get_locks(talloc_tos(), fsp);
613
614 if (br_lck) {
615 DEBUG(10, ("remove_pending_lock_requests_by_mid - "
616 "removing request type %d for file %s fnum "
617 "= %d\n", blr->req->cmd, fsp_str_dbg(fsp),
618 fsp->fnum ));
619
620 brl_lock_cancel(br_lck,
621 blr->lock_pid,
622 procid_self(),
623 blr->offset,
624 blr->count,
625 blr->lock_flav,
626 blr);
627 TALLOC_FREE(br_lck);
628 }
629
630 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
631 DLIST_REMOVE(blocking_lock_queue, blr);
632 TALLOC_FREE(blr);
633 }
634}
635
636/****************************************************************************
637 Is this mid a blocking lock request on the queue ?
638*****************************************************************************/
639
640bool blocking_lock_was_deferred(int mid)
641{
642 struct blocking_lock_record *blr, *next = NULL;
643
644 for(blr = blocking_lock_queue; blr; blr = next) {
645 next = blr->next;
646 if(blr->req->mid == mid) {
647 return True;
648 }
649 }
650 return False;
651}
652
653/****************************************************************************
654 Set a flag as an unlock request affects one of our pending locks.
655*****************************************************************************/
656
657static void received_unlock_msg(struct messaging_context *msg,
658 void *private_data,
659 uint32_t msg_type,
660 struct server_id server_id,
661 DATA_BLOB *data)
662{
663 DEBUG(10,("received_unlock_msg\n"));
664 process_blocking_lock_queue();
665}
666
667/****************************************************************************
668 Process the blocking lock queue. Note that this is only called as root.
669*****************************************************************************/
670
671void process_blocking_lock_queue(void)
672{
673 struct timeval tv_curr = timeval_current();
674 struct blocking_lock_record *blr, *next = NULL;
675
676 /*
677 * Go through the queue and see if we can get any of the locks.
678 */
679
680 for (blr = blocking_lock_queue; blr; blr = next) {
681
682 next = blr->next;
683
684 /*
685 * Go through the remaining locks and try and obtain them.
686 * The call returns True if all locks were obtained successfully
687 * and False if we still need to wait.
688 */
689
690 DEBUG(10, ("Processing BLR = %p\n", blr));
691
692 /* We use set_current_service so connections with
693 * pending locks are not marked as idle.
694 */
695
696 set_current_service(blr->fsp->conn,
697 SVAL(blr->req->inbuf,smb_flg),
698 false);
699
700 if(blocking_lock_record_process(blr)) {
701 struct byte_range_lock *br_lck = brl_get_locks(
702 talloc_tos(), blr->fsp);
703
704 DEBUG(10, ("BLR_process returned true: cancelling and "
705 "removing lock. BLR = %p\n", blr));
706
707 if (br_lck) {
708 brl_lock_cancel(br_lck,
709 blr->lock_pid,
710 procid_self(),
711 blr->offset,
712 blr->count,
713 blr->lock_flav,
714 blr);
715 TALLOC_FREE(br_lck);
716 }
717
718 DLIST_REMOVE(blocking_lock_queue, blr);
719 TALLOC_FREE(blr);
720 continue;
721 }
722
723 /*
724 * We couldn't get the locks for this record on the list.
725 * If the time has expired, return a lock error.
726 */
727
728 if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
729 struct byte_range_lock *br_lck = brl_get_locks(
730 talloc_tos(), blr->fsp);
731
732 DEBUG(10, ("Lock timed out! BLR = %p\n", blr));
733
734 /*
735 * Lock expired - throw away all previously
736 * obtained locks and return lock error.
737 */
738
739 if (br_lck) {
740 DEBUG(5,("process_blocking_lock_queue: "
741 "pending lock fnum = %d for file %s "
742 "timed out.\n", blr->fsp->fnum,
743 fsp_str_dbg(blr->fsp)));
744
745 brl_lock_cancel(br_lck,
746 blr->lock_pid,
747 procid_self(),
748 blr->offset,
749 blr->count,
750 blr->lock_flav,
751 blr);
752 TALLOC_FREE(br_lck);
753 }
754
755 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
756 DLIST_REMOVE(blocking_lock_queue, blr);
757 TALLOC_FREE(blr);
758 }
759 }
760
761 recalc_brl_timeout();
762}
763
764/****************************************************************************
765 Handle a cancel message. Lock already moved onto the cancel queue.
766*****************************************************************************/
767
768#define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
769
770static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
771 void *private_data,
772 uint32_t msg_type,
773 struct server_id server_id,
774 DATA_BLOB *data)
775{
776 NTSTATUS err;
777 const char *msg = (const char *)data->data;
778 struct blocking_lock_record *blr;
779
780 if (data->data == NULL) {
781 smb_panic("process_blocking_lock_cancel_message: null msg");
782 }
783
784 if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
785 DEBUG(0, ("process_blocking_lock_cancel_message: "
786 "Got invalid msg len %d\n", (int)data->length));
787 smb_panic("process_blocking_lock_cancel_message: bad msg");
788 }
789
790 memcpy(&blr, msg, sizeof(blr));
791 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
792
793 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
794 nt_errstr(err) ));
795
796 blocking_lock_reply_error(blr, err);
797 DLIST_REMOVE(blocking_lock_cancelled_queue, blr);
798 TALLOC_FREE(blr);
799}
800
801/****************************************************************************
802 Send ourselves a blocking lock cancelled message. Handled asynchronously above.
803 Returns the blocking_lock_record that is being cancelled.
804*****************************************************************************/
805
806struct blocking_lock_record *blocking_lock_cancel(files_struct *fsp,
807 uint32 lock_pid,
808 uint64_t offset,
809 uint64_t count,
810 enum brl_flavour lock_flav,
811 unsigned char locktype,
812 NTSTATUS err)
813{
814 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
815 struct blocking_lock_record *blr;
816
817 if (!blocking_lock_cancel_state) {
818 /* Register our message. */
819 messaging_register(smbd_messaging_context(), NULL,
820 MSG_SMB_BLOCKING_LOCK_CANCEL,
821 process_blocking_lock_cancel_message);
822
823 blocking_lock_cancel_state = True;
824 }
825
826 for (blr = blocking_lock_queue; blr; blr = blr->next) {
827 if (fsp == blr->fsp &&
828 lock_pid == blr->lock_pid &&
829 offset == blr->offset &&
830 count == blr->count &&
831 lock_flav == blr->lock_flav) {
832 break;
833 }
834 }
835
836 if (!blr) {
837 return NULL;
838 }
839
840 /* Check the flags are right. */
841 if (blr->req->cmd == SMBlockingX &&
842 (locktype & LOCKING_ANDX_LARGE_FILES) !=
843 (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
844 return NULL;
845 }
846
847 /* Move to cancelled queue. */
848 DLIST_REMOVE(blocking_lock_queue, blr);
849 DLIST_ADD(blocking_lock_cancelled_queue, blr);
850
851 /* Create the message. */
852 memcpy(msg, &blr, sizeof(blr));
853 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
854
855 messaging_send_buf(smbd_messaging_context(), procid_self(),
856 MSG_SMB_BLOCKING_LOCK_CANCEL,
857 (uint8 *)&msg, sizeof(msg));
858
859 return blr;
860}
Note: See TracBrowser for help on using the repository browser.