2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Jeremy Allison 1992-2000
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 12 aug 96: Erik.Devriendt@te6.siemens.be
25 added support for shared memory implementation of share mode locking
27 May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
28 locking to deal with multiple share modes per open file.
30 September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
33 rewrtten completely to use new tdb code. Tridge, Dec '99
35 Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
39 extern int DEBUGLEVEL
;
42 /* the locking database handle */
43 static TDB_CONTEXT
*tdb
;
45 /****************************************************************************
47 ****************************************************************************/
49 static const char *lock_type_name(enum brl_type lock_type
)
51 return (lock_type
== READ_LOCK
) ? "READ" : "WRITE";
54 /****************************************************************************
55 Utility function called to see if a file region is locked.
56 If check_self is True, then checks on our own fd with the same locking context
57 are still made. If check_self is False, then checks are not made on our own fd
58 with the same locking context are not made.
59 ****************************************************************************/
61 BOOL
is_locked(files_struct
*fsp
,connection_struct
*conn
,
62 SMB_BIG_UINT count
,SMB_BIG_UINT offset
,
63 enum brl_type lock_type
, BOOL check_self
)
65 int snum
= SNUM(conn
);
71 if (!lp_locking(snum
) || !lp_strict_locking(snum
))
74 ret
= !brl_locktest(fsp
->dev
, fsp
->inode
, fsp
->fnum
,
75 global_smbpid
, sys_getpid(), conn
->cnum
,
76 offset
, count
, lock_type
, check_self
);
78 DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n",
79 (double)offset
, (double)count
, ret
? "locked" : "unlocked",
83 * There is no lock held by an SMB daemon, check to
84 * see if there is a POSIX lock from a UNIX or NFS process.
87 if(!ret
&& lp_posix_locking(snum
)) {
88 ret
= is_posix_locked(fsp
, offset
, count
, lock_type
);
90 DEBUG(10,("is_locked: posix start=%.0f len=%.0f %s for file %s\n",
91 (double)offset
, (double)count
, ret
? "locked" : "unlocked",
98 /****************************************************************************
99 Utility function called by locking requests.
100 ****************************************************************************/
102 BOOL
do_lock(files_struct
*fsp
,connection_struct
*conn
, uint16 lock_pid
,
103 SMB_BIG_UINT count
,SMB_BIG_UINT offset
,enum brl_type lock_type
,
104 int *eclass
,uint32
*ecode
)
108 if (!lp_locking(SNUM(conn
)))
113 *ecode
= ERRnoaccess
;
117 DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n",
118 lock_type_name(lock_type
), (double)offset
, (double)count
, fsp
->fsp_name
));
120 if (OPEN_FSP(fsp
) && fsp
->can_lock
&& (fsp
->conn
== conn
)) {
121 ok
= brl_lock(fsp
->dev
, fsp
->inode
, fsp
->fnum
,
122 lock_pid
, sys_getpid(), conn
->cnum
,
126 if (ok
&& lp_posix_locking(SNUM(conn
))) {
129 * Try and get a POSIX lock on this range.
130 * Note that this is ok if it is a read lock
131 * overlapping on a different fd. JRA.
134 ok
= set_posix_lock(fsp
, offset
, count
, lock_type
);
138 * We failed to map - we must now remove the brl
141 (void)brl_unlock(fsp
->dev
, fsp
->inode
, fsp
->fnum
,
142 lock_pid
, sys_getpid(), conn
->cnum
,
153 return True
; /* Got lock */
156 /****************************************************************************
157 Utility function called by unlocking requests.
158 ****************************************************************************/
160 BOOL
do_unlock(files_struct
*fsp
,connection_struct
*conn
, uint16 lock_pid
,
161 SMB_BIG_UINT count
,SMB_BIG_UINT offset
,
162 int *eclass
,uint32
*ecode
)
166 if (!lp_locking(SNUM(conn
)))
169 if (!OPEN_FSP(fsp
) || !fsp
->can_lock
|| (fsp
->conn
!= conn
)) {
175 DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n",
176 (double)offset
, (double)count
, fsp
->fsp_name
));
179 * Remove the existing lock record from the tdb lockdb
180 * before looking at POSIX locks. If this record doesn't
181 * match then don't bother looking to remove POSIX locks.
184 ok
= brl_unlock(fsp
->dev
, fsp
->inode
, fsp
->fnum
,
185 lock_pid
, sys_getpid(), conn
->cnum
, offset
, count
);
188 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
190 *ecode
= ERRnotlocked
;
194 if (!lp_posix_locking(SNUM(conn
)))
197 (void)release_posix_lock(fsp
, offset
, count
);
199 return True
; /* Did unlock */
202 /****************************************************************************
203 Remove any locks on this fd. Called from file_close().
204 ****************************************************************************/
206 void locking_close_file(files_struct
*fsp
)
208 pid_t pid
= sys_getpid();
210 if (!lp_locking(SNUM(fsp
->conn
)))
214 * Just release all the brl locks, no need to release individually.
217 brl_close(fsp
->dev
, fsp
->inode
, pid
, fsp
->conn
->cnum
, fsp
->fnum
);
219 if(lp_posix_locking(SNUM(fsp
->conn
))) {
222 * Release all the POSIX locks.
224 posix_locking_close_file(fsp
);
229 /****************************************************************************
230 Delete a record if it is for a dead process, if check_self is true, then
231 delete any records belonging to this pid also (there shouldn't be any).
232 This function is only called on locking startup and shutdown.
233 ****************************************************************************/
235 static int delete_fn(TDB_CONTEXT
*ttdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
237 struct locking_data
*data
;
238 share_mode_entry
*shares
;
240 pid_t mypid
= sys_getpid();
241 BOOL check_self
= *(BOOL
*)state
;
244 tdb_chainlock(tdb
, kbuf
);
246 data
= (struct locking_data
*)dbuf
.dptr
;
247 shares
= (share_mode_entry
*)(dbuf
.dptr
+ sizeof(*data
));
249 for (i
=0;i
<data
->num_share_mode_entries
;) {
251 if (check_self
&& (shares
[i
].pid
== mypid
)) {
252 DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n",
253 (unsigned int)shares
[i
].pid
));
254 } else if (!process_exists(shares
[i
].pid
)) {
255 DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Entry for pid %u and it no longer exists !\n",
256 (unsigned int)shares
[i
].pid
));
258 /* Process exists, leave this record alone. */
263 data
->num_share_mode_entries
--;
264 memmove(&shares
[i
], &shares
[i
+1],
265 dbuf
.dsize
- (sizeof(*data
) + (i
+1)*sizeof(*shares
)));
270 /* the record has shrunk a bit */
271 dbuf
.dsize
-= del_count
* sizeof(*shares
);
273 /* store it back in the database */
274 if (data
->num_share_mode_entries
== 0) {
275 if (tdb_delete(ttdb
, kbuf
) == -1)
278 if (tdb_store(ttdb
, kbuf
, dbuf
, TDB_REPLACE
) == -1)
282 tdb_chainunlock(tdb
, kbuf
);
286 /****************************************************************************
287 Initialise the locking functions.
288 ****************************************************************************/
290 static int open_read_only
;
292 BOOL
locking_init(int read_only
)
294 BOOL check_self
= False
;
301 tdb
= tdb_open_log(lock_path("locking.tdb"),
302 0, USE_TDB_MMAP_FLAG
|(read_only
?0x0:TDB_CLEAR_IF_FIRST
),
303 read_only
?O_RDONLY
:O_RDWR
|O_CREAT
,
307 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
311 if (!posix_locking_init(read_only
))
314 /* delete any dead locks */
316 tdb_traverse(tdb
, delete_fn
, &check_self
);
318 open_read_only
= read_only
;
323 /*******************************************************************
324 Deinitialize the share_mode management.
325 ******************************************************************/
327 BOOL
locking_end(void)
329 BOOL check_self
= True
;
331 brl_shutdown(open_read_only
);
334 /* delete any dead locks */
337 tdb_traverse(tdb
, delete_fn
, &check_self
);
339 if (tdb_close(tdb
) != 0)
346 /*******************************************************************
347 Form a static locking key for a dev/inode pair.
348 ******************************************************************/
350 static TDB_DATA
locking_key(SMB_DEV_T dev
, SMB_INO_T inode
)
352 static struct locking_key key
;
355 memset(&key
, '\0', sizeof(key
));
358 kbuf
.dptr
= (char *)&key
;
359 kbuf
.dsize
= sizeof(key
);
363 static TDB_DATA
locking_key_fsp(files_struct
*fsp
)
365 return locking_key(fsp
->dev
, fsp
->inode
);
368 #ifndef LOCK_SHARE_ENTRY_SPIN_COUNT
369 #define LOCK_SHARE_ENTRY_SPIN_COUNT 100
372 /*******************************************************************
373 Lock a hash bucket entry.
374 ******************************************************************/
376 BOOL
lock_share_entry(connection_struct
*conn
,
377 SMB_DEV_T dev
, SMB_INO_T inode
)
381 for (count
= 0; count
< LOCK_SHARE_ENTRY_SPIN_COUNT
; count
++)
382 if (tdb_chainlock(tdb
, locking_key(dev
, inode
)) == 0)
385 DEBUG(0,("lock_share_entry: locking (%d) for dev = %x, inode = %.0f failed with error %s\n",
386 count
, (unsigned int)dev
, (double)inode
, strerror(errno
) ));
389 return tdb_chainlock(tdb
, locking_key(dev
, inode
)) == 0;
393 /*******************************************************************
394 Unlock a hash bucket entry.
395 ******************************************************************/
397 void unlock_share_entry(connection_struct
*conn
,
398 SMB_DEV_T dev
, SMB_INO_T inode
)
400 tdb_chainunlock(tdb
, locking_key(dev
, inode
));
403 /*******************************************************************
404 Lock a hash bucket entry. use a fsp for convenience
405 ******************************************************************/
407 BOOL
lock_share_entry_fsp(files_struct
*fsp
)
411 for (count
= 0; count
< LOCK_SHARE_ENTRY_SPIN_COUNT
; count
++)
412 if (tdb_chainlock(tdb
, locking_key(fsp
->dev
, fsp
->inode
)) == 0)
415 DEBUG(0,("lock_share_entry_fsp: locking (%d) for dev = %x, inode = %.0f failed with error %s\n",
416 count
, (unsigned int)fsp
->dev
, (double)fsp
->inode
, strerror(errno
) ));
419 return tdb_chainlock(tdb
, locking_key(fsp
->dev
, fsp
->inode
)) == 0;
423 /*******************************************************************
424 Unlock a hash bucket entry.
425 ******************************************************************/
427 void unlock_share_entry_fsp(files_struct
*fsp
)
429 tdb_chainunlock(tdb
, locking_key(fsp
->dev
, fsp
->inode
));
432 /*******************************************************************
433 Get all share mode entries for a dev/inode pair.
434 ********************************************************************/
436 int get_share_modes(connection_struct
*conn
,
437 SMB_DEV_T dev
, SMB_INO_T inode
,
438 share_mode_entry
**shares
)
441 struct locking_data
*data
;
446 dbuf
= tdb_fetch(tdb
, locking_key(dev
, inode
));
450 data
= (struct locking_data
*)dbuf
.dptr
;
451 ret
= data
->num_share_mode_entries
;
453 *shares
= (share_mode_entry
*)memdup(dbuf
.dptr
+ sizeof(*data
), ret
* sizeof(**shares
));
462 /*******************************************************************
463 Fill a share mode entry.
464 ********************************************************************/
466 static void fill_share_mode(char *p
, files_struct
*fsp
, uint16 port
, uint16 op_type
)
468 share_mode_entry
*e
= (share_mode_entry
*)p
;
469 memset(e
, '\0', sizeof(share_mode_entry
));
470 e
->pid
= sys_getpid();
471 e
->share_mode
= fsp
->share_mode
;
473 e
->op_type
= op_type
;
474 memcpy((char *)&e
->time
, (char *)&fsp
->open_time
, sizeof(struct timeval
));
477 /*******************************************************************
478 Check if two share mode entries are identical, ignoring oplock
480 ********************************************************************/
482 BOOL
share_modes_identical( share_mode_entry
*e1
, share_mode_entry
*e2
)
484 return (e1
->pid
== e2
->pid
&&
485 e1
->share_mode
== e2
->share_mode
&&
486 e1
->time
.tv_sec
== e2
->time
.tv_sec
&&
487 e1
->time
.tv_usec
== e2
->time
.tv_usec
);
490 /*******************************************************************
491 Delete a specific share mode. Return the number
492 of entries left, and a memdup'ed copy of the entry deleted (if required).
493 Ignore if no entry deleted.
494 ********************************************************************/
496 ssize_t
del_share_entry( SMB_DEV_T dev
, SMB_INO_T inode
,
497 share_mode_entry
*entry
, share_mode_entry
**ppse
)
500 struct locking_data
*data
;
502 share_mode_entry
*shares
;
508 /* read in the existing share modes */
509 dbuf
= tdb_fetch(tdb
, locking_key(dev
, inode
));
513 data
= (struct locking_data
*)dbuf
.dptr
;
514 shares
= (share_mode_entry
*)(dbuf
.dptr
+ sizeof(*data
));
517 * Find any with this pid and delete it
518 * by overwriting with the rest of the data
522 DEBUG(10,("del_share_mode: num_share_modes = %d\n", data
->num_share_mode_entries
));
524 for (i
=0;i
<data
->num_share_mode_entries
;) {
525 if (share_modes_identical(&shares
[i
], entry
)) {
527 *ppse
= memdup(&shares
[i
], sizeof(*shares
));
528 data
->num_share_mode_entries
--;
529 memmove(&shares
[i
], &shares
[i
+1],
530 dbuf
.dsize
- (sizeof(*data
) + (i
+1)*sizeof(*shares
)));
533 DEBUG(10,("del_share_mode: deleting entry %d\n", i
));
541 /* the record may have shrunk a bit */
542 dbuf
.dsize
-= del_count
* sizeof(*shares
);
544 count
= (ssize_t
)data
->num_share_mode_entries
;
546 /* store it back in the database */
547 if (data
->num_share_mode_entries
== 0) {
548 if (tdb_delete(tdb
, locking_key(dev
, inode
)) == -1)
551 if (tdb_store(tdb
, locking_key(dev
, inode
), dbuf
, TDB_REPLACE
) == -1)
559 /*******************************************************************
560 Del the share mode of a file for this process. Return the number
561 of entries left, and a memdup'ed copy of the entry deleted.
562 ********************************************************************/
564 ssize_t
del_share_mode(files_struct
*fsp
, share_mode_entry
**ppse
)
566 share_mode_entry entry
;
569 * Fake up a share_mode_entry for comparisons.
572 fill_share_mode((char *)&entry
, fsp
, 0, 0);
573 return del_share_entry(fsp
->dev
, fsp
->inode
, &entry
, ppse
);
576 /*******************************************************************
577 Set the share mode of a file. Return False on fail, True on success.
578 ********************************************************************/
580 BOOL
set_share_mode(files_struct
*fsp
, uint16 port
, uint16 op_type
)
583 struct locking_data
*data
;
588 /* read in the existing share modes if any */
589 dbuf
= tdb_fetch(tdb
, locking_key_fsp(fsp
));
591 /* we'll need to create a new record */
594 pstrcpy(fname
, fsp
->conn
->connectpath
);
596 pstrcat(fname
, fsp
->fsp_name
);
598 size
= sizeof(*data
) + sizeof(share_mode_entry
) + strlen(fname
) + 1;
599 p
= (char *)malloc(size
);
602 data
= (struct locking_data
*)p
;
603 data
->num_share_mode_entries
= 1;
604 pstrcpy(p
+ sizeof(*data
) + sizeof(share_mode_entry
), fname
);
605 fill_share_mode(p
+ sizeof(*data
), fsp
, port
, op_type
);
608 if (tdb_store(tdb
, locking_key_fsp(fsp
), dbuf
, TDB_REPLACE
) == -1)
614 /* we're adding to an existing entry - this is a bit fiddly */
615 data
= (struct locking_data
*)dbuf
.dptr
;
617 data
->num_share_mode_entries
++;
618 size
= dbuf
.dsize
+ sizeof(share_mode_entry
);
622 memcpy(p
, dbuf
.dptr
, sizeof(*data
));
623 fill_share_mode(p
+ sizeof(*data
), fsp
, port
, op_type
);
624 memcpy(p
+ sizeof(*data
) + sizeof(share_mode_entry
), dbuf
.dptr
+ sizeof(*data
),
625 dbuf
.dsize
- sizeof(*data
));
629 if (tdb_store(tdb
, locking_key_fsp(fsp
), dbuf
, TDB_REPLACE
) == -1)
635 /*******************************************************************
636 A generic in-place modification call for share mode entries.
637 ********************************************************************/
639 static BOOL
mod_share_mode( SMB_DEV_T dev
, SMB_INO_T inode
, share_mode_entry
*entry
,
640 void (*mod_fn
)(share_mode_entry
*, SMB_DEV_T
, SMB_INO_T
, void *),
644 struct locking_data
*data
;
646 share_mode_entry
*shares
;
647 BOOL need_store
=False
;
649 /* read in the existing share modes */
650 dbuf
= tdb_fetch(tdb
, locking_key(dev
, inode
));
654 data
= (struct locking_data
*)dbuf
.dptr
;
655 shares
= (share_mode_entry
*)(dbuf
.dptr
+ sizeof(*data
));
657 /* find any with our pid and call the supplied function */
658 for (i
=0;i
<data
->num_share_mode_entries
;i
++) {
659 if (share_modes_identical(entry
, &shares
[i
])) {
660 mod_fn(&shares
[i
], dev
, inode
, param
);
665 /* if the mod fn was called then store it back */
667 if (data
->num_share_mode_entries
== 0) {
668 if (tdb_delete(tdb
, locking_key(dev
, inode
)) == -1)
671 if (tdb_store(tdb
, locking_key(dev
, inode
), dbuf
, TDB_REPLACE
) == -1)
680 /*******************************************************************
681 Static function that actually does the work for the generic function
683 ********************************************************************/
685 static void remove_share_oplock_fn(share_mode_entry
*entry
, SMB_DEV_T dev
, SMB_INO_T inode
,
688 DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n",
689 (unsigned int)dev
, (double)inode
));
690 /* Delete the oplock info. */
692 entry
->op_type
= NO_OPLOCK
;
695 /*******************************************************************
696 Remove an oplock port and mode entry from a share mode.
697 ********************************************************************/
699 BOOL
remove_share_oplock(files_struct
*fsp
)
701 share_mode_entry entry
;
703 * Fake up an entry for comparisons...
705 fill_share_mode((char *)&entry
, fsp
, 0, 0);
706 return mod_share_mode(fsp
->dev
, fsp
->inode
, &entry
, remove_share_oplock_fn
, NULL
);
709 /*******************************************************************
710 Static function that actually does the work for the generic function
712 ********************************************************************/
714 static void downgrade_share_oplock_fn(share_mode_entry
*entry
, SMB_DEV_T dev
, SMB_INO_T inode
,
717 DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n",
718 (unsigned int)dev
, (double)inode
));
719 entry
->op_type
= LEVEL_II_OPLOCK
;
722 /*******************************************************************
723 Downgrade a oplock type from exclusive to level II.
724 ********************************************************************/
726 BOOL
downgrade_share_oplock(files_struct
*fsp
)
728 share_mode_entry entry
;
730 * Fake up an entry for comparisons...
732 fill_share_mode((char *)&entry
, fsp
, 0, 0);
733 return mod_share_mode(fsp
->dev
, fsp
->inode
, &entry
, downgrade_share_oplock_fn
, NULL
);
736 /*******************************************************************
737 Get/Set the delete on close flag in a set of share modes.
738 Return False on fail, True on success.
739 ********************************************************************/
741 BOOL
modify_delete_flag( SMB_DEV_T dev
, SMB_INO_T inode
, BOOL delete_on_close
)
744 struct locking_data
*data
;
746 share_mode_entry
*shares
;
748 /* read in the existing share modes */
749 dbuf
= tdb_fetch(tdb
, locking_key(dev
, inode
));
753 data
= (struct locking_data
*)dbuf
.dptr
;
754 shares
= (share_mode_entry
*)(dbuf
.dptr
+ sizeof(*data
));
756 /* Set/Unset the delete on close element. */
757 for (i
=0;i
<data
->num_share_mode_entries
;i
++,shares
++) {
758 shares
->share_mode
= (delete_on_close
?
759 (shares
->share_mode
| DELETE_ON_CLOSE_FLAG
) :
760 (shares
->share_mode
& ~DELETE_ON_CLOSE_FLAG
) );
764 if (data
->num_share_mode_entries
) {
765 if (tdb_store(tdb
, locking_key(dev
,inode
), dbuf
, TDB_REPLACE
)==-1) {
775 /****************************************************************************
776 Traverse the whole database with this function, calling traverse_callback
778 ****************************************************************************/
780 static int traverse_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
783 struct locking_data
*data
;
784 share_mode_entry
*shares
;
788 SHAREMODE_FN(traverse_callback
) = (SHAREMODE_FN_CAST())state
;
790 data
= (struct locking_data
*)dbuf
.dptr
;
791 shares
= (share_mode_entry
*)(dbuf
.dptr
+ sizeof(*data
));
792 name
= dbuf
.dptr
+ sizeof(*data
) + data
->num_share_mode_entries
*sizeof(*shares
);
794 for (i
=0;i
<data
->num_share_mode_entries
;i
++) {
795 traverse_callback(&shares
[i
], name
);
800 /*******************************************************************
801 Call the specified function on each entry under management by the
803 ********************************************************************/
805 int share_mode_forall(SHAREMODE_FN(fn
))
809 return tdb_traverse(tdb
, traverse_fn
, (void*)fn
);