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); } /*