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