summaryrefslogtreecommitdiff
path: root/source3/locking
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2000-04-28 20:54:23 +0000
committerJeremy Allison <jra@samba.org>2000-04-28 20:54:23 +0000
commit9a5eb068ab32418e793d482db1f078f147f9ee08 (patch)
tree9939206f1f8220e16f168cba1f19f18ee25dacc6 /source3/locking
parent46e84a0090516e3ae67b3ceb06b3d9a546e8e71e (diff)
downloadsamba-9a5eb068ab32418e793d482db1f078f147f9ee08.tar.gz
samba-9a5eb068ab32418e793d482db1f078f147f9ee08.tar.bz2
samba-9a5eb068ab32418e793d482db1f078f147f9ee08.zip
Ok - this is the *third* implementation of this (third time's the charm :-).
This implementation keeps all POSIX lock records in a separate in memory tdb database only known about in locking/posix.c. In addition, the pending close fd's are also held in a tdb which has an array of fd's indexed by device and inode. The walk-split code uglyness has been moved to posix.c from brlock.c, which is the only place that needs to know about it, and the extra functions hacked into brlock to expose internal state have been removed. This implementation passes smbtorture locktest4, the only thing I need to check now for completeness is what to do about lock upgrade/downgrades which Win32 allows under some *very* strange circumstances. Jeremy. (This used to be commit 3f655de1c764b9ee1472a111621d4317f19f624d)
Diffstat (limited to 'source3/locking')
-rw-r--r--source3/locking/brlock.c296
-rw-r--r--source3/locking/locking.c641
-rw-r--r--source3/locking/posix.c322
3 files changed, 137 insertions, 1122 deletions
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index 410fb3fc0b..0ded1846b4 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -171,237 +171,6 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
}
/****************************************************************************
- Create a list of lock ranges that don't overlap a given range. Used in calculating
- POSIX lock unlocks. This is a difficult function that requires ASCII art to
- understand it :-).
-****************************************************************************/
-
-struct unlock_list *brl_unlock_list(TALLOC_CTX *ctx, struct unlock_list *ulhead,
- pid_t pid, SMB_DEV_T dev, SMB_INO_T ino)
-{
- struct lock_key key;
- TDB_DATA kbuf, dbuf;
- struct lock_struct *locks;
- int num_locks, i;
-
- /*
- * Setup the key for this fetch.
- */
- key.device = dev;
- key.inode = ino;
- kbuf.dptr = (char *)&key;
- kbuf.dsize = sizeof(key);
-
- dbuf.dptr = NULL;
-
- tdb_lockchain(tdb, kbuf);
- dbuf = tdb_fetch(tdb, kbuf);
-
- if (!dbuf.dptr) {
- tdb_unlockchain(tdb, kbuf);
- return ulhead;
- }
-
- locks = (struct lock_struct *)dbuf.dptr;
- num_locks = dbuf.dsize / sizeof(*locks);
-
- /*
- * Check the current lock list on this dev/inode pair.
- * Quit if the list is deleted.
- */
-
- DEBUG(10,("brl_unlock_list: curr: start=%.0f,size=%.0f\n",
- (double)ulhead->start, (double)ulhead->size ));
-
- for (i=0; i<num_locks && ulhead; i++) {
-
- struct lock_struct *lock = &locks[i];
- struct unlock_list *ul_curr;
-
- /* If it's not this process, ignore it. */
- if (lock->context.pid != pid)
- continue;
-
- /*
- * Walk the unlock list, checking for overlaps. Note that
- * the unlock list can expand within this loop if the current
- * range being examined needs to be split.
- */
-
- for (ul_curr = ulhead; ul_curr;) {
-
- DEBUG(10,("brl_unlock_list: lock: start=%.0f,size=%.0f:",
- (double)lock->start, (double)lock->size ));
-
- if ( (ul_curr->start >= (lock->start + lock->size)) ||
- (lock->start > (ul_curr->start + ul_curr->size))) {
-
- /* No overlap with this lock - leave this range alone. */
-/*********************************************
- +---------+
- | ul_curr |
- +---------+
- +-------+
- | lock |
- +-------+
-OR....
- +---------+
- | ul_curr |
- +---------+
-**********************************************/
-
- DEBUG(10,("no overlap case.\n" ));
-
- ul_curr = ul_curr->next;
-
- } else if ( (ul_curr->start >= lock->start) &&
- (ul_curr->start + ul_curr->size <= lock->start + lock->size) ) {
-
- /*
- * This unlock is completely overlapped by this existing lock range
- * and thus should have no effect (not be unlocked). Delete it from the list.
- */
-/*********************************************
- +---------+
- | ul_curr |
- +---------+
- +---------------------------+
- | lock |
- +---------------------------+
-**********************************************/
- /* Save the next pointer */
- struct unlock_list *ul_next = ul_curr->next;
-
- DEBUG(10,("delete case.\n" ));
-
- DLIST_REMOVE(ulhead, ul_curr);
- if(ulhead == NULL)
- break; /* No more list... */
-
- ul_curr = ul_next;
-
- } else if ( (ul_curr->start >= lock->start) &&
- (ul_curr->start < lock->start + lock->size) &&
- (ul_curr->start + ul_curr->size > lock->start + lock->size) ) {
-
- /*
- * This unlock overlaps the existing lock range at the high end.
- * Truncate by moving start to existing range end and reducing size.
- */
-/*********************************************
- +---------------+
- | ul_curr |
- +---------------+
- +---------------+
- | lock |
- +---------------+
-BECOMES....
- +-------+
- |ul_curr|
- +-------+
-**********************************************/
-
- ul_curr->size = (ul_curr->start + ul_curr->size) - (lock->start + lock->size);
- ul_curr->start = lock->start + lock->size;
-
- DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n",
- (double)ul_curr->start, (double)ul_curr->size ));
-
- ul_curr = ul_curr->next;
-
- } else if ( (ul_curr->start < lock->start) &&
- (ul_curr->start + ul_curr->size > lock->start) ) {
-
- /*
- * This unlock overlaps the existing lock range at the low end.
- * Truncate by reducing size.
- */
-/*********************************************
- +---------------+
- | ul_curr |
- +---------------+
- +---------------+
- | lock |
- +---------------+
-BECOMES....
- +-------+
- |ul_curr|
- +-------+
-**********************************************/
-
- ul_curr->size = lock->start - ul_curr->start;
-
- DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n",
- (double)ul_curr->start, (double)ul_curr->size ));
-
- ul_curr = ul_curr->next;
-
- } else if ( (ul_curr->start < lock->start) &&
- (ul_curr->start + ul_curr->size > lock->start + lock->size) ) {
- /*
- * Worst case scenario. Unlock request completely overlaps an existing
- * lock range. Split the request into two, push the new (upper) request
- * into the dlink list, and continue with the entry after ul_new (as we
- * know that ul_new will not overlap with this lock).
- */
-/*********************************************
- +---------------------------+
- | ul_curr |
- +---------------------------+
- +---------+
- | lock |
- +---------+
-BECOMES.....
- +-------+ +---------+
- |ul_curr| |ul_new |
- +-------+ +---------+
-**********************************************/
- struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx,
- sizeof(struct unlock_list));
-
- if(ul_new == NULL) {
- DEBUG(0,("brl_unlock_list: talloc fail.\n"));
- return NULL; /* The talloc_destroy takes care of cleanup. */
- }
-
- ZERO_STRUCTP(ul_new);
- ul_new->start = lock->start + lock->size;
- ul_new->size = ul_curr->start + ul_curr->size - ul_new->start;
- ul_new->smbpid = ul_curr->smbpid;
-
- /* Add into the dlink list after the ul_curr point - NOT at ulhead. */
- DLIST_ADD(ul_curr, ul_new);
-
- /* Truncate the ul_curr. */
- ul_curr->size = lock->start - ul_curr->start;
-
- DEBUG(10,("split case: curr: start=%.0f,size=%.0f \
-new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size,
- (double)ul_new->start, (double)ul_new->size ));
-
- ul_curr = ul_new->next;
-
- } else {
-
- /*
- * This logic case should never happen. Ensure this is the
- * case by forcing an abort.... Remove in production.
- */
-
- smb_panic("logic flaw in cases...\n");
- }
- } /* end for ( ul_curr = ulhead; ul_curr;) */
- } /* end for (i=0; i<num_locks && ul_head; i++) */
-
- tdb_unlockchain(tdb, kbuf);
-
- if (dbuf.dptr)
- free(dbuf.dptr);
-
- return ulhead;
-}
-
-/****************************************************************************
Unlock a range of bytes.
****************************************************************************/
@@ -426,7 +195,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
dbuf = tdb_fetch(tdb, kbuf);
if (!dbuf.dptr) {
- DEBUG(0,("brl_unlock: tdb_fetch failed !\n"));
+ DEBUG(10,("brl_unlock: tdb_fetch failed !\n"));
goto fail;
}
@@ -591,69 +360,6 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
}
/****************************************************************************
- Return a lock list associated with an open file.
-****************************************************************************/
-
-struct unlock_list *brl_getlocklist( TALLOC_CTX *ctx, SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
-{
- struct lock_key key;
- TDB_DATA kbuf, dbuf;
- int i, count;
- struct lock_struct *locks;
- struct unlock_list *ulist = NULL;
-
- key.device = dev;
- key.inode = ino;
- kbuf.dptr = (char *)&key;
- kbuf.dsize = sizeof(key);
-
- dbuf.dptr = NULL;
-
- tdb_lockchain(tdb, kbuf);
- dbuf = tdb_fetch(tdb, kbuf);
-
- if (!dbuf.dptr) {
- tdb_unlockchain(tdb, kbuf);
- return NULL;
- }
-
- /* There are existing locks - allocate an entry for each one. */
- locks = (struct lock_struct *)dbuf.dptr;
- count = dbuf.dsize / sizeof(*locks);
-
- for (i=0; i<count; i++) {
- struct lock_struct *lock = &locks[i];
-
- if (lock->context.tid == tid &&
- lock->context.pid == pid &&
- lock->fnum == fnum) {
-
- struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx,
- sizeof(struct unlock_list));
-
- if(ul_new == NULL) {
- DEBUG(0,("brl_getlocklist: talloc fail.\n"));
- return NULL; /* The talloc_destroy takes care of cleanup. */
- }
-
- ZERO_STRUCTP(ul_new);
- ul_new->start = lock->start;
- ul_new->size = lock->size;
- ul_new->smbpid = lock->context.smbpid;
-
- DLIST_ADD(ulist, ul_new);
- }
- }
-
- if (dbuf.dptr)
- free(dbuf.dptr);
- tdb_unlockchain(tdb, kbuf);
-
- return ulist;
-}
-
-
-/****************************************************************************
Traverse the whole database with this function, calling traverse_callback
on each lock.
****************************************************************************/
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index fa56e0a628..75198d6303 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -42,190 +42,6 @@ int global_smbpid;
/* the locking database handle */
static TDB_CONTEXT *tdb;
-/*
- * Doubly linked list to hold pending closes needed for
- * POSIX locks. This may be changed to use a hash table (as
- * in lib/hash.c if this is too slow in use.... JRA.
- */
-
-struct pending_closes {
- struct pending_closes *next;
- struct pending_closes *prev;
- SMB_DEV_T dev;
- SMB_INO_T inode;
- int num_posix_locks;
- size_t fd_array_size;
- int *fd_array;
-};
-
-static struct pending_closes *pending_close_list = NULL;
-
-/****************************************************************************
- Find a dev/inode pair in the pending close list.
-****************************************************************************/
-
-static struct pending_closes *find_pending_close_entry(SMB_DEV_T dev, SMB_INO_T inode)
-{
- struct pending_closes *pc;
-
- for(pc = pending_close_list; pc; pc = pc->next) {
- if (dev == pc->dev && inode == pc->inode) {
- DLIST_PROMOTE(pending_close_list,pc);
- return pc;
- }
- }
-
- return NULL;
-}
-
-/****************************************************************************
- Add an fd into the pending close array.
-****************************************************************************/
-
-static BOOL add_fd_to_close_entry(struct pending_closes *pc, int fd)
-{
- if ((pc->fd_array = (int *)Realloc(pc->fd_array, (pc->fd_array_size + 1)*sizeof(int))) == NULL) {
- DEBUG(0,("add_fd_to_close_entry: Unable to increase fd_array !\n"));
- return False;
- }
-
- pc->fd_array[pc->fd_array_size] = fd;
- pc->fd_array_size++;
-
- DEBUG(10,("add_fd_to_close_entry: added fd = %d, size = %u : dev = %.0f, ino = %.0f\n",
- fd, (unsigned int)pc->fd_array_size, (double)pc->dev, (double)pc->inode ));
-
- return True;
-}
-
-/****************************************************************************
- Deal with pending closes needed by POSIX locking support.
-****************************************************************************/
-
-int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
-{
- struct pending_closes *pc;
- int saved_errno = 0;
- int ret;
- size_t i;
-
- if (!lp_posix_locking(SNUM(conn))) {
- ret = conn->vfs_ops.close(fsp->fd);
- fsp->fd = -1;
- return ret;
- }
-
- pc = find_pending_close_entry(fsp->dev, fsp->inode);
-
- if (!pc) {
- /*
- * No other open with a POSIX lock on this dev/inode within this smbd.
- * Just close the fd.
- */
- ret = conn->vfs_ops.close(fsp->fd);
- fsp->fd = -1;
- return ret;
- }
-
- if (pc->num_posix_locks) {
- /*
- * There are outstanding locks on this dev/inode pair.
- * Add our fd to the list and set fsp->fd to -1 to
- * stop the close.
- */
-
- if (!add_fd_to_close_entry(pc, fsp->fd))
- return False;
-
- fsp->fd = -1;
- return 0;
- }
-
- DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)pc->fd_array_size ));
-
- /*
- * This is the last close. If there are pending fd's close them
- * now. Save the errno just in case.
- */
-
- for(i = 0; i < pc->fd_array_size; i++) {
- if (pc->fd_array[i] != -1) {
- if (conn->vfs_ops.close(pc->fd_array[i]) == -1) {
- saved_errno = errno;
- }
- }
- }
-
- if (pc->fd_array)
- free((char *)pc->fd_array);
-
- DLIST_REMOVE(pending_close_list, pc);
-
- free((char *)pc);
-
- ret = conn->vfs_ops.close(fsp->fd);
-
- if (saved_errno != 0) {
- errno = saved_errno;
- ret = -1;
- }
-
- fsp->fd = -1;
-
- return ret;
-}
-
-/****************************************************************************
- A POSIX lock was granted. Increment the lock list count (create if needed).
-****************************************************************************/
-
-static void increment_posix_lock_list(files_struct *fsp)
-{
- struct pending_closes *pc;
-
- if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) == NULL) {
- if (!(pc = (struct pending_closes *)malloc(sizeof(struct pending_closes)))) {
- DEBUG(0,("increment_lock_list: malloc fail.\n"));
- return;
- }
- ZERO_STRUCTP(pc);
- pc->dev = fsp->dev;
- pc->inode = fsp->inode;
- DLIST_ADD(pending_close_list, pc);
-
- DEBUG(10,("increment_posix_lock_list: creating entry for file %s: dev = %.0f, ino = %.0f\n",
- fsp->fsp_name, (double)fsp->dev, (double)fsp->inode ));
- }
-
- pc->num_posix_locks++;
-
- DEBUG(10,("increment_posix_lock_list: entry for file %s: dev = %.0f, ino = %.0f, num_locks = %d\n",
- fsp->fsp_name, (double)pc->dev, (double)pc->inode, pc->num_posix_locks ));
-}
-
-
-/****************************************************************************
- A POSIX lock was granted. Decrement the lock list count.
-****************************************************************************/
-
-static void decrement_posix_lock_list(files_struct *fsp)
-{
- struct pending_closes *pc;
-
- pc = find_pending_close_entry(fsp->dev, fsp->inode);
-
- if (pc == NULL) {
- smb_panic("decrement_lock_list: Unlock not found !\n");
- }
-
- pc->num_posix_locks--;
-
- DEBUG(10,("decrement_posix_lock_list: entry for file %s: dev = %.0f, ino = %.0f, num_locks = %d\n",
- fsp->fsp_name, (double)pc->dev, (double)pc->inode, pc->num_posix_locks ));
-
- SMB_ASSERT(pc->num_posix_locks >= 0);
-}
-
/****************************************************************************
Debugging aid :-).
****************************************************************************/
@@ -236,347 +52,6 @@ static const char *lock_type_name(enum brl_type lock_type)
}
/****************************************************************************
- Utility function to map a lock type correctly depending on the open
- mode of a file.
-****************************************************************************/
-
-static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
-{
- if((lock_type == WRITE_LOCK) && !fsp->can_write) {
- /*
- * Many UNIX's cannot get a write lock on a file opened read-only.
- * Win32 locking semantics allow this.
- * Do the best we can and attempt a read-only lock.
- */
- DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));
- return F_RDLCK;
- } else if((lock_type == READ_LOCK) && !fsp->can_read) {
- /*
- * Ditto for read locks on write only files.
- */
- DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n"));
- return F_WRLCK;
- }
-
- /*
- * This return should be the most normal, as we attempt
- * to always open files read/write.
- */
-
- return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK;
-}
-
-/****************************************************************************
- Check to see if the given unsigned lock range is within the possible POSIX
- range. Modifies the given args to be in range if possible, just returns
- False if not.
-****************************************************************************/
-
-static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
- SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
-{
- SMB_OFF_T offset;
- SMB_OFF_T count;
-
-#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
-
- SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
- SMB_OFF_T mask = (mask2<<1);
- SMB_OFF_T neg_mask = ~mask;
-
- /*
- * In this case SMB_OFF_T is 64 bits,
- * and the underlying system can handle 64 bit signed locks.
- * Cast to signed type.
- */
-
- offset = (SMB_OFF_T)u_offset;
- count = (SMB_OFF_T)u_count;
-
- /*
- * Deal with a very common case of count of all ones.
- * (lock entire file).
- */
-
- if(count == (SMB_OFF_T)-1)
- count &= ~mask;
-
- /*
- * POSIX lock ranges cannot be negative.
- * Fail if any combination becomes negative.
- */
-
- if(offset < 0 || count < 0 || (offset + count < 0)) {
- DEBUG(10,("posix_lock_in_range: negative range: offset = %.0f, count = %.0f. Ignoring lock.\n",
- (double)offset, (double)count ));
- return False;
- }
-
- /*
- * In this case SMB_OFF_T is 64 bits, the offset and count
- * fit within the positive range, and the underlying
- * system can handle 64 bit locks. Just return as the
- * cast values are ok.
- */
-
-#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
-
- /*
- * In this case either SMB_OFF_T is 32 bits,
- * or the underlying system cannot handle 64 bit signed locks.
- * Either way we have to try and mangle to fit within 31 bits.
- * This is difficult.
- */
-
-#if defined(HAVE_BROKEN_FCNTL64_LOCKS)
-
- /*
- * SMB_OFF_T is 64 bits, but we need to use 31 bits due to
- * broken large locking.
- */
-
- /*
- * Deal with a very common case of count of all ones.
- * (lock entire file).
- */
-
- if(u_count == (SMB_BIG_UINT)-1)
- count = 0x7FFFFFFF;
-
- if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) {
- DEBUG(10,("posix_lock_in_range: top 32 bits not zero. offset = %.0f, count = %.0f. Ignoring lock.\n",
- (double)u_offset, (double)u_count ));
- /* Top 32 bits of offset or count were not zero. */
- return False;
- }
-
- /* Cast from 64 bits unsigned to 64 bits signed. */
- offset = (SMB_OFF_T)u_offset;
- count = (SMB_OFF_T)u_count;
-
- /*
- * Check if we are within the 2^31 range.
- */
-
- {
- int32 low_offset = (int32)offset;
- int32 low_count = (int32)count;
-
- if(low_offset < 0 || low_count < 0 || (low_offset + low_count < 0)) {
- DEBUG(10,("posix_lock_in_range: not within 2^31 range. low_offset = %d, low_count = %d. Ignoring lock.\n",
- low_offset, low_count ));
- return False;
- }
- }
-
- /*
- * Ok - we can map from a 64 bit number to a 31 bit lock.
- */
-
-#else /* HAVE_BROKEN_FCNTL64_LOCKS */
-
- /*
- * SMB_OFF_T is 32 bits.
- */
-
-#if defined(HAVE_LONGLONG)
-
- /*
- * SMB_BIG_UINT is 64 bits, we can do a 32 bit shift.
- */
-
- /*
- * Deal with a very common case of count of all ones.
- * (lock entire file).
- */
-
- if(u_count == (SMB_BIG_UINT)-1)
- count = 0x7FFFFFFF;
-
- if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) {
- DEBUG(10,("posix_lock_in_range: top 32 bits not zero. u_offset = %.0f, u_count = %.0f. Ignoring lock.\n",
- (double)u_offset, (double)u_count ));
- return False;
- }
-
- /* Cast from 64 bits unsigned to 32 bits signed. */
- offset = (SMB_OFF_T)u_offset;
- count = (SMB_OFF_T)u_count;
-
- /*
- * Check if we are within the 2^31 range.
- */
-
- if(offset < 0 || count < 0 || (offset + count < 0)) {
- DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n",
- (int)offset, (int)count ));
- return False;
- }
-
-#else /* HAVE_LONGLONG */
-
- /*
- * SMB_BIG_UINT and SMB_OFF_T are both 32 bits,
- * just cast.
- */
-
- /*
- * Deal with a very common case of count of all ones.
- * (lock entire file).
- */
-
- if(u_count == (SMB_BIG_UINT)-1)
- count = 0x7FFFFFFF;
-
- /* Cast from 32 bits unsigned to 32 bits signed. */
- offset = (SMB_OFF_T)u_offset;
- count = (SMB_OFF_T)u_count;
-
- /*
- * Check if we are within the 2^31 range.
- */
-
- if(offset < 0 || count < 0 || (offset + count < 0)) {
- DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n",
- (int)offset, (int)count ));
- return False;
- }
-
-#endif /* HAVE_LONGLONG */
-#endif /* LARGE_SMB_OFF_T */
-#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
-
- /*
- * The mapping was successful.
- */
-
- DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n",
- (double)offset, (double)count ));
-
- *offset_out = offset;
- *count_out = count;
-
- return True;
-}
-
-/****************************************************************************
- POSIX function to see if a file region is locked. Returns True if the
- region is locked, False otherwise.
-****************************************************************************/
-
-static BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type)
-{
- SMB_OFF_T offset;
- SMB_OFF_T count;
-
- DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
- fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) ));
-
- /*
- * If the requested lock won't fit in the POSIX range, we will
- * never set it, so presume it is not locked.
- */
-
- if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
- return False;
-
- /*
- * Note that most UNIX's can *test* for a write lock on
- * a read-only fd, just not *set* a write lock on a read-only
- * fd. So we don't need to use map_lock_type here.
- */
-
- return fcntl_lock(fsp->fd,SMB_F_GETLK,offset,count,lock_type);
-}
-
-/****************************************************************************
- POSIX function to acquire a lock. Returns True if the
- lock could be granted, False if not.
-****************************************************************************/
-
-static BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type)
-{
- SMB_OFF_T offset;
- SMB_OFF_T count;
- BOOL ret = True;
-
- DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n",
- fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) ));
-
- /*
- * If the requested lock won't fit in the POSIX range, we will
- * pretend it was successful.
- */
-
- if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
- increment_posix_lock_list(fsp);
- return True;
- }
-
- /*
- * Note that setting multiple overlapping read locks on different
- * file descriptors will not be held separately by the kernel (POSIX
- * braindamage), but will be merged into one continuous read lock
- * range. We cope with this case in the release_posix_lock code
- * below. JRA.
- */
-
- ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,map_posix_lock_type(fsp,lock_type));
-
- if (ret)
- increment_posix_lock_list(fsp);
-
- return ret;
-}
-
-/****************************************************************************
- POSIX function to release a lock given a list. Returns True if the
- lock could be released, False if not.
-****************************************************************************/
-
-static BOOL release_posix_lock(files_struct *fsp, struct unlock_list *ulist)
-{
- BOOL ret = True;
-
- for(; ulist; ulist = ulist->next) {
- SMB_OFF_T offset = ulist->start;
- SMB_OFF_T count = ulist->size;
-
- DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n",
- fsp->fsp_name, (double)offset, (double)count ));
-
- if(count == 0) {
-
- /*
- * This lock must overlap with an existing read-only lock
- * held by another fd. Don't do any POSIX call.
- */
-
- continue;
- }
-
- /*
- * If the requested lock won't fit in the POSIX range, we will
- * pretend it was successful.
- */
-
- if(!posix_lock_in_range(&offset, &count, offset, count))
- continue;
-
- ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK);
- }
-
- /*
- * We treat this as one unlock request for POSIX accounting purposes even
- * if it may have been split into multiple smaller POSIX unlock ranges.
- */
-
- decrement_posix_lock_list(fsp);
-
- return ret;
-}
-
-/****************************************************************************
Utility function called to see if a file region is locked.
****************************************************************************/
@@ -675,10 +150,6 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn,
int *eclass,uint32 *ecode)
{
BOOL ok = False;
- TALLOC_CTX *ul_ctx = NULL;
- struct unlock_list *ulist = NULL;
- struct unlock_list *ul = NULL;
- pid_t pid;
if (!lp_locking(SNUM(conn)))
return(True);
@@ -698,10 +169,8 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn,
* match then don't bother looking to remove POSIX locks.
*/
- pid = getpid();
-
ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
- global_smbpid, pid, conn->cnum, offset, count);
+ global_smbpid, getpid(), conn->cnum, offset, count);
if (!ok) {
DEBUG(10,("do_unlock: returning ERRlock.\n" ));
@@ -713,47 +182,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn,
if (!lp_posix_locking(SNUM(conn)))
return True;
- if ((ul_ctx = talloc_init()) == NULL) {
- DEBUG(0,("do_unlock: unable to init talloc context.\n"));
- return True; /* Not a fatal error. */
- }
-
- if ((ul = (struct unlock_list *)talloc(ul_ctx, sizeof(struct unlock_list))) == NULL) {
- DEBUG(0,("do_unlock: unable to talloc unlock list.\n"));
- talloc_destroy(ul_ctx);
- return True; /* Not a fatal error. */
- }
-
- /*
- * Create the initial list entry containing the
- * lock we want to remove.
- */
-
- ZERO_STRUCTP(ul);
- ul->start = offset;
- ul->size = count;
- ul->smbpid = global_smbpid;
-
- DLIST_ADD(ulist, ul);
-
- /*
- * The following call calculates if there are any
- * overlapping read locks held by this process on
- * other fd's open on the same file and creates a
- * list of unlock ranges that will allow other
- * POSIX lock ranges to remain on the file whilst the
- * unlocks are performed.
- */
-
- ulist = brl_unlock_list(ul_ctx, ulist, pid, fsp->dev, fsp->inode);
-
- /*
- * Release the POSIX locks on the list of ranges returned.
- */
-
- (void)release_posix_lock(fsp, ulist);
-
- talloc_destroy(ul_ctx);
+ (void)release_posix_lock(fsp, offset, count);
return True; /* Did unlock */
}
@@ -769,66 +198,19 @@ void locking_close_file(files_struct *fsp)
if (!lp_locking(SNUM(fsp->conn)))
return;
- if(lp_posix_locking(SNUM(fsp->conn))) {
-
- TALLOC_CTX *ul_ctx = NULL;
- struct unlock_list *ul = NULL;
- int eclass;
- uint32 ecode;
- struct pending_closes *pc;
-
- /*
- * Optimization for the common case where we are the only
- * opener of a file. If all fd entries are our own, we don't
- * need to explicitly release all the locks via the POSIX functions,
- * we can just release all the brl locks, as in the no POSIX locking case.
- */
-
- if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) != NULL) {
-
- if (pc->fd_array_size == 1 && pc->fd_array[0] == fsp->fd ) {
- /*
- * Just release all the brl locks, no need to release individually.
- */
-
- brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
- return;
- }
- }
-
- if ((ul_ctx = talloc_init()) == NULL) {
- DEBUG(0,("locking_close_file: unable to init talloc context.\n"));
- return;
- }
-
- /*
- * We need to release all POSIX locks we have on this
- * fd. Get all our existing locks from the tdb locking database.
- */
-
- ul = brl_getlocklist(ul_ctx, fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
-
- /*
- * Now unlock all of them. This will remove the brl entry also
- * for each lock. Note we need to make sure the global_smbpid matches
- * the one associated with each lock in case the client plays games
- * with smbpids (like smbtorture does :-).
- */
+ /*
+ * Just release all the brl locks, no need to release individually.
+ */
- for(; ul; ul = ul->next) {
- global_smbpid = ul->smbpid;
- do_unlock(fsp,fsp->conn,ul->size,ul->start,&eclass,&ecode);
- }
-
- talloc_destroy(ul_ctx);
+ brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
- } else {
+ if(lp_posix_locking(SNUM(fsp->conn))) {
- /*
- * Just release all the brl locks, no need to release individually.
+ /*
+ * Release all the POSIX locks.
*/
+ posix_locking_close_file(fsp);
- brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
}
}
@@ -851,6 +233,9 @@ BOOL locking_init(int read_only)
return False;
}
+ if (!posix_locking_init())
+ return False;
+
return True;
}
diff --git a/source3/locking/posix.c b/source3/locking/posix.c
index f05a0a2a31..0fcba3432d 100644
--- a/source3/locking/posix.c
+++ b/source3/locking/posix.c
@@ -53,7 +53,7 @@ struct posix_lock {
};
/*
- * The data in POSIX pending close records is an unsorted linear array of ints
+ * The data in POSIX pending close records is an unsorted linear array of int
* records. It is unnecessary to store the count as tdb provides the
* size of the record.
*/
@@ -73,7 +73,7 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
{
static struct posix_lock_key key;
TDB_DATA kbuf;
- key.dev = dev;
+ key.device = dev;
key.inode = inode;
kbuf.dptr = (char *)&key;
kbuf.dsize = sizeof(key);
@@ -95,10 +95,8 @@ static TDB_DATA locking_key_fsp(files_struct *fsp)
static BOOL add_fd_to_close_entry(files_struct *fsp)
{
- struct posix_lock_key = locking_key_fsp(fsp);
- TDB_DATA kbuf, dbuf;
- size_t count = 0;
- int *fd_array = NULL;
+ TDB_DATA kbuf = locking_key_fsp(fsp);
+ TDB_DATA dbuf;
dbuf.dptr = NULL;
@@ -129,8 +127,7 @@ static BOOL add_fd_to_close_entry(files_struct *fsp)
static void delete_close_entries(files_struct *fsp)
{
- struct posix_lock_key = locking_key_fsp(fsp);
- TDB_DATA kbuf, dbuf;
+ TDB_DATA kbuf = locking_key_fsp(fsp);
tdb_lockchain(posix_pending_close_tdb, kbuf);
if (tdb_delete(posix_pending_close_tdb, kbuf) == -1)
@@ -145,8 +142,8 @@ static void delete_close_entries(files_struct *fsp)
static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
{
- struct posix_lock_key = locking_key_fsp(fsp);
- TDB_DATA kbuf, dbuf;
+ TDB_DATA kbuf = locking_key_fsp(fsp);
+ TDB_DATA dbuf;
size_t count = 0;
*entries = NULL;
@@ -175,8 +172,8 @@ static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries)
{
- struct posix_lock_key = locking_key_fsp(fsp);
- TDB_DATA kbuf, dbuf;
+ TDB_DATA kbuf = locking_key_fsp(fsp);
+ TDB_DATA dbuf;
size_t count = 0;
*entries = NULL;
@@ -191,8 +188,8 @@ static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entr
return 0;
}
- *entries = (struct posix_lock_struct *)dbuf.dptr;
- count = (size_t)(dbuf.dsize / sizeof(struct posix_lock_struct));
+ *entries = (struct posix_lock *)dbuf.dptr;
+ count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
tdb_unlockchain(posix_lock_tdb, kbuf);
@@ -251,7 +248,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
* from the tdb and close them all.
*/
- count = get_posix_pending_close_entries(fsp, &fd_array)
+ count = get_posix_pending_close_entries(fsp, &fd_array);
if (count) {
DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
@@ -307,8 +304,8 @@ static const char *posix_lock_type_name(int lock_type)
static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type)
{
- struct posix_lock_key = locking_key_fsp(fsp);
- TDB_DATA kbuf, dbuf;
+ TDB_DATA kbuf = locking_key_fsp(fsp);
+ TDB_DATA dbuf;
struct posix_lock pl;
/*
@@ -325,14 +322,14 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s
tdb_lockchain(posix_lock_tdb, kbuf);
dbuf = tdb_fetch(posix_lock_tdb, kbuf);
- dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*pl));
+ dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl));
if (!dbuf.dptr) {
DEBUG(0,("add_posix_lock_entry: Realloc fail !\n"));
goto fail;
}
- memcpy(dbuf.dptr + dbuf.dsize, rec, sizeof(*pl));
- dbuf.dsize += sizeof(*pl);
+ memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl));
+ dbuf.dsize += sizeof(pl);
if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name));
@@ -351,7 +348,7 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s
fail:
if (dbuf.dptr)
free(dbuf.dptr);
- tdb_unlockchain(tdb, kbuf);
+ tdb_unlockchain(posix_lock_tdb, kbuf);
return False;
}
@@ -361,8 +358,8 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s
static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size)
{
- struct posix_lock_key = locking_key_fsp(fsp);
- TDB_DATA kbuf, dbuf;
+ TDB_DATA kbuf = locking_key_fsp(fsp);
+ TDB_DATA dbuf;
struct posix_lock *locks;
size_t i, count;
@@ -377,13 +374,13 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_
}
/* There are existing locks - find a match. */
- locks = (struct lock_struct *)dbuf.dptr;
- count = (size_t(dbuf.dsize / sizeof(*locks));
+ locks = (struct posix_lock *)dbuf.dptr;
+ count = (size_t)(dbuf.dsize / sizeof(*locks));
for (i=0; i<count; i++) {
struct posix_lock *pl = &locks[i];
- if (pl->fd == fd &&
+ if (pl->fd == fsp->fd &&
pl->start == start &&
pl->size == size) {
/* Found it - delete it. */
@@ -394,11 +391,11 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_
memmove(&locks[i], &locks[i+1], sizeof(*locks)*((count-1) - i));
}
dbuf.dsize -= sizeof(*locks);
- tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
+ tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);
}
free(dbuf.dptr);
- tdb_unlockchain(tdb, kbuf);
+ tdb_unlockchain(posix_lock_tdb, kbuf);
return True;
}
}
@@ -408,7 +405,7 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_
fail:
if (dbuf.dptr)
free(dbuf.dptr);
- tdb_unlockchain(tdb, kbuf);
+ tdb_unlockchain(posix_lock_tdb, kbuf);
return False;
}
@@ -648,7 +645,7 @@ BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_co
int posix_lock_type = map_posix_lock_type(fsp,lock_type);
DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
- fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) ));
+ fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
/*
* If the requested lock won't fit in the POSIX range, we will
@@ -680,7 +677,7 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou
int posix_lock_type = map_posix_lock_type(fsp,lock_type);
DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n",
- fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) ));
+ fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
/*
* If the requested lock won't fit in the POSIX range, we will
@@ -691,9 +688,9 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou
return True;
/*
- * Note that setting multiple overlapping read locks on different
+ * Note that setting multiple overlapping locks on different
* file descriptors will not be held separately by the kernel (POSIX
- * braindamage), but will be merged into one continuous read lock
+ * braindamage), but will be merged into one continuous lock
* range. We cope with this case in the release_posix_lock code
* below. JRA.
*/
@@ -716,7 +713,6 @@ struct unlock_list {
struct unlock_list *prev;
SMB_OFF_T start;
SMB_OFF_T size;
- int fd;
};
/****************************************************************************
@@ -727,49 +723,37 @@ struct unlock_list {
static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list *ulhead, files_struct *fsp)
{
- struct lock_key key;
- TDB_DATA kbuf, dbuf;
- struct lock_struct *locks;
- int num_locks, i;
-
- /*
- * Setup the key for this fetch.
- */
- key.device = dev;
- key.inode = ino;
- kbuf.dptr = (char *)&key;
- kbuf.dsize = sizeof(key);
+ TDB_DATA kbuf = locking_key_fsp(fsp);
+ TDB_DATA dbuf;
+ struct posix_lock *locks;
+ size_t num_locks, i;
dbuf.dptr = NULL;
- tdb_lockchain(tdb, kbuf);
- dbuf = tdb_fetch(tdb, kbuf);
+ tdb_lockchain(posix_lock_tdb, kbuf);
+ dbuf = tdb_fetch(posix_lock_tdb, kbuf);
if (!dbuf.dptr) {
- tdb_unlockchain(tdb, kbuf);
+ tdb_unlockchain(posix_lock_tdb, kbuf);
return ulhead;
}
- locks = (struct lock_struct *)dbuf.dptr;
- num_locks = dbuf.dsize / sizeof(*locks);
+ locks = (struct posix_lock *)dbuf.dptr;
+ num_locks = (size_t)(dbuf.dsize / sizeof(*locks));
/*
* Check the current lock list on this dev/inode pair.
* Quit if the list is deleted.
*/
- DEBUG(10,("brl_unlock_list: curr: start=%.0f,size=%.0f\n",
+ DEBUG(10,("posix_unlock_list: curr: start=%.0f,size=%.0f\n",
(double)ulhead->start, (double)ulhead->size ));
for (i=0; i<num_locks && ulhead; i++) {
- struct lock_struct *lock = &locks[i];
+ struct posix_lock *lock = &locks[i];
struct unlock_list *ul_curr;
- /* If it's not this process, ignore it. */
- if (lock->context.pid != pid)
- continue;
-
/*
* Walk the unlock list, checking for overlaps. Note that
* the unlock list can expand within this loop if the current
@@ -778,7 +762,7 @@ static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list
for (ul_curr = ulhead; ul_curr;) {
- DEBUG(10,("brl_unlock_list: lock: start=%.0f,size=%.0f:",
+ DEBUG(10,("posix_unlock_list: lock: start=%.0f,size=%.0f:",
(double)lock->start, (double)lock->size ));
if ( (ul_curr->start >= (lock->start + lock->size)) ||
@@ -908,14 +892,13 @@ BECOMES.....
sizeof(struct unlock_list));
if(ul_new == NULL) {
- DEBUG(0,("brl_unlock_list: talloc fail.\n"));
+ DEBUG(0,("posix_unlock_list: talloc fail.\n"));
return NULL; /* The talloc_destroy takes care of cleanup. */
}
ZERO_STRUCTP(ul_new);
ul_new->start = lock->start + lock->size;
ul_new->size = ul_curr->start + ul_curr->size - ul_new->start;
- ul_new->smbpid = ul_curr->smbpid;
/* Add into the dlink list after the ul_curr point - NOT at ulhead. */
DLIST_ADD(ul_curr, ul_new);
@@ -941,7 +924,7 @@ new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size,
} /* end for ( ul_curr = ulhead; ul_curr;) */
} /* end for (i=0; i<num_locks && ul_head; i++) */
- tdb_unlockchain(tdb, kbuf);
+ tdb_unlockchain(posix_lock_tdb, kbuf);
if (dbuf.dptr)
free(dbuf.dptr);
@@ -950,11 +933,11 @@ new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size,
}
/****************************************************************************
- POSIX function to release a lock given a list. Returns True if the
+ POSIX function to release a lock. Returns True if the
lock could be released, False if not.
****************************************************************************/
-static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
+BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
{
SMB_OFF_T offset;
SMB_OFF_T count;
@@ -964,7 +947,7 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG
struct unlock_list *ul = NULL;
DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n",
- fsp->fsp_name, (double)offset, (double)count ));
+ fsp->fsp_name, (double)u_offset, (double)u_count ));
/*
* If the requested lock won't fit in the POSIX range, we will
@@ -974,6 +957,13 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG
if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
return True;
+ /*
+ * We treat this as one unlock request for POSIX accounting purposes even
+ * if it may have been split into multiple smaller POSIX unlock ranges.
+ */
+
+ delete_posix_lock_entry(fsp, offset, count);
+
if ((ul_ctx = talloc_init()) == NULL) {
DEBUG(0,("release_posix_lock: unable to init talloc context.\n"));
return True; /* Not a fatal error. */
@@ -993,15 +983,14 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG
ZERO_STRUCTP(ul);
ul->start = offset;
ul->size = count;
- ul->fd = fsp->fd;
DLIST_ADD(ulist, ul);
/*
* The following call calculates if there are any
- * overlapping read locks held by this process on
- * other fd's open on the same file and creates a
- * list of unlock ranges that will allow other
+ * overlapping locks held by this process on
+ * fd's open on the same file and creates a
+ * list of unlock ranges that will allow
* POSIX lock ranges to remain on the file whilst the
* unlocks are performed.
*/
@@ -1013,108 +1002,43 @@ static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG
*/
for(; ulist; ulist = ulist->next) {
- SMB_OFF_T offset = ulist->start;
- SMB_OFF_T count = ulist->size;
-
- DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n",
- (double)offset, (double)count ));
+ offset = ulist->start;
+ count = ulist->size;
if(u_count == 0) {
/*
- * This lock must overlap with an existing read-only lock
- * held by another fd. Don't do any POSIX call.
+ * This lock must overlap with an existing lock.
+ * Don't do any POSIX call.
*/
continue;
}
- /*
- * If the requested lock won't fit in the POSIX range, we will
- * pretend it was successful.
- */
-
- if(!posix_lock_in_range(&offset, &count, offset, count))
- continue;
-
DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n",
(double)offset, (double)count ));
- ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK);
+ if (!fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK))
+ ret = False;
}
talloc_destroy(ul_ctx);
- /*
- * We treat this as one unlock request for POSIX accounting purposes even
- * if it may have been split into multiple smaller POSIX unlock ranges.
- */
-
- delete_posix_lock_entry(fsp->
-
return ret;
}
/****************************************************************************
- Return a lock list associated with an open file.
+ Remove all lock entries for a specific dev/inode pair from the tdb.
****************************************************************************/
-struct unlock_list *brl_getlocklist( TALLOC_CTX *ctx, SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
+static void delete_posix_lock_entries(files_struct *fsp)
{
- struct lock_key key;
- TDB_DATA kbuf, dbuf;
- int i, count;
- struct lock_struct *locks;
- struct unlock_list *ulist = NULL;
-
- key.device = dev;
- key.inode = ino;
- kbuf.dptr = (char *)&key;
- kbuf.dsize = sizeof(key);
-
- dbuf.dptr = NULL;
-
- tdb_lockchain(tdb, kbuf);
- dbuf = tdb_fetch(tdb, kbuf);
-
- if (!dbuf.dptr) {
- tdb_unlockchain(tdb, kbuf);
- return NULL;
- }
-
- /* There are existing locks - allocate an entry for each one. */
- locks = (struct lock_struct *)dbuf.dptr;
- count = dbuf.dsize / sizeof(*locks);
-
- for (i=0; i<count; i++) {
- struct lock_struct *lock = &locks[i];
-
- if (lock->context.tid == tid &&
- lock->context.pid == pid &&
- lock->fnum == fnum) {
-
- struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx,
- sizeof(struct unlock_list));
-
- if(ul_new == NULL) {
- DEBUG(0,("brl_getlocklist: talloc fail.\n"));
- return NULL; /* The talloc_destroy takes care of cleanup. */
- }
-
- ZERO_STRUCTP(ul_new);
- ul_new->start = lock->start;
- ul_new->size = lock->size;
- ul_new->smbpid = lock->context.smbpid;
-
- DLIST_ADD(ulist, ul_new);
- }
- }
+ TDB_DATA kbuf = locking_key_fsp(fsp);
- if (dbuf.dptr)
- free(dbuf.dptr);
- tdb_unlockchain(tdb, kbuf);
-
- return ulist;
+ tdb_lockchain(posix_lock_tdb, kbuf);
+ if (tdb_delete(posix_lock_tdb, kbuf) == -1)
+ DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
+ tdb_unlockchain(posix_lock_tdb, kbuf);
}
/****************************************************************************
@@ -1123,86 +1047,86 @@ struct unlock_list *brl_getlocklist( TALLOC_CTX *ctx, SMB_DEV_T dev, SMB_INO_T i
void posix_locking_close_file(files_struct *fsp)
{
- TALLOC_CTX *ul_ctx = NULL;
- struct unlock_list *ul = NULL;
- int eclass;
- uint32 ecode;
- struct pending_closes *pc;
-
- /*
- * Optimization for the common case where we are the only
- * opener of a file. If all fd entries are our own, we don't
- * need to explicitly release all the locks via the POSIX functions,
- * we can just release all the brl locks, as in the no POSIX locking case.
- */
-
- if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) != NULL) {
-
- if (pc->fd_array_size == 1 && pc->fd_array[0] == fsp->fd ) {
- /*
- * Just release all the brl locks, no need to release individually.
- */
-
- brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
- return;
- }
- }
-
- if ((ul_ctx = talloc_init()) == NULL) {
- DEBUG(0,("locking_close_file: unable to init talloc context.\n"));
- return;
- }
+ struct posix_lock *entries = NULL;
+ size_t count, i;
- /*
- * We need to release all POSIX locks we have on this
- * fd. Get all our existing locks from the tdb locking database.
- */
+ /*
+ * Optimization for the common case where we are the only
+ * opener of a file. If all fd entries are our own, we don't
+ * need to explicitly release all the locks via the POSIX functions,
+ * we can just remove all the entries in the tdb and allow the
+ * close to remove the real locks.
+ */
- ul = brl_getlocklist(ul_ctx, fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
+ count = get_posix_lock_entries(fsp, &entries);
- /*
- * Now unlock all of them. This will remove the brl entry also
- * for each lock. Note we need to make sure the global_smbpid matches
- * the one associated with each lock in case the client plays games
- * with smbpids (like smbtorture does :-).
- */
+ if (count == 0) {
+ DEBUG(10,("posix_locking_close_file: file %s has no outstanding locks.\n", fsp->fsp_name ));
+ return;
+ }
- for(; ul; ul = ul->next) {
- global_smbpid = ul->smbpid;
- do_unlock(fsp,fsp->conn,ul->size,ul->start,&eclass,&ecode);
- }
-
- talloc_destroy(ul_ctx);
+ for (i = 0; i < count; i++) {
+ if (entries[i].fd != fsp->fd )
+ break;
+ }
- } else {
+ if (i == count) {
+ /* All locks are ours. */
+ DEBUG(10,("posix_locking_close_file: file %s has %u outstanding locks, but all on one fd.\n",
+ fsp->fsp_name, (unsigned int)count ));
+ free((char *)entries);
+ delete_posix_lock_entries(fsp);
+ return;
+ }
- /*
- * Just release all the brl locks, no need to release individually.
- */
+ /*
+ * Difficult case. We need to delete all our locks, whilst leaving
+ * all other POSIX locks in place.
+ */
- brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
+ for (i = 0; i < count; i++) {
+ struct posix_lock *pl = &entries[i];
+ release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size );
}
+ free((char *)entries);
}
/*******************************************************************
Create the in-memory POSIX lock databases.
********************************************************************/
-void posix_lock_init(void)
+BOOL posix_locking_init(void)
{
if (posix_lock_tdb && posix_pending_close_tdb)
- return;
+ return True;
if (!posix_lock_tdb)
posix_lock_tdb = tdb_open(NULL, 0, TDB_CLEAR_IF_FIRST,
O_RDWR|O_CREAT, 0644);
if (!posix_lock_tdb) {
DEBUG(0,("Failed to open POSIX byte range locking database.\n"));
+ return False;
}
if (!posix_pending_close_tdb)
posix_pending_close_tdb = tdb_open(NULL, 0, TDB_CLEAR_IF_FIRST,
O_RDWR|O_CREAT, 0644);
if (!posix_pending_close_tdb) {
DEBUG(0,("Failed to open POSIX pending close database.\n"));
+ return False;
}
+
+ return True;
+}
+
+/*******************************************************************
+ Delete the in-memory POSIX lock databases.
+********************************************************************/
+
+BOOL posix_locking_end(void)
+{
+ if (posix_lock_tdb && tdb_close(posix_lock_tdb) != 0)
+ return False;
+ if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0)
+ return False;
+ return True;
}