Did the rewrite Andrew wanted where all knowledge of POSIX locking is
authorJeremy Allison <jra@samba.org>
Thu, 27 Apr 2000 21:12:33 +0000 (21:12 +0000)
committerJeremy Allison <jra@samba.org>
Thu, 27 Apr 2000 21:12:33 +0000 (21:12 +0000)
removed from the smbd/open.c code.
We now use a dlink list of structures indexed by dev/inode to store
all pending fd's for close. This could be rewritten to use lib/hash.c
if this is discovered to be too slow in use.
Andrew, please take a look and let me know if this is what you
had in mind.
Jeremy.
(This used to be commit 0487841120a7584da9a2b83b9574562c415d7024)

source3/include/proto.h
source3/include/smb.h
source3/locking/locking.c
source3/smbd/open.c

index 79ebe331ad0816c0d5e32d827d7b4c30f1324f9e..8c6fcd56b740eb367d612c4063b4251b6a3c136a 100644 (file)
@@ -831,6 +831,7 @@ int brl_forall(BRLOCK_FN(fn));
 
 /*The following definitions come from  locking/locking.c  */
 
+BOOL fd_close_posix_locks(struct connection_struct *conn, files_struct *fsp);
 BOOL is_locked(files_struct *fsp,connection_struct *conn,
               SMB_BIG_UINT count,SMB_BIG_UINT offset, 
               enum brl_type lock_type);
index 2e11d667298c19e6b4198f5b6325f688d9889b8d..6a3964e0f3eb83314aed03cf89a42a5fdbea84d9 100644 (file)
@@ -489,9 +489,6 @@ typedef struct files_struct
        time_t pending_modtime;
        int oplock_type;
        int sent_oplock_break;
-       int num_posix_locks;
-       unsigned int num_posix_pending_closes;
-       int *posix_pending_close_fds;
        BOOL can_lock;
        BOOL can_read;
        BOOL can_write;
index b61e8acedc66a6c847d668ed1ac5bda83dcb0e1b..9d407bf16b5217c707e5bec3e966ed20a710d299 100644 (file)
@@ -2,7 +2,8 @@
    Unix SMB/Netbios implementation.
    Version 3.0
    Locking functions
-   Copyright (C) Andrew Tridgell 1992-1999
+   Copyright (C) Andrew Tridgell 1992-2000
+   Copyright (C) Jeremy Allison 1992-2000
    
    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
@@ -30,6 +31,8 @@
    support.
 
    rewrtten completely to use new tdb code. Tridge, Dec '99
+
+   Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
 */
 
 #include "includes.h"
@@ -40,6 +43,179 @@ static TDB_CONTEXT *tdb;
 
 int global_smbpid;
 
+/*
+ * Doubly linked list to hold pending closes needed for
+ * POSIX locks. This may be changed to use a hash table (as
+ * in lib/hash.c if this is too slow in use.... JRA.
+ */
+
+struct pending_closes {
+       struct pending_closes *next;
+       struct pending_closes *prev;
+       SMB_DEV_T dev;
+       SMB_INO_T inode;
+       int num_posix_locks;
+       size_t fd_array_size;
+       int *fd_array;
+};
+
+static struct pending_closes *pending_close_list = NULL;
+
+/****************************************************************************
+ Find a dev/inode pair in the pending close list.
+****************************************************************************/
+
+static struct pending_closes *find_pending_close_entry(SMB_DEV_T dev, SMB_INO_T inode)
+{
+       struct pending_closes *pc;
+
+       for(pc = pending_close_list; pc; pc = pc->next) {
+               if (dev == pc->dev && inode == pc->inode) {
+                       DLIST_PROMOTE(pending_close_list,pc);
+                       return pc;
+               }
+       }
+
+       return NULL;
+}
+/****************************************************************************
+ Add an fd into the pending close array.
+****************************************************************************/
+
+static BOOL add_fd_to_close_entry(struct pending_closes *pc, int fd)
+{
+       if ((pc->fd_array = (int *)Realloc(pc->fd_array, (pc->fd_array_size + 1)*sizeof(int))) == NULL) {
+               DEBUG(0,("add_fd_to_close_entry: Unable to increase fd_array !\n"));
+               return False;
+       }
+
+       pc->fd_array[pc->fd_array_size] = fd;
+       pc->fd_array_size++;
+
+       DEBUG(10,("add_fd_to_close_entry: added fd = %d, size = %u : dev = %.0f, ino = %.0f\n",
+                       fd, (unsigned int)pc->fd_array_size, (double)pc->dev, (double)pc->inode ));
+
+       return True;
+}
+
+/****************************************************************************
+ Deal with pending closes needed by POSIX locking support.
+****************************************************************************/
+
+BOOL fd_close_posix_locks(struct connection_struct *conn, files_struct *fsp)
+{
+       struct pending_closes *pc;
+       int saved_errno = 0;
+       size_t i;
+
+       if (!lp_posix_locking(SNUM(conn)))
+               return True;
+
+       pc = find_pending_close_entry(fsp->dev, fsp->inode);
+       
+       if (!pc) {
+               /* 
+                * No other open with a POSIX lock on this dev/inode within this smbd.
+                * Just exit.
+                */
+               return True;
+       }
+
+       if (pc->num_posix_locks) {
+               /*
+                * There are outstanding locks on this dev/inode pair.
+                * Add our fd to the list and set fsp->fd to -1 to
+                * stop the close.
+                */
+
+               if (!add_fd_to_close_entry(pc, fsp->fd))
+                       return False;
+
+               fsp->fd = -1;
+               return True;
+       }
+
+       DEBUG(10,("fd_close_posix_locks: doing close on %u fd's.\n", (unsigned int)pc->fd_array_size ));
+
+       /*
+        * This is the last close. If there are pending fd's close them
+        * now. Save the errno just in case.
+        */
+
+       for(i = 0; i < pc->fd_array_size; i++) {
+               if (pc->fd_array[i] != -1) {
+                       if (conn->vfs_ops.close(pc->fd_array[i]) == -1) {
+                               saved_errno = errno;
+                       }
+               }
+       }
+
+       if (pc->fd_array)
+               free((char *)pc->fd_array);
+
+       DLIST_REMOVE(pending_close_list, pc);
+
+       free((char *)pc);
+
+       if (saved_errno != 0) {
+        errno = saved_errno;
+    } 
+
+       return True;
+}
+
+/****************************************************************************
+ A POSIX lock was granted. Increment the lock list count (create if needed).
+****************************************************************************/
+
+static void increment_posix_lock_list(files_struct *fsp)
+{
+       struct pending_closes *pc;
+
+       if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) == NULL) {
+               if (!(pc = (struct pending_closes *)malloc(sizeof(struct pending_closes)))) {
+                       DEBUG(0,("increment_lock_list: malloc fail.\n"));
+                       return;
+               }
+               ZERO_STRUCTP(pc);
+               pc->dev = fsp->dev;
+               pc->inode = fsp->inode;
+               DLIST_ADD(pending_close_list, pc);
+
+               DEBUG(10,("increment_posix_lock_list: creating entry for file %s: dev = %.0f, ino = %.0f\n",
+                               fsp->fsp_name, (double)fsp->dev, (double)fsp->inode ));
+       }
+
+       pc->num_posix_locks++;
+
+       DEBUG(10,("increment_posix_lock_list: entry for file %s: dev = %.0f, ino = %.0f, num_locks = %d\n",
+                       fsp->fsp_name, (double)pc->dev, (double)pc->inode, pc->num_posix_locks ));
+}
+
+
+/****************************************************************************
+ A POSIX lock was granted. Decrement the lock list count.
+****************************************************************************/
+
+static void decrement_posix_lock_list(files_struct *fsp)
+{
+       struct pending_closes *pc;
+
+       pc = find_pending_close_entry(fsp->dev, fsp->inode);
+
+       if (pc == NULL) {
+               smb_panic("decrement_lock_list: Unlock not found !\n");
+       }
+
+       pc->num_posix_locks--;
+
+       DEBUG(10,("decrement_posix_lock_list: entry for file %s: dev = %.0f, ino = %.0f, num_locks = %d\n",
+                       fsp->fsp_name, (double)pc->dev, (double)pc->inode, pc->num_posix_locks ));
+
+       SMB_ASSERT(pc->num_posix_locks >= 0);
+}
+
 /****************************************************************************
  Debugging aid :-).
 ****************************************************************************/
@@ -444,7 +620,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn,
                         */
 
                        if((ok = set_posix_lock(fsp, offset, count, lock_type)) == True)
-                               fsp->num_posix_locks++;
+                               increment_posix_lock_list(fsp);
                        else {
                                /*
                                 * We failed to map - we must now remove the brl
@@ -558,9 +734,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn,
         * if it may have been split into multiple smaller POSIX unlock ranges.
         */
 
-       fsp->num_posix_locks--;
-
-       SMB_ASSERT(fsp->num_posix_locks >= 0);
+       decrement_posix_lock_list(fsp);
 
        return True; /* Did unlock */
 }
index c7ca8256d2118a1d4ff7268484e498c193471269..737b9b5ef3684f62d259db377ab59abe4915888b 100644 (file)
@@ -49,130 +49,26 @@ static int fd_open(struct connection_struct *conn, char *fname,
        return fd;
 }
 
-/****************************************************************************
-  Take care of moving any POSIX pending close fd's to another fsp.
-****************************************************************************/
-
-static BOOL fd_close_posix_locks(files_struct *fsp)
-{
-       files_struct *other_fsp;
-
-       DEBUG(10,("fd_close_posix_locks: file %s: fsp->num_posix_pending_closes = %u \
-fsp->posix_pending_close_fds = %lx.\n", fsp->fsp_name,
-                               (unsigned int)fsp->num_posix_pending_closes, (unsigned long)fsp->posix_pending_close_fds ));
-
-       for(other_fsp = file_find_di_first(fsp->dev, fsp->inode); other_fsp;
-                                       other_fsp = file_find_di_next(other_fsp)) {
-
-               if(other_fsp == fsp)
-                       continue;
-
-               if ((other_fsp->fd != -1) && other_fsp->num_posix_locks) {
-
-                       /*
-                        * POSIX locks pending on another fsp held open, transfer
-                        * the fd in this fsp and all the pending fd's in this fsp pending close array
-                        * to the other_fsp pending close array.
-                        */
-
-                       unsigned int extra_fds = fsp->num_posix_pending_closes + 1;
-
-                       DEBUG(10,("fd_close_posix_locks: file %s: Transferring to \
-file %s, extra_fds = %u, other_fsp->num_posix_pending_closes = %u.\n",
-                               fsp->fsp_name, other_fsp->fsp_name, extra_fds, (unsigned int)other_fsp->num_posix_pending_closes ));
-
-                       other_fsp->posix_pending_close_fds = (int *)Realloc(other_fsp->posix_pending_close_fds,
-                                                                                                                               (other_fsp->num_posix_pending_closes +
-                                                                                                                                       extra_fds)*sizeof(int));
-
-                       if(other_fsp->posix_pending_close_fds == NULL) {
-                               DEBUG(0,("fd_close_posix_locks: Unable to increase posix_pending_close_fds array size !\n"));
-                               return False;
-                       }
-
-                       /*
-                        * Copy over any fd's in the existing fsp's pending array.
-                        */
-
-                       if(fsp->posix_pending_close_fds) {
-                               memcpy(&other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes],
-                                       &fsp->posix_pending_close_fds[0], fsp->num_posix_pending_closes * sizeof(int) );
-
-                               free((char *)fsp->posix_pending_close_fds);
-                               fsp->posix_pending_close_fds = NULL;
-                               fsp->num_posix_pending_closes = 0;
-                       }                       
-
-                       other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes+extra_fds-1] = fsp->fd;
-                       other_fsp->num_posix_pending_closes += extra_fds;
-
-                       fsp->fd = -1; /* We have moved this fd to other_fsp's pending close array.... */
-
-                       break;
-               }
-       }
-
-       return True;
-}
-
 /****************************************************************************
  Close the file associated with a fsp.
-
- This is where we must deal with POSIX "first close drops all locks"
- locking braindamage. We do this by searching for any other fsp open
- on the same dev/inode with open POSIX locks, and then transferring this
- fd (and all pending fd's attached to this fsp) to the posix_pending_close_fds
- array in that fsp.
-
- If there are no open fsp's on the same dev/inode then we close all the
- fd's in the posix_pending_close_fds array and then close the fd.
-
 ****************************************************************************/
 
 int fd_close(struct connection_struct *conn, files_struct *fsp)
 {
        int ret = 0;
-       int saved_errno = 0;
-       unsigned int i;
 
        /*
         * Deal with transferring any pending fd's if there
         * are POSIX locks outstanding.
         */
 
-       if(!fd_close_posix_locks(fsp))
+       if(!fd_close_posix_locks(conn,fsp))
                return -1;
 
-       /*
-        * Close and free any pending closes given to use from
-        * other fsp's.
-        */
-
-       if (fsp->posix_pending_close_fds) {
-
-               for(i = 0; i < fsp->num_posix_pending_closes; i++) {
-                       if (fsp->posix_pending_close_fds[i] != -1) {
-                               if (conn->vfs_ops.close(fsp->posix_pending_close_fds[i]) == -1) {
-                                       saved_errno = errno;
-                               }
-                       }
-               }
-
-               free((char *)fsp->posix_pending_close_fds);
-               fsp->posix_pending_close_fds = NULL;
-               fsp->num_posix_pending_closes = 0;
-       }
-
        if(fsp->fd != -1)
                ret = conn->vfs_ops.close(fsp->fd);
 
        fsp->fd = -1;
-
-       if (saved_errno != 0) {
-               errno = saved_errno;
-               ret = -1;
-       }
-
        return ret;
 }
 
@@ -278,9 +174,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
        fsp->modified = False;
        fsp->oplock_type = NO_OPLOCK;
        fsp->sent_oplock_break = NO_BREAK_SENT;
-       fsp->num_posix_locks = 0;
-       fsp->num_posix_pending_closes = 0;
-       fsp->posix_pending_close_fds = NULL;
        fsp->is_directory = False;
        fsp->stat_open = False;
        fsp->directory_delete_on_close = False;
@@ -914,9 +807,6 @@ files_struct *open_file_stat(connection_struct *conn,
        fsp->modified = False;
        fsp->oplock_type = NO_OPLOCK;
        fsp->sent_oplock_break = NO_BREAK_SENT;
-       fsp->num_posix_locks = 0;
-       fsp->num_posix_pending_closes = 0;
-       fsp->posix_pending_close_fds = NULL;
        fsp->is_directory = False;
        fsp->stat_open = True;
        fsp->directory_delete_on_close = False;
@@ -1040,9 +930,6 @@ files_struct *open_directory(connection_struct *conn,
        fsp->modified = False;
        fsp->oplock_type = NO_OPLOCK;
        fsp->sent_oplock_break = NO_BREAK_SENT;
-       fsp->num_posix_locks = 0;
-       fsp->num_posix_pending_closes = 0;
-       fsp->posix_pending_close_fds = NULL;
        fsp->is_directory = True;
        fsp->directory_delete_on_close = False;
        fsp->conn = conn;