diff options
| author | Pavel Shilovsky <piastry@etersoft.ru> | 2011-05-26 02:02:00 -0400 |
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2011-05-26 23:57:16 -0400 |
| commit | d4ffff1fa9695c5b5c0bf337e208d8833b88ff2d (patch) | |
| tree | acd4b6cfa7962a1cee7e9c81f11bd9ccb0d3ff24 | |
| parent | 25c7f41e9234f60af30e086278f1de7974f8816f (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/README | 3 | ||||
| -rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 8 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 1 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 5 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 17 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 4 | ||||
| -rw-r--r-- | fs/cifs/file.c | 82 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 11 | ||||
| -rw-r--r-- | fs/cifs/link.c | 22 |
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 | ||
| 45 | struct cifs_sb_info { | 46 | struct 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, | |||
| 345 | extern int CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, | 345 | extern int CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, |
| 346 | const int smb_file_id); | 346 | const int smb_file_id); |
| 347 | 347 | ||
| 348 | extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | 348 | extern 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); |
| 352 | extern int CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms, | 351 | extern 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 | ||
| 1384 | int | 1384 | int |
| 1385 | CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | 1385 | CIFSSMBRead(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 | |||
