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