summaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2008-12-02 17:24:33 +0000
committerSteve French <sfrench@us.ibm.com>2008-12-26 02:29:10 +0000
commit13a6e42af8d90e2e8eb7fa50adf862a525b70518 (patch)
tree5d6021da7bc49b75cca5a0947f89bde7233ebce4 /fs/cifs/file.c
parentd5c5605c27c92dac6de1a7a658af5b030847f949 (diff)
downloadlinux-stable-13a6e42af8d90e2e8eb7fa50adf862a525b70518.tar.gz
linux-stable-13a6e42af8d90e2e8eb7fa50adf862a525b70518.tar.bz2
linux-stable-13a6e42af8d90e2e8eb7fa50adf862a525b70518.zip
[CIFS] add mount option to send mandatory rather than advisory locks
Some applications/subsystems require mandatory byte range locks (as is used for Windows/DOS/OS2 etc). Sending advisory (posix style) byte range lock requests (instead of mandatory byte range locks) can lead to problems for these applications (which expect that other clients be prevented from writing to portions of the file which they have locked and are updating). This mount option allows mounting cifs with the new mount option "forcemand" (or "forcemandatorylock") in order to have the cifs client use mandatory byte range locks (ie SMB/CIFS/Windows/NTFS style locks) rather than posix byte range lock requests, even if the server would support posix byte range lock requests. This has no effect if the server does not support the CIFS Unix Extensions (since posix style locks require support for the CIFS Unix Extensions), but for mounts to Samba servers this can be helpful for Wine and applications that require mandatory byte range locks. Acked-by: Jeff Layton <jlayton@redhat.com> CC: Alexander Bokovoy <ab@samba.org> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index f0a81e631ae6..babd27a4699a 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -644,10 +644,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
__u64 length;
bool wait_flag = false;
struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *pTcon;
+ struct cifsTconInfo *tcon;
__u16 netfid;
__u8 lockType = LOCKING_ANDX_LARGE_FILES;
- bool posix_locking;
+ bool posix_locking = 0;
length = 1 + pfLock->fl_end - pfLock->fl_start;
rc = -EACCES;
@@ -698,7 +698,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
cFYI(1, ("Unknown type of lock"));
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb->tcon;
+ tcon = cifs_sb->tcon;
if (file->private_data == NULL) {
FreeXid(xid);
@@ -706,9 +706,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
}
netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
- posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
- (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability));
-
+ if ((tcon->ses->capabilities & CAP_UNIX) &&
+ (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
+ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL == 0))
+ posix_locking = 1;
/* BB add code here to normalize offset and length to
account for negative length which we can not accept over the
wire */
@@ -719,7 +720,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
posix_lock_type = CIFS_RDLCK;
else
posix_lock_type = CIFS_WRLCK;
- rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */,
+ rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */,
length, pfLock,
posix_lock_type, wait_flag);
FreeXid(xid);
@@ -727,10 +728,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
}
/* BB we could chain these into one lock request BB */
- rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
+ rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start,
0, 1, lockType, 0 /* wait flag */ );
if (rc == 0) {
- rc = CIFSSMBLock(xid, pTcon, netfid, length,
+ rc = CIFSSMBLock(xid, tcon, netfid, length,
pfLock->fl_start, 1 /* numUnlock */ ,
0 /* numLock */ , lockType,
0 /* wait flag */ );
@@ -767,7 +768,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if (numUnlock == 1)
posix_lock_type = CIFS_UNLCK;
- rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
+ rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */,
length, pfLock,
posix_lock_type, wait_flag);
} else {
@@ -775,7 +776,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
(struct cifsFileInfo *)file->private_data;
if (numLock) {
- rc = CIFSSMBLock(xid, pTcon, netfid, length,
+ rc = CIFSSMBLock(xid, tcon, netfid, length,
pfLock->fl_start,
0, numLock, lockType, wait_flag);
@@ -796,7 +797,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if (pfLock->fl_start <= li->offset &&
(pfLock->fl_start + length) >=
(li->offset + li->length)) {
- stored_rc = CIFSSMBLock(xid, pTcon,
+ stored_rc = CIFSSMBLock(xid, tcon,
netfid,
li->length, li->offset,
1, 0, li->type, false);