Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Pavel Shilovsky and committed by
Steve French
d4ffff1f 25c7f41e

+115 -39
+3
fs/cifs/README
··· 457 457 otherwise - read from the server. All written data are stored 458 458 in the cache, but if the client doesn't have Exclusive Oplock, 459 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 463 acl Allow setfacl and getfacl to manage posix ACLs if server 461 464 supports them. (default) 462 465 noacl Do not allow setfacl and getfacl calls on this mount
+1
fs/cifs/cifs_fs_sb.h
··· 41 41 #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ 42 42 #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ 43 43 #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ 44 + #define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ 44 45 45 46 struct cifs_sb_info { 46 47 struct rb_root tlink_tree;
+8
fs/cifs/cifsfs.c
··· 415 415 seq_printf(s, ",nocase"); 416 416 if (tcon->retry) 417 417 seq_printf(s, ",hard"); 418 + if (tcon->unix_ext) 419 + seq_printf(s, ",unix"); 420 + else 421 + seq_printf(s, ",nounix"); 418 422 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) 419 423 seq_printf(s, ",posixpaths"); 420 424 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) 421 425 seq_printf(s, ",setuids"); 422 426 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) 423 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 432 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 425 433 seq_printf(s, ",directio"); 426 434 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+1
fs/cifs/cifsglob.h
··· 200 200 bool fsc:1; /* enable fscache */ 201 201 bool mfsymlinks:1; /* use Minshall+French Symlinks */ 202 202 bool multiuser:1; 203 + bool rwpidforward:1; /* pid forward for read/write operations */ 203 204 unsigned int rsize; 204 205 unsigned int wsize; 205 206 bool sockopt_tcp_nodelay:1;
+2 -3
fs/cifs/cifsproto.h
··· 345 345 extern int CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, 346 346 const int smb_file_id); 347 347 348 - extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 349 - const int netfid, unsigned int count, 350 - const __u64 lseek, unsigned int *nbytes, char **buf, 348 + extern int CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, 349 + unsigned int *nbytes, char **buf, 351 350 int *return_buf_type); 352 351 extern int CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms, 353 352 unsigned int *nbytes, const char *buf,
+12 -5
fs/cifs/cifssmb.c
··· 1382 1382 } 1383 1383 1384 1384 int 1385 - CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, 1386 - const unsigned int count, const __u64 lseek, unsigned int *nbytes, 1385 + CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, 1387 1386 char **buf, int *pbuf_type) 1388 1387 { 1389 1388 int rc = -EACCES; ··· 1392 1393 int wct; 1393 1394 int resp_buf_type = 0; 1394 1395 struct kvec iov[1]; 1396 + __u32 pid = io_parms->pid; 1397 + __u16 netfid = io_parms->netfid; 1398 + __u64 offset = io_parms->offset; 1399 + struct cifsTconInfo *tcon = io_parms->tcon; 1400 + unsigned int count = io_parms->length; 1395 1401 1396 1402 cFYI(1, "Reading %d bytes on fid %d", count, netfid); 1397 1403 if (tcon->ses->capabilities & CAP_LARGE_FILES) 1398 1404 wct = 12; 1399 1405 else { 1400 1406 wct = 10; /* old style read */ 1401 - if ((lseek >> 32) > 0) { 1407 + if ((offset >> 32) > 0) { 1402 1408 /* can not handle this big offset for old */ 1403 1409 return -EIO; 1404 1410 } ··· 1414 1410 if (rc) 1415 1411 return rc; 1416 1412 1413 + pSMB->hdr.Pid = cpu_to_le16((__u16)pid); 1414 + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16)); 1415 + 1417 1416 /* tcon and ses pointer are checked in smb_init */ 1418 1417 if (tcon->ses->server == NULL) 1419 1418 return -ECONNABORTED; 1420 1419 1421 1420 pSMB->AndXCommand = 0xFF; /* none */ 1422 1421 pSMB->Fid = netfid; 1423 - pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 1422 + pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1424 1423 if (wct == 12) 1425 - pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 1424 + pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1426 1425 1427 1426 pSMB->Remaining = 0; 1428 1427 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
+4
fs/cifs/connect.c
··· 1359 1359 vol->server_ino = 1; 1360 1360 } else if (strnicmp(data, "noserverino", 9) == 0) { 1361 1361 vol->server_ino = 0; 1362 + } else if (strnicmp(data, "rwpidforward", 4) == 0) { 1363 + vol->rwpidforward = 1; 1362 1364 } else if (strnicmp(data, "cifsacl", 7) == 0) { 1363 1365 vol->cifs_acl = 1; 1364 1366 } else if (strnicmp(data, "nocifsacl", 9) == 0) { ··· 2710 2708 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; 2711 2709 if (pvolume_info->mand_lock) 2712 2710 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; 2711 + if (pvolume_info->rwpidforward) 2712 + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD; 2713 2713 if (pvolume_info->cifs_acl) 2714 2714 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; 2715 2715 if (pvolume_info->override_uid)
+62 -20
fs/cifs/file.c
··· 725 725 else 726 726 posix_lock_type = CIFS_WRLCK; 727 727 rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */, 728 - length, pfLock, 729 - posix_lock_type, wait_flag); 728 + length, pfLock, posix_lock_type, 729 + wait_flag); 730 730 FreeXid(xid); 731 731 return rc; 732 732 } ··· 797 797 posix_lock_type = CIFS_UNLCK; 798 798 799 799 rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */, 800 - length, pfLock, 801 - posix_lock_type, wait_flag); 800 + length, pfLock, posix_lock_type, 801 + wait_flag); 802 802 } else { 803 803 struct cifsFileInfo *fid = file->private_data; 804 804 ··· 1346 1346 { 1347 1347 int rc; 1348 1348 struct inode *inode = mapping->host; 1349 + struct cifsFileInfo *cfile = file->private_data; 1350 + struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); 1351 + __u32 pid; 1352 + 1353 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 1354 + pid = cfile->pid; 1355 + else 1356 + pid = current->tgid; 1349 1357 1350 1358 cFYI(1, "write_end for page %p from pos %lld with %d bytes", 1351 1359 page, pos, copied); ··· 1377 1369 /* BB check if anything else missing out of ppw 1378 1370 such as updating last write time */ 1379 1371 page_data = kmap(page); 1380 - rc = cifs_write(file->private_data, current->tgid, 1381 - page_data + offset, copied, &pos); 1372 + rc = cifs_write(cfile, pid, page_data + offset, copied, &pos); 1382 1373 /* if (rc < 0) should we set writebehind rc? */ 1383 1374 kunmap(page); 1384 1375 ··· 1530 1523 struct cifs_sb_info *cifs_sb; 1531 1524 struct cifs_io_parms io_parms; 1532 1525 int xid, rc; 1526 + __u32 pid; 1533 1527 1534 1528 len = iov_length(iov, nr_segs); 1535 1529 if (!len) ··· 1562 1554 1563 1555 xid = GetXid(); 1564 1556 open_file = file->private_data; 1557 + 1558 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 1559 + pid = open_file->pid; 1560 + else 1561 + pid = current->tgid; 1562 + 1565 1563 pTcon = tlink_tcon(open_file->tlink); 1566 1564 inode = file->f_path.dentry->d_inode; 1567 1565 ··· 1595 1581 break; 1596 1582 } 1597 1583 io_parms.netfid = open_file->netfid; 1598 - io_parms.pid = current->tgid; 1584 + io_parms.pid = pid; 1599 1585 io_parms.tcon = pTcon; 1600 1586 io_parms.offset = *poffset; 1601 1587 io_parms.length = cur_len; ··· 1696 1682 struct cifsTconInfo *pTcon; 1697 1683 struct cifsFileInfo *open_file; 1698 1684 struct smb_com_read_rsp *pSMBr; 1685 + struct cifs_io_parms io_parms; 1699 1686 char *read_data; 1687 + __u32 pid; 1700 1688 1701 1689 if (!nr_segs) 1702 1690 return 0; ··· 1712 1696 1713 1697 open_file = file->private_data; 1714 1698 pTcon = tlink_tcon(open_file->tlink); 1699 + 1700 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 1701 + pid = open_file->pid; 1702 + else 1703 + pid = current->tgid; 1715 1704 1716 1705 if ((file->f_flags & O_ACCMODE) == O_WRONLY) 1717 1706 cFYI(1, "attempting read on write only file instance"); ··· 1733 1712 if (rc != 0) 1734 1713 break; 1735 1714 } 1736 - rc = CIFSSMBRead(xid, pTcon, open_file->netfid, 1737 - cur_len, *poffset, &bytes_read, 1715 + io_parms.netfid = open_file->netfid; 1716 + io_parms.pid = pid; 1717 + io_parms.tcon = pTcon; 1718 + io_parms.offset = *poffset; 1719 + io_parms.length = len; 1720 + rc = CIFSSMBRead(xid, &io_parms, &bytes_read, 1738 1721 &read_data, &buf_type); 1739 1722 pSMBr = (struct smb_com_read_rsp *)read_data; 1740 1723 if (read_data) { ··· 1819 1794 int xid; 1820 1795 char *current_offset; 1821 1796 struct cifsFileInfo *open_file; 1797 + struct cifs_io_parms io_parms; 1822 1798 int buf_type = CIFS_NO_BUFFER; 1799 + __u32 pid; 1823 1800 1824 1801 xid = GetXid(); 1825 1802 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); ··· 1833 1806 } 1834 1807 open_file = file->private_data; 1835 1808 pTcon = tlink_tcon(open_file->tlink); 1809 + 1810 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 1811 + pid = open_file->pid; 1812 + else 1813 + pid = current->tgid; 1836 1814 1837 1815 if ((file->f_flags & O_ACCMODE) == O_WRONLY) 1838 1816 cFYI(1, "attempting read on write only file instance"); ··· 1861 1829 if (rc != 0) 1862 1830 break; 1863 1831 } 1864 - rc = CIFSSMBRead(xid, pTcon, 1865 - open_file->netfid, 1866 - current_read_size, *poffset, 1867 - &bytes_read, &current_offset, 1868 - &buf_type); 1832 + io_parms.netfid = open_file->netfid; 1833 + io_parms.pid = pid; 1834 + io_parms.tcon = pTcon; 1835 + io_parms.offset = *poffset; 1836 + io_parms.length = current_read_size; 1837 + rc = CIFSSMBRead(xid, &io_parms, &bytes_read, 1838 + &current_offset, &buf_type); 1869 1839 } 1870 1840 if (rc || (bytes_read == 0)) { 1871 1841 if (total_read) { ··· 2004 1970 char *smb_read_data = NULL; 2005 1971 struct smb_com_read_rsp *pSMBr; 2006 1972 struct cifsFileInfo *open_file; 1973 + struct cifs_io_parms io_parms; 2007 1974 int buf_type = CIFS_NO_BUFFER; 1975 + __u32 pid; 2008 1976 2009 1977 xid = GetXid(); 2010 1978 if (file->private_data == NULL) { ··· 2028 1992 goto read_complete; 2029 1993 2030 1994 cFYI(DBG2, "rpages: num pages %d", num_pages); 1995 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 1996 + pid = open_file->pid; 1997 + else 1998 + pid = current->tgid; 1999 + 2031 2000 for (i = 0; i < num_pages; ) { 2032 2001 unsigned contig_pages; 2033 2002 struct page *tmp_page; ··· 2074 2033 if (rc != 0) 2075 2034 break; 2076 2035 } 2077 - 2078 - rc = CIFSSMBRead(xid, pTcon, 2079 - open_file->netfid, 2080 - read_size, offset, 2081 - &bytes_read, &smb_read_data, 2082 - &buf_type); 2036 + io_parms.netfid = open_file->netfid; 2037 + io_parms.pid = pid; 2038 + io_parms.tcon = pTcon; 2039 + io_parms.offset = offset; 2040 + io_parms.length = read_size; 2041 + rc = CIFSSMBRead(xid, &io_parms, &bytes_read, 2042 + &smb_read_data, &buf_type); 2083 2043 /* BB more RC checks ? */ 2084 2044 if (rc == -EAGAIN) { 2085 2045 if (smb_read_data) {
+8 -3
fs/cifs/inode.c
··· 374 374 __u16 netfid; 375 375 struct tcon_link *tlink; 376 376 struct cifsTconInfo *tcon; 377 + struct cifs_io_parms io_parms; 377 378 char buf[24]; 378 379 unsigned int bytes_read; 379 380 char *pbuf; ··· 406 405 if (rc == 0) { 407 406 int buf_type = CIFS_NO_BUFFER; 408 407 /* Read header */ 409 - rc = CIFSSMBRead(xid, tcon, netfid, 410 - 24 /* length */, 0 /* offset */, 411 - &bytes_read, &pbuf, &buf_type); 408 + io_parms.netfid = netfid; 409 + io_parms.pid = current->tgid; 410 + io_parms.tcon = tcon; 411 + io_parms.offset = 0; 412 + io_parms.length = 24; 413 + rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, 414 + &buf_type); 412 415 if ((rc == 0) && (bytes_read >= 8)) { 413 416 if (memcmp("IntxBLK", pbuf, 8) == 0) { 414 417 cFYI(1, "Block device");
+14 -8
fs/cifs/link.c
··· 235 235 unsigned int bytes_read = 0; 236 236 int buf_type = CIFS_NO_BUFFER; 237 237 unsigned int link_len = 0; 238 + struct cifs_io_parms io_parms; 238 239 FILE_ALL_INFO file_info; 239 240 240 241 rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ, ··· 254 253 if (!buf) 255 254 return -ENOMEM; 256 255 pbuf = buf; 256 + io_parms.netfid = netfid; 257 + io_parms.pid = current->tgid; 258 + io_parms.tcon = tcon; 259 + io_parms.offset = 0; 260 + io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; 257 261 258 - rc = CIFSSMBRead(xid, tcon, netfid, 259 - CIFS_MF_SYMLINK_FILE_SIZE /* length */, 260 - 0 /* offset */, 261 - &bytes_read, &pbuf, &buf_type); 262 + rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); 262 263 CIFSSMBClose(xid, tcon, netfid); 263 264 if (rc != 0) { 264 265 kfree(buf); ··· 299 296 __u16 netfid = 0; 300 297 struct tcon_link *tlink; 301 298 struct cifsTconInfo *pTcon; 299 + struct cifs_io_parms io_parms; 302 300 u8 *buf; 303 301 char *pbuf; 304 302 unsigned int bytes_read = 0; ··· 336 332 goto out; 337 333 } 338 334 pbuf = buf; 335 + io_parms.netfid = netfid; 336 + io_parms.pid = current->tgid; 337 + io_parms.tcon = pTcon; 338 + io_parms.offset = 0; 339 + io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; 339 340 340 - rc = CIFSSMBRead(xid, pTcon, netfid, 341 - CIFS_MF_SYMLINK_FILE_SIZE /* length */, 342 - 0 /* offset */, 343 - &bytes_read, &pbuf, &buf_type); 341 + rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); 344 342 CIFSSMBClose(xid, pTcon, netfid); 345 343 if (rc != 0) { 346 344 kfree(buf);