r16883: Restructure the code in locking/posix.c to get ready to
authorJeremy Allison <jra@samba.org>
Sat, 8 Jul 2006 20:16:35 +0000 (20:16 +0000)
committerJeremy Allison <jra@samba.org>
Sat, 8 Jul 2006 20:16:35 +0000 (20:16 +0000)
add the mapping from CIFS POSIX locks to system POSIX
locks. No difference in the lock tests in Samba4 lock
tests for Windows locks. Next will come the code to
map the CIFS POSIX locks onto system locks. I will
add Samba4 torture test code to test this.
Jeremy.

source/include/smb.h
source/locking/brlock.c
source/locking/posix.c

index a870fca8eef7584d11d5eda2d08d6effb623fff9..fb54d458e9a923f09d95f88145c85dd5d078c30f 100644 (file)
@@ -859,6 +859,16 @@ struct parm_struct {
 enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_LOCK, UNLOCK_LOCK};
 enum brl_flavour {WINDOWS_LOCK = 0, POSIX_LOCK = 1};
 
+/* This contains elements that differentiate locks. The smbpid is a
+   client supplied pid, and is essentially the locking context for
+   this client */
+
+struct lock_context {
+        uint16 smbpid;
+        uint16 tid;
+        struct process_id pid;
+};
+
 /* The key used in the brlock database. */
 
 struct lock_key {
index de6ecde0557d86991371892b2869cbd167cd5c11..1dccaba7fa21fd58eb4bfe990e475d27cc2faa82 100644 (file)
 
 #define ZERO_ZERO 0
 
-/* This contains elements that differentiate locks. The smbpid is a
-   client supplied pid, and is essentially the locking context for
-   this client */
-
-struct lock_context {
-       uint16 smbpid;
-       uint16 tid;
-       struct process_id pid;
-};
-
 /* The data in brlock records is an unsorted linear array of these
    records.  It is unnecessary to store the count as tdb provides the
    size of the record */
@@ -83,7 +73,7 @@ static void print_lock_struct(unsigned int i, struct lock_struct *pls)
  See if two locking contexts are equal.
 ****************************************************************************/
 
-static BOOL brl_same_context(const struct lock_context *ctx1, 
+BOOL brl_same_context(const struct lock_context *ctx1, 
                             const struct lock_context *ctx2)
 {
        return (procid_equal(&ctx1->pid, &ctx2->pid) &&
@@ -343,13 +333,16 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
 
        /* We can get the Windows lock, now see if it needs to
           be mapped into a lower level POSIX one, and if so can
-          we get it ? We tell the lower lock layer about the
-          lock type so it can cope with the difference between
-          Windows "stacking" locks and POSIX "flat" ones. */
+          we get it ? */
 
        if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) {
-               if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, WINDOWS_LOCK)) {
-                       if (errno == EACCES || errno == EAGAIN) {
+               int errno_ret;
+               if (!set_posix_lock_windows_flavour(fsp,
+                               plock->start,
+                               plock->size,
+                               plock->lock_type,
+                               &errno_ret)) {
+                       if (errno_ret == EACCES || errno_ret == EAGAIN) {
                                return NT_STATUS_FILE_LOCK_CONFLICT;
                        } else {
                                return map_nt_error_from_unix(errno);
@@ -375,9 +368,9 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
  Cope with POSIX range splits and merges.
 ****************************************************************************/
 
-static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr,
-                                               const struct lock_struct *ex,
-                                               const struct lock_struct *plock,
+static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr,              /* Output array. */
+                                               const struct lock_struct *ex,           /* existing lock. */
+                                               const struct lock_struct *plock,        /* proposed lock. */
                                                BOOL *lock_was_added)
 {
        BOOL lock_types_differ = (ex->lock_type != plock->lock_type);
@@ -577,6 +570,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
                        BOOL *my_lock_ctx)
 {
        unsigned int i, count;
+       files_struct *fsp = br_lck->fsp;
        struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
        struct lock_struct *tp;
        BOOL lock_was_added = False;
@@ -633,18 +627,18 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
 
        /* We can get the POSIX lock, now see if it needs to
           be mapped into a lower level POSIX one, and if so can
-          we get it ? We well the lower lock layer about the
-          lock type so it can cope with the difference between
-          Windows "stacking" locks and POSIX "flat" ones. */
-
-#if 0
-       /* FIXME - this call doesn't work correctly yet for POSIX locks... */
+          we get it ? */
 
        if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) {
-               files_struct *fsp = br_lck->fsp;
-
-               if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, POSIX_LOCK)) {
-                       if (errno == EACCES || errno == EAGAIN) {
+               int errno_ret;
+
+               if (!set_posix_lock_posix_flavour(fsp,
+                               plock->start,
+                               plock->size,
+                               plock->lock_type,
+                               &plock->context,
+                               &errno_ret)) {
+                       if (errno_ret == EACCES || errno_ret == EAGAIN) {
                                SAFE_FREE(tp);
                                return NT_STATUS_FILE_LOCK_CONFLICT;
                        } else {
@@ -653,7 +647,6 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
                        }
                }
        }
-#endif
 
        if (!lock_was_added) {
                memcpy(&tp[count], plock, sizeof(struct lock_struct));
@@ -783,9 +776,11 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
                return False;
        }
 
-       /* Unlock any POSIX regions. */
+       /* Unlock the underlying POSIX regions. */
        if(lp_posix_locking(br_lck->fsp->conn->cnum)) {
-               release_posix_lock(br_lck->fsp, plock->start, plock->size);
+               release_posix_lock_windows_flavour(br_lck->fsp,
+                               plock->start,
+                               plock->size);
        }
 
        /* Send unlock messages to any pending waiters that overlap. */
@@ -933,14 +928,10 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
                return True;
        }
 
-#if 0
-       /* FIXME - this call doesn't work correctly yet for POSIX locks... */
-
        /* Unlock any POSIX regions. */
        if(lp_posix_locking(br_lck->fsp->conn->cnum)) {
-               release_posix_lock(br_lck->fsp, plock->start, plock->size);
+               release_posix_lock_posix_flavour(br_lck->fsp, plock->start, plock->size, &plock->context);
        }
-#endif
 
        /* Realloc so we don't leak entries per unlock call. */
        if (count) {
index 4a5f59b622d5f2b8b60c8ddd0ae2bad4bec77ea0..9650914e30c92bfbab9ef188e848d75601681a15 100644 (file)
@@ -1,7 +1,7 @@
 /* 
    Unix SMB/CIFS implementation.
    Locking functions
-   Copyright (C) Jeremy Allison 1992-2000
+   Copyright (C) Jeremy Allison 1992-2006
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -50,728 +50,881 @@ struct posix_lock {
        SMB_OFF_T start;
        SMB_OFF_T size;
        int lock_type;
+       enum brl_flavour lock_flav;
+       struct lock_context lock_ctx;
 };
 
-/*
- * 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.
- */
-
-/* The key used in both the POSIX databases. */
-
-struct posix_lock_key {
-       SMB_DEV_T device;
-       SMB_INO_T inode;
-}; 
-
-/*******************************************************************
- Form a static locking key for a dev/inode pair.
-******************************************************************/
-
-static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
-{
-       static struct posix_lock_key key;
-       TDB_DATA kbuf;
-
-       memset(&key, '\0', sizeof(key));
-       key.device = dev;
-       key.inode = inode;
-       kbuf.dptr = (char *)&key;
-       kbuf.dsize = sizeof(key);
-       return kbuf;
-}
-
-/*******************************************************************
- Convenience function to get a key from an fsp.
-******************************************************************/
-
-static TDB_DATA locking_key_fsp(files_struct *fsp)
-{
-       return locking_key(fsp->dev, fsp->inode);
-}
+/****************************************************************************
+ First - the functions that deal with the underlying system locks - these
+ functions are used no matter if we're mapping CIFS Windows locks or CIFS
+ POSIX locks onto POSIX.
+****************************************************************************/
 
 /****************************************************************************
Add an fd to the pending close tdb.
Calculate if locks have any overlap at all.
 ****************************************************************************/
 
-static BOOL add_fd_to_close_entry(files_struct *fsp)
+static BOOL does_lock_overlap(SMB_OFF_T start1, SMB_OFF_T size1, SMB_OFF_T start2, SMB_OFF_T size2)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-       TDB_DATA dbuf;
-
-       dbuf.dptr = NULL;
-       dbuf.dsize = 0;
-
-       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
-
-       dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
-       if (!dbuf.dptr) {
-               DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n"));
-               return False;
+       if (start1 >= start2 && start1 <= start2 + size2) {
+               return True;
        }
 
-       memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
-       dbuf.dsize += sizeof(int);
-
-       if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
-               DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n"));
+       if (start1 < start2 && start1 + size1 > start2) {
+               return True;
        }
 
-       SAFE_FREE(dbuf.dptr);
-       return True;
+       return False;
 }
 
 /****************************************************************************
- Remove all fd entries for a specific dev/inode pair from the tdb.
+ Utility function to map a lock type correctly depending on the open
+ mode of a file.
 ****************************************************************************/
 
-static void delete_close_entries(files_struct *fsp)
+static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
+       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;
+       }
 
-       if (tdb_delete(posix_pending_close_tdb, kbuf) == -1)
-               DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
+       /*
+        * 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;
 }
 
 /****************************************************************************
- Get the array of POSIX pending close records for an open fsp. Caller must
- free. Returns number of entries.
+ Debugging aid :-).
 ****************************************************************************/
 
-static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
+static const char *posix_lock_type_name(int lock_type)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-       TDB_DATA dbuf;
-       size_t count = 0;
-
-       *entries = NULL;
-       dbuf.dptr = NULL;
-
-       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
-
-       if (!dbuf.dptr) {
-               return 0;
-       }
-
-       *entries = (int *)dbuf.dptr;
-       count = (size_t)(dbuf.dsize / sizeof(int));
-
-       return count;
+       return (lock_type == F_RDLCK) ? "READ" : "WRITE";
 }
 
 /****************************************************************************
- Get the array of POSIX locks for an fsp. Caller must free. Returns
- number of entries.
+ 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 size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries)
+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)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-       TDB_DATA dbuf;
-       size_t count = 0;
-
-       *entries = NULL;
-
-       dbuf.dptr = NULL;
+       SMB_OFF_T offset = (SMB_OFF_T)u_offset;
+       SMB_OFF_T count = (SMB_OFF_T)u_count;
 
-       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
+       /*
+        * For the type of system we are, attempt to
+        * find the maximum positive lock offset as an SMB_OFF_T.
+        */
 
-       if (!dbuf.dptr) {
-               return 0;
-       }
+#if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */
 
-       *entries = (struct posix_lock *)dbuf.dptr;
-       count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
+       SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET);
 
-       return count;
-}
+#elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
 
-/****************************************************************************
- Deal with pending closes needed by POSIX locking support.
- Note that posix_locking_close_file() is expected to have been called
- to delete all locks on this fsp before this function is called.
-****************************************************************************/
+       /*
+        * In this case SMB_OFF_T is 64 bits,
+        * and the underlying system can handle 64 bit signed locks.
+        */
 
-int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
-{
-       int saved_errno = 0;
-       int ret;
-       size_t count, i;
-       struct posix_lock *entries = NULL;
-       int *fd_array = NULL;
-       BOOL locks_on_other_fds = False;
+       SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
+       SMB_OFF_T mask = (mask2<<1);
+       SMB_OFF_T max_positive_lock_offset = ~mask;
 
-       if (!lp_posix_locking(SNUM(conn))) {
-               /*
-                * No POSIX to worry about, just close.
-                */
-               ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
-               fsp->fh->fd = -1;
-               return ret;
-       }
+#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
 
        /*
-        * Get the number of outstanding POSIX locks on this dev/inode pair.
+        * In this case either SMB_OFF_T is 32 bits,
+        * or the underlying system cannot handle 64 bit signed locks.
+        * All offsets & counts must be 2^31 or less.
         */
 
-       count = get_posix_lock_entries(fsp, &entries);
+       SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF;
+
+#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
 
        /*
-        * Check if there are any outstanding locks belonging to
-        * other fd's. This should never be the case if posix_locking_close_file()
-        * has been called first, but it never hurts to be *sure*.
+        * POSIX locks of length zero mean lock to end-of-file.
+        * Win32 locks of length zero are point probes. Ignore
+        * any Win32 locks of length zero. JRA.
         */
 
-       for (i = 0; i < count; i++) {
-               if (entries[i].fd != fsp->fh->fd) {
-                       locks_on_other_fds = True;
-                       break;
-               }
+       if (count == (SMB_OFF_T)0) {
+               DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n"));
+               return False;
        }
 
-       if (locks_on_other_fds) {
-
-               /*
-                * There are outstanding locks on this dev/inode pair on other fds.
-                * Add our fd to the pending close tdb and set fsp->fh->fd to -1.
-                */
-
-               if (!add_fd_to_close_entry(fsp)) {
-                       SAFE_FREE(entries);
-                       return -1;
-               }
+       /*
+        * If the given offset was > max_positive_lock_offset then we cannot map this at all
+        * ignore this lock.
+        */
 
-               SAFE_FREE(entries);
-               fsp->fh->fd = -1;
-               return 0;
+       if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
+               DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n",
+                               (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) ));
+               return False;
        }
 
-       SAFE_FREE(entries);
-
        /*
-        * No outstanding POSIX locks. Get the pending close fd's
-        * from the tdb and close them all.
+        * We must truncate the count to less than max_positive_lock_offset.
         */
 
-       count = get_posix_pending_close_entries(fsp, &fd_array);
+       if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
+               count = max_positive_lock_offset;
+       }
 
-       if (count) {
-               DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
+       /*
+        * Truncate count to end at max lock offset.
+        */
 
-               for(i = 0; i < count; i++) {
-                       if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {
-                               saved_errno = errno;
-                       }
-               }
+       if (offset + count < 0 || offset + count > max_positive_lock_offset) {
+               count = max_positive_lock_offset - offset;
+       }
 
-               /*
-                * Delete all fd's stored in the tdb
-                * for this dev/inode pair.
-                */
+       /*
+        * If we ate all the count, ignore this lock.
+        */
 
-               delete_close_entries(fsp);
+       if (count == 0) {
+               DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n",
+                               (double)u_offset, (double)u_count ));
+               return False;
        }
 
-       SAFE_FREE(fd_array);
-
        /*
-        * Finally close the fd associated with this fsp.
+        * The mapping was successful.
         */
 
-       ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
+       DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n",
+                       (double)offset, (double)count ));
 
-       if (saved_errno != 0) {
-               errno = saved_errno;
-               ret = -1;
-       } 
+       *offset_out = offset;
+       *count_out = count;
+       
+       return True;
+}
 
-       fsp->fh->fd = -1;
+/****************************************************************************
+ Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and
+ broken NFS implementations.
+****************************************************************************/
+
+static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
+{
+       BOOL ret;
+
+       DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type));
+
+       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
+
+       if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
+
+               DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n",
+                                       (double)offset,(double)count));
+               DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
+               DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
+
+               /*
+                * If the offset is > 0x7FFFFFFF then this will cause problems on
+                * 32 bit NFS mounted filesystems. Just ignore it.
+                */
+
+               if (offset & ~((SMB_OFF_T)0x7fffffff)) {
+                       DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
+                       return True;
+               }
+
+               if (count & ~((SMB_OFF_T)0x7fffffff)) {
+                       /* 32 bit NFS file system, retry with smaller offset */
+                       DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
+                       errno = 0;
+                       count &= 0x7fffffff;
+                       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
+               }
+       }
 
+       DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed"));
        return ret;
 }
 
 /****************************************************************************
- Debugging aid :-).
+ Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and
+ broken NFS implementations.
 ****************************************************************************/
 
-static const char *posix_lock_type_name(int lock_type)
+static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype)
 {
-       return (lock_type == F_RDLCK) ? "READ" : "WRITE";
+       pid_t pid;
+       BOOL ret;
+
+       DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n",
+               fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype));
+
+       ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
+
+       if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
+
+               DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n",
+                                       (double)*poffset,(double)*pcount));
+               DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
+               DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
+
+               /*
+                * If the offset is > 0x7FFFFFFF then this will cause problems on
+                * 32 bit NFS mounted filesystems. Just ignore it.
+                */
+
+               if (*poffset & ~((SMB_OFF_T)0x7fffffff)) {
+                       DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
+                       return True;
+               }
+
+               if (*pcount & ~((SMB_OFF_T)0x7fffffff)) {
+                       /* 32 bit NFS file system, retry with smaller offset */
+                       DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
+                       errno = 0;
+                       *pcount &= 0x7fffffff;
+                       ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
+               }
+       }
+
+       DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed"));
+       return ret;
 }
 
 /****************************************************************************
- Delete a POSIX lock entry by index number. Used if the tdb add succeeds, but
then the POSIX fcntl lock fails.
+ POSIX function to see if a file region is locked. Returns True if the
region is locked, False otherwise.
 ****************************************************************************/
 
-static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry)
+BOOL is_posix_locked(files_struct *fsp,
+                       SMB_BIG_UINT *pu_offset,
+                       SMB_BIG_UINT *pu_count,
+                       enum brl_type *plock_type,
+                       enum brl_flavour lock_flav)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-       TDB_DATA dbuf;
-       struct posix_lock *locks;
-       size_t count;
+       SMB_OFF_T offset;
+       SMB_OFF_T count;
+       int posix_lock_type = map_posix_lock_type(fsp,*plock_type);
 
-       dbuf.dptr = NULL;
-       
-       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
+       DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
+               fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) ));
 
-       if (!dbuf.dptr) {
-               DEBUG(10,("delete_posix_lock_entry_by_index: tdb_fetch failed !\n"));
-               goto fail;
+       /*
+        * 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, *pu_offset, *pu_count)) {
+               return False;
        }
 
-       count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
-       locks = (struct posix_lock *)dbuf.dptr;
+       if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) {
+               return False;
+       }
 
-       if (count == 1) {
-               tdb_delete(posix_lock_tdb, kbuf);
-       } else {
-               if (entry < count-1) {
-                       memmove(&locks[entry], &locks[entry+1], sizeof(struct posix_lock)*((count-1) - entry));
-               }
-               dbuf.dsize -= sizeof(struct posix_lock);
-               tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);
+       if (posix_lock_type == F_UNLCK) {
+               return False;
        }
 
-       SAFE_FREE(dbuf.dptr);
+       if (lock_flav == POSIX_LOCK) {
+               /* Only POSIX lock queries need to know the details. */
+               *pu_offset = (SMB_BIG_UINT)offset;
+               *pu_count = (SMB_BIG_UINT)count;
+               *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK;
+       }
+       return True;
+}
+
+/****************************************************************************
+ Next - the functions that deal with in memory database storing representations
+ of either Windows CIFS locks or POSIX CIFS locks.
+****************************************************************************/
+
+/*
+ * 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.
+ */
+
+/* The key used in both the POSIX databases. */
+
+struct posix_lock_key {
+       SMB_DEV_T device;
+       SMB_INO_T inode;
+}; 
+
+/*******************************************************************
+ Form a static locking key for a dev/inode pair.
+******************************************************************/
+
+static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
+{
+       static struct posix_lock_key key;
+       TDB_DATA kbuf;
+
+       memset(&key, '\0', sizeof(key));
+       key.device = dev;
+       key.inode = inode;
+       kbuf.dptr = (char *)&key;
+       kbuf.dsize = sizeof(key);
+       return kbuf;
+}
+
+/*******************************************************************
+ Convenience function to get a key from an fsp.
+******************************************************************/
+
+static TDB_DATA locking_key_fsp(files_struct *fsp)
+{
+       return locking_key(fsp->dev, fsp->inode);
+}
+
+/*******************************************************************
+ Create the in-memory POSIX lock databases.
+********************************************************************/
+
+BOOL posix_locking_init(int read_only)
+{
+       if (posix_lock_tdb && posix_pending_close_tdb) {
+               return True;
+       }
+       
+       if (!posix_lock_tdb) {
+               posix_lock_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,
+                                         read_only?O_RDONLY:(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_log(NULL, 0, TDB_INTERNAL,
+                                                  read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
+       }
+       if (!posix_pending_close_tdb) {
+               DEBUG(0,("Failed to open POSIX pending close database.\n"));
+               return False;
+       }
 
        return True;
+}
 
- fail:
+/*******************************************************************
+ Delete the in-memory POSIX lock databases.
+********************************************************************/
 
-       SAFE_FREE(dbuf.dptr);
-       return False;
+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;
 }
 
 /****************************************************************************
- Add an entry into the POSIX locking tdb. We return the index number of the
- added lock (used in case we need to delete *exactly* this entry). Returns
- False on fail, True on success.
+ Remove all lock entries for a specific dev/inode pair from the tdb.
 ****************************************************************************/
 
-static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *pentry_num)
+static void delete_posix_lock_entries(files_struct *fsp)
 {
        TDB_DATA kbuf = locking_key_fsp(fsp);
-       TDB_DATA dbuf;
-       struct posix_lock pl;
 
-       dbuf.dptr = NULL;
-       dbuf.dsize = 0;
+       if (tdb_delete(posix_lock_tdb, kbuf) == -1) {
+               DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
+       }
+}
 
-       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
+/****************************************************************************
+ Debug function.
+****************************************************************************/
 
-       *pentry_num = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
+static void dump_entry(struct posix_lock *pl)
+{
+       DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n",
+               (double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd ));
+}
 
-       /*
-        * Add new record.
-        */
+/****************************************************************************
+ Next - the functions that deal with storing fd's that have outstanding
+ POSIX locks when closed.
+****************************************************************************/
 
-       pl.fd = fsp->fh->fd;
-       pl.start = start;
-       pl.size = size;
-       pl.lock_type = lock_type;
+/****************************************************************************
+ Add an fd to the pending close tdb.
+****************************************************************************/
 
-       dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock));
+static BOOL add_fd_to_close_entry(files_struct *fsp)
+{
+       TDB_DATA kbuf = locking_key_fsp(fsp);
+       TDB_DATA dbuf;
+
+       dbuf.dptr = NULL;
+       dbuf.dsize = 0;
+
+       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+
+       dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
        if (!dbuf.dptr) {
-               DEBUG(0,("add_posix_lock_entry: Realloc fail !\n"));
-               goto fail;
+               DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n"));
+               return False;
        }
 
-       memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock));
-       dbuf.dsize += sizeof(struct posix_lock);
+       memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
+       dbuf.dsize += sizeof(int);
 
-       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));
-               goto fail;
+       if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
+               DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n"));
        }
 
        SAFE_FREE(dbuf.dptr);
-
-       DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n",
-                       fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size,
-                       (double)fsp->dev, (double)fsp->inode ));
-
        return True;
+}
 
- fail:
+/****************************************************************************
+ Remove all fd entries for a specific dev/inode pair from the tdb.
+****************************************************************************/
 
-       SAFE_FREE(dbuf.dptr);
-       return False;
+static void delete_close_entries(files_struct *fsp)
+{
+       TDB_DATA kbuf = locking_key_fsp(fsp);
+
+       if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) {
+               DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
+       }
 }
 
 /****************************************************************************
- Calculate if locks have any overlap at all.
+ Get the array of POSIX pending close records for an open fsp. Caller must
+ free. Returns number of entries.
 ****************************************************************************/
 
-static BOOL does_lock_overlap(SMB_OFF_T start1, SMB_OFF_T size1, SMB_OFF_T start2, SMB_OFF_T size2)
+static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
 {
-       if (start1 >= start2 && start1 <= start2 + size2)
-               return True;
+       TDB_DATA kbuf = locking_key_fsp(fsp);
+       TDB_DATA dbuf;
+       size_t count = 0;
 
-       if (start1 < start2 && start1 + size1 > start2)
-               return True;
+       *entries = NULL;
+       dbuf.dptr = NULL;
 
-       return False;
+       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+
+       if (!dbuf.dptr) {
+               return 0;
+       }
+
+       *entries = (int *)dbuf.dptr;
+       count = (size_t)(dbuf.dsize / sizeof(int));
+
+       return count;
 }
 
 /****************************************************************************
- Delete an entry from the POSIX locking tdb. Returns a copy of the entry being
deleted and the number of records that are overlapped by this one, or -1 on error.
+ Get the array of POSIX locks for an fsp. Caller must free. Returns
number of entries.
 ****************************************************************************/
 
-static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl)
+static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries)
 {
        TDB_DATA kbuf = locking_key_fsp(fsp);
        TDB_DATA dbuf;
-       struct posix_lock *locks;
-       size_t i, count;
-       BOOL found = False;
-       int num_overlapping_records = 0;
+       size_t count = 0;
+
+       *entries = NULL;
 
        dbuf.dptr = NULL;
-       
+
        dbuf = tdb_fetch(posix_lock_tdb, kbuf);
 
        if (!dbuf.dptr) {
-               DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n"));
-               goto fail;
+               return 0;
        }
 
-       /* There are existing locks - find a match. */
-       locks = (struct posix_lock *)dbuf.dptr;
+       *entries = (struct posix_lock *)dbuf.dptr;
        count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
 
+       return count;
+}
+
+/****************************************************************************
+ Deal with pending closes needed by POSIX locking support.
+ Note that posix_locking_close_file() is expected to have been called
+ to delete all locks on this fsp before this function is called.
+****************************************************************************/
+
+int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
+{
+       int saved_errno = 0;
+       int ret;
+       size_t count, i;
+       struct posix_lock *entries = NULL;
+       int *fd_array = NULL;
+       BOOL locks_on_other_fds = False;
+
+       if (!lp_posix_locking(SNUM(conn))) {
+               /*
+                * No POSIX to worry about, just close.
+                */
+               ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
+               fsp->fh->fd = -1;
+               return ret;
+       }
+
        /*
-        * Search for and delete the first record that matches the
-        * unlock criteria.
+        * Get the number of outstanding POSIX locks on this dev/inode pair.
         */
 
-       for (i=0; i<count; i++) { 
-               struct posix_lock *entry = &locks[i];
-
-               if (entry->fd == fsp->fh->fd &&
-                       entry->start == start &&
-                       entry->size == size) {
+       count = get_posix_lock_entries(fsp, &entries);
 
-                       /* Make a copy */
-                       *pl = *entry;
+       /*
+        * Check if there are any outstanding locks belonging to
+        * other fd's. This should never be the case if posix_locking_close_file()
+        * has been called first, but it never hurts to be *sure*.
+        */
 
-                       /* Found it - delete it. */
-                       if (count == 1) {
-                               tdb_delete(posix_lock_tdb, kbuf);
-                       } else {
-                               if (i < count-1) {
-                                       memmove(&locks[i], &locks[i+1], sizeof(struct posix_lock)*((count-1) - i));
-                               }
-                               dbuf.dsize -= sizeof(struct posix_lock);
-                               tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);
-                       }
-                       count--;
-                       found = True;
+       for (i = 0; i < count; i++) {
+               if (entries[i].fd != fsp->fh->fd) {
+                       locks_on_other_fds = True;
                        break;
                }
        }
 
-       if (!found)
-               goto fail;
+       if (locks_on_other_fds) {
+
+               /*
+                * There are outstanding locks on this dev/inode pair on other fds.
+                * Add our fd to the pending close tdb and set fsp->fh->fd to -1.
+                */
+
+               if (!add_fd_to_close_entry(fsp)) {
+                       SAFE_FREE(entries);
+                       return -1;
+               }
+
+               SAFE_FREE(entries);
+               fsp->fh->fd = -1;
+               return 0;
+       }
+
+       SAFE_FREE(entries);
 
        /*
-        * Count the number of entries that are
-        * overlapped by this unlock request.
+        * No outstanding POSIX locks. Get the pending close fd's
+        * from the tdb and close them all.
         */
 
-       for (i = 0; i < count; i++) {
-               struct posix_lock *entry = &locks[i];
-
-               if (fsp->fh->fd == entry->fd &&
-                       does_lock_overlap( start, size, entry->start, entry->size))
-                               num_overlapping_records++;
-       }
-
-       DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n",
-                       posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size,
-                               (unsigned int)num_overlapping_records ));
-
-       SAFE_FREE(dbuf.dptr);
-
-       return num_overlapping_records;
-
- fail:
+       count = get_posix_pending_close_entries(fsp, &fd_array);
 
-       SAFE_FREE(dbuf.dptr);
-       return -1;
-}
+       if (count) {
+               DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
 
-/****************************************************************************
- Utility function to map a lock type correctly depending on the open
- mode of a file.
-****************************************************************************/
+               for(i = 0; i < count; i++) {
+                       if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {
+                               saved_errno = errno;
+                       }
+               }
 
-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;
-       }
-#if 0
-       /* We no longer open files write-only. */
-        else if((lock_type == READ_LOCK) && !fsp->can_read) {
                /*
-                * Ditto for read locks on write only files.
+                * Delete all fd's stored in the tdb
+                * for this dev/inode pair.
                 */
-               DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n"));
-               return F_WRLCK;
+
+               delete_close_entries(fsp);
        }
-#endif
+
+       SAFE_FREE(fd_array);
 
        /*
-        * This return should be the most normal, as we attempt
-        * to always open files read/write.
+        * Finally close the fd associated with this fsp.
         */
 
-       return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK;
+       ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
+
+       if (saved_errno != 0) {
+               errno = saved_errno;
+               ret = -1;
+       } 
+
+       fsp->fh->fd = -1;
+
+       return ret;
 }
 
 /****************************************************************************
- 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.
+ Remove any locks on this fd. Called from file_close().
 ****************************************************************************/
 
-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)
+void posix_locking_close_file(files_struct *fsp)
 {
-       SMB_OFF_T offset = (SMB_OFF_T)u_offset;
-       SMB_OFF_T count = (SMB_OFF_T)u_count;
-
-       /*
-        * For the type of system we are, attempt to
-        * find the maximum positive lock offset as an SMB_OFF_T.
-        */
-
-#if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */
-
-       SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET);
-
-#elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
+       struct posix_lock *entries = NULL;
+       size_t count, i;
 
        /*
-        * In this case SMB_OFF_T is 64 bits,
-        * and the underlying system can handle 64 bit signed locks.
+        * 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.
         */
 
-       SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
-       SMB_OFF_T mask = (mask2<<1);
-       SMB_OFF_T max_positive_lock_offset = ~mask;
-
-#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.
-        * All offsets & counts must be 2^31 or less.
-        */
+       count = get_posix_lock_entries(fsp, &entries);
 
-       SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF;
+       if (count == 0) {
+               DEBUG(10,("posix_locking_close_file: file %s has no outstanding locks.\n", fsp->fsp_name ));
+               return;
+       }
 
-#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
+       for (i = 0; i < count; i++) {
+               if (entries[i].fd != fsp->fh->fd ) {
+                       break;
+               }
 
-       /*
-        * POSIX locks of length zero mean lock to end-of-file.
-        * Win32 locks of length zero are point probes. Ignore
-        * any Win32 locks of length zero. JRA.
-        */
+               dump_entry(&entries[i]);
+       }
 
-       if (count == (SMB_OFF_T)0) {
-               DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n"));
-               return False;
+       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 ));
+               SAFE_FREE(entries);
+               delete_posix_lock_entries(fsp);
+               return;
        }
 
        /*
-        * If the given offset was > max_positive_lock_offset then we cannot map this at all
-        * ignore this lock.
+        * Difficult case. We need to delete all our locks, whilst leaving
+        * all other POSIX locks in place.
         */
 
-       if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
-               DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n",
-                               (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) ));
-               return False;
+       for (i = 0; i < count; i++) {
+               struct posix_lock *pl = &entries[i];
+               if (pl->fd == fsp->fh->fd) {
+                       release_posix_lock_windows_flavour(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size );
+               }
        }
+       SAFE_FREE(entries);
+}
 
-       /*
-        * We must truncate the count to less than max_positive_lock_offset.
-        */
 
-       if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset))
-               count = max_positive_lock_offset;
+/****************************************************************************
+ Next - the functions that deal with the mapping CIFS Windows locks onto
+ the underlying system POSIX locks.
+****************************************************************************/
 
-       /*
-        * Truncate count to end at max lock offset.
-        */
+/****************************************************************************
+ Delete a lock entry by index number.
+ Used when dealing with POSIX locks created from Windows lock requests if the
+ tdb add succeeds, but then the system POSIX fcntl lock fails.
+****************************************************************************/
 
-       if (offset + count < 0 || offset + count > max_positive_lock_offset)
-               count = max_positive_lock_offset - offset;
+static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry)
+{
+       TDB_DATA kbuf = locking_key_fsp(fsp);
+       TDB_DATA dbuf;
+       struct posix_lock *locks;
+       size_t count;
 
-       /*
-        * If we ate all the count, ignore this lock.
-        */
+       dbuf.dptr = NULL;
+       
+       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
 
-       if (count == 0) {
-               DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n",
-                               (double)u_offset, (double)u_count ));
-               return False;
+       if (!dbuf.dptr) {
+               DEBUG(10,("delete_posix_lock_entry_by_index: tdb_fetch failed !\n"));
+               goto fail;
        }
 
-       /*
-        * The mapping was successful.
-        */
+       count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
+       locks = (struct posix_lock *)dbuf.dptr;
 
-       DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n",
-                       (double)offset, (double)count ));
+       if (count == 1) {
+               tdb_delete(posix_lock_tdb, kbuf);
+       } else {
+               if (entry < count-1) {
+                       memmove(&locks[entry], &locks[entry+1], sizeof(struct posix_lock)*((count-1) - entry));
+               }
+               dbuf.dsize -= sizeof(struct posix_lock);
+               tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);
+       }
+
+       SAFE_FREE(dbuf.dptr);
 
-       *offset_out = offset;
-       *count_out = count;
-       
        return True;
+
+ fail:
+
+       SAFE_FREE(dbuf.dptr);
+       return False;
 }
 
 /****************************************************************************
- Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and
- broken NFS implementations.
+ Add an entry into the locking tdb. This function is used when mapping Windows
+ flavour locks onto underlying system POSIX locks. We return the index number of the
+ added lock (used in case we need to delete *exactly* this entry). Returns
+ False on fail, True on success.
 ****************************************************************************/
 
-static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
+static BOOL add_posix_lock_entry(files_struct *fsp,
+                               SMB_OFF_T start,
+                               SMB_OFF_T size,
+                               int lock_type,
+                               struct lock_context *lock_ctx,
+                               enum brl_flavour lock_flav,
+                               size_t *pentry_num)
 {
-       BOOL ret;
+       TDB_DATA kbuf = locking_key_fsp(fsp);
+       TDB_DATA dbuf;
+       struct posix_lock pl;
 
-       DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type));
+       dbuf.dptr = NULL;
+       dbuf.dsize = 0;
 
-       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
+       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
 
-       if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
+       *pentry_num = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
 
-               DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n",
-                                       (double)offset,(double)count));
-               DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
-               DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
+       /*
+        * Add new record.
+        */
 
-               /*
-                * If the offset is > 0x7FFFFFFF then this will cause problems on
-                * 32 bit NFS mounted filesystems. Just ignore it.
-                */
+       pl.fd = fsp->fh->fd;
+       pl.start = start;
+       pl.size = size;
+       pl.lock_type = lock_type;
+       pl.lock_flav = lock_flav;
+       pl.lock_ctx = *lock_ctx;
+
+       dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock));
+       if (!dbuf.dptr) {
+               DEBUG(0,("add_posix_lock_entry: Realloc fail !\n"));
+               goto fail;
+       }
+
+       memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock));
+       dbuf.dsize += sizeof(struct posix_lock);
+
+       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));
+               goto fail;
+       }
+
+       SAFE_FREE(dbuf.dptr);
 
-               if (offset & ~((SMB_OFF_T)0x7fffffff)) {
-                       DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
-                       return True;
-               }
+       DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n",
+                       fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size,
+                       (double)fsp->dev, (double)fsp->inode ));
 
-               if (count & ~((SMB_OFF_T)0x7fffffff)) {
-                       /* 32 bit NFS file system, retry with smaller offset */
-                       DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
-                       errno = 0;
-                       count &= 0x7fffffff;
-                       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
-               }
-       }
+       return True;
 
-       DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed"));
-       return ret;
+ fail:
+
+       SAFE_FREE(dbuf.dptr);
+       return False;
 }
 
 /****************************************************************************
- Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and
- broken NFS implementations.
+ Delete an entry from the POSIX locking tdb. Used by Windows flavour locks being
+ mapped onto underlying system POSIX locks. Returns a copy of the entry being
+ deleted and the number of records that are overlapped by this one, or -1 on error.
 ****************************************************************************/
 
-static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype)
+static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl)
 {
-       pid_t pid;
-       BOOL ret;
+       TDB_DATA kbuf = locking_key_fsp(fsp);
+       TDB_DATA dbuf;
+       struct posix_lock *locks;
+       size_t i, count;
+       BOOL found = False;
+       int num_overlapping_records = 0;
 
-       DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n",
-               fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype));
+       dbuf.dptr = NULL;
+       
+       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
 
-       ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
+       if (!dbuf.dptr) {
+               DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n"));
+               goto fail;
+       }
 
-       if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
+       /* There are existing locks - find a match. */
+       locks = (struct posix_lock *)dbuf.dptr;
+       count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
 
-               DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n",
-                                       (double)*poffset,(double)*pcount));
-               DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
-               DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
+       /*
+        * Search for and delete the first record that matches the
+        * unlock criteria.
+        */
 
-               /*
-                * If the offset is > 0x7FFFFFFF then this will cause problems on
-                * 32 bit NFS mounted filesystems. Just ignore it.
-                */
+       for (i=0; i<count; i++) { 
+               struct posix_lock *entry = &locks[i];
 
-               if (*poffset & ~((SMB_OFF_T)0x7fffffff)) {
-                       DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
-                       return True;
-               }
+               if (entry->fd == fsp->fh->fd &&
+                       entry->start == start &&
+                       entry->size == size) {
 
-               if (*pcount & ~((SMB_OFF_T)0x7fffffff)) {
-                       /* 32 bit NFS file system, retry with smaller offset */
-                       DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
-                       errno = 0;
-                       *pcount &= 0x7fffffff;
-                       ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
+                       /* Make a copy */
+                       *pl = *entry;
+
+                       /* Found it - delete it. */
+                       if (count == 1) {
+                               tdb_delete(posix_lock_tdb, kbuf);
+                       } else {
+                               if (i < count-1) {
+                                       memmove(&locks[i], &locks[i+1], sizeof(struct posix_lock)*((count-1) - i));
+                               }
+                               dbuf.dsize -= sizeof(struct posix_lock);
+                               tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);
+                       }
+                       count--;
+                       found = True;
+                       break;
                }
        }
 
-       DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed"));
-       return ret;
-}
-
-
-/****************************************************************************
- POSIX function to see if a file region is locked. Returns True if the
- region is locked, False otherwise.
-****************************************************************************/
-
-BOOL is_posix_locked(files_struct *fsp,
-                       SMB_BIG_UINT *pu_offset,
-                       SMB_BIG_UINT *pu_count,
-                       enum brl_type *plock_type,
-                       enum brl_flavour lock_flav)
-{
-       SMB_OFF_T offset;
-       SMB_OFF_T count;
-       int posix_lock_type = map_posix_lock_type(fsp,*plock_type);
-
-       DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
-               fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) ));
+       if (!found)
+               goto fail;
 
        /*
-        * If the requested lock won't fit in the POSIX range, we will
-        * never set it, so presume it is not locked.
+        * Count the number of entries that are
+        * overlapped by this unlock request.
         */
 
-       if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) {
-               return False;
-       }
+       for (i = 0; i < count; i++) {
+               struct posix_lock *entry = &locks[i];
 
-       if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) {
-               return False;
+               if (fsp->fh->fd == entry->fd && does_lock_overlap( start, size, entry->start, entry->size)) {
+                       num_overlapping_records++;
+               }
        }
 
-       if (posix_lock_type == F_UNLCK) {
-               return False;
-       }
+       DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n",
+                       posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size,
+                               (unsigned int)num_overlapping_records ));
 
-       if (lock_flav == POSIX_LOCK) {
-               /* Only POSIX lock queries need to know the details. */
-               *pu_offset = (SMB_BIG_UINT)offset;
-               *pu_count = (SMB_BIG_UINT)count;
-               *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK;
-       }
-       return True;
+       SAFE_FREE(dbuf.dptr);
+
+       return num_overlapping_records;
+
+ fail:
+
+       SAFE_FREE(dbuf.dptr);
+       return -1;
 }
 
 /*
@@ -803,8 +956,9 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea
 
        dbuf = tdb_fetch(posix_lock_tdb, kbuf);
 
-       if (!dbuf.dptr)
+       if (!dbuf.dptr) {
                return lhead;
+       }
        
        locks = (struct posix_lock *)dbuf.dptr;
        num_locks = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
@@ -836,7 +990,7 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea
                        if ( (l_curr->start >= (lock->start + lock->size)) ||
                                 (lock->start >= (l_curr->start + l_curr->size))) {
 
-                               /* No overlap with this lock - leave this range alone. */
+                               /* No overlap with existing lock - leave this range alone. */
 /*********************************************
                                              +---------+
                                              | l_curr  |
@@ -858,8 +1012,8 @@ OR....
                                                (l_curr->start + l_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.
+                                * This range is completely overlapped by this existing lock range
+                                * and thus should have no effect. Delete it from the list.
                                 */
 /*********************************************
                 +---------+
@@ -875,8 +1029,9 @@ OR....
                                DEBUG(10,("delete case.\n" ));
 
                                DLIST_REMOVE(lhead, l_curr);
-                               if(lhead == NULL)
+                               if(lhead == NULL) {
                                        break; /* No more list... */
+                               }
 
                                l_curr = ul_next;
                                
@@ -885,7 +1040,7 @@ OR....
                                                (l_curr->start + l_curr->size > lock->start + lock->size) ) {
 
                                /*
-                                * This unlock overlaps the existing lock range at the high end.
+                                * This range overlaps the existing lock range at the high end.
                                 * Truncate by moving start to existing range end and reducing size.
                                 */
 /*********************************************
@@ -914,7 +1069,7 @@ BECOMES....
                                                (l_curr->start + l_curr->size <= lock->start + lock->size) ) {
 
                                /*
-                                * This unlock overlaps the existing lock range at the low end.
+                                * This range overlaps the existing lock range at the low end.
                                 * Truncate by reducing size.
                                 */
 /*********************************************
@@ -940,10 +1095,10 @@ BECOMES....
                        } else if ( (l_curr->start < lock->start) &&
                                                (l_curr->start + l_curr->size > lock->start + lock->size) ) {
                                /*
-                                * Worst case scenario. Unlock request completely overlaps an existing
+                                * Worst case scenario. Range 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).
+                                * into the dlink list, and continue with the entry after l_new (as we
+                                * know that l_new will not overlap with this lock).
                                 */
 /*********************************************
         +---------------------------+
@@ -1011,15 +1166,15 @@ lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size,
 /****************************************************************************
  POSIX function to acquire a lock. Returns True if the
  lock could be granted, False if not.
- TODO -- Fix POSIX lock flavour semantics.
 ****************************************************************************/
 
-BOOL set_posix_lock(files_struct *fsp,
+BOOL set_posix_lock_windows_flavour(files_struct *fsp,
                        SMB_BIG_UINT u_offset,
                        SMB_BIG_UINT u_count,
                        enum brl_type lock_type,
-                       enum brl_flavour lock_flav)
+                       int *errno_ret)
 {
+       struct lock_context lock_ctx;
        SMB_OFF_T offset;
        SMB_OFF_T count;
        BOOL ret = True;
@@ -1030,7 +1185,9 @@ BOOL set_posix_lock(files_struct *fsp,
        struct lock_list *ll = NULL;
        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",
+       ZERO_STRUCT(lock_ctx);
+
+       DEBUG(5,("set_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n",
                        fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
 
        /*
@@ -1038,8 +1195,9 @@ BOOL set_posix_lock(files_struct *fsp,
         * pretend it was successful.
         */
 
-       if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
+       if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
                return True;
+       }
 
        /*
         * Windows is very strange. It allows read locks to be overlayed
@@ -1063,12 +1221,12 @@ BOOL set_posix_lock(files_struct *fsp,
         */
        
        if ((l_ctx = talloc_init("set_posix_lock")) == NULL) {
-               DEBUG(0,("set_posix_lock: unable to init talloc context.\n"));
+               DEBUG(0,("set_posix_lock_windows_flavour: unable to init talloc context.\n"));
                return True; /* Not a fatal error. */
        }
 
        if ((ll = TALLOC_P(l_ctx, struct lock_list)) == NULL) {
-               DEBUG(0,("set_posix_lock: unable to talloc unlock list.\n"));
+               DEBUG(0,("set_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
                talloc_destroy(l_ctx);
                return True; /* Not a fatal error. */
        }
@@ -1100,8 +1258,14 @@ BOOL set_posix_lock(files_struct *fsp,
         * added here in case we have to remove it on POSIX lock fail.
         */
 
-       if (!add_posix_lock_entry(fsp,offset,count,posix_lock_type,&entry_num)) {
-               DEBUG(0,("set_posix_lock: Unable to create posix lock entry !\n"));
+       if (!add_posix_lock_entry(fsp,
+                       offset,
+                       count,
+                       posix_lock_type,
+                       &lock_ctx,
+                       WINDOWS_LOCK,
+                       &entry_num)) {
+               DEBUG(0,("set_posix_lock_windows_flavour: Unable to create posix lock entry !\n"));
                talloc_destroy(l_ctx);
                return False;
        }
@@ -1116,11 +1280,12 @@ BOOL set_posix_lock(files_struct *fsp,
                offset = ll->start;
                count = ll->size;
 
-               DEBUG(5,("set_posix_lock: Real lock: Type = %s: offset = %.0f, count = %.0f\n",
+               DEBUG(5,("set_posix_lock_windows_flavour: Real lock: Type = %s: offset = %.0f, count = %.0f\n",
                        posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));
 
                if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) {
-                       DEBUG(5,("set_posix_lock: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
+                       *errno_ret = errno;
+                       DEBUG(5,("set_posix_lock_windows_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
                                posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) ));
                        ret = False;
                        break;
@@ -1137,7 +1302,7 @@ BOOL set_posix_lock(files_struct *fsp,
                        offset = ll->start;
                        count = ll->size;
 
-                       DEBUG(5,("set_posix_lock: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n",
+                       DEBUG(5,("set_posix_lock_windows_flavour: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n",
                                posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));
 
                        posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK);
@@ -1159,7 +1324,9 @@ BOOL set_posix_lock(files_struct *fsp,
  lock could be released, False if not.
 ****************************************************************************/
 
-BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
+BOOL release_posix_lock_windows_flavour(files_struct *fsp,
+                               SMB_BIG_UINT u_offset,
+                               SMB_BIG_UINT u_count)
 {
        SMB_OFF_T offset;
        SMB_OFF_T count;
@@ -1170,7 +1337,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
        struct posix_lock deleted_lock;
        int num_overlapped_entries;
 
-       DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n",
+       DEBUG(5,("release_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f\n",
                fsp->fsp_name, (double)u_offset, (double)u_count ));
 
        /*
@@ -1178,8 +1345,9 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
         * pretend it was successful.
         */
 
-       if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
+       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
@@ -1191,7 +1359,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
        num_overlapped_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock);
 
        if (num_overlapped_entries == -1) {
-               smb_panic("release_posix_lock: unable find entry to delete !\n");
+               smb_panic("release_posix_lock_windows_flavour: unable find entry to delete !\n");
        }
 
        /*
@@ -1203,18 +1371,18 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
 
        if (num_overlapped_entries > 0 && deleted_lock.lock_type == F_WRLCK) {
                if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) {
-                       DEBUG(0,("release_posix_lock: downgrade of lock failed with error %s !\n", strerror(errno) ));
+                       DEBUG(0,("release_posix_lock_windows_flavour: downgrade of lock failed with error %s !\n", strerror(errno) ));
                        return False;
                }
        }
 
        if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
-               DEBUG(0,("release_posix_lock: unable to init talloc context.\n"));
+               DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
                return True; /* Not a fatal error. */
        }
 
        if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) {
-               DEBUG(0,("release_posix_lock: unable to talloc unlock list.\n"));
+               DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
                talloc_destroy(ul_ctx);
                return True; /* Not a fatal error. */
        }
@@ -1249,11 +1417,12 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
                offset = ulist->start;
                count = ulist->size;
 
-               DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n",
+               DEBUG(5,("release_posix_lock_windows_flavour: Real unlock: offset = %.0f, count = %.0f\n",
                        (double)offset, (double)count ));
 
-               if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK))
+               if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) {
                        ret = False;
+               }
        }
 
        talloc_destroy(ul_ctx);
@@ -1262,116 +1431,34 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
 }
 
 /****************************************************************************
- Remove all lock entries for a specific dev/inode pair from the tdb.
+ Next - the functions that deal with mapping CIFS POSIX locks onto
+ the underlying system POSIX locks.
 ****************************************************************************/
 
-static void delete_posix_lock_entries(files_struct *fsp)
-{
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-
-       if (tdb_delete(posix_lock_tdb, kbuf) == -1)
-               DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
-}
-
 /****************************************************************************
- Debug function.
+ POSIX function to acquire a lock. Returns True if the
+ lock could be granted, False if not.
 ****************************************************************************/
 
-static void dump_entry(struct posix_lock *pl)
+BOOL set_posix_lock_posix_flavour(files_struct *fsp,
+                       SMB_BIG_UINT u_offset,
+                       SMB_BIG_UINT u_count,
+                       enum brl_type lock_type,
+                       const struct lock_context *plock_ctx,
+                       int *errno_ret)
 {
-       DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n",
-               (double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd ));
+       return True;
 }
 
 /****************************************************************************
- Remove any locks on this fd. Called from file_close().
+ POSIX function to release a lock. Returns True if the
+ lock could be released, False if not.
 ****************************************************************************/
 
-void posix_locking_close_file(files_struct *fsp)
-{
-       struct posix_lock *entries = NULL;
-       size_t count, i;
-
-       /*
-        * 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.
-        */
-
-       count = get_posix_lock_entries(fsp, &entries);
-
-       if (count == 0) {
-               DEBUG(10,("posix_locking_close_file: file %s has no outstanding locks.\n", fsp->fsp_name ));
-               return;
-       }
-
-       for (i = 0; i < count; i++) {
-               if (entries[i].fd != fsp->fh->fd )
-                       break;
-
-               dump_entry(&entries[i]);
-       }
-
-       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 ));
-               SAFE_FREE(entries);
-               delete_posix_lock_entries(fsp);
-               return;
-       }
-
-       /*
-        * Difficult case. We need to delete all our locks, whilst leaving
-        * all other POSIX locks in place.
-        */
-
-       for (i = 0; i < count; i++) {
-               struct posix_lock *pl = &entries[i];
-               if (pl->fd == fsp->fh->fd)
-                       release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size );
-       }
-       SAFE_FREE(entries);
-}
-
-/*******************************************************************
- Create the in-memory POSIX lock databases.
-********************************************************************/
-
-BOOL posix_locking_init(int read_only)
-{
-       if (posix_lock_tdb && posix_pending_close_tdb)
-               return True;
-       
-       if (!posix_lock_tdb)
-               posix_lock_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,
-                                         read_only?O_RDONLY:(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_log(NULL, 0, TDB_INTERNAL,
-                                                  read_only?O_RDONLY:(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)
+BOOL release_posix_lock_posix_flavour(files_struct *fsp,
+                               SMB_BIG_UINT u_offset,
+                               SMB_BIG_UINT u_count,
+                               const struct lock_context *plock_ctx)
 {
-    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;
 }