r24266: Remove the "open files database hash size" parameter
[samba.git] / source3 / locking / brlock.c
1 /* 
2    Unix SMB/CIFS implementation.
3    byte range locking code
4    Updated to handle range splits/merges.
5
6    Copyright (C) Andrew Tridgell 1992-2000
7    Copyright (C) Jeremy Allison 1992-2000
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /* This module implements a tdb based byte range locking service,
24    replacing the fcntl() based byte range locking previously
25    used. This allows us to provide the same semantics as NT */
26
27 #include "includes.h"
28
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_LOCKING
31
32 #define ZERO_ZERO 0
33
34 /* The open brlock.tdb database. */
35
36 static struct db_context *brlock_db;
37
38 /****************************************************************************
39  Debug info at level 10 for lock struct.
40 ****************************************************************************/
41
42 static void print_lock_struct(unsigned int i, struct lock_struct *pls)
43 {
44         DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %s, ",
45                         i,
46                         (unsigned int)pls->context.smbpid,
47                         (unsigned int)pls->context.tid,
48                         procid_str_static(&pls->context.pid) ));
49         
50         DEBUG(10,("start = %.0f, size = %.0f, fnum = %d, %s %s\n",
51                 (double)pls->start,
52                 (double)pls->size,
53                 pls->fnum,
54                 lock_type_name(pls->lock_type),
55                 lock_flav_name(pls->lock_flav) ));
56 }
57
58 /****************************************************************************
59  See if two locking contexts are equal.
60 ****************************************************************************/
61
62 BOOL brl_same_context(const struct lock_context *ctx1, 
63                              const struct lock_context *ctx2)
64 {
65         return (procid_equal(&ctx1->pid, &ctx2->pid) &&
66                 (ctx1->smbpid == ctx2->smbpid) &&
67                 (ctx1->tid == ctx2->tid));
68 }
69
70 /****************************************************************************
71  See if lck1 and lck2 overlap.
72 ****************************************************************************/
73
74 static BOOL brl_overlap(const struct lock_struct *lck1,
75                         const struct lock_struct *lck2)
76 {
77         /* this extra check is not redundent - it copes with locks
78            that go beyond the end of 64 bit file space */
79         if (lck1->size != 0 &&
80             lck1->start == lck2->start &&
81             lck1->size == lck2->size) {
82                 return True;
83         }
84
85         if (lck1->start >= (lck2->start+lck2->size) ||
86             lck2->start >= (lck1->start+lck1->size)) {
87                 return False;
88         }
89         return True;
90 }
91
92 /****************************************************************************
93  See if lock2 can be added when lock1 is in place.
94 ****************************************************************************/
95
96 static BOOL brl_conflict(const struct lock_struct *lck1, 
97                          const struct lock_struct *lck2)
98 {
99         /* Ignore PENDING locks. */
100         if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
101                 return False;
102
103         /* Read locks never conflict. */
104         if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
105                 return False;
106         }
107
108         if (brl_same_context(&lck1->context, &lck2->context) &&
109             lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) {
110                 return False;
111         }
112
113         return brl_overlap(lck1, lck2);
114
115
116 /****************************************************************************
117  See if lock2 can be added when lock1 is in place - when both locks are POSIX
118  flavour. POSIX locks ignore fnum - they only care about dev/ino which we
119  know already match.
120 ****************************************************************************/
121
122 static BOOL brl_conflict_posix(const struct lock_struct *lck1, 
123                                 const struct lock_struct *lck2)
124 {
125 #if defined(DEVELOPER)
126         SMB_ASSERT(lck1->lock_flav == POSIX_LOCK);
127         SMB_ASSERT(lck2->lock_flav == POSIX_LOCK);
128 #endif
129
130         /* Ignore PENDING locks. */
131         if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
132                 return False;
133
134         /* Read locks never conflict. */
135         if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
136                 return False;
137         }
138
139         /* Locks on the same context con't conflict. Ignore fnum. */
140         if (brl_same_context(&lck1->context, &lck2->context)) {
141                 return False;
142         }
143
144         /* One is read, the other write, or the context is different,
145            do they overlap ? */
146         return brl_overlap(lck1, lck2);
147
148
149 #if ZERO_ZERO
150 static BOOL brl_conflict1(const struct lock_struct *lck1, 
151                          const struct lock_struct *lck2)
152 {
153         if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
154                 return False;
155
156         if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
157                 return False;
158         }
159
160         if (brl_same_context(&lck1->context, &lck2->context) &&
161             lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) {
162                 return False;
163         }
164
165         if (lck2->start == 0 && lck2->size == 0 && lck1->size != 0) {
166                 return True;
167         }
168
169         if (lck1->start >= (lck2->start + lck2->size) ||
170             lck2->start >= (lck1->start + lck1->size)) {
171                 return False;
172         }
173             
174         return True;
175
176 #endif
177
178 /****************************************************************************
179  Check to see if this lock conflicts, but ignore our own locks on the
180  same fnum only. This is the read/write lock check code path.
181  This is never used in the POSIX lock case.
182 ****************************************************************************/
183
184 static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock_struct *lck2)
185 {
186         if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
187                 return False;
188
189         if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) 
190                 return False;
191
192         /* POSIX flavour locks never conflict here - this is only called
193            in the read/write path. */
194
195         if (lck1->lock_flav == POSIX_LOCK && lck2->lock_flav == POSIX_LOCK)
196                 return False;
197
198         /*
199          * Incoming WRITE locks conflict with existing READ locks even
200          * if the context is the same. JRA. See LOCKTEST7 in smbtorture.
201          */
202
203         if (!(lck2->lock_type == WRITE_LOCK && lck1->lock_type == READ_LOCK)) {
204                 if (brl_same_context(&lck1->context, &lck2->context) &&
205                                         lck1->fnum == lck2->fnum)
206                         return False;
207         }
208
209         return brl_overlap(lck1, lck2);
210
211
212 /****************************************************************************
213  Check if an unlock overlaps a pending lock.
214 ****************************************************************************/
215
216 static BOOL brl_pending_overlap(const struct lock_struct *lock, const struct lock_struct *pend_lock)
217 {
218         if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start))
219                 return True;
220         if ((lock->start >= pend_lock->start) && (lock->start <= pend_lock->start + pend_lock->size))
221                 return True;
222         return False;
223 }
224
225 /****************************************************************************
226  Amazingly enough, w2k3 "remembers" whether the last lock failure on a fnum
227  is the same as this one and changes its error code. I wonder if any
228  app depends on this ?
229 ****************************************************************************/
230
231 static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, BOOL blocking_lock)
232 {
233         if (lock->start >= 0xEF000000 && (lock->start >> 63) == 0) {
234                 /* amazing the little things you learn with a test
235                    suite. Locks beyond this offset (as a 64 bit
236                    number!) always generate the conflict error code,
237                    unless the top bit is set */
238                 if (!blocking_lock) {
239                         fsp->last_lock_failure = *lock;
240                 }
241                 return NT_STATUS_FILE_LOCK_CONFLICT;
242         }
243
244         if (procid_equal(&lock->context.pid, &fsp->last_lock_failure.context.pid) &&
245                         lock->context.tid == fsp->last_lock_failure.context.tid &&
246                         lock->fnum == fsp->last_lock_failure.fnum &&
247                         lock->start == fsp->last_lock_failure.start) {
248                 return NT_STATUS_FILE_LOCK_CONFLICT;
249         }
250
251         if (!blocking_lock) {
252                 fsp->last_lock_failure = *lock;
253         }
254         return NT_STATUS_LOCK_NOT_GRANTED;
255 }
256
257 /****************************************************************************
258  Open up the brlock.tdb database.
259 ****************************************************************************/
260
261 void brl_init(int read_only)
262 {
263         if (brlock_db) {
264                 return;
265         }
266         brlock_db = db_open(NULL, lock_path("brlock.tdb"), 0,
267                             TDB_DEFAULT
268                             |TDB_VOLATILE
269                             |(read_only?0x0:TDB_CLEAR_IF_FIRST),
270                             read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 );
271         if (!brlock_db) {
272                 DEBUG(0,("Failed to open byte range locking database %s\n",
273                         lock_path("brlock.tdb")));
274                 return;
275         }
276 }
277
278 /****************************************************************************
279  Close down the brlock.tdb database.
280 ****************************************************************************/
281
282 void brl_shutdown(int read_only)
283 {
284         if (!brlock_db) {
285                 return;
286         }
287         TALLOC_FREE(brlock_db);
288 }
289
290 #if ZERO_ZERO
291 /****************************************************************************
292  Compare two locks for sorting.
293 ****************************************************************************/
294
295 static int lock_compare(const struct lock_struct *lck1, 
296                          const struct lock_struct *lck2)
297 {
298         if (lck1->start != lck2->start) {
299                 return (lck1->start - lck2->start);
300         }
301         if (lck2->size != lck1->size) {
302                 return ((int)lck1->size - (int)lck2->size);
303         }
304         return 0;
305 }
306 #endif
307
308 /****************************************************************************
309  Lock a range of bytes - Windows lock semantics.
310 ****************************************************************************/
311
312 static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
313                         struct lock_struct *plock, BOOL blocking_lock)
314 {
315         unsigned int i;
316         files_struct *fsp = br_lck->fsp;
317         struct lock_struct *locks = br_lck->lock_data;
318
319         for (i=0; i < br_lck->num_locks; i++) {
320                 /* Do any Windows or POSIX locks conflict ? */
321                 if (brl_conflict(&locks[i], plock)) {
322                         /* Remember who blocked us. */
323                         plock->context.smbpid = locks[i].context.smbpid;
324                         return brl_lock_failed(fsp,plock,blocking_lock);
325                 }
326 #if ZERO_ZERO
327                 if (plock->start == 0 && plock->size == 0 && 
328                                 locks[i].size == 0) {
329                         break;
330                 }
331 #endif
332         }
333
334         /* We can get the Windows lock, now see if it needs to
335            be mapped into a lower level POSIX one, and if so can
336            we get it ? */
337
338         if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(fsp->conn->params)) {
339                 int errno_ret;
340                 if (!set_posix_lock_windows_flavour(fsp,
341                                 plock->start,
342                                 plock->size,
343                                 plock->lock_type,
344                                 &plock->context,
345                                 locks,
346                                 br_lck->num_locks,
347                                 &errno_ret)) {
348
349                         /* We don't know who blocked us. */
350                         plock->context.smbpid = 0xFFFFFFFF;
351
352                         if (errno_ret == EACCES || errno_ret == EAGAIN) {
353                                 return NT_STATUS_FILE_LOCK_CONFLICT;
354                         } else {
355                                 return map_nt_error_from_unix(errno);
356                         }
357                 }
358         }
359
360         /* no conflicts - add it to the list of locks */
361         locks = (struct lock_struct *)SMB_REALLOC(locks, (br_lck->num_locks + 1) * sizeof(*locks));
362         if (!locks) {
363                 return NT_STATUS_NO_MEMORY;
364         }
365
366         memcpy(&locks[br_lck->num_locks], plock, sizeof(struct lock_struct));
367         br_lck->num_locks += 1;
368         br_lck->lock_data = locks;
369         br_lck->modified = True;
370
371         return NT_STATUS_OK;
372 }
373
374 /****************************************************************************
375  Cope with POSIX range splits and merges.
376 ****************************************************************************/
377
378 static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr,               /* Output array. */
379                                                 const struct lock_struct *ex,           /* existing lock. */
380                                                 const struct lock_struct *plock,        /* proposed lock. */
381                                                 BOOL *lock_was_added)
382 {
383         BOOL lock_types_differ = (ex->lock_type != plock->lock_type);
384
385         /* We can't merge non-conflicting locks on different context - ignore fnum. */
386
387         if (!brl_same_context(&ex->context, &plock->context)) {
388                 /* Just copy. */
389                 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
390                 return 1;
391         }
392
393         /* We now know we have the same context. */
394
395         /* Did we overlap ? */
396
397 /*********************************************
398                                              +---------+
399                                              | ex      |
400                                              +---------+
401                               +-------+
402                               | plock |
403                               +-------+
404 OR....
405              +---------+
406              |  ex     |
407              +---------+
408 **********************************************/
409
410         if ( (ex->start > (plock->start + plock->size)) ||
411                         (plock->start > (ex->start + ex->size))) {
412                 /* No overlap with this lock - copy existing. */
413                 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
414                 return 1;
415         }
416
417 /*********************************************
418         +---------------------------+
419         |          ex               |
420         +---------------------------+
421         +---------------------------+
422         |       plock               | -> replace with plock.
423         +---------------------------+
424 **********************************************/
425
426         if ( (ex->start >= plock->start) &&
427                         (ex->start + ex->size <= plock->start + plock->size) ) {
428                 memcpy(&lck_arr[0], plock, sizeof(struct lock_struct));
429                 *lock_was_added = True;
430                 return 1;
431         }
432
433 /*********************************************
434         +-----------------------+
435         |          ex           |
436         +-----------------------+
437         +---------------+
438         |   plock       |
439         +---------------+
440 OR....
441                         +-------+
442                         |  ex   |
443                         +-------+
444         +---------------+
445         |   plock       |
446         +---------------+
447
448 BECOMES....
449         +---------------+-------+
450         |   plock       | ex    | - different lock types.
451         +---------------+-------+
452 OR.... (merge)
453         +-----------------------+
454         |   ex                  | - same lock type.
455         +-----------------------+
456 **********************************************/
457
458         if ( (ex->start >= plock->start) &&
459                                 (ex->start <= plock->start + plock->size) &&
460                                 (ex->start + ex->size > plock->start + plock->size) ) {
461
462                 *lock_was_added = True;
463
464                 /* If the lock types are the same, we merge, if different, we
465                    add the new lock before the old. */
466
467                 if (lock_types_differ) {
468                         /* Add new. */
469                         memcpy(&lck_arr[0], plock, sizeof(struct lock_struct));
470                         memcpy(&lck_arr[1], ex, sizeof(struct lock_struct));
471                         /* Adjust existing start and size. */
472                         lck_arr[1].start = plock->start + plock->size;
473                         lck_arr[1].size = (ex->start + ex->size) - (plock->start + plock->size);
474                         return 2;
475                 } else {
476                         /* Merge. */
477                         memcpy(&lck_arr[0], plock, sizeof(struct lock_struct));
478                         /* Set new start and size. */
479                         lck_arr[0].start = plock->start;
480                         lck_arr[0].size = (ex->start + ex->size) - plock->start;
481                         return 1;
482                 }
483         }
484
485 /*********************************************
486    +-----------------------+
487    |  ex                   |
488    +-----------------------+
489            +---------------+
490            |   plock       |
491            +---------------+
492 OR....
493    +-------+        
494    |  ex   |
495    +-------+
496            +---------------+
497            |   plock       |
498            +---------------+
499 BECOMES....
500    +-------+---------------+
501    | ex    |   plock       | - different lock types
502    +-------+---------------+
503
504 OR.... (merge)
505    +-----------------------+
506    | ex                    | - same lock type.
507    +-----------------------+
508
509 **********************************************/
510
511         if ( (ex->start < plock->start) &&
512                         (ex->start + ex->size >= plock->start) &&
513                         (ex->start + ex->size <= plock->start + plock->size) ) {
514
515                 *lock_was_added = True;
516
517                 /* If the lock types are the same, we merge, if different, we
518                    add the new lock after the old. */
519
520                 if (lock_types_differ) {
521                         memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
522                         memcpy(&lck_arr[1], plock, sizeof(struct lock_struct));
523                         /* Adjust existing size. */
524                         lck_arr[0].size = plock->start - ex->start;
525                         return 2;
526                 } else {
527                         /* Merge. */
528                         memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
529                         /* Adjust existing size. */
530                         lck_arr[0].size = (plock->start + plock->size) - ex->start;
531                         return 1;
532                 }
533         }
534
535 /*********************************************
536         +---------------------------+
537         |        ex                 |
538         +---------------------------+
539                 +---------+
540                 |  plock  |
541                 +---------+
542 BECOMES.....
543         +-------+---------+---------+
544         | ex    |  plock  | ex      | - different lock types.
545         +-------+---------+---------+
546 OR
547         +---------------------------+
548         |        ex                 | - same lock type.
549         +---------------------------+
550 **********************************************/
551
552         if ( (ex->start < plock->start) && (ex->start + ex->size > plock->start + plock->size) ) {
553                 *lock_was_added = True;
554
555                 if (lock_types_differ) {
556
557                         /* We have to split ex into two locks here. */
558
559                         memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
560                         memcpy(&lck_arr[1], plock, sizeof(struct lock_struct));
561                         memcpy(&lck_arr[2], ex, sizeof(struct lock_struct));
562
563                         /* Adjust first existing size. */
564                         lck_arr[0].size = plock->start - ex->start;
565
566                         /* Adjust second existing start and size. */
567                         lck_arr[2].start = plock->start + plock->size;
568                         lck_arr[2].size = (ex->start + ex->size) - (plock->start + plock->size);
569                         return 3;
570                 } else {
571                         /* Just eat plock. */
572                         memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
573                         return 1;
574                 }
575         }
576
577         /* Never get here. */
578         smb_panic("brlock_posix_split_merge");
579         /* Notreached. */
580
581         /* Keep some compilers happy. */
582         return 0;
583 }
584
585 /****************************************************************************
586  Lock a range of bytes - POSIX lock semantics.
587  We must cope with range splits and merges.
588 ****************************************************************************/
589
590 static NTSTATUS brl_lock_posix(struct messaging_context *msg_ctx,
591                                struct byte_range_lock *br_lck,
592                                struct lock_struct *plock)
593 {
594         unsigned int i, count;
595         struct lock_struct *locks = br_lck->lock_data;
596         struct lock_struct *tp;
597         BOOL lock_was_added = False;
598         BOOL signal_pending_read = False;
599
600         /* No zero-zero locks for POSIX. */
601         if (plock->start == 0 && plock->size == 0) {
602                 return NT_STATUS_INVALID_PARAMETER;
603         }
604
605         /* Don't allow 64-bit lock wrap. */
606         if (plock->start + plock->size < plock->start ||
607                         plock->start + plock->size < plock->size) {
608                 return NT_STATUS_INVALID_PARAMETER;
609         }
610
611         /* The worst case scenario here is we have to split an
612            existing POSIX lock range into two, and add our lock,
613            so we need at most 2 more entries. */
614
615         tp = SMB_MALLOC_ARRAY(struct lock_struct, (br_lck->num_locks + 2));
616         if (!tp) {
617                 return NT_STATUS_NO_MEMORY;
618         }
619         
620         count = 0;
621         for (i=0; i < br_lck->num_locks; i++) {
622                 struct lock_struct *curr_lock = &locks[i];
623
624                 /* If we have a pending read lock, a lock downgrade should
625                    trigger a lock re-evaluation. */
626                 if (curr_lock->lock_type == PENDING_READ_LOCK &&
627                                 brl_pending_overlap(plock, curr_lock)) {
628                         signal_pending_read = True;
629                 }
630
631                 if (curr_lock->lock_flav == WINDOWS_LOCK) {
632                         /* Do any Windows flavour locks conflict ? */
633                         if (brl_conflict(curr_lock, plock)) {
634                                 /* No games with error messages. */
635                                 SAFE_FREE(tp);
636                                 /* Remember who blocked us. */
637                                 plock->context.smbpid = curr_lock->context.smbpid;
638                                 return NT_STATUS_FILE_LOCK_CONFLICT;
639                         }
640                         /* Just copy the Windows lock into the new array. */
641                         memcpy(&tp[count], curr_lock, sizeof(struct lock_struct));
642                         count++;
643                 } else {
644                         /* POSIX conflict semantics are different. */
645                         if (brl_conflict_posix(curr_lock, plock)) {
646                                 /* Can't block ourselves with POSIX locks. */
647                                 /* No games with error messages. */
648                                 SAFE_FREE(tp);
649                                 /* Remember who blocked us. */
650                                 plock->context.smbpid = curr_lock->context.smbpid;
651                                 return NT_STATUS_FILE_LOCK_CONFLICT;
652                         }
653
654                         /* Work out overlaps. */
655                         count += brlock_posix_split_merge(&tp[count], curr_lock, plock, &lock_was_added);
656                 }
657         }
658
659         if (!lock_was_added) {
660                 memcpy(&tp[count], plock, sizeof(struct lock_struct));
661                 count++;
662         }
663
664         /* We can get the POSIX lock, now see if it needs to
665            be mapped into a lower level POSIX one, and if so can
666            we get it ? */
667
668         if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(br_lck->fsp->conn->params)) {
669                 int errno_ret;
670
671                 /* The lower layer just needs to attempt to
672                    get the system POSIX lock. We've weeded out
673                    any conflicts above. */
674
675                 if (!set_posix_lock_posix_flavour(br_lck->fsp,
676                                 plock->start,
677                                 plock->size,
678                                 plock->lock_type,
679                                 &errno_ret)) {
680
681                         /* We don't know who blocked us. */
682                         plock->context.smbpid = 0xFFFFFFFF;
683
684                         if (errno_ret == EACCES || errno_ret == EAGAIN) {
685                                 SAFE_FREE(tp);
686                                 return NT_STATUS_FILE_LOCK_CONFLICT;
687                         } else {
688                                 SAFE_FREE(tp);
689                                 return map_nt_error_from_unix(errno);
690                         }
691                 }
692         }
693
694         /* Realloc so we don't leak entries per lock call. */
695         tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks));
696         if (!tp) {
697                 return NT_STATUS_NO_MEMORY;
698         }
699         br_lck->num_locks = count;
700         SAFE_FREE(br_lck->lock_data);
701         br_lck->lock_data = tp;
702         locks = tp;
703         br_lck->modified = True;
704
705         /* A successful downgrade from write to read lock can trigger a lock
706            re-evalutation where waiting readers can now proceed. */
707
708         if (signal_pending_read) {
709                 /* Send unlock messages to any pending read waiters that overlap. */
710                 for (i=0; i < br_lck->num_locks; i++) {
711                         struct lock_struct *pend_lock = &locks[i];
712
713                         /* Ignore non-pending locks. */
714                         if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
715                                 continue;
716                         }
717
718                         if (pend_lock->lock_type == PENDING_READ_LOCK &&
719                                         brl_pending_overlap(plock, pend_lock)) {
720                                 DEBUG(10,("brl_lock_posix: sending unlock message to pid %s\n",
721                                         procid_str_static(&pend_lock->context.pid )));
722
723                                 messaging_send(msg_ctx, pend_lock->context.pid,
724                                                MSG_SMB_UNLOCK, &data_blob_null);
725                         }
726                 }
727         }
728
729         return NT_STATUS_OK;
730 }
731
732 /****************************************************************************
733  Lock a range of bytes.
734 ****************************************************************************/
735
736 NTSTATUS brl_lock(struct messaging_context *msg_ctx,
737                 struct byte_range_lock *br_lck,
738                 uint32 smbpid,
739                 struct server_id pid,
740                 br_off start,
741                 br_off size, 
742                 enum brl_type lock_type,
743                 enum brl_flavour lock_flav,
744                 BOOL blocking_lock,
745                 uint32 *psmbpid)
746 {
747         NTSTATUS ret;
748         struct lock_struct lock;
749
750 #if !ZERO_ZERO
751         if (start == 0 && size == 0) {
752                 DEBUG(0,("client sent 0/0 lock - please report this\n"));
753         }
754 #endif
755
756         lock.context.smbpid = smbpid;
757         lock.context.pid = pid;
758         lock.context.tid = br_lck->fsp->conn->cnum;
759         lock.start = start;
760         lock.size = size;
761         lock.fnum = br_lck->fsp->fnum;
762         lock.lock_type = lock_type;
763         lock.lock_flav = lock_flav;
764
765         if (lock_flav == WINDOWS_LOCK) {
766                 ret = brl_lock_windows(br_lck, &lock, blocking_lock);
767         } else {
768                 ret = brl_lock_posix(msg_ctx, br_lck, &lock);
769         }
770
771 #if ZERO_ZERO
772         /* sort the lock list */
773         qsort(br_lck->lock_data, (size_t)br_lck->num_locks, sizeof(lock), lock_compare);
774 #endif
775
776         /* If we're returning an error, return who blocked us. */
777         if (!NT_STATUS_IS_OK(ret) && psmbpid) {
778                 *psmbpid = lock.context.smbpid;
779         }
780         return ret;
781 }
782
783 /****************************************************************************
784  Unlock a range of bytes - Windows semantics.
785 ****************************************************************************/
786
787 static BOOL brl_unlock_windows(struct messaging_context *msg_ctx,
788                                struct byte_range_lock *br_lck,
789                                const struct lock_struct *plock)
790 {
791         unsigned int i, j;
792         struct lock_struct *locks = br_lck->lock_data;
793         enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */
794
795 #if ZERO_ZERO
796         /* Delete write locks by preference... The lock list
797            is sorted in the zero zero case. */
798
799         for (i = 0; i < br_lck->num_locks; i++) {
800                 struct lock_struct *lock = &locks[i];
801
802                 if (lock->lock_type == WRITE_LOCK &&
803                     brl_same_context(&lock->context, &plock->context) &&
804                     lock->fnum == plock->fnum &&
805                     lock->lock_flav == WINDOWS_LOCK &&
806                     lock->start == plock->start &&
807                     lock->size == plock->size) {
808
809                         /* found it - delete it */
810                         deleted_lock_type = lock->lock_type;
811                         break;
812                 }
813         }
814
815         if (i != br_lck->num_locks) {
816                 /* We found it - don't search again. */
817                 goto unlock_continue;
818         }
819 #endif
820
821         for (i = 0; i < br_lck->num_locks; i++) {
822                 struct lock_struct *lock = &locks[i];
823
824                 /* Only remove our own locks that match in start, size, and flavour. */
825                 if (brl_same_context(&lock->context, &plock->context) &&
826                                         lock->fnum == plock->fnum &&
827                                         lock->lock_flav == WINDOWS_LOCK &&
828                                         lock->start == plock->start &&
829                                         lock->size == plock->size ) {
830                         deleted_lock_type = lock->lock_type;
831                         break;
832                 }
833         }
834
835         if (i == br_lck->num_locks) {
836                 /* we didn't find it */
837                 return False;
838         }
839
840 #if ZERO_ZERO
841   unlock_continue:
842 #endif
843
844         /* Actually delete the lock. */
845         if (i < br_lck->num_locks - 1) {
846                 memmove(&locks[i], &locks[i+1], 
847                         sizeof(*locks)*((br_lck->num_locks-1) - i));
848         }
849
850         br_lck->num_locks -= 1;
851         br_lck->modified = True;
852
853         /* Unlock the underlying POSIX regions. */
854         if(lp_posix_locking(br_lck->fsp->conn->params)) {
855                 release_posix_lock_windows_flavour(br_lck->fsp,
856                                 plock->start,
857                                 plock->size,
858                                 deleted_lock_type,
859                                 &plock->context,
860                                 locks,
861                                 br_lck->num_locks);
862         }
863
864         /* Send unlock messages to any pending waiters that overlap. */
865         for (j=0; j < br_lck->num_locks; j++) {
866                 struct lock_struct *pend_lock = &locks[j];
867
868                 /* Ignore non-pending locks. */
869                 if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
870                         continue;
871                 }
872
873                 /* We could send specific lock info here... */
874                 if (brl_pending_overlap(plock, pend_lock)) {
875                         DEBUG(10,("brl_unlock: sending unlock message to pid %s\n",
876                                 procid_str_static(&pend_lock->context.pid )));
877
878                         messaging_send(msg_ctx, pend_lock->context.pid,
879                                        MSG_SMB_UNLOCK, &data_blob_null);
880                 }
881         }
882
883         return True;
884 }
885
886 /****************************************************************************
887  Unlock a range of bytes - POSIX semantics.
888 ****************************************************************************/
889
890 static BOOL brl_unlock_posix(struct messaging_context *msg_ctx,
891                              struct byte_range_lock *br_lck,
892                              const struct lock_struct *plock)
893 {
894         unsigned int i, j, count;
895         struct lock_struct *tp;
896         struct lock_struct *locks = br_lck->lock_data;
897         BOOL overlap_found = False;
898
899         /* No zero-zero locks for POSIX. */
900         if (plock->start == 0 && plock->size == 0) {
901                 return False;
902         }
903
904         /* Don't allow 64-bit lock wrap. */
905         if (plock->start + plock->size < plock->start ||
906                         plock->start + plock->size < plock->size) {
907                 DEBUG(10,("brl_unlock_posix: lock wrap\n"));
908                 return False;
909         }
910
911         /* The worst case scenario here is we have to split an
912            existing POSIX lock range into two, so we need at most
913            1 more entry. */
914
915         tp = SMB_MALLOC_ARRAY(struct lock_struct, (br_lck->num_locks + 1));
916         if (!tp) {
917                 DEBUG(10,("brl_unlock_posix: malloc fail\n"));
918                 return False;
919         }
920
921         count = 0;
922         for (i = 0; i < br_lck->num_locks; i++) {
923                 struct lock_struct *lock = &locks[i];
924                 struct lock_struct tmp_lock[3];
925                 BOOL lock_was_added = False;
926                 unsigned int tmp_count;
927
928                 /* Only remove our own locks - ignore fnum. */
929                 if (IS_PENDING_LOCK(lock->lock_type) ||
930                                 !brl_same_context(&lock->context, &plock->context)) {
931                         memcpy(&tp[count], lock, sizeof(struct lock_struct));
932                         count++;
933                         continue;
934                 }
935
936                 /* Work out overlaps. */
937                 tmp_count = brlock_posix_split_merge(&tmp_lock[0], &locks[i], plock, &lock_was_added);
938
939                 if (tmp_count == 1) {
940                         /* Ether the locks didn't overlap, or the unlock completely
941                            overlapped this lock. If it didn't overlap, then there's
942                            no change in the locks. */
943                         if (tmp_lock[0].lock_type != UNLOCK_LOCK) {
944                                 SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type);
945                                 /* No change in this lock. */
946                                 memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct));
947                                 count++;
948                         } else {
949                                 SMB_ASSERT(tmp_lock[0].lock_type == UNLOCK_LOCK);
950                                 overlap_found = True;
951                         }
952                         continue;
953                 } else if (tmp_count == 2) {
954                         /* The unlock overlapped an existing lock. Copy the truncated
955                            lock into the lock array. */
956                         if (tmp_lock[0].lock_type != UNLOCK_LOCK) {
957                                 SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type);
958                                 SMB_ASSERT(tmp_lock[1].lock_type == UNLOCK_LOCK);
959                                 memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct));
960                                 if (tmp_lock[0].size != locks[i].size) {
961                                         overlap_found = True;
962                                 }
963                         } else {
964                                 SMB_ASSERT(tmp_lock[0].lock_type == UNLOCK_LOCK);
965                                 SMB_ASSERT(tmp_lock[1].lock_type == locks[i].lock_type);
966                                 memcpy(&tp[count], &tmp_lock[1], sizeof(struct lock_struct));
967                                 if (tmp_lock[1].start != locks[i].start) {
968                                         overlap_found = True;
969                                 }
970                         }
971                         count++;
972                         continue;
973                 } else {
974                         /* tmp_count == 3 - (we split a lock range in two). */
975                         SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type);
976                         SMB_ASSERT(tmp_lock[1].lock_type == UNLOCK_LOCK);
977                         SMB_ASSERT(tmp_lock[2].lock_type == locks[i].lock_type);
978
979                         memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct));
980                         count++;
981                         memcpy(&tp[count], &tmp_lock[2], sizeof(struct lock_struct));
982                         count++;
983                         overlap_found = True;
984                         /* Optimisation... */
985                         /* We know we're finished here as we can't overlap any
986                            more POSIX locks. Copy the rest of the lock array. */
987                         if (i < br_lck->num_locks - 1) {
988                                 memcpy(&tp[count], &locks[i+1], 
989                                         sizeof(*locks)*((br_lck->num_locks-1) - i));
990                                 count += ((br_lck->num_locks-1) - i);
991                         }
992                         break;
993                 }
994         }
995
996         if (!overlap_found) {
997                 /* Just ignore - no change. */
998                 SAFE_FREE(tp);
999                 DEBUG(10,("brl_unlock_posix: No overlap - unlocked.\n"));
1000                 return True;
1001         }
1002
1003         /* Unlock any POSIX regions. */
1004         if(lp_posix_locking(br_lck->fsp->conn->params)) {
1005                 release_posix_lock_posix_flavour(br_lck->fsp,
1006                                                 plock->start,
1007                                                 plock->size,
1008                                                 &plock->context,
1009                                                 tp,
1010                                                 count);
1011         }
1012
1013         /* Realloc so we don't leak entries per unlock call. */
1014         if (count) {
1015                 tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks));
1016                 if (!tp) {
1017                         DEBUG(10,("brl_unlock_posix: realloc fail\n"));
1018                         return False;
1019                 }
1020         } else {
1021                 /* We deleted the last lock. */
1022                 SAFE_FREE(tp);
1023                 tp = NULL;
1024         }
1025
1026         br_lck->num_locks = count;
1027         SAFE_FREE(br_lck->lock_data);
1028         locks = tp;
1029         br_lck->lock_data = tp;
1030         br_lck->modified = True;
1031
1032         /* Send unlock messages to any pending waiters that overlap. */
1033
1034         for (j=0; j < br_lck->num_locks; j++) {
1035                 struct lock_struct *pend_lock = &locks[j];
1036
1037                 /* Ignore non-pending locks. */
1038                 if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
1039                         continue;
1040                 }
1041
1042                 /* We could send specific lock info here... */
1043                 if (brl_pending_overlap(plock, pend_lock)) {
1044                         DEBUG(10,("brl_unlock: sending unlock message to pid %s\n",
1045                                 procid_str_static(&pend_lock->context.pid )));
1046
1047                         messaging_send(msg_ctx, pend_lock->context.pid,
1048                                        MSG_SMB_UNLOCK, &data_blob_null);
1049                 }
1050         }
1051
1052         return True;
1053 }
1054
1055 /****************************************************************************
1056  Unlock a range of bytes.
1057 ****************************************************************************/
1058
1059 BOOL brl_unlock(struct messaging_context *msg_ctx,
1060                 struct byte_range_lock *br_lck,
1061                 uint32 smbpid,
1062                 struct server_id pid,
1063                 br_off start,
1064                 br_off size,
1065                 enum brl_flavour lock_flav)
1066 {
1067         struct lock_struct lock;
1068
1069         lock.context.smbpid = smbpid;
1070         lock.context.pid = pid;
1071         lock.context.tid = br_lck->fsp->conn->cnum;
1072         lock.start = start;
1073         lock.size = size;
1074         lock.fnum = br_lck->fsp->fnum;
1075         lock.lock_type = UNLOCK_LOCK;
1076         lock.lock_flav = lock_flav;
1077
1078         if (lock_flav == WINDOWS_LOCK) {
1079                 return brl_unlock_windows(msg_ctx, br_lck, &lock);
1080         } else {
1081                 return brl_unlock_posix(msg_ctx, br_lck, &lock);
1082         }
1083 }
1084
1085 /****************************************************************************
1086  Test if we could add a lock if we wanted to.
1087  Returns True if the region required is currently unlocked, False if locked.
1088 ****************************************************************************/
1089
1090 BOOL brl_locktest(struct byte_range_lock *br_lck,
1091                 uint32 smbpid,
1092                 struct server_id pid,
1093                 br_off start,
1094                 br_off size, 
1095                 enum brl_type lock_type,
1096                 enum brl_flavour lock_flav)
1097 {
1098         BOOL ret = True;
1099         unsigned int i;
1100         struct lock_struct lock;
1101         const struct lock_struct *locks = br_lck->lock_data;
1102         files_struct *fsp = br_lck->fsp;
1103
1104         lock.context.smbpid = smbpid;
1105         lock.context.pid = pid;
1106         lock.context.tid = br_lck->fsp->conn->cnum;
1107         lock.start = start;
1108         lock.size = size;
1109         lock.fnum = fsp->fnum;
1110         lock.lock_type = lock_type;
1111         lock.lock_flav = lock_flav;
1112
1113         /* Make sure existing locks don't conflict */
1114         for (i=0; i < br_lck->num_locks; i++) {
1115                 /*
1116                  * Our own locks don't conflict.
1117                  */
1118                 if (brl_conflict_other(&locks[i], &lock)) {
1119                         return False;
1120                 }
1121         }
1122
1123         /*
1124          * There is no lock held by an SMB daemon, check to
1125          * see if there is a POSIX lock from a UNIX or NFS process.
1126          * This only conflicts with Windows locks, not POSIX locks.
1127          */
1128
1129         if(lp_posix_locking(fsp->conn->params) && (lock_flav == WINDOWS_LOCK)) {
1130                 ret = is_posix_locked(fsp, &start, &size, &lock_type, WINDOWS_LOCK);
1131
1132                 DEBUG(10,("brl_locktest: posix start=%.0f len=%.0f %s for fnum %d file %s\n",
1133                         (double)start, (double)size, ret ? "locked" : "unlocked",
1134                         fsp->fnum, fsp->fsp_name ));
1135
1136                 /* We need to return the inverse of is_posix_locked. */
1137                 ret = !ret;
1138         }
1139
1140         /* no conflicts - we could have added it */
1141         return ret;
1142 }
1143
1144 /****************************************************************************
1145  Query for existing locks.
1146 ****************************************************************************/
1147
1148 NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
1149                 uint32 *psmbpid,
1150                 struct server_id pid,
1151                 br_off *pstart,
1152                 br_off *psize, 
1153                 enum brl_type *plock_type,
1154                 enum brl_flavour lock_flav)
1155 {
1156         unsigned int i;
1157         struct lock_struct lock;
1158         const struct lock_struct *locks = br_lck->lock_data;
1159         files_struct *fsp = br_lck->fsp;
1160
1161         lock.context.smbpid = *psmbpid;
1162         lock.context.pid = pid;
1163         lock.context.tid = br_lck->fsp->conn->cnum;
1164         lock.start = *pstart;
1165         lock.size = *psize;
1166         lock.fnum = fsp->fnum;
1167         lock.lock_type = *plock_type;
1168         lock.lock_flav = lock_flav;
1169
1170         /* Make sure existing locks don't conflict */
1171         for (i=0; i < br_lck->num_locks; i++) {
1172                 const struct lock_struct *exlock = &locks[i];
1173                 BOOL conflict = False;
1174
1175                 if (exlock->lock_flav == WINDOWS_LOCK) {
1176                         conflict = brl_conflict(exlock, &lock);
1177                 } else {        
1178                         conflict = brl_conflict_posix(exlock, &lock);
1179                 }
1180
1181                 if (conflict) {
1182                         *psmbpid = exlock->context.smbpid;
1183                         *pstart = exlock->start;
1184                         *psize = exlock->size;
1185                         *plock_type = exlock->lock_type;
1186                         return NT_STATUS_LOCK_NOT_GRANTED;
1187                 }
1188         }
1189
1190         /*
1191          * There is no lock held by an SMB daemon, check to
1192          * see if there is a POSIX lock from a UNIX or NFS process.
1193          */
1194
1195         if(lp_posix_locking(fsp->conn->params)) {
1196                 BOOL ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK);
1197
1198                 DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for fnum %d file %s\n",
1199                         (double)*pstart, (double)*psize, ret ? "locked" : "unlocked",
1200                         fsp->fnum, fsp->fsp_name ));
1201
1202                 if (ret) {
1203                         /* Hmmm. No clue what to set smbpid to - use -1. */
1204                         *psmbpid = 0xFFFF;
1205                         return NT_STATUS_LOCK_NOT_GRANTED;
1206                 }
1207         }
1208
1209         return NT_STATUS_OK;
1210 }
1211
1212 /****************************************************************************
1213  Remove a particular pending lock.
1214 ****************************************************************************/
1215
1216 BOOL brl_lock_cancel(struct byte_range_lock *br_lck,
1217                 uint32 smbpid,
1218                 struct server_id pid,
1219                 br_off start,
1220                 br_off size,
1221                 enum brl_flavour lock_flav)
1222 {
1223         unsigned int i;
1224         struct lock_struct *locks = br_lck->lock_data;
1225         struct lock_context context;
1226
1227         context.smbpid = smbpid;
1228         context.pid = pid;
1229         context.tid = br_lck->fsp->conn->cnum;
1230
1231         for (i = 0; i < br_lck->num_locks; i++) {
1232                 struct lock_struct *lock = &locks[i];
1233
1234                 /* For pending locks we *always* care about the fnum. */
1235                 if (brl_same_context(&lock->context, &context) &&
1236                                 lock->fnum == br_lck->fsp->fnum &&
1237                                 IS_PENDING_LOCK(lock->lock_type) &&
1238                                 lock->lock_flav == lock_flav &&
1239                                 lock->start == start &&
1240                                 lock->size == size) {
1241                         break;
1242                 }
1243         }
1244
1245         if (i == br_lck->num_locks) {
1246                 /* Didn't find it. */
1247                 return False;
1248         }
1249
1250         if (i < br_lck->num_locks - 1) {
1251                 /* Found this particular pending lock - delete it */
1252                 memmove(&locks[i], &locks[i+1], 
1253                         sizeof(*locks)*((br_lck->num_locks-1) - i));
1254         }
1255
1256         br_lck->num_locks -= 1;
1257         br_lck->modified = True;
1258         return True;
1259 }
1260
1261 /****************************************************************************
1262  Remove any locks associated with a open file.
1263  We return True if this process owns any other Windows locks on this
1264  fd and so we should not immediately close the fd.
1265 ****************************************************************************/
1266
1267 void brl_close_fnum(struct messaging_context *msg_ctx,
1268                     struct byte_range_lock *br_lck)
1269 {
1270         files_struct *fsp = br_lck->fsp;
1271         uint16 tid = fsp->conn->cnum;
1272         int fnum = fsp->fnum;
1273         unsigned int i, j, dcount=0;
1274         int num_deleted_windows_locks = 0;
1275         struct lock_struct *locks = br_lck->lock_data;
1276         struct server_id pid = procid_self();
1277         BOOL unlock_individually = False;
1278
1279         if(lp_posix_locking(fsp->conn->params)) {
1280
1281                 /* Check if there are any Windows locks associated with this dev/ino
1282                    pair that are not this fnum. If so we need to call unlock on each
1283                    one in order to release the system POSIX locks correctly. */
1284
1285                 for (i=0; i < br_lck->num_locks; i++) {
1286                         struct lock_struct *lock = &locks[i];
1287
1288                         if (!procid_equal(&lock->context.pid, &pid)) {
1289                                 continue;
1290                         }
1291
1292                         if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) {
1293                                 continue; /* Ignore pending. */
1294                         }
1295
1296                         if (lock->context.tid != tid || lock->fnum != fnum) {
1297                                 unlock_individually = True;
1298                                 break;
1299                         }
1300                 }
1301
1302                 if (unlock_individually) {
1303                         struct lock_struct *locks_copy;
1304                         unsigned int num_locks_copy;
1305
1306                         /* Copy the current lock array. */
1307                         if (br_lck->num_locks) {
1308                                 locks_copy = (struct lock_struct *)TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct));
1309                                 if (!locks_copy) {
1310                                         smb_panic("brl_close_fnum: talloc failed");
1311                                 }
1312                         } else {        
1313                                 locks_copy = NULL;
1314                         }
1315
1316                         num_locks_copy = br_lck->num_locks;
1317
1318                         for (i=0; i < num_locks_copy; i++) {
1319                                 struct lock_struct *lock = &locks_copy[i];
1320
1321                                 if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid) &&
1322                                                 (lock->fnum == fnum)) {
1323                                         brl_unlock(msg_ctx,
1324                                                 br_lck,
1325                                                 lock->context.smbpid,
1326                                                 pid,
1327                                                 lock->start,
1328                                                 lock->size,
1329                                                 lock->lock_flav);
1330                                 }
1331                         }
1332                         return;
1333                 }
1334         }
1335
1336         /* We can bulk delete - any POSIX locks will be removed when the fd closes. */
1337
1338         /* Remove any existing locks for this fnum (or any fnum if they're POSIX). */
1339
1340         for (i=0; i < br_lck->num_locks; i++) {
1341                 struct lock_struct *lock = &locks[i];
1342                 BOOL del_this_lock = False;
1343
1344                 if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid)) {
1345                         if ((lock->lock_flav == WINDOWS_LOCK) && (lock->fnum == fnum)) {
1346                                 del_this_lock = True;
1347                                 num_deleted_windows_locks++;
1348                         } else if (lock->lock_flav == POSIX_LOCK) {
1349                                 del_this_lock = True;
1350                         }
1351                 }
1352
1353                 if (del_this_lock) {
1354                         /* Send unlock messages to any pending waiters that overlap. */
1355                         for (j=0; j < br_lck->num_locks; j++) {
1356                                 struct lock_struct *pend_lock = &locks[j];
1357
1358                                 /* Ignore our own or non-pending locks. */
1359                                 if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
1360                                         continue;
1361                                 }
1362
1363                                 /* Optimisation - don't send to this fnum as we're
1364                                    closing it. */
1365                                 if (pend_lock->context.tid == tid &&
1366                                     procid_equal(&pend_lock->context.pid, &pid) &&
1367                                     pend_lock->fnum == fnum) {
1368                                         continue;
1369                                 }
1370
1371                                 /* We could send specific lock info here... */
1372                                 if (brl_pending_overlap(lock, pend_lock)) {
1373                                         messaging_send(msg_ctx, pend_lock->context.pid,
1374                                                        MSG_SMB_UNLOCK, &data_blob_null);
1375                                 }
1376                         }
1377
1378                         /* found it - delete it */
1379                         if (br_lck->num_locks > 1 && i < br_lck->num_locks - 1) {
1380                                 memmove(&locks[i], &locks[i+1], 
1381                                         sizeof(*locks)*((br_lck->num_locks-1) - i));
1382                         }
1383                         br_lck->num_locks--;
1384                         br_lck->modified = True;
1385                         i--;
1386                         dcount++;
1387                 }
1388         }
1389
1390         if(lp_posix_locking(fsp->conn->params) && num_deleted_windows_locks) {
1391                 /* Reduce the Windows lock POSIX reference count on this dev/ino pair. */
1392                 reduce_windows_lock_ref_count(fsp, num_deleted_windows_locks);
1393         }
1394 }
1395
1396 /****************************************************************************
1397  Ensure this set of lock entries is valid.
1398 ****************************************************************************/
1399
1400 static BOOL validate_lock_entries(unsigned int *pnum_entries, struct lock_struct **pplocks)
1401 {
1402         unsigned int i;
1403         unsigned int num_valid_entries = 0;
1404         struct lock_struct *locks = *pplocks;
1405
1406         for (i = 0; i < *pnum_entries; i++) {
1407                 struct lock_struct *lock_data = &locks[i];
1408                 if (!process_exists(lock_data->context.pid)) {
1409                         /* This process no longer exists - mark this
1410                            entry as invalid by zeroing it. */
1411                         ZERO_STRUCTP(lock_data);
1412                 } else {
1413                         num_valid_entries++;
1414                 }
1415         }
1416
1417         if (num_valid_entries != *pnum_entries) {
1418                 struct lock_struct *new_lock_data = NULL;
1419
1420                 if (num_valid_entries) {
1421                         new_lock_data = SMB_MALLOC_ARRAY(struct lock_struct, num_valid_entries);
1422                         if (!new_lock_data) {
1423                                 DEBUG(3, ("malloc fail\n"));
1424                                 return False;
1425                         }
1426
1427                         num_valid_entries = 0;
1428                         for (i = 0; i < *pnum_entries; i++) {
1429                                 struct lock_struct *lock_data = &locks[i];
1430                                 if (lock_data->context.smbpid &&
1431                                                 lock_data->context.tid) {
1432                                         /* Valid (nonzero) entry - copy it. */
1433                                         memcpy(&new_lock_data[num_valid_entries],
1434                                                 lock_data, sizeof(struct lock_struct));
1435                                         num_valid_entries++;
1436                                 }
1437                         }
1438                 }
1439
1440                 SAFE_FREE(*pplocks);
1441                 *pplocks = new_lock_data;
1442                 *pnum_entries = num_valid_entries;
1443         }
1444
1445         return True;
1446 }
1447
1448 struct brl_forall_cb {
1449         void (*fn)(struct file_id id, struct server_id pid,
1450                    enum brl_type lock_type,
1451                    enum brl_flavour lock_flav,
1452                    br_off start, br_off size,
1453                    void *private_data);
1454         void *private_data;
1455 };
1456
1457 /****************************************************************************
1458  Traverse the whole database with this function, calling traverse_callback
1459  on each lock.
1460 ****************************************************************************/
1461
1462 static int traverse_fn(struct db_record *rec, void *state)
1463 {
1464         struct brl_forall_cb *cb = (struct brl_forall_cb *)state;
1465         struct lock_struct *locks;
1466         struct file_id *key;
1467         unsigned int i;
1468         unsigned int num_locks = 0;
1469         unsigned int orig_num_locks = 0;
1470
1471         /* In a traverse function we must make a copy of
1472            dbuf before modifying it. */
1473
1474         locks = (struct lock_struct *)memdup(rec->value.dptr,
1475                                              rec->value.dsize);
1476         if (!locks) {
1477                 return -1; /* Terminate traversal. */
1478         }
1479
1480         key = (struct file_id *)rec->key.dptr;
1481         orig_num_locks = num_locks = rec->value.dsize/sizeof(*locks);
1482
1483         /* Ensure the lock db is clean of entries from invalid processes. */
1484
1485         if (!validate_lock_entries(&num_locks, &locks)) {
1486                 SAFE_FREE(locks);
1487                 return -1; /* Terminate traversal */
1488         }
1489
1490         if (orig_num_locks != num_locks) {
1491                 if (num_locks) {
1492                         TDB_DATA data;
1493                         data.dptr = (uint8_t *)locks;
1494                         data.dsize = num_locks*sizeof(struct lock_struct);
1495                         rec->store(rec, data, TDB_REPLACE);
1496                 } else {
1497                         rec->delete_rec(rec);
1498                 }
1499         }
1500
1501         for ( i=0; i<num_locks; i++) {
1502                 cb->fn(*key,
1503                        locks[i].context.pid,
1504                        locks[i].lock_type,
1505                        locks[i].lock_flav,
1506                        locks[i].start,
1507                        locks[i].size,
1508                        cb->private_data);
1509         }
1510
1511         SAFE_FREE(locks);
1512         return 0;
1513 }
1514
1515 /*******************************************************************
1516  Call the specified function on each lock in the database.
1517 ********************************************************************/
1518
1519 int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
1520                           enum brl_type lock_type,
1521                           enum brl_flavour lock_flav,
1522                           br_off start, br_off size,
1523                           void *private_data),
1524                void *private_data)
1525 {
1526         struct brl_forall_cb cb;
1527
1528         if (!brlock_db) {
1529                 return 0;
1530         }
1531         cb.fn = fn;
1532         cb.private_data = private_data;
1533         return brlock_db->traverse(brlock_db, traverse_fn, &cb);
1534 }
1535
1536 /*******************************************************************
1537  Store a potentially modified set of byte range lock data back into
1538  the database.
1539  Unlock the record.
1540 ********************************************************************/
1541
1542 static int byte_range_lock_destructor(struct byte_range_lock *br_lck)
1543 {
1544         TDB_DATA key;
1545
1546         key.dptr = (uint8 *)&br_lck->key;
1547         key.dsize = sizeof(struct file_id);
1548
1549         if (br_lck->read_only) {
1550                 SMB_ASSERT(!br_lck->modified);
1551         }
1552
1553         if (!br_lck->modified) {
1554                 goto done;
1555         }
1556
1557         if (br_lck->num_locks == 0) {
1558                 /* No locks - delete this entry. */
1559                 NTSTATUS status = br_lck->record->delete_rec(br_lck->record);
1560                 if (!NT_STATUS_IS_OK(status)) {
1561                         DEBUG(0, ("delete_rec returned %s\n",
1562                                   nt_errstr(status)));
1563                         smb_panic("Could not delete byte range lock entry");
1564                 }
1565         } else {
1566                 TDB_DATA data;
1567                 NTSTATUS status;
1568
1569                 data.dptr = (uint8 *)br_lck->lock_data;
1570                 data.dsize = br_lck->num_locks * sizeof(struct lock_struct);
1571
1572                 status = br_lck->record->store(br_lck->record, data,
1573                                                TDB_REPLACE);
1574                 if (!NT_STATUS_IS_OK(status)) {
1575                         DEBUG(0, ("store returned %s\n", nt_errstr(status)));
1576                         smb_panic("Could not store byte range mode entry");
1577                 }
1578         }
1579
1580  done:
1581
1582         SAFE_FREE(br_lck->lock_data);
1583         TALLOC_FREE(br_lck->record);
1584         return 0;
1585 }
1586
1587 /*******************************************************************
1588  Fetch a set of byte range lock data from the database.
1589  Leave the record locked.
1590  TALLOC_FREE(brl) will release the lock in the destructor.
1591 ********************************************************************/
1592
1593 static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx,
1594                                         files_struct *fsp, BOOL read_only)
1595 {
1596         TDB_DATA key, data;
1597         struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock);
1598
1599         if (br_lck == NULL) {
1600                 return NULL;
1601         }
1602
1603         br_lck->fsp = fsp;
1604         br_lck->num_locks = 0;
1605         br_lck->modified = False;
1606         memset(&br_lck->key, '\0', sizeof(struct file_id));
1607         br_lck->key = fsp->file_id;
1608
1609         key.dptr = (uint8 *)&br_lck->key;
1610         key.dsize = sizeof(struct file_id);
1611
1612         if (!fsp->lockdb_clean) {
1613                 /* We must be read/write to clean
1614                    the dead entries. */
1615                 read_only = False;
1616         }
1617
1618         if (read_only) {
1619                 if (brlock_db->fetch(brlock_db, br_lck, key, &data) == -1) {
1620                         DEBUG(3, ("Could not fetch byte range lock record\n"));
1621                         TALLOC_FREE(br_lck);
1622                         return NULL;
1623                 }
1624                 br_lck->record = NULL;
1625         }
1626         else {
1627                 br_lck->record = brlock_db->fetch_locked(brlock_db, br_lck, key);
1628
1629                 if (br_lck->record == NULL) {
1630                         DEBUG(3, ("Could not lock byte range lock entry\n"));
1631                         TALLOC_FREE(br_lck);
1632                         return NULL;
1633                 }
1634
1635                 data = br_lck->record->value;
1636         }
1637
1638         br_lck->read_only = read_only;
1639         br_lck->lock_data = NULL;
1640
1641         talloc_set_destructor(br_lck, byte_range_lock_destructor);
1642
1643         br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
1644
1645         if (br_lck->num_locks != 0) {
1646                 br_lck->lock_data = SMB_MALLOC_ARRAY(struct lock_struct,
1647                                                      br_lck->num_locks);
1648                 if (br_lck->lock_data == NULL) {
1649                         DEBUG(0, ("malloc failed\n"));
1650                         TALLOC_FREE(br_lck);
1651                         return NULL;
1652                 }
1653
1654                 memcpy(br_lck->lock_data, data.dptr, data.dsize);
1655         }
1656         
1657         if (!fsp->lockdb_clean) {
1658                 int orig_num_locks = br_lck->num_locks;
1659
1660                 /* This is the first time we've accessed this. */
1661                 /* Go through and ensure all entries exist - remove any that don't. */
1662                 /* Makes the lockdb self cleaning at low cost. */
1663
1664                 if (!validate_lock_entries(&br_lck->num_locks,
1665                                            &br_lck->lock_data)) {
1666                         SAFE_FREE(br_lck->lock_data);
1667                         TALLOC_FREE(br_lck);
1668                         return NULL;
1669                 }
1670
1671                 /* Ensure invalid locks are cleaned up in the destructor. */
1672                 if (orig_num_locks != br_lck->num_locks) {
1673                         br_lck->modified = True;
1674                 }
1675
1676                 /* Mark the lockdb as "clean" as seen from this open file. */
1677                 fsp->lockdb_clean = True;
1678         }
1679
1680         if (DEBUGLEVEL >= 10) {
1681                 unsigned int i;
1682                 struct lock_struct *locks = br_lck->lock_data;
1683                 DEBUG(10,("brl_get_locks_internal: %u current locks on file_id %s\n",
1684                         br_lck->num_locks,
1685                           file_id_static_string(&fsp->file_id)));
1686                 for( i = 0; i < br_lck->num_locks; i++) {
1687                         print_lock_struct(i, &locks[i]);
1688                 }
1689         }
1690         return br_lck;
1691 }
1692
1693 struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx,
1694                                         files_struct *fsp)
1695 {
1696         return brl_get_locks_internal(mem_ctx, fsp, False);
1697 }
1698
1699 struct byte_range_lock *brl_get_locks_readonly(TALLOC_CTX *mem_ctx,
1700                                         files_struct *fsp)
1701 {
1702         return brl_get_locks_internal(mem_ctx, fsp, True);
1703 }
1704
1705 struct brl_revalidate_state {
1706         ssize_t array_size;
1707         uint32 num_pids;
1708         struct server_id *pids;
1709 };
1710
1711 /*
1712  * Collect PIDs of all processes with pending entries
1713  */
1714
1715 static void brl_revalidate_collect(struct file_id id, struct server_id pid,
1716                                    enum brl_type lock_type,
1717                                    enum brl_flavour lock_flav,
1718                                    br_off start, br_off size,
1719                                    void *private_data)
1720 {
1721         struct brl_revalidate_state *state =
1722                 (struct brl_revalidate_state *)private_data;
1723
1724         if (!IS_PENDING_LOCK(lock_type)) {
1725                 return;
1726         }
1727
1728         add_to_large_array(state, sizeof(pid), (void *)&pid,
1729                            &state->pids, &state->num_pids,
1730                            &state->array_size);
1731 }
1732
1733 /*
1734  * qsort callback to sort the processes
1735  */
1736
1737 static int compare_procids(const void *p1, const void *p2)
1738 {
1739         const struct server_id *i1 = (struct server_id *)p1;
1740         const struct server_id *i2 = (struct server_id *)p2;
1741
1742         if (i1->pid < i2->pid) return -1;
1743         if (i2->pid > i2->pid) return 1;
1744         return 0;
1745 }
1746
1747 /*
1748  * Send a MSG_SMB_UNLOCK message to all processes with pending byte range
1749  * locks so that they retry. Mainly used in the cluster code after a node has
1750  * died.
1751  *
1752  * Done in two steps to avoid double-sends: First we collect all entries in an
1753  * array, then qsort that array and only send to non-dupes.
1754  */
1755
1756 static void brl_revalidate(struct messaging_context *msg_ctx,
1757                            void *private_data,
1758                            uint32_t msg_type,
1759                            struct server_id server_id,
1760                            DATA_BLOB *data)
1761 {
1762         struct brl_revalidate_state *state;
1763         uint32 i;
1764         struct server_id last_pid;
1765
1766         if (!(state = TALLOC_ZERO_P(NULL, struct brl_revalidate_state))) {
1767                 DEBUG(0, ("talloc failed\n"));
1768                 return;
1769         }
1770
1771         brl_forall(brl_revalidate_collect, state);
1772
1773         if (state->array_size == -1) {
1774                 DEBUG(0, ("talloc failed\n"));
1775                 goto done;
1776         }
1777
1778         if (state->num_pids == 0) {
1779                 goto done;
1780         }
1781
1782         qsort(state->pids, state->num_pids, sizeof(state->pids[0]),
1783               compare_procids);
1784
1785         ZERO_STRUCT(last_pid);
1786
1787         for (i=0; i<state->num_pids; i++) {
1788                 if (procid_equal(&last_pid, &state->pids[i])) {
1789                         /*
1790                          * We've seen that one already
1791                          */
1792                         continue;
1793                 }
1794
1795                 messaging_send(msg_ctx, state->pids[i], MSG_SMB_UNLOCK,
1796                                &data_blob_null);
1797                 last_pid = state->pids[i];
1798         }
1799
1800  done:
1801         TALLOC_FREE(state);
1802         return;
1803 }
1804
1805 void brl_register_msgs(struct messaging_context *msg_ctx)
1806 {
1807         messaging_register(msg_ctx, NULL, MSG_SMB_BRL_VALIDATE,
1808                            brl_revalidate);
1809 }