[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