aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Shilovsky <piastry@etersoft.ru>2011-05-26 02:02:00 -0400
committerSteve French <sfrench@us.ibm.com>2011-05-26 23:57:16 -0400
commitd4ffff1fa9695c5b5c0bf337e208d8833b88ff2d (patch)
treeacd4b6cfa7962a1cee7e9c81f11bd9ccb0d3ff24
parent25c7f41e9234f60af30e086278f1de7974f8816f (diff)
CIFS: Add rwpidforward mount option
Add rwpidforward mount option that switches on a mode when we forward pid of a process who opened a file to any read and write operation. This can prevent applications like WINE from failing on read or write operation on a previously locked file region from the same netfd from another process if we use mandatory brlock style. It is actual for WINE because during a run of WINE program two processes work on the same netfd - share the same file struct between several VFS fds: 1) WINE-server does open and lock; 2) WINE-application does read and write. Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/README3
-rw-r--r--fs/cifs/cifs_fs_sb.h1
-rw-r--r--fs/cifs/cifsfs.c8
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/cifsproto.h5
-rw-r--r--fs/cifs/cifssmb.c17
-rw-r--r--fs/cifs/connect.c4
-rw-r--r--fs/cifs/file.c82
-rw-r--r--fs/cifs/inode.c11
-rw-r--r--fs/cifs/link.c22
10 files changed, 115 insertions, 39 deletions
diff --git a/fs/cifs/README b/fs/cifs/README
index 4a3ca0e5ca24..c5c2c5e5f0f2 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -457,6 +457,9 @@ A partial list of the supported mount options follows:
457 otherwise - read from the server. All written data are stored 457 otherwise - read from the server. All written data are stored
458 in the cache, but if the client doesn't have Exclusive Oplock, 458 in the cache, but if the client doesn't have Exclusive Oplock,
459 it writes the data to the server. 459 it writes the data to the server.
460 rwpidforward Forward pid of a process who opened a file to any read or write
461 operation on that file. This prevent applications like WINE
462 from failing on read and write if we use mandatory brlock style.
460 acl Allow setfacl and getfacl to manage posix ACLs if server 463 acl Allow setfacl and getfacl to manage posix ACLs if server
461 supports them. (default) 464 supports them. (default)
462 noacl Do not allow setfacl and getfacl calls on this mount 465 noacl Do not allow setfacl and getfacl calls on this mount
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index c96b44b4e262..ffb1459dc6ec 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -41,6 +41,7 @@
41#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ 41#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */
42#define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ 42#define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */
43#define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ 43#define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */
44#define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */
44 45
45struct cifs_sb_info { 46struct cifs_sb_info {
46 struct rb_root tlink_tree; 47 struct rb_root tlink_tree;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 360fe2ec2a19..26981bf2cf3f 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -415,12 +415,20 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
415 seq_printf(s, ",nocase"); 415 seq_printf(s, ",nocase");
416 if (tcon->retry) 416 if (tcon->retry)
417 seq_printf(s, ",hard"); 417 seq_printf(s, ",hard");
418 if (tcon->unix_ext)
419 seq_printf(s, ",unix");
420 else
421 seq_printf(s, ",nounix");
418 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) 422 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
419 seq_printf(s, ",posixpaths"); 423 seq_printf(s, ",posixpaths");
420 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) 424 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
421 seq_printf(s, ",setuids"); 425 seq_printf(s, ",setuids");
422 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) 426 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
423 seq_printf(s, ",serverino"); 427 seq_printf(s, ",serverino");
428 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
429 seq_printf(s, ",rwpidforward");
430 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL)
431 seq_printf(s, ",forcemand");
424 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 432 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
425 seq_printf(s, ",directio"); 433 seq_printf(s, ",directio");
426 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 434 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index ca0c3789206e..310cddabd3fd 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -200,6 +200,7 @@ struct smb_vol {
200 bool fsc:1; /* enable fscache */ 200 bool fsc:1; /* enable fscache */
201 bool mfsymlinks:1; /* use Minshall+French Symlinks */ 201 bool mfsymlinks:1; /* use Minshall+French Symlinks */
202 bool multiuser:1; 202 bool multiuser:1;
203 bool rwpidforward:1; /* pid forward for read/write operations */
203 unsigned int rsize; 204 unsigned int rsize;
204 unsigned int wsize; 205 unsigned int wsize;
205 bool sockopt_tcp_nodelay:1; 206 bool sockopt_tcp_nodelay:1;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index e41f6071cdd2..17063455918f 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -345,9 +345,8 @@ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
345extern int CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, 345extern int CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon,
346 const int smb_file_id); 346 const int smb_file_id);
347 347
348extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 348extern int CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms,
349 const int netfid, unsigned int count, 349 unsigned int *nbytes, char **buf,
350 const __u64 lseek, unsigned int *nbytes, char **buf,
351 int *return_buf_type); 350 int *return_buf_type);
352extern int CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms, 351extern int CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
353 unsigned int *nbytes, const char *buf, 352 unsigned int *nbytes, const char *buf,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f39fa08b9b0e..19fd8158bb47 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1382,8 +1382,7 @@ openRetry:
1382} 1382}
1383 1383
1384int 1384int
1385CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, 1385CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
1386 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1387 char **buf, int *pbuf_type) 1386 char **buf, int *pbuf_type)
1388{ 1387{
1389 int rc = -EACCES; 1388 int rc = -EACCES;
@@ -1393,13 +1392,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1393 int wct; 1392 int wct;
1394 int resp_buf_type = 0; 1393 int resp_buf_type = 0;
1395 struct kvec iov[1]; 1394 struct kvec iov[1];
1395 __u32 pid = io_parms->pid;
1396 __u16 netfid = io_parms->netfid;
1397 __u64 offset = io_parms->offset;
1398 struct cifsTconInfo *tcon = io_parms->tcon;
1399 unsigned int count = io_parms->length;
1396 1400
1397 cFYI(1, "Reading %d bytes on fid %d", count, netfid); 1401 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1398 if (tcon->ses->capabilities & CAP_LARGE_FILES) 1402 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1399 wct = 12; 1403 wct = 12;
1400 else { 1404 else {
1401 wct = 10; /* old style read */ 1405 wct = 10; /* old style read */
1402 if ((lseek >> 32) > 0) { 1406 if ((offset >> 32) > 0) {
1403 /* can not handle this big offset for old */ 1407 /* can not handle this big offset for old */
1404 return -EIO; 1408 return -EIO;
1405 } 1409 }
@@ -1410,15 +1414,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1410 if (rc) 1414 if (rc)
1411 return rc; 1415 return rc;
1412 1416
1417 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1418 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1419
1413 /* tcon and ses pointer are checked in smb_init */ 1420 /* tcon and ses pointer are checked in smb_init */
1414 if (tcon->ses->server == NULL) 1421 if (tcon->ses->server == NULL)
1415 return -ECONNABORTED; 1422 return -ECONNABORTED;
1416 1423
1417 pSMB->AndXCommand = 0xFF; /* none */ 1424 pSMB->AndXCommand = 0xFF; /* none */
1418 pSMB->Fid = netfid; 1425 pSMB->Fid = netfid;
1419 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 1426 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1420 if (wct == 12) 1427 if (wct == 12)
1421 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 1428 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1422 1429
1423 pSMB->Remaining = 0; 1430 pSMB->Remaining = 0;
1424 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); 1431 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 261ca81d5e49..21bc83586beb 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1359,6 +1359,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1359 vol->server_ino = 1; 1359 vol->server_ino = 1;
1360 } else if (strnicmp(data, "noserverino", 9) == 0) { 1360 } else if (strnicmp(data, "noserverino", 9) == 0) {
1361 vol->server_ino = 0; 1361 vol->server_ino = 0;
1362 } else if (strnicmp(data, "rwpidforward", 4) == 0) {
1363 vol->rwpidforward = 1;
1362 } else if (strnicmp(data, "cifsacl", 7) == 0) { 1364 } else if (strnicmp(data, "cifsacl", 7) == 0) {
1363 vol->cifs_acl = 1; 1365 vol->cifs_acl = 1;
1364 } else if (strnicmp(data, "nocifsacl", 9) == 0) { 1366 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
@@ -2708,6 +2710,8 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
2708 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; 2710 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
2709 if (pvolume_info->mand_lock) 2711 if (pvolume_info->mand_lock)
2710 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; 2712 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
2713 if (pvolume_info->rwpidforward)
2714 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
2711 if (pvolume_info->cifs_acl) 2715 if (pvolume_info->cifs_acl)
2712 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; 2716 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2713 if (pvolume_info->override_uid) 2717 if (pvolume_info->override_uid)
diff --git a/fs/cifs/fi