[Wine-patches] [eterhack 1/2] server: Workaround for bug with locks on NFS.

Alexander Morozov amorozov на etersoft.ru
Пт Июл 10 14:22:45 MSD 2009


----------- следующая часть -----------
From 774f0dabc1d3e36655c2f682daa03b4ba33656f6 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Fri, 10 Jul 2009 13:57:28 +0400
Subject: [eterhack 1/2] server: Workaround for bug with locks on NFS.

---
 include/wine/etersoft.h |    2 +
 server/fd.c             |   49 +++++++++++++++++++++++++++++++---------------
 2 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/include/wine/etersoft.h b/include/wine/etersoft.h
index aceccce..18f50e4 100644
--- a/include/wine/etersoft.h
+++ b/include/wine/etersoft.h
@@ -125,6 +125,8 @@ static int (*etersoft_sharing_pre)(int unix_fd, DWORD access, DWORD sharing, uns
                           unsigned int * existing_sharing);
 static void (*etersoft_sharing_post)(int unix_fd, DWORD access, unsigned int existing_access,
                            unsigned int existing_sharing);
+
+static void (*etersoft_sharing_set_test_fd)(int test_fd);
 #endif
 
 #ifdef ETERSOFT_FUNC_COMPARE
diff --git a/server/fd.c b/server/fd.c
index 40ebcaf..16f3eeb 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -289,6 +289,7 @@ struct inode
     struct list         open;       /* list of open file descriptors */
     struct list         locks;      /* list of file locks */
     struct list         closed;     /* list of file descriptors to close at destroy time */
+    int                 lock_fd;    /* unix file descriptor for locks */
 };
 
 static void inode_dump( struct object *obj, int verbose );
@@ -994,6 +995,11 @@ static void inode_close_pending( struct inode *inode, int keep_unlinks )
         }
         ptr = next;
     }
+    if (list_empty( &inode->open ) && inode->lock_fd != -1)
+    {
+        close( inode->lock_fd );
+        inode->lock_fd = -1;
+    }
 }
 
 static void inode_dump( struct object *obj, int verbose )
@@ -1031,6 +1037,8 @@ static void inode_destroy( struct object *obj )
         }
         free( fd );
     }
+    if (inode->lock_fd != -1)
+        close( inode->lock_fd );
     release_object( inode->device );
 }
 
@@ -1060,6 +1068,7 @@ static struct inode *get_inode( dev_t dev, ino_t ino, int unix_fd )
         list_init( &inode->open );
         list_init( &inode->locks );
         list_init( &inode->closed );
+        inode->lock_fd = -1;
         list_add_head( &device->inode_hash[hash], &inode->entry );
     }
     else release_object( device );
@@ -1070,7 +1079,7 @@ static struct inode *get_inode( dev_t dev, ino_t ino, int unix_fd )
 /* add fd to the inode list of file descriptors to close */
 static void inode_add_closed_fd( struct inode *inode, struct closed_fd *fd )
 {
-    if (!list_empty( &inode->locks ))
+    if (!list_empty( &inode->open ))
     {
         list_add_head( &inode->closed, &fd->entry );
     }
@@ -1087,6 +1096,18 @@ static void inode_add_closed_fd( struct inode *inode, struct closed_fd *fd )
     }
 }
 
+/* get fd which can be used for locks */
+static int inode_get_lock_fd( struct inode *inode )
+{
+    return inode->lock_fd;
+}
+
+/* set fd which can be used for locks */
+static void inode_set_lock_fd( struct inode *inode, int lock_fd )
+{
+    inode->lock_fd = lock_fd;
+}
+
 
 /****************************************************************/
 /* file lock functions */
@@ -1125,24 +1146,10 @@ static int set_unix_lock( struct fd *fd, file_pos_t start, file_pos_t end, int t
         fl.l_start  = start;
         if (!end || end > max_unix_offset) fl.l_len = 0;
         else fl.l_len = end - start;
-        if (fd->access == FILE_GENERIC_READ && type == F_WRLCK)
-        {   /* We can't set WR lock on read only opened file */
-            TRACEL(stderr, "Try to set WR on r/o file. Check with GETK\n");
-            fl.l_type   = F_WRLCK;
-	    /* WARNING! Some races between GETLK and SETLK can be! */
-            fcntl( fd->unix_fd, F_GETLK, &fl );
-            if (fl.l_type != F_UNLCK)
-	    {
-	        TRACEL(stderr,"Already locked. \n");
-                set_error( STATUS_FILE_LOCK_CONFLICT );
-                return 0;
-            }
-            fl.l_type = F_RDLCK;
-        }
 	if (!fl.l_len) {
 		TRACEL(stderr, "LEN is NULL!!!!!!!!!!");
 	}
-        if (fcntl( fd->unix_fd, F_SETLK, &fl ) != -1) return 1;
+        if (fcntl( inode_get_lock_fd( fd->inode ), F_SETLK, &fl ) != -1) return 1;
 	/* perror("Etersoft warning (some error during lock):"); */
         switch(errno)
         {
@@ -1611,6 +1618,8 @@ static int check_sharing( struct fd *fd, unsigned int access, unsigned int shari
         }
     }
     /* Etersoft: Set existing modes from special lock region state, get cifs status */
+    if (etersoft_sharing_set_test_fd)
+        etersoft_sharing_set_test_fd( inode_get_lock_fd( fd->inode ) );
     if (etersoft_sharing_pre)
         fd->cifs = etersoft_sharing_pre(fd->unix_fd, fd->access, fd->sharing,
             &existing_access, &existing_sharing);
@@ -1688,6 +1697,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce
         LOADETER_FUNC(etersoft_sharing_open);
         LOADETER_FUNC(etersoft_sharing_pre);
         LOADETER_FUNC(etersoft_sharing_post);
+        LOADETER_FUNC(etersoft_sharing_set_test_fd);
     }
 
     /* Etersoft: Set existing modes from special lock region state */
@@ -1718,6 +1728,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce
     if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
     {
         struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd );
+        int lock_fd;
 
         if (!inode)
         {
@@ -1730,6 +1741,12 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce
         fd->closed = closed_fd;
         list_add_head( &inode->open, &fd->inode_entry );
 
+        if (inode_get_lock_fd( inode ) == -1)
+        {
+            lock_fd = open( name, O_RDWR );
+            inode_set_lock_fd( inode, lock_fd );
+        }
+
         /* check directory options */
         if ((options & FILE_DIRECTORY_FILE) && !S_ISDIR(st.st_mode))
         {
-- 
1.6.3.3



Подробная информация о списке рассылки Wine-patches