[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>
This commit is contained in:
parent
d5c5605c27
commit
13a6e42af8
6 changed files with 48 additions and 16 deletions
|
@ -1,3 +1,9 @@
|
|||
Version 1.56
|
||||
------------
|
||||
Add "forcemandatorylock" mount option to allow user to use mandatory
|
||||
rather than posix (advisory) byte range locks, even though server would
|
||||
support posix byte range locks.
|
||||
|
||||
Version 1.55
|
||||
------------
|
||||
Various fixes to make delete of open files behavior more predictable
|
||||
|
|
|
@ -463,9 +463,19 @@ A partial list of the supported mount options follows:
|
|||
with cifs style mandatory byte range locks (and most
|
||||
cifs servers do not yet support requesting advisory
|
||||
byte range locks).
|
||||
forcemandatorylock Even if the server supports posix (advisory) byte range
|
||||
locking, send only mandatory lock requests. For some
|
||||
(presumably rare) applications, originally coded for
|
||||
DOS/Windows, which require Windows style mandatory byte range
|
||||
locking, they may be able to take advantage of this option,
|
||||
forcing the cifs client to only send mandatory locks
|
||||
even if the cifs server would support posix advisory locks.
|
||||
"forcemand" is accepted as a shorter form of this mount
|
||||
option.
|
||||
nodfs Disable DFS (global name space support) even if the
|
||||
server claims to support it. This can help work around
|
||||
a problem with parsing of DFS paths with Samba 3.0.24 server.
|
||||
a problem with parsing of DFS paths with Samba server
|
||||
versions 3.0.24 and 3.0.25.
|
||||
remount remount the share (often used to change from ro to rw mounts
|
||||
or vice versa)
|
||||
cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */
|
||||
#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */
|
||||
#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */
|
||||
#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */
|
||||
|
||||
struct cifs_sb_info {
|
||||
struct cifsTconInfo *tcon; /* primary mount */
|
||||
|
|
|
@ -101,5 +101,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
|
|||
extern const struct export_operations cifs_export_ops;
|
||||
#endif /* EXPERIMENTAL */
|
||||
|
||||
#define CIFS_VERSION "1.55"
|
||||
#define CIFS_VERSION "1.5666666"
|
||||
#endif /* _CIFSFS_H */
|
||||
|
|
|
@ -89,6 +89,7 @@ struct smb_vol {
|
|||
bool nullauth:1; /* attempt to authenticate with null user */
|
||||
bool nocase:1; /* request case insensitive filenames */
|
||||
bool nobrl:1; /* disable sending byte range locks to srv */
|
||||
bool mand_lock:1; /* send mandatory not posix byte range lock reqs */
|
||||
bool seal:1; /* request transport encryption on share */
|
||||
bool nodfs:1; /* Do not request DFS, even if available */
|
||||
bool local_lease:1; /* check leases only on local system, not remote */
|
||||
|
@ -1246,6 +1247,17 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|||
if (vol->file_mode ==
|
||||
(S_IALLUGO & ~(S_ISUID | S_IXGRP)))
|
||||
vol->file_mode = S_IALLUGO;
|
||||
} else if (strnicmp(data, "forcemandatorylock", 9) == 0) {
|
||||
/* will take the shorter form "forcemand" as well */
|
||||
/* This mount option will force use of mandatory
|
||||
(DOS/Windows style) byte range locks, instead of
|
||||
using posix advisory byte range locks, even if the
|
||||
Unix extensions are available and posix locks would
|
||||
be supported otherwise. If Unix extensions are not
|
||||
negotiated this has no effect since mandatory locks
|
||||
would be used (mandatory locks is all that those
|
||||
those servers support) */
|
||||
vol->mand_lock = 1;
|
||||
} else if (strnicmp(data, "setuids", 7) == 0) {
|
||||
vol->setuids = 1;
|
||||
} else if (strnicmp(data, "nosetuids", 9) == 0) {
|
||||
|
@ -2150,6 +2162,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
|
|||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
|
||||
if (pvolume_info->nobrl)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
|
||||
if (pvolume_info->mand_lock)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
|
||||
if (pvolume_info->cifs_acl)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
|
||||
if (pvolume_info->override_uid)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue