Fix for debug statement crash.
[kamenim/samba-autobuild/.git] / source3 / locking / posix.c
index 0fcba3432db57c405c7f6cdc012dacb50ac5c520..45d139b7342f9839518457812715a180b6ce35c8 100644 (file)
@@ -100,13 +100,11 @@ static BOOL add_fd_to_close_entry(files_struct *fsp)
 
        dbuf.dptr = NULL;
 
-       tdb_lockchain(posix_pending_close_tdb, kbuf);
        dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
 
        dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(int));
        if (!dbuf.dptr) {
                DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n"));
-               tdb_unlockchain(posix_pending_close_tdb, kbuf);
                return False;
        }
        memcpy(dbuf.dptr + dbuf.dsize, &fsp->fd, sizeof(int));
@@ -117,7 +115,6 @@ static BOOL add_fd_to_close_entry(files_struct *fsp)
        }
 
        free(dbuf.dptr);
-       tdb_unlockchain(posix_pending_close_tdb, kbuf);
        return True;
 }
 
@@ -129,10 +126,8 @@ static void delete_close_entries(files_struct *fsp)
 {
        TDB_DATA kbuf = locking_key_fsp(fsp);
 
-       tdb_lockchain(posix_pending_close_tdb, kbuf);
        if (tdb_delete(posix_pending_close_tdb, kbuf) == -1)
                DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
-       tdb_unlockchain(posix_pending_close_tdb, kbuf);
 }
 
 /****************************************************************************
@@ -149,19 +144,15 @@ static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
        *entries = NULL;
        dbuf.dptr = NULL;
 
-       tdb_lockchain(posix_pending_close_tdb, kbuf);
        dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
 
     if (!dbuf.dptr) {
-               tdb_unlockchain(posix_pending_close_tdb, kbuf);
                return 0;
        }
 
        *entries = (int *)dbuf.dptr;
        count = (size_t)(dbuf.dsize / sizeof(int));
 
-       tdb_unlockchain(posix_pending_close_tdb, kbuf);
-
        return count;
 }
 
@@ -180,24 +171,22 @@ static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entr
 
        dbuf.dptr = NULL;
 
-       tdb_lockchain(posix_lock_tdb, kbuf);
        dbuf = tdb_fetch(posix_lock_tdb, kbuf);
 
     if (!dbuf.dptr) {
-               tdb_unlockchain(posix_lock_tdb, kbuf);
                return 0;
        }
 
        *entries = (struct posix_lock *)dbuf.dptr;
        count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
 
-    tdb_unlockchain(posix_lock_tdb, kbuf);
-
        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)
@@ -207,6 +196,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
        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))) {
                /*
@@ -222,8 +212,21 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
         */
 
        count = get_posix_lock_entries(fsp, &entries);
-       
-       if (count) {
+
+       /*
+        * 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*.
+        */
+
+       for (i = 0; i < count; i++) {
+               if (entries[i].fd != fsp->fd) {
+                       locks_on_other_fds = True;
+                       break;
+               }
+       }
+
+       if (locks_on_other_fds) {
 
                /*
                 * There are outstanding locks on this dev/inode pair on other fds.
@@ -259,9 +262,6 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
                        }
                }
 
-               if (fd_array)
-                       free((char *)fd_array);
-
                /*
                 * Delete all fd's stored in the tdb
                 * for this dev/inode pair.
@@ -299,17 +299,46 @@ static const char *posix_lock_type_name(int lock_type)
 }
 
 /****************************************************************************
- Add an entry into the POSIX locking tdb.
+ Add an entry into the POSIX locking tdb. Returns the number of records that
+ match the given start and size, or -1 on error.
 ****************************************************************************/
 
-static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type)
+static int add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type)
 {
        TDB_DATA kbuf = locking_key_fsp(fsp);
        TDB_DATA dbuf;
        struct posix_lock pl;
+       struct posix_lock *entries;
+       size_t i, count;
+       int num_records = 0;
 
        /*
-        * Now setup the new record.
+        * Windows is very strange. It allows read locks to be overlayed on 
+        * a write lock, but leaves the write lock in force until the first
+        * unlock. It also reference counts the locks. This means the following sequence :
+        *
+        * process1                                      process2
+        * ------------------------------------------------------------------------
+        * WRITE LOCK : start = 0, len = 10
+        *                                            READ LOCK: start =0, len = 10 - FAIL
+        * READ LOCK : start = 0, len = 10
+        *                                            READ LOCK: start =0, len = 10 - FAIL
+        * UNLOCK : start = 0, len = 10
+        *                                            READ LOCK: start =0, len = 10 - OK
+        *
+        * Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but
+        * would leave a single read lock over the 0-10 region. In order to
+        * re-create Windows semantics mapped to POSIX locks, we create multiple TDB
+        * entries, one for each overlayed lock request. We are guarenteed by the brlock
+        * semantics that if a write lock is added, then it will be first in the array.
+        */
+       
+       dbuf.dptr = NULL;
+
+       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
+
+       /*
+        * New record.
         */
 
        pl.fd = fsp->fd;
@@ -317,11 +346,6 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s
        pl.size = size;
        pl.lock_type = lock_type;
 
-       dbuf.dptr = NULL;
-
-       tdb_lockchain(posix_lock_tdb, kbuf);
-       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
        dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl));
        if (!dbuf.dptr) {
                DEBUG(0,("add_posix_lock_entry: Realloc fail !\n"));
@@ -331,41 +355,53 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s
        memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl));
        dbuf.dsize += sizeof(pl);
 
+       count = (size_t)(dbuf.dsize / sizeof(pl));
+       entries = (struct posix_lock *)dbuf.dptr;
+
+       for (i = 0; i < count; i++) {
+               struct posix_lock *entry = &entries[i];
+
+               if (fsp->fd == entry->fd &&
+                       start == entry->start &&
+                       size == entry->size)
+                       num_records++;
+
+       }
+
        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;
        }
 
     free(dbuf.dptr);
-    tdb_unlockchain(posix_lock_tdb, kbuf);
 
-       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,
+       DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: num_records = %d : dev=%.0f inode=%.0f\n",
+                       fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, num_records,
                        (double)fsp->dev, (double)fsp->inode ));
 
-    return True;
+    return num_records;
 
  fail:
     if (dbuf.dptr)
                free(dbuf.dptr);
-    tdb_unlockchain(posix_lock_tdb, kbuf);
-    return False;
+    return -1;
 }
 
 /****************************************************************************
- Delete an entry from the POSIX locking tdb.
+ Delete an entry from the POSIX locking tdb. Returns a copy of the entry being
+ deleted and the number of remaining matching records, or -1 on error.
 ****************************************************************************/
 
-static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size)
+static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl)
 {
        TDB_DATA kbuf = locking_key_fsp(fsp);
        TDB_DATA dbuf;
        struct posix_lock *locks;
        size_t i, count;
+       int num_records = 0;
 
        dbuf.dptr = NULL;
-
-       tdb_lockchain(posix_lock_tdb, kbuf);
+       
        dbuf = tdb_fetch(posix_lock_tdb, kbuf);
 
        if (!dbuf.dptr) {
@@ -377,12 +413,38 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_
        locks = (struct posix_lock *)dbuf.dptr;
        count = (size_t)(dbuf.dsize / sizeof(*locks));
 
+       /*
+        * Count the number of entries that match this
+        * unlock request.
+        */
+
+       for (i = 0; i < count; i++) {
+               struct posix_lock *entry = &locks[i];
+
+               if (entry->fd == fsp->fd &&
+                       entry->start == start &&
+                       entry->size == size) {
+                               num_records++;
+               }
+       }
+
        for (i=0; i<count; i++) { 
-               struct posix_lock *pl = &locks[i];
+               struct posix_lock *entry = &locks[i];
+
+               if (entry->fd == fsp->fd &&
+                       entry->start == start &&
+                       entry->size == size) {
+
+                       num_records--; /* We're deleting one. */
+
+                       /* Make a copy if requested. */
+                       if (pl)
+                               *pl = *entry;
+
+                       DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n",
+                                       posix_lock_type_name(entry->lock_type), (double)entry->start, (double)entry->size,
+                                       (unsigned int)num_records ));
 
-               if (pl->fd == fsp->fd &&
-                       pl->start == start &&
-                       pl->size == size) {
                        /* Found it - delete it. */
                        if (count == 1) {
                                tdb_delete(posix_lock_tdb, kbuf);
@@ -395,8 +457,7 @@ static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_
                        }
 
                        free(dbuf.dptr);
-                       tdb_unlockchain(posix_lock_tdb, kbuf);
-                       return True;
+                       return num_records;
                }
        }
 
@@ -405,8 +466,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(posix_lock_tdb, kbuf);
-    return False;
+    return -1;
 }
 
 /****************************************************************************
@@ -633,6 +693,126 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
        return True;
 }
 
+#if defined(LARGE_SMB_OFF_T)
+/****************************************************************************
+ Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
+****************************************************************************/
+
+static uint32 map_lock_offset(uint32 high, uint32 low)
+{
+       unsigned int i;
+       uint32 mask = 0;
+       uint32 highcopy = high;
+
+       /*
+        * Try and find out how many significant bits there are in high.
+        */
+
+       for(i = 0; highcopy; i++)
+               highcopy >>= 1;
+
+       /*
+        * We use 31 bits not 32 here as POSIX
+        * lock offsets may not be negative.
+        */
+
+       mask = (~0) << (31 - i);
+
+       if(low & mask)
+               return 0; /* Fail. */
+
+       high <<= (31 - i);
+
+       return (high|low);
+}
+#endif
+
+/****************************************************************************
+ 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)
+{
+       int ret;
+       struct connection_struct *conn = fsp->conn;
+
+#if defined(LARGE_SMB_OFF_T)
+       /*
+        * In the 64 bit locking case we store the original
+        * values in case we have to map to a 32 bit lock on
+        * a filesystem that doesn't support 64 bit locks.
+        */
+       SMB_OFF_T orig_offset = offset;
+       SMB_OFF_T orig_count = count;
+#endif /* LARGE_SMB_OFF_T */
+
+       DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fd,op,(double)offset,(double)count,type));
+
+       ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type);
+
+       if (!ret && (errno == EFBIG)) {
+               if( DEBUGLVL( 0 )) {
+                       dbgtext("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
+                       dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
+                       dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
+               }
+               /* 32 bit NFS file system, retry with smaller offset */
+               errno = 0;
+               count &= 0x7fffffff;
+               ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type);
+       }
+
+       /* A lock query - just return. */
+       if (op == SMB_F_GETLK)
+               return ret;
+
+       /* A lock set or unset. */
+       if (!ret) {
+               DEBUG(3,("posix_fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
+                               (double)offset,(double)count,op,type,strerror(errno)));
+
+               /* Perhaps it doesn't support this sort of locking ? */
+               if (errno == EINVAL) {
+#if defined(LARGE_SMB_OFF_T)
+                       {
+                               /*
+                                * Ok - if we get here then we have a 64 bit lock request
+                                * that has returned EINVAL. Try and map to 31 bits for offset
+                                * and length and try again. This may happen if a filesystem
+                                * doesn't support 64 bit offsets (efs/ufs) although the underlying
+                                * OS does.
+                                */
+                               uint32 off_low = (orig_offset & 0xFFFFFFFF);
+                               uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF);
+
+                               count = (orig_count & 0x7FFFFFFF);
+                               offset = (SMB_OFF_T)map_lock_offset(off_high, off_low);
+                               ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type);
+                               if (!ret) {
+                                       if (errno == EINVAL) {
+                                               DEBUG(3,("posix_fcntl_lock: locking not supported? returning True\n"));
+                                               return(True);
+                                       }
+                                       return False;
+                               }
+                               DEBUG(3,("posix_fcntl_lock: 64 -> 32 bit modified lock call successful\n"));
+                               return True;
+                       }
+#else /* LARGE_SMB_OFF_T */
+                       DEBUG(3,("locking not supported? returning True\n"));
+                       return(True);
+#endif /* LARGE_SMB_OFF_T */
+               }
+
+               return(False);
+       }
+
+       DEBUG(8,("posix_fcntl_lock: Lock call successful\n"));
+
+       return(True);
+}
+
 /****************************************************************************
  POSIX function to see if a file region is locked. Returns True if the
  region is locked, False otherwise.
@@ -661,7 +841,7 @@ BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_co
         * fd. So we don't need to use map_lock_type here.
         */ 
 
-       return fcntl_lock(fsp->fd,SMB_F_GETLK,offset,count,posix_lock_type);
+       return posix_fcntl_lock(fsp,SMB_F_GETLK,offset,count,posix_lock_type);
 }
 
 /****************************************************************************
@@ -675,6 +855,7 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou
        SMB_OFF_T count;
        BOOL ret = True;
        int posix_lock_type = map_posix_lock_type(fsp,lock_type);
+       int ref_count;
 
        DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n",
                        fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
@@ -692,13 +873,25 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou
         * file descriptors will not be held separately by the kernel (POSIX
         * braindamage), but will be merged into one continuous lock
         * range. We cope with this case in the release_posix_lock code
-        * below. JRA.
+        * below. We need to add the posix lock entry into the tdb before
+        * doing the real posix lock call to deal with the locking overlay
+        * case described above in add_posix_lock_entry().
         */
 
-    ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,posix_lock_type);
+       ref_count = add_posix_lock_entry(fsp,offset,count,posix_lock_type);
+
+       if (ref_count == 1) {
+               /*
+                * First lock entry created. Do a real POSIX lock.
+                */
+           ret = posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type);
 
-       if (ret)
-               add_posix_lock_entry(fsp,offset,count,posix_lock_type);
+               /*
+                * Oops, POSIX lock failed, delete the tdb entry.
+                */
+               if (!ret)
+                       delete_posix_lock_entry(fsp,offset,count,NULL);
+       }
 
        return ret;
 }
@@ -730,11 +923,9 @@ static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list
 
        dbuf.dptr = NULL;
 
-       tdb_lockchain(posix_lock_tdb, kbuf);
        dbuf = tdb_fetch(posix_lock_tdb, kbuf);
 
        if (!dbuf.dptr) {
-               tdb_unlockchain(posix_lock_tdb, kbuf);
                return ulhead;
        }
        
@@ -766,7 +957,7 @@ static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list
                                (double)lock->start, (double)lock->size ));
 
                        if ( (ul_curr->start >= (lock->start + lock->size)) ||
-                                (lock->start > (ul_curr->start + ul_curr->size))) {
+                                (lock->start >= (ul_curr->start + ul_curr->size))) {
 
                                /* No overlap with this lock - leave this range alone. */
 /*********************************************
@@ -918,14 +1109,16 @@ new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size,
                                 * This logic case should never happen. Ensure this is the
                                 * case by forcing an abort.... Remove in production.
                                 */
+                               pstring msg;
+
+                               slprintf(msg, sizeof(msg)-1, "logic flaw in cases: ul_curr: start = %.0f, size = %.0f : \
+lock: start = %.0f, size = %.0f\n", (double)ul_curr->start, (double)ul_curr->size, (double)lock->start, (double)lock->size );
 
-                               smb_panic("logic flaw in cases...\n");
+                               smb_panic(msg);
                        }
                } /* end for ( ul_curr = ulhead; ul_curr;) */
        } /* end for (i=0; i<num_locks && ul_head; i++) */
 
-       tdb_unlockchain(posix_lock_tdb, kbuf);
-
        if (dbuf.dptr)
                free(dbuf.dptr);
        
@@ -945,6 +1138,8 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
        TALLOC_CTX *ul_ctx = NULL;
        struct unlock_list *ulist = NULL;
        struct unlock_list *ul = NULL;
+       struct posix_lock deleted_lock;
+       int num_entries;
 
        DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n",
                fsp->fsp_name, (double)u_offset, (double)u_count ));
@@ -962,7 +1157,30 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
         * if it may have been split into multiple smaller POSIX unlock ranges.
         */ 
 
-       delete_posix_lock_entry(fsp, offset, count);
+       num_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock);
+
+       if (num_entries == -1) {
+        smb_panic("release_posix_lock: unable find entry to delete !\n");
+       }
+
+       /*
+        * If num_entries is > 0, and the lock_type we just deleted from the tdb was
+        * a POSIX write lock, then rather than doing an unlock we need to downgrade
+        * the POSIX lock to a read lock.
+        */
+
+       if (num_entries > 0 && deleted_lock.lock_type == F_WRLCK) {
+               return posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK);
+       }
+
+       /*
+        * Only do the POSIX unlock when the num_entries is now zero.
+        */
+
+       if (num_entries > 0) {
+               DEBUG(10, ("release_posix_lock: num_entries = %d\n", num_entries ));
+               return True;
+       }
 
        if ((ul_ctx = talloc_init()) == NULL) {
         DEBUG(0,("release_posix_lock: unable to init talloc context.\n"));
@@ -1018,11 +1236,11 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
                DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n",
                        (double)offset, (double)count ));
 
-               if (!fcntl_lock(fsp->fd,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);
+       talloc_destroy(ul_ctx);
 
        return ret;
 }
@@ -1035,10 +1253,18 @@ static void delete_posix_lock_entries(files_struct *fsp)
 {
        TDB_DATA kbuf = locking_key_fsp(fsp);
 
-       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);
+}
+
+/****************************************************************************
+ Debug function.
+****************************************************************************/
+
+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 ));
 }
 
 /****************************************************************************
@@ -1068,6 +1294,8 @@ void posix_locking_close_file(files_struct *fsp)
        for (i = 0; i < count; i++) {
                if (entries[i].fd != fsp->fd )
                        break;
+
+               dump_entry(&entries[i]);
        }
 
        if (i == count) {
@@ -1086,7 +1314,8 @@ void posix_locking_close_file(files_struct *fsp)
 
        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 );
+               if (pl->fd == fsp->fd)
+                       release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size );
        }
        free((char *)entries);
 }
@@ -1101,14 +1330,14 @@ BOOL posix_locking_init(void)
                return True;
 
        if (!posix_lock_tdb)
-               posix_lock_tdb = tdb_open(NULL, 0, TDB_CLEAR_IF_FIRST,
-                   O_RDWR|O_CREAT, 0644);
+               posix_lock_tdb = tdb_open(NULL, 0, TDB_INTERNAL,
+                                         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,
+               posix_pending_close_tdb = tdb_open(NULL, 0, TDB_INTERNAL,
                    O_RDWR|O_CREAT, 0644);
     if (!posix_pending_close_tdb) {
         DEBUG(0,("Failed to open POSIX pending close database.\n"));