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.
41 /* the locking database handle */
42 static TDB_CONTEXT
*tdb
;
44 /****************************************************************************
46 ****************************************************************************/
48 static const char *lock_type_name(enum brl_type lock_type
)
50 return (lock_type
== READ_LOCK
) ? "READ" : "WRITE";
53 /****************************************************************************
54 Utility function called to see if a file region is locked.
55 If check_self is True, then checks on our own fd with the same locking context
56 are still made. If check_self is False, then checks are not made on our own fd
57 with the same locking context are not made.
58 ****************************************************************************/
60 BOOL
is_locked(files_struct
*fsp
,connection_struct
*conn
,
61 SMB_BIG_UINT count
,SMB_BIG_UINT offset
,
62 enum brl_type lock_type
, BOOL check_self
)
64 int snum
= SNUM(conn
);
70 if (!lp_locking(snum
) || !lp_strict_locking(snum
))
73 ret
= !brl_locktest(fsp
->dev
, fsp
->inode
, fsp
->fnum
,
74 global_smbpid
, sys_getpid(), conn
->cnum
,
75 offset
, count
, lock_type
, check_self
);
77 DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n",
78 (double)offset
, (double)count
, ret
? "locked" : "unlocked",
82 * There is no lock held by an SMB daemon, check to
83 * see if there is a POSIX lock from a UNIX or NFS process.
86 if(!ret
&& lp_posix_locking(snum
)) {
87 ret
= is_posix_locked(fsp
, offset
, count
, lock_type
);
89 DEBUG(10,("is_locked: posix start=%.0f len=%.0f %s for file %s\n",
90 (double)offset
, (double)count
, ret
? "locked" : "unlocked",
97 /****************************************************************************
98 Utility function called by locking requests.
99 ****************************************************************************/
101 static NTSTATUS
do_lock(files_struct
*fsp
,connection_struct
*conn
, uint16 lock_pid
,
102 SMB_BIG_UINT count
,SMB_BIG_UINT offset
,enum brl_type lock_type
)
106 if (!lp_locking(SNUM(conn
)))
109 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
112 DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n",
113 lock_type_name(lock_type
), (double)offset
, (double)count
, fsp
->fsp_name
));
115 if (OPEN_FSP(fsp
) && fsp
->can_lock
&& (fsp
->conn
== conn
)) {
116 status
= brl_lock(fsp
->dev
, fsp
->inode
, fsp
->fnum
,
117 lock_pid
, sys_getpid(), conn
->cnum
,
121 if (NT_STATUS_IS_OK(status
) && lp_posix_locking(SNUM(conn
))) {
124 * Try and get a POSIX lock on this range.
125 * Note that this is ok if it is a read lock
126 * overlapping on a different fd. JRA.
129 if (!set_posix_lock(fsp
, offset
, count
, lock_type
)) {
130 status
= NT_STATUS_LOCK_NOT_GRANTED
;
132 * We failed to map - we must now remove the brl
135 (void)brl_unlock(fsp
->dev
, fsp
->inode
, fsp
->fnum
,
136 lock_pid
, sys_getpid(), conn
->cnum
,
145 /****************************************************************************
146 Utility function called by locking requests. This is *DISGISTING*. It also
147 appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000
148 is so slow on the locking tests...... ? This is the reason. Much though I hate
149 it, we need this. JRA.
150 ****************************************************************************/
152 NTSTATUS
do_lock_spin(files_struct
*fsp
,connection_struct
*conn
, uint16 lock_pid
,
153 SMB_BIG_UINT count
,SMB_BIG_UINT offset
,enum brl_type lock_type
)
155 int j
, maxj
= lp_lock_spin_count();
156 int sleeptime
= lp_lock_sleep_time();
157 NTSTATUS status
, ret
;
162 ret
= NT_STATUS_OK
; /* to keep dumb compilers happy */
164 for (j
= 0; j
< maxj
; j
++) {
165 status
= do_lock(fsp
, conn
, lock_pid
, count
, offset
, lock_type
);
166 if (!NT_STATUS_EQUAL(status
, NT_STATUS_LOCK_NOT_GRANTED
) &&
167 !NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
170 /* if we do fail then return the first error code we got */
175 sys_usleep(sleeptime
);
180 /****************************************************************************
181 Utility function called by unlocking requests.
182 ****************************************************************************/
184 NTSTATUS
do_unlock(files_struct
*fsp
,connection_struct
*conn
, uint16 lock_pid
,
185 SMB_BIG_UINT count
,SMB_BIG_UINT offset
)
189 if (!lp_locking(SNUM(conn
)))
192 if (!OPEN_FSP(fsp
) || !fsp
->can_lock
|| (fsp
->conn
!= conn
)) {
193 return NT_STATUS_INVALID_HANDLE
;
196 DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n",
197 (double)offset
, (double)count
, fsp
->fsp_name
));
200 * Remove the existing lock record from the tdb lockdb
201 * before looking at POSIX locks. If this record doesn't
202 * match then don't bother looking to remove POSIX locks.
205 ok
= brl_unlock(fsp
->dev
, fsp
->inode
, fsp
->fnum
,
206 lock_pid
, sys_getpid(), conn
->cnum
, offset
, count
);
209 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
210 return NT_STATUS_RANGE_NOT_LOCKED
;
213 if (!lp_posix_locking(SNUM(conn
)))
216 (void)release_posix_lock(fsp
, offset
, count
);
221 /****************************************************************************
222 Remove any locks on this fd. Called from file_close().
223 ****************************************************************************/
225 void locking_close_file(files_struct
*fsp
)
227 pid_t pid
= sys_getpid();
229 if (!lp_locking(SNUM(fsp
->conn
)))
233 * Just release all the brl locks, no need to release individually.
236 brl_close(fsp
->dev
, fsp
->inode
, pid
, fsp
->conn
->cnum
, fsp
->fnum
);
238 if(lp_posix_locking(SNUM(fsp
->conn
))) {
241 * Release all the POSIX locks.
243 posix_locking_close_file(fsp
);
249 /* Not currently used. JRA */
251 /****************************************************************************
252 Delete a record if it is for a dead process, if check_self is true, then
253 delete any records belonging to this pid also (there shouldn't be any).
254 This function is only called on locking startup and shutdown.
255 ****************************************************************************/
257 static int delete_fn(TDB_CONTEXT
*ttdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
259 struct locking_data
*data
;
260 share_mode_entry
*shares
;
262 pid_t mypid
= sys_getpid();
263 BOOL check_self
= *(BOOL
*)state
;
266 tdb_chainlock(tdb
, kbuf
);
268 data
= (struct locking_data
*)dbuf
.dptr
;
269 shares
= (share_mode_entry
*)(dbuf
.dptr
+ sizeof(*data
));
271 for (i
=0;i
<data
->u
.num_share_mode_entries
;) {
273 if (check_self
&& (shares
[i
].pid
== mypid
)) {
274 DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n",
275 (unsigned int)shares
[i
].pid
));
276 } else if (!process_exists(shares
[i
].pid
)) {
277 DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Entry for pid %u and it no longer exists !\n",
278 (unsigned int)shares
[i
].pid
));
280 /* Process exists, leave this record alone. */
285 data
->u
.num_share_mode_entries
--;
286 memmove(&shares
[i
], &shares
[i
+1],
287 dbuf
.dsize
- (sizeof(*data
) + (i
+1)*sizeof(*shares
)));
292 /* the record has shrunk a bit */
293 dbuf
.dsize
-= del_count
* sizeof(*shares
);
295 /* store it back in the database */
296 if (data
->u
.num_share_mode_entries
== 0) {
297 if (tdb_delete(ttdb
, kbuf
) == -1)
300 if (tdb_store(ttdb
, kbuf
, dbuf
, TDB_REPLACE
) == -1)
304 tdb_chainunlock(tdb
, kbuf
);
309 /****************************************************************************
310 Initialise the locking functions.
311 ****************************************************************************/
313 static int open_read_only
;
315 BOOL
locking_init(int read_only
)
322 tdb
= tdb_open_log(lock_path("locking.tdb"),
323 0, TDB_DEFAULT
|(read_only
?0x0:TDB_CLEAR_IF_FIRST
),
324 read_only
?O_RDONLY
:O_RDWR
|O_CREAT
,
328 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
332 if (!posix_locking_init(read_only
))
335 open_read_only
= read_only
;
340 /*******************************************************************
341 Deinitialize the share_mode management.
342 ******************************************************************/
344 BOOL
locking_end(void)
347 brl_shutdown(open_read_only
);
350 if (tdb_close(tdb
) != 0)
357 /*******************************************************************
358 Form a static locking key for a dev/inode pair.
359 ******************************************************************/
361 static TDB_DATA
locking_key(SMB_DEV_T dev
, SMB_INO_T inode
)
363 static struct locking_key key
;
366 memset(&key
, '\0', sizeof(key
));
369 kbuf
.dptr
= (char *)&key
;
370 kbuf
.dsize
= sizeof(key
);
374 static TDB_DATA
locking_key_fsp(files_struct
*fsp
)
376 return locking_key(fsp
->dev
, fsp
->inode
);
379 /*******************************************************************
380 Lock a hash bucket entry.
381 ******************************************************************/
383 BOOL
lock_share_entry(connection_struct
*conn
,
384 SMB_DEV_T dev
, SMB_INO_T inode
)
386 return tdb_chainlock(tdb
, locking_key(dev
, inode
)) == 0;
389 /*******************************************************************
390 Unlock a hash bucket entry.
391 ******************************************************************/
393 void unlock_share_entry(connection_struct
*conn
,
394 SMB_DEV_T dev
, SMB_INO_T inode
)
396 tdb_chainunlock(tdb
, locking_key(dev
, inode
));
399 /*******************************************************************
400 Lock a hash bucket entry. use a fsp for convenience
401 ******************************************************************/
403 BOOL
lock_share_entry_fsp(files_struct
*fsp
)
405 return tdb_chainlock(tdb
, locking_key(fsp
->dev
, fsp
->inode
)) == 0;
408 /*******************************************************************
409 Unlock a hash bucket entry.
410 ******************************************************************/
412 void unlock_share_entry_fsp(files_struct
*fsp
)
414 tdb_chainunlock(tdb
, locking_key(fsp
->dev
, fsp
->inode
));
417 /*******************************************************************
418 Print out a share mode.
419 ********************************************************************/
421 static char *share_mode_str(int num
, share_mode_entry
*e
)
423 static pstring share_str
;
425 slprintf(share_str
, sizeof(share_str
)-1, "share_mode_entry[%d]: \
426 pid = %u, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f",
427 num
, e
->pid
, e
->share_mode
, (unsigned int)e
->desired_access
, e
->op_port
, e
->op_type
, e
->share_file_id
,
428 (unsigned int)e
->dev
, (double)e
->inode
);
433 /*******************************************************************
434 Print out a share mode table.
435 ********************************************************************/
437 static void print_share_mode_table(struct locking_data
*data
)
439 int num_share_modes
= data
->u
.num_share_mode_entries
;
440 share_mode_entry
*shares
= (share_mode_entry
*)(data
+ 1);
443 for (i
= 0; i
< num_share_modes
; i
++) {
444 share_mode_entry
*entry_p
= &shares
[i
];
445 DEBUG(10,("print_share_mode_table: %s\n", share_mode_str(i
, entry_p
) ));
449 /*******************************************************************
450 Get all share mode entries for a dev/inode pair.
451 ********************************************************************/
453 int get_share_modes(connection_struct
*conn
,
454 SMB_DEV_T dev
, SMB_INO_T inode
,
455 share_mode_entry
**pp_shares
)
458 struct locking_data
*data
;
460 share_mode_entry
*shares
= NULL
;
464 dbuf
= tdb_fetch(tdb
, locking_key(dev
, inode
));
468 data
= (struct locking_data
*)dbuf
.dptr
;
469 num_share_modes
= data
->u
.num_share_mode_entries
;
470 if(num_share_modes
) {
474 shares
= (share_mode_entry
*)memdup(dbuf
.dptr
+ sizeof(*data
),
475 num_share_modes
* sizeof(share_mode_entry
));
478 SAFE_FREE(dbuf
.dptr
);
483 * Ensure that each entry has a real process attached.
486 for (i
= 0; i
< num_share_modes
; ) {
487 share_mode_entry
*entry_p
= &shares
[i
];
488 if (process_exists(entry_p
->pid
)) {
489 DEBUG(10,("get_share_modes: %s\n", share_mode_str(i
, entry_p
) ));
492 DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i
, entry_p
) ));
493 memcpy( &shares
[i
], &shares
[i
+1],
494 sizeof(share_mode_entry
) * (num_share_modes
- i
- 1));
500 /* Did we delete any ? If so, re-store in tdb. */
502 data
->u
.num_share_mode_entries
= num_share_modes
;
505 memcpy(dbuf
.dptr
+ sizeof(*data
), shares
,
506 num_share_modes
* sizeof(share_mode_entry
));
508 /* The record has shrunk a bit */
509 dbuf
.dsize
-= del_count
* sizeof(share_mode_entry
);
511 if (tdb_store(tdb
, locking_key(dev
, inode
), dbuf
, TDB_REPLACE
) == -1) {
513 SAFE_FREE(dbuf
.dptr
);
519 SAFE_FREE(dbuf
.dptr
);
521 return num_share_modes
;
524 /*******************************************************************
525 Fill a share mode entry.
526 ********************************************************************/
528 static void fill_share_mode(char *p
, files_struct
*fsp
, uint16 port
, uint16 op_type
)
530 share_mode_entry
*e
= (share_mode_entry
*)p
;
531 void *x
= &e
->time
; /* Needed to force alignment. p may not be aligned.... */
533 memset(e
, '\0', sizeof(share_mode_entry
));
534 e
->pid
= sys_getpid();
535 e
->share_mode
= fsp
->share_mode
;
536 e
->desired_access
= fsp
->desired_access
;
538 e
->op_type
= op_type
;
539 memcpy(x
, &fsp
->open_time
, sizeof(struct timeval
));
540 e
->share_file_id
= fsp
->file_id
;
542 e
->inode
= fsp
->inode
;
545 /*******************************************************************
546 Check if two share mode entries are identical, ignoring oplock
547 and port info and desired_access.
548 ********************************************************************/
550 BOOL
share_modes_identical( share_mode_entry
*e1
, share_mode_entry
*e2
)
552 #if 1 /* JRA PARANOIA TEST - REMOVE LATER */
553 if (e1
->pid
== e2
->pid
&&
554 e1
->share_file_id
== e2
->share_file_id
&&
555 e1
->dev
== e2
->dev
&&
556 e1
->inode
== e2
->inode
&&
557 (e1
->share_mode
& ~DELETE_ON_CLOSE_FLAG
) != (e2
->share_mode
& ~DELETE_ON_CLOSE_FLAG
)) {
558 DEBUG(0,("PANIC: share_modes_identical: share_mode missmatch (e1 = %u, e2 = %u). Logic error.\n",
559 (unsigned int)(e1
->share_mode
& ~DELETE_ON_CLOSE_FLAG
),
560 (unsigned int)(e2
->share_mode
& ~DELETE_ON_CLOSE_FLAG
) ));
561 smb_panic("PANIC: share_modes_identical logic error.\n");
565 return (e1
->pid
== e2
->pid
&&
566 (e1
->share_mode
& ~DELETE_ON_CLOSE_FLAG
) == (e2
->share_mode
& ~DELETE_ON_CLOSE_FLAG
) &&
567 e1
->dev
== e2
->dev
&&
568 e1
->inode
== e2
->inode
&&
569 e1
->share_file_id
== e2
->share_file_id
);
572 /*******************************************************************
573 Delete a specific share mode. Return the number
574 of entries left, and a memdup'ed copy of the entry deleted (if required).
575 Ignore if no entry deleted.
576 ********************************************************************/
578 ssize_t
del_share_entry( SMB_DEV_T dev
, SMB_INO_T inode
,
579 share_mode_entry
*entry
, share_mode_entry
**ppse
)
582 struct locking_data
*data
;
584 share_mode_entry
*shares
;
590 /* read in the existing share modes */
591 dbuf
= tdb_fetch(tdb
, locking_key(dev
, inode
));
595 data
= (struct locking_data
*)dbuf
.dptr
;
596 shares
= (share_mode_entry
*)(dbuf
.dptr
+ sizeof(*data
));
599 * Find any with this pid and delete it
600 * by overwriting with the rest of the data
604 DEBUG(10,("del_share_entry: num_share_modes = %d\n", data
->u
.num_share_mode_entries
));
606 for (i
=0;i
<data
->u
.num_share_mode_entries
;) {
607 if (share_modes_identical(&shares
[i
], entry
)) {
608 DEBUG(10,("del_share_entry: deleted %s\n",
609 share_mode_str(i
, &shares
[i
]) ));
611 *ppse
= memdup(&shares
[i
], sizeof(*shares
));
612 data
->u
.num_share_mode_entries
--;
613 memmove(&shares
[i
], &shares
[i
+1],
614 dbuf
.dsize
- (sizeof(*data
) + (i
+1)*sizeof(*shares
)));
617 DEBUG(10,("del_share_entry: deleting entry %d\n", i
));
625 /* the record may have shrunk a bit */
626 dbuf
.dsize
-= del_count
* sizeof(*shares
);
628 count
= (ssize_t
)data
->u
.num_share_mode_entries
;
630 /* store it back in the database */
631 if (data
->u
.num_share_mode_entries
== 0) {
632 if (tdb_delete(tdb
, locking_key(dev
, inode
)) == -1)
635 if (tdb_store(tdb
, locking_key(dev
, inode
), dbuf
, TDB_REPLACE
) == -1)
639 DEBUG(10,("del_share_entry: Remaining table.\n"));
640 print_share_mode_table((struct locking_data
*)dbuf
.dptr
);
641 SAFE_FREE(dbuf
.dptr
);
645 /*******************************************************************
646 Del the share mode of a file for this process. Return the number
647 of entries left, and a memdup'ed copy of the entry deleted.
648 ********************************************************************/
650 ssize_t
del_share_mode(files_struct
*fsp
, share_mode_entry
**ppse
)
652 share_mode_entry entry
;
655 * Fake up a share_mode_entry for comparisons.
658 fill_share_mode((char *)&entry
, fsp
, 0, 0);
659 return del_share_entry(fsp
->dev
, fsp
->inode
, &entry
, ppse
);
662 /*******************************************************************
663 Set the share mode of a file. Return False on fail, True on success.
664 ********************************************************************/
666 BOOL
set_share_mode(files_struct
*fsp
, uint16 port
, uint16 op_type
)
669 struct locking_data
*data
;
674 /* read in the existing share modes if any */
675 dbuf
= tdb_fetch(tdb
, locking_key_fsp(fsp
));
677 /* we'll need to create a new record */
680 pstrcpy(fname
, fsp
->conn
->connectpath
);
682 pstrcat(fname
, fsp
->fsp_name
);
684 size
= sizeof(*data
) + sizeof(share_mode_entry
) + strlen(fname
) + 1;
685 p
= (char *)malloc(size
);
688 data
= (struct locking_data
*)p
;
689 data
->u
.num_share_mode_entries
= 1;
691 DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n",
694 pstrcpy(p
+ sizeof(*data
) + sizeof(share_mode_entry
), fname
);
695 fill_share_mode(p
+ sizeof(*data
), fsp
, port
, op_type
);
698 if (tdb_store(tdb
, locking_key_fsp(fsp
), dbuf
, TDB_REPLACE
) == -1)
701 print_share_mode_table((struct locking_data
*)p
);
707 /* we're adding to an existing entry - this is a bit fiddly */
708 data
= (struct locking_data
*)dbuf
.dptr
;
710 data
->u
.num_share_mode_entries
++;
712 DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n",
713 fsp
->fsp_name
, data
->u
.num_share_mode_entries
));
715 size
= dbuf
.dsize
+ sizeof(share_mode_entry
);
719 memcpy(p
, dbuf
.dptr
, sizeof(*data
));
720 fill_share_mode(p
+ sizeof(*data
), fsp
, port
, op_type
);
721 memcpy(p
+ sizeof(*data
) + sizeof(share_mode_entry
), dbuf
.dptr
+ sizeof(*data
),
722 dbuf
.dsize
- sizeof(*data
));
723 SAFE_FREE(dbuf
.dptr
);
726 if (tdb_store(tdb
, locking_key_fsp(fsp
), dbuf
, TDB_REPLACE
) == -1)
728 print_share_mode_table((struct locking_data
*)p
);
733 /*******************************************************************
734 A generic in-place modification call for share mode entries.
735 ********************************************************************/
737 static BOOL
mod_share_mode( SMB_DEV_T dev
, SMB_INO_T inode
, share_mode_entry
*entry
,
738 void (*mod_fn
)(share_mode_entry
*, SMB_DEV_T
, SMB_INO_T
, void *),
742 struct locking_data
*data
;
744 share_mode_entry
*shares
;
745 BOOL need_store
=False
;
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 /* find any with our pid and call the supplied function */
757 for (i
=0;i
<data
->u
.num_share_mode_entries
;i
++) {
758 if (share_modes_identical(entry
, &shares
[i
])) {
759 mod_fn(&shares
[i
], dev
, inode
, param
);
764 /* if the mod fn was called then store it back */
766 if (data
->u
.num_share_mode_entries
== 0) {
767 if (tdb_delete(tdb
, locking_key(dev
, inode
)) == -1)
770 if (tdb_store(tdb
, locking_key(dev
, inode
), dbuf
, TDB_REPLACE
) == -1)
775 SAFE_FREE(dbuf
.dptr
);
779 /*******************************************************************
780 Static function that actually does the work for the generic function
782 ********************************************************************/
784 static void remove_share_oplock_fn(share_mode_entry
*entry
, SMB_DEV_T dev
, SMB_INO_T inode
,
787 DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n",
788 (unsigned int)dev
, (double)inode
));
789 /* Delete the oplock info. */
791 entry
->op_type
= NO_OPLOCK
;
794 /*******************************************************************
795 Remove an oplock port and mode entry from a share mode.
796 ********************************************************************/
798 BOOL
remove_share_oplock(files_struct
*fsp
)
800 share_mode_entry entry
;
802 * Fake up an entry for comparisons...
804 fill_share_mode((char *)&entry
, fsp
, 0, 0);
805 return mod_share_mode(fsp
->dev
, fsp
->inode
, &entry
, remove_share_oplock_fn
, NULL
);
808 /*******************************************************************
809 Static function that actually does the work for the generic function
811 ********************************************************************/
813 static void downgrade_share_oplock_fn(share_mode_entry
*entry
, SMB_DEV_T dev
, SMB_INO_T inode
,
816 DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n",
817 (unsigned int)dev
, (double)inode
));
818 entry
->op_type
= LEVEL_II_OPLOCK
;
821 /*******************************************************************
822 Downgrade a oplock type from exclusive to level II.
823 ********************************************************************/
825 BOOL
downgrade_share_oplock(files_struct
*fsp
)
827 share_mode_entry entry
;
829 * Fake up an entry for comparisons...
831 fill_share_mode((char *)&entry
, fsp
, 0, 0);
832 return mod_share_mode(fsp
->dev
, fsp
->inode
, &entry
, downgrade_share_oplock_fn
, NULL
);
835 /*******************************************************************
836 Get/Set the delete on close flag in a set of share modes.
837 Return False on fail, True on success.
838 ********************************************************************/
840 BOOL
modify_delete_flag( SMB_DEV_T dev
, SMB_INO_T inode
, BOOL delete_on_close
)
843 struct locking_data
*data
;
845 share_mode_entry
*shares
;
847 /* read in the existing share modes */
848 dbuf
= tdb_fetch(tdb
, locking_key(dev
, inode
));
852 data
= (struct locking_data
*)dbuf
.dptr
;
853 shares
= (share_mode_entry
*)(dbuf
.dptr
+ sizeof(*data
));
855 /* Set/Unset the delete on close element. */
856 for (i
=0;i
<data
->u
.num_share_mode_entries
;i
++,shares
++) {
857 shares
->share_mode
= (delete_on_close
?
858 (shares
->share_mode
| DELETE_ON_CLOSE_FLAG
) :
859 (shares
->share_mode
& ~DELETE_ON_CLOSE_FLAG
) );
863 if (data
->u
.num_share_mode_entries
) {
864 if (tdb_store(tdb
, locking_key(dev
,inode
), dbuf
, TDB_REPLACE
)==-1) {
865 SAFE_FREE(dbuf
.dptr
);
870 SAFE_FREE(dbuf
.dptr
);
874 /****************************************************************************
875 Traverse the whole database with this function, calling traverse_callback
877 ****************************************************************************/
879 static int traverse_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
882 struct locking_data
*data
;
883 share_mode_entry
*shares
;
887 SHAREMODE_FN(traverse_callback
) = (SHAREMODE_FN_CAST())state
;
889 data
= (struct locking_data
*)dbuf
.dptr
;
890 shares
= (share_mode_entry
*)(dbuf
.dptr
+ sizeof(*data
));
891 name
= dbuf
.dptr
+ sizeof(*data
) + data
->u
.num_share_mode_entries
*sizeof(*shares
);
893 for (i
=0;i
<data
->u
.num_share_mode_entries
;i
++) {
894 traverse_callback(&shares
[i
], name
);
899 /*******************************************************************
900 Call the specified function on each entry under management by the
902 ********************************************************************/
904 int share_mode_forall(SHAREMODE_FN(fn
))
908 return tdb_traverse(tdb
, traverse_fn
, (void*)fn
);