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 */
30
#define DBGC_CLASS DBGC_LOCKING
34
/* The open brlock.tdb database. */
36
static struct db_context *brlock_db;
38
/****************************************************************************
39
Debug info at level 10 for lock struct.
40
****************************************************************************/
42
static void print_lock_struct(unsigned int i, struct lock_struct *pls)
44
DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %s, ",
46
(unsigned int)pls->context.smbpid,
47
(unsigned int)pls->context.tid,
48
procid_str(debug_ctx(), &pls->context.pid) ));
50
DEBUG(10,("start = %.0f, size = %.0f, fnum = %d, %s %s\n",
54
lock_type_name(pls->lock_type),
55
lock_flav_name(pls->lock_flav) ));
58
/****************************************************************************
59
See if two locking contexts are equal.
60
****************************************************************************/
62
bool brl_same_context(const struct lock_context *ctx1,
63
const struct lock_context *ctx2)
65
return (procid_equal(&ctx1->pid, &ctx2->pid) &&
66
(ctx1->smbpid == ctx2->smbpid) &&
67
(ctx1->tid == ctx2->tid));
70
/****************************************************************************
71
See if lck1 and lck2 overlap.
72
****************************************************************************/
74
static bool brl_overlap(const struct lock_struct *lck1,
75
const struct lock_struct *lck2)
77
/* XXX Remove for Win7 compatibility. */
78
/* this extra check is not redundent - it copes with locks
79
that go beyond the end of 64 bit file space */
80
if (lck1->size != 0 &&
81
lck1->start == lck2->start &&
82
lck1->size == lck2->size) {
86
if (lck1->start >= (lck2->start+lck2->size) ||
87
lck2->start >= (lck1->start+lck1->size)) {
93
/****************************************************************************
94
See if lock2 can be added when lock1 is in place.
95
****************************************************************************/
97
static bool brl_conflict(const struct lock_struct *lck1,
98
const struct lock_struct *lck2)
100
/* Ignore PENDING locks. */
101
if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
104
/* Read locks never conflict. */
105
if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
109
/* A READ lock can stack on top of a WRITE lock if they have the same
111
if (lck1->lock_type == WRITE_LOCK && lck2->lock_type == READ_LOCK &&
112
brl_same_context(&lck1->context, &lck2->context) &&
113
lck1->fnum == lck2->fnum) {
117
return brl_overlap(lck1, lck2);
120
/****************************************************************************
121
See if lock2 can be added when lock1 is in place - when both locks are POSIX
122
flavour. POSIX locks ignore fnum - they only care about dev/ino which we
124
****************************************************************************/
126
static bool brl_conflict_posix(const struct lock_struct *lck1,
127
const struct lock_struct *lck2)
129
#if defined(DEVELOPER)
130
SMB_ASSERT(lck1->lock_flav == POSIX_LOCK);
131
SMB_ASSERT(lck2->lock_flav == POSIX_LOCK);
134
/* Ignore PENDING locks. */
135
if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
138
/* Read locks never conflict. */
139
if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
143
/* Locks on the same context con't conflict. Ignore fnum. */
144
if (brl_same_context(&lck1->context, &lck2->context)) {
148
/* One is read, the other write, or the context is different,
150
return brl_overlap(lck1, lck2);
154
static bool brl_conflict1(const struct lock_struct *lck1,
155
const struct lock_struct *lck2)
157
if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
160
if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
164
if (brl_same_context(&lck1->context, &lck2->context) &&
165
lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) {
169
if (lck2->start == 0 && lck2->size == 0 && lck1->size != 0) {
173
if (lck1->start >= (lck2->start + lck2->size) ||
174
lck2->start >= (lck1->start + lck1->size)) {
182
/****************************************************************************
183
Check to see if this lock conflicts, but ignore our own locks on the
184
same fnum only. This is the read/write lock check code path.
185
This is never used in the POSIX lock case.
186
****************************************************************************/
188
static bool brl_conflict_other(const struct lock_struct *lck1, const struct lock_struct *lck2)
190
if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
193
if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK)
196
/* POSIX flavour locks never conflict here - this is only called
197
in the read/write path. */
199
if (lck1->lock_flav == POSIX_LOCK && lck2->lock_flav == POSIX_LOCK)
203
* Incoming WRITE locks conflict with existing READ locks even
204
* if the context is the same. JRA. See LOCKTEST7 in smbtorture.
207
if (!(lck2->lock_type == WRITE_LOCK && lck1->lock_type == READ_LOCK)) {
208
if (brl_same_context(&lck1->context, &lck2->context) &&
209
lck1->fnum == lck2->fnum)
213
return brl_overlap(lck1, lck2);
216
/****************************************************************************
217
Check if an unlock overlaps a pending lock.
218
****************************************************************************/
220
static bool brl_pending_overlap(const struct lock_struct *lock, const struct lock_struct *pend_lock)
222
if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start))
224
if ((lock->start >= pend_lock->start) && (lock->start <= pend_lock->start + pend_lock->size))
229
/****************************************************************************
230
Amazingly enough, w2k3 "remembers" whether the last lock failure on a fnum
231
is the same as this one and changes its error code. I wonder if any
232
app depends on this ?
233
****************************************************************************/
235
NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, bool blocking_lock)
237
if (lock->start >= 0xEF000000 && (lock->start >> 63) == 0) {
238
/* amazing the little things you learn with a test
239
suite. Locks beyond this offset (as a 64 bit
240
number!) always generate the conflict error code,
241
unless the top bit is set */
242
if (!blocking_lock) {
243
fsp->last_lock_failure = *lock;
245
return NT_STATUS_FILE_LOCK_CONFLICT;
248
if (procid_equal(&lock->context.pid, &fsp->last_lock_failure.context.pid) &&
249
lock->context.tid == fsp->last_lock_failure.context.tid &&
250
lock->fnum == fsp->last_lock_failure.fnum &&
251
lock->start == fsp->last_lock_failure.start) {
252
return NT_STATUS_FILE_LOCK_CONFLICT;
255
if (!blocking_lock) {
256
fsp->last_lock_failure = *lock;
258
return NT_STATUS_LOCK_NOT_GRANTED;
261
/****************************************************************************
262
Open up the brlock.tdb database.
263
****************************************************************************/
265
void brl_init(bool read_only)
270
brlock_db = db_open(NULL, lock_path("brlock.tdb"),
271
lp_open_files_db_hash_size(),
272
TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST,
273
read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 );
275
DEBUG(0,("Failed to open byte range locking database %s\n",
276
lock_path("brlock.tdb")));
281
/****************************************************************************
282
Close down the brlock.tdb database.
283
****************************************************************************/
285
void brl_shutdown(void)
287
TALLOC_FREE(brlock_db);
291
/****************************************************************************
292
Compare two locks for sorting.
293
****************************************************************************/
295
static int lock_compare(const struct lock_struct *lck1,
296
const struct lock_struct *lck2)
298
if (lck1->start != lck2->start) {
299
return (lck1->start - lck2->start);
301
if (lck2->size != lck1->size) {
302
return ((int)lck1->size - (int)lck2->size);
308
/****************************************************************************
309
Lock a range of bytes - Windows lock semantics.
310
****************************************************************************/
312
NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck,
313
struct lock_struct *plock, bool blocking_lock)
316
files_struct *fsp = br_lck->fsp;
317
struct lock_struct *locks = br_lck->lock_data;
320
SMB_ASSERT(plock->lock_type != UNLOCK_LOCK);
322
for (i=0; i < br_lck->num_locks; i++) {
323
/* Do any Windows or POSIX locks conflict ? */
324
if (brl_conflict(&locks[i], plock)) {
325
/* Remember who blocked us. */
326
plock->context.smbpid = locks[i].context.smbpid;
327
return brl_lock_failed(fsp,plock,blocking_lock);
330
if (plock->start == 0 && plock->size == 0 &&
331
locks[i].size == 0) {
337
if (!IS_PENDING_LOCK(plock->lock_type)) {
338
contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WINDOWS_BRL);
341
/* We can get the Windows lock, now see if it needs to
342
be mapped into a lower level POSIX one, and if so can
345
if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(fsp->conn->params)) {
347
if (!set_posix_lock_windows_flavour(fsp,
356
/* We don't know who blocked us. */
357
plock->context.smbpid = 0xFFFFFFFF;
359
if (errno_ret == EACCES || errno_ret == EAGAIN) {
360
status = NT_STATUS_FILE_LOCK_CONFLICT;
363
status = map_nt_error_from_unix(errno);
369
/* no conflicts - add it to the list of locks */
370
locks = (struct lock_struct *)SMB_REALLOC(locks, (br_lck->num_locks + 1) * sizeof(*locks));
372
status = NT_STATUS_NO_MEMORY;
376
memcpy(&locks[br_lck->num_locks], plock, sizeof(struct lock_struct));
377
br_lck->num_locks += 1;
378
br_lck->lock_data = locks;
379
br_lck->modified = True;
383
if (!IS_PENDING_LOCK(plock->lock_type)) {
384
contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WINDOWS_BRL);
389
/****************************************************************************
390
Cope with POSIX range splits and merges.
391
****************************************************************************/
393
static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, /* Output array. */
394
struct lock_struct *ex, /* existing lock. */
395
struct lock_struct *plock) /* proposed lock. */
397
bool lock_types_differ = (ex->lock_type != plock->lock_type);
399
/* We can't merge non-conflicting locks on different context - ignore fnum. */
401
if (!brl_same_context(&ex->context, &plock->context)) {
403
memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
407
/* We now know we have the same context. */
409
/* Did we overlap ? */
411
/*********************************************
422
**********************************************/
424
if ( (ex->start > (plock->start + plock->size)) ||
425
(plock->start > (ex->start + ex->size))) {
427
/* No overlap with this lock - copy existing. */
429
memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
433
/*********************************************
434
+---------------------------+
436
+---------------------------+
437
+---------------------------+
438
| plock | -> replace with plock.
439
+---------------------------+
444
+---------------------------+
445
| plock | -> replace with plock.
446
+---------------------------+
448
**********************************************/
450
if ( (ex->start >= plock->start) &&
451
(ex->start + ex->size <= plock->start + plock->size) ) {
453
/* Replace - discard existing lock. */
458
/*********************************************
468
+---------------+-------+
469
| plock | ex | - different lock types.
470
+---------------+-------+
472
+-----------------------+
473
| plock | - same lock type.
474
+-----------------------+
475
**********************************************/
477
if (plock->start + plock->size == ex->start) {
479
/* If the lock types are the same, we merge, if different, we
480
add the remainder of the old lock. */
482
if (lock_types_differ) {
484
memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
487
/* Merge - adjust incoming lock as we may have more
488
* merging to come. */
489
plock->size += ex->size;
494
/*********************************************
503
+-------+---------------+
504
| ex | plock | - different lock types
505
+-------+---------------+
508
+-----------------------+
509
| plock | - same lock type.
510
+-----------------------+
512
**********************************************/
514
if (ex->start + ex->size == plock->start) {
516
/* If the lock types are the same, we merge, if different, we
517
add the existing lock. */
519
if (lock_types_differ) {
520
memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
523
/* Merge - adjust incoming lock as we may have more
524
* merging to come. */
525
plock->start = ex->start;
526
plock->size += ex->size;
531
/*********************************************
533
+-----------------------+
535
+-----------------------+
548
+---------------+-------+
549
| plock | ex | - different lock types.
550
+---------------+-------+
552
+-----------------------+
553
| plock | - same lock type.
554
+-----------------------+
555
**********************************************/
557
if ( (ex->start >= plock->start) &&
558
(ex->start <= plock->start + plock->size) &&
559
(ex->start + ex->size > plock->start + plock->size) ) {
561
/* If the lock types are the same, we merge, if different, we
562
add the remainder of the old lock. */
564
if (lock_types_differ) {
565
/* Add remaining existing. */
566
memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
567
/* Adjust existing start and size. */
568
lck_arr[0].start = plock->start + plock->size;
569
lck_arr[0].size = (ex->start + ex->size) - (plock->start + plock->size);
572
/* Merge - adjust incoming lock as we may have more
573
* merging to come. */
574
plock->size += (ex->start + ex->size) - (plock->start + plock->size);
579
/*********************************************
581
+-----------------------+
583
+-----------------------+
596
+-------+---------------+
597
| ex | plock | - different lock types
598
+-------+---------------+
601
+-----------------------+
602
| plock | - same lock type.
603
+-----------------------+
605
**********************************************/
607
if ( (ex->start < plock->start) &&
608
(ex->start + ex->size >= plock->start) &&
609
(ex->start + ex->size <= plock->start + plock->size) ) {
611
/* If the lock types are the same, we merge, if different, we
612
add the truncated old lock. */
614
if (lock_types_differ) {
615
memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
616
/* Adjust existing size. */
617
lck_arr[0].size = plock->start - ex->start;
620
/* Merge - adjust incoming lock as we may have more
621
* merging to come. MUST ADJUST plock SIZE FIRST ! */
622
plock->size += (plock->start - ex->start);
623
plock->start = ex->start;
628
/*********************************************
630
+---------------------------+
632
+---------------------------+
637
+-------+---------+---------+
638
| ex | plock | ex | - different lock types.
639
+-------+---------+---------+
641
+---------------------------+
642
| plock | - same lock type.
643
+---------------------------+
644
**********************************************/
646
if ( (ex->start < plock->start) && (ex->start + ex->size > plock->start + plock->size) ) {
648
if (lock_types_differ) {
650
/* We have to split ex into two locks here. */
652
memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
653
memcpy(&lck_arr[1], ex, sizeof(struct lock_struct));
655
/* Adjust first existing size. */
656
lck_arr[0].size = plock->start - ex->start;
658
/* Adjust second existing start and size. */
659
lck_arr[1].start = plock->start + plock->size;
660
lck_arr[1].size = (ex->start + ex->size) - (plock->start + plock->size);
663
/* Just eat the existing locks, merge them into plock. */
664
plock->start = ex->start;
665
plock->size = ex->size;
670
/* Never get here. */
671
smb_panic("brlock_posix_split_merge");
674
/* Keep some compilers happy. */
678
/****************************************************************************
679
Lock a range of bytes - POSIX lock semantics.
680
We must cope with range splits and merges.
681
****************************************************************************/
683
static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx,
684
struct byte_range_lock *br_lck,
685
struct lock_struct *plock)
687
unsigned int i, count, posix_count;
688
struct lock_struct *locks = br_lck->lock_data;
689
struct lock_struct *tp;
690
bool signal_pending_read = False;
691
bool break_oplocks = false;
694
/* No zero-zero locks for POSIX. */
695
if (plock->start == 0 && plock->size == 0) {
696
return NT_STATUS_INVALID_PARAMETER;
699
/* Don't allow 64-bit lock wrap. */
700
if (plock->start + plock->size < plock->start ||
701
plock->start + plock->size < plock->size) {
702
return NT_STATUS_INVALID_PARAMETER;
705
/* The worst case scenario here is we have to split an
706
existing POSIX lock range into two, and add our lock,
707
so we need at most 2 more entries. */
709
tp = SMB_MALLOC_ARRAY(struct lock_struct, (br_lck->num_locks + 2));
711
return NT_STATUS_NO_MEMORY;
714
count = posix_count = 0;
716
for (i=0; i < br_lck->num_locks; i++) {
717
struct lock_struct *curr_lock = &locks[i];
719
/* If we have a pending read lock, a lock downgrade should
720
trigger a lock re-evaluation. */
721
if (curr_lock->lock_type == PENDING_READ_LOCK &&
722
brl_pending_overlap(plock, curr_lock)) {
723
signal_pending_read = True;
726
if (curr_lock->lock_flav == WINDOWS_LOCK) {
727
/* Do any Windows flavour locks conflict ? */
728
if (brl_conflict(curr_lock, plock)) {
729
/* No games with error messages. */
731
/* Remember who blocked us. */
732
plock->context.smbpid = curr_lock->context.smbpid;
733
return NT_STATUS_FILE_LOCK_CONFLICT;
735
/* Just copy the Windows lock into the new array. */
736
memcpy(&tp[count], curr_lock, sizeof(struct lock_struct));
739
unsigned int tmp_count = 0;
741
/* POSIX conflict semantics are different. */
742
if (brl_conflict_posix(curr_lock, plock)) {
743
/* Can't block ourselves with POSIX locks. */
744
/* No games with error messages. */
746
/* Remember who blocked us. */
747
plock->context.smbpid = curr_lock->context.smbpid;
748
return NT_STATUS_FILE_LOCK_CONFLICT;
751
/* Work out overlaps. */
752
tmp_count += brlock_posix_split_merge(&tp[count], curr_lock, plock);
753
posix_count += tmp_count;
759
* Break oplocks while we hold a brl. Since lock() and unlock() calls
760
* are not symetric with POSIX semantics, we cannot guarantee our
761
* contend_level2_oplocks_begin/end calls will be acquired and
762
* released one-for-one as with Windows semantics. Therefore we only
763
* call contend_level2_oplocks_begin if this is the first POSIX brl on
766
break_oplocks = (!IS_PENDING_LOCK(plock->lock_type) &&
769
contend_level2_oplocks_begin(br_lck->fsp,
770
LEVEL2_CONTEND_POSIX_BRL);
773
/* Try and add the lock in order, sorted by lock start. */
774
for (i=0; i < count; i++) {
775
struct lock_struct *curr_lock = &tp[i];
777
if (curr_lock->start <= plock->start) {
783
memmove(&tp[i+1], &tp[i],
784
(count - i)*sizeof(struct lock_struct));
786
memcpy(&tp[i], plock, sizeof(struct lock_struct));
789
/* We can get the POSIX lock, now see if it needs to
790
be mapped into a lower level POSIX one, and if so can
793
if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(br_lck->fsp->conn->params)) {
796
/* The lower layer just needs to attempt to
797
get the system POSIX lock. We've weeded out
798
any conflicts above. */
800
if (!set_posix_lock_posix_flavour(br_lck->fsp,
806
/* We don't know who blocked us. */
807
plock->context.smbpid = 0xFFFFFFFF;
809
if (errno_ret == EACCES || errno_ret == EAGAIN) {
811
status = NT_STATUS_FILE_LOCK_CONFLICT;
815
status = map_nt_error_from_unix(errno);
821
/* If we didn't use all the allocated size,
822
* Realloc so we don't leak entries per lock call. */
823
if (count < br_lck->num_locks + 2) {
824
tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks));
826
status = NT_STATUS_NO_MEMORY;
831
br_lck->num_locks = count;
832
SAFE_FREE(br_lck->lock_data);
833
br_lck->lock_data = tp;
835
br_lck->modified = True;
837
/* A successful downgrade from write to read lock can trigger a lock
838
re-evalutation where waiting readers can now proceed. */
840
if (signal_pending_read) {
841
/* Send unlock messages to any pending read waiters that overlap. */
842
for (i=0; i < br_lck->num_locks; i++) {
843
struct lock_struct *pend_lock = &locks[i];
845
/* Ignore non-pending locks. */
846
if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
850
if (pend_lock->lock_type == PENDING_READ_LOCK &&
851
brl_pending_overlap(plock, pend_lock)) {
852
DEBUG(10,("brl_lock_posix: sending unlock message to pid %s\n",
853
procid_str_static(&pend_lock->context.pid )));
855
messaging_send(msg_ctx, pend_lock->context.pid,
856
MSG_SMB_UNLOCK, &data_blob_null);
864
contend_level2_oplocks_end(br_lck->fsp,
865
LEVEL2_CONTEND_POSIX_BRL);
870
/****************************************************************************
871
Lock a range of bytes.
872
****************************************************************************/
874
NTSTATUS brl_lock(struct messaging_context *msg_ctx,
875
struct byte_range_lock *br_lck,
877
struct server_id pid,
880
enum brl_type lock_type,
881
enum brl_flavour lock_flav,
884
struct blocking_lock_record *blr)
887
struct lock_struct lock;
890
if (start == 0 && size == 0) {
891
DEBUG(0,("client sent 0/0 lock - please report this\n"));
896
/* Quieten valgrind on test. */
897
memset(&lock, '\0', sizeof(lock));
900
lock.context.smbpid = smbpid;
901
lock.context.pid = pid;
902
lock.context.tid = br_lck->fsp->conn->cnum;
905
lock.fnum = br_lck->fsp->fnum;
906
lock.lock_type = lock_type;
907
lock.lock_flav = lock_flav;
909
if (lock_flav == WINDOWS_LOCK) {
910
ret = SMB_VFS_BRL_LOCK_WINDOWS(br_lck->fsp->conn, br_lck,
911
&lock, blocking_lock, blr);
913
ret = brl_lock_posix(msg_ctx, br_lck, &lock);
917
/* sort the lock list */
918
qsort(br_lck->lock_data, (size_t)br_lck->num_locks, sizeof(lock), lock_compare);
921
/* If we're returning an error, return who blocked us. */
922
if (!NT_STATUS_IS_OK(ret) && psmbpid) {
923
*psmbpid = lock.context.smbpid;
928
/****************************************************************************
929
Unlock a range of bytes - Windows semantics.
930
****************************************************************************/
932
bool brl_unlock_windows_default(struct messaging_context *msg_ctx,
933
struct byte_range_lock *br_lck,
934
const struct lock_struct *plock)
937
struct lock_struct *locks = br_lck->lock_data;
938
enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */
940
SMB_ASSERT(plock->lock_type == UNLOCK_LOCK);
943
/* Delete write locks by preference... The lock list
944
is sorted in the zero zero case. */
946
for (i = 0; i < br_lck->num_locks; i++) {
947
struct lock_struct *lock = &locks[i];
949
if (lock->lock_type == WRITE_LOCK &&
950
brl_same_context(&lock->context, &plock->context) &&
951
lock->fnum == plock->fnum &&
952
lock->lock_flav == WINDOWS_LOCK &&
953
lock->start == plock->start &&
954
lock->size == plock->size) {
956
/* found it - delete it */
957
deleted_lock_type = lock->lock_type;
962
if (i != br_lck->num_locks) {
963
/* We found it - don't search again. */
964
goto unlock_continue;
968
for (i = 0; i < br_lck->num_locks; i++) {
969
struct lock_struct *lock = &locks[i];
971
/* Only remove our own locks that match in start, size, and flavour. */
972
if (brl_same_context(&lock->context, &plock->context) &&
973
lock->fnum == plock->fnum &&
974
lock->lock_flav == WINDOWS_LOCK &&
975
lock->start == plock->start &&
976
lock->size == plock->size ) {
977
deleted_lock_type = lock->lock_type;
982
if (i == br_lck->num_locks) {
983
/* we didn't find it */
991
/* Actually delete the lock. */
992
if (i < br_lck->num_locks - 1) {
993
memmove(&locks[i], &locks[i+1],
994
sizeof(*locks)*((br_lck->num_locks-1) - i));
997
br_lck->num_locks -= 1;
998
br_lck->modified = True;
1000
/* Unlock the underlying POSIX regions. */
1001
if(lp_posix_locking(br_lck->fsp->conn->params)) {
1002
release_posix_lock_windows_flavour(br_lck->fsp,
1011
/* Send unlock messages to any pending waiters that overlap. */
1012
for (j=0; j < br_lck->num_locks; j++) {
1013
struct lock_struct *pend_lock = &locks[j];
1015
/* Ignore non-pending locks. */
1016
if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
1020
/* We could send specific lock info here... */
1021
if (brl_pending_overlap(plock, pend_lock)) {
1022
DEBUG(10,("brl_unlock: sending unlock message to pid %s\n",
1023
procid_str_static(&pend_lock->context.pid )));
1025
messaging_send(msg_ctx, pend_lock->context.pid,
1026
MSG_SMB_UNLOCK, &data_blob_null);
1030
contend_level2_oplocks_end(br_lck->fsp, LEVEL2_CONTEND_WINDOWS_BRL);
1034
/****************************************************************************
1035
Unlock a range of bytes - POSIX semantics.
1036
****************************************************************************/
1038
static bool brl_unlock_posix(struct messaging_context *msg_ctx,
1039
struct byte_range_lock *br_lck,
1040
struct lock_struct *plock)
1042
unsigned int i, j, count;
1043
struct lock_struct *tp;
1044
struct lock_struct *locks = br_lck->lock_data;
1045
bool overlap_found = False;
1047
/* No zero-zero locks for POSIX. */
1048
if (plock->start == 0 && plock->size == 0) {
1052
/* Don't allow 64-bit lock wrap. */
1053
if (plock->start + plock->size < plock->start ||
1054
plock->start + plock->size < plock->size) {
1055
DEBUG(10,("brl_unlock_posix: lock wrap\n"));
1059
/* The worst case scenario here is we have to split an
1060
existing POSIX lock range into two, so we need at most
1063
tp = SMB_MALLOC_ARRAY(struct lock_struct, (br_lck->num_locks + 1));
1065
DEBUG(10,("brl_unlock_posix: malloc fail\n"));
1070
for (i = 0; i < br_lck->num_locks; i++) {
1071
struct lock_struct *lock = &locks[i];
1072
unsigned int tmp_count;
1074
/* Only remove our own locks - ignore fnum. */
1075
if (IS_PENDING_LOCK(lock->lock_type) ||
1076
!brl_same_context(&lock->context, &plock->context)) {
1077
memcpy(&tp[count], lock, sizeof(struct lock_struct));
1082
if (lock->lock_flav == WINDOWS_LOCK) {
1083
/* Do any Windows flavour locks conflict ? */
1084
if (brl_conflict(lock, plock)) {
1088
/* Just copy the Windows lock into the new array. */
1089
memcpy(&tp[count], lock, sizeof(struct lock_struct));
1094
/* Work out overlaps. */
1095
tmp_count = brlock_posix_split_merge(&tp[count], lock, plock);
1097
if (tmp_count == 0) {
1098
/* plock overlapped the existing lock completely,
1099
or replaced it. Don't copy the existing lock. */
1100
overlap_found = true;
1101
} else if (tmp_count == 1) {
1102
/* Either no overlap, (simple copy of existing lock) or
1103
* an overlap of an existing lock. */
1104
/* If the lock changed size, we had an overlap. */
1105
if (tp[count].size != lock->size) {
1106
overlap_found = true;
1109
} else if (tmp_count == 2) {
1110
/* We split a lock range in two. */
1111
overlap_found = true;
1114
/* Optimisation... */
1115
/* We know we're finished here as we can't overlap any
1116
more POSIX locks. Copy the rest of the lock array. */
1118
if (i < br_lck->num_locks - 1) {
1119
memcpy(&tp[count], &locks[i+1],
1120
sizeof(*locks)*((br_lck->num_locks-1) - i));
1121
count += ((br_lck->num_locks-1) - i);
1128
if (!overlap_found) {
1129
/* Just ignore - no change. */
1131
DEBUG(10,("brl_unlock_posix: No overlap - unlocked.\n"));
1135
/* Unlock any POSIX regions. */
1136
if(lp_posix_locking(br_lck->fsp->conn->params)) {
1137
release_posix_lock_posix_flavour(br_lck->fsp,
1145
/* Realloc so we don't leak entries per unlock call. */
1147
tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks));
1149
DEBUG(10,("brl_unlock_posix: realloc fail\n"));
1153
/* We deleted the last lock. */
1158
contend_level2_oplocks_end(br_lck->fsp,
1159
LEVEL2_CONTEND_POSIX_BRL);
1161
br_lck->num_locks = count;
1162
SAFE_FREE(br_lck->lock_data);
1164
br_lck->lock_data = tp;
1165
br_lck->modified = True;
1167
/* Send unlock messages to any pending waiters that overlap. */
1169
for (j=0; j < br_lck->num_locks; j++) {
1170
struct lock_struct *pend_lock = &locks[j];
1172
/* Ignore non-pending locks. */
1173
if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
1177
/* We could send specific lock info here... */
1178
if (brl_pending_overlap(plock, pend_lock)) {
1179
DEBUG(10,("brl_unlock: sending unlock message to pid %s\n",
1180
procid_str_static(&pend_lock->context.pid )));
1182
messaging_send(msg_ctx, pend_lock->context.pid,
1183
MSG_SMB_UNLOCK, &data_blob_null);
1190
/****************************************************************************
1191
Unlock a range of bytes.
1192
****************************************************************************/
1194
bool brl_unlock(struct messaging_context *msg_ctx,
1195
struct byte_range_lock *br_lck,
1197
struct server_id pid,
1200
enum brl_flavour lock_flav)
1202
struct lock_struct lock;
1204
lock.context.smbpid = smbpid;
1205
lock.context.pid = pid;
1206
lock.context.tid = br_lck->fsp->conn->cnum;
1209
lock.fnum = br_lck->fsp->fnum;
1210
lock.lock_type = UNLOCK_LOCK;
1211
lock.lock_flav = lock_flav;
1213
if (lock_flav == WINDOWS_LOCK) {
1214
return SMB_VFS_BRL_UNLOCK_WINDOWS(br_lck->fsp->conn, msg_ctx,
1217
return brl_unlock_posix(msg_ctx, br_lck, &lock);
1221
/****************************************************************************
1222
Test if we could add a lock if we wanted to.
1223
Returns True if the region required is currently unlocked, False if locked.
1224
****************************************************************************/
1226
bool brl_locktest(struct byte_range_lock *br_lck,
1228
struct server_id pid,
1231
enum brl_type lock_type,
1232
enum brl_flavour lock_flav)
1236
struct lock_struct lock;
1237
const struct lock_struct *locks = br_lck->lock_data;
1238
files_struct *fsp = br_lck->fsp;
1240
lock.context.smbpid = smbpid;
1241
lock.context.pid = pid;
1242
lock.context.tid = br_lck->fsp->conn->cnum;
1245
lock.fnum = fsp->fnum;
1246
lock.lock_type = lock_type;
1247
lock.lock_flav = lock_flav;
1249
/* Make sure existing locks don't conflict */
1250
for (i=0; i < br_lck->num_locks; i++) {
1252
* Our own locks don't conflict.
1254
if (brl_conflict_other(&locks[i], &lock)) {
1260
* There is no lock held by an SMB daemon, check to
1261
* see if there is a POSIX lock from a UNIX or NFS process.
1262
* This only conflicts with Windows locks, not POSIX locks.
1265
if(lp_posix_locking(fsp->conn->params) && (lock_flav == WINDOWS_LOCK)) {
1266
ret = is_posix_locked(fsp, &start, &size, &lock_type, WINDOWS_LOCK);
1268
DEBUG(10,("brl_locktest: posix start=%.0f len=%.0f %s for fnum %d file %s\n",
1269
(double)start, (double)size, ret ? "locked" : "unlocked",
1270
fsp->fnum, fsp->fsp_name ));
1272
/* We need to return the inverse of is_posix_locked. */
1276
/* no conflicts - we could have added it */
1280
/****************************************************************************
1281
Query for existing locks.
1282
****************************************************************************/
1284
NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
1286
struct server_id pid,
1289
enum brl_type *plock_type,
1290
enum brl_flavour lock_flav)
1293
struct lock_struct lock;
1294
const struct lock_struct *locks = br_lck->lock_data;
1295
files_struct *fsp = br_lck->fsp;
1297
lock.context.smbpid = *psmbpid;
1298
lock.context.pid = pid;
1299
lock.context.tid = br_lck->fsp->conn->cnum;
1300
lock.start = *pstart;
1302
lock.fnum = fsp->fnum;
1303
lock.lock_type = *plock_type;
1304
lock.lock_flav = lock_flav;
1306
/* Make sure existing locks don't conflict */
1307
for (i=0; i < br_lck->num_locks; i++) {
1308
const struct lock_struct *exlock = &locks[i];
1309
bool conflict = False;
1311
if (exlock->lock_flav == WINDOWS_LOCK) {
1312
conflict = brl_conflict(exlock, &lock);
1314
conflict = brl_conflict_posix(exlock, &lock);
1318
*psmbpid = exlock->context.smbpid;
1319
*pstart = exlock->start;
1320
*psize = exlock->size;
1321
*plock_type = exlock->lock_type;
1322
return NT_STATUS_LOCK_NOT_GRANTED;
1327
* There is no lock held by an SMB daemon, check to
1328
* see if there is a POSIX lock from a UNIX or NFS process.
1331
if(lp_posix_locking(fsp->conn->params)) {
1332
bool ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK);
1334
DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for fnum %d file %s\n",
1335
(double)*pstart, (double)*psize, ret ? "locked" : "unlocked",
1336
fsp->fnum, fsp->fsp_name ));
1339
/* Hmmm. No clue what to set smbpid to - use -1. */
1341
return NT_STATUS_LOCK_NOT_GRANTED;
1345
return NT_STATUS_OK;
1348
/****************************************************************************
1349
Remove a particular pending lock.
1350
****************************************************************************/
1351
bool brl_lock_cancel(struct byte_range_lock *br_lck,
1353
struct server_id pid,
1356
enum brl_flavour lock_flav,
1357
struct blocking_lock_record *blr)
1360
struct lock_struct lock;
1362
lock.context.smbpid = smbpid;
1363
lock.context.pid = pid;
1364
lock.context.tid = br_lck->fsp->conn->cnum;
1367
lock.fnum = br_lck->fsp->fnum;
1368
lock.lock_flav = lock_flav;
1369
/* lock.lock_type doesn't matter */
1371
if (lock_flav == WINDOWS_LOCK) {
1372
ret = SMB_VFS_BRL_CANCEL_WINDOWS(br_lck->fsp->conn, br_lck,
1375
ret = brl_lock_cancel_default(br_lck, &lock);
1381
bool brl_lock_cancel_default(struct byte_range_lock *br_lck,
1382
struct lock_struct *plock)
1385
struct lock_struct *locks = br_lck->lock_data;
1389
for (i = 0; i < br_lck->num_locks; i++) {
1390
struct lock_struct *lock = &locks[i];
1392
/* For pending locks we *always* care about the fnum. */
1393
if (brl_same_context(&lock->context, &plock->context) &&
1394
lock->fnum == plock->fnum &&
1395
IS_PENDING_LOCK(lock->lock_type) &&
1396
lock->lock_flav == plock->lock_flav &&
1397
lock->start == plock->start &&
1398
lock->size == plock->size) {
1403
if (i == br_lck->num_locks) {
1404
/* Didn't find it. */
1408
if (i < br_lck->num_locks - 1) {
1409
/* Found this particular pending lock - delete it */
1410
memmove(&locks[i], &locks[i+1],
1411
sizeof(*locks)*((br_lck->num_locks-1) - i));
1414
br_lck->num_locks -= 1;
1415
br_lck->modified = True;
1419
/****************************************************************************
1420
Remove any locks associated with a open file.
1421
We return True if this process owns any other Windows locks on this
1422
fd and so we should not immediately close the fd.
1423
****************************************************************************/
1425
void brl_close_fnum(struct messaging_context *msg_ctx,
1426
struct byte_range_lock *br_lck)
1428
files_struct *fsp = br_lck->fsp;
1429
uint16 tid = fsp->conn->cnum;
1430
int fnum = fsp->fnum;
1431
unsigned int i, j, dcount=0;
1432
int num_deleted_windows_locks = 0;
1433
struct lock_struct *locks = br_lck->lock_data;
1434
struct server_id pid = procid_self();
1435
bool unlock_individually = False;
1436
bool posix_level2_contention_ended = false;
1438
if(lp_posix_locking(fsp->conn->params)) {
1440
/* Check if there are any Windows locks associated with this dev/ino
1441
pair that are not this fnum. If so we need to call unlock on each
1442
one in order to release the system POSIX locks correctly. */
1444
for (i=0; i < br_lck->num_locks; i++) {
1445
struct lock_struct *lock = &locks[i];
1447
if (!procid_equal(&lock->context.pid, &pid)) {
1451
if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) {
1452
continue; /* Ignore pending. */
1455
if (lock->context.tid != tid || lock->fnum != fnum) {
1456
unlock_individually = True;
1461
if (unlock_individually) {
1462
struct lock_struct *locks_copy;
1463
unsigned int num_locks_copy;
1465
/* Copy the current lock array. */
1466
if (br_lck->num_locks) {
1467
locks_copy = (struct lock_struct *)TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct));
1469
smb_panic("brl_close_fnum: talloc failed");
1475
num_locks_copy = br_lck->num_locks;
1477
for (i=0; i < num_locks_copy; i++) {
1478
struct lock_struct *lock = &locks_copy[i];
1480
if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid) &&
1481
(lock->fnum == fnum)) {
1484
lock->context.smbpid,
1495
/* We can bulk delete - any POSIX locks will be removed when the fd closes. */
1497
/* Remove any existing locks for this fnum (or any fnum if they're POSIX). */
1499
for (i=0; i < br_lck->num_locks; i++) {
1500
struct lock_struct *lock = &locks[i];
1501
bool del_this_lock = False;
1503
if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid)) {
1504
if ((lock->lock_flav == WINDOWS_LOCK) && (lock->fnum == fnum)) {
1505
del_this_lock = True;
1506
num_deleted_windows_locks++;
1507
contend_level2_oplocks_end(br_lck->fsp,
1508
LEVEL2_CONTEND_WINDOWS_BRL);
1509
} else if (lock->lock_flav == POSIX_LOCK) {
1510
del_this_lock = True;
1512
/* Only end level2 contention once for posix */
1513
if (!posix_level2_contention_ended) {
1514
posix_level2_contention_ended = true;
1515
contend_level2_oplocks_end(br_lck->fsp,
1516
LEVEL2_CONTEND_POSIX_BRL);
1521
if (del_this_lock) {
1522
/* Send unlock messages to any pending waiters that overlap. */
1523
for (j=0; j < br_lck->num_locks; j++) {
1524
struct lock_struct *pend_lock = &locks[j];
1526
/* Ignore our own or non-pending locks. */
1527
if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
1531
/* Optimisation - don't send to this fnum as we're
1533
if (pend_lock->context.tid == tid &&
1534
procid_equal(&pend_lock->context.pid, &pid) &&
1535
pend_lock->fnum == fnum) {
1539
/* We could send specific lock info here... */
1540
if (brl_pending_overlap(lock, pend_lock)) {
1541
messaging_send(msg_ctx, pend_lock->context.pid,
1542
MSG_SMB_UNLOCK, &data_blob_null);
1546
/* found it - delete it */
1547
if (br_lck->num_locks > 1 && i < br_lck->num_locks - 1) {
1548
memmove(&locks[i], &locks[i+1],
1549
sizeof(*locks)*((br_lck->num_locks-1) - i));
1551
br_lck->num_locks--;
1552
br_lck->modified = True;
1558
if(lp_posix_locking(fsp->conn->params) && num_deleted_windows_locks) {
1559
/* Reduce the Windows lock POSIX reference count on this dev/ino pair. */
1560
reduce_windows_lock_ref_count(fsp, num_deleted_windows_locks);
1564
/****************************************************************************
1565
Ensure this set of lock entries is valid.
1566
****************************************************************************/
1567
static bool validate_lock_entries(unsigned int *pnum_entries, struct lock_struct **pplocks)
1570
unsigned int num_valid_entries = 0;
1571
struct lock_struct *locks = *pplocks;
1573
for (i = 0; i < *pnum_entries; i++) {
1574
struct lock_struct *lock_data = &locks[i];
1575
if (!process_exists(lock_data->context.pid)) {
1576
/* This process no longer exists - mark this
1577
entry as invalid by zeroing it. */
1578
ZERO_STRUCTP(lock_data);
1580
num_valid_entries++;
1584
if (num_valid_entries != *pnum_entries) {
1585
struct lock_struct *new_lock_data = NULL;
1587
if (num_valid_entries) {
1588
new_lock_data = SMB_MALLOC_ARRAY(struct lock_struct, num_valid_entries);
1589
if (!new_lock_data) {
1590
DEBUG(3, ("malloc fail\n"));
1594
num_valid_entries = 0;
1595
for (i = 0; i < *pnum_entries; i++) {
1596
struct lock_struct *lock_data = &locks[i];
1597
if (lock_data->context.smbpid &&
1598
lock_data->context.tid) {
1599
/* Valid (nonzero) entry - copy it. */
1600
memcpy(&new_lock_data[num_valid_entries],
1601
lock_data, sizeof(struct lock_struct));
1602
num_valid_entries++;
1607
SAFE_FREE(*pplocks);
1608
*pplocks = new_lock_data;
1609
*pnum_entries = num_valid_entries;
1615
struct brl_forall_cb {
1616
void (*fn)(struct file_id id, struct server_id pid,
1617
enum brl_type lock_type,
1618
enum brl_flavour lock_flav,
1619
br_off start, br_off size,
1620
void *private_data);
1624
/****************************************************************************
1625
Traverse the whole database with this function, calling traverse_callback
1627
****************************************************************************/
1629
static int traverse_fn(struct db_record *rec, void *state)
1631
struct brl_forall_cb *cb = (struct brl_forall_cb *)state;
1632
struct lock_struct *locks;
1633
struct file_id *key;
1635
unsigned int num_locks = 0;
1636
unsigned int orig_num_locks = 0;
1638
/* In a traverse function we must make a copy of
1639
dbuf before modifying it. */
1641
locks = (struct lock_struct *)memdup(rec->value.dptr,
1644
return -1; /* Terminate traversal. */
1647
key = (struct file_id *)rec->key.dptr;
1648
orig_num_locks = num_locks = rec->value.dsize/sizeof(*locks);
1650
/* Ensure the lock db is clean of entries from invalid processes. */
1652
if (!validate_lock_entries(&num_locks, &locks)) {
1654
return -1; /* Terminate traversal */
1657
if (orig_num_locks != num_locks) {
1660
data.dptr = (uint8_t *)locks;
1661
data.dsize = num_locks*sizeof(struct lock_struct);
1662
rec->store(rec, data, TDB_REPLACE);
1664
rec->delete_rec(rec);
1669
for ( i=0; i<num_locks; i++) {
1671
locks[i].context.pid,
1684
/*******************************************************************
1685
Call the specified function on each lock in the database.
1686
********************************************************************/
1688
int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
1689
enum brl_type lock_type,
1690
enum brl_flavour lock_flav,
1691
br_off start, br_off size,
1692
void *private_data),
1695
struct brl_forall_cb cb;
1701
cb.private_data = private_data;
1702
return brlock_db->traverse(brlock_db, traverse_fn, &cb);
1705
/*******************************************************************
1706
Store a potentially modified set of byte range lock data back into
1709
********************************************************************/
1711
static int byte_range_lock_destructor(struct byte_range_lock *br_lck)
1713
if (br_lck->read_only) {
1714
SMB_ASSERT(!br_lck->modified);
1717
if (!br_lck->modified) {
1721
if (br_lck->num_locks == 0) {
1722
/* No locks - delete this entry. */
1723
NTSTATUS status = br_lck->record->delete_rec(br_lck->record);
1724
if (!NT_STATUS_IS_OK(status)) {
1725
DEBUG(0, ("delete_rec returned %s\n",
1726
nt_errstr(status)));
1727
smb_panic("Could not delete byte range lock entry");
1733
data.dptr = (uint8 *)br_lck->lock_data;
1734
data.dsize = br_lck->num_locks * sizeof(struct lock_struct);
1736
status = br_lck->record->store(br_lck->record, data,
1738
if (!NT_STATUS_IS_OK(status)) {
1739
DEBUG(0, ("store returned %s\n", nt_errstr(status)));
1740
smb_panic("Could not store byte range mode entry");
1746
SAFE_FREE(br_lck->lock_data);
1747
TALLOC_FREE(br_lck->record);
1751
/*******************************************************************
1752
Fetch a set of byte range lock data from the database.
1753
Leave the record locked.
1754
TALLOC_FREE(brl) will release the lock in the destructor.
1755
********************************************************************/
1757
static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx,
1758
files_struct *fsp, bool read_only)
1761
struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock);
1763
if (br_lck == NULL) {
1768
br_lck->num_locks = 0;
1769
br_lck->modified = False;
1770
memset(&br_lck->key, '\0', sizeof(struct file_id));
1771
br_lck->key = fsp->file_id;
1773
key.dptr = (uint8 *)&br_lck->key;
1774
key.dsize = sizeof(struct file_id);
1776
if (!fsp->lockdb_clean) {
1777
/* We must be read/write to clean
1778
the dead entries. */
1783
if (brlock_db->fetch(brlock_db, br_lck, key, &data) == -1) {
1784
DEBUG(3, ("Could not fetch byte range lock record\n"));
1785
TALLOC_FREE(br_lck);
1788
br_lck->record = NULL;
1791
br_lck->record = brlock_db->fetch_locked(brlock_db, br_lck, key);
1793
if (br_lck->record == NULL) {
1794
DEBUG(3, ("Could not lock byte range lock entry\n"));
1795
TALLOC_FREE(br_lck);
1799
data = br_lck->record->value;
1802
br_lck->read_only = read_only;
1803
br_lck->lock_data = NULL;
1805
talloc_set_destructor(br_lck, byte_range_lock_destructor);
1807
br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
1809
if (br_lck->num_locks != 0) {
1810
br_lck->lock_data = SMB_MALLOC_ARRAY(struct lock_struct,
1812
if (br_lck->lock_data == NULL) {
1813
DEBUG(0, ("malloc failed\n"));
1814
TALLOC_FREE(br_lck);
1818
memcpy(br_lck->lock_data, data.dptr, data.dsize);
1821
if (!fsp->lockdb_clean) {
1822
int orig_num_locks = br_lck->num_locks;
1824
/* This is the first time we've accessed this. */
1825
/* Go through and ensure all entries exist - remove any that don't. */
1826
/* Makes the lockdb self cleaning at low cost. */
1828
if (!validate_lock_entries(&br_lck->num_locks,
1829
&br_lck->lock_data)) {
1830
SAFE_FREE(br_lck->lock_data);
1831
TALLOC_FREE(br_lck);
1835
/* Ensure invalid locks are cleaned up in the destructor. */
1836
if (orig_num_locks != br_lck->num_locks) {
1837
br_lck->modified = True;
1840
/* Mark the lockdb as "clean" as seen from this open file. */
1841
fsp->lockdb_clean = True;
1844
if (DEBUGLEVEL >= 10) {
1846
struct lock_struct *locks = br_lck->lock_data;
1847
DEBUG(10,("brl_get_locks_internal: %u current locks on file_id %s\n",
1849
file_id_string_tos(&fsp->file_id)));
1850
for( i = 0; i < br_lck->num_locks; i++) {
1851
print_lock_struct(i, &locks[i]);
1857
struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx,
1860
return brl_get_locks_internal(mem_ctx, fsp, False);
1863
struct byte_range_lock *brl_get_locks_readonly(TALLOC_CTX *mem_ctx,
1866
return brl_get_locks_internal(mem_ctx, fsp, True);
1869
struct brl_revalidate_state {
1872
struct server_id *pids;
1876
* Collect PIDs of all processes with pending entries
1879
static void brl_revalidate_collect(struct file_id id, struct server_id pid,
1880
enum brl_type lock_type,
1881
enum brl_flavour lock_flav,
1882
br_off start, br_off size,
1885
struct brl_revalidate_state *state =
1886
(struct brl_revalidate_state *)private_data;
1888
if (!IS_PENDING_LOCK(lock_type)) {
1892
add_to_large_array(state, sizeof(pid), (void *)&pid,
1893
&state->pids, &state->num_pids,
1894
&state->array_size);
1898
* qsort callback to sort the processes
1901
static int compare_procids(const void *p1, const void *p2)
1903
const struct server_id *i1 = (struct server_id *)p1;
1904
const struct server_id *i2 = (struct server_id *)p2;
1906
if (i1->pid < i2->pid) return -1;
1907
if (i2->pid > i2->pid) return 1;
1912
* Send a MSG_SMB_UNLOCK message to all processes with pending byte range
1913
* locks so that they retry. Mainly used in the cluster code after a node has
1916
* Done in two steps to avoid double-sends: First we collect all entries in an
1917
* array, then qsort that array and only send to non-dupes.
1920
static void brl_revalidate(struct messaging_context *msg_ctx,
1923
struct server_id server_id,
1926
struct brl_revalidate_state *state;
1928
struct server_id last_pid;
1930
if (!(state = TALLOC_ZERO_P(NULL, struct brl_revalidate_state))) {
1931
DEBUG(0, ("talloc failed\n"));
1935
brl_forall(brl_revalidate_collect, state);
1937
if (state->array_size == -1) {
1938
DEBUG(0, ("talloc failed\n"));
1942
if (state->num_pids == 0) {
1946
qsort(state->pids, state->num_pids, sizeof(state->pids[0]),
1949
ZERO_STRUCT(last_pid);
1951
for (i=0; i<state->num_pids; i++) {
1952
if (procid_equal(&last_pid, &state->pids[i])) {
1954
* We've seen that one already
1959
messaging_send(msg_ctx, state->pids[i], MSG_SMB_UNLOCK,
1961
last_pid = state->pids[i];
1969
void brl_register_msgs(struct messaging_context *msg_ctx)
1971
messaging_register(msg_ctx, NULL, MSG_SMB_BRL_VALIDATE,