summaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c94
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);
OpenPOWER on IntegriCloud