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