Skip to content
Snippets Groups Projects
Commit d28b74e4 authored by rswindell's avatar rswindell
Browse files

Use "Open file description locks" when available (i.e. Linux 3.15 and later)

This variation on fcntl() record-locks resolves multiple-thread / forking
issue with region locks. No longer falls back to using flock() (whole-file
locks), when OFD locks are available and used successfully. At the least,
this should provide a performance boost for shared files using region
locks (on Linux). No change for Windows (region locks already worked sanely
among multiple threads) and other *nixes (that use POSIX fcntl() locks
only).
parent 279bc350
No related branches found
No related tags found
No related merge requests found
......@@ -90,7 +90,11 @@ off_t DLLCALL filelength(int fd)
int DLLCALL lock(int fd, off_t pos, off_t len)
{
#if defined(F_SANERDLCKNO) || !defined(BSD)
struct flock alock;
struct flock alock = {0};
int cmd = F_SETLK;
#ifdef F_OFD_SETLK
cmd = F_OFD_SETLK;
#endif
#ifndef F_SANEWRLCKNO
int flags;
......@@ -107,8 +111,13 @@ int DLLCALL lock(int fd, off_t pos, off_t len)
alock.l_start = pos;
alock.l_len = (int)len;
if(fcntl(fd, F_SETLK, &alock)==-1 && errno != EINVAL)
return(-1);
int result = fcntl(fd, cmd, &alock);
if(result == -1 && errno != EINVAL)
return -1;
#ifdef F_OFD_SETLK
if(result == 0)
return 0;
#endif
#endif
#if !defined(F_SANEWRLCKNO) && !defined(__QNX__) && !defined(__solaris__)
......@@ -125,7 +134,11 @@ int DLLCALL unlock(int fd, off_t pos, off_t len)
{
#if defined(F_SANEUNLCK) || !defined(BSD)
struct flock alock;
struct flock alock = {0};
int cmd = F_SETLK;
#ifdef F_OFD_SETLK
cmd = F_OFD_SETLK;
#endif
#ifdef F_SANEUNLCK
alock.l_type = F_SANEUNLCK; /* remove the lock */
#else
......@@ -134,8 +147,13 @@ int DLLCALL unlock(int fd, off_t pos, off_t len)
alock.l_whence = L_SET;
alock.l_start = pos;
alock.l_len = (int)len;
if(fcntl(fd, F_SETLK, &alock)==-1 && errno != EINVAL)
return(-1);
int result = fcntl(fd, cmd, &alock);
if(result == -1 && errno != EINVAL)
return -1;
#ifdef F_OFD_SETLK
if(result == 0)
return 0;
#endif
#endif
#if !defined(F_SANEUNLCK) && !defined(__QNX__) && !defined(__solaris__)
......@@ -192,7 +210,7 @@ int DLLCALL sopen(const char *fn, int sh_access, int share, ...)
int flock_op=LOCK_NB; /* non-blocking */
#endif
#if defined(F_SANEWRLCKNO) || !defined(BSD)
struct flock alock;
struct flock alock = {0};
#endif
va_list ap;
......@@ -208,13 +226,17 @@ int DLLCALL sopen(const char *fn, int sh_access, int share, ...)
if (share == SH_DENYNO || share == SH_COMPAT) /* no lock needed */
return fd;
#if defined(F_SANEWRLCKNO) || !defined(BSD)
int cmd = F_SETLK;
#ifdef F_OFD_SETLK
cmd = F_OFD_SETLK;
#endif
/* use fcntl (doesn't work correctly with threads) */
alock.l_type = share;
alock.l_whence = L_SET;
alock.l_start = 0;
alock.l_len = 0; /* lock to EOF */
if(fcntl(fd, F_SETLK, &alock)==-1 && errno != EINVAL) { /* EINVAL means the file does not support locking */
if(fcntl(fd, cmd, &alock)==-1 && errno != EINVAL) { /* EINVAL means the file does not support locking */
close(fd);
return -1;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment