Author: jra
Date: 2006-03-25 01:50:00 +0000 (Sat, 25 Mar 2006)
New Revision: 14704

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=14704

Log:
Fix lock queries with the new VFS semantics.
Jeremy.

Modified:
   trunk/source/locking/posix.c


Changeset:
Modified: trunk/source/locking/posix.c
===================================================================
--- trunk/source/locking/posix.c        2006-03-25 01:35:43 UTC (rev 14703)
+++ trunk/source/locking/posix.c        2006-03-25 01:50:00 UTC (rev 14704)
@@ -649,16 +649,11 @@
 
 static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, 
SMB_OFF_T count, int type)
 {
-       int ret;
+       BOOL ret;
 
        DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f 
%d\n",fsp->fh->fd,op,(double)offset,(double)count,type));
 
-       if (op != SMB_F_GETLK) {
-               ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
-       } else {
-               pid_t pid;
-               ret = 
SMB_VFS_GETLOCK(fsp,fsp->fh->fd,&offset,&count,&type,&pid);
-       }
+       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
 
        if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  
EINVAL))) {
 
@@ -682,12 +677,7 @@
                        DEBUG(0,("Count greater than 31 bits - retrying with 31 
bit truncated length.\n"));
                        errno = 0;
                        count &= 0x7fffffff;
-                       if (op != SMB_F_GETLK) {
-                               ret = 
SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
-                       } else {
-                               pid_t pid;
-                               ret = 
SMB_VFS_GETLOCK(fsp,fsp->fh->fd,&offset,&count,&type,&pid);
-                       }
+                       ret = 
SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
                }
        }
 
@@ -696,6 +686,52 @@
 }
 
 /****************************************************************************
+ Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and
+ broken NFS implementations.
+****************************************************************************/
+
+static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, 
SMB_OFF_T *pcount, int *ptype)
+{
+       pid_t pid;
+       BOOL ret;
+
+       DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n",
+               fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype));
+
+       ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
+
+       if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  
EINVAL))) {
+
+               DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset 
%.0f, length %.0f returned\n",
+                                       (double)*poffset,(double)*pcount));
+               DEBUG(0,("an %s error. This can happen when using 64 bit lock 
offsets\n", strerror(errno)));
+               DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
+
+               /*
+                * If the offset is > 0x7FFFFFFF then this will cause problems 
on
+                * 32 bit NFS mounted filesystems. Just ignore it.
+                */
+
+               if (*poffset & ~((SMB_OFF_T)0x7fffffff)) {
+                       DEBUG(0,("Offset greater than 31 bits. Returning 
success.\n"));
+                       return True;
+               }
+
+               if (*pcount & ~((SMB_OFF_T)0x7fffffff)) {
+                       /* 32 bit NFS file system, retry with smaller offset */
+                       DEBUG(0,("Count greater than 31 bits - retrying with 31 
bit truncated length.\n"));
+                       errno = 0;
+                       *pcount &= 0x7fffffff;
+                       ret = 
SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
+               }
+       }
+
+       DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? 
"successful" : "failed"));
+       return ret;
+}
+
+
+/****************************************************************************
  POSIX function to see if a file region is locked. Returns True if the
  region is locked, False otherwise.
 ****************************************************************************/
@@ -718,20 +754,15 @@
         * never set it, so presume it is not locked.
         */
 
-       if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
+       if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
                return False;
+       }
 
-       /*
-        * Note that most UNIX's can *test* for a write lock on
-        * a read-only fd, just not *set* a write lock on a read-only
-        * fd. So we don't need to use map_lock_type here.
-        */ 
-
-       if (!posix_fcntl_lock(fsp,SMB_F_GETLK,offset,count,posix_lock_type)) {
+       if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) {
                return False;
        }
 
-       return (posix_lock_type != F_UNLCK ? True : False);
+       return (posix_lock_type == F_UNLCK ? False : True);
 }
 
 /*

Reply via email to