r3360: improved the deletion of tmp files. smbd now puts all tmp files in var/locks...
[bbaumbach/samba-autobuild/.git] / source4 / ntvfs / common / brlock.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    generic byte range locking code
5
6    Copyright (C) Andrew Tridgell 1992-2004
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 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 /* This module implements a tdb based byte range locking service,
25    replacing the fcntl() based byte range locking previously
26    used. This allows us to provide the same semantics as NT */
27
28 #include "includes.h"
29
30 /*
31   in this module a "DATA_BLOB *file_key" is a blob that uniquely identifies
32   a file. For a local posix filesystem this will usually be a combination
33   of the device and inode numbers of the file, but it can be anything 
34   that uniquely idetifies a file for locking purposes, as long
35   as it is applied consistently.
36 */
37
38 /*
39   the lock context contains the elements that define whether one
40   lock is the same as another lock
41 */
42 struct lock_context {
43         servid_t server;
44         uint16_t smbpid;
45         uint16_t tid;
46 };
47
48 /* The data in brlock records is an unsorted linear array of these
49    records.  It is unnecessary to store the count as tdb provides the
50    size of the record */
51 struct lock_struct {
52         struct lock_context context;
53         uint64_t start;
54         uint64_t size;
55         uint16_t fnum;
56         enum brl_type lock_type;
57         void *notify_ptr;
58 };
59
60 struct brl_context {
61         struct tdb_wrap *w;
62         servid_t server;
63         uint16_t tid;
64         struct messaging_context *messaging_ctx;
65         struct lock_struct last_lock_failure;
66 };
67
68
69 /*
70   Open up the brlock.tdb database. Close it down using
71   talloc_free(). We need the messaging_ctx to allow for
72   pending lock notifications.
73 */
74 struct brl_context *brl_init(TALLOC_CTX *mem_ctx, servid_t server, uint16_t tid, 
75                              struct messaging_context *messaging_ctx)
76 {
77         char *path;
78         struct brl_context *brl;
79
80         brl = talloc_p(mem_ctx, struct brl_context);
81         if (brl == NULL) {
82                 return NULL;
83         }
84
85         path = smbd_tmp_path(brl, "brlock.tdb");
86         brl->w = tdb_wrap_open(brl, path, 0,  
87                                TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
88         talloc_free(path);
89         if (brl->w == NULL) {
90                 talloc_free(brl);
91                 return NULL;
92         }
93
94         brl->server = server;
95         brl->tid = tid;
96         brl->messaging_ctx = messaging_ctx;
97         ZERO_STRUCT(brl->last_lock_failure);
98
99         return brl;
100 }
101
102
103 /*
104   see if two locking contexts are equal
105 */
106 static BOOL brl_same_context(struct lock_context *ctx1, struct lock_context *ctx2)
107 {
108         return (ctx1->server == ctx2->server &&
109                 ctx1->smbpid == ctx2->smbpid &&
110                 ctx1->tid == ctx2->tid);
111 }
112
113 /*
114   see if lck1 and lck2 overlap
115 */
116 static BOOL brl_overlap(struct lock_struct *lck1, 
117                         struct lock_struct *lck2)
118 {
119         /* this extra check is not redundent - it copes with locks
120            that go beyond the end of 64 bit file space */
121         if (lck1->size != 0 &&
122             lck1->start == lck2->start &&
123             lck1->size == lck2->size) {
124                 return True;
125         }
126             
127         if (lck1->start >= (lck2->start+lck2->size) ||
128             lck2->start >= (lck1->start+lck1->size)) {
129                 return False;
130         }
131         return True;
132
133
134 /*
135  See if lock2 can be added when lock1 is in place.
136 */
137 static BOOL brl_conflict(struct lock_struct *lck1, 
138                          struct lock_struct *lck2)
139 {
140         /* pending locks don't conflict with anything */
141         if (lck1->lock_type >= PENDING_READ_LOCK ||
142             lck2->lock_type >= PENDING_READ_LOCK) {
143                 return False;
144         }
145
146         if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
147                 return False;
148         }
149
150         if (brl_same_context(&lck1->context, &lck2->context) &&
151             lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) {
152                 return False;
153         }
154
155         return brl_overlap(lck1, lck2);
156
157
158
159 /*
160  Check to see if this lock conflicts, but ignore our own locks on the
161  same fnum only.
162 */
163 static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck2)
164 {
165         /* pending locks don't conflict with anything */
166         if (lck1->lock_type >= PENDING_READ_LOCK ||
167             lck2->lock_type >= PENDING_READ_LOCK) {
168                 return False;
169         }
170
171         if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) 
172                 return False;
173
174         /*
175          * note that incoming write calls conflict with existing READ
176          * locks even if the context is the same. JRA. See LOCKTEST7
177          * in smbtorture.
178          */
179         if (brl_same_context(&lck1->context, &lck2->context) &&
180             lck1->fnum == lck2->fnum &&
181             (lck2->lock_type == READ_LOCK || lck1->lock_type == WRITE_LOCK)) {
182                 return False;
183         }
184
185         return brl_overlap(lck1, lck2);
186
187
188
189 /*
190   amazingly enough, w2k3 "remembers" whether the last lock failure
191   is the same as this one and changes its error code. I wonder if any
192   app depends on this?
193 */
194 static NTSTATUS brl_lock_failed(struct brl_context *brl, struct lock_struct *lock)
195 {
196         if (brl_same_context(&lock->context, &brl->last_lock_failure.context) &&
197             lock->fnum == brl->last_lock_failure.fnum &&
198             lock->start == brl->last_lock_failure.start &&
199             lock->size == brl->last_lock_failure.size) {
200                 return NT_STATUS_FILE_LOCK_CONFLICT;
201         }
202         brl->last_lock_failure = *lock;
203         if (lock->start >= 0xEF000000 && 
204             (lock->start >> 63) == 0) {
205                 /* amazing the little things you learn with a test
206                    suite. Locks beyond this offset (as a 64 bit
207                    number!) always generate the conflict error code,
208                    unless the top bit is set */
209                 return NT_STATUS_FILE_LOCK_CONFLICT;
210         }
211         return NT_STATUS_LOCK_NOT_GRANTED;
212 }
213
214 /*
215   Lock a range of bytes.  The lock_type can be a PENDING_*_LOCK, in
216   which case a real lock is first tried, and if that fails then a
217   pending lock is created. When the pending lock is triggered (by
218   someone else closing an overlapping lock range) a messaging
219   notification is sent, identified by the notify_ptr
220 */
221 NTSTATUS brl_lock(struct brl_context *brl,
222                   DATA_BLOB *file_key, 
223                   uint16_t smbpid,
224                   uint16_t fnum, 
225                   uint64_t start, uint64_t size, 
226                   enum brl_type lock_type,
227                   void *notify_ptr)
228 {
229         TDB_DATA kbuf, dbuf;
230         int count, i;
231         struct lock_struct lock, *locks;
232         char *tp;
233         NTSTATUS status;
234
235         kbuf.dptr = file_key->data;
236         kbuf.dsize = file_key->length;
237
238         if (tdb_chainlock(brl->w->tdb, kbuf) != 0) {
239                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
240         }
241
242         /* if this is a pending lock, then with the chainlock held we
243            try to get the real lock. If we succeed then we don't need
244            to make it pending. This prevents a possible race condition
245            where the pending lock gets created after the lock that is
246            preventing the real lock gets removed */
247         if (lock_type >= PENDING_READ_LOCK) {
248                 enum brl_type rw = (lock_type==PENDING_READ_LOCK? READ_LOCK : WRITE_LOCK);
249                 status = brl_lock(brl, file_key, smbpid, fnum, start, size, rw, NULL);
250                 if (NT_STATUS_IS_OK(status)) {
251                         tdb_chainunlock(brl->w->tdb, kbuf);
252                         return NT_STATUS_OK;
253                 }
254         }
255
256         dbuf = tdb_fetch(brl->w->tdb, kbuf);
257
258         lock.context.smbpid = smbpid;
259         lock.context.server = brl->server;
260         lock.context.tid = brl->tid;
261         lock.start = start;
262         lock.size = size;
263         lock.fnum = fnum;
264         lock.lock_type = lock_type;
265         lock.notify_ptr = notify_ptr;
266
267         if (dbuf.dptr) {
268                 /* there are existing locks - make sure they don't conflict */
269                 locks = (struct lock_struct *)dbuf.dptr;
270                 count = dbuf.dsize / sizeof(*locks);
271                 for (i=0; i<count; i++) {
272                         if (brl_conflict(&locks[i], &lock)) {
273                                 status = brl_lock_failed(brl, &lock);
274                                 goto fail;
275                         }
276                 }
277         }
278
279         /* no conflicts - add it to the list of locks */
280         tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*locks));
281         if (!tp) {
282                 status = NT_STATUS_NO_MEMORY;
283                 goto fail;
284         } else {
285                 dbuf.dptr = tp;
286         }
287         memcpy(dbuf.dptr + dbuf.dsize, &lock, sizeof(lock));
288         dbuf.dsize += sizeof(lock);
289
290         if (tdb_store(brl->w->tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
291                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
292                 goto fail;
293         }
294
295         free(dbuf.dptr);
296         tdb_chainunlock(brl->w->tdb, kbuf);
297
298         /* the caller needs to know if the real lock was granted. If
299            we have reached here then it must be a pending lock that
300            was granted, so tell them the lock failed */
301         if (lock_type >= PENDING_READ_LOCK) {
302                 return brl_lock_failed(brl, &lock);
303         }
304
305         return NT_STATUS_OK;
306
307  fail:
308
309         free(dbuf.dptr);
310         tdb_chainunlock(brl->w->tdb, kbuf);
311         return status;
312 }
313
314
315 /*
316   we are removing a lock that might be holding up a pending lock. Scan for pending
317   locks that cover this range and if we find any then notify the server that it should
318   retry the lock
319 */
320 static void brl_notify_unlock(struct brl_context *brl,
321                               struct lock_struct *locks, int count, 
322                               struct lock_struct *removed_lock)
323 {
324         int i, last_notice;
325
326         /* the last_notice logic is to prevent stampeding on a lock
327            range. It prevents us sending hundreds of notifies on the
328            same range of bytes. It doesn't prevent all possible
329            stampedes, but it does prevent the most common problem */
330         last_notice = -1;
331
332         for (i=0;i<count;i++) {
333                 if (locks[i].lock_type >= PENDING_READ_LOCK &&
334                     brl_overlap(&locks[i], removed_lock)) {
335                         DATA_BLOB data;
336
337                         if (last_notice != -1 && brl_overlap(&locks[i], &locks[last_notice])) {
338                                 continue;
339                         }
340                         if (locks[i].lock_type == PENDING_WRITE_LOCK) {
341                                 last_notice = i;
342                         }
343                         data.data = (void *)&locks[i].notify_ptr;
344                         data.length = sizeof(void *);
345                         messaging_send(brl->messaging_ctx, locks[i].context.server, MSG_BRL_RETRY, &data);
346                 }
347         }
348 }
349
350
351 /*
352   send notifications for all pending locks - the file is being closed by this
353   user
354 */
355 static void brl_notify_all(struct brl_context *brl,
356                            struct lock_struct *locks, int count)
357 {
358         int i;
359         for (i=0;i<count;i++) {
360                 if (locks->lock_type >= PENDING_READ_LOCK) {
361                         brl_notify_unlock(brl, locks, count, &locks[i]);
362                 }
363         }
364 }
365
366
367
368 /*
369  Unlock a range of bytes.
370 */
371 NTSTATUS brl_unlock(struct brl_context *brl,
372                     DATA_BLOB *file_key, 
373                     uint16_t smbpid,
374                     uint16_t fnum,
375                     uint64_t start, uint64_t size)
376 {
377         TDB_DATA kbuf, dbuf;
378         int count, i;
379         struct lock_struct *locks;
380         struct lock_context context;
381         NTSTATUS status;
382
383         kbuf.dptr = file_key->data;
384         kbuf.dsize = file_key->length;
385
386         if (tdb_chainlock(brl->w->tdb, kbuf) != 0) {
387                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
388         }
389
390         dbuf = tdb_fetch(brl->w->tdb, kbuf);
391         if (!dbuf.dptr) {
392                 tdb_chainunlock(brl->w->tdb, kbuf);
393                 return NT_STATUS_RANGE_NOT_LOCKED;
394         }
395
396         context.smbpid = smbpid;
397         context.server = brl->server;
398         context.tid = brl->tid;
399
400         /* there are existing locks - find a match */
401         locks = (struct lock_struct *)dbuf.dptr;
402         count = dbuf.dsize / sizeof(*locks);
403
404         for (i=0; i<count; i++) {
405                 struct lock_struct *lock = &locks[i];
406                 
407                 if (brl_same_context(&lock->context, &context) &&
408                     lock->fnum == fnum &&
409                     lock->start == start &&
410                     lock->size == size &&
411                     lock->notify_ptr == NULL) {
412                         /* found it - delete it */
413                         if (count == 1) {
414                                 if (tdb_delete(brl->w->tdb, kbuf) != 0) {
415                                         status = NT_STATUS_INTERNAL_DB_CORRUPTION;
416                                         goto fail;
417                                 }
418                         } else {
419                                 struct lock_struct removed_lock = *lock;
420                                 if (i < count-1) {
421                                         memmove(&locks[i], &locks[i+1], 
422                                                 sizeof(*locks)*((count-1) - i));
423                                 }
424                                 count--;
425
426                                 /* send notifications for any relevant pending locks */
427                                 brl_notify_unlock(brl, locks, count, &removed_lock);
428
429                                 dbuf.dsize = count * sizeof(*locks);
430
431                                 if (tdb_store(brl->w->tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
432                                         status = NT_STATUS_INTERNAL_DB_CORRUPTION;
433                                         goto fail;
434                                 }
435                         }
436                         
437                         free(dbuf.dptr);
438                         tdb_chainunlock(brl->w->tdb, kbuf);
439                         return NT_STATUS_OK;
440                 }
441         }
442         
443         /* we didn't find it */
444         status = NT_STATUS_RANGE_NOT_LOCKED;
445
446  fail:
447         free(dbuf.dptr);
448         tdb_chainunlock(brl->w->tdb, kbuf);
449         return status;
450 }
451
452
453 /*
454   remove a pending lock. This is called when the caller has either
455   given up trying to establish a lock or when they have succeeded in
456   getting it. In either case they no longer need to be notified.
457 */
458 NTSTATUS brl_remove_pending(struct brl_context *brl,
459                             DATA_BLOB *file_key, 
460                             void *notify_ptr)
461 {
462         TDB_DATA kbuf, dbuf;
463         int count, i;
464         struct lock_struct *locks;
465         NTSTATUS status;
466
467         kbuf.dptr = file_key->data;
468         kbuf.dsize = file_key->length;
469
470         if (tdb_chainlock(brl->w->tdb, kbuf) != 0) {
471                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
472         }
473
474         dbuf = tdb_fetch(brl->w->tdb, kbuf);
475         if (!dbuf.dptr) {
476                 tdb_chainunlock(brl->w->tdb, kbuf);
477                 return NT_STATUS_RANGE_NOT_LOCKED;
478         }
479
480         /* there are existing locks - find a match */
481         locks = (struct lock_struct *)dbuf.dptr;
482         count = dbuf.dsize / sizeof(*locks);
483
484         for (i=0; i<count; i++) {
485                 struct lock_struct *lock = &locks[i];
486                 
487                 if (lock->notify_ptr == notify_ptr &&
488                     lock->context.server == brl->server) {
489                         /* found it - delete it */
490                         if (count == 1) {
491                                 if (tdb_delete(brl->w->tdb, kbuf) != 0) {
492                                         status = NT_STATUS_INTERNAL_DB_CORRUPTION;
493                                         goto fail;
494                                 }
495                         } else {
496                                 if (i < count-1) {
497                                         memmove(&locks[i], &locks[i+1], 
498                                                 sizeof(*locks)*((count-1) - i));
499                                 }
500                                 count--;
501                                 dbuf.dsize = count * sizeof(*locks);
502                                 if (tdb_store(brl->w->tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
503                                         status = NT_STATUS_INTERNAL_DB_CORRUPTION;
504                                         goto fail;
505                                 }
506                         }
507                         
508                         free(dbuf.dptr);
509                         tdb_chainunlock(brl->w->tdb, kbuf);
510                         return NT_STATUS_OK;
511                 }
512         }
513         
514         /* we didn't find it */
515         status = NT_STATUS_RANGE_NOT_LOCKED;
516
517  fail:
518         free(dbuf.dptr);
519         tdb_chainunlock(brl->w->tdb, kbuf);
520         return status;
521 }
522
523
524 /*
525   Test if we are allowed to perform IO on a region of an open file
526 */
527 NTSTATUS brl_locktest(struct brl_context *brl,
528                       DATA_BLOB *file_key, 
529                       uint16_t fnum,
530                       uint16 smbpid, 
531                       uint64_t start, uint64_t size, 
532                       enum brl_type lock_type)
533 {
534         TDB_DATA kbuf, dbuf;
535         int count, i;
536         struct lock_struct lock, *locks;
537
538         kbuf.dptr = file_key->data;
539         kbuf.dsize = file_key->length;
540
541         dbuf = tdb_fetch(brl->w->tdb, kbuf);
542         if (dbuf.dptr == NULL) {
543                 return NT_STATUS_OK;
544         }
545
546         lock.context.smbpid = smbpid;
547         lock.context.server = brl->server;
548         lock.context.tid = brl->tid;
549         lock.start = start;
550         lock.size = size;
551         lock.fnum = fnum;
552         lock.lock_type = lock_type;
553
554         /* there are existing locks - make sure they don't conflict */
555         locks = (struct lock_struct *)dbuf.dptr;
556         count = dbuf.dsize / sizeof(*locks);
557
558         for (i=0; i<count; i++) {
559                 if (brl_conflict_other(&locks[i], &lock)) {
560                         free(dbuf.dptr);
561                         return NT_STATUS_FILE_LOCK_CONFLICT;
562                 }
563         }
564
565         free(dbuf.dptr);
566         return NT_STATUS_OK;
567 }
568
569
570 /*
571  Remove any locks associated with a open file.
572 */
573 NTSTATUS brl_close(struct brl_context *brl,
574                    DATA_BLOB *file_key, int fnum)
575 {
576         TDB_DATA kbuf, dbuf;
577         int count, i, dcount=0;
578         struct lock_struct *locks;
579         NTSTATUS status;
580
581         kbuf.dptr = file_key->data;
582         kbuf.dsize = file_key->length;
583
584         if (tdb_chainlock(brl->w->tdb, kbuf) != 0) {
585                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
586         }
587
588         dbuf = tdb_fetch(brl->w->tdb, kbuf);
589         if (!dbuf.dptr) {
590                 tdb_chainunlock(brl->w->tdb, kbuf);
591                 return NT_STATUS_OK;
592         }
593
594         /* there are existing locks - remove any for this fnum */
595         locks = (struct lock_struct *)dbuf.dptr;
596         count = dbuf.dsize / sizeof(*locks);
597
598         for (i=0; i<count; i++) {
599                 struct lock_struct *lock = &locks[i];
600
601                 if (lock->context.tid == brl->tid &&
602                     lock->context.server == brl->server &&
603                     lock->fnum == fnum) {
604                         /* found it - delete it */
605                         if (count > 1 && i < count-1) {
606                                 memmove(&locks[i], &locks[i+1], 
607                                         sizeof(*locks)*((count-1) - i));
608                         }
609                         count--;
610                         i--;
611                         dcount++;
612                 }
613         }
614
615         status = NT_STATUS_OK;
616
617         if (count == 0) {
618                 if (tdb_delete(brl->w->tdb, kbuf) != 0) {
619                         status = NT_STATUS_INTERNAL_DB_CORRUPTION;
620                 }
621         } else if (dcount != 0) {
622                 /* tell all pending lock holders for this file that
623                    they have a chance now. This is a bit indiscriminant,
624                    but works OK */
625                 brl_notify_all(brl, locks, count);
626
627                 dbuf.dsize = count * sizeof(*locks);
628
629                 if (tdb_store(brl->w->tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
630                         status = NT_STATUS_INTERNAL_DB_CORRUPTION;
631                 }
632         }
633
634         free(dbuf.dptr);
635         tdb_chainunlock(brl->w->tdb, kbuf);
636
637         return status;
638 }
639