2 Unix SMB/CIFS implementation.
3 byte range locking code
4 Updated to handle range splits/merges.
6 Copyright (C) Andrew Tridgell 1992-2000
7 Copyright (C) Jeremy Allison 1992-2000
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.
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.
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/>.
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 */
28 #include "system/filesys.h"
29 #include "locking/proto.h"
30 #include "smbd/globals.h"
31 #include "dbwrap/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
38 #define DBGC_CLASS DBGC_LOCKING
42 /* The open brlock.tdb database. */
44 static struct db_context *brlock_db;
46 struct byte_range_lock {
47 struct files_struct *fsp;
48 unsigned int num_locks;
50 bool have_read_oplocks;
51 struct lock_struct *lock_data;
52 struct db_record *record;
55 /****************************************************************************
56 Debug info at level 10 for lock struct.
57 ****************************************************************************/
59 static void print_lock_struct(unsigned int i, const struct lock_struct *pls)
61 DEBUG(10,("[%u]: smblctx = %llu, tid = %u, pid = %s, ",
63 (unsigned long long)pls->context.smblctx,
64 (unsigned int)pls->context.tid,
65 server_id_str(talloc_tos(), &pls->context.pid) ));
67 DEBUG(10,("start = %.0f, size = %.0f, fnum = %llu, %s %s\n",
70 (unsigned long long)pls->fnum,
71 lock_type_name(pls->lock_type),
72 lock_flav_name(pls->lock_flav) ));
75 unsigned int brl_num_locks(const struct byte_range_lock *brl)
77 return brl->num_locks;
80 struct files_struct *brl_fsp(struct byte_range_lock *brl)
85 bool brl_have_read_oplocks(const struct byte_range_lock *brl)
87 return brl->have_read_oplocks;
90 void brl_set_have_read_oplocks(struct byte_range_lock *brl,
91 bool have_read_oplocks)
93 SMB_ASSERT(brl->record != NULL); /* otherwise we're readonly */
94 brl->have_read_oplocks = have_read_oplocks;
98 /****************************************************************************
99 See if two locking contexts are equal.
100 ****************************************************************************/
102 static bool brl_same_context(const struct lock_context *ctx1,
103 const struct lock_context *ctx2)
105 return (serverid_equal(&ctx1->pid, &ctx2->pid) &&
106 (ctx1->smblctx == ctx2->smblctx) &&
107 (ctx1->tid == ctx2->tid));
110 /****************************************************************************
111 See if lck1 and lck2 overlap.
112 ****************************************************************************/
114 static bool brl_overlap(const struct lock_struct *lck1,
115 const struct lock_struct *lck2)
117 /* XXX Remove for Win7 compatibility. */
118 /* this extra check is not redundant - it copes with locks
119 that go beyond the end of 64 bit file space */
120 if (lck1->size != 0 &&
121 lck1->start == lck2->start &&
122 lck1->size == lck2->size) {
126 if (lck1->start >= (lck2->start+lck2->size) ||
127 lck2->start >= (lck1->start+lck1->size)) {
133 /****************************************************************************
134 See if lock2 can be added when lock1 is in place.
135 ****************************************************************************/
137 static bool brl_conflict(const struct lock_struct *lck1,
138 const struct lock_struct *lck2)
140 /* Ignore PENDING locks. */
141 if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
144 /* Read locks never conflict. */
145 if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
149 /* A READ lock can stack on top of a WRITE lock if they have the same
151 if (lck1->lock_type == WRITE_LOCK && lck2->lock_type == READ_LOCK &&
152 brl_same_context(&lck1->context, &lck2->context) &&
153 lck1->fnum == lck2->fnum) {
157 return brl_overlap(lck1, lck2);
160 /****************************************************************************
161 See if lock2 can be added when lock1 is in place - when both locks are POSIX
162 flavour. POSIX locks ignore fnum - they only care about dev/ino which we
164 ****************************************************************************/
166 static bool brl_conflict_posix(const struct lock_struct *lck1,
167 const struct lock_struct *lck2)
169 #if defined(DEVELOPER)
170 SMB_ASSERT(lck1->lock_flav == POSIX_LOCK);
171 SMB_ASSERT(lck2->lock_flav == POSIX_LOCK);
174 /* Ignore PENDING locks. */
175 if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
178 /* Read locks never conflict. */
179 if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
183 /* Locks on the same context con't conflict. Ignore fnum. */
184 if (brl_same_context(&lck1->context, &lck2->context)) {
188 /* One is read, the other write, or the context is different,
190 return brl_overlap(lck1, lck2);
194 static bool brl_conflict1(const struct lock_struct *lck1,
195 const struct lock_struct *lck2)
197 if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
200 if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
204 if (brl_same_context(&lck1->context, &lck2->context) &&
205 lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) {
209 if (lck2->start == 0 && lck2->size == 0 && lck1->size != 0) {
213 if (lck1->start >= (lck2->start + lck2->size) ||
214 lck2->start >= (lck1->start + lck1->size)) {
222 /****************************************************************************
223 Check to see if this lock conflicts, but ignore our own locks on the
224 same fnum only. This is the read/write lock check code path.
225 This is never used in the POSIX lock case.
226 ****************************************************************************/
228 static bool brl_conflict_other(const struct lock_struct *lck1, const struct lock_struct *lck2)
230 if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
233 if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK)
236 /* POSIX flavour locks never conflict here - this is only called
237 in the read/write path. */
239 if (lck1->lock_flav == POSIX_LOCK && lck2->lock_flav == POSIX_LOCK)
243 * Incoming WRITE locks conflict with existing READ locks even
244 * if the context is the same. JRA. See LOCKTEST7 in smbtorture.
247 if (!(lck2->lock_type == WRITE_LOCK && lck1->lock_type == READ_LOCK)) {
248 if (brl_same_context(&lck1->context, &lck2->context) &&
249 lck1->fnum == lck2->fnum)
253 return brl_overlap(lck1, lck2);
256 /****************************************************************************
257 Check if an unlock overlaps a pending lock.
258 ****************************************************************************/
260 static bool brl_pending_overlap(const struct lock_struct *lock, const struct lock_struct *pend_lock)
262 if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start))
264 if ((lock->start >= pend_lock->start) && (lock->start <= pend_lock->start + pend_lock->size))
269 /****************************************************************************
270 Amazingly enough, w2k3 "remembers" whether the last lock failure on a fnum
271 is the same as this one and changes its error code. I wonder if any
272 app depends on this ?
273 ****************************************************************************/
275 static NTSTATUS brl_lock_failed(files_struct *fsp,
276 const struct lock_struct *lock,
279 if (lock->start >= 0xEF000000 && (lock->start >> 63) == 0) {
280 /* amazing the little things you learn with a test
281 suite. Locks beyond this offset (as a 64 bit
282 number!) always generate the conflict error code,
283 unless the top bit is set */
284 if (!blocking_lock) {
285 fsp->last_lock_failure = *lock;
287 return NT_STATUS_FILE_LOCK_CONFLICT;
290 if (serverid_equal(&lock->context.pid, &fsp->last_lock_failure.context.pid) &&
291 lock->context.tid == fsp->last_lock_failure.context.tid &&
292 lock->fnum == fsp->last_lock_failure.fnum &&
293 lock->start == fsp->last_lock_failure.start) {
294 return NT_STATUS_FILE_LOCK_CONFLICT;
297 if (!blocking_lock) {
298 fsp->last_lock_failure = *lock;
300 return NT_STATUS_LOCK_NOT_GRANTED;
303 /****************************************************************************
304 Open up the brlock.tdb database.
305 ****************************************************************************/
307 void brl_init(bool read_only)
315 tdb_flags = TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH;
317 if (!lp_clustering()) {
319 * We can't use the SEQNUM trick to cache brlock
320 * entries in the clustering case because ctdb seqnum
321 * propagation has a delay.
323 tdb_flags |= TDB_SEQNUM;
326 brlock_db = db_open(NULL, lock_path("brlock.tdb"),
327 lp_open_files_db_hash_size(), tdb_flags,
328 read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644,
329 DBWRAP_LOCK_ORDER_2);
331 DEBUG(0,("Failed to open byte range locking database %s\n",
332 lock_path("brlock.tdb")));
337 /****************************************************************************
338 Close down the brlock.tdb database.
339 ****************************************************************************/
341 void brl_shutdown(void)
343 TALLOC_FREE(brlock_db);
347 /****************************************************************************
348 Compare two locks for sorting.
349 ****************************************************************************/
351 static int lock_compare(const struct lock_struct *lck1,
352 const struct lock_struct *lck2)
354 if (lck1->start != lck2->start) {
355 return (lck1->start - lck2->start);
357 if (lck2->size != lck1->size) {
358 return ((int)lck1->size - (int)lck2->size);
364 /****************************************************************************
365 Lock a range of bytes - Windows lock semantics.
366 ****************************************************************************/
368 NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck,
369 struct lock_struct *plock, bool blocking_lock)
372 files_struct *fsp = br_lck->fsp;
373 struct lock_struct *locks = br_lck->lock_data;
376 SMB_ASSERT(plock->lock_type != UNLOCK_LOCK);
378 if ((plock->start + plock->size - 1 < plock->start) &&
380 return NT_STATUS_INVALID_LOCK_RANGE;
383 for (i=0; i < br_lck->num_locks; i++) {
384 /* Do any Windows or POSIX locks conflict ? */
385 if (brl_conflict(&locks[i], plock)) {
386 /* Remember who blocked us. */
387 plock->context.smblctx = locks[i].context.smblctx;
388 return brl_lock_failed(fsp,plock,blocking_lock);
391 if (plock->start == 0 && plock->size == 0 &&
392 locks[i].size == 0) {
398 if (!IS_PENDING_LOCK(plock->lock_type)) {
399 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WINDOWS_BRL);
402 /* We can get the Windows lock, now see if it needs to
403 be mapped into a lower level POSIX one, and if so can
406 if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(fsp->conn->params)) {
408 if (!set_posix_lock_windows_flavour(fsp,
417 /* We don't know who blocked us. */
418 plock->context.smblctx = 0xFFFFFFFFFFFFFFFFLL;
420 if (errno_ret == EACCES || errno_ret == EAGAIN) {
421 status = NT_STATUS_FILE_LOCK_CONFLICT;
424 status = map_nt_error_from_unix(errno);
430 /* no conflicts - add it to the list of locks */
431 locks = talloc_realloc(br_lck, locks, struct lock_struct,
432 (br_lck->num_locks + 1));
434 status = NT_STATUS_NO_MEMORY;
438 memcpy(&locks[br_lck->num_locks], plock, sizeof(struct lock_struct));
439 br_lck->num_locks += 1;
440 br_lck->lock_data = locks;
441 br_lck->modified = True;
445 if (!IS_PENDING_LOCK(plock->lock_type)) {
446 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WINDOWS_BRL);
451 /****************************************************************************
452 Cope with POSIX range splits and merges.
453 ****************************************************************************/
455 static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, /* Output array. */
456 struct lock_struct *ex, /* existing lock. */
457 struct lock_struct *plock) /* proposed lock. */
459 bool lock_types_differ = (ex->lock_type != plock->lock_type);
461 /* We can't merge non-conflicting locks on different context - ignore fnum. */
463 if (!brl_same_context(&ex->context, &plock->context)) {
465 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
469 /* We now know we have the same context. */
471 /* Did we overlap ? */
473 /*********************************************
484 **********************************************/
486 if ( (ex->start > (plock->start + plock->size)) ||
487 (plock->start > (ex->start + ex->size))) {
489 /* No overlap with this lock - copy existing. */
491 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
495 /*********************************************
496 +---------------------------+
498 +---------------------------+
499 +---------------------------+
500 | plock | -> replace with plock.
501 +---------------------------+
506 +---------------------------+
507 | plock | -> replace with plock.
508 +---------------------------+
510 **********************************************/
512 if ( (ex->start >= plock->start) &&
513 (ex->start + ex->size <= plock->start + plock->size) ) {
515 /* Replace - discard existing lock. */
520 /*********************************************
530 +---------------+-------+
531 | plock | ex | - different lock types.
532 +---------------+-------+
534 +-----------------------+
535 | plock | - same lock type.
536 +-----------------------+
537 **********************************************/
539 if (plock->start + plock->size == ex->start) {
541 /* If the lock types are the same, we merge, if different, we
542 add the remainder of the old lock. */
544 if (lock_types_differ) {
546 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
549 /* Merge - adjust incoming lock as we may have more
550 * merging to come. */
551 plock->size += ex->size;
556 /*********************************************
565 +-------+---------------+
566 | ex | plock | - different lock types
567 +-------+---------------+
570 +-----------------------+
571 | plock | - same lock type.
572 +-----------------------+
574 **********************************************/
576 if (ex->start + ex->size == plock->start) {
578 /* If the lock types are the same, we merge, if different, we
579 add the existing lock. */
581 if (lock_types_differ) {
582 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
585 /* Merge - adjust incoming lock as we may have more
586 * merging to come. */
587 plock->start = ex->start;
588 plock->size += ex->size;
593 /*********************************************
595 +-----------------------+
597 +-----------------------+
610 +---------------+-------+
611 | plock | ex | - different lock types.
612 +---------------+-------+
614 +-----------------------+
615 | plock | - same lock type.
616 +-----------------------+
617 **********************************************/
619 if ( (ex->start >= plock->start) &&
620 (ex->start <= plock->start + plock->size) &&
621 (ex->start + ex->size > plock->start + plock->size) ) {
623 /* If the lock types are the same, we merge, if different, we
624 add the remainder of the old lock. */
626 if (lock_types_differ) {
627 /* Add remaining existing. */
628 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
629 /* Adjust existing start and size. */
630 lck_arr[0].start = plock->start + plock->size;
631 lck_arr[0].size = (ex->start + ex->size) - (plock->start + plock->size);
634 /* Merge - adjust incoming lock as we may have more
635 * merging to come. */
636 plock->size += (ex->start + ex->size) - (plock->start + plock->size);
641 /*********************************************
643 +-----------------------+
645 +-----------------------+
658 +-------+---------------+
659 | ex | plock | - different lock types
660 +-------+---------------+
663 +-----------------------+
664 | plock | - same lock type.
665 +-----------------------+
667 **********************************************/
669 if ( (ex->start < plock->start) &&
670 (ex->start + ex->size >= plock->start) &&
671 (ex->start + ex->size <= plock->start + plock->size) ) {
673 /* If the lock types are the same, we merge, if different, we
674 add the truncated old lock. */
676 if (lock_types_differ) {
677 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
678 /* Adjust existing size. */
679 lck_arr[0].size = plock->start - ex->start;
682 /* Merge - adjust incoming lock as we may have more
683 * merging to come. MUST ADJUST plock SIZE FIRST ! */
684 plock->size += (plock->start - ex->start);
685 plock->start = ex->start;
690 /*********************************************
692 +---------------------------+
694 +---------------------------+
699 +-------+---------+---------+
700 | ex | plock | ex | - different lock types.
701 +-------+---------+---------+
703 +---------------------------+
704 | plock | - same lock type.
705 +---------------------------+
706 **********************************************/
708 if ( (ex->start < plock->start) && (ex->start + ex->size > plock->start + plock->size) ) {
710 if (lock_types_differ) {
712 /* We have to split ex into two locks here. */
714 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
715 memcpy(&lck_arr[1], ex, sizeof(struct lock_struct));
717 /* Adjust first existing size. */
718 lck_arr[0].size = plock->start - ex->start;
720 /* Adjust second existing start and size. */
721 lck_arr[1].start = plock->start + plock->size;
722 lck_arr[1].size = (ex->start + ex->size) - (plock->start + plock->size);
725 /* Just eat the existing locks, merge them into plock. */
726 plock->start = ex->start;
727 plock->size = ex->size;
732 /* Never get here. */
733 smb_panic("brlock_posix_split_merge");
736 /* Keep some compilers happy. */
740 /****************************************************************************
741 Lock a range of bytes - POSIX lock semantics.
742 We must cope with range splits and merges.
743 ****************************************************************************/
745 static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx,
746 struct byte_range_lock *br_lck,
747 struct lock_struct *plock)
749 unsigned int i, count, posix_count;
750 struct lock_struct *locks = br_lck->lock_data;
751 struct lock_struct *tp;
752 bool signal_pending_read = False;
753 bool break_oplocks = false;
756 /* No zero-zero locks for POSIX. */
757 if (plock->start == 0 && plock->size == 0) {
758 return NT_STATUS_INVALID_PARAMETER;
761 /* Don't allow 64-bit lock wrap. */
762 if (plock->start + plock->size - 1 < plock->start) {
763 return NT_STATUS_INVALID_PARAMETER;
766 /* The worst case scenario here is we have to split an
767 existing POSIX lock range into two, and add our lock,
768 so we need at most 2 more entries. */
770 tp = talloc_array(br_lck, struct lock_struct, br_lck->num_locks + 2);
772 return NT_STATUS_NO_MEMORY;
775 count = posix_count = 0;
777 for (i=0; i < br_lck->num_locks; i++) {
778 struct lock_struct *curr_lock = &locks[i];
780 /* If we have a pending read lock, a lock downgrade should
781 trigger a lock re-evaluation. */
782 if (curr_lock->lock_type == PENDING_READ_LOCK &&
783 brl_pending_overlap(plock, curr_lock)) {
784 signal_pending_read = True;
787 if (curr_lock->lock_flav == WINDOWS_LOCK) {
788 /* Do any Windows flavour locks conflict ? */
789 if (brl_conflict(curr_lock, plock)) {
790 /* No games with error messages. */
792 /* Remember who blocked us. */
793 plock->context.smblctx = curr_lock->context.smblctx;
794 return NT_STATUS_FILE_LOCK_CONFLICT;
796 /* Just copy the Windows lock into the new array. */
797 memcpy(&tp[count], curr_lock, sizeof(struct lock_struct));
800 unsigned int tmp_count = 0;
802 /* POSIX conflict semantics are different. */
803 if (brl_conflict_posix(curr_lock, plock)) {
804 /* Can't block ourselves with POSIX locks. */
805 /* No games with error messages. */
807 /* Remember who blocked us. */
808 plock->context.smblctx = curr_lock->context.smblctx;
809 return NT_STATUS_FILE_LOCK_CONFLICT;
812 /* Work out overlaps. */
813 tmp_count += brlock_posix_split_merge(&tp[count], curr_lock, plock);
814 posix_count += tmp_count;
820 * Break oplocks while we hold a brl. Since lock() and unlock() calls
821 * are not symetric with POSIX semantics, we cannot guarantee our
822 * contend_level2_oplocks_begin/end calls will be acquired and
823 * released one-for-one as with Windows semantics. Therefore we only
824 * call contend_level2_oplocks_begin if this is the first POSIX brl on
827 break_oplocks = (!IS_PENDING_LOCK(plock->lock_type) &&
830 contend_level2_oplocks_begin(br_lck->fsp,
831 LEVEL2_CONTEND_POSIX_BRL);
834 /* Try and add the lock in order, sorted by lock start. */
835 for (i=0; i < count; i++) {
836 struct lock_struct *curr_lock = &tp[i];
838 if (curr_lock->start <= plock->start) {
844 memmove(&tp[i+1], &tp[i],
845 (count - i)*sizeof(struct lock_struct));
847 memcpy(&tp[i], plock, sizeof(struct lock_struct));
850 /* We can get the POSIX lock, now see if it needs to
851 be mapped into a lower level POSIX one, and if so can
854 if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(br_lck->fsp->conn->params)) {
857 /* The lower layer just needs to attempt to
858 get the system POSIX lock. We've weeded out
859 any conflicts above. */
861 if (!set_posix_lock_posix_flavour(br_lck->fsp,
867 /* We don't know who blocked us. */
868 plock->context.smblctx = 0xFFFFFFFFFFFFFFFFLL;
870 if (errno_ret == EACCES || errno_ret == EAGAIN) {
872 status = NT_STATUS_FILE_LOCK_CONFLICT;
876 status = map_nt_error_from_unix(errno);
882 /* If we didn't use all the allocated size,
883 * Realloc so we don't leak entries per lock call. */
884 if (count < br_lck->num_locks + 2) {
885 tp = talloc_realloc(br_lck, tp, struct lock_struct, count);
887 status = NT_STATUS_NO_MEMORY;
892 br_lck->num_locks = count;
893 TALLOC_FREE(br_lck->lock_data);
894 br_lck->lock_data = tp;
896 br_lck->modified = True;
898 /* A successful downgrade from write to read lock can trigger a lock
899 re-evalutation where waiting readers can now proceed. */
901 if (signal_pending_read) {
902 /* Send unlock messages to any pending read waiters that overlap. */
903 for (i=0; i < br_lck->num_locks; i++) {
904 struct lock_struct *pend_lock = &locks[i];
906 /* Ignore non-pending locks. */
907 if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
911 if (pend_lock->lock_type == PENDING_READ_LOCK &&
912 brl_pending_overlap(plock, pend_lock)) {
913 DEBUG(10,("brl_lock_posix: sending unlock message to pid %s\n",
914 procid_str_static(&pend_lock->context.pid )));
916 messaging_send(msg_ctx, pend_lock->context.pid,
917 MSG_SMB_UNLOCK, &data_blob_null);
925 contend_level2_oplocks_end(br_lck->fsp,
926 LEVEL2_CONTEND_POSIX_BRL);
931 NTSTATUS smb_vfs_call_brl_lock_windows(struct vfs_handle_struct *handle,
932 struct byte_range_lock *br_lck,
933 struct lock_struct *plock,
935 struct blocking_lock_record *blr)
937 VFS_FIND(brl_lock_windows);
938 return handle->fns->brl_lock_windows_fn(handle, br_lck, plock,
942 /****************************************************************************
943 Lock a range of bytes.
944 ****************************************************************************/
946 NTSTATUS brl_lock(struct messaging_context *msg_ctx,
947 struct byte_range_lock *br_lck,
949 struct server_id pid,
952 enum brl_type lock_type,
953 enum brl_flavour lock_flav,
956 struct blocking_lock_record *blr)
959 struct lock_struct lock;
962 if (start == 0 && size == 0) {
963 DEBUG(0,("client sent 0/0 lock - please report this\n"));
968 /* Quieten valgrind on test. */
972 lock.context.smblctx = smblctx;
973 lock.context.pid = pid;
974 lock.context.tid = br_lck->fsp->conn->cnum;
977 lock.fnum = br_lck->fsp->fnum;
978 lock.lock_type = lock_type;
979 lock.lock_flav = lock_flav;
981 if (lock_flav == WINDOWS_LOCK) {
982 ret = SMB_VFS_BRL_LOCK_WINDOWS(br_lck->fsp->conn, br_lck,
983 &lock, blocking_lock, blr);
985 ret = brl_lock_posix(msg_ctx, br_lck, &lock);
989 /* sort the lock list */
990 TYPESAFE_QSORT(br_lck->lock_data, (size_t)br_lck->num_locks, lock_compare);
993 /* If we're returning an error, return who blocked us. */
994 if (!NT_STATUS_IS_OK(ret) && psmblctx) {
995 *psmblctx = lock.context.smblctx;
1000 /****************************************************************************
1001 Unlock a range of bytes - Windows semantics.
1002 ****************************************************************************/
1004 bool brl_unlock_windows_default(struct messaging_context *msg_ctx,
1005 struct byte_range_lock *br_lck,
1006 const struct lock_struct *plock)
1009 struct lock_struct *locks = br_lck->lock_data;
1010 enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */
1012 SMB_ASSERT(plock->lock_type == UNLOCK_LOCK);
1015 /* Delete write locks by preference... The lock list
1016 is sorted in the zero zero case. */
1018 for (i = 0; i < br_lck->num_locks; i++) {
1019 struct lock_struct *lock = &locks[i];
1021 if (lock->lock_type == WRITE_LOCK &&
1022 brl_same_context(&lock->context, &plock->context) &&
1023 lock->fnum == plock->fnum &&
1024 lock->lock_flav == WINDOWS_LOCK &&
1025 lock->start == plock->start &&
1026 lock->size == plock->size) {
1028 /* found it - delete it */
1029 deleted_lock_type = lock->lock_type;
1034 if (i != br_lck->num_locks) {
1035 /* We found it - don't search again. */
1036 goto unlock_continue;
1040 for (i = 0; i < br_lck->num_locks; i++) {
1041 struct lock_struct *lock = &locks[i];
1043 if (IS_PENDING_LOCK(lock->lock_type)) {
1047 /* Only remove our own locks that match in start, size, and flavour. */
1048 if (brl_same_context(&lock->context, &plock->context) &&
1049 lock->fnum == plock->fnum &&
1050 lock->lock_flav == WINDOWS_LOCK &&
1051 lock->start == plock->start &&
1052 lock->size == plock->size ) {
1053 deleted_lock_type = lock->lock_type;
1058 if (i == br_lck->num_locks) {
1059 /* we didn't find it */
1067 /* Actually delete the lock. */
1068 if (i < br_lck->num_locks - 1) {
1069 memmove(&locks[i], &locks[i+1],
1070 sizeof(*locks)*((br_lck->num_locks-1) - i));
1073 br_lck->num_locks -= 1;
1074 br_lck->modified = True;
1076 /* Unlock the underlying POSIX regions. */
1077 if(lp_posix_locking(br_lck->fsp->conn->params)) {
1078 release_posix_lock_windows_flavour(br_lck->fsp,
1087 /* Send unlock messages to any pending waiters that overlap. */
1088 for (j=0; j < br_lck->num_locks; j++) {
1089 struct lock_struct *pend_lock = &locks[j];
1091 /* Ignore non-pending locks. */
1092 if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
1096 /* We could send specific lock info here... */
1097 if (brl_pending_overlap(plock, pend_lock)) {
1098 DEBUG(10,("brl_unlock: sending unlock message to pid %s\n",
1099 procid_str_static(&pend_lock->context.pid )));
1101 messaging_send(msg_ctx, pend_lock->context.pid,
1102 MSG_SMB_UNLOCK, &data_blob_null);
1106 contend_level2_oplocks_end(br_lck->fsp, LEVEL2_CONTEND_WINDOWS_BRL);
1110 /****************************************************************************
1111 Unlock a range of bytes - POSIX semantics.
1112 ****************************************************************************/
1114 static bool brl_unlock_posix(struct messaging_context *msg_ctx,
1115 struct byte_range_lock *br_lck,
1116 struct lock_struct *plock)
1118 unsigned int i, j, count;
1119 struct lock_struct *tp;
1120 struct lock_struct *locks = br_lck->lock_data;
1121 bool overlap_found = False;
1123 /* No zero-zero locks for POSIX. */
1124 if (plock->start == 0 && plock->size == 0) {
1128 /* Don't allow 64-bit lock wrap. */
1129 if (plock->start + plock->size < plock->start ||
1130 plock->start + plock->size < plock->size) {
1131 DEBUG(10,("brl_unlock_posix: lock wrap\n"));
1135 /* The worst case scenario here is we have to split an
1136 existing POSIX lock range into two, so we need at most
1139 tp = talloc_array(br_lck, struct lock_struct, br_lck->num_locks + 1);
1141 DEBUG(10,("brl_unlock_posix: malloc fail\n"));
1146 for (i = 0; i < br_lck->num_locks; i++) {
1147 struct lock_struct *lock = &locks[i];
1148 unsigned int tmp_count;
1150 /* Only remove our own locks - ignore fnum. */
1151 if (IS_PENDING_LOCK(lock->lock_type) ||
1152 !brl_same_context(&lock->context, &plock->context)) {
1153 memcpy(&tp[count], lock, sizeof(struct lock_struct));
1158 if (lock->lock_flav == WINDOWS_LOCK) {
1159 /* Do any Windows flavour locks conflict ? */
1160 if (brl_conflict(lock, plock)) {
1164 /* Just copy the Windows lock into the new array. */
1165 memcpy(&tp[count], lock, sizeof(struct lock_struct));
1170 /* Work out overlaps. */
1171 tmp_count = brlock_posix_split_merge(&tp[count], lock, plock);
1173 if (tmp_count == 0) {
1174 /* plock overlapped the existing lock completely,
1175 or replaced it. Don't copy the existing lock. */
1176 overlap_found = true;
1177 } else if (tmp_count == 1) {
1178 /* Either no overlap, (simple copy of existing lock) or
1179 * an overlap of an existing lock. */
1180 /* If the lock changed size, we had an overlap. */
1181 if (tp[count].size != lock->size) {
1182 overlap_found = true;
1185 } else if (tmp_count == 2) {
1186 /* We split a lock range in two. */
1187 overlap_found = true;
1190 /* Optimisation... */
1191 /* We know we're finished here as we can't overlap any
1192 more POSIX locks. Copy the rest of the lock array. */
1194 if (i < br_lck->num_locks - 1) {
1195 memcpy(&tp[count], &locks[i+1],
1196 sizeof(*locks)*((br_lck->num_locks-1) - i));
1197 count += ((br_lck->num_locks-1) - i);
1204 if (!overlap_found) {
1205 /* Just ignore - no change. */
1207 DEBUG(10,("brl_unlock_posix: No overlap - unlocked.\n"));
1211 /* Unlock any POSIX regions. */
1212 if(lp_posix_locking(br_lck->fsp->conn->params)) {
1213 release_posix_lock_posix_flavour(br_lck->fsp,
1221 /* Realloc so we don't leak entries per unlock call. */
1223 tp = talloc_realloc(br_lck, tp, struct lock_struct, count);
1225 DEBUG(10,("brl_unlock_posix: realloc fail\n"));
1229 /* We deleted the last lock. */
1234 contend_level2_oplocks_end(br_lck->fsp,
1235 LEVEL2_CONTEND_POSIX_BRL);
1237 br_lck->num_locks = count;
1238 TALLOC_FREE(br_lck->lock_data);
1240 br_lck->lock_data = tp;
1241 br_lck->modified = True;
1243 /* Send unlock messages to any pending waiters that overlap. */
1245 for (j=0; j < br_lck->num_locks; j++) {
1246 struct lock_struct *pend_lock = &locks[j];
1248 /* Ignore non-pending locks. */
1249 if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
1253 /* We could send specific lock info here... */
1254 if (brl_pending_overlap(plock, pend_lock)) {
1255 DEBUG(10,("brl_unlock: sending unlock message to pid %s\n",
1256 procid_str_static(&pend_lock->context.pid )));
1258 messaging_send(msg_ctx, pend_lock->context.pid,
1259 MSG_SMB_UNLOCK, &data_blob_null);
1266 bool smb_vfs_call_brl_unlock_windows(struct vfs_handle_struct *handle,
1267 struct messaging_context *msg_ctx,
1268 struct byte_range_lock *br_lck,
1269 const struct lock_struct *plock)
1271 VFS_FIND(brl_unlock_windows);
1272 return handle->fns->brl_unlock_windows_fn(handle, msg_ctx, br_lck,
1276 /****************************************************************************
1277 Unlock a range of bytes.
1278 ****************************************************************************/
1280 bool brl_unlock(struct messaging_context *msg_ctx,
1281 struct byte_range_lock *br_lck,
1283 struct server_id pid,
1286 enum brl_flavour lock_flav)
1288 struct lock_struct lock;
1290 lock.context.smblctx = smblctx;
1291 lock.context.pid = pid;
1292 lock.context.tid = br_lck->fsp->conn->cnum;
1295 lock.fnum = br_lck->fsp->fnum;
1296 lock.lock_type = UNLOCK_LOCK;
1297 lock.lock_flav = lock_flav;
1299 if (lock_flav == WINDOWS_LOCK) {
1300 return SMB_VFS_BRL_UNLOCK_WINDOWS(br_lck->fsp->conn, msg_ctx,
1303 return brl_unlock_posix(msg_ctx, br_lck, &lock);
1307 /****************************************************************************
1308 Test if we could add a lock if we wanted to.
1309 Returns True if the region required is currently unlocked, False if locked.
1310 ****************************************************************************/
1312 bool brl_locktest(struct byte_range_lock *br_lck,
1314 struct server_id pid,
1317 enum brl_type lock_type,
1318 enum brl_flavour lock_flav)
1322 struct lock_struct lock;
1323 const struct lock_struct *locks = br_lck->lock_data;
1324 files_struct *fsp = br_lck->fsp;
1326 lock.context.smblctx = smblctx;
1327 lock.context.pid = pid;
1328 lock.context.tid = br_lck->fsp->conn->cnum;
1331 lock.fnum = fsp->fnum;
1332 lock.lock_type = lock_type;
1333 lock.lock_flav = lock_flav;
1335 /* Make sure existing locks don't conflict */
1336 for (i=0; i < br_lck->num_locks; i++) {
1338 * Our own locks don't conflict.
1340 if (brl_conflict_other(&locks[i], &lock)) {
1346 * There is no lock held by an SMB daemon, check to
1347 * see if there is a POSIX lock from a UNIX or NFS process.
1348 * This only conflicts with Windows locks, not POSIX locks.
1351 if(lp_posix_locking(fsp->conn->params) && (lock_flav == WINDOWS_LOCK)) {
1352 ret = is_posix_locked(fsp, &start, &size, &lock_type, WINDOWS_LOCK);
1354 DEBUG(10,("brl_locktest: posix start=%.0f len=%.0f %s for %s file %s\n",
1355 (double)start, (double)size, ret ? "locked" : "unlocked",
1356 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
1358 /* We need to return the inverse of is_posix_locked. */
1362 /* no conflicts - we could have added it */
1366 /****************************************************************************
1367 Query for existing locks.
1368 ****************************************************************************/
1370 NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
1372 struct server_id pid,
1375 enum brl_type *plock_type,
1376 enum brl_flavour lock_flav)
1379 struct lock_struct lock;
1380 const struct lock_struct *locks = br_lck->lock_data;
1381 files_struct *fsp = br_lck->fsp;
1383 lock.context.smblctx = *psmblctx;
1384 lock.context.pid = pid;
1385 lock.context.tid = br_lck->fsp->conn->cnum;
1386 lock.start = *pstart;
1388 lock.fnum = fsp->fnum;
1389 lock.lock_type = *plock_type;
1390 lock.lock_flav = lock_flav;
1392 /* Make sure existing locks don't conflict */
1393 for (i=0; i < br_lck->num_locks; i++) {
1394 const struct lock_struct *exlock = &locks[i];
1395 bool conflict = False;
1397 if (exlock->lock_flav == WINDOWS_LOCK) {
1398 conflict = brl_conflict(exlock, &lock);
1400 conflict = brl_conflict_posix(exlock, &lock);
1404 *psmblctx = exlock->context.smblctx;
1405 *pstart = exlock->start;
1406 *psize = exlock->size;
1407 *plock_type = exlock->lock_type;
1408 return NT_STATUS_LOCK_NOT_GRANTED;
1413 * There is no lock held by an SMB daemon, check to
1414 * see if there is a POSIX lock from a UNIX or NFS process.
1417 if(lp_posix_locking(fsp->conn->params)) {
1418 bool ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK);
1420 DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for %s file %s\n",
1421 (double)*pstart, (double)*psize, ret ? "locked" : "unlocked",
1422 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
1425 /* Hmmm. No clue what to set smblctx to - use -1. */
1426 *psmblctx = 0xFFFFFFFFFFFFFFFFLL;
1427 return NT_STATUS_LOCK_NOT_GRANTED;
1431 return NT_STATUS_OK;
1435 bool smb_vfs_call_brl_cancel_windows(struct vfs_handle_struct *handle,
1436 struct byte_range_lock *br_lck,
1437 struct lock_struct *plock,
1438 struct blocking_lock_record *blr)
1440 VFS_FIND(brl_cancel_windows);
1441 return handle->fns->brl_cancel_windows_fn(handle, br_lck, plock, blr);
1444 /****************************************************************************
1445 Remove a particular pending lock.
1446 ****************************************************************************/
1447 bool brl_lock_cancel(struct byte_range_lock *br_lck,
1449 struct server_id pid,
1452 enum brl_flavour lock_flav,
1453 struct blocking_lock_record *blr)
1456 struct lock_struct lock;
1458 lock.context.smblctx = smblctx;
1459 lock.context.pid = pid;
1460 lock.context.tid = br_lck->fsp->conn->cnum;
1463 lock.fnum = br_lck->fsp->fnum;
1464 lock.lock_flav = lock_flav;
1465 /* lock.lock_type doesn't matter */
1467 if (lock_flav == WINDOWS_LOCK) {
1468 ret = SMB_VFS_BRL_CANCEL_WINDOWS(br_lck->fsp->conn, br_lck,
1471 ret = brl_lock_cancel_default(br_lck, &lock);
1477 bool brl_lock_cancel_default(struct byte_range_lock *br_lck,
1478 struct lock_struct *plock)
1481 struct lock_struct *locks = br_lck->lock_data;
1485 for (i = 0; i < br_lck->num_locks; i++) {
1486 struct lock_struct *lock = &locks[i];
1488 /* For pending locks we *always* care about the fnum. */
1489 if (brl_same_context(&lock->context, &plock->context) &&
1490 lock->fnum == plock->fnum &&
1491 IS_PENDING_LOCK(lock->lock_type) &&
1492 lock->lock_flav == plock->lock_flav &&
1493 lock->start == plock->start &&
1494 lock->size == plock->size) {
1499 if (i == br_lck->num_locks) {
1500 /* Didn't find it. */
1504 if (i < br_lck->num_locks - 1) {
1505 /* Found this particular pending lock - delete it */
1506 memmove(&locks[i], &locks[i+1],
1507 sizeof(*locks)*((br_lck->num_locks-1) - i));
1510 br_lck->num_locks -= 1;
1511 br_lck->modified = True;
1515 /****************************************************************************
1516 Remove any locks associated with a open file.
1517 We return True if this process owns any other Windows locks on this
1518 fd and so we should not immediately close the fd.
1519 ****************************************************************************/
1521 void brl_close_fnum(struct messaging_context *msg_ctx,
1522 struct byte_range_lock *br_lck)
1524 files_struct *fsp = br_lck->fsp;
1525 uint32_t tid = fsp->conn->cnum;
1526 uint64_t fnum = fsp->fnum;
1528 struct lock_struct *locks = br_lck->lock_data;
1529 struct server_id pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
1530 struct lock_struct *locks_copy;
1531 unsigned int num_locks_copy;
1533 /* Copy the current lock array. */
1534 if (br_lck->num_locks) {
1535 locks_copy = (struct lock_struct *)talloc_memdup(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct));
1537 smb_panic("brl_close_fnum: talloc failed");
1543 num_locks_copy = br_lck->num_locks;
1545 for (i=0; i < num_locks_copy; i++) {
1546 struct lock_struct *lock = &locks_copy[i];
1548 if (lock->context.tid == tid && serverid_equal(&lock->context.pid, &pid) &&
1549 (lock->fnum == fnum)) {
1552 lock->context.smblctx,
1561 bool brl_mark_disconnected(struct files_struct *fsp)
1563 uint32_t tid = fsp->conn->cnum;
1564 uint64_t smblctx = fsp->op->global->open_persistent_id;
1565 uint64_t fnum = fsp->fnum;
1567 struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
1568 struct byte_range_lock *br_lck = NULL;
1570 if (!fsp->op->global->durable) {
1574 if (fsp->current_lock_count == 0) {
1578 br_lck = brl_get_locks(talloc_tos(), fsp);
1579 if (br_lck == NULL) {
1583 for (i=0; i < br_lck->num_locks; i++) {
1584 struct lock_struct *lock = &br_lck->lock_data[i];
1587 * as this is a durable handle, we only expect locks
1588 * of the current file handle!
1591 if (lock->context.smblctx != smblctx) {
1592 TALLOC_FREE(br_lck);
1596 if (lock->context.tid != tid) {
1597 TALLOC_FREE(br_lck);
1601 if (!serverid_equal(&lock->context.pid, &self)) {
1602 TALLOC_FREE(br_lck);
1606 if (lock->fnum != fnum) {
1607 TALLOC_FREE(br_lck);
1611 server_id_set_disconnected(&lock->context.pid);
1612 lock->context.tid = TID_FIELD_INVALID;
1613 lock->fnum = FNUM_FIELD_INVALID;
1616 br_lck->modified = true;
1617 TALLOC_FREE(br_lck);
1621 bool brl_reconnect_disconnected(struct files_struct *fsp)
1623 uint32_t tid = fsp->conn->cnum;
1624 uint64_t smblctx = fsp->op->global->open_persistent_id;
1625 uint64_t fnum = fsp->fnum;
1627 struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
1628 struct byte_range_lock *br_lck = NULL;
1630 if (!fsp->op->global->durable) {
1635 * When reconnecting, we do not want to validate the brlock entries
1636 * and thereby remove our own (disconnected) entries but reactivate
1639 fsp->lockdb_clean = true;
1641 br_lck = brl_get_locks(talloc_tos(), fsp);
1642 if (br_lck == NULL) {
1646 if (br_lck->num_locks == 0) {
1647 TALLOC_FREE(br_lck);
1651 for (i=0; i < br_lck->num_locks; i++) {
1652 struct lock_struct *lock = &br_lck->lock_data[i];
1655 * as this is a durable handle we only expect locks
1656 * of the current file handle!
1659 if (lock->context.smblctx != smblctx) {
1660 TALLOC_FREE(br_lck);
1664 if (lock->context.tid != TID_FIELD_INVALID) {
1665 TALLOC_FREE(br_lck);
1669 if (!server_id_is_disconnected(&lock->context.pid)) {
1670 TALLOC_FREE(br_lck);
1674 if (lock->fnum != FNUM_FIELD_INVALID) {
1675 TALLOC_FREE(br_lck);
1679 lock->context.pid = self;
1680 lock->context.tid = tid;
1684 fsp->current_lock_count = br_lck->num_locks;
1685 br_lck->modified = true;
1686 TALLOC_FREE(br_lck);
1690 /****************************************************************************
1691 Ensure this set of lock entries is valid.
1692 ****************************************************************************/
1693 static bool validate_lock_entries(TALLOC_CTX *mem_ctx,
1694 unsigned int *pnum_entries, struct lock_struct **pplocks,
1695 bool keep_disconnected)
1698 unsigned int num_valid_entries = 0;
1699 struct lock_struct *locks = *pplocks;
1700 TALLOC_CTX *frame = talloc_stackframe();
1701 struct server_id *ids;
1704 ids = talloc_array(frame, struct server_id, *pnum_entries);
1706 DEBUG(0, ("validate_lock_entries: "
1707 "talloc_array(struct server_id, %u) failed\n",
1713 exists = talloc_array(frame, bool, *pnum_entries);
1714 if (exists == NULL) {
1715 DEBUG(0, ("validate_lock_entries: "
1716 "talloc_array(bool, %u) failed\n",
1722 for (i = 0; i < *pnum_entries; i++) {
1723 ids[i] = locks[i].context.pid;
1726 if (!serverids_exist(ids, *pnum_entries, exists)) {
1727 DEBUG(3, ("validate_lock_entries: serverids_exists failed\n"));
1732 for (i = 0; i < *pnum_entries; i++) {
1734 num_valid_entries++;
1738 if (keep_disconnected &&
1739 server_id_is_disconnected(&ids[i]))
1741 num_valid_entries++;
1745 /* This process no longer exists - mark this
1746 entry as invalid by zeroing it. */
1747 ZERO_STRUCTP(&locks[i]);
1751 if (num_valid_entries != *pnum_entries) {
1752 struct lock_struct *new_lock_data = NULL;
1754 if (num_valid_entries) {
1755 new_lock_data = talloc_array(
1756 mem_ctx, struct lock_struct,
1758 if (!new_lock_data) {
1759 DEBUG(3, ("malloc fail\n"));
1763 num_valid_entries = 0;
1764 for (i = 0; i < *pnum_entries; i++) {
1765 struct lock_struct *lock_data = &locks[i];
1766 if (lock_data->context.smblctx &&
1767 lock_data->context.tid) {
1768 /* Valid (nonzero) entry - copy it. */
1769 memcpy(&new_lock_data[num_valid_entries],
1770 lock_data, sizeof(struct lock_struct));
1771 num_valid_entries++;
1776 TALLOC_FREE(*pplocks);
1777 *pplocks = new_lock_data;
1778 *pnum_entries = num_valid_entries;
1784 struct brl_forall_cb {
1785 void (*fn)(struct file_id id, struct server_id pid,
1786 enum brl_type lock_type,
1787 enum brl_flavour lock_flav,
1788 br_off start, br_off size,
1789 void *private_data);
1793 /****************************************************************************
1794 Traverse the whole database with this function, calling traverse_callback
1796 ****************************************************************************/
1798 static int brl_traverse_fn(struct db_record *rec, void *state)
1800 struct brl_forall_cb *cb = (struct brl_forall_cb *)state;
1801 struct lock_struct *locks;
1802 struct file_id *key;
1804 unsigned int num_locks = 0;
1805 unsigned int orig_num_locks = 0;
1809 dbkey = dbwrap_record_get_key(rec);
1810 value = dbwrap_record_get_value(rec);
1812 /* In a traverse function we must make a copy of
1813 dbuf before modifying it. */
1815 locks = (struct lock_struct *)talloc_memdup(
1816 talloc_tos(), value.dptr, value.dsize);
1818 return -1; /* Terminate traversal. */
1821 key = (struct file_id *)dbkey.dptr;
1822 orig_num_locks = num_locks = value.dsize/sizeof(*locks);
1824 /* Ensure the lock db is clean of entries from invalid processes. */
1826 if (!validate_lock_entries(talloc_tos(), &num_locks, &locks, true)) {
1828 return -1; /* Terminate traversal */
1831 if (orig_num_locks != num_locks) {
1834 data.dptr = (uint8_t *)locks;
1835 data.dsize = num_locks*sizeof(struct lock_struct);
1836 dbwrap_record_store(rec, data, TDB_REPLACE);
1838 dbwrap_record_delete(rec);
1843 for ( i=0; i<num_locks; i++) {
1845 locks[i].context.pid,
1858 /*******************************************************************
1859 Call the specified function on each lock in the database.
1860 ********************************************************************/
1862 int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
1863 enum brl_type lock_type,
1864 enum brl_flavour lock_flav,
1865 br_off start, br_off size,
1866 void *private_data),
1869 struct brl_forall_cb cb;
1877 cb.private_data = private_data;
1878 status = dbwrap_traverse(brlock_db, brl_traverse_fn, &cb, &count);
1880 if (!NT_STATUS_IS_OK(status)) {
1887 /*******************************************************************
1888 Store a potentially modified set of byte range lock data back into
1891 ********************************************************************/
1893 static void byte_range_lock_flush(struct byte_range_lock *br_lck)
1896 if (!br_lck->modified) {
1900 data_len = br_lck->num_locks * sizeof(struct lock_struct);
1902 if (br_lck->have_read_oplocks) {
1906 if (data_len == 0) {
1907 /* No locks - delete this entry. */
1908 NTSTATUS status = dbwrap_record_delete(br_lck->record);
1909 if (!NT_STATUS_IS_OK(status)) {
1910 DEBUG(0, ("delete_rec returned %s\n",
1911 nt_errstr(status)));
1912 smb_panic("Could not delete byte range lock entry");
1918 data.dsize = data_len;
1919 data.dptr = talloc_array(talloc_tos(), uint8_t, data_len);
1920 SMB_ASSERT(data.dptr != NULL);
1922 memcpy(data.dptr, br_lck->lock_data,
1923 br_lck->num_locks * sizeof(struct lock_struct));
1925 if (br_lck->have_read_oplocks) {
1926 data.dptr[data_len-1] = 1;
1929 status = dbwrap_record_store(br_lck->record, data, TDB_REPLACE);
1930 TALLOC_FREE(data.dptr);
1931 if (!NT_STATUS_IS_OK(status)) {
1932 DEBUG(0, ("store returned %s\n", nt_errstr(status)));
1933 smb_panic("Could not store byte range mode entry");
1938 br_lck->modified = false;
1939 TALLOC_FREE(br_lck->record);
1942 static int byte_range_lock_destructor(struct byte_range_lock *br_lck)
1944 byte_range_lock_flush(br_lck);
1948 /*******************************************************************
1949 Fetch a set of byte range lock data from the database.
1950 Leave the record locked.
1951 TALLOC_FREE(brl) will release the lock in the destructor.
1952 ********************************************************************/
1954 struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp)
1957 struct byte_range_lock *br_lck = talloc(mem_ctx, struct byte_range_lock);
1959 if (br_lck == NULL) {
1964 br_lck->num_locks = 0;
1965 br_lck->have_read_oplocks = false;
1966 br_lck->modified = False;
1968 key.dptr = (uint8 *)&fsp->file_id;
1969 key.dsize = sizeof(struct file_id);
1971 br_lck->record = dbwrap_fetch_locked(brlock_db, br_lck, key);
1973 if (br_lck->record == NULL) {
1974 DEBUG(3, ("Could not lock byte range lock entry\n"));
1975 TALLOC_FREE(br_lck);
1979 data = dbwrap_record_get_value(br_lck->record);
1981 br_lck->lock_data = NULL;
1983 talloc_set_destructor(br_lck, byte_range_lock_destructor);
1985 br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
1987 if (br_lck->num_locks != 0) {
1988 br_lck->lock_data = talloc_array(
1989 br_lck, struct lock_struct, br_lck->num_locks);
1990 if (br_lck->lock_data == NULL) {
1991 DEBUG(0, ("malloc failed\n"));
1992 TALLOC_FREE(br_lck);
1996 memcpy(br_lck->lock_data, data.dptr,
1997 talloc_get_size(br_lck->lock_data));
2000 if ((data.dsize % sizeof(struct lock_struct)) == 1) {
2001 br_lck->have_read_oplocks = (data.dptr[data.dsize-1] == 1);
2004 if (!fsp->lockdb_clean) {
2005 int orig_num_locks = br_lck->num_locks;
2008 * This is the first time we access the byte range lock
2009 * record with this fsp. Go through and ensure all entries
2010 * are valid - remove any that don't.
2011 * This makes the lockdb self cleaning at low cost.
2013 * Note: Disconnected entries belong to disconnected
2014 * durable handles. So at this point, we have a new
2015 * handle on the file and the disconnected durable has
2016 * already been closed (we are not a durable reconnect).
2017 * So we need to clean the disconnected brl entry.
2020 if (!validate_lock_entries(br_lck, &br_lck->num_locks,
2021 &br_lck->lock_data, false)) {
2022 TALLOC_FREE(br_lck);
2026 /* Ensure invalid locks are cleaned up in the destructor. */
2027 if (orig_num_locks != br_lck->num_locks) {
2028 br_lck->modified = True;
2031 /* Mark the lockdb as "clean" as seen from this open file. */
2032 fsp->lockdb_clean = True;
2035 if (DEBUGLEVEL >= 10) {
2037 struct lock_struct *locks = br_lck->lock_data;
2038 DEBUG(10,("brl_get_locks_internal: %u current locks on file_id %s\n",
2040 file_id_string_tos(&fsp->file_id)));
2041 for( i = 0; i < br_lck->num_locks; i++) {
2042 print_lock_struct(i, &locks[i]);
2049 struct brl_get_locks_readonly_state {
2050 TALLOC_CTX *mem_ctx;
2051 struct byte_range_lock **br_lock;
2054 static void brl_get_locks_readonly_parser(TDB_DATA key, TDB_DATA data,
2057 struct brl_get_locks_readonly_state *state =
2058 (struct brl_get_locks_readonly_state *)private_data;
2059 struct byte_range_lock *br_lock;
2061 br_lock = talloc_pooled_object(
2062 state->mem_ctx, struct byte_range_lock, 1, data.dsize);
2063 if (br_lock == NULL) {
2064 *state->br_lock = NULL;
2067 br_lock->lock_data = (struct lock_struct *)talloc_memdup(
2068 br_lock, data.dptr, data.dsize);
2069 br_lock->num_locks = data.dsize / sizeof(struct lock_struct);
2071 if ((data.dsize % sizeof(struct lock_struct)) == 1) {
2072 br_lock->have_read_oplocks = (data.dptr[data.dsize-1] == 1);
2075 *state->br_lock = br_lock;
2078 struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp)
2080 struct byte_range_lock *br_lock = NULL;
2081 struct byte_range_lock *rw = NULL;
2083 if ((fsp->brlock_rec != NULL)
2084 && (dbwrap_get_seqnum(brlock_db) == fsp->brlock_seqnum)) {
2086 * We have cached the brlock_rec and the database did not
2089 return fsp->brlock_rec;
2092 if (!fsp->lockdb_clean) {
2094 * Fetch the record in R/W mode to give validate_lock_entries
2095 * a chance to kick in once.
2097 rw = brl_get_locks(talloc_tos(), fsp);
2101 fsp->lockdb_clean = true;
2105 size_t lock_data_size;
2108 * Make a copy of the already retrieved and sanitized rw record
2110 lock_data_size = rw->num_locks * sizeof(struct lock_struct);
2111 br_lock = talloc_pooled_object(
2112 fsp, struct byte_range_lock, 1, lock_data_size);
2113 if (br_lock == NULL) {
2116 br_lock->have_read_oplocks = rw->have_read_oplocks;
2117 br_lock->num_locks = rw->num_locks;
2118 br_lock->lock_data = (struct lock_struct *)talloc_memdup(
2119 br_lock, rw->lock_data, lock_data_size);
2121 struct brl_get_locks_readonly_state state;
2125 * Parse the record fresh from the database
2128 state.mem_ctx = fsp;
2129 state.br_lock = &br_lock;
2131 status = dbwrap_parse_record(
2133 make_tdb_data((uint8_t *)&fsp->file_id,
2134 sizeof(fsp->file_id)),
2135 brl_get_locks_readonly_parser, &state);
2136 if (!NT_STATUS_IS_OK(status)) {
2137 DEBUG(3, ("Could not parse byte range lock record: "
2138 "%s\n", nt_errstr(status)));
2141 if (br_lock == NULL) {
2147 br_lock->modified = false;
2148 br_lock->record = NULL;
2150 if (lp_clustering()) {
2152 * In the cluster case we can't cache the brlock struct
2153 * because dbwrap_get_seqnum does not work reliably over
2154 * ctdb. Thus we have to throw away the brlock struct soon.
2156 talloc_steal(talloc_tos(), br_lock);
2159 * Cache the brlock struct, invalidated when the dbwrap_seqnum
2160 * changes. See beginning of this routine.
2162 TALLOC_FREE(fsp->brlock_rec);
2163 fsp->brlock_rec = br_lock;
2164 fsp->brlock_seqnum = dbwrap_get_seqnum(brlock_db);
2172 struct brl_revalidate_state {
2175 struct server_id *pids;
2179 * Collect PIDs of all processes with pending entries
2182 static void brl_revalidate_collect(struct file_id id, struct server_id pid,
2183 enum brl_type lock_type,
2184 enum brl_flavour lock_flav,
2185 br_off start, br_off size,
2188 struct brl_revalidate_state *state =
2189 (struct brl_revalidate_state *)private_data;
2191 if (!IS_PENDING_LOCK(lock_type)) {
2195 add_to_large_array(state, sizeof(pid), (void *)&pid,
2196 &state->pids, &state->num_pids,
2197 &state->array_size);
2201 * qsort callback to sort the processes
2204 static int compare_procids(const void *p1, const void *p2)
2206 const struct server_id *i1 = (const struct server_id *)p1;
2207 const struct server_id *i2 = (const struct server_id *)p2;
2209 if (i1->pid < i2->pid) return -1;
2210 if (i2->pid > i2->pid) return 1;
2215 * Send a MSG_SMB_UNLOCK message to all processes with pending byte range
2216 * locks so that they retry. Mainly used in the cluster code after a node has
2219 * Done in two steps to avoid double-sends: First we collect all entries in an
2220 * array, then qsort that array and only send to non-dupes.
2223 void brl_revalidate(struct messaging_context *msg_ctx,
2226 struct server_id server_id,
2229 struct brl_revalidate_state *state;
2231 struct server_id last_pid;
2233 if (!(state = talloc_zero(NULL, struct brl_revalidate_state))) {
2234 DEBUG(0, ("talloc failed\n"));
2238 brl_forall(brl_revalidate_collect, state);
2240 if (state->array_size == -1) {
2241 DEBUG(0, ("talloc failed\n"));
2245 if (state->num_pids == 0) {
2249 TYPESAFE_QSORT(state->pids, state->num_pids, compare_procids);
2251 ZERO_STRUCT(last_pid);
2253 for (i=0; i<state->num_pids; i++) {
2254 if (serverid_equal(&last_pid, &state->pids[i])) {
2256 * We've seen that one already
2261 messaging_send(msg_ctx, state->pids[i], MSG_SMB_UNLOCK,
2263 last_pid = state->pids[i];
2271 bool brl_cleanup_disconnected(struct file_id fid, uint64_t open_persistent_id)
2274 TALLOC_CTX *frame = talloc_stackframe();
2276 struct db_record *rec;
2277 struct lock_struct *lock;
2281 key = make_tdb_data((void*)&fid, sizeof(fid));
2283 rec = dbwrap_fetch_locked(brlock_db, frame, key);
2285 DEBUG(5, ("brl_cleanup_disconnected: failed to fetch record "
2286 "for file %s\n", file_id_string(frame, &fid)));
2290 val = dbwrap_record_get_value(rec);
2291 lock = (struct lock_struct*)val.dptr;
2292 num = val.dsize / sizeof(struct lock_struct);
2294 DEBUG(10, ("brl_cleanup_disconnected: no byte range locks for "
2295 "file %s\n", file_id_string(frame, &fid)));
2300 for (n=0; n<num; n++) {
2301 struct lock_context *ctx = &lock[n].context;
2303 if (!server_id_is_disconnected(&ctx->pid)) {
2304 DEBUG(5, ("brl_cleanup_disconnected: byte range lock "
2305 "%s used by server %s, do not cleanup\n",
2306 file_id_string(frame, &fid),
2307 server_id_str(frame, &ctx->pid)));
2311 if (ctx->smblctx != open_persistent_id) {
2312 DEBUG(5, ("brl_cleanup_disconnected: byte range lock "
2313 "%s expected smblctx %llu but found %llu"
2314 ", do not cleanup\n",
2315 file_id_string(frame, &fid),
2316 (unsigned long long)open_persistent_id,
2317 (unsigned long long)ctx->smblctx));
2322 status = dbwrap_record_delete(rec);
2323 if (!NT_STATUS_IS_OK(status)) {
2324 DEBUG(5, ("brl_cleanup_disconnected: failed to delete record "
2325 "for file %s from %s, open %llu: %s\n",
2326 file_id_string(frame, &fid), dbwrap_name(brlock_db),
2327 (unsigned long long)open_persistent_id,
2328 nt_errstr(status)));
2332 DEBUG(10, ("brl_cleanup_disconnected: "
2333 "file %s cleaned up %u entries from open %llu\n",
2334 file_id_string(frame, &fid), num,
2335 (unsigned long long)open_persistent_id));