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