Message ID | 1302190937-7274-1-git-send-email-piastry@etersoft.ru (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, 7 Apr 2011 19:42:17 +0400 Pavel Shilovsky <piastry@etersoft.ru> wrote: > Add wine mount option that switches on WINE-capability mode - forward > pid of a process who opened a file to any read and write operation > even if the file descriptor was inherited by another process. > > Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> What problem does this solve? Why should we do this? If it's a reasonable thing to do, perhaps we needn't use a mount option for this and can turn it on unconditionally. To my knowledge the pid isn't really used much by the server, is it? I suppose it could if there were FID conflicts, but does that ever happen? > --- > fs/cifs/cifs_fs_sb.h | 1 + > fs/cifs/cifsfs.c | 8 ++++++ > fs/cifs/cifsproto.h | 21 ++++++++------- > fs/cifs/cifssmb.c | 31 +++++++++++++++------- > fs/cifs/connect.c | 7 +++++ > fs/cifs/dir.c | 4 +- > fs/cifs/file.c | 69 ++++++++++++++++++++++++++++++++++++++----------- > fs/cifs/inode.c | 10 ++++--- > fs/cifs/link.c | 6 ++-- > 9 files changed, 112 insertions(+), 45 deletions(-) > > diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h > index 1ef54ab..7a24eb3 100644 > --- a/fs/cifs/cifs_fs_sb.h > +++ b/fs/cifs/cifs_fs_sb.h > @@ -43,6 +43,7 @@ > #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ > #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ > #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ > +#define CIFS_MOUNT_WINE_MODE 0x80000 /* use pid forwarding for wine apps */ > > struct cifs_sb_info { > struct rb_root tlink_tree; > diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c > index fb6a2ad..f4ec759 100644 > --- a/fs/cifs/cifsfs.c > +++ b/fs/cifs/cifsfs.c > @@ -460,6 +460,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) > seq_printf(s, ",nocase"); > if (tcon->retry) > seq_printf(s, ",hard"); > + if (tcon->unix_ext) > + seq_printf(s, ",unix"); > + else > + seq_printf(s, ",nounix"); > if (cifs_sb->prepath) > seq_printf(s, ",prepath=%s", cifs_sb->prepath); > if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) > @@ -468,6 +472,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) > seq_printf(s, ",setuids"); > if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) > seq_printf(s, ",serverino"); > + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) > + seq_printf(s, ",wine"); > + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) > + seq_printf(s, ",forcemand"); > if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) > seq_printf(s, ",directio"); > if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) > diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h > index 76c4dc7..28e975c 100644 > --- a/fs/cifs/cifsproto.h > +++ b/fs/cifs/cifsproto.h > @@ -335,18 +335,19 @@ extern int CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, > const int smb_file_id); > > extern int CIFSSMBRead(const int xid, struct cifs_tcon *tcon, > - const int netfid, unsigned int count, > - const __u64 lseek, unsigned int *nbytes, char **buf, > - int *return_buf_type); > + const int netfid, const __u32 netpid, > + unsigned int count, const __u64 lseek, > + unsigned int *nbytes, char **buf, int *return_buf_type); > extern int CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, > - const int netfid, const unsigned int count, > - const __u64 lseek, unsigned int *nbytes, > - const char *buf, const char __user *ubuf, > - const int long_op); > + const int netfid, const __u32 netpid, > + const unsigned int count, const __u64 lseek, > + unsigned int *nbytes, const char *buf, > + const char __user *ubuf, const int long_op); > extern int CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, > - const int netfid, const unsigned int count, > - const __u64 offset, unsigned int *nbytes, > - struct kvec *iov, const int nvec, const int long_op); > + const int netfid, const __u32 netpid, > + const unsigned int count, const __u64 offset, > + unsigned int *nbytes, struct kvec *iov, const int nvec, > + const int long_op); > extern int CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon, > const unsigned char *searchName, __u64 *inode_number, > const struct nls_table *nls_codepage, > diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c > index 3291770..890897c 100644 > --- a/fs/cifs/cifssmb.c > +++ b/fs/cifs/cifssmb.c > @@ -1380,8 +1380,8 @@ openRetry: > > int > CIFSSMBRead(const int xid, struct cifs_tcon *tcon, const int netfid, > - const unsigned int count, const __u64 lseek, unsigned int *nbytes, > - char **buf, int *pbuf_type) > + const __u32 netpid, const unsigned int count, const __u64 lseek, > + unsigned int *nbytes, char **buf, int *pbuf_type) > { > int rc = -EACCES; > READ_REQ *pSMB = NULL; > @@ -1407,6 +1407,9 @@ CIFSSMBRead(const int xid, struct cifs_tcon *tcon, const int netfid, > if (rc) > return rc; > > + pSMB->hdr.Pid = cpu_to_le16((__u16)netpid); > + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(netpid >> 16)); > + > /* tcon and ses pointer are checked in smb_init */ > if (tcon->ses->server == NULL) > return -ECONNABORTED; > @@ -1484,10 +1487,10 @@ CIFSSMBRead(const int xid, struct cifs_tcon *tcon, const int netfid, > > > int > -CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, > - const int netfid, const unsigned int count, > - const __u64 offset, unsigned int *nbytes, const char *buf, > - const char __user *ubuf, const int long_op) > +CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, const int netfid, > + const __u32 netpid, const unsigned int count, const __u64 offset, > + unsigned int *nbytes, const char *buf, const char __user *ubuf, > + const int long_op) > { > int rc = -EACCES; > WRITE_REQ *pSMB = NULL; > @@ -1516,6 +1519,10 @@ CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, > (void **) &pSMBr); > if (rc) > return rc; > + > + pSMB->hdr.Pid = cpu_to_le16((__u16)netpid); > + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(netpid >> 16)); > + > /* tcon and ses pointer are checked in smb_init */ > if (tcon->ses->server == NULL) > return -ECONNABORTED; > @@ -1603,10 +1610,10 @@ CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, > } > > int > -CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, > - const int netfid, const unsigned int count, > - const __u64 offset, unsigned int *nbytes, struct kvec *iov, > - int n_vec, const int long_op) > +CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, const int netfid, > + const __u32 netpid, const unsigned int count, const __u64 offset, > + unsigned int *nbytes, struct kvec *iov, int n_vec, > + const int long_op) > { > int rc = -EACCES; > WRITE_REQ *pSMB = NULL; > @@ -1630,6 +1637,10 @@ CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, > rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB); > if (rc) > return rc; > + > + pSMB->hdr.Pid = cpu_to_le16((__u16)netpid); > + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(netpid >> 16)); > + > /* tcon and ses pointer are checked in smb_init */ > if (tcon->ses->server == NULL) > return -ECONNABORTED; > diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > index 94e60c5..c540028 100644 > --- a/fs/cifs/connect.c > +++ b/fs/cifs/connect.c > @@ -103,6 +103,7 @@ struct smb_vol { > bool noautotune:1; > bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ > bool fsc:1; /* enable fscache */ > + bool wine_mode:1; > bool mfsymlinks:1; /* use Minshall+French Symlinks */ > bool multiuser:1; > bool use_smb2:1; /* force smb2 use on mount instead of cifs */ > @@ -1362,6 +1363,10 @@ cifs_parse_mount_options(char *options, const char *devname, > vol->server_ino = 1; > } else if (strnicmp(data, "noserverino", 9) == 0) { > vol->server_ino = 0; > + } else if (strnicmp(data, "wine", 4) == 0) { > + vol->wine_mode = 1; > + vol->mand_lock = 1; > + vol->strict_io = 1; ^^^^^^^^^^^^^^^ This seems to do a lot more than what your description suggests. > } else if (strnicmp(data, "cifsacl", 7) == 0) { > vol->cifs_acl = 1; > } else if (strnicmp(data, "nocifsacl", 9) == 0) { > @@ -2643,6 +2648,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, > cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; > if (pvolume_info->mand_lock) > cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; > + if (pvolume_info->wine_mode) > + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_WINE_MODE; > if (pvolume_info->cifs_acl) > cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; > if (pvolume_info->override_uid) > diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c > index ab74179..6cdac98 100644 > --- a/fs/cifs/dir.c > +++ b/fs/cifs/dir.c > @@ -446,7 +446,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, > pdev->minor = > cpu_to_le64(MINOR(device_number)); > rc = CIFSSMBWrite(xid, pTcon, > - fileHandle, > + fileHandle, current->tgid, > sizeof(struct win_dev), > 0, &bytes_written, (char *)pdev, > NULL, 0); > @@ -457,7 +457,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, > pdev->minor = > cpu_to_le64(MINOR(device_number)); > rc = CIFSSMBWrite(xid, pTcon, > - fileHandle, > + fileHandle, current->tgid, > sizeof(struct win_dev), > 0, &bytes_written, (char *)pdev, > NULL, 0); > diff --git a/fs/cifs/file.c b/fs/cifs/file.c > index 9c7f83f..635806f 100644 > --- a/fs/cifs/file.c > +++ b/fs/cifs/file.c > @@ -725,8 +725,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) > else > posix_lock_type = CIFS_WRLCK; > rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */, > - length, pfLock, > - posix_lock_type, wait_flag); > + length, pfLock, posix_lock_type, > + wait_flag); > FreeXid(xid); > return rc; > } > @@ -797,8 +797,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) > posix_lock_type = CIFS_UNLCK; > > rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */, > - length, pfLock, > - posix_lock_type, wait_flag); > + length, pfLock, posix_lock_type, > + wait_flag); > } else { > struct cifsFileInfo *fid = file->private_data; > > @@ -866,6 +866,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, > unsigned int total_written; > struct cifs_sb_info *cifs_sb; > struct cifs_tcon *pTcon; > + __u32 netpid; > int xid; > struct dentry *dentry = open_file->dentry; > struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); > @@ -877,6 +878,11 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, > > pTcon = tlink_tcon(open_file->tlink); > > + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) > + netpid = open_file->pid; > + else > + netpid = current->tgid; > + > xid = GetXid(); > > for (total_written = 0; write_size > total_written; > @@ -901,8 +907,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, > /* iov[0] is reserved for smb header */ > iov[1].iov_base = (char *)write_data + total_written; > iov[1].iov_len = len; > - rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, len, > - *poffset, &bytes_written, iov, 1, 0); > + rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, > + netpid, len, *poffset, > + &bytes_written, iov, 1, 0); > } > if (rc || (bytes_written == 0)) { > if (total_written) > @@ -1112,6 +1119,7 @@ static int cifs_writepages(struct address_space *mapping, > struct pagevec pvec; > int rc = 0; > int scanned = 0; > + __u32 netpid; > int xid; > > cifs_sb = CIFS_SB(mapping->host->i_sb); > @@ -1251,10 +1259,15 @@ retry_write: > cERROR(1, "No writable handles for inode"); > rc = -EBADF; > } else { > + if (cifs_sb->mnt_cifs_flags & > + CIFS_MOUNT_WINE_MODE) > + netpid = open_file->pid; > + else > + netpid = current->tgid; > rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, > - bytes_to_write, offset, > - &bytes_written, iov, n_iov, > - 0); > + netpid, bytes_to_write, > + offset, &bytes_written, > + iov, n_iov, 0); > cifsFileInfo_put(open_file); > } > > @@ -1567,6 +1580,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, > struct cifs_tcon *pTcon; > struct cifs_sb_info *cifs_sb; > int xid, rc; > + __u32 netpid; > > len = iov_length(iov, nr_segs); > if (!len) > @@ -1598,6 +1612,12 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, > > xid = GetXid(); > open_file = file->private_data; > + > + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) > + netpid = open_file->pid; > + else > + netpid = current->tgid; > + > pTcon = tlink_tcon(open_file->tlink); > inode = file->f_path.dentry->d_inode; > > @@ -1625,7 +1645,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, > break; > } > rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, > - cur_len, *poffset, &written, > + netpid, cur_len, *poffset, &written, > to_send, npages, 0); > } while (rc == -EAGAIN); > > @@ -1723,6 +1743,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, > struct cifsFileInfo *open_file; > struct smb_com_read_rsp *pSMBr; > char *read_data; > + __u32 netpid; > > if (!nr_segs) > return 0; > @@ -1737,6 +1758,11 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, > open_file = file->private_data; > pTcon = tlink_tcon(open_file->tlink); > > + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) > + netpid = open_file->pid; > + else > + netpid = current->tgid; > + > if ((file->f_flags & O_ACCMODE) == O_WRONLY) > cFYI(1, "attempting read on write only file instance"); > > @@ -1753,7 +1779,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, > break; > } > rc = CIFSSMBRead(xid, pTcon, open_file->netfid, > - cur_len, *poffset, &bytes_read, > + netpid, cur_len, *poffset, &bytes_read, > &read_data, &buf_type); > pSMBr = (struct smb_com_read_rsp *)read_data; > if (read_data) { > @@ -1835,6 +1861,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, > char *current_offset; > struct cifsFileInfo *open_file; > int buf_type = CIFS_NO_BUFFER; > + __u32 netpid; > > xid = GetXid(); > cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); > @@ -1847,6 +1874,11 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, > open_file = file->private_data; > pTcon = tlink_tcon(open_file->tlink); > > + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) > + netpid = open_file->pid; > + else > + netpid = current->tgid; > + > if ((file->f_flags & O_ACCMODE) == O_WRONLY) > cFYI(1, "attempting read on write only file instance"); > > @@ -1870,7 +1902,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, > break; > } > rc = CIFSSMBRead(xid, pTcon, > - open_file->netfid, > + open_file->netfid, netpid, > current_read_size, *poffset, > &bytes_read, ¤t_offset, > &buf_type); > @@ -2008,6 +2040,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, > struct smb_com_read_rsp *pSMBr; > struct cifsFileInfo *open_file; > int buf_type = CIFS_NO_BUFFER; > + __u32 netpid; > > xid = GetXid(); > if (file->private_data == NULL) { > @@ -2029,6 +2062,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, > goto read_complete; > > cFYI(DBG2, "rpages: num pages %d", num_pages); > + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) > + netpid = open_file->pid; > + else > + netpid = current->tgid; > + > for (i = 0; i < num_pages; ) { > unsigned contig_pages; > struct page *tmp_page; > @@ -2072,10 +2110,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, > } > > rc = CIFSSMBRead(xid, pTcon, > - open_file->netfid, > - read_size, offset, > - &bytes_read, &smb_read_data, > - &buf_type); > + open_file->netfid, netpid, > + read_size, offset, &bytes_read, > + &smb_read_data, &buf_type); > /* BB more RC checks ? */ > if (rc == -EAGAIN) { > if (smb_read_data) { > diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c > index adb6324..bafeae6 100644 > --- a/fs/cifs/inode.c > +++ b/fs/cifs/inode.c > @@ -405,7 +405,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, > if (rc == 0) { > int buf_type = CIFS_NO_BUFFER; > /* Read header */ > - rc = CIFSSMBRead(xid, tcon, netfid, > + rc = CIFSSMBRead(xid, tcon, netfid, current->tgid, > 24 /* length */, 0 /* offset */, > &bytes_read, &pbuf, &buf_type); > if ((rc == 0) && (bytes_read >= 8)) { > @@ -1859,8 +1859,9 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, > cFYI(1, "SetFSize for attrs rc = %d", rc); > if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { > unsigned int bytes_written; > - rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, > - &bytes_written, NULL, NULL, 1); > + rc = CIFSSMBWrite(xid, pTcon, nfid, npid, > + 0, attrs->ia_size, &bytes_written, > + NULL, NULL, 1); > cFYI(1, "Wrt seteof rc %d", rc); > } > } else > @@ -1895,7 +1896,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, > CIFS_MOUNT_MAP_SPECIAL_CHR); > if (rc == 0) { > unsigned int bytes_written; > - rc = CIFSSMBWrite(xid, pTcon, netfid, 0, > + rc = CIFSSMBWrite(xid, pTcon, netfid, > + current->tgid, 0, > attrs->ia_size, > &bytes_written, NULL, > NULL, 1); > diff --git a/fs/cifs/link.c b/fs/cifs/link.c > index 3a097b6..7536104 100644 > --- a/fs/cifs/link.c > +++ b/fs/cifs/link.c > @@ -203,7 +203,7 @@ CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon, > return rc; > } > > - rc = CIFSSMBWrite(xid, tcon, netfid, > + rc = CIFSSMBWrite(xid, tcon, netfid, current->tgid, > CIFS_MF_SYMLINK_FILE_SIZE /* length */, > 0 /* offset */, > &bytes_written, buf, NULL, 0); > @@ -250,7 +250,7 @@ CIFSQueryMFSymLink(const int xid, struct cifs_tcon *tcon, > return -ENOMEM; > pbuf = buf; > > - rc = CIFSSMBRead(xid, tcon, netfid, > + rc = CIFSSMBRead(xid, tcon, netfid, current->tgid, > CIFS_MF_SYMLINK_FILE_SIZE /* length */, > 0 /* offset */, > &bytes_read, &pbuf, &buf_type); > @@ -329,7 +329,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, > } > pbuf = buf; > > - rc = CIFSSMBRead(xid, pTcon, netfid, > + rc = CIFSSMBRead(xid, pTcon, netfid, current->tgid, > CIFS_MF_SYMLINK_FILE_SIZE /* length */, > 0 /* offset */, > &bytes_read, &pbuf, &buf_type);
2011/4/8 Jeff Layton <jlayton@poochiereds.net>: > On Thu, 7 Apr 2011 19:42:17 +0400 > Pavel Shilovsky <piastry@etersoft.ru> wrote: > >> Add wine mount option that switches on WINE-capability mode - forward >> pid of a process who opened a file to any read and write operation >> even if the file descriptor was inherited by another process. >> >> Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> > > What problem does this solve? Why should we do this? If it's a > reasonable thing to do, perhaps we needn't use a mount option for this > and can turn it on unconditionally. To my knowledge the pid isn't > really used much by the server, is it? I suppose it could if there were > FID conflicts, but does that ever happen? Sorry for being unclear in the description. In WINE there are wine-server and wine-application. The first opens files and sets brlocks, the second - reads and writes. Wine-server sends fd to wine-application to perform read and write, but wine-server and wine-application are two different processes with different pids. And then wine-application does reads or writes on locked region with fd it needs to set pid of process that and opened a file and set locks (wine-server). Otherwise, a operation fails. As for servers - Samba and Windows 7 servers does pid check. The only way where Samba doesn't do brlock check during read or write request processing is 'strict locking = auto' (by default) and a file is oplocked. We should not use this mode always, because in this case when we open a file and do fork a child process will get access on the locked region - I don't think that we need it. As for strict_io and mand_lock mode - both is necessary for get WINE application work correctly. Anyway, I will provide the right description with the try #2 soon. > > >> --- >> fs/cifs/cifs_fs_sb.h | 1 + >> fs/cifs/cifsfs.c | 8 ++++++ >> fs/cifs/cifsproto.h | 21 ++++++++------- >> fs/cifs/cifssmb.c | 31 +++++++++++++++------- >> fs/cifs/connect.c | 7 +++++ >> fs/cifs/dir.c | 4 +- >> fs/cifs/file.c | 69 ++++++++++++++++++++++++++++++++++++++----------- >> fs/cifs/inode.c | 10 ++++--- >> fs/cifs/link.c | 6 ++-- >> 9 files changed, 112 insertions(+), 45 deletions(-) >> >> diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h >> index 1ef54ab..7a24eb3 100644 >> --- a/fs/cifs/cifs_fs_sb.h >> +++ b/fs/cifs/cifs_fs_sb.h >> @@ -43,6 +43,7 @@ >> #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ >> #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ >> #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ >> +#define CIFS_MOUNT_WINE_MODE 0x80000 /* use pid forwarding for wine apps */ >> >> struct cifs_sb_info { >> struct rb_root tlink_tree; >> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c >> index fb6a2ad..f4ec759 100644 >> --- a/fs/cifs/cifsfs.c >> +++ b/fs/cifs/cifsfs.c >> @@ -460,6 +460,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) >> seq_printf(s, ",nocase"); >> if (tcon->retry) >> seq_printf(s, ",hard"); >> + if (tcon->unix_ext) >> + seq_printf(s, ",unix"); >> + else >> + seq_printf(s, ",nounix"); >> if (cifs_sb->prepath) >> seq_printf(s, ",prepath=%s", cifs_sb->prepath); >> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) >> @@ -468,6 +472,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) >> seq_printf(s, ",setuids"); >> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) >> seq_printf(s, ",serverino"); >> + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) >> + seq_printf(s, ",wine"); >> + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) >> + seq_printf(s, ",forcemand"); >> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) >> seq_printf(s, ",directio"); >> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) >> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h >> index 76c4dc7..28e975c 100644 >> --- a/fs/cifs/cifsproto.h >> +++ b/fs/cifs/cifsproto.h >> @@ -335,18 +335,19 @@ extern int CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, >> const int smb_file_id); >> >> extern int CIFSSMBRead(const int xid, struct cifs_tcon *tcon, >> - const int netfid, unsigned int count, >> - const __u64 lseek, unsigned int *nbytes, char **buf, >> - int *return_buf_type); >> + const int netfid, const __u32 netpid, >> + unsigned int count, const __u64 lseek, >> + unsigned int *nbytes, char **buf, int *return_buf_type); >> extern int CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, >> - const int netfid, const unsigned int count, >> - const __u64 lseek, unsigned int *nbytes, >> - const char *buf, const char __user *ubuf, >> - const int long_op); >> + const int netfid, const __u32 netpid, >> + const unsigned int count, const __u64 lseek, >> + unsigned int *nbytes, const char *buf, >> + const char __user *ubuf, const int long_op); >> extern int CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, >> - const int netfid, const unsigned int count, >> - const __u64 offset, unsigned int *nbytes, >> - struct kvec *iov, const int nvec, const int long_op); >> + const int netfid, const __u32 netpid, >> + const unsigned int count, const __u64 offset, >> + unsigned int *nbytes, struct kvec *iov, const int nvec, >> + const int long_op); >> extern int CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon, >> const unsigned char *searchName, __u64 *inode_number, >> const struct nls_table *nls_codepage, >> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c >> index 3291770..890897c 100644 >> --- a/fs/cifs/cifssmb.c >> +++ b/fs/cifs/cifssmb.c >> @@ -1380,8 +1380,8 @@ openRetry: >> >> int >> CIFSSMBRead(const int xid, struct cifs_tcon *tcon, const int netfid, >> - const unsigned int count, const __u64 lseek, unsigned int *nbytes, >> - char **buf, int *pbuf_type) >> + const __u32 netpid, const unsigned int count, const __u64 lseek, >> + unsigned int *nbytes, char **buf, int *pbuf_type) >> { >> int rc = -EACCES; >> READ_REQ *pSMB = NULL; >> @@ -1407,6 +1407,9 @@ CIFSSMBRead(const int xid, struct cifs_tcon *tcon, const int netfid, >> if (rc) >> return rc; >> >> + pSMB->hdr.Pid = cpu_to_le16((__u16)netpid); >> + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(netpid >> 16)); >> + >> /* tcon and ses pointer are checked in smb_init */ >> if (tcon->ses->server == NULL) >> return -ECONNABORTED; >> @@ -1484,10 +1487,10 @@ CIFSSMBRead(const int xid, struct cifs_tcon *tcon, const int netfid, >> >> >> int >> -CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, >> - const int netfid, const unsigned int count, >> - const __u64 offset, unsigned int *nbytes, const char *buf, >> - const char __user *ubuf, const int long_op) >> +CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, const int netfid, >> + const __u32 netpid, const unsigned int count, const __u64 offset, >> + unsigned int *nbytes, const char *buf, const char __user *ubuf, >> + const int long_op) >> { >> int rc = -EACCES; >> WRITE_REQ *pSMB = NULL; >> @@ -1516,6 +1519,10 @@ CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, >> (void **) &pSMBr); >> if (rc) >> return rc; >> + >> + pSMB->hdr.Pid = cpu_to_le16((__u16)netpid); >> + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(netpid >> 16)); >> + >> /* tcon and ses pointer are checked in smb_init */ >> if (tcon->ses->server == NULL) >> return -ECONNABORTED; >> @@ -1603,10 +1610,10 @@ CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, >> } >> >> int >> -CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, >> - const int netfid, const unsigned int count, >> - const __u64 offset, unsigned int *nbytes, struct kvec *iov, >> - int n_vec, const int long_op) >> +CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, const int netfid, >> + const __u32 netpid, const unsigned int count, const __u64 offset, >> + unsigned int *nbytes, struct kvec *iov, int n_vec, >> + const int long_op) >> { >> int rc = -EACCES; >> WRITE_REQ *pSMB = NULL; >> @@ -1630,6 +1637,10 @@ CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, >> rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB); >> if (rc) >> return rc; >> + >> + pSMB->hdr.Pid = cpu_to_le16((__u16)netpid); >> + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(netpid >> 16)); >> + >> /* tcon and ses pointer are checked in smb_init */ >> if (tcon->ses->server == NULL) >> return -ECONNABORTED; >> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c >> index 94e60c5..c540028 100644 >> --- a/fs/cifs/connect.c >> +++ b/fs/cifs/connect.c >> @@ -103,6 +103,7 @@ struct smb_vol { >> bool noautotune:1; >> bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ >> bool fsc:1; /* enable fscache */ >> + bool wine_mode:1; >> bool mfsymlinks:1; /* use Minshall+French Symlinks */ >> bool multiuser:1; >> bool use_smb2:1; /* force smb2 use on mount instead of cifs */ >> @@ -1362,6 +1363,10 @@ cifs_parse_mount_options(char *options, const char *devname, >> vol->server_ino = 1; >> } else if (strnicmp(data, "noserverino", 9) == 0) { >> vol->server_ino = 0; >> + } else if (strnicmp(data, "wine", 4) == 0) { >> + vol->wine_mode = 1; >> + vol->mand_lock = 1; >> + vol->strict_io = 1; > ^^^^^^^^^^^^^^^ > This seems to do a lot more than what your description suggests. > >> } else if (strnicmp(data, "cifsacl", 7) == 0) { >> vol->cifs_acl = 1; >> } else if (strnicmp(data, "nocifsacl", 9) == 0) { >> @@ -2643,6 +2648,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, >> cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; >> if (pvolume_info->mand_lock) >> cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; >> + if (pvolume_info->wine_mode) >> + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_WINE_MODE; >> if (pvolume_info->cifs_acl) >> cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; >> if (pvolume_info->override_uid) >> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c >> index ab74179..6cdac98 100644 >> --- a/fs/cifs/dir.c >> +++ b/fs/cifs/dir.c >> @@ -446,7 +446,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, >> pdev->minor = >> cpu_to_le64(MINOR(device_number)); >> rc = CIFSSMBWrite(xid, pTcon, >> - fileHandle, >> + fileHandle, current->tgid, >> sizeof(struct win_dev), >> 0, &bytes_written, (char *)pdev, >> NULL, 0); >> @@ -457,7 +457,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, >> pdev->minor = >> cpu_to_le64(MINOR(device_number)); >> rc = CIFSSMBWrite(xid, pTcon, >> - fileHandle, >> + fileHandle, current->tgid, >> sizeof(struct win_dev), >> 0, &bytes_written, (char *)pdev, >> NULL, 0); >> diff --git a/fs/cifs/file.c b/fs/cifs/file.c >> index 9c7f83f..635806f 100644 >> --- a/fs/cifs/file.c >> +++ b/fs/cifs/file.c >> @@ -725,8 +725,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) >> else >> posix_lock_type = CIFS_WRLCK; >> rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */, >> - length, pfLock, >> - posix_lock_type, wait_flag); >> + length, pfLock, posix_lock_type, >> + wait_flag); >> FreeXid(xid); >> return rc; >> } >> @@ -797,8 +797,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) >> posix_lock_type = CIFS_UNLCK; >> >> rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */, >> - length, pfLock, >> - posix_lock_type, wait_flag); >> + length, pfLock, posix_lock_type, >> + wait_flag); >> } else { >> struct cifsFileInfo *fid = file->private_data; >> >> @@ -866,6 +866,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, >> unsigned int total_written; >> struct cifs_sb_info *cifs_sb; >> struct cifs_tcon *pTcon; >> + __u32 netpid; >> int xid; >> struct dentry *dentry = open_file->dentry; >> struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); >> @@ -877,6 +878,11 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, >> >> pTcon = tlink_tcon(open_file->tlink); >> >> + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) >> + netpid = open_file->pid; >> + else >> + netpid = current->tgid; >> + >> xid = GetXid(); >> >> for (total_written = 0; write_size > total_written; >> @@ -901,8 +907,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, >> /* iov[0] is reserved for smb header */ >> iov[1].iov_base = (char *)write_data + total_written; >> iov[1].iov_len = len; >> - rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, len, >> - *poffset, &bytes_written, iov, 1, 0); >> + rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, >> + netpid, len, *poffset, >> + &bytes_written, iov, 1, 0); >> } >> if (rc || (bytes_written == 0)) { >> if (total_written) >> @@ -1112,6 +1119,7 @@ static int cifs_writepages(struct address_space *mapping, >> struct pagevec pvec; >> int rc = 0; >> int scanned = 0; >> + __u32 netpid; >> int xid; >> >> cifs_sb = CIFS_SB(mapping->host->i_sb); >> @@ -1251,10 +1259,15 @@ retry_write: >> cERROR(1, "No writable handles for inode"); >> rc = -EBADF; >> } else { >> + if (cifs_sb->mnt_cifs_flags & >> + CIFS_MOUNT_WINE_MODE) >> + netpid = open_file->pid; >> + else >> + netpid = current->tgid; >> rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, >> - bytes_to_write, offset, >> - &bytes_written, iov, n_iov, >> - 0); >> + netpid, bytes_to_write, >> + offset, &bytes_written, >> + iov, n_iov, 0); >> cifsFileInfo_put(open_file); >> } >> >> @@ -1567,6 +1580,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, >> struct cifs_tcon *pTcon; >> struct cifs_sb_info *cifs_sb; >> int xid, rc; >> + __u32 netpid; >> >> len = iov_length(iov, nr_segs); >> if (!len) >> @@ -1598,6 +1612,12 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, >> >> xid = GetXid(); >> open_file = file->private_data; >> + >> + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) >> + netpid = open_file->pid; >> + else >> + netpid = current->tgid; >> + >> pTcon = tlink_tcon(open_file->tlink); >> inode = file->f_path.dentry->d_inode; >> >> @@ -1625,7 +1645,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, >> break; >> } >> rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, >> - cur_len, *poffset, &written, >> + netpid, cur_len, *poffset, &written, >> to_send, npages, 0); >> } while (rc == -EAGAIN); >> >> @@ -1723,6 +1743,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, >> struct cifsFileInfo *open_file; >> struct smb_com_read_rsp *pSMBr; >> char *read_data; >> + __u32 netpid; >> >> if (!nr_segs) >> return 0; >> @@ -1737,6 +1758,11 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, >> open_file = file->private_data; >> pTcon = tlink_tcon(open_file->tlink); >> >> + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) >> + netpid = open_file->pid; >> + else >> + netpid = current->tgid; >> + >> if ((file->f_flags & O_ACCMODE) == O_WRONLY) >> cFYI(1, "attempting read on write only file instance"); >> >> @@ -1753,7 +1779,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, >> break; >> } >> rc = CIFSSMBRead(xid, pTcon, open_file->netfid, >> - cur_len, *poffset, &bytes_read, >> + netpid, cur_len, *poffset, &bytes_read, >> &read_data, &buf_type); >> pSMBr = (struct smb_com_read_rsp *)read_data; >> if (read_data) { >> @@ -1835,6 +1861,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, >> char *current_offset; >> struct cifsFileInfo *open_file; >> int buf_type = CIFS_NO_BUFFER; >> + __u32 netpid; >> >> xid = GetXid(); >> cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); >> @@ -1847,6 +1874,11 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, >> open_file = file->private_data; >> pTcon = tlink_tcon(open_file->tlink); >> >> + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) >> + netpid = open_file->pid; >> + else >> + netpid = current->tgid; >> + >> if ((file->f_flags & O_ACCMODE) == O_WRONLY) >> cFYI(1, "attempting read on write only file instance"); >> >> @@ -1870,7 +1902,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, >> break; >> } >> rc = CIFSSMBRead(xid, pTcon, >> - open_file->netfid, >> + open_file->netfid, netpid, >> current_read_size, *poffset, >> &bytes_read, ¤t_offset, >> &buf_type); >> @@ -2008,6 +2040,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, >> struct smb_com_read_rsp *pSMBr; >> struct cifsFileInfo *open_file; >> int buf_type = CIFS_NO_BUFFER; >> + __u32 netpid; >> >> xid = GetXid(); >> if (file->private_data == NULL) { >> @@ -2029,6 +2062,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, >> goto read_complete; >> >> cFYI(DBG2, "rpages: num pages %d", num_pages); >> + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) >> + netpid = open_file->pid; >> + else >> + netpid = current->tgid; >> + >> for (i = 0; i < num_pages; ) { >> unsigned contig_pages; >> struct page *tmp_page; >> @@ -2072,10 +2110,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, >> } >> >> rc = CIFSSMBRead(xid, pTcon, >> - open_file->netfid, >> - read_size, offset, >> - &bytes_read, &smb_read_data, >> - &buf_type); >> + open_file->netfid, netpid, >> + read_size, offset, &bytes_read, >> + &smb_read_data, &buf_type); >> /* BB more RC checks ? */ >> if (rc == -EAGAIN) { >> if (smb_read_data) { >> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c >> index adb6324..bafeae6 100644 >> --- a/fs/cifs/inode.c >> +++ b/fs/cifs/inode.c >> @@ -405,7 +405,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, >> if (rc == 0) { >> int buf_type = CIFS_NO_BUFFER; >> /* Read header */ >> - rc = CIFSSMBRead(xid, tcon, netfid, >> + rc = CIFSSMBRead(xid, tcon, netfid, current->tgid, >> 24 /* length */, 0 /* offset */, >> &bytes_read, &pbuf, &buf_type); >> if ((rc == 0) && (bytes_read >= 8)) { >> @@ -1859,8 +1859,9 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, >> cFYI(1, "SetFSize for attrs rc = %d", rc); >> if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { >> unsigned int bytes_written; >> - rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, >> - &bytes_written, NULL, NULL, 1); >> + rc = CIFSSMBWrite(xid, pTcon, nfid, npid, >> + 0, attrs->ia_size, &bytes_written, >> + NULL, NULL, 1); >> cFYI(1, "Wrt seteof rc %d", rc); >> } >> } else >> @@ -1895,7 +1896,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, >> CIFS_MOUNT_MAP_SPECIAL_CHR); >> if (rc == 0) { >> unsigned int bytes_written; >> - rc = CIFSSMBWrite(xid, pTcon, netfid, 0, >> + rc = CIFSSMBWrite(xid, pTcon, netfid, >> + current->tgid, 0, >> attrs->ia_size, >> &bytes_written, NULL, >> NULL, 1); >> diff --git a/fs/cifs/link.c b/fs/cifs/link.c >> index 3a097b6..7536104 100644 >> --- a/fs/cifs/link.c >> +++ b/fs/cifs/link.c >> @@ -203,7 +203,7 @@ CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon, >> return rc; >> } >> >> - rc = CIFSSMBWrite(xid, tcon, netfid, >> + rc = CIFSSMBWrite(xid, tcon, netfid, current->tgid, >> CIFS_MF_SYMLINK_FILE_SIZE /* length */, >> 0 /* offset */, >> &bytes_written, buf, NULL, 0); >> @@ -250,7 +250,7 @@ CIFSQueryMFSymLink(const int xid, struct cifs_tcon *tcon, >> return -ENOMEM; >> pbuf = buf; >> >> - rc = CIFSSMBRead(xid, tcon, netfid, >> + rc = CIFSSMBRead(xid, tcon, netfid, current->tgid, >> CIFS_MF_SYMLINK_FILE_SIZE /* length */, >> 0 /* offset */, >> &bytes_read, &pbuf, &buf_type); >> @@ -329,7 +329,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, >> } >> pbuf = buf; >> >> - rc = CIFSSMBRead(xid, pTcon, netfid, >> + rc = CIFSSMBRead(xid, pTcon, netfid, current->tgid, >> CIFS_MF_SYMLINK_FILE_SIZE /* length */, >> 0 /* offset */, >> &bytes_read, &pbuf, &buf_type); > > > -- > Jeff Layton <jlayton@poochiereds.net> >
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 1ef54ab..7a24eb3 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -43,6 +43,7 @@ #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ +#define CIFS_MOUNT_WINE_MODE 0x80000 /* use pid forwarding for wine apps */ struct cifs_sb_info { struct rb_root tlink_tree; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index fb6a2ad..f4ec759 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -460,6 +460,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) seq_printf(s, ",nocase"); if (tcon->retry) seq_printf(s, ",hard"); + if (tcon->unix_ext) + seq_printf(s, ",unix"); + else + seq_printf(s, ",nounix"); if (cifs_sb->prepath) seq_printf(s, ",prepath=%s", cifs_sb->prepath); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) @@ -468,6 +472,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) seq_printf(s, ",setuids"); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) seq_printf(s, ",serverino"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) + seq_printf(s, ",wine"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) + seq_printf(s, ",forcemand"); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) seq_printf(s, ",directio"); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 76c4dc7..28e975c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -335,18 +335,19 @@ extern int CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, const int smb_file_id); extern int CIFSSMBRead(const int xid, struct cifs_tcon *tcon, - const int netfid, unsigned int count, - const __u64 lseek, unsigned int *nbytes, char **buf, - int *return_buf_type); + const int netfid, const __u32 netpid, + unsigned int count, const __u64 lseek, + unsigned int *nbytes, char **buf, int *return_buf_type); extern int CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, - const int netfid, const unsigned int count, - const __u64 lseek, unsigned int *nbytes, - const char *buf, const char __user *ubuf, - const int long_op); + const int netfid, const __u32 netpid, + const unsigned int count, const __u64 lseek, + unsigned int *nbytes, const char *buf, + const char __user *ubuf, const int long_op); extern int CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, - const int netfid, const unsigned int count, - const __u64 offset, unsigned int *nbytes, - struct kvec *iov, const int nvec, const int long_op); + const int netfid, const __u32 netpid, + const unsigned int count, const __u64 offset, + unsigned int *nbytes, struct kvec *iov, const int nvec, + const int long_op); extern int CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon, const unsigned char *searchName, __u64 *inode_number, const struct nls_table *nls_codepage, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 3291770..890897c 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1380,8 +1380,8 @@ openRetry: int CIFSSMBRead(const int xid, struct cifs_tcon *tcon, const int netfid, - const unsigned int count, const __u64 lseek, unsigned int *nbytes, - char **buf, int *pbuf_type) + const __u32 netpid, const unsigned int count, const __u64 lseek, + unsigned int *nbytes, char **buf, int *pbuf_type) { int rc = -EACCES; READ_REQ *pSMB = NULL; @@ -1407,6 +1407,9 @@ CIFSSMBRead(const int xid, struct cifs_tcon *tcon, const int netfid, if (rc) return rc; + pSMB->hdr.Pid = cpu_to_le16((__u16)netpid); + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(netpid >> 16)); + /* tcon and ses pointer are checked in smb_init */ if (tcon->ses->server == NULL) return -ECONNABORTED; @@ -1484,10 +1487,10 @@ CIFSSMBRead(const int xid, struct cifs_tcon *tcon, const int netfid, int -CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, - const int netfid, const unsigned int count, - const __u64 offset, unsigned int *nbytes, const char *buf, - const char __user *ubuf, const int long_op) +CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, const int netfid, + const __u32 netpid, const unsigned int count, const __u64 offset, + unsigned int *nbytes, const char *buf, const char __user *ubuf, + const int long_op) { int rc = -EACCES; WRITE_REQ *pSMB = NULL; @@ -1516,6 +1519,10 @@ CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, (void **) &pSMBr); if (rc) return rc; + + pSMB->hdr.Pid = cpu_to_le16((__u16)netpid); + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(netpid >> 16)); + /* tcon and ses pointer are checked in smb_init */ if (tcon->ses->server == NULL) return -ECONNABORTED; @@ -1603,10 +1610,10 @@ CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, } int -CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, - const int netfid, const unsigned int count, - const __u64 offset, unsigned int *nbytes, struct kvec *iov, - int n_vec, const int long_op) +CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, const int netfid, + const __u32 netpid, const unsigned int count, const __u64 offset, + unsigned int *nbytes, struct kvec *iov, int n_vec, + const int long_op) { int rc = -EACCES; WRITE_REQ *pSMB = NULL; @@ -1630,6 +1637,10 @@ CIFSSMBWrite2(const int xid, struct cifs_tcon *tcon, rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB); if (rc) return rc; + + pSMB->hdr.Pid = cpu_to_le16((__u16)netpid); + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(netpid >> 16)); + /* tcon and ses pointer are checked in smb_init */ if (tcon->ses->server == NULL) return -ECONNABORTED; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 94e60c5..c540028 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -103,6 +103,7 @@ struct smb_vol { bool noautotune:1; bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ bool fsc:1; /* enable fscache */ + bool wine_mode:1; bool mfsymlinks:1; /* use Minshall+French Symlinks */ bool multiuser:1; bool use_smb2:1; /* force smb2 use on mount instead of cifs */ @@ -1362,6 +1363,10 @@ cifs_parse_mount_options(char *options, const char *devname, vol->server_ino = 1; } else if (strnicmp(data, "noserverino", 9) == 0) { vol->server_ino = 0; + } else if (strnicmp(data, "wine", 4) == 0) { + vol->wine_mode = 1; + vol->mand_lock = 1; + vol->strict_io = 1; } else if (strnicmp(data, "cifsacl", 7) == 0) { vol->cifs_acl = 1; } else if (strnicmp(data, "nocifsacl", 9) == 0) { @@ -2643,6 +2648,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; if (pvolume_info->mand_lock) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; + if (pvolume_info->wine_mode) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_WINE_MODE; if (pvolume_info->cifs_acl) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; if (pvolume_info->override_uid) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index ab74179..6cdac98 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -446,7 +446,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, pdev->minor = cpu_to_le64(MINOR(device_number)); rc = CIFSSMBWrite(xid, pTcon, - fileHandle, + fileHandle, current->tgid, sizeof(struct win_dev), 0, &bytes_written, (char *)pdev, NULL, 0); @@ -457,7 +457,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, pdev->minor = cpu_to_le64(MINOR(device_number)); rc = CIFSSMBWrite(xid, pTcon, - fileHandle, + fileHandle, current->tgid, sizeof(struct win_dev), 0, &bytes_written, (char *)pdev, NULL, 0); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 9c7f83f..635806f 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -725,8 +725,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) else posix_lock_type = CIFS_WRLCK; rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */, - length, pfLock, - posix_lock_type, wait_flag); + length, pfLock, posix_lock_type, + wait_flag); FreeXid(xid); return rc; } @@ -797,8 +797,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) posix_lock_type = CIFS_UNLCK; rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */, - length, pfLock, - posix_lock_type, wait_flag); + length, pfLock, posix_lock_type, + wait_flag); } else { struct cifsFileInfo *fid = file->private_data; @@ -866,6 +866,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, unsigned int total_written; struct cifs_sb_info *cifs_sb; struct cifs_tcon *pTcon; + __u32 netpid; int xid; struct dentry *dentry = open_file->dentry; struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); @@ -877,6 +878,11 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, pTcon = tlink_tcon(open_file->tlink); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) + netpid = open_file->pid; + else + netpid = current->tgid; + xid = GetXid(); for (total_written = 0; write_size > total_written; @@ -901,8 +907,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, /* iov[0] is reserved for smb header */ iov[1].iov_base = (char *)write_data + total_written; iov[1].iov_len = len; - rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, len, - *poffset, &bytes_written, iov, 1, 0); + rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, + netpid, len, *poffset, + &bytes_written, iov, 1, 0); } if (rc || (bytes_written == 0)) { if (total_written) @@ -1112,6 +1119,7 @@ static int cifs_writepages(struct address_space *mapping, struct pagevec pvec; int rc = 0; int scanned = 0; + __u32 netpid; int xid; cifs_sb = CIFS_SB(mapping->host->i_sb); @@ -1251,10 +1259,15 @@ retry_write: cERROR(1, "No writable handles for inode"); rc = -EBADF; } else { + if (cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_WINE_MODE) + netpid = open_file->pid; + else + netpid = current->tgid; rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, - bytes_to_write, offset, - &bytes_written, iov, n_iov, - 0); + netpid, bytes_to_write, + offset, &bytes_written, + iov, n_iov, 0); cifsFileInfo_put(open_file); } @@ -1567,6 +1580,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, struct cifs_tcon *pTcon; struct cifs_sb_info *cifs_sb; int xid, rc; + __u32 netpid; len = iov_length(iov, nr_segs); if (!len) @@ -1598,6 +1612,12 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, xid = GetXid(); open_file = file->private_data; + + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) + netpid = open_file->pid; + else + netpid = current->tgid; + pTcon = tlink_tcon(open_file->tlink); inode = file->f_path.dentry->d_inode; @@ -1625,7 +1645,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, break; } rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, - cur_len, *poffset, &written, + netpid, cur_len, *poffset, &written, to_send, npages, 0); } while (rc == -EAGAIN); @@ -1723,6 +1743,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, struct cifsFileInfo *open_file; struct smb_com_read_rsp *pSMBr; char *read_data; + __u32 netpid; if (!nr_segs) return 0; @@ -1737,6 +1758,11 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, open_file = file->private_data; pTcon = tlink_tcon(open_file->tlink); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) + netpid = open_file->pid; + else + netpid = current->tgid; + if ((file->f_flags & O_ACCMODE) == O_WRONLY) cFYI(1, "attempting read on write only file instance"); @@ -1753,7 +1779,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, break; } rc = CIFSSMBRead(xid, pTcon, open_file->netfid, - cur_len, *poffset, &bytes_read, + netpid, cur_len, *poffset, &bytes_read, &read_data, &buf_type); pSMBr = (struct smb_com_read_rsp *)read_data; if (read_data) { @@ -1835,6 +1861,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, char *current_offset; struct cifsFileInfo *open_file; int buf_type = CIFS_NO_BUFFER; + __u32 netpid; xid = GetXid(); cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); @@ -1847,6 +1874,11 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, open_file = file->private_data; pTcon = tlink_tcon(open_file->tlink); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) + netpid = open_file->pid; + else + netpid = current->tgid; + if ((file->f_flags & O_ACCMODE) == O_WRONLY) cFYI(1, "attempting read on write only file instance"); @@ -1870,7 +1902,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, break; } rc = CIFSSMBRead(xid, pTcon, - open_file->netfid, + open_file->netfid, netpid, current_read_size, *poffset, &bytes_read, ¤t_offset, &buf_type); @@ -2008,6 +2040,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, struct smb_com_read_rsp *pSMBr; struct cifsFileInfo *open_file; int buf_type = CIFS_NO_BUFFER; + __u32 netpid; xid = GetXid(); if (file->private_data == NULL) { @@ -2029,6 +2062,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, goto read_complete; cFYI(DBG2, "rpages: num pages %d", num_pages); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE) + netpid = open_file->pid; + else + netpid = current->tgid; + for (i = 0; i < num_pages; ) { unsigned contig_pages; struct page *tmp_page; @@ -2072,10 +2110,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, } rc = CIFSSMBRead(xid, pTcon, - open_file->netfid, - read_size, offset, - &bytes_read, &smb_read_data, - &buf_type); + open_file->netfid, netpid, + read_size, offset, &bytes_read, + &smb_read_data, &buf_type); /* BB more RC checks ? */ if (rc == -EAGAIN) { if (smb_read_data) { diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index adb6324..bafeae6 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -405,7 +405,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, if (rc == 0) { int buf_type = CIFS_NO_BUFFER; /* Read header */ - rc = CIFSSMBRead(xid, tcon, netfid, + rc = CIFSSMBRead(xid, tcon, netfid, current->tgid, 24 /* length */, 0 /* offset */, &bytes_read, &pbuf, &buf_type); if ((rc == 0) && (bytes_read >= 8)) { @@ -1859,8 +1859,9 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, cFYI(1, "SetFSize for attrs rc = %d", rc); if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { unsigned int bytes_written; - rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, - &bytes_written, NULL, NULL, 1); + rc = CIFSSMBWrite(xid, pTcon, nfid, npid, + 0, attrs->ia_size, &bytes_written, + NULL, NULL, 1); cFYI(1, "Wrt seteof rc %d", rc); } } else @@ -1895,7 +1896,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc == 0) { unsigned int bytes_written; - rc = CIFSSMBWrite(xid, pTcon, netfid, 0, + rc = CIFSSMBWrite(xid, pTcon, netfid, + current->tgid, 0, attrs->ia_size, &bytes_written, NULL, NULL, 1); diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 3a097b6..7536104 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -203,7 +203,7 @@ CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon, return rc; } - rc = CIFSSMBWrite(xid, tcon, netfid, + rc = CIFSSMBWrite(xid, tcon, netfid, current->tgid, CIFS_MF_SYMLINK_FILE_SIZE /* length */, 0 /* offset */, &bytes_written, buf, NULL, 0); @@ -250,7 +250,7 @@ CIFSQueryMFSymLink(const int xid, struct cifs_tcon *tcon, return -ENOMEM; pbuf = buf; - rc = CIFSSMBRead(xid, tcon, netfid, + rc = CIFSSMBRead(xid, tcon, netfid, current->tgid, CIFS_MF_SYMLINK_FILE_SIZE /* length */, 0 /* offset */, &bytes_read, &pbuf, &buf_type); @@ -329,7 +329,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, } pbuf = buf; - rc = CIFSSMBRead(xid, pTcon, netfid, + rc = CIFSSMBRead(xid, pTcon, netfid, current->tgid, CIFS_MF_SYMLINK_FILE_SIZE /* length */, 0 /* offset */, &bytes_read, &pbuf, &buf_type);
Add wine mount option that switches on WINE-capability mode - forward pid of a process who opened a file to any read and write operation even if the file descriptor was inherited by another process. Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> --- fs/cifs/cifs_fs_sb.h | 1 + fs/cifs/cifsfs.c | 8 ++++++ fs/cifs/cifsproto.h | 21 ++++++++------- fs/cifs/cifssmb.c | 31 +++++++++++++++------- fs/cifs/connect.c | 7 +++++ fs/cifs/dir.c | 4 +- fs/cifs/file.c | 69 ++++++++++++++++++++++++++++++++++++++----------- fs/cifs/inode.c | 10 ++++--- fs/cifs/link.c | 6 ++-- 9 files changed, 112 insertions(+), 45 deletions(-)