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 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#define ZERO_ZERO 0
31
32/* This contains elements that differentiate locks. The smbpid is a
33   client supplied pid, and is essentially the locking context for
34   this client */
35
36struct lock_context {
37	uint16 smbpid;
38	uint16 tid;
39	pid_t pid;
40};
41
42/* The data in brlock records is an unsorted linear array of these
43   records.  It is unnecessary to store the count as tdb provides the
44   size of the record */
45
46struct lock_struct {
47	struct lock_context context;
48	br_off start;
49	br_off size;
50	int fnum;
51	enum brl_type lock_type;
52};
53
54/* The key used in the brlock database. */
55
56struct lock_key {
57	SMB_DEV_T device;
58	SMB_INO_T inode;
59};
60
61/* The open brlock.tdb database. */
62
63static TDB_CONTEXT *tdb;
64
65/****************************************************************************
66 Create a locking key - ensuring zero filled for pad purposes.
67****************************************************************************/
68
69static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
70{
71        static struct lock_key key;
72        TDB_DATA kbuf;
73
74        memset(&key, '\0', sizeof(key));
75        key.device = dev;
76        key.inode = inode;
77        kbuf.dptr = (char *)&key;
78        kbuf.dsize = sizeof(key);
79        return kbuf;
80}
81
82/****************************************************************************
83 See if two locking contexts are equal.
84****************************************************************************/
85
86static BOOL brl_same_context(struct lock_context *ctx1,
87			     struct lock_context *ctx2)
88{
89	return (ctx1->pid == ctx2->pid) &&
90		(ctx1->smbpid == ctx2->smbpid) &&
91		(ctx1->tid == ctx2->tid);
92}
93
94/****************************************************************************
95 See if lck1 and lck2 overlap.
96****************************************************************************/
97
98static BOOL brl_overlap(struct lock_struct *lck1,
99                        struct lock_struct *lck2)
100{
101	/* this extra check is not redundent - it copes with locks
102	   that go beyond the end of 64 bit file space */
103	if (lck1->size != 0 &&
104	    lck1->start == lck2->start &&
105	    lck1->size == lck2->size) {
106		return True;
107	}
108
109	if (lck1->start >= (lck2->start+lck2->size) ||
110	    lck2->start >= (lck1->start+lck1->size)) {
111		return False;
112	}
113	return True;
114}
115
116/****************************************************************************
117 See if lock2 can be added when lock1 is in place.
118****************************************************************************/
119
120static BOOL brl_conflict(struct lock_struct *lck1,
121			 struct lock_struct *lck2)
122{
123	if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )
124		return False;
125
126	if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
127		return False;
128	}
129
130	if (brl_same_context(&lck1->context, &lck2->context) &&
131	    lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) {
132		return False;
133	}
134
135	return brl_overlap(lck1, lck2);
136}
137
138#if ZERO_ZERO
139static BOOL brl_conflict1(struct lock_struct *lck1,
140			 struct lock_struct *lck2)
141{
142	if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )
143		return False;
144
145	if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
146		return False;
147	}
148
149	if (brl_same_context(&lck1->context, &lck2->context) &&
150	    lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) {
151		return False;
152	}
153
154	if (lck2->start == 0 && lck2->size == 0 && lck1->size != 0) {
155		return True;
156	}
157
158	if (lck1->start >= (lck2->start + lck2->size) ||
159	    lck2->start >= (lck1->start + lck1->size)) {
160		return False;
161	}
162
163	return True;
164}
165#endif
166
167/****************************************************************************
168 Check to see if this lock conflicts, but ignore our own locks on the
169 same fnum only.
170****************************************************************************/
171
172static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck2)
173{
174	if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )
175		return False;
176
177	if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK)
178		return False;
179
180	/*
181	 * Incoming WRITE locks conflict with existing READ locks even
182	 * if the context is the same. JRA. See LOCKTEST7 in smbtorture.
183	 */
184
185	if (!(lck2->lock_type == WRITE_LOCK && lck1->lock_type == READ_LOCK)) {
186		if (brl_same_context(&lck1->context, &lck2->context) &&
187					lck1->fnum == lck2->fnum)
188			return False;
189	}
190
191	return brl_overlap(lck1, lck2);
192}
193
194/****************************************************************************
195 Amazingly enough, w2k3 "remembers" whether the last lock failure
196 is the same as this one and changes its error code. I wonder if any
197 app depends on this ?
198****************************************************************************/
199
200static NTSTATUS brl_lock_failed(struct lock_struct *lock)
201{
202	static struct lock_struct last_lock_failure;
203
204	if (brl_same_context(&lock->context, &last_lock_failure.context) &&
205			lock->fnum == last_lock_failure.fnum &&
206			lock->start == last_lock_failure.start &&
207			lock->size == last_lock_failure.size) {
208		return NT_STATUS_FILE_LOCK_CONFLICT;
209	}
210	last_lock_failure = *lock;
211	if (lock->start >= 0xEF000000 &&
212			(lock->start >> 63) == 0) {
213		/* amazing the little things you learn with a test
214		   suite. Locks beyond this offset (as a 64 bit
215		   number!) always generate the conflict error code,
216		   unless the top bit is set */
217		return NT_STATUS_FILE_LOCK_CONFLICT;
218	}
219	return NT_STATUS_LOCK_NOT_GRANTED;
220}
221
222#if DONT_DO_THIS
223	/* doing this traversal could kill solaris machines under high load (tridge) */
224	/* delete any dead locks */
225
226/****************************************************************************
227 Delete a record if it is for a dead process, if check_self is true, then
228 delete any records belonging to this pid also (there shouldn't be any).
229****************************************************************************/
230
231static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
232{
233	struct lock_struct *locks;
234	int count, i;
235	BOOL check_self = *(BOOL *)state;
236	pid_t mypid = sys_getpid();
237
238	tdb_chainlock(tdb, kbuf);
239
240	locks = (struct lock_struct *)dbuf.dptr;
241
242	count = dbuf.dsize / sizeof(*locks);
243	for (i=0; i<count; i++) {
244		struct lock_struct *lock = &locks[i];
245
246		/* If check_self is true we want to remove our own records. */
247		if (check_self && (mypid == lock->context.pid)) {
248
249			DEBUG(0,("brlock : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n",
250					(unsigned int)lock->context.pid ));
251
252		} else if (process_exists(lock->context.pid)) {
253
254			DEBUG(10,("brlock : delete_fn. pid %u exists.\n", (unsigned int)lock->context.pid ));
255			continue;
256		}
257
258		DEBUG(10,("brlock : delete_fn. Deleting record for process %u\n",
259				(unsigned int)lock->context.pid ));
260
261		if (count > 1 && i < count-1) {
262			memmove(&locks[i], &locks[i+1],
263				sizeof(*locks)*((count-1) - i));
264		}
265		count--;
266		i--;
267	}
268
269	if (count == 0) {
270		tdb_delete(tdb, kbuf);
271	} else if (count < (dbuf.dsize / sizeof(*locks))) {
272		dbuf.dsize = count * sizeof(*locks);
273		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
274	}
275
276	tdb_chainunlock(tdb, kbuf);
277	return 0;
278}
279#endif
280
281/****************************************************************************
282 Open up the brlock.tdb database.
283****************************************************************************/
284
285void brl_init(int read_only)
286{
287	if (tdb)
288		return;
289	tdb = tdb_open_log(lock_path("brlock.tdb"), 0,  TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST),
290		       read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 );
291	if (!tdb) {
292		DEBUG(0,("Failed to open byte range locking database\n"));
293		return;
294	}
295
296#if DONT_DO_THIS
297	/* doing this traversal could kill solaris machines under high load (tridge) */
298	/* delete any dead locks */
299	if (!read_only) {
300		BOOL check_self = False;
301		tdb_traverse(tdb, delete_fn, &check_self);
302	}
303#endif
304}
305
306/****************************************************************************
307 Close down the brlock.tdb database.
308****************************************************************************/
309
310void brl_shutdown(int read_only)
311{
312	if (!tdb)
313		return;
314
315#if DONT_DO_THIS
316	/* doing this traversal could kill solaris machines under high load (tridge) */
317	/* delete any dead locks */
318	if (!read_only) {
319		BOOL check_self = True;
320		tdb_traverse(tdb, delete_fn, &check_self);
321	}
322#endif
323
324	tdb_close(tdb);
325}
326
327#if ZERO_ZERO
328/****************************************************************************
329compare two locks for sorting
330****************************************************************************/
331static int lock_compare(struct lock_struct *lck1,
332			 struct lock_struct *lck2)
333{
334	if (lck1->start != lck2->start) return (lck1->start - lck2->start);
335	if (lck2->size != lck1->size) {
336		return ((int)lck1->size - (int)lck2->size);
337	}
338	return 0;
339}
340#endif
341
342/****************************************************************************
343 Lock a range of bytes.
344****************************************************************************/
345
346NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
347		  uint16 smbpid, pid_t pid, uint16 tid,
348		  br_off start, br_off size,
349		  enum brl_type lock_type, BOOL *my_lock_ctx)
350{
351	TDB_DATA kbuf, dbuf;
352	int count, i;
353	struct lock_struct lock, *locks;
354	char *tp;
355	NTSTATUS status = NT_STATUS_OK;
356
357	*my_lock_ctx = False;
358	kbuf = locking_key(dev,ino);
359
360	dbuf.dptr = NULL;
361
362#if !ZERO_ZERO
363	if (start == 0 && size == 0) {
364		DEBUG(0,("client sent 0/0 lock - please report this\n"));
365	}
366#endif
367
368	tdb_chainlock(tdb, kbuf);
369	dbuf = tdb_fetch(tdb, kbuf);
370
371	lock.context.smbpid = smbpid;
372	lock.context.pid = pid;
373	lock.context.tid = tid;
374	lock.start = start;
375	lock.size = size;
376	lock.fnum = fnum;
377	lock.lock_type = lock_type;
378
379	if (dbuf.dptr) {
380		/* there are existing locks - make sure they don't conflict */
381		locks = (struct lock_struct *)dbuf.dptr;
382		count = dbuf.dsize / sizeof(*locks);
383		for (i=0; i<count; i++) {
384			if (brl_conflict(&locks[i], &lock)) {
385				status = brl_lock_failed(&lock);;
386				/* Did we block ourselves ? */
387				if (brl_same_context(&locks[i].context, &lock.context))
388					*my_lock_ctx = True;
389				goto fail;
390			}
391#if ZERO_ZERO
392			if (lock.start == 0 && lock.size == 0 &&
393			    locks[i].size == 0) {
394				break;
395			}
396#endif
397		}
398	}
399
400	/* no conflicts - add it to the list of locks */
401	tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(*locks));
402	if (!tp) {
403		status = NT_STATUS_NO_MEMORY;
404		goto fail;
405	} else {
406		dbuf.dptr = tp;
407	}
408	memcpy(dbuf.dptr + dbuf.dsize, &lock, sizeof(lock));
409	dbuf.dsize += sizeof(lock);
410
411#if ZERO_ZERO
412	/* sort the lock list */
413	qsort(dbuf.dptr, dbuf.dsize/sizeof(lock), sizeof(lock), lock_compare);
414#endif
415
416	if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
417		status = NT_STATUS_INTERNAL_DB_CORRUPTION;
418		goto fail;
419	}
420
421	SAFE_FREE(dbuf.dptr);
422	tdb_chainunlock(tdb, kbuf);
423	return NT_STATUS_OK;
424
425 fail:
426
427	SAFE_FREE(dbuf.dptr);
428	tdb_chainunlock(tdb, kbuf);
429	return status;
430}
431
432/****************************************************************************
433 Check if an unlock overlaps a pending lock.
434****************************************************************************/
435
436static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pend_lock)
437{
438	if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start))
439		return True;
440	if ((lock->start >= pend_lock->start) && (lock->start <= pend_lock->start + pend_lock->size))
441		return True;
442	return False;
443}
444
445/****************************************************************************
446 Unlock a range of bytes.
447****************************************************************************/
448
449BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
450		uint16 smbpid, pid_t pid, uint16 tid,
451		br_off start, br_off size,
452		BOOL remove_pending_locks_only,
453		void (*pre_unlock_fn)(void *),
454		void *pre_unlock_data)
455{
456	TDB_DATA kbuf, dbuf;
457	int count, i, j;
458	struct lock_struct *locks;
459	struct lock_context context;
460
461	kbuf = locking_key(dev,ino);
462
463	dbuf.dptr = NULL;
464
465	tdb_chainlock(tdb, kbuf);
466	dbuf = tdb_fetch(tdb, kbuf);
467
468	if (!dbuf.dptr) {
469		DEBUG(10,("brl_unlock: tdb_fetch failed !\n"));
470		goto fail;
471	}
472
473	context.smbpid = smbpid;
474	context.pid = pid;
475	context.tid = tid;
476
477	/* there are existing locks - find a match */
478	locks = (struct lock_struct *)dbuf.dptr;
479	count = dbuf.dsize / sizeof(*locks);
480
481#if ZERO_ZERO
482	for (i=0; i<count; i++) {
483		struct lock_struct *lock = &locks[i];
484
485		if (lock->lock_type == WRITE_LOCK &&
486		    brl_same_context(&lock->context, &context) &&
487		    lock->fnum == fnum &&
488		    lock->start == start &&
489		    lock->size == size) {
490
491			if (pre_unlock_fn)
492				(*pre_unlock_fn)(pre_unlock_data);
493
494			/* found it - delete it */
495			if (count == 1) {
496				tdb_delete(tdb, kbuf);
497			} else {
498				if (i < count-1) {
499					memmove(&locks[i], &locks[i+1],
500						sizeof(*locks)*((count-1) - i));
501				}
502				dbuf.dsize -= sizeof(*locks);
503				tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
504			}
505
506			SAFE_FREE(dbuf.dptr);
507			tdb_chainunlock(tdb, kbuf);
508			return True;
509		}
510	}
511#endif
512
513	locks = (struct lock_struct *)dbuf.dptr;
514	count = dbuf.dsize / sizeof(*locks);
515	for (i=0; i<count; i++) {
516		struct lock_struct *lock = &locks[i];
517
518		if (brl_same_context(&lock->context, &context) &&
519				lock->fnum == fnum &&
520				lock->start == start &&
521				lock->size == size) {
522
523			if (remove_pending_locks_only && lock->lock_type != PENDING_LOCK)
524				continue;
525
526			if (lock->lock_type != PENDING_LOCK) {
527
528				/* Do any POSIX unlocks needed. */
529				if (pre_unlock_fn)
530					(*pre_unlock_fn)(pre_unlock_data);
531
532				/* Send unlock messages to any pending waiters that overlap. */
533				for (j=0; j<count; j++) {
534					struct lock_struct *pend_lock = &locks[j];
535
536					/* Ignore non-pending locks. */
537					if (pend_lock->lock_type != PENDING_LOCK)
538						continue;
539
540					/* We could send specific lock info here... */
541					if (brl_pending_overlap(lock, pend_lock)) {
542						DEBUG(10,("brl_unlock: sending unlock message to pid %u\n",
543									(unsigned int)pend_lock->context.pid ));
544
545						message_send_pid(pend_lock->context.pid,
546								MSG_SMB_UNLOCK,
547								NULL, 0, True);
548					}
549				}
550			}
551
552			/* found it - delete it */
553			if (count == 1) {
554				tdb_delete(tdb, kbuf);
555			} else {
556				if (i < count-1) {
557					memmove(&locks[i], &locks[i+1],
558						sizeof(*locks)*((count-1) - i));
559				}
560				dbuf.dsize -= sizeof(*locks);
561				tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
562			}
563
564			SAFE_FREE(dbuf.dptr);
565			tdb_chainunlock(tdb, kbuf);
566			return True;
567		}
568	}
569
570	/* we didn't find it */
571
572 fail:
573	SAFE_FREE(dbuf.dptr);
574	tdb_chainunlock(tdb, kbuf);
575	return False;
576}
577
578
579/****************************************************************************
580 Test if we could add a lock if we wanted to.
581****************************************************************************/
582
583BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
584		  uint16 smbpid, pid_t pid, uint16 tid,
585		  br_off start, br_off size,
586		  enum brl_type lock_type)
587{
588	TDB_DATA kbuf, dbuf;
589	int count, i;
590	struct lock_struct lock, *locks;
591
592	kbuf = locking_key(dev,ino);
593
594	dbuf.dptr = NULL;
595
596	dbuf = tdb_fetch(tdb, kbuf);
597
598	lock.context.smbpid = smbpid;
599	lock.context.pid = pid;
600	lock.context.tid = tid;
601	lock.start = start;
602	lock.size = size;
603	lock.fnum = fnum;
604	lock.lock_type = lock_type;
605
606	if (dbuf.dptr) {
607		/* there are existing locks - make sure they don't conflict */
608		locks = (struct lock_struct *)dbuf.dptr;
609		count = dbuf.dsize / sizeof(*locks);
610		for (i=0; i<count; i++) {
611			/*
612			 * Our own locks don't conflict.
613			 */
614			if (brl_conflict_other(&locks[i], &lock))
615				goto fail;
616		}
617	}
618
619	/* no conflicts - we could have added it */
620	SAFE_FREE(dbuf.dptr);
621	return True;
622
623 fail:
624	SAFE_FREE(dbuf.dptr);
625	return False;
626}
627
628/****************************************************************************
629 Remove any locks associated with a open file.
630****************************************************************************/
631
632void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
633{
634	TDB_DATA kbuf, dbuf;
635	int count, i, j, dcount=0;
636	struct lock_struct *locks;
637
638	kbuf = locking_key(dev,ino);
639
640	dbuf.dptr = NULL;
641
642	tdb_chainlock(tdb, kbuf);
643	dbuf = tdb_fetch(tdb, kbuf);
644
645	if (!dbuf.dptr) goto fail;
646
647	/* there are existing locks - remove any for this fnum */
648	locks = (struct lock_struct *)dbuf.dptr;
649	count = dbuf.dsize / sizeof(*locks);
650
651	for (i=0; i<count; i++) {
652		struct lock_struct *lock = &locks[i];
653
654		if (lock->context.tid == tid &&
655		    lock->context.pid == pid &&
656		    lock->fnum == fnum) {
657
658			/* Send unlock messages to any pending waiters that overlap. */
659			for (j=0; j<count; j++) {
660				struct lock_struct *pend_lock = &locks[j];
661
662				/* Ignore our own or non-pending locks. */
663				if (pend_lock->lock_type != PENDING_LOCK)
664					continue;
665
666				if (pend_lock->context.tid == tid &&
667				    pend_lock->context.pid == pid &&
668				    pend_lock->fnum == fnum)
669					continue;
670
671				/* We could send specific lock info here... */
672				if (brl_pending_overlap(lock, pend_lock))
673					message_send_pid(pend_lock->context.pid,
674							MSG_SMB_UNLOCK,
675							NULL, 0, True);
676			}
677
678			/* found it - delete it */
679			if (count > 1 && i < count-1) {
680				memmove(&locks[i], &locks[i+1],
681					sizeof(*locks)*((count-1) - i));
682			}
683			count--;
684			i--;
685			dcount++;
686		}
687	}
688
689	if (count == 0) {
690		tdb_delete(tdb, kbuf);
691	} else if (count < (dbuf.dsize / sizeof(*locks))) {
692		dbuf.dsize -= dcount * sizeof(*locks);
693		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
694	}
695
696	/* we didn't find it */
697 fail:
698	SAFE_FREE(dbuf.dptr);
699	tdb_chainunlock(tdb, kbuf);
700}
701
702/****************************************************************************
703 Traverse the whole database with this function, calling traverse_callback
704 on each lock.
705****************************************************************************/
706
707static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
708{
709	struct lock_struct *locks;
710	struct lock_key *key;
711	int i;
712
713	BRLOCK_FN(traverse_callback) = (BRLOCK_FN_CAST())state;
714
715	locks = (struct lock_struct *)dbuf.dptr;
716	key = (struct lock_key *)kbuf.dptr;
717
718	for (i=0;i<dbuf.dsize/sizeof(*locks);i++) {
719		traverse_callback(key->device, key->inode,
720				  locks[i].context.pid,
721				  locks[i].lock_type,
722				  locks[i].start,
723				  locks[i].size);
724	}
725	return 0;
726}
727
728/*******************************************************************
729 Call the specified function on each lock in the database.
730********************************************************************/
731
732int brl_forall(BRLOCK_FN(fn))
733{
734	if (!tdb) return 0;
735	return tdb_traverse(tdb, traverse_fn, (void *)fn);
736}
737