2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-2000
5 Copyright (C) Jeremy Allison 1992-2000
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 12 aug 96: Erik.Devriendt@te6.siemens.be
24 added support for shared memory implementation of share mode locking
26 May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27 locking to deal with multiple share modes per open file.
29 September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
32 rewrtten completely to use new tdb code. Tridge, Dec '99
34 Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
40 /* the locking database handle */
41 static TDB_CONTEXT *tdb;
43 /****************************************************************************
45 ****************************************************************************/
47 static const char *lock_type_name(enum brl_type lock_type)
49 return (lock_type == READ_LOCK) ? "READ" : "WRITE";
52 /****************************************************************************
53 Utility function called to see if a file region is locked.
54 If check_self is True, then checks on our own fd with the same locking context
55 are still made. If check_self is False, then checks are not made on our own fd
56 with the same locking context are not made.
57 ****************************************************************************/
59 BOOL is_locked(files_struct *fsp,connection_struct *conn,
60 SMB_BIG_UINT count,SMB_BIG_UINT offset,
61 enum brl_type lock_type, BOOL check_self)
63 int snum = SNUM(conn);
69 if (!lp_locking(snum) || !lp_strict_locking(snum))
72 ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum,
73 global_smbpid, sys_getpid(), conn->cnum,
74 offset, count, lock_type, check_self);
76 DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n",
77 (double)offset, (double)count, ret ? "locked" : "unlocked",
81 * There is no lock held by an SMB daemon, check to
82 * see if there is a POSIX lock from a UNIX or NFS process.
85 if(!ret && lp_posix_locking(snum)) {
86 ret = is_posix_locked(fsp, offset, count, lock_type);
88 DEBUG(10,("is_locked: posix start=%.0f len=%.0f %s for file %s\n",
89 (double)offset, (double)count, ret ? "locked" : "unlocked",
96 /****************************************************************************
97 Utility function called by locking requests.
98 ****************************************************************************/
100 static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
101 SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type)
105 if (!lp_locking(SNUM(conn)))
108 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
111 DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n",
112 lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name ));
114 if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) {
115 status = brl_lock(fsp->dev, fsp->inode, fsp->fnum,
116 lock_pid, sys_getpid(), conn->cnum,
120 if (NT_STATUS_IS_OK(status) && lp_posix_locking(SNUM(conn))) {
123 * Try and get a POSIX lock on this range.
124 * Note that this is ok if it is a read lock
125 * overlapping on a different fd. JRA.
128 if (!set_posix_lock(fsp, offset, count, lock_type)) {
129 status = NT_STATUS_LOCK_NOT_GRANTED;
131 * We failed to map - we must now remove the brl
134 (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
135 lock_pid, sys_getpid(), conn->cnum,
144 /****************************************************************************
145 Utility function called by locking requests. This is *DISGISTING*. It also
146 appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000
147 is so slow on the locking tests...... ? This is the reason. Much though I hate
148 it, we need this. JRA.
149 ****************************************************************************/
151 NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
152 SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type)
154 int j, maxj = lp_lock_spin_count();
155 int sleeptime = lp_lock_sleep_time();
161 for (j = 0; j < maxj; j++) {
162 status = do_lock(fsp, conn, lock_pid, count, offset, lock_type);
163 if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) &&
164 !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT))
167 sys_usleep(sleeptime);
172 /****************************************************************************
173 Utility function called by unlocking requests.
174 ****************************************************************************/
176 NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
177 SMB_BIG_UINT count,SMB_BIG_UINT offset)
181 if (!lp_locking(SNUM(conn)))
184 if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) {
185 return NT_STATUS_INVALID_HANDLE;
188 DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n",
189 (double)offset, (double)count, fsp->fsp_name ));
192 * Remove the existing lock record from the tdb lockdb
193 * before looking at POSIX locks. If this record doesn't
194 * match then don't bother looking to remove POSIX locks.
197 ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
198 lock_pid, sys_getpid(), conn->cnum, offset, count);
201 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
202 return NT_STATUS_RANGE_NOT_LOCKED;
205 if (!lp_posix_locking(SNUM(conn)))
208 (void)release_posix_lock(fsp, offset, count);
213 /****************************************************************************
214 Remove any locks on this fd. Called from file_close().
215 ****************************************************************************/
217 void locking_close_file(files_struct *fsp)
219 pid_t pid = sys_getpid();
221 if (!lp_locking(SNUM(fsp->conn)))
225 * Just release all the brl locks, no need to release individually.
228 brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
230 if(lp_posix_locking(SNUM(fsp->conn))) {
233 * Release all the POSIX locks.
235 posix_locking_close_file(fsp);
240 /****************************************************************************
241 Initialise the locking functions.
242 ****************************************************************************/
244 static int open_read_only;
246 BOOL locking_init(int read_only)
253 tdb = tdb_open_log(lock_path("locking.tdb"),
254 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST),
255 read_only?O_RDONLY:O_RDWR|O_CREAT,
259 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
263 if (!posix_locking_init(read_only))
266 open_read_only = read_only;
271 /*******************************************************************
272 Deinitialize the share_mode management.
273 ******************************************************************/
275 BOOL locking_end(void)
278 brl_shutdown(open_read_only);
281 if (tdb_close(tdb) != 0)
288 /*******************************************************************
289 Form a static locking key for a dev/inode pair.
290 ******************************************************************/
292 static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
294 static struct locking_key key;
297 memset(&key, '\0', sizeof(key));
300 kbuf.dptr = (char *)&key;
301 kbuf.dsize = sizeof(key);
305 static TDB_DATA locking_key_fsp(files_struct *fsp)
307 return locking_key(fsp->dev, fsp->inode);
310 /*******************************************************************
311 Lock a hash bucket entry.
312 ******************************************************************/
314 BOOL lock_share_entry(connection_struct *conn,
315 SMB_DEV_T dev, SMB_INO_T inode)
317 return tdb_chainlock(tdb, locking_key(dev, inode)) == 0;
320 /*******************************************************************
321 Unlock a hash bucket entry.
322 ******************************************************************/
324 void unlock_share_entry(connection_struct *conn,
325 SMB_DEV_T dev, SMB_INO_T inode)
327 tdb_chainunlock(tdb, locking_key(dev, inode));
330 /*******************************************************************
331 Lock a hash bucket entry. use a fsp for convenience
332 ******************************************************************/
334 BOOL lock_share_entry_fsp(files_struct *fsp)
336 return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
339 /*******************************************************************
340 Unlock a hash bucket entry.
341 ******************************************************************/
343 void unlock_share_entry_fsp(files_struct *fsp)
345 tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode));
348 /*******************************************************************
349 Print out a share mode.
350 ********************************************************************/
352 static char *share_mode_str(int num, share_mode_entry *e)
354 static pstring share_str;
356 slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: \
357 pid = %u, share_mode = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f",
358 num, e->pid, e->share_mode, e->op_port, e->op_type, e->share_file_id,
359 (unsigned int)e->dev, (double)e->inode );
364 /*******************************************************************
365 Print out a share mode table.
366 ********************************************************************/
368 static void print_share_mode_table(struct locking_data *data)
370 int num_share_modes = data->u.num_share_mode_entries;
371 share_mode_entry *shares = (share_mode_entry *)(data + 1);
374 for (i = 0; i < num_share_modes; i++) {
375 share_mode_entry *entry_p = &shares[i];
376 DEBUG(10,("print_share_mode_table: %s\n", share_mode_str(i, entry_p) ));
380 /*******************************************************************
381 Get all share mode entries for a dev/inode pair.
382 ********************************************************************/
384 int get_share_modes(connection_struct *conn,
385 SMB_DEV_T dev, SMB_INO_T inode,
386 share_mode_entry **pp_shares)
389 struct locking_data *data;
391 share_mode_entry *shares = NULL;
395 dbuf = tdb_fetch(tdb, locking_key(dev, inode));
399 data = (struct locking_data *)dbuf.dptr;
400 num_share_modes = data->u.num_share_mode_entries;
401 if(num_share_modes) {
405 shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data),
406 num_share_modes * sizeof(share_mode_entry));
409 SAFE_FREE(dbuf.dptr);
414 * Ensure that each entry has a real process attached.
417 for (i = 0; i < num_share_modes; ) {
418 share_mode_entry *entry_p = &shares[i];
419 if (process_exists(entry_p->pid)) {
420 DEBUG(10,("get_share_modes: %s\n", share_mode_str(i, entry_p) ));
423 DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) ));
424 memcpy( &shares[i], &shares[i+1],
425 sizeof(share_mode_entry) * (num_share_modes - i - 1));
431 /* Did we delete any ? If so, re-store in tdb. */
433 data->u.num_share_mode_entries = num_share_modes;
436 memcpy(dbuf.dptr + sizeof(*data), shares,
437 num_share_modes * sizeof(share_mode_entry));
439 /* The record has shrunk a bit */
440 dbuf.dsize -= del_count * sizeof(share_mode_entry);
442 if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) {
444 SAFE_FREE(dbuf.dptr);
450 SAFE_FREE(dbuf.dptr);
452 return num_share_modes;
455 /*******************************************************************
456 Fill a share mode entry.
457 ********************************************************************/
459 static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type)
461 share_mode_entry *e = (share_mode_entry *)p;
462 void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */
464 memset(e, '\0', sizeof(share_mode_entry));
465 e->pid = sys_getpid();
466 e->share_mode = fsp->share_mode;
468 e->op_type = op_type;
469 memcpy(x, &fsp->open_time, sizeof(struct timeval));
470 e->share_file_id = fsp->file_id;
472 e->inode = fsp->inode;
475 /*******************************************************************
476 Check if two share mode entries are identical, ignoring oplock
478 ********************************************************************/
480 BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2)
482 #if 1 /* JRA PARANOIA TEST - REMOVE LATER */
483 if (e1->pid == e2->pid &&
484 e1->share_file_id == e2->share_file_id &&
485 e1->dev == e2->dev &&
486 e1->inode == e2->inode &&
487 (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) != (e2->share_mode & ~DELETE_ON_CLOSE_FLAG)) {
488 DEBUG(0,("PANIC: share_modes_identical: share_mode missmatch (e1 = %u, e2 = %u). Logic error.\n",
489 (unsigned int)(e1->share_mode & ~DELETE_ON_CLOSE_FLAG),
490 (unsigned int)(e2->share_mode & ~DELETE_ON_CLOSE_FLAG) ));
491 smb_panic("PANIC: share_modes_identical logic error.\n");
495 return (e1->pid == e2->pid &&
496 (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) == (e2->share_mode & ~DELETE_ON_CLOSE_FLAG) &&
497 e1->dev == e2->dev &&
498 e1->inode == e2->inode &&
499 e1->share_file_id == e2->share_file_id );
502 /*******************************************************************
503 Delete a specific share mode. Return the number
504 of entries left, and a memdup'ed copy of the entry deleted (if required).
505 Ignore if no entry deleted.
506 ********************************************************************/
508 ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
509 share_mode_entry *entry, share_mode_entry **ppse)
512 struct locking_data *data;
514 share_mode_entry *shares;
520 /* read in the existing share modes */
521 dbuf = tdb_fetch(tdb, locking_key(dev, inode));
525 data = (struct locking_data *)dbuf.dptr;
526 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
529 * Find any with this pid and delete it
530 * by overwriting with the rest of the data
534 DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.num_share_mode_entries ));
536 for (i=0;i<data->u.num_share_mode_entries;) {
537 if (share_modes_identical(&shares[i], entry)) {
538 DEBUG(10,("del_share_entry: deleted %s\n",
539 share_mode_str(i, &shares[i]) ));
541 *ppse = memdup(&shares[i], sizeof(*shares));
542 data->u.num_share_mode_entries--;
543 memmove(&shares[i], &shares[i+1],
544 dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
547 DEBUG(10,("del_share_entry: deleting entry %d\n", i ));
555 /* the record may have shrunk a bit */
556 dbuf.dsize -= del_count * sizeof(*shares);
558 count = (ssize_t)data->u.num_share_mode_entries;
560 /* store it back in the database */
561 if (data->u.num_share_mode_entries == 0) {
562 if (tdb_delete(tdb, locking_key(dev, inode)) == -1)
565 if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1)
569 DEBUG(10,("del_share_entry: Remaining table.\n"));
570 print_share_mode_table((struct locking_data *)dbuf.dptr);
571 SAFE_FREE(dbuf.dptr);
575 /*******************************************************************
576 Del the share mode of a file for this process. Return the number
577 of entries left, and a memdup'ed copy of the entry deleted.
578 ********************************************************************/
580 ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse)
582 share_mode_entry entry;
585 * Fake up a share_mode_entry for comparisons.
588 fill_share_mode((char *)&entry, fsp, 0, 0);
589 return del_share_entry(fsp->dev, fsp->inode, &entry, ppse);
592 /*******************************************************************
593 Set the share mode of a file. Return False on fail, True on success.
594 ********************************************************************/
596 BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type)
599 struct locking_data *data;
604 /* read in the existing share modes if any */
605 dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
607 /* we'll need to create a new record */
610 pstrcpy(fname, fsp->conn->connectpath);
612 pstrcat(fname, fsp->fsp_name);
614 size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1;
615 p = (char *)malloc(size);
618 data = (struct locking_data *)p;
619 data->u.num_share_mode_entries = 1;
621 DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n",
624 pstrcpy(p + sizeof(*data) + sizeof(share_mode_entry), fname);
625 fill_share_mode(p + sizeof(*data), fsp, port, op_type);
628 if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1)
631 print_share_mode_table((struct locking_data *)p);
637 /* we're adding to an existing entry - this is a bit fiddly */
638 data = (struct locking_data *)dbuf.dptr;
640 data->u.num_share_mode_entries++;
642 DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n",
643 fsp->fsp_name, data->u.num_share_mode_entries ));
645 size = dbuf.dsize + sizeof(share_mode_entry);
649 memcpy(p, dbuf.dptr, sizeof(*data));
650 fill_share_mode(p + sizeof(*data), fsp, port, op_type);
651 memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data),
652 dbuf.dsize - sizeof(*data));
653 SAFE_FREE(dbuf.dptr);
656 if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1)
658 print_share_mode_table((struct locking_data *)p);
663 /*******************************************************************
664 A generic in-place modification call for share mode entries.
665 ********************************************************************/
667 static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry,
668 void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *),
672 struct locking_data *data;
674 share_mode_entry *shares;
675 BOOL need_store=False;
677 /* read in the existing share modes */
678 dbuf = tdb_fetch(tdb, locking_key(dev, inode));
682 data = (struct locking_data *)dbuf.dptr;
683 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
685 /* find any with our pid and call the supplied function */
686 for (i=0;i<data->u.num_share_mode_entries;i++) {
687 if (share_modes_identical(entry, &shares[i])) {
688 mod_fn(&shares[i], dev, inode, param);
693 /* if the mod fn was called then store it back */
695 if (data->u.num_share_mode_entries == 0) {
696 if (tdb_delete(tdb, locking_key(dev, inode)) == -1)
699 if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1)
704 SAFE_FREE(dbuf.dptr);
708 /*******************************************************************
709 Static function that actually does the work for the generic function
711 ********************************************************************/
713 static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
716 DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n",
717 (unsigned int)dev, (double)inode ));
718 /* Delete the oplock info. */
720 entry->op_type = NO_OPLOCK;
723 /*******************************************************************
724 Remove an oplock port and mode entry from a share mode.
725 ********************************************************************/
727 BOOL remove_share_oplock(files_struct *fsp)
729 share_mode_entry entry;
731 * Fake up an entry for comparisons...
733 fill_share_mode((char *)&entry, fsp, 0, 0);
734 return mod_share_mode(fsp->dev, fsp->inode, &entry, remove_share_oplock_fn, NULL);
737 /*******************************************************************
738 Static function that actually does the work for the generic function
740 ********************************************************************/
742 static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
745 DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n",
746 (unsigned int)dev, (double)inode ));
747 entry->op_type = LEVEL_II_OPLOCK;
750 /*******************************************************************
751 Downgrade a oplock type from exclusive to level II.
752 ********************************************************************/
754 BOOL downgrade_share_oplock(files_struct *fsp)
756 share_mode_entry entry;
758 * Fake up an entry for comparisons...
760 fill_share_mode((char *)&entry, fsp, 0, 0);
761 return mod_share_mode(fsp->dev, fsp->inode, &entry, downgrade_share_oplock_fn, NULL);
764 /*******************************************************************
765 Get/Set the delete on close flag in a set of share modes.
766 Return False on fail, True on success.
767 ********************************************************************/
769 BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close)
772 struct locking_data *data;
774 share_mode_entry *shares;
776 /* read in the existing share modes */
777 dbuf = tdb_fetch(tdb, locking_key(dev, inode));
781 data = (struct locking_data *)dbuf.dptr;
782 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
784 /* Set/Unset the delete on close element. */
785 for (i=0;i<data->u.num_share_mode_entries;i++,shares++) {
786 shares->share_mode = (delete_on_close ?
787 (shares->share_mode | DELETE_ON_CLOSE_FLAG) :
788 (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) );
792 if (data->u.num_share_mode_entries) {
793 if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) {
794 SAFE_FREE(dbuf.dptr);
799 SAFE_FREE(dbuf.dptr);
803 /****************************************************************************
804 Traverse the whole database with this function, calling traverse_callback
806 ****************************************************************************/
808 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
811 struct locking_data *data;
812 share_mode_entry *shares;
816 SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state;
818 data = (struct locking_data *)dbuf.dptr;
819 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
820 name = dbuf.dptr + sizeof(*data) + data->u.num_share_mode_entries*sizeof(*shares);
822 for (i=0;i<data->u.num_share_mode_entries;i++) {
823 traverse_callback(&shares[i], name);
828 /*******************************************************************
829 Call the specified function on each entry under management by the
831 ********************************************************************/
833 int share_mode_forall(SHAREMODE_FN(fn))
837 return tdb_traverse(tdb, traverse_fn, (void*)fn);