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