Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : byte range locking code
4 : Updated to handle range splits/merges.
5 :
6 : Copyright (C) Andrew Tridgell 1992-2000
7 : Copyright (C) Jeremy Allison 1992-2000
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : /* This module implements a tdb based byte range locking service,
24 : replacing the fcntl() based byte range locking previously
25 : used. This allows us to provide the same semantics as NT */
26 :
27 : #include "includes.h"
28 : #include "system/filesys.h"
29 : #include "lib/util/server_id.h"
30 : #include "locking/proto.h"
31 : #include "smbd/globals.h"
32 : #include "dbwrap/dbwrap.h"
33 : #include "dbwrap/dbwrap_open.h"
34 : #include "serverid.h"
35 : #include "messages.h"
36 : #include "util_tdb.h"
37 :
38 : #undef DBGC_CLASS
39 : #define DBGC_CLASS DBGC_LOCKING
40 :
41 : /* The open brlock.tdb database. */
42 :
43 : static struct db_context *brlock_db;
44 :
45 : struct byte_range_lock {
46 : struct files_struct *fsp;
47 : TALLOC_CTX *req_mem_ctx;
48 : const struct GUID *req_guid;
49 : unsigned int num_locks;
50 : bool modified;
51 : struct lock_struct *lock_data;
52 : struct db_record *record;
53 : };
54 :
55 : /****************************************************************************
56 : Debug info at level 10 for lock struct.
57 : ****************************************************************************/
58 :
59 0 : static void print_lock_struct(unsigned int i, const struct lock_struct *pls)
60 : {
61 0 : struct server_id_buf tmp;
62 :
63 0 : DBG_DEBUG("[%u]: smblctx = %"PRIu64", tid = %"PRIu32", pid = %s, "
64 : "start = %"PRIu64", size = %"PRIu64", fnum = %"PRIu64", "
65 : "%s %s\n",
66 : i,
67 : pls->context.smblctx,
68 : pls->context.tid,
69 : server_id_str_buf(pls->context.pid, &tmp),
70 : pls->start,
71 : pls->size,
72 : pls->fnum,
73 : lock_type_name(pls->lock_type),
74 : lock_flav_name(pls->lock_flav));
75 0 : }
76 :
77 350299 : unsigned int brl_num_locks(const struct byte_range_lock *brl)
78 : {
79 350299 : return brl->num_locks;
80 : }
81 :
82 8462 : struct files_struct *brl_fsp(struct byte_range_lock *brl)
83 : {
84 8462 : return brl->fsp;
85 : }
86 :
87 60 : TALLOC_CTX *brl_req_mem_ctx(const struct byte_range_lock *brl)
88 : {
89 60 : if (brl->req_mem_ctx == NULL) {
90 0 : return talloc_get_type_abort(brl, struct byte_range_lock);
91 : }
92 :
93 60 : return brl->req_mem_ctx;
94 : }
95 :
96 60 : const struct GUID *brl_req_guid(const struct byte_range_lock *brl)
97 : {
98 60 : if (brl->req_guid == NULL) {
99 0 : static const struct GUID brl_zero_req_guid;
100 0 : return &brl_zero_req_guid;
101 : }
102 :
103 60 : return brl->req_guid;
104 : }
105 :
106 : /****************************************************************************
107 : See if two locking contexts are equal.
108 : ****************************************************************************/
109 :
110 6844 : static bool brl_same_context(const struct lock_context *ctx1,
111 : const struct lock_context *ctx2)
112 : {
113 6844 : return (server_id_equal(&ctx1->pid, &ctx2->pid) &&
114 12075 : (ctx1->smblctx == ctx2->smblctx) &&
115 5256 : (ctx1->tid == ctx2->tid));
116 : }
117 :
118 547409 : bool byte_range_valid(uint64_t ofs, uint64_t len)
119 : {
120 547409 : uint64_t max_len = UINT64_MAX - ofs;
121 98 : uint64_t effective_len;
122 :
123 : /*
124 : * [MS-FSA] specifies this:
125 : *
126 : * If (((FileOffset + Length - 1) < FileOffset) && Length != 0) {
127 : * return STATUS_INVALID_LOCK_RANGE
128 : * }
129 : *
130 : * We avoid integer wrapping and calculate
131 : * max and effective len instead.
132 : */
133 :
134 547409 : if (len == 0) {
135 790 : return true;
136 : }
137 :
138 546615 : effective_len = len - 1;
139 546615 : if (effective_len <= max_len) {
140 546601 : return true;
141 : }
142 :
143 14 : return false;
144 : }
145 :
146 270826 : bool byte_range_overlap(uint64_t ofs1,
147 : uint64_t len1,
148 : uint64_t ofs2,
149 : uint64_t len2)
150 : {
151 36 : uint64_t last1;
152 36 : uint64_t last2;
153 36 : bool valid;
154 :
155 : /*
156 : * This is based on [MS-FSA] 2.1.4.10
157 : * Algorithm for Determining If a Range Access
158 : * Conflicts with Byte-Range Locks
159 : */
160 :
161 : /*
162 : * The {0, 0} range doesn't conflict with any byte-range lock
163 : */
164 270826 : if (ofs1 == 0 && len1 == 0) {
165 98 : return false;
166 : }
167 270728 : if (ofs2 == 0 && len2 == 0) {
168 0 : return false;
169 : }
170 :
171 : /*
172 : * The caller should have checked that the ranges are
173 : * valid. But currently we gracefully handle
174 : * the overflow of a read/write check.
175 : */
176 270728 : valid = byte_range_valid(ofs1, len1);
177 270728 : if (valid) {
178 270728 : last1 = ofs1 + len1 - 1;
179 : } else {
180 0 : last1 = UINT64_MAX;
181 : }
182 270728 : valid = byte_range_valid(ofs2, len2);
183 270728 : if (valid) {
184 270728 : last2 = ofs2 + len2 - 1;
185 : } else {
186 0 : last2 = UINT64_MAX;
187 : }
188 :
189 : /*
190 : * If one range starts after the last
191 : * byte of the other range there's
192 : * no conflict.
193 : */
194 270728 : if (ofs1 > last2) {
195 1872 : return false;
196 : }
197 268848 : if (ofs2 > last1) {
198 265446 : return false;
199 : }
200 :
201 3382 : return true;
202 : }
203 :
204 : /****************************************************************************
205 : See if lck1 and lck2 overlap.
206 : ****************************************************************************/
207 :
208 270652 : static bool brl_overlap(const struct lock_struct *lck1,
209 : const struct lock_struct *lck2)
210 : {
211 541268 : return byte_range_overlap(lck1->start,
212 270652 : lck1->size,
213 270652 : lck2->start,
214 270652 : lck2->size);
215 : }
216 :
217 : /****************************************************************************
218 : See if lock2 can be added when lock1 is in place.
219 : ****************************************************************************/
220 :
221 270407 : static bool brl_conflict(const struct lock_struct *lck1,
222 : const struct lock_struct *lck2)
223 : {
224 : /* Read locks never conflict. */
225 270407 : if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
226 1138 : return False;
227 : }
228 :
229 : /* A READ lock can stack on top of a WRITE lock if they have the same
230 : * context & fnum. */
231 270009 : if (lck1->lock_type == WRITE_LOCK && lck2->lock_type == READ_LOCK &&
232 740 : brl_same_context(&lck1->context, &lck2->context) &&
233 322 : lck1->fnum == lck2->fnum) {
234 298 : return False;
235 : }
236 :
237 268971 : return brl_overlap(lck1, lck2);
238 : }
239 :
240 : /****************************************************************************
241 : See if lock2 can be added when lock1 is in place - when both locks are POSIX
242 : flavour. POSIX locks ignore fnum - they only care about dev/ino which we
243 : know already match.
244 : ****************************************************************************/
245 :
246 480 : static bool brl_conflict_posix(const struct lock_struct *lck1,
247 : const struct lock_struct *lck2)
248 : {
249 : #if defined(DEVELOPER)
250 480 : SMB_ASSERT(lck1->lock_flav == POSIX_LOCK);
251 480 : SMB_ASSERT(lck2->lock_flav == POSIX_LOCK);
252 : #endif
253 :
254 : /* Read locks never conflict. */
255 480 : if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
256 464 : return False;
257 : }
258 :
259 : /* Locks on the same context don't conflict. Ignore fnum. */
260 16 : if (brl_same_context(&lck1->context, &lck2->context)) {
261 4 : return False;
262 : }
263 :
264 : /* One is read, the other write, or the context is different,
265 : do they overlap ? */
266 12 : return brl_overlap(lck1, lck2);
267 : }
268 :
269 : /****************************************************************************
270 : Check to see if this lock conflicts, but ignore our own locks on the
271 : same fnum only. This is the read/write lock check code path.
272 : This is never used in the POSIX lock case.
273 : ****************************************************************************/
274 :
275 2175 : static bool brl_conflict_other(const struct lock_struct *lock,
276 : const struct lock_struct *rw_probe)
277 : {
278 2175 : if (lock->lock_type == READ_LOCK && rw_probe->lock_type == READ_LOCK) {
279 506 : return False;
280 : }
281 :
282 1669 : if (lock->lock_flav == POSIX_LOCK &&
283 8 : rw_probe->lock_flav == POSIX_LOCK) {
284 : /*
285 : * POSIX flavour locks never conflict here - this is only called
286 : * in the read/write path.
287 : */
288 0 : return False;
289 : }
290 :
291 1669 : if (!brl_overlap(lock, rw_probe)) {
292 : /*
293 : * I/O can only conflict when overlapping a lock, thus let it
294 : * pass
295 : */
296 1342 : return false;
297 : }
298 :
299 318 : if (!brl_same_context(&lock->context, &rw_probe->context)) {
300 : /*
301 : * Different process, conflict
302 : */
303 224 : return true;
304 : }
305 :
306 88 : if (lock->fnum != rw_probe->fnum) {
307 : /*
308 : * Different file handle, conflict
309 : */
310 0 : return true;
311 : }
312 :
313 88 : if ((lock->lock_type == READ_LOCK) &&
314 28 : (rw_probe->lock_type == WRITE_LOCK)) {
315 : /*
316 : * Incoming WRITE locks conflict with existing READ locks even
317 : * if the context is the same. JRA. See LOCKTEST7 in
318 : * smbtorture.
319 : */
320 28 : return true;
321 : }
322 :
323 : /*
324 : * I/O request compatible with existing lock, let it pass without
325 : * conflict
326 : */
327 :
328 54 : return false;
329 : }
330 :
331 : /****************************************************************************
332 : Open up the brlock.tdb database.
333 : ****************************************************************************/
334 :
335 198 : void brl_init(bool read_only)
336 : {
337 0 : int tdb_flags;
338 0 : char *db_path;
339 :
340 198 : if (brlock_db) {
341 0 : return;
342 : }
343 :
344 198 : tdb_flags = SMBD_VOLATILE_TDB_FLAGS | TDB_SEQNUM;
345 :
346 198 : db_path = lock_path(talloc_tos(), "brlock.tdb");
347 198 : if (db_path == NULL) {
348 0 : DEBUG(0, ("out of memory!\n"));
349 0 : return;
350 : }
351 :
352 198 : brlock_db = db_open(NULL, db_path,
353 : SMBD_VOLATILE_TDB_HASH_SIZE, tdb_flags,
354 : read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644,
355 : DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE);
356 198 : if (!brlock_db) {
357 0 : DEBUG(0,("Failed to open byte range locking database %s\n",
358 : db_path));
359 0 : TALLOC_FREE(db_path);
360 0 : return;
361 : }
362 198 : TALLOC_FREE(db_path);
363 : }
364 :
365 : /****************************************************************************
366 : Close down the brlock.tdb database.
367 : ****************************************************************************/
368 :
369 31929 : void brl_shutdown(void)
370 : {
371 31929 : TALLOC_FREE(brlock_db);
372 31929 : }
373 :
374 : /****************************************************************************
375 : Lock a range of bytes - Windows lock semantics.
376 : ****************************************************************************/
377 :
378 5807 : NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck,
379 : struct lock_struct *plock)
380 : {
381 26 : unsigned int i;
382 5807 : files_struct *fsp = br_lck->fsp;
383 5807 : struct lock_struct *locks = br_lck->lock_data;
384 26 : NTSTATUS status;
385 26 : bool valid;
386 :
387 5807 : SMB_ASSERT(plock->lock_type != UNLOCK_LOCK);
388 :
389 5807 : valid = byte_range_valid(plock->start, plock->size);
390 5807 : if (!valid) {
391 14 : return NT_STATUS_INVALID_LOCK_RANGE;
392 : }
393 :
394 273206 : for (i=0; i < br_lck->num_locks; i++) {
395 : /* Do any Windows or POSIX locks conflict ? */
396 270403 : if (brl_conflict(&locks[i], plock)) {
397 2990 : if (!serverid_exists(&locks[i].context.pid)) {
398 0 : locks[i].context.pid.pid = 0;
399 0 : br_lck->modified = true;
400 0 : continue;
401 : }
402 : /* Remember who blocked us. */
403 2990 : plock->context.smblctx = locks[i].context.smblctx;
404 2990 : return NT_STATUS_LOCK_NOT_GRANTED;
405 : }
406 : }
407 :
408 2803 : contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WINDOWS_BRL);
409 :
410 : /* We can get the Windows lock, now see if it needs to
411 : be mapped into a lower level POSIX one, and if so can
412 : we get it ? */
413 :
414 2803 : if (lp_posix_locking(fsp->conn->params)) {
415 18 : int errno_ret;
416 2455 : if (!set_posix_lock_windows_flavour(fsp,
417 : plock->start,
418 : plock->size,
419 : plock->lock_type,
420 2455 : &plock->context,
421 : locks,
422 2455 : br_lck->num_locks,
423 : &errno_ret)) {
424 :
425 : /* We don't know who blocked us. */
426 110 : plock->context.smblctx = 0xFFFFFFFFFFFFFFFFLL;
427 :
428 110 : if (errno_ret == EACCES || errno_ret == EAGAIN) {
429 110 : status = NT_STATUS_LOCK_NOT_GRANTED;
430 110 : goto fail;
431 : } else {
432 0 : status = map_nt_error_from_unix(errno);
433 0 : goto fail;
434 : }
435 : }
436 : }
437 :
438 : /* no conflicts - add it to the list of locks */
439 2693 : locks = talloc_realloc(br_lck, locks, struct lock_struct,
440 : (br_lck->num_locks + 1));
441 2693 : if (!locks) {
442 0 : status = NT_STATUS_NO_MEMORY;
443 0 : goto fail;
444 : }
445 :
446 2693 : memcpy(&locks[br_lck->num_locks], plock, sizeof(struct lock_struct));
447 2693 : br_lck->num_locks += 1;
448 2693 : br_lck->lock_data = locks;
449 2693 : br_lck->modified = True;
450 :
451 2693 : return NT_STATUS_OK;
452 110 : fail:
453 110 : contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WINDOWS_BRL);
454 110 : return status;
455 : }
456 :
457 : /****************************************************************************
458 : Cope with POSIX range splits and merges.
459 : ****************************************************************************/
460 :
461 958 : static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, /* Output array. */
462 : struct lock_struct *ex, /* existing lock. */
463 : struct lock_struct *plock) /* proposed lock. */
464 : {
465 958 : bool lock_types_differ = (ex->lock_type != plock->lock_type);
466 :
467 : /* We can't merge non-conflicting locks on different context - ignore fnum. */
468 :
469 958 : if (!brl_same_context(&ex->context, &plock->context)) {
470 : /* Just copy. */
471 22 : memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
472 22 : return 1;
473 : }
474 :
475 : /* We now know we have the same context. */
476 :
477 : /* Did we overlap ? */
478 :
479 : /*********************************************
480 : +---------+
481 : | ex |
482 : +---------+
483 : +-------+
484 : | plock |
485 : +-------+
486 : OR....
487 : +---------+
488 : | ex |
489 : +---------+
490 : **********************************************/
491 :
492 936 : if ( (ex->start > (plock->start + plock->size)) ||
493 924 : (plock->start > (ex->start + ex->size))) {
494 :
495 : /* No overlap with this lock - copy existing. */
496 :
497 20 : memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
498 20 : return 1;
499 : }
500 :
501 : /*********************************************
502 : +---------------------------+
503 : | ex |
504 : +---------------------------+
505 : +---------------------------+
506 : | plock | -> replace with plock.
507 : +---------------------------+
508 : OR
509 : +---------------+
510 : | ex |
511 : +---------------+
512 : +---------------------------+
513 : | plock | -> replace with plock.
514 : +---------------------------+
515 :
516 : **********************************************/
517 :
518 916 : if ( (ex->start >= plock->start) &&
519 912 : (ex->start + ex->size <= plock->start + plock->size) ) {
520 :
521 : /* Replace - discard existing lock. */
522 :
523 472 : return 0;
524 : }
525 :
526 : /*********************************************
527 : Adjacent after.
528 : +-------+
529 : | ex |
530 : +-------+
531 : +---------------+
532 : | plock |
533 : +---------------+
534 :
535 : BECOMES....
536 : +---------------+-------+
537 : | plock | ex | - different lock types.
538 : +---------------+-------+
539 : OR.... (merge)
540 : +-----------------------+
541 : | plock | - same lock type.
542 : +-----------------------+
543 : **********************************************/
544 :
545 444 : if (plock->start + plock->size == ex->start) {
546 :
547 : /* If the lock types are the same, we merge, if different, we
548 : add the remainder of the old lock. */
549 :
550 440 : if (lock_types_differ) {
551 : /* Add existing. */
552 0 : memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
553 0 : return 1;
554 : } else {
555 : /* Merge - adjust incoming lock as we may have more
556 : * merging to come. */
557 440 : plock->size += ex->size;
558 440 : return 0;
559 : }
560 : }
561 :
562 : /*********************************************
563 : Adjacent before.
564 : +-------+
565 : | ex |
566 : +-------+
567 : +---------------+
568 : | plock |
569 : +---------------+
570 : BECOMES....
571 : +-------+---------------+
572 : | ex | plock | - different lock types
573 : +-------+---------------+
574 :
575 : OR.... (merge)
576 : +-----------------------+
577 : | plock | - same lock type.
578 : +-----------------------+
579 :
580 : **********************************************/
581 :
582 4 : if (ex->start + ex->size == plock->start) {
583 :
584 : /* If the lock types are the same, we merge, if different, we
585 : add the existing lock. */
586 :
587 0 : if (lock_types_differ) {
588 0 : memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
589 0 : return 1;
590 : } else {
591 : /* Merge - adjust incoming lock as we may have more
592 : * merging to come. */
593 0 : plock->start = ex->start;
594 0 : plock->size += ex->size;
595 0 : return 0;
596 : }
597 : }
598 :
599 : /*********************************************
600 : Overlap after.
601 : +-----------------------+
602 : | ex |
603 : +-----------------------+
604 : +---------------+
605 : | plock |
606 : +---------------+
607 : OR
608 : +----------------+
609 : | ex |
610 : +----------------+
611 : +---------------+
612 : | plock |
613 : +---------------+
614 :
615 : BECOMES....
616 : +---------------+-------+
617 : | plock | ex | - different lock types.
618 : +---------------+-------+
619 : OR.... (merge)
620 : +-----------------------+
621 : | plock | - same lock type.
622 : +-----------------------+
623 : **********************************************/
624 :
625 4 : if ( (ex->start >= plock->start) &&
626 0 : (ex->start <= plock->start + plock->size) &&
627 0 : (ex->start + ex->size > plock->start + plock->size) ) {
628 :
629 : /* If the lock types are the same, we merge, if different, we
630 : add the remainder of the old lock. */
631 :
632 0 : if (lock_types_differ) {
633 : /* Add remaining existing. */
634 0 : memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
635 : /* Adjust existing start and size. */
636 0 : lck_arr[0].start = plock->start + plock->size;
637 0 : lck_arr[0].size = (ex->start + ex->size) - (plock->start + plock->size);
638 0 : return 1;
639 : } else {
640 : /* Merge - adjust incoming lock as we may have more
641 : * merging to come. */
642 0 : plock->size += (ex->start + ex->size) - (plock->start + plock->size);
643 0 : return 0;
644 : }
645 : }
646 :
647 : /*********************************************
648 : Overlap before.
649 : +-----------------------+
650 : | ex |
651 : +-----------------------+
652 : +---------------+
653 : | plock |
654 : +---------------+
655 : OR
656 : +-------------+
657 : | ex |
658 : +-------------+
659 : +---------------+
660 : | plock |
661 : +---------------+
662 :
663 : BECOMES....
664 : +-------+---------------+
665 : | ex | plock | - different lock types
666 : +-------+---------------+
667 :
668 : OR.... (merge)
669 : +-----------------------+
670 : | plock | - same lock type.
671 : +-----------------------+
672 :
673 : **********************************************/
674 :
675 4 : if ( (ex->start < plock->start) &&
676 4 : (ex->start + ex->size >= plock->start) &&
677 4 : (ex->start + ex->size <= plock->start + plock->size) ) {
678 :
679 : /* If the lock types are the same, we merge, if different, we
680 : add the truncated old lock. */
681 :
682 0 : if (lock_types_differ) {
683 0 : memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
684 : /* Adjust existing size. */
685 0 : lck_arr[0].size = plock->start - ex->start;
686 0 : return 1;
687 : } else {
688 : /* Merge - adjust incoming lock as we may have more
689 : * merging to come. MUST ADJUST plock SIZE FIRST ! */
690 0 : plock->size += (plock->start - ex->start);
691 0 : plock->start = ex->start;
692 0 : return 0;
693 : }
694 : }
695 :
696 : /*********************************************
697 : Complete overlap.
698 : +---------------------------+
699 : | ex |
700 : +---------------------------+
701 : +---------+
702 : | plock |
703 : +---------+
704 : BECOMES.....
705 : +-------+---------+---------+
706 : | ex | plock | ex | - different lock types.
707 : +-------+---------+---------+
708 : OR
709 : +---------------------------+
710 : | plock | - same lock type.
711 : +---------------------------+
712 : **********************************************/
713 :
714 4 : if ( (ex->start < plock->start) && (ex->start + ex->size > plock->start + plock->size) ) {
715 :
716 4 : if (lock_types_differ) {
717 :
718 : /* We have to split ex into two locks here. */
719 :
720 4 : memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
721 4 : memcpy(&lck_arr[1], ex, sizeof(struct lock_struct));
722 :
723 : /* Adjust first existing size. */
724 4 : lck_arr[0].size = plock->start - ex->start;
725 :
726 : /* Adjust second existing start and size. */
727 4 : lck_arr[1].start = plock->start + plock->size;
728 4 : lck_arr[1].size = (ex->start + ex->size) - (plock->start + plock->size);
729 4 : return 2;
730 : } else {
731 : /* Just eat the existing locks, merge them into plock. */
732 0 : plock->start = ex->start;
733 0 : plock->size = ex->size;
734 0 : return 0;
735 : }
736 : }
737 :
738 : /* Never get here. */
739 0 : smb_panic("brlock_posix_split_merge");
740 : /* Notreached. */
741 :
742 : /* Keep some compilers happy. */
743 : return 0;
744 : }
745 :
746 : /****************************************************************************
747 : Lock a range of bytes - POSIX lock semantics.
748 : We must cope with range splits and merges.
749 : ****************************************************************************/
750 :
751 916 : static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
752 : struct lock_struct *plock)
753 : {
754 0 : unsigned int i, count, posix_count;
755 916 : struct lock_struct *locks = br_lck->lock_data;
756 0 : struct lock_struct *tp;
757 916 : bool break_oplocks = false;
758 0 : NTSTATUS status;
759 :
760 : /* No zero-zero locks for POSIX. */
761 916 : if (plock->start == 0 && plock->size == 0) {
762 0 : return NT_STATUS_INVALID_PARAMETER;
763 : }
764 :
765 : /* Don't allow 64-bit lock wrap. */
766 916 : if (plock->start + plock->size - 1 < plock->start) {
767 0 : return NT_STATUS_INVALID_PARAMETER;
768 : }
769 :
770 : /* The worst case scenario here is we have to split an
771 : existing POSIX lock range into two, and add our lock,
772 : so we need at most 2 more entries. */
773 :
774 916 : tp = talloc_array(br_lck, struct lock_struct, br_lck->num_locks + 2);
775 916 : if (!tp) {
776 0 : return NT_STATUS_NO_MEMORY;
777 : }
778 :
779 916 : count = posix_count = 0;
780 :
781 1388 : for (i=0; i < br_lck->num_locks; i++) {
782 480 : struct lock_struct *curr_lock = &locks[i];
783 :
784 480 : if (curr_lock->lock_flav == WINDOWS_LOCK) {
785 : /* Do any Windows flavour locks conflict ? */
786 0 : if (brl_conflict(curr_lock, plock)) {
787 0 : if (!serverid_exists(&curr_lock->context.pid)) {
788 0 : curr_lock->context.pid.pid = 0;
789 0 : br_lck->modified = true;
790 0 : continue;
791 : }
792 : /* No games with error messages. */
793 0 : TALLOC_FREE(tp);
794 : /* Remember who blocked us. */
795 0 : plock->context.smblctx = curr_lock->context.smblctx;
796 0 : return NT_STATUS_LOCK_NOT_GRANTED;
797 : }
798 : /* Just copy the Windows lock into the new array. */
799 0 : memcpy(&tp[count], curr_lock, sizeof(struct lock_struct));
800 0 : count++;
801 : } else {
802 480 : unsigned int tmp_count = 0;
803 :
804 : /* POSIX conflict semantics are different. */
805 480 : if (brl_conflict_posix(curr_lock, plock)) {
806 8 : if (!serverid_exists(&curr_lock->context.pid)) {
807 0 : curr_lock->context.pid.pid = 0;
808 0 : br_lck->modified = true;
809 0 : continue;
810 : }
811 : /* Can't block ourselves with POSIX locks. */
812 : /* No games with error messages. */
813 8 : TALLOC_FREE(tp);
814 : /* Remember who blocked us. */
815 8 : plock->context.smblctx = curr_lock->context.smblctx;
816 8 : return NT_STATUS_LOCK_NOT_GRANTED;
817 : }
818 :
819 : /* Work out overlaps. */
820 472 : tmp_count += brlock_posix_split_merge(&tp[count], curr_lock, plock);
821 472 : posix_count += tmp_count;
822 472 : count += tmp_count;
823 : }
824 : }
825 :
826 : /*
827 : * Break oplocks while we hold a brl. Since lock() and unlock() calls
828 : * are not symmetric with POSIX semantics, we cannot guarantee our
829 : * contend_level2_oplocks_begin/end calls will be acquired and
830 : * released one-for-one as with Windows semantics. Therefore we only
831 : * call contend_level2_oplocks_begin if this is the first POSIX brl on
832 : * the file.
833 : */
834 908 : break_oplocks = (posix_count == 0);
835 908 : if (break_oplocks) {
836 876 : contend_level2_oplocks_begin(br_lck->fsp,
837 : LEVEL2_CONTEND_POSIX_BRL);
838 : }
839 :
840 : /* Try and add the lock in order, sorted by lock start. */
841 940 : for (i=0; i < count; i++) {
842 32 : struct lock_struct *curr_lock = &tp[i];
843 :
844 32 : if (curr_lock->start <= plock->start) {
845 26 : continue;
846 : }
847 : }
848 :
849 908 : if (i < count) {
850 0 : memmove(&tp[i+1], &tp[i],
851 0 : (count - i)*sizeof(struct lock_struct));
852 : }
853 908 : memcpy(&tp[i], plock, sizeof(struct lock_struct));
854 908 : count++;
855 :
856 : /* We can get the POSIX lock, now see if it needs to
857 : be mapped into a lower level POSIX one, and if so can
858 : we get it ? */
859 :
860 908 : if (lp_posix_locking(br_lck->fsp->conn->params)) {
861 0 : int errno_ret;
862 :
863 : /* The lower layer just needs to attempt to
864 : get the system POSIX lock. We've weeded out
865 : any conflicts above. */
866 :
867 908 : if (!set_posix_lock_posix_flavour(br_lck->fsp,
868 : plock->start,
869 : plock->size,
870 : plock->lock_type,
871 908 : &plock->context,
872 : &errno_ret)) {
873 :
874 : /* We don't know who blocked us. */
875 0 : plock->context.smblctx = 0xFFFFFFFFFFFFFFFFLL;
876 :
877 0 : if (errno_ret == EACCES || errno_ret == EAGAIN) {
878 0 : TALLOC_FREE(tp);
879 0 : status = NT_STATUS_LOCK_NOT_GRANTED;
880 0 : goto fail;
881 : } else {
882 0 : TALLOC_FREE(tp);
883 0 : status = map_nt_error_from_unix(errno);
884 0 : goto fail;
885 : }
886 : }
887 : }
888 :
889 : /* If we didn't use all the allocated size,
890 : * Realloc so we don't leak entries per lock call. */
891 908 : if (count < br_lck->num_locks + 2) {
892 908 : tp = talloc_realloc(br_lck, tp, struct lock_struct, count);
893 908 : if (!tp) {
894 0 : status = NT_STATUS_NO_MEMORY;
895 0 : goto fail;
896 : }
897 : }
898 :
899 908 : br_lck->num_locks = count;
900 908 : TALLOC_FREE(br_lck->lock_data);
901 908 : br_lck->lock_data = tp;
902 908 : locks = tp;
903 908 : br_lck->modified = True;
904 :
905 : /* A successful downgrade from write to read lock can trigger a lock
906 : re-evalutation where waiting readers can now proceed. */
907 :
908 908 : return NT_STATUS_OK;
909 0 : fail:
910 0 : if (break_oplocks) {
911 0 : contend_level2_oplocks_end(br_lck->fsp,
912 : LEVEL2_CONTEND_POSIX_BRL);
913 : }
914 0 : return status;
915 : }
916 :
917 : /****************************************************************************
918 : Lock a range of bytes.
919 : ****************************************************************************/
920 :
921 6753 : NTSTATUS brl_lock(
922 : struct byte_range_lock *br_lck,
923 : uint64_t smblctx,
924 : struct server_id pid,
925 : br_off start,
926 : br_off size,
927 : enum brl_type lock_type,
928 : enum brl_flavour lock_flav,
929 : struct server_id *blocker_pid,
930 : uint64_t *psmblctx)
931 : {
932 26 : NTSTATUS ret;
933 26 : struct lock_struct lock;
934 :
935 6753 : ZERO_STRUCT(lock);
936 :
937 6753 : lock = (struct lock_struct) {
938 : .context.smblctx = smblctx,
939 : .context.pid = pid,
940 6753 : .context.tid = br_lck->fsp->conn->cnum,
941 : .start = start,
942 : .size = size,
943 6753 : .fnum = br_lck->fsp->fnum,
944 : .lock_type = lock_type,
945 : .lock_flav = lock_flav
946 : };
947 :
948 6753 : if (lock_flav == WINDOWS_LOCK) {
949 5837 : ret = SMB_VFS_BRL_LOCK_WINDOWS(
950 : br_lck->fsp->conn, br_lck, &lock);
951 : } else {
952 916 : ret = brl_lock_posix(br_lck, &lock);
953 : }
954 :
955 : /* If we're returning an error, return who blocked us. */
956 6753 : if (!NT_STATUS_IS_OK(ret) && psmblctx) {
957 3152 : *blocker_pid = lock.context.pid;
958 3152 : *psmblctx = lock.context.smblctx;
959 : }
960 6753 : return ret;
961 : }
962 :
963 : /****************************************************************************
964 : Unlock a range of bytes - Windows semantics.
965 : ****************************************************************************/
966 :
967 2889 : bool brl_unlock_windows_default(struct byte_range_lock *br_lck,
968 : const struct lock_struct *plock)
969 : {
970 22 : unsigned int i;
971 2889 : struct lock_struct *locks = br_lck->lock_data;
972 2889 : enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */
973 :
974 2889 : SMB_ASSERT(plock->lock_type == UNLOCK_LOCK);
975 :
976 :
977 4512 : for (i = 0; i < br_lck->num_locks; i++) {
978 4308 : struct lock_struct *lock = &locks[i];
979 :
980 : /* Only remove our own locks that match in start, size, and flavour. */
981 4308 : if (brl_same_context(&lock->context, &plock->context) &&
982 3416 : lock->fnum == plock->fnum &&
983 3360 : lock->lock_flav == WINDOWS_LOCK &&
984 3360 : lock->start == plock->start &&
985 2711 : lock->size == plock->size ) {
986 2685 : deleted_lock_type = lock->lock_type;
987 2685 : break;
988 : }
989 : }
990 :
991 2889 : if (i == br_lck->num_locks) {
992 : /* we didn't find it */
993 200 : return False;
994 : }
995 :
996 2685 : ARRAY_DEL_ELEMENT(locks, i, br_lck->num_locks);
997 2685 : br_lck->num_locks -= 1;
998 2685 : br_lck->modified = True;
999 :
1000 : /* Unlock the underlying POSIX regions. */
1001 2685 : if(lp_posix_locking(br_lck->fsp->conn->params)) {
1002 2337 : release_posix_lock_windows_flavour(br_lck->fsp,
1003 2337 : plock->start,
1004 2337 : plock->size,
1005 : deleted_lock_type,
1006 : &plock->context,
1007 : locks,
1008 2337 : br_lck->num_locks);
1009 : }
1010 :
1011 2685 : contend_level2_oplocks_end(br_lck->fsp, LEVEL2_CONTEND_WINDOWS_BRL);
1012 2685 : return True;
1013 : }
1014 :
1015 : /****************************************************************************
1016 : Unlock a range of bytes - POSIX semantics.
1017 : ****************************************************************************/
1018 :
1019 476 : static bool brl_unlock_posix(struct byte_range_lock *br_lck,
1020 : struct lock_struct *plock)
1021 : {
1022 0 : unsigned int i, count;
1023 0 : struct lock_struct *tp;
1024 476 : struct lock_struct *locks = br_lck->lock_data;
1025 476 : bool overlap_found = False;
1026 :
1027 : /* No zero-zero locks for POSIX. */
1028 476 : if (plock->start == 0 && plock->size == 0) {
1029 0 : return False;
1030 : }
1031 :
1032 : /* Don't allow 64-bit lock wrap. */
1033 476 : if (plock->start + plock->size < plock->start ||
1034 476 : plock->start + plock->size < plock->size) {
1035 0 : DEBUG(10,("brl_unlock_posix: lock wrap\n"));
1036 0 : return False;
1037 : }
1038 :
1039 : /* The worst case scenario here is we have to split an
1040 : existing POSIX lock range into two, so we need at most
1041 : 1 more entry. */
1042 :
1043 476 : tp = talloc_array(br_lck, struct lock_struct, br_lck->num_locks + 1);
1044 476 : if (!tp) {
1045 0 : DEBUG(10,("brl_unlock_posix: malloc fail\n"));
1046 0 : return False;
1047 : }
1048 :
1049 476 : count = 0;
1050 976 : for (i = 0; i < br_lck->num_locks; i++) {
1051 504 : struct lock_struct *lock = &locks[i];
1052 0 : unsigned int tmp_count;
1053 :
1054 : /* Only remove our own locks - ignore fnum. */
1055 504 : if (!brl_same_context(&lock->context, &plock->context)) {
1056 14 : memcpy(&tp[count], lock, sizeof(struct lock_struct));
1057 14 : count++;
1058 14 : continue;
1059 : }
1060 :
1061 490 : if (lock->lock_flav == WINDOWS_LOCK) {
1062 : /* Do any Windows flavour locks conflict ? */
1063 4 : if (brl_conflict(lock, plock)) {
1064 0 : TALLOC_FREE(tp);
1065 0 : return false;
1066 : }
1067 : /* Just copy the Windows lock into the new array. */
1068 4 : memcpy(&tp[count], lock, sizeof(struct lock_struct));
1069 4 : count++;
1070 4 : continue;
1071 : }
1072 :
1073 : /* Work out overlaps. */
1074 486 : tmp_count = brlock_posix_split_merge(&tp[count], lock, plock);
1075 :
1076 486 : if (tmp_count == 0) {
1077 : /* plock overlapped the existing lock completely,
1078 : or replaced it. Don't copy the existing lock. */
1079 472 : overlap_found = true;
1080 14 : } else if (tmp_count == 1) {
1081 : /* Either no overlap, (simple copy of existing lock) or
1082 : * an overlap of an existing lock. */
1083 : /* If the lock changed size, we had an overlap. */
1084 10 : if (tp[count].size != lock->size) {
1085 0 : overlap_found = true;
1086 : }
1087 10 : count += tmp_count;
1088 4 : } else if (tmp_count == 2) {
1089 : /* We split a lock range in two. */
1090 4 : overlap_found = true;
1091 4 : count += tmp_count;
1092 :
1093 : /* Optimisation... */
1094 : /* We know we're finished here as we can't overlap any
1095 : more POSIX locks. Copy the rest of the lock array. */
1096 :
1097 4 : if (i < br_lck->num_locks - 1) {
1098 0 : memcpy(&tp[count], &locks[i+1],
1099 0 : sizeof(*locks)*((br_lck->num_locks-1) - i));
1100 0 : count += ((br_lck->num_locks-1) - i);
1101 : }
1102 4 : break;
1103 : }
1104 :
1105 : }
1106 :
1107 476 : if (!overlap_found) {
1108 : /* Just ignore - no change. */
1109 0 : TALLOC_FREE(tp);
1110 0 : DEBUG(10,("brl_unlock_posix: No overlap - unlocked.\n"));
1111 0 : return True;
1112 : }
1113 :
1114 : /* Unlock any POSIX regions. */
1115 476 : if(lp_posix_locking(br_lck->fsp->conn->params)) {
1116 476 : release_posix_lock_posix_flavour(br_lck->fsp,
1117 : plock->start,
1118 : plock->size,
1119 476 : &plock->context,
1120 : tp,
1121 : count);
1122 : }
1123 :
1124 : /* Realloc so we don't leak entries per unlock call. */
1125 476 : if (count) {
1126 30 : tp = talloc_realloc(br_lck, tp, struct lock_struct, count);
1127 30 : if (!tp) {
1128 0 : DEBUG(10,("brl_unlock_posix: realloc fail\n"));
1129 0 : return False;
1130 : }
1131 : } else {
1132 : /* We deleted the last lock. */
1133 446 : TALLOC_FREE(tp);
1134 446 : tp = NULL;
1135 : }
1136 :
1137 476 : contend_level2_oplocks_end(br_lck->fsp,
1138 : LEVEL2_CONTEND_POSIX_BRL);
1139 :
1140 476 : br_lck->num_locks = count;
1141 476 : TALLOC_FREE(br_lck->lock_data);
1142 476 : locks = tp;
1143 476 : br_lck->lock_data = tp;
1144 476 : br_lck->modified = True;
1145 :
1146 476 : return True;
1147 : }
1148 :
1149 : /****************************************************************************
1150 : Unlock a range of bytes.
1151 : ****************************************************************************/
1152 :
1153 3365 : bool brl_unlock(struct byte_range_lock *br_lck,
1154 : uint64_t smblctx,
1155 : struct server_id pid,
1156 : br_off start,
1157 : br_off size,
1158 : enum brl_flavour lock_flav)
1159 : {
1160 22 : struct lock_struct lock;
1161 :
1162 3365 : lock.context.smblctx = smblctx;
1163 3365 : lock.context.pid = pid;
1164 3365 : lock.context.tid = br_lck->fsp->conn->cnum;
1165 3365 : lock.start = start;
1166 3365 : lock.size = size;
1167 3365 : lock.fnum = br_lck->fsp->fnum;
1168 3365 : lock.lock_type = UNLOCK_LOCK;
1169 3365 : lock.lock_flav = lock_flav;
1170 :
1171 3365 : if (lock_flav == WINDOWS_LOCK) {
1172 2889 : return SMB_VFS_BRL_UNLOCK_WINDOWS(
1173 : br_lck->fsp->conn, br_lck, &lock);
1174 : } else {
1175 476 : return brl_unlock_posix(br_lck, &lock);
1176 : }
1177 : }
1178 :
1179 : /****************************************************************************
1180 : Test if we could add a lock if we wanted to.
1181 : Returns True if the region required is currently unlocked, False if locked.
1182 : ****************************************************************************/
1183 :
1184 203861 : bool brl_locktest(struct byte_range_lock *br_lck,
1185 : const struct lock_struct *rw_probe)
1186 : {
1187 203861 : bool ret = True;
1188 119 : unsigned int i;
1189 203861 : struct lock_struct *locks = br_lck->lock_data;
1190 203861 : files_struct *fsp = br_lck->fsp;
1191 :
1192 : /* Make sure existing locks don't conflict */
1193 205782 : for (i=0; i < br_lck->num_locks; i++) {
1194 : /*
1195 : * Our own locks don't conflict.
1196 : */
1197 2175 : if (brl_conflict_other(&locks[i], rw_probe)) {
1198 258 : if (br_lck->record == NULL) {
1199 : /* readonly */
1200 126 : return false;
1201 : }
1202 :
1203 129 : if (!serverid_exists(&locks[i].context.pid)) {
1204 4 : locks[i].context.pid.pid = 0;
1205 4 : br_lck->modified = true;
1206 4 : continue;
1207 : }
1208 :
1209 122 : return False;
1210 : }
1211 : }
1212 :
1213 : /*
1214 : * There is no lock held by an SMB daemon, check to
1215 : * see if there is a POSIX lock from a UNIX or NFS process.
1216 : * This only conflicts with Windows locks, not POSIX locks.
1217 : */
1218 :
1219 203607 : if(lp_posix_locking(fsp->conn->params) &&
1220 203389 : (rw_probe->lock_flav == WINDOWS_LOCK)) {
1221 : /*
1222 : * Make copies -- is_posix_locked might modify the values
1223 : */
1224 :
1225 202869 : br_off start = rw_probe->start;
1226 202869 : br_off size = rw_probe->size;
1227 202869 : enum brl_type lock_type = rw_probe->lock_type;
1228 :
1229 202869 : ret = is_posix_locked(fsp, &start, &size, &lock_type, WINDOWS_LOCK);
1230 :
1231 202869 : DEBUG(10, ("brl_locktest: posix start=%ju len=%ju %s for %s "
1232 : "file %s\n", (uintmax_t)start, (uintmax_t)size,
1233 : ret ? "locked" : "unlocked",
1234 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
1235 :
1236 : /* We need to return the inverse of is_posix_locked. */
1237 202869 : ret = !ret;
1238 : }
1239 :
1240 : /* no conflicts - we could have added it */
1241 203494 : return ret;
1242 : }
1243 :
1244 : /****************************************************************************
1245 : Query for existing locks.
1246 : ****************************************************************************/
1247 :
1248 0 : NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
1249 : uint64_t *psmblctx,
1250 : struct server_id pid,
1251 : br_off *pstart,
1252 : br_off *psize,
1253 : enum brl_type *plock_type,
1254 : enum brl_flavour lock_flav)
1255 : {
1256 0 : unsigned int i;
1257 0 : struct lock_struct lock;
1258 0 : const struct lock_struct *locks = br_lck->lock_data;
1259 0 : files_struct *fsp = br_lck->fsp;
1260 :
1261 0 : lock.context.smblctx = *psmblctx;
1262 0 : lock.context.pid = pid;
1263 0 : lock.context.tid = br_lck->fsp->conn->cnum;
1264 0 : lock.start = *pstart;
1265 0 : lock.size = *psize;
1266 0 : lock.fnum = fsp->fnum;
1267 0 : lock.lock_type = *plock_type;
1268 0 : lock.lock_flav = lock_flav;
1269 :
1270 : /* Make sure existing locks don't conflict */
1271 0 : for (i=0; i < br_lck->num_locks; i++) {
1272 0 : const struct lock_struct *exlock = &locks[i];
1273 0 : bool conflict = False;
1274 :
1275 0 : if (exlock->lock_flav == WINDOWS_LOCK) {
1276 0 : conflict = brl_conflict(exlock, &lock);
1277 : } else {
1278 0 : conflict = brl_conflict_posix(exlock, &lock);
1279 : }
1280 :
1281 0 : if (conflict) {
1282 0 : *psmblctx = exlock->context.smblctx;
1283 0 : *pstart = exlock->start;
1284 0 : *psize = exlock->size;
1285 0 : *plock_type = exlock->lock_type;
1286 0 : return NT_STATUS_LOCK_NOT_GRANTED;
1287 : }
1288 : }
1289 :
1290 : /*
1291 : * There is no lock held by an SMB daemon, check to
1292 : * see if there is a POSIX lock from a UNIX or NFS process.
1293 : */
1294 :
1295 0 : if(lp_posix_locking(fsp->conn->params)) {
1296 0 : bool ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK);
1297 :
1298 0 : DEBUG(10, ("brl_lockquery: posix start=%ju len=%ju %s for %s "
1299 : "file %s\n", (uintmax_t)*pstart,
1300 : (uintmax_t)*psize, ret ? "locked" : "unlocked",
1301 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
1302 :
1303 0 : if (ret) {
1304 : /* Hmmm. No clue what to set smblctx to - use -1. */
1305 0 : *psmblctx = 0xFFFFFFFFFFFFFFFFLL;
1306 0 : return NT_STATUS_LOCK_NOT_GRANTED;
1307 : }
1308 : }
1309 :
1310 0 : return NT_STATUS_OK;
1311 : }
1312 :
1313 :
1314 : /****************************************************************************
1315 : Remove any locks associated with a open file.
1316 : We return True if this process owns any other Windows locks on this
1317 : fd and so we should not immediately close the fd.
1318 : ****************************************************************************/
1319 :
1320 899 : void brl_close_fnum(struct byte_range_lock *br_lck)
1321 : {
1322 899 : files_struct *fsp = br_lck->fsp;
1323 899 : uint32_t tid = fsp->conn->cnum;
1324 899 : uint64_t fnum = fsp->fnum;
1325 6 : unsigned int i;
1326 899 : struct lock_struct *locks = br_lck->lock_data;
1327 899 : struct server_id pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
1328 6 : struct lock_struct *locks_copy;
1329 6 : unsigned int num_locks_copy;
1330 :
1331 : /* Copy the current lock array. */
1332 899 : if (br_lck->num_locks) {
1333 803 : locks_copy = (struct lock_struct *)talloc_memdup(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct));
1334 803 : if (!locks_copy) {
1335 0 : smb_panic("brl_close_fnum: talloc failed");
1336 : }
1337 : } else {
1338 96 : locks_copy = NULL;
1339 : }
1340 :
1341 899 : num_locks_copy = br_lck->num_locks;
1342 :
1343 2068 : for (i=0; i < num_locks_copy; i++) {
1344 1169 : struct lock_struct *lock = &locks_copy[i];
1345 :
1346 2290 : if (lock->context.tid == tid &&
1347 1121 : server_id_equal(&lock->context.pid, &pid) &&
1348 1121 : (lock->fnum == fnum)) {
1349 1003 : brl_unlock(
1350 : br_lck,
1351 : lock->context.smblctx,
1352 : pid,
1353 : lock->start,
1354 : lock->size,
1355 : lock->lock_flav);
1356 : }
1357 : }
1358 899 : }
1359 :
1360 160 : bool brl_mark_disconnected(struct files_struct *fsp)
1361 : {
1362 160 : uint32_t tid = fsp->conn->cnum;
1363 0 : uint64_t smblctx;
1364 160 : uint64_t fnum = fsp->fnum;
1365 0 : unsigned int i;
1366 160 : struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
1367 160 : struct byte_range_lock *br_lck = NULL;
1368 :
1369 160 : if (fsp->op == NULL) {
1370 0 : return false;
1371 : }
1372 :
1373 160 : smblctx = fsp->op->global->open_persistent_id;
1374 :
1375 160 : if (!fsp->op->global->durable) {
1376 0 : return false;
1377 : }
1378 :
1379 160 : if (fsp->current_lock_count == 0) {
1380 154 : return true;
1381 : }
1382 :
1383 6 : br_lck = brl_get_locks(talloc_tos(), fsp);
1384 6 : if (br_lck == NULL) {
1385 0 : return false;
1386 : }
1387 :
1388 12 : for (i=0; i < br_lck->num_locks; i++) {
1389 6 : struct lock_struct *lock = &br_lck->lock_data[i];
1390 :
1391 : /*
1392 : * as this is a durable handle, we only expect locks
1393 : * of the current file handle!
1394 : */
1395 :
1396 6 : if (lock->context.smblctx != smblctx) {
1397 0 : TALLOC_FREE(br_lck);
1398 0 : return false;
1399 : }
1400 :
1401 6 : if (lock->context.tid != tid) {
1402 0 : TALLOC_FREE(br_lck);
1403 0 : return false;
1404 : }
1405 :
1406 6 : if (!server_id_equal(&lock->context.pid, &self)) {
1407 0 : TALLOC_FREE(br_lck);
1408 0 : return false;
1409 : }
1410 :
1411 6 : if (lock->fnum != fnum) {
1412 0 : TALLOC_FREE(br_lck);
1413 0 : return false;
1414 : }
1415 :
1416 6 : server_id_set_disconnected(&lock->context.pid);
1417 6 : lock->context.tid = TID_FIELD_INVALID;
1418 6 : lock->fnum = FNUM_FIELD_INVALID;
1419 : }
1420 :
1421 6 : br_lck->modified = true;
1422 6 : TALLOC_FREE(br_lck);
1423 6 : return true;
1424 : }
1425 :
1426 130 : bool brl_reconnect_disconnected(struct files_struct *fsp)
1427 : {
1428 130 : uint32_t tid = fsp->conn->cnum;
1429 0 : uint64_t smblctx;
1430 130 : uint64_t fnum = fsp->fnum;
1431 0 : unsigned int i;
1432 130 : struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
1433 130 : struct byte_range_lock *br_lck = NULL;
1434 :
1435 130 : if (fsp->op == NULL) {
1436 0 : return false;
1437 : }
1438 :
1439 130 : smblctx = fsp->op->global->open_persistent_id;
1440 :
1441 130 : if (!fsp->op->global->durable) {
1442 0 : return false;
1443 : }
1444 :
1445 : /*
1446 : * When reconnecting, we do not want to validate the brlock entries
1447 : * and thereby remove our own (disconnected) entries but reactivate
1448 : * them instead.
1449 : */
1450 :
1451 130 : br_lck = brl_get_locks(talloc_tos(), fsp);
1452 130 : if (br_lck == NULL) {
1453 0 : return false;
1454 : }
1455 :
1456 130 : if (br_lck->num_locks == 0) {
1457 124 : TALLOC_FREE(br_lck);
1458 124 : return true;
1459 : }
1460 :
1461 12 : for (i=0; i < br_lck->num_locks; i++) {
1462 6 : struct lock_struct *lock = &br_lck->lock_data[i];
1463 :
1464 : /*
1465 : * as this is a durable handle we only expect locks
1466 : * of the current file handle!
1467 : */
1468 :
1469 6 : if (lock->context.smblctx != smblctx) {
1470 0 : TALLOC_FREE(br_lck);
1471 0 : return false;
1472 : }
1473 :
1474 6 : if (lock->context.tid != TID_FIELD_INVALID) {
1475 0 : TALLOC_FREE(br_lck);
1476 0 : return false;
1477 : }
1478 :
1479 6 : if (!server_id_is_disconnected(&lock->context.pid)) {
1480 0 : TALLOC_FREE(br_lck);
1481 0 : return false;
1482 : }
1483 :
1484 6 : if (lock->fnum != FNUM_FIELD_INVALID) {
1485 0 : TALLOC_FREE(br_lck);
1486 0 : return false;
1487 : }
1488 :
1489 6 : lock->context.pid = self;
1490 6 : lock->context.tid = tid;
1491 6 : lock->fnum = fnum;
1492 : }
1493 :
1494 6 : fsp->current_lock_count = br_lck->num_locks;
1495 6 : br_lck->modified = true;
1496 6 : TALLOC_FREE(br_lck);
1497 6 : return true;
1498 : }
1499 :
1500 : struct brl_forall_cb {
1501 : void (*fn)(struct file_id id, struct server_id pid,
1502 : enum brl_type lock_type,
1503 : enum brl_flavour lock_flav,
1504 : br_off start, br_off size,
1505 : void *private_data);
1506 : void *private_data;
1507 : };
1508 :
1509 : /****************************************************************************
1510 : Traverse the whole database with this function, calling traverse_callback
1511 : on each lock.
1512 : ****************************************************************************/
1513 :
1514 0 : static int brl_traverse_fn(struct db_record *rec, void *state)
1515 : {
1516 0 : struct brl_forall_cb *cb = (struct brl_forall_cb *)state;
1517 0 : struct lock_struct *locks;
1518 0 : struct file_id *key;
1519 0 : unsigned int i;
1520 0 : unsigned int num_locks = 0;
1521 0 : TDB_DATA dbkey;
1522 0 : TDB_DATA value;
1523 :
1524 0 : dbkey = dbwrap_record_get_key(rec);
1525 0 : value = dbwrap_record_get_value(rec);
1526 :
1527 : /* In a traverse function we must make a copy of
1528 : dbuf before modifying it. */
1529 :
1530 0 : locks = (struct lock_struct *)talloc_memdup(
1531 : talloc_tos(), value.dptr, value.dsize);
1532 0 : if (!locks) {
1533 0 : return -1; /* Terminate traversal. */
1534 : }
1535 :
1536 0 : key = (struct file_id *)dbkey.dptr;
1537 0 : num_locks = value.dsize/sizeof(*locks);
1538 :
1539 0 : if (cb->fn) {
1540 0 : for ( i=0; i<num_locks; i++) {
1541 0 : cb->fn(*key,
1542 0 : locks[i].context.pid,
1543 0 : locks[i].lock_type,
1544 0 : locks[i].lock_flav,
1545 0 : locks[i].start,
1546 0 : locks[i].size,
1547 : cb->private_data);
1548 : }
1549 : }
1550 :
1551 0 : TALLOC_FREE(locks);
1552 0 : return 0;
1553 : }
1554 :
1555 : /*******************************************************************
1556 : Call the specified function on each lock in the database.
1557 : ********************************************************************/
1558 :
1559 2 : int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
1560 : enum brl_type lock_type,
1561 : enum brl_flavour lock_flav,
1562 : br_off start, br_off size,
1563 : void *private_data),
1564 : void *private_data)
1565 : {
1566 0 : struct brl_forall_cb cb;
1567 0 : NTSTATUS status;
1568 2 : int count = 0;
1569 :
1570 2 : if (!brlock_db) {
1571 0 : return 0;
1572 : }
1573 2 : cb.fn = fn;
1574 2 : cb.private_data = private_data;
1575 2 : status = dbwrap_traverse(brlock_db, brl_traverse_fn, &cb, &count);
1576 :
1577 2 : if (!NT_STATUS_IS_OK(status)) {
1578 0 : return -1;
1579 : } else {
1580 2 : return count;
1581 : }
1582 : }
1583 :
1584 : /*******************************************************************
1585 : Store a potentially modified set of byte range lock data back into
1586 : the database.
1587 : Unlock the record.
1588 : ********************************************************************/
1589 :
1590 10281 : static void byte_range_lock_flush(struct byte_range_lock *br_lck)
1591 : {
1592 49 : unsigned i;
1593 10281 : struct lock_struct *locks = br_lck->lock_data;
1594 :
1595 10281 : if (!br_lck->modified) {
1596 3731 : DEBUG(10, ("br_lck not modified\n"));
1597 3731 : goto done;
1598 : }
1599 :
1600 6516 : i = 0;
1601 :
1602 176157 : while (i < br_lck->num_locks) {
1603 169607 : if (locks[i].context.pid.pid == 0) {
1604 : /*
1605 : * Autocleanup, the process conflicted and does not
1606 : * exist anymore.
1607 : */
1608 4 : locks[i] = locks[br_lck->num_locks-1];
1609 4 : br_lck->num_locks -= 1;
1610 : } else {
1611 169603 : i += 1;
1612 : }
1613 : }
1614 :
1615 6550 : if (br_lck->num_locks == 0) {
1616 : /* No locks - delete this entry. */
1617 1536 : NTSTATUS status = dbwrap_record_delete(br_lck->record);
1618 1536 : if (!NT_STATUS_IS_OK(status)) {
1619 0 : DEBUG(0, ("delete_rec returned %s\n",
1620 : nt_errstr(status)));
1621 0 : smb_panic("Could not delete byte range lock entry");
1622 : }
1623 : } else {
1624 5014 : TDB_DATA data = {
1625 5014 : .dsize = br_lck->num_locks * sizeof(struct lock_struct),
1626 4993 : .dptr = (uint8_t *)br_lck->lock_data,
1627 : };
1628 21 : NTSTATUS status;
1629 :
1630 5014 : status = dbwrap_record_store(br_lck->record, data, TDB_REPLACE);
1631 5014 : if (!NT_STATUS_IS_OK(status)) {
1632 0 : DEBUG(0, ("store returned %s\n", nt_errstr(status)));
1633 0 : smb_panic("Could not store byte range mode entry");
1634 : }
1635 : }
1636 :
1637 6550 : DEBUG(10, ("seqnum=%d\n", dbwrap_get_seqnum(brlock_db)));
1638 :
1639 10281 : done:
1640 10281 : br_lck->modified = false;
1641 10281 : TALLOC_FREE(br_lck->record);
1642 10281 : }
1643 :
1644 10281 : static int byte_range_lock_destructor(struct byte_range_lock *br_lck)
1645 : {
1646 10281 : byte_range_lock_flush(br_lck);
1647 10281 : return 0;
1648 : }
1649 :
1650 10541 : static bool brl_parse_data(struct byte_range_lock *br_lck, TDB_DATA data)
1651 : {
1652 60 : size_t data_len;
1653 :
1654 10541 : if (data.dsize == 0) {
1655 1985 : return true;
1656 : }
1657 8539 : if (data.dsize % sizeof(struct lock_struct) != 0) {
1658 0 : DEBUG(1, ("Invalid data size: %u\n", (unsigned)data.dsize));
1659 0 : return false;
1660 : }
1661 :
1662 8539 : br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
1663 8539 : data_len = br_lck->num_locks * sizeof(struct lock_struct);
1664 :
1665 8539 : br_lck->lock_data = talloc_memdup(br_lck, data.dptr, data_len);
1666 8539 : if (br_lck->lock_data == NULL) {
1667 0 : DEBUG(1, ("talloc_memdup failed\n"));
1668 0 : return false;
1669 : }
1670 8496 : return true;
1671 : }
1672 :
1673 : /*******************************************************************
1674 : Fetch a set of byte range lock data from the database.
1675 : Leave the record locked.
1676 : TALLOC_FREE(brl) will release the lock in the destructor.
1677 : ********************************************************************/
1678 :
1679 10281 : struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp)
1680 : {
1681 49 : TDB_DATA key, data;
1682 49 : struct byte_range_lock *br_lck;
1683 :
1684 10281 : br_lck = talloc_zero(mem_ctx, struct byte_range_lock);
1685 10281 : if (br_lck == NULL) {
1686 0 : return NULL;
1687 : }
1688 :
1689 10281 : br_lck->fsp = fsp;
1690 :
1691 10281 : key.dptr = (uint8_t *)&fsp->file_id;
1692 10281 : key.dsize = sizeof(struct file_id);
1693 :
1694 10281 : br_lck->record = dbwrap_fetch_locked(brlock_db, br_lck, key);
1695 :
1696 10281 : if (br_lck->record == NULL) {
1697 0 : DEBUG(3, ("Could not lock byte range lock entry\n"));
1698 0 : TALLOC_FREE(br_lck);
1699 0 : return NULL;
1700 : }
1701 :
1702 10281 : data = dbwrap_record_get_value(br_lck->record);
1703 :
1704 10281 : if (!brl_parse_data(br_lck, data)) {
1705 0 : TALLOC_FREE(br_lck);
1706 0 : return NULL;
1707 : }
1708 :
1709 10281 : talloc_set_destructor(br_lck, byte_range_lock_destructor);
1710 :
1711 10281 : if (DEBUGLEVEL >= 10) {
1712 0 : unsigned int i;
1713 0 : struct file_id_buf buf;
1714 0 : struct lock_struct *locks = br_lck->lock_data;
1715 0 : DBG_DEBUG("%u current locks on file_id %s\n",
1716 : br_lck->num_locks,
1717 : file_id_str_buf(fsp->file_id, &buf));
1718 0 : for( i = 0; i < br_lck->num_locks; i++) {
1719 0 : print_lock_struct(i, &locks[i]);
1720 : }
1721 : }
1722 :
1723 10232 : return br_lck;
1724 : }
1725 :
1726 6753 : struct byte_range_lock *brl_get_locks_for_locking(TALLOC_CTX *mem_ctx,
1727 : files_struct *fsp,
1728 : TALLOC_CTX *req_mem_ctx,
1729 : const struct GUID *req_guid)
1730 : {
1731 6753 : struct byte_range_lock *br_lck = NULL;
1732 :
1733 6753 : br_lck = brl_get_locks(mem_ctx, fsp);
1734 6753 : if (br_lck == NULL) {
1735 0 : return NULL;
1736 : }
1737 6753 : SMB_ASSERT(req_mem_ctx != NULL);
1738 6753 : br_lck->req_mem_ctx = req_mem_ctx;
1739 6753 : SMB_ASSERT(req_guid != NULL);
1740 6753 : br_lck->req_guid = req_guid;
1741 :
1742 6753 : return br_lck;
1743 : }
1744 :
1745 : struct brl_get_locks_readonly_state {
1746 : TALLOC_CTX *mem_ctx;
1747 : struct byte_range_lock **br_lock;
1748 : };
1749 :
1750 260 : static void brl_get_locks_readonly_parser(TDB_DATA key, TDB_DATA data,
1751 : void *private_data)
1752 : {
1753 260 : struct brl_get_locks_readonly_state *state =
1754 : (struct brl_get_locks_readonly_state *)private_data;
1755 11 : struct byte_range_lock *br_lck;
1756 :
1757 260 : br_lck = talloc_pooled_object(
1758 : state->mem_ctx, struct byte_range_lock, 1, data.dsize);
1759 260 : if (br_lck == NULL) {
1760 0 : *state->br_lock = NULL;
1761 0 : return;
1762 : }
1763 260 : *br_lck = (struct byte_range_lock) { 0 };
1764 260 : if (!brl_parse_data(br_lck, data)) {
1765 0 : *state->br_lock = NULL;
1766 0 : return;
1767 : }
1768 260 : *state->br_lock = br_lck;
1769 : }
1770 :
1771 554029 : struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp)
1772 : {
1773 554029 : struct byte_range_lock *br_lock = NULL;
1774 706 : struct brl_get_locks_readonly_state state;
1775 706 : NTSTATUS status;
1776 :
1777 554029 : DEBUG(10, ("seqnum=%d, fsp->brlock_seqnum=%d\n",
1778 : dbwrap_get_seqnum(brlock_db), fsp->brlock_seqnum));
1779 :
1780 554029 : if ((fsp->brlock_rec != NULL)
1781 203603 : && (dbwrap_get_seqnum(brlock_db) == fsp->brlock_seqnum)) {
1782 : /*
1783 : * We have cached the brlock_rec and the database did not
1784 : * change.
1785 : */
1786 203383 : return fsp->brlock_rec;
1787 : }
1788 :
1789 : /*
1790 : * Parse the record fresh from the database
1791 : */
1792 :
1793 350646 : state.mem_ctx = fsp;
1794 350646 : state.br_lock = &br_lock;
1795 :
1796 350646 : status = dbwrap_parse_record(
1797 : brlock_db,
1798 350646 : make_tdb_data((uint8_t *)&fsp->file_id,
1799 : sizeof(fsp->file_id)),
1800 : brl_get_locks_readonly_parser, &state);
1801 :
1802 350646 : if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_FOUND)) {
1803 : /*
1804 : * No locks on this file. Return an empty br_lock.
1805 : */
1806 350386 : br_lock = talloc_zero(fsp, struct byte_range_lock);
1807 350386 : if (br_lock == NULL) {
1808 0 : return NULL;
1809 : }
1810 :
1811 260 : } else if (!NT_STATUS_IS_OK(status)) {
1812 0 : DEBUG(3, ("Could not parse byte range lock record: "
1813 : "%s\n", nt_errstr(status)));
1814 0 : return NULL;
1815 : }
1816 350646 : if (br_lock == NULL) {
1817 0 : return NULL;
1818 : }
1819 :
1820 350646 : br_lock->fsp = fsp;
1821 350646 : br_lock->modified = false;
1822 350646 : br_lock->record = NULL;
1823 :
1824 : /*
1825 : * Cache the brlock struct, invalidated when the dbwrap_seqnum
1826 : * changes. See beginning of this routine.
1827 : */
1828 350646 : TALLOC_FREE(fsp->brlock_rec);
1829 350646 : fsp->brlock_rec = br_lock;
1830 350646 : fsp->brlock_seqnum = dbwrap_get_seqnum(brlock_db);
1831 :
1832 350646 : return br_lock;
1833 : }
1834 :
1835 2 : bool brl_cleanup_disconnected(struct file_id fid, uint64_t open_persistent_id)
1836 : {
1837 2 : bool ret = false;
1838 2 : TALLOC_CTX *frame = talloc_stackframe();
1839 0 : TDB_DATA key, val;
1840 0 : struct db_record *rec;
1841 0 : struct lock_struct *lock;
1842 0 : unsigned n, num;
1843 0 : struct file_id_buf buf;
1844 0 : NTSTATUS status;
1845 :
1846 2 : key = make_tdb_data((void*)&fid, sizeof(fid));
1847 :
1848 2 : rec = dbwrap_fetch_locked(brlock_db, frame, key);
1849 2 : if (rec == NULL) {
1850 0 : DBG_INFO("failed to fetch record for file %s\n",
1851 : file_id_str_buf(fid, &buf));
1852 0 : goto done;
1853 : }
1854 :
1855 2 : val = dbwrap_record_get_value(rec);
1856 2 : lock = (struct lock_struct*)val.dptr;
1857 2 : num = val.dsize / sizeof(struct lock_struct);
1858 2 : if (lock == NULL) {
1859 2 : DBG_DEBUG("no byte range locks for file %s\n",
1860 : file_id_str_buf(fid, &buf));
1861 2 : ret = true;
1862 2 : goto done;
1863 : }
1864 :
1865 0 : for (n=0; n<num; n++) {
1866 0 : struct lock_context *ctx = &lock[n].context;
1867 :
1868 0 : if (!server_id_is_disconnected(&ctx->pid)) {
1869 0 : struct server_id_buf tmp;
1870 0 : DBG_INFO("byte range lock "
1871 : "%s used by server %s, do not cleanup\n",
1872 : file_id_str_buf(fid, &buf),
1873 : server_id_str_buf(ctx->pid, &tmp));
1874 0 : goto done;
1875 : }
1876 :
1877 0 : if (ctx->smblctx != open_persistent_id) {
1878 0 : DBG_INFO("byte range lock %s expected smblctx %"PRIu64" "
1879 : "but found %"PRIu64", do not cleanup\n",
1880 : file_id_str_buf(fid, &buf),
1881 : open_persistent_id,
1882 : ctx->smblctx);
1883 0 : goto done;
1884 : }
1885 : }
1886 :
1887 0 : status = dbwrap_record_delete(rec);
1888 0 : if (!NT_STATUS_IS_OK(status)) {
1889 0 : DBG_INFO("failed to delete record "
1890 : "for file %s from %s, open %"PRIu64": %s\n",
1891 : file_id_str_buf(fid, &buf),
1892 : dbwrap_name(brlock_db),
1893 : open_persistent_id,
1894 : nt_errstr(status));
1895 0 : goto done;
1896 : }
1897 :
1898 0 : DBG_DEBUG("file %s cleaned up %u entries from open %"PRIu64"\n",
1899 : file_id_str_buf(fid, &buf),
1900 : num,
1901 : open_persistent_id);
1902 :
1903 0 : ret = true;
1904 2 : done:
1905 2 : talloc_free(frame);
1906 2 : return ret;
1907 : }
|