s3: include smbd/smbd.h where needed.
[kai/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 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 "librpc/gen_ndr/messaging.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 event_context *event_ctx,
39                            struct timed_event *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 = event_add_timed(smbd_event_context(),
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(lock_timeout/1000,
212                                         (lock_timeout % 1000) * 1000);
213         }
214         blr->lock_num = lock_num;
215         blr->smblctx = smblctx;
216         blr->blocking_smblctx = blocking_smblctx;
217         blr->lock_flav = lock_flav;
218         blr->lock_type = lock_type;
219         blr->offset = offset;
220         blr->count = count;
221       
222         /* Specific brl_lock() implementations can fill this in. */
223         blr->blr_private = NULL;
224
225         /* Add a pending lock record for this. */
226         status = brl_lock(req->sconn->msg_ctx,
227                         br_lck,
228                         smblctx,
229                         sconn_server_id(req->sconn),
230                         offset,
231                         count,
232                         lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
233                         blr->lock_flav,
234                         True,
235                         NULL,
236                         blr);
237
238         if (!NT_STATUS_IS_OK(status)) {
239                 DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
240                 TALLOC_FREE(blr);
241                 return False;
242         }
243
244         SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd);
245         blr->req = talloc_move(blr, &req);
246
247         DLIST_ADD_END(sconn->smb1.locks.blocking_lock_queue, blr, struct blocking_lock_record *);
248         recalc_brl_timeout(sconn);
249
250         /* Ensure we'll receive messages when this is unlocked. */
251         if (!sconn->smb1.locks.blocking_lock_unlock_state) {
252                 messaging_register(sconn->msg_ctx, NULL,
253                                    MSG_SMB_UNLOCK, received_unlock_msg);
254                 sconn->smb1.locks.blocking_lock_unlock_state = true;
255         }
256
257         DEBUG(3,("push_blocking_lock_request: lock request blocked with "
258                 "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n",
259                 (unsigned int)blr->expire_time.tv_sec,
260                 (unsigned int)blr->expire_time.tv_usec, lock_timeout,
261                 blr->fsp->fnum, fsp_str_dbg(blr->fsp)));
262
263         return True;
264 }
265
266 /****************************************************************************
267  Return a lockingX success SMB.
268 *****************************************************************************/
269
270 static void reply_lockingX_success(struct blocking_lock_record *blr)
271 {
272         reply_outbuf(blr->req, 2, 0);
273
274         /*
275          * As this message is a lockingX call we must handle
276          * any following chained message correctly.
277          * This is normally handled in construct_reply(),
278          * but as that calls switch_message, we can't use
279          * that here and must set up the chain info manually.
280          */
281
282         chain_reply(blr->req);
283         TALLOC_FREE(blr->req->outbuf);
284 }
285
286 /****************************************************************************
287  Return a generic lock fail error blocking call.
288 *****************************************************************************/
289
290 static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
291 {
292         /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
293            FILE_LOCK_CONFLICT! (tridge) */
294         if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
295                 status = NT_STATUS_FILE_LOCK_CONFLICT;
296         }
297
298         if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
299                 /* Store the last lock error. */
300                 files_struct *fsp = blr->fsp;
301
302                 if (fsp) {
303                         fsp->last_lock_failure.context.smblctx = blr->smblctx;
304                         fsp->last_lock_failure.context.tid = fsp->conn->cnum;
305                         fsp->last_lock_failure.context.pid =
306                                 sconn_server_id(fsp->conn->sconn);
307                         fsp->last_lock_failure.start = blr->offset;
308                         fsp->last_lock_failure.size = blr->count;
309                         fsp->last_lock_failure.fnum = fsp->fnum;
310                         fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
311                         fsp->last_lock_failure.lock_flav = blr->lock_flav;
312                 }
313         }
314
315         reply_nterror(blr->req, status);
316         if (!srv_send_smb(blr->req->sconn, (char *)blr->req->outbuf,
317                           true, blr->req->seqnum+1,
318                           blr->req->encrypted, NULL)) {
319                 exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
320         }
321         TALLOC_FREE(blr->req->outbuf);
322 }
323
324 /****************************************************************************
325  Return a lock fail error for a lockingX call. Undo all the locks we have 
326  obtained first.
327 *****************************************************************************/
328
329 static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS status)
330 {
331         files_struct *fsp = blr->fsp;
332         uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
333         uint64_t count = (uint64_t)0, offset = (uint64_t) 0;
334         uint64_t smblctx;
335         unsigned char locktype = CVAL(blr->req->vwv+3, 0);
336         bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
337         uint8_t *data;
338         int i;
339
340         data = (uint8_t *)blr->req->buf
341                 + ((large_file_format ? 20 : 10)*num_ulocks);
342
343         /* 
344          * Data now points at the beginning of the list
345          * of smb_lkrng structs.
346          */
347
348         /*
349          * Ensure we don't do a remove on the lock that just failed,
350          * as under POSIX rules, if we have a lock already there, we
351          * will delete it (and we shouldn't) .....
352          */
353
354         for(i = blr->lock_num - 1; i >= 0; i--) {
355                 bool err;
356
357                 smblctx = get_lock_pid( data, i, large_file_format);
358                 count = get_lock_count( data, i, large_file_format);
359                 offset = get_lock_offset( data, i, large_file_format, &err);
360
361                 /*
362                  * We know err cannot be set as if it was the lock
363                  * request would never have been queued. JRA.
364                  */
365
366                 do_unlock(fsp->conn->sconn->msg_ctx,
367                         fsp,
368                         smblctx,
369                         count,
370                         offset,
371                         WINDOWS_LOCK);
372         }
373
374         generic_blocking_lock_error(blr, status);
375 }
376
377 /****************************************************************************
378  Return a lock fail error.
379 *****************************************************************************/
380
381 static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
382 {
383         DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
384
385         switch(blr->req->cmd) {
386         case SMBlockingX:
387                 reply_lockingX_error(blr, status);
388                 break;
389         case SMBtrans2:
390         case SMBtranss2:
391                 reply_nterror(blr->req, status);
392
393                 /*
394                  * construct_reply_common has done us the favor to pre-fill
395                  * the command field with SMBtranss2 which is wrong :-)
396                  */
397                 SCVAL(blr->req->outbuf,smb_com,SMBtrans2);
398
399                 if (!srv_send_smb(blr->req->sconn,
400                                   (char *)blr->req->outbuf,
401                                   true, blr->req->seqnum+1,
402                                   IS_CONN_ENCRYPTED(blr->fsp->conn),
403                                   NULL)) {
404                         exit_server_cleanly("blocking_lock_reply_error: "
405                                             "srv_send_smb failed.");
406                 }
407                 TALLOC_FREE(blr->req->outbuf);
408                 break;
409         default:
410                 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
411                 exit_server("PANIC - unknown type on blocking lock queue");
412         }
413 }
414
415 /****************************************************************************
416  Attempt to finish off getting all pending blocking locks for a lockingX call.
417  Returns True if we want to be removed from the list.
418 *****************************************************************************/
419
420 static bool process_lockingX(struct blocking_lock_record *blr)
421 {
422         unsigned char locktype = CVAL(blr->req->vwv+3, 0);
423         files_struct *fsp = blr->fsp;
424         uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
425         uint16 num_locks = SVAL(blr->req->vwv+7, 0);
426         uint64_t count = (uint64_t)0, offset = (uint64_t)0;
427         uint64_t smblctx;
428         bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
429         uint8_t *data;
430         NTSTATUS status = NT_STATUS_OK;
431
432         data = (uint8_t *)blr->req->buf
433                 + ((large_file_format ? 20 : 10)*num_ulocks);
434
435         /* 
436          * Data now points at the beginning of the list
437          * of smb_lkrng structs.
438          */
439
440         for(; blr->lock_num < num_locks; blr->lock_num++) {
441                 struct byte_range_lock *br_lck = NULL;
442                 bool err;
443
444                 smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
445                 count = get_lock_count( data, blr->lock_num, large_file_format);
446                 offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
447
448                 /*
449                  * We know err cannot be set as if it was the lock
450                  * request would never have been queued. JRA.
451                  */
452                 errno = 0;
453                 br_lck = do_lock(fsp->conn->sconn->msg_ctx,
454                                 fsp,
455                                 smblctx,
456                                 count,
457                                 offset,
458                                 ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
459                                         READ_LOCK : WRITE_LOCK),
460                                 WINDOWS_LOCK,
461                                 True,
462                                 &status,
463                                 &blr->blocking_smblctx,
464                                 blr);
465
466                 TALLOC_FREE(br_lck);
467
468                 if (NT_STATUS_IS_ERR(status)) {
469                         break;
470                 }
471         }
472
473         if(blr->lock_num == num_locks) {
474                 /*
475                  * Success - we got all the locks.
476                  */
477
478                 DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d "
479                          "num_locks=%d\n", fsp_str_dbg(fsp), fsp->fnum,
480                          (unsigned int)locktype, num_locks));
481
482                 reply_lockingX_success(blr);
483                 return True;
484         }
485
486         if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
487             !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
488                 /*
489                  * We have other than a "can't get lock"
490                  * error. Free any locks we had and return an error.
491                  * Return True so we get dequeued.
492                  */
493                 blocking_lock_reply_error(blr, status);
494                 return True;
495         }
496
497         /*
498          * Still can't get all the locks - keep waiting.
499          */
500
501         DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
502 Waiting....\n", 
503                  blr->lock_num, num_locks, fsp_str_dbg(fsp), fsp->fnum));
504
505         return False;
506 }
507
508 /****************************************************************************
509  Attempt to get the posix lock request from a SMBtrans2 call.
510  Returns True if we want to be removed from the list.
511 *****************************************************************************/
512
513 static bool process_trans2(struct blocking_lock_record *blr)
514 {
515         char params[2];
516         NTSTATUS status;
517         struct byte_range_lock *br_lck = do_lock(
518                                                 blr->fsp->conn->sconn->msg_ctx,
519                                                 blr->fsp,
520                                                 blr->smblctx,
521                                                 blr->count,
522                                                 blr->offset,
523                                                 blr->lock_type,
524                                                 blr->lock_flav,
525                                                 True,
526                                                 &status,
527                                                 &blr->blocking_smblctx,
528                                                 blr);
529         TALLOC_FREE(br_lck);
530
531         if (!NT_STATUS_IS_OK(status)) {
532                 if (ERROR_WAS_LOCK_DENIED(status)) {
533                         /* Still can't get the lock, just keep waiting. */
534                         return False;
535                 }       
536                 /*
537                  * We have other than a "can't get lock"
538                  * error. Send an error and return True so we get dequeued.
539                  */
540                 blocking_lock_reply_error(blr, status);
541                 return True;
542         }
543
544         /* We finally got the lock, return success. */
545
546         SSVAL(params,0,0);
547         /* Fake up max_data_bytes here - we know it fits. */
548         send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff);
549         return True;
550 }
551
552
553 /****************************************************************************
554  Process a blocking lock SMB.
555  Returns True if we want to be removed from the list.
556 *****************************************************************************/
557
558 static bool blocking_lock_record_process(struct blocking_lock_record *blr)
559 {
560         switch(blr->req->cmd) {
561                 case SMBlockingX:
562                         return process_lockingX(blr);
563                 case SMBtrans2:
564                 case SMBtranss2:
565                         return process_trans2(blr);
566                 default:
567                         DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
568                         exit_server("PANIC - unknown type on blocking lock queue");
569         }
570         return False; /* Keep compiler happy. */
571 }
572
573 /****************************************************************************
574  Cancel entries by fnum from the blocking lock pending queue.
575  Called when a file is closed.
576 *****************************************************************************/
577
578 void cancel_pending_lock_requests_by_fid(files_struct *fsp,
579                         struct byte_range_lock *br_lck,
580                         enum file_close_type close_type)
581 {
582         struct smbd_server_connection *sconn = fsp->conn->sconn;
583         struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
584
585         if (sconn->using_smb2) {
586                 cancel_pending_lock_requests_by_fid_smb2(fsp,
587                                         br_lck,
588                                         close_type);
589                 return;
590         }
591
592         for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
593                 unsigned char locktype = 0;
594
595                 next = blr->next;
596                 if (blr->fsp->fnum != fsp->fnum) {
597                         continue;
598                 }
599
600                 if (blr->req->cmd == SMBlockingX) {
601                         locktype = CVAL(blr->req->vwv+3, 0);
602                 }
603
604                 DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
605                            "request type %d for file %s fnum = %d\n",
606                            blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum));
607
608                 blr_cancelled = blocking_lock_cancel_smb1(fsp,
609                                      blr->smblctx,
610                                      blr->offset,
611                                      blr->count,
612                                      blr->lock_flav,
613                                      locktype,
614                                      NT_STATUS_RANGE_NOT_LOCKED);
615
616                 SMB_ASSERT(blr_cancelled == blr);
617
618                 brl_lock_cancel(br_lck,
619                                 blr->smblctx,
620                                 sconn_server_id(sconn),
621                                 blr->offset,
622                                 blr->count,
623                                 blr->lock_flav,
624                                 blr);
625
626                 /* We're closing the file fsp here, so ensure
627                  * we don't have a dangling pointer. */
628                 blr->fsp = NULL;
629         }
630 }
631
632 /****************************************************************************
633  Delete entries by mid from the blocking lock pending queue. Always send reply.
634  Only called from the SMB1 cancel code.
635 *****************************************************************************/
636
637 void remove_pending_lock_requests_by_mid_smb1(
638         struct smbd_server_connection *sconn, uint64_t mid)
639 {
640         struct blocking_lock_record *blr, *next = NULL;
641
642         for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
643                 files_struct *fsp;
644                 struct byte_range_lock *br_lck;
645
646                 next = blr->next;
647
648                 if (blr->req->mid != mid) {
649                         continue;
650                 }
651
652                 fsp = blr->fsp;
653                 br_lck = brl_get_locks(talloc_tos(), fsp);
654
655                 if (br_lck) {
656                         DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
657                                    "removing request type %d for file %s fnum "
658                                    "= %d\n", blr->req->cmd, fsp_str_dbg(fsp),
659                                    fsp->fnum ));
660
661                         brl_lock_cancel(br_lck,
662                                         blr->smblctx,
663                                         sconn_server_id(sconn),
664                                         blr->offset,
665                                         blr->count,
666                                         blr->lock_flav,
667                                         blr);
668                         TALLOC_FREE(br_lck);
669                 }
670
671                 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
672                 DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
673                 TALLOC_FREE(blr);
674         }
675 }
676
677 /****************************************************************************
678  Is this mid a blocking lock request on the queue ?
679  Currently only called from the SMB1 unix extensions POSIX lock code.
680 *****************************************************************************/
681
682 bool blocking_lock_was_deferred_smb1(
683         struct smbd_server_connection *sconn, uint64_t mid)
684 {
685         struct blocking_lock_record *blr, *next = NULL;
686
687         for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
688                 next = blr->next;
689                 if(blr->req->mid == mid) {
690                         return True;
691                 }
692         }
693         return False;
694 }
695
696 /****************************************************************************
697   Set a flag as an unlock request affects one of our pending locks.
698 *****************************************************************************/
699
700 static void received_unlock_msg(struct messaging_context *msg,
701                                 void *private_data,
702                                 uint32_t msg_type,
703                                 struct server_id server_id,
704                                 DATA_BLOB *data)
705 {
706         struct smbd_server_connection *sconn;
707
708         sconn = msg_ctx_to_sconn(msg);
709         if (sconn == NULL) {
710                 DEBUG(1, ("could not find sconn\n"));
711                 return;
712         }
713
714         DEBUG(10,("received_unlock_msg\n"));
715         process_blocking_lock_queue(sconn);
716 }
717
718 /****************************************************************************
719  Process the blocking lock queue. Note that this is only called as root.
720 *****************************************************************************/
721
722 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
723 {
724         struct timeval tv_curr = timeval_current();
725         struct blocking_lock_record *blr, *next = NULL;
726
727         if (sconn->using_smb2) {
728                 process_blocking_lock_queue_smb2(sconn, tv_curr);
729                 return;
730         }
731
732         /*
733          * Go through the queue and see if we can get any of the locks.
734          */
735
736         for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
737
738                 next = blr->next;
739
740                 /*
741                  * Go through the remaining locks and try and obtain them.
742                  * The call returns True if all locks were obtained successfully
743                  * and False if we still need to wait.
744                  */
745
746                 DEBUG(10, ("Processing BLR = %p\n", blr));
747
748                 /* We use set_current_service so connections with
749                  * pending locks are not marked as idle.
750                  */
751
752                 set_current_service(blr->fsp->conn,
753                                 SVAL(blr->req->inbuf,smb_flg),
754                                 false);
755
756                 if(blocking_lock_record_process(blr)) {
757                         struct byte_range_lock *br_lck = brl_get_locks(
758                                 talloc_tos(), blr->fsp);
759
760                         DEBUG(10, ("BLR_process returned true: cancelling and "
761                             "removing lock. BLR = %p\n", blr));
762
763                         if (br_lck) {
764                                 brl_lock_cancel(br_lck,
765                                         blr->smblctx,
766                                         sconn_server_id(sconn),
767                                         blr->offset,
768                                         blr->count,
769                                         blr->lock_flav,
770                                         blr);
771                                 TALLOC_FREE(br_lck);
772                         }
773
774                         DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
775                         TALLOC_FREE(blr);
776                         continue;
777                 }
778
779                 /*
780                  * We couldn't get the locks for this record on the list.
781                  * If the time has expired, return a lock error.
782                  */
783
784                 if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
785                         struct byte_range_lock *br_lck = brl_get_locks(
786                                 talloc_tos(), blr->fsp);
787
788                         DEBUG(10, ("Lock timed out! BLR = %p\n", blr));
789
790                         /*
791                          * Lock expired - throw away all previously
792                          * obtained locks and return lock error.
793                          */
794
795                         if (br_lck) {
796                                 DEBUG(5,("process_blocking_lock_queue: "
797                                          "pending lock fnum = %d for file %s "
798                                          "timed out.\n", blr->fsp->fnum,
799                                          fsp_str_dbg(blr->fsp)));
800
801                                 brl_lock_cancel(br_lck,
802                                         blr->smblctx,
803                                         sconn_server_id(sconn),
804                                         blr->offset,
805                                         blr->count,
806                                         blr->lock_flav,
807                                         blr);
808                                 TALLOC_FREE(br_lck);
809                         }
810
811                         blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
812                         DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
813                         TALLOC_FREE(blr);
814                 }
815         }
816
817         recalc_brl_timeout(sconn);
818 }
819
820 /****************************************************************************
821  Handle a cancel message. Lock already moved onto the cancel queue.
822 *****************************************************************************/
823
824 #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(struct blocking_lock_record *) + sizeof(NTSTATUS))
825
826 static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
827                                                  void *private_data,
828                                                  uint32_t msg_type,
829                                                  struct server_id server_id,
830                                                  DATA_BLOB *data)
831 {
832         struct smbd_server_connection *sconn;
833         NTSTATUS err;
834         const char *msg = (const char *)data->data;
835         struct blocking_lock_record *blr;
836
837         if (data->data == NULL) {
838                 smb_panic("process_blocking_lock_cancel_message: null msg");
839         }
840
841         if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
842                 DEBUG(0, ("process_blocking_lock_cancel_message: "
843                           "Got invalid msg len %d\n", (int)data->length));
844                 smb_panic("process_blocking_lock_cancel_message: bad msg");
845         }
846
847         sconn = msg_ctx_to_sconn(ctx);
848         if (sconn == NULL) {
849                 DEBUG(1, ("could not find sconn\n"));
850                 return;
851         }
852
853         memcpy(&blr, msg, sizeof(blr));
854         memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
855
856         DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
857                 nt_errstr(err) ));
858
859         blocking_lock_reply_error(blr, err);
860         DLIST_REMOVE(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
861         TALLOC_FREE(blr);
862 }
863
864 /****************************************************************************
865  Send ourselves a blocking lock cancelled message. Handled asynchronously above.
866  Returns the blocking_lock_record that is being cancelled.
867  Only called from the SMB1 code.
868 *****************************************************************************/
869
870 struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp,
871                         uint64_t smblctx,
872                         uint64_t offset,
873                         uint64_t count,
874                         enum brl_flavour lock_flav,
875                         unsigned char locktype,
876                         NTSTATUS err)
877 {
878         struct smbd_server_connection *sconn = fsp->conn->sconn;
879         char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
880         struct blocking_lock_record *blr;
881
882         if (!sconn->smb1.locks.blocking_lock_cancel_state) {
883                 /* Register our message. */
884                 messaging_register(sconn->msg_ctx, NULL,
885                                    MSG_SMB_BLOCKING_LOCK_CANCEL,
886                                    process_blocking_lock_cancel_message);
887
888                 sconn->smb1.locks.blocking_lock_cancel_state = True;
889         }
890
891         for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
892                 if (fsp == blr->fsp &&
893                                 smblctx == blr->smblctx &&
894                                 offset == blr->offset &&
895                                 count == blr->count &&
896                                 lock_flav == blr->lock_flav) {
897                         break;
898                 }
899         }
900
901         if (!blr) {
902                 return NULL;
903         }
904
905         /* Check the flags are right. */
906         if (blr->req->cmd == SMBlockingX &&
907                 (locktype & LOCKING_ANDX_LARGE_FILES) !=
908                         (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
909                 return NULL;
910         }
911
912         /* Move to cancelled queue. */
913         DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
914         DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr);
915
916         /* Create the message. */
917         memcpy(msg, &blr, sizeof(blr));
918         memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
919
920         messaging_send_buf(sconn->msg_ctx, sconn_server_id(sconn),
921                            MSG_SMB_BLOCKING_LOCK_CANCEL,
922                            (uint8 *)&msg, sizeof(msg));
923
924         return blr;
925 }