瀏覽代碼

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>
Pavel Shilovsky 14 年之前
父節點
當前提交
d4ffff1fa9
共有 10 個文件被更改,包括 115 次插入39 次删除
  1. 3 0
      fs/cifs/README
  2. 1 0
      fs/cifs/cifs_fs_sb.h
  3. 8 0
      fs/cifs/cifsfs.c
  4. 1 0
      fs/cifs/cifsglob.h
  5. 2 3
      fs/cifs/cifsproto.h
  6. 12 5
      fs/cifs/cifssmb.c
  7. 4 0
      fs/cifs/connect.c
  8. 62 20
      fs/cifs/file.c
  9. 8 3
      fs/cifs/inode.c
  10. 14 8
      fs/cifs/link.c

+ 3 - 0
fs/cifs/README

@@ -457,6 +457,9 @@ A partial list of the supported mount options follows:
 		otherwise - read from the server. All written data are stored
 		otherwise - read from the server. All written data are stored
 		in the cache, but if the client doesn't have Exclusive Oplock,
 		in the cache, but if the client doesn't have Exclusive Oplock,
 		it writes the data to the server.
 		it writes the data to the server.
+  rwpidforward  Forward pid of a process who opened a file to any read or write
+		operation on that file. This prevent applications like WINE
+		from failing on read and write if we use mandatory brlock style.
   acl   	Allow setfacl and getfacl to manage posix ACLs if server
   acl   	Allow setfacl and getfacl to manage posix ACLs if server
 		supports them.  (default)
 		supports them.  (default)
   noacl 	Do not allow setfacl and getfacl calls on this mount
   noacl 	Do not allow setfacl and getfacl calls on this mount

+ 1 - 0
fs/cifs/cifs_fs_sb.h

@@ -41,6 +41,7 @@
 #define CIFS_MOUNT_MF_SYMLINKS	0x10000 /* Minshall+French Symlinks enabled */
 #define CIFS_MOUNT_MF_SYMLINKS	0x10000 /* Minshall+French Symlinks enabled */
 #define CIFS_MOUNT_MULTIUSER	0x20000 /* multiuser mount */
 #define CIFS_MOUNT_MULTIUSER	0x20000 /* multiuser mount */
 #define CIFS_MOUNT_STRICT_IO	0x40000 /* strict cache mode */
 #define CIFS_MOUNT_STRICT_IO	0x40000 /* strict cache mode */
+#define CIFS_MOUNT_RWPIDFORWARD	0x80000 /* use pid forwarding for rw */
 
 
 struct cifs_sb_info {
 struct cifs_sb_info {
 	struct rb_root tlink_tree;
 	struct rb_root tlink_tree;

+ 8 - 0
fs/cifs/cifsfs.c

@@ -415,12 +415,20 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 		seq_printf(s, ",nocase");
 		seq_printf(s, ",nocase");
 	if (tcon->retry)
 	if (tcon->retry)
 		seq_printf(s, ",hard");
 		seq_printf(s, ",hard");
+	if (tcon->unix_ext)
+		seq_printf(s, ",unix");
+	else
+		seq_printf(s, ",nounix");
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
 		seq_printf(s, ",posixpaths");
 		seq_printf(s, ",posixpaths");
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
 		seq_printf(s, ",setuids");
 		seq_printf(s, ",setuids");
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
 		seq_printf(s, ",serverino");
 		seq_printf(s, ",serverino");
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+		seq_printf(s, ",rwpidforward");
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL)
+		seq_printf(s, ",forcemand");
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
 		seq_printf(s, ",directio");
 		seq_printf(s, ",directio");
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)

+ 1 - 0
fs/cifs/cifsglob.h

@@ -200,6 +200,7 @@ struct smb_vol {
 	bool fsc:1;	/* enable fscache */
 	bool fsc:1;	/* enable fscache */
 	bool mfsymlinks:1; /* use Minshall+French Symlinks */
 	bool mfsymlinks:1; /* use Minshall+French Symlinks */
 	bool multiuser:1;
 	bool multiuser:1;
+	bool rwpidforward:1; /* pid forward for read/write operations */
 	unsigned int rsize;
 	unsigned int rsize;
 	unsigned int wsize;
 	unsigned int wsize;
 	bool sockopt_tcp_nodelay:1;
 	bool sockopt_tcp_nodelay:1;

+ 2 - 3
fs/cifs/cifsproto.h

@@ -345,9 +345,8 @@ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
 extern int CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon,
 extern int CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon,
 			const int smb_file_id);
 			const int smb_file_id);
 
 
-extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
-			const int netfid, unsigned int count,
-			const __u64 lseek, unsigned int *nbytes, char **buf,
+extern int CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms,
+			unsigned int *nbytes, char **buf,
 			int *return_buf_type);
 			int *return_buf_type);
 extern int CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
 extern int CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
 			unsigned int *nbytes, const char *buf,
 			unsigned int *nbytes, const char *buf,

+ 12 - 5
fs/cifs/cifssmb.c

@@ -1382,8 +1382,7 @@ openRetry:
 }
 }
 
 
 int
 int
-CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
-	    const unsigned int count, const __u64 lseek, unsigned int *nbytes,
+CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
 	    char **buf, int *pbuf_type)
 	    char **buf, int *pbuf_type)
 {
 {
 	int rc = -EACCES;
 	int rc = -EACCES;
@@ -1393,13 +1392,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
 	int wct;
 	int wct;
 	int resp_buf_type = 0;
 	int resp_buf_type = 0;
 	struct kvec iov[1];
 	struct kvec iov[1];
+	__u32 pid = io_parms->pid;
+	__u16 netfid = io_parms->netfid;
+	__u64 offset = io_parms->offset;
+	struct cifsTconInfo *tcon = io_parms->tcon;
+	unsigned int count = io_parms->length;
 
 
 	cFYI(1, "Reading %d bytes on fid %d", count, netfid);
 	cFYI(1, "Reading %d bytes on fid %d", count, netfid);
 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
 		wct = 12;
 		wct = 12;
 	else {
 	else {
 		wct = 10; /* old style read */
 		wct = 10; /* old style read */
-		if ((lseek >> 32) > 0)  {
+		if ((offset >> 32) > 0)  {
 			/* can not handle this big offset for old */
 			/* can not handle this big offset for old */
 			return -EIO;
 			return -EIO;
 		}
 		}
@@ -1410,15 +1414,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
 	if (rc)
 	if (rc)
 		return rc;
 		return rc;
 
 
+	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
+	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
+
 	/* tcon and ses pointer are checked in smb_init */
 	/* tcon and ses pointer are checked in smb_init */
 	if (tcon->ses->server == NULL)
 	if (tcon->ses->server == NULL)
 		return -ECONNABORTED;
 		return -ECONNABORTED;
 
 
 	pSMB->AndXCommand = 0xFF;       /* none */
 	pSMB->AndXCommand = 0xFF;       /* none */
 	pSMB->Fid = netfid;
 	pSMB->Fid = netfid;
-	pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
+	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
 	if (wct == 12)
 	if (wct == 12)
-		pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
+		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
 
 
 	pSMB->Remaining = 0;
 	pSMB->Remaining = 0;
 	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
 	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);

+ 4 - 0
fs/cifs/connect.c

@@ -1359,6 +1359,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 			vol->server_ino = 1;
 			vol->server_ino = 1;
 		} else if (strnicmp(data, "noserverino", 9) == 0) {
 		} else if (strnicmp(data, "noserverino", 9) == 0) {
 			vol->server_ino = 0;
 			vol->server_ino = 0;
+		} else if (strnicmp(data, "rwpidforward", 4) == 0) {
+			vol->rwpidforward = 1;
 		} else if (strnicmp(data, "cifsacl", 7) == 0) {
 		} else if (strnicmp(data, "cifsacl", 7) == 0) {
 			vol->cifs_acl = 1;
 			vol->cifs_acl = 1;
 		} else if (strnicmp(data, "nocifsacl", 9) == 0) {
 		} else if (strnicmp(data, "nocifsacl", 9) == 0) {
@@ -2708,6 +2710,8 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
 	if (pvolume_info->mand_lock)
 	if (pvolume_info->mand_lock)
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
+	if (pvolume_info->rwpidforward)
+		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
 	if (pvolume_info->cifs_acl)
 	if (pvolume_info->cifs_acl)
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
 	if (pvolume_info->override_uid)
 	if (pvolume_info->override_uid)

+ 62 - 20
fs/cifs/file.c

@@ -725,8 +725,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
 			else
 			else
 				posix_lock_type = CIFS_WRLCK;
 				posix_lock_type = CIFS_WRLCK;
 			rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */,
 			rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */,
-					length,	pfLock,
-					posix_lock_type, wait_flag);
+					length, pfLock, posix_lock_type,
+					wait_flag);
 			FreeXid(xid);
 			FreeXid(xid);
 			return rc;
 			return rc;
 		}
 		}
@@ -797,8 +797,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
 			posix_lock_type = CIFS_UNLCK;
 			posix_lock_type = CIFS_UNLCK;
 
 
 		rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */,
 		rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */,
-				      length, pfLock,
-				      posix_lock_type, wait_flag);
+				      length, pfLock, posix_lock_type,
+				      wait_flag);
 	} else {
 	} else {
 		struct cifsFileInfo *fid = file->private_data;
 		struct cifsFileInfo *fid = file->private_data;
 
 
@@ -1346,6 +1346,14 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
 {
 {
 	int rc;
 	int rc;
 	struct inode *inode = mapping->host;
 	struct inode *inode = mapping->host;
+	struct cifsFileInfo *cfile = file->private_data;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
+	__u32 pid;
+
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+		pid = cfile->pid;
+	else
+		pid = current->tgid;
 
 
 	cFYI(1, "write_end for page %p from pos %lld with %d bytes",
 	cFYI(1, "write_end for page %p from pos %lld with %d bytes",
 		 page, pos, copied);
 		 page, pos, copied);
@@ -1369,8 +1377,7 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
 		/* BB check if anything else missing out of ppw
 		/* BB check if anything else missing out of ppw
 		   such as updating last write time */
 		   such as updating last write time */
 		page_data = kmap(page);
 		page_data = kmap(page);
-		rc = cifs_write(file->private_data, current->tgid,
-				page_data + offset, copied, &pos);
+		rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
 		/* if (rc < 0) should we set writebehind rc? */
 		/* if (rc < 0) should we set writebehind rc? */
 		kunmap(page);
 		kunmap(page);
 
 
@@ -1523,6 +1530,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
 	struct cifs_sb_info *cifs_sb;
 	struct cifs_sb_info *cifs_sb;
 	struct cifs_io_parms io_parms;
 	struct cifs_io_parms io_parms;
 	int xid, rc;
 	int xid, rc;
+	__u32 pid;
 
 
 	len = iov_length(iov, nr_segs);
 	len = iov_length(iov, nr_segs);
 	if (!len)
 	if (!len)
@@ -1554,6 +1562,12 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
 
 
 	xid = GetXid();
 	xid = GetXid();
 	open_file = file->private_data;
 	open_file = file->private_data;
+
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+		pid = open_file->pid;
+	else
+		pid = current->tgid;
+
 	pTcon = tlink_tcon(open_file->tlink);
 	pTcon = tlink_tcon(open_file->tlink);
 	inode = file->f_path.dentry->d_inode;
 	inode = file->f_path.dentry->d_inode;
 
 
@@ -1581,7 +1595,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
 					break;
 					break;
 			}
 			}
 			io_parms.netfid = open_file->netfid;
 			io_parms.netfid = open_file->netfid;
-			io_parms.pid = current->tgid;
+			io_parms.pid = pid;
 			io_parms.tcon = pTcon;
 			io_parms.tcon = pTcon;
 			io_parms.offset = *poffset;
 			io_parms.offset = *poffset;
 			io_parms.length = cur_len;
 			io_parms.length = cur_len;
@@ -1682,7 +1696,9 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
 	struct cifsTconInfo *pTcon;
 	struct cifsTconInfo *pTcon;
 	struct cifsFileInfo *open_file;
 	struct cifsFileInfo *open_file;
 	struct smb_com_read_rsp *pSMBr;
 	struct smb_com_read_rsp *pSMBr;
+	struct cifs_io_parms io_parms;
 	char *read_data;
 	char *read_data;
+	__u32 pid;
 
 
 	if (!nr_segs)
 	if (!nr_segs)
 		return 0;
 		return 0;
@@ -1697,6 +1713,11 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
 	open_file = file->private_data;
 	open_file = file->private_data;
 	pTcon = tlink_tcon(open_file->tlink);
 	pTcon = tlink_tcon(open_file->tlink);
 
 
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+		pid = open_file->pid;
+	else
+		pid = current->tgid;
+
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 		cFYI(1, "attempting read on write only file instance");
 		cFYI(1, "attempting read on write only file instance");
 
 
@@ -1712,8 +1733,12 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
 				if (rc != 0)
 				if (rc != 0)
 					break;
 					break;
 			}
 			}
-			rc = CIFSSMBRead(xid, pTcon, open_file->netfid,
-					 cur_len, *poffset, &bytes_read,
+			io_parms.netfid = open_file->netfid;
+			io_parms.pid = pid;
+			io_parms.tcon = pTcon;
+			io_parms.offset = *poffset;
+			io_parms.length = len;
+			rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
 					 &read_data, &buf_type);
 					 &read_data, &buf_type);
 			pSMBr = (struct smb_com_read_rsp *)read_data;
 			pSMBr = (struct smb_com_read_rsp *)read_data;
 			if (read_data) {
 			if (read_data) {
@@ -1794,7 +1819,9 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
 	int xid;
 	int xid;
 	char *current_offset;
 	char *current_offset;
 	struct cifsFileInfo *open_file;
 	struct cifsFileInfo *open_file;
+	struct cifs_io_parms io_parms;
 	int buf_type = CIFS_NO_BUFFER;
 	int buf_type = CIFS_NO_BUFFER;
+	__u32 pid;
 
 
 	xid = GetXid();
 	xid = GetXid();
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
@@ -1807,6 +1834,11 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
 	open_file = file->private_data;
 	open_file = file->private_data;
 	pTcon = tlink_tcon(open_file->tlink);
 	pTcon = tlink_tcon(open_file->tlink);
 
 
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+		pid = open_file->pid;
+	else
+		pid = current->tgid;
+
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 		cFYI(1, "attempting read on write only file instance");
 		cFYI(1, "attempting read on write only file instance");
 
 
@@ -1829,11 +1861,13 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
 				if (rc != 0)
 				if (rc != 0)
 					break;
 					break;
 			}
 			}
-			rc = CIFSSMBRead(xid, pTcon,
-					 open_file->netfid,
-					 current_read_size, *poffset,
-					 &bytes_read, &current_offset,
-					 &buf_type);
+			io_parms.netfid = open_file->netfid;
+			io_parms.pid = pid;
+			io_parms.tcon = pTcon;
+			io_parms.offset = *poffset;
+			io_parms.length = current_read_size;
+			rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
+					 &current_offset, &buf_type);
 		}
 		}
 		if (rc || (bytes_read == 0)) {
 		if (rc || (bytes_read == 0)) {
 			if (total_read) {
 			if (total_read) {
@@ -1970,7 +2004,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
 	char *smb_read_data = NULL;
 	char *smb_read_data = NULL;
 	struct smb_com_read_rsp *pSMBr;
 	struct smb_com_read_rsp *pSMBr;
 	struct cifsFileInfo *open_file;
 	struct cifsFileInfo *open_file;
+	struct cifs_io_parms io_parms;
 	int buf_type = CIFS_NO_BUFFER;
 	int buf_type = CIFS_NO_BUFFER;
+	__u32 pid;
 
 
 	xid = GetXid();
 	xid = GetXid();
 	if (file->private_data == NULL) {
 	if (file->private_data == NULL) {
@@ -1992,6 +2028,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
 		goto read_complete;
 		goto read_complete;
 
 
 	cFYI(DBG2, "rpages: num pages %d", num_pages);
 	cFYI(DBG2, "rpages: num pages %d", num_pages);
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+		pid = open_file->pid;
+	else
+		pid = current->tgid;
+
 	for (i = 0; i < num_pages; ) {
 	for (i = 0; i < num_pages; ) {
 		unsigned contig_pages;
 		unsigned contig_pages;
 		struct page *tmp_page;
 		struct page *tmp_page;
@@ -2033,12 +2074,13 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
 				if (rc != 0)
 				if (rc != 0)
 					break;
 					break;
 			}
 			}
-
-			rc = CIFSSMBRead(xid, pTcon,
-					 open_file->netfid,
-					 read_size, offset,
-					 &bytes_read, &smb_read_data,
-					 &buf_type);
+			io_parms.netfid = open_file->netfid;
+			io_parms.pid = pid;
+			io_parms.tcon = pTcon;
+			io_parms.offset = offset;
+			io_parms.length = read_size;
+			rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
+					 &smb_read_data, &buf_type);
 			/* BB more RC checks ? */
 			/* BB more RC checks ? */
 			if (rc == -EAGAIN) {
 			if (rc == -EAGAIN) {
 				if (smb_read_data) {
 				if (smb_read_data) {

+ 8 - 3
fs/cifs/inode.c

@@ -374,6 +374,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
 	__u16 netfid;
 	__u16 netfid;
 	struct tcon_link *tlink;
 	struct tcon_link *tlink;
 	struct cifsTconInfo *tcon;
 	struct cifsTconInfo *tcon;
+	struct cifs_io_parms io_parms;
 	char buf[24];
 	char buf[24];
 	unsigned int bytes_read;
 	unsigned int bytes_read;
 	char *pbuf;
 	char *pbuf;
@@ -405,9 +406,13 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
 	if (rc == 0) {
 	if (rc == 0) {
 		int buf_type = CIFS_NO_BUFFER;
 		int buf_type = CIFS_NO_BUFFER;
 			/* Read header */
 			/* Read header */
-		rc = CIFSSMBRead(xid, tcon, netfid,
-				 24 /* length */, 0 /* offset */,
-				 &bytes_read, &pbuf, &buf_type);
+		io_parms.netfid = netfid;
+		io_parms.pid = current->tgid;
+		io_parms.tcon = tcon;
+		io_parms.offset = 0;
+		io_parms.length = 24;
+		rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
+				 &buf_type);
 		if ((rc == 0) && (bytes_read >= 8)) {
 		if ((rc == 0) && (bytes_read >= 8)) {
 			if (memcmp("IntxBLK", pbuf, 8) == 0) {
 			if (memcmp("IntxBLK", pbuf, 8) == 0) {
 				cFYI(1, "Block device");
 				cFYI(1, "Block device");

+ 14 - 8
fs/cifs/link.c

@@ -235,6 +235,7 @@ CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
 	unsigned int bytes_read = 0;
 	unsigned int bytes_read = 0;
 	int buf_type = CIFS_NO_BUFFER;
 	int buf_type = CIFS_NO_BUFFER;
 	unsigned int link_len = 0;
 	unsigned int link_len = 0;
+	struct cifs_io_parms io_parms;
 	FILE_ALL_INFO file_info;
 	FILE_ALL_INFO file_info;
 
 
 	rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
 	rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
@@ -253,11 +254,13 @@ CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
 	if (!buf)
 	if (!buf)
 		return -ENOMEM;
 		return -ENOMEM;
 	pbuf = buf;
 	pbuf = buf;
+	io_parms.netfid = netfid;
+	io_parms.pid = current->tgid;
+	io_parms.tcon = tcon;
+	io_parms.offset = 0;
+	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
 
 
-	rc = CIFSSMBRead(xid, tcon, netfid,
-			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
-			 0 /* offset */,
-			 &bytes_read, &pbuf, &buf_type);
+	rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
 	CIFSSMBClose(xid, tcon, netfid);
 	CIFSSMBClose(xid, tcon, netfid);
 	if (rc != 0) {
 	if (rc != 0) {
 		kfree(buf);
 		kfree(buf);
@@ -296,6 +299,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
 	__u16 netfid = 0;
 	__u16 netfid = 0;
 	struct tcon_link *tlink;
 	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct cifsTconInfo *pTcon;
+	struct cifs_io_parms io_parms;
 	u8 *buf;
 	u8 *buf;
 	char *pbuf;
 	char *pbuf;
 	unsigned int bytes_read = 0;
 	unsigned int bytes_read = 0;
@@ -332,11 +336,13 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
 		goto out;
 		goto out;
 	}
 	}
 	pbuf = buf;
 	pbuf = buf;
+	io_parms.netfid = netfid;
+	io_parms.pid = current->tgid;
+	io_parms.tcon = pTcon;
+	io_parms.offset = 0;
+	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
 
 
-	rc = CIFSSMBRead(xid, pTcon, netfid,
-			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
-			 0 /* offset */,
-			 &bytes_read, &pbuf, &buf_type);
+	rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
 	CIFSSMBClose(xid, pTcon, netfid);
 	CIFSSMBClose(xid, pTcon, netfid);
 	if (rc != 0) {
 	if (rc != 0) {
 		kfree(buf);
 		kfree(buf);