diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 94 |
1 files changed, 66 insertions, 28 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index fb49aef1f2ec..5c497c529772 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -555,7 +555,10 @@ int cifs_closedir(struct inode *inode, struct file *file) if (ptmp) { cFYI(1, ("closedir free smb buf in srch struct")); pCFileStruct->srch_inf.ntwrk_buf_start = NULL; - cifs_buf_release(ptmp); + if(pCFileStruct->srch_inf.smallBuf) + cifs_small_buf_release(ptmp); + else + cifs_buf_release(ptmp); } ptmp = pCFileStruct->search_resume_name; if (ptmp) { @@ -574,13 +577,14 @@ int cifs_closedir(struct inode *inode, struct file *file) int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) { int rc, xid; - __u32 lockType = LOCKING_ANDX_LARGE_FILES; __u32 numLock = 0; __u32 numUnlock = 0; __u64 length; int wait_flag = FALSE; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; + __u16 netfid; + __u8 lockType = LOCKING_ANDX_LARGE_FILES; length = 1 + pfLock->fl_end - pfLock->fl_start; rc = -EACCES; @@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) pfLock->fl_end)); if (pfLock->fl_flags & FL_POSIX) - cFYI(1, ("Posix ")); + cFYI(1, ("Posix")); if (pfLock->fl_flags & FL_FLOCK) - cFYI(1, ("Flock ")); + cFYI(1, ("Flock")); if (pfLock->fl_flags & FL_SLEEP) { - cFYI(1, ("Blocking lock ")); + cFYI(1, ("Blocking lock")); wait_flag = TRUE; } if (pfLock->fl_flags & FL_ACCESS) @@ -612,21 +616,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) cFYI(1, ("F_WRLCK ")); numLock = 1; } else if (pfLock->fl_type == F_UNLCK) { - cFYI(1, ("F_UNLCK ")); + cFYI(1, ("F_UNLCK")); numUnlock = 1; + /* Check if unlock includes more than + one lock range */ } else if (pfLock->fl_type == F_RDLCK) { - cFYI(1, ("F_RDLCK ")); + cFYI(1, ("F_RDLCK")); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else if (pfLock->fl_type == F_EXLCK) { - cFYI(1, ("F_EXLCK ")); + cFYI(1, ("F_EXLCK")); numLock = 1; } else if (pfLock->fl_type == F_SHLCK) { - cFYI(1, ("F_SHLCK ")); + cFYI(1, ("F_SHLCK")); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else - cFYI(1, ("Unknown type of lock ")); + cFYI(1, ("Unknown type of lock")); cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; @@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) FreeXid(xid); return -EBADF; } + netfid = ((struct cifsFileInfo *)file->private_data)->netfid; + + /* BB add code here to normalize offset and length to + account for negative length which we can not accept over the + wire */ if (IS_GETLK(cmd)) { - rc = CIFSSMBLock(xid, pTcon, - ((struct cifsFileInfo *)file-> - private_data)->netfid, - length, - pfLock->fl_start, 0, 1, lockType, - 0 /* wait flag */ ); + if(experimEnabled && + (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_FCNTL_CAP & + le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { + int posix_lock_type; + if(lockType & LOCKING_ANDX_SHARED_LOCK) + posix_lock_type = CIFS_RDLCK; + else + posix_lock_type = CIFS_WRLCK; + rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */, + length, pfLock->fl_start, + posix_lock_type, wait_flag); + FreeXid(xid); + return rc; + } + + /* BB we could chain these into one lock request BB */ + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, + 0, 1, lockType, 0 /* wait flag */ ); if (rc == 0) { - rc = CIFSSMBLock(xid, pTcon, - ((struct cifsFileInfo *) file-> - private_data)->netfid, - length, + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, 1 /* numUnlock */ , 0 /* numLock */ , lockType, 0 /* wait flag */ ); pfLock->fl_type = F_UNLCK; if (rc != 0) cERROR(1, ("Error unlocking previously locked " - "range %d during test of lock ", - rc)); + "range %d during test of lock", rc)); rc = 0; } else { @@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) FreeXid(xid); return rc; } - - rc = CIFSSMBLock(xid, pTcon, - ((struct cifsFileInfo *) file->private_data)-> - netfid, length, - pfLock->fl_start, numUnlock, numLock, lockType, - wait_flag); + if (experimEnabled && + (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_FCNTL_CAP & + le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { + int posix_lock_type; + if(lockType & LOCKING_ANDX_SHARED_LOCK) + posix_lock_type = CIFS_RDLCK; + else + posix_lock_type = CIFS_WRLCK; + + if(numUnlock == 1) + posix_lock_type = CIFS_UNLCK; + else if(numLock == 0) { + /* if no lock or unlock then nothing + to do since we do not know what it is */ + FreeXid(xid); + return -EOPNOTSUPP; + } + rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, + length, pfLock->fl_start, + posix_lock_type, wait_flag); + } else + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, + numUnlock, numLock, lockType, wait_flag); if (pfLock->fl_flags & FL_POSIX) posix_lock_file_wait(file, pfLock); FreeXid(xid); |