From abf9767c823bf57837c2032f21332a6efc38a13e Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Sat, 11 Jan 2014 01:57:22 +0100 Subject: cifs: Fix memory leak in cifs_hardlink() Fix a potential memory leak in the cifs_hardlink() error handling path. Detected by Coverity: CID 728510, CID 728511. Signed-off-by: Christian Engelmayer Signed-off-by: Steve French --- fs/cifs/link.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 92aee08483a5..28bc8ee97056 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -438,8 +438,10 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, CIFS_MOUNT_MAP_SPECIAL_CHR); else { server = tcon->ses->server; - if (!server->ops->create_hardlink) - return -ENOSYS; + if (!server->ops->create_hardlink) { + rc = -ENOSYS; + goto cifs_hl_exit; + } rc = server->ops->create_hardlink(xid, tcon, from_name, to_name, cifs_sb); if ((rc == -EIO) || (rc == -EINVAL)) -- cgit v1.2.3 From b5be1a1c4c57a092cb60c709a0491d4ecead3d58 Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Mon, 25 Nov 2013 17:09:49 +0000 Subject: cifs: Rename and cleanup open_query_close_cifs_symlink() Rename open_query_close_cifs_symlink to cifs_query_mf_symlink() to make the name more consistent with other protocol version specific functions. We also pass tcon as an argument to the function. This is already available in the calling functions and we can avoid having to make an unnecessary lookup. Signed-off-by: Sachin Prabhu Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsglob.h | 5 +++-- fs/cifs/cifsproto.h | 7 ++++--- fs/cifs/link.c | 37 ++++++++++++------------------------- fs/cifs/smb1ops.c | 2 +- 4 files changed, 20 insertions(+), 31 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index f918a998a087..fba4d1341f88 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -370,8 +370,9 @@ struct smb_version_operations { void (*new_lease_key)(struct cifs_fid *); int (*generate_signingkey)(struct cifs_ses *); int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); - int (*query_mf_symlink)(const unsigned char *, char *, unsigned int *, - struct cifs_sb_info *, unsigned int); + int (*query_mf_symlink)(unsigned int, struct cifs_tcon *, + struct cifs_sb_info *, const unsigned char *, + char *, unsigned int *); /* if we can do cache read operations */ bool (*is_read_op)(__u32); /* set oplock level for the inode */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 2c29db6a247e..10b9ab1d1ae9 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -496,7 +496,8 @@ void cifs_writev_complete(struct work_struct *work); struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete); void cifs_writedata_release(struct kref *refcount); -int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, - unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, - unsigned int xid); +int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, + const unsigned char *path, char *pbuf, + unsigned int *pbytes_read); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 28bc8ee97056..c8e29682ccdb 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -305,54 +305,41 @@ CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr) } int -open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, - unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, - unsigned int xid) +cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, const unsigned char *path, + char *pbuf, unsigned int *pbytes_read) { int rc; int oplock = 0; __u16 netfid = 0; - struct tcon_link *tlink; - struct cifs_tcon *ptcon; struct cifs_io_parms io_parms; int buf_type = CIFS_NO_BUFFER; FILE_ALL_INFO file_info; - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - ptcon = tlink_tcon(tlink); - - rc = CIFSSMBOpen(xid, ptcon, path, FILE_OPEN, GENERIC_READ, + rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, CREATE_NOT_DIR, &netfid, &oplock, &file_info, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc != 0) { - cifs_put_tlink(tlink); + if (rc) return rc; - } - if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { - CIFSSMBClose(xid, ptcon, netfid); - cifs_put_tlink(tlink); + if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) /* it's not a symlink */ - return rc; - } + goto out; io_parms.netfid = netfid; io_parms.pid = current->tgid; - io_parms.tcon = ptcon; + io_parms.tcon = tcon; io_parms.offset = 0; io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); - CIFSSMBClose(xid, ptcon, netfid); - cifs_put_tlink(tlink); +out: + CIFSSMBClose(xid, tcon, netfid); return rc; } - int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, @@ -372,8 +359,8 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, return -ENOMEM; if (tcon->ses->server->ops->query_mf_symlink) - rc = tcon->ses->server->ops->query_mf_symlink(path, buf, - &bytes_read, cifs_sb, xid); + rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, + cifs_sb, path, buf, &bytes_read); else rc = -ENOSYS; diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 5f5ba0dc2ee1..099c27602257 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -1009,7 +1009,7 @@ struct smb_version_operations smb1_operations = { .mand_lock = cifs_mand_lock, .mand_unlock_range = cifs_unlock_range, .push_mand_locks = cifs_push_mandatory_locks, - .query_mf_symlink = open_query_close_cifs_symlink, + .query_mf_symlink = cifs_query_mf_symlink, .is_read_op = cifs_is_read_op, }; -- cgit v1.2.3 From cb084b1a9be34729bea23428c1a42f7d2f5defbc Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Mon, 25 Nov 2013 17:09:50 +0000 Subject: cifs: Rename MF symlink function names Clean up camel case in functionnames. Signed-off-by: Sachin Prabhu Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 4 ++-- fs/cifs/inode.c | 12 ++++++------ fs/cifs/link.c | 32 +++++++++++++++----------------- fs/cifs/readdir.c | 2 +- 4 files changed, 24 insertions(+), 26 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 10b9ab1d1ae9..78bb6d6ad06a 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -476,8 +476,8 @@ extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon, extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, const int netfid, __u64 *pExtAttrBits, __u64 *pMask); extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb); -extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr); -extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, +extern bool couldbe_mf_symlink(const struct cifs_fattr *fattr); +extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, const unsigned char *path); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 49719b8228e5..6f7f57a3a46a 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -383,10 +383,10 @@ int cifs_get_inode_info_unix(struct inode **pinode, /* check for Minshall+French symlinks */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { - int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, - full_path); + int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr, + full_path); if (tmprc) - cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); + cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); } if (*pinode == NULL) { @@ -800,10 +800,10 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, /* check for Minshall+French symlinks */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { - tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, - full_path); + tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr, + full_path); if (tmprc) - cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); + cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); } if (!*inode) { diff --git a/fs/cifs/link.c b/fs/cifs/link.c index c8e29682ccdb..500bc77a786e 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -91,10 +91,8 @@ symlink_hash_err: } static int -CIFSParseMFSymlink(const u8 *buf, - unsigned int buf_len, - unsigned int *_link_len, - char **_link_str) +parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len, + char **_link_str) { int rc; unsigned int link_len; @@ -137,7 +135,7 @@ CIFSParseMFSymlink(const u8 *buf, } static int -CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) +format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str) { int rc; unsigned int link_len; @@ -181,7 +179,7 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) } static int -CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, +create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, const char *fromName, const char *toName, struct cifs_sb_info *cifs_sb) { @@ -202,7 +200,7 @@ CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, if (!buf) return -ENOMEM; - rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); + rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); if (rc != 0) { kfree(buf); return rc; @@ -238,7 +236,7 @@ CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, } static int -CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, +query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, const unsigned char *searchName, char **symlinkinfo, const struct nls_table *nls_codepage, int remap) { @@ -282,7 +280,7 @@ CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, return rc; } - rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo); + rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo); kfree(buf); if (rc != 0) return rc; @@ -291,7 +289,7 @@ CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, } bool -CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr) +couldbe_mf_symlink(const struct cifs_fattr *fattr) { if (!(fattr->cf_mode & S_IFREG)) /* it's not a symlink */ @@ -341,16 +339,16 @@ out: } int -CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, - const unsigned char *path) +check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, + const unsigned char *path) { int rc; u8 *buf = NULL; unsigned int link_len = 0; unsigned int bytes_read = 0; - if (!CIFSCouldBeMFSymlink(fattr)) + if (!couldbe_mf_symlink(fattr)) /* it's not a symlink */ return 0; @@ -370,7 +368,7 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, if (bytes_read == 0) /* not a symlink */ goto out; - rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); + rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL); if (rc == -EINVAL) { /* it's not a symlink */ rc = 0; @@ -519,7 +517,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) * and fallback to UNIX Extensions Symlinks. */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) - rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path, + rc = query_mf_symlink(xid, tcon, full_path, &target_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -576,7 +574,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) /* BB what if DFS and this volume is on different share? BB */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) - rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, + rc = create_mf_symlink(xid, pTcon, full_path, symname, cifs_sb); else if (pTcon->unix_ext) rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 5940ecabbe6a..b15862e0f68c 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -749,7 +749,7 @@ static int cifs_filldir(char *find_entry, struct file *file, } if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && - CIFSCouldBeMFSymlink(&fattr)) + couldbe_mf_symlink(&fattr)) /* * trying to get the type and mode can be slow, * so just call those regular files for now, and mark -- cgit v1.2.3 From 8205d1bb31af047c6893a4f9e86ed88cf5d6113d Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Mon, 25 Nov 2013 17:09:51 +0000 Subject: cifs: use protocol specific call for query_mf_symlink() We have an existing protocol specific call query_mf_symlink() created for check_mf_symlink which can also be used for query_mf_symlink(). Signed-off-by: Sachin Prabhu Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/link.c | 61 +++++++++++++++++++--------------------------------------- 1 file changed, 20 insertions(+), 41 deletions(-) (limited to 'fs') diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 500bc77a786e..77dbd55795d8 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -237,55 +237,36 @@ create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, static int query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, char **symlinkinfo, - const struct nls_table *nls_codepage, int remap) + struct cifs_sb_info *cifs_sb, const unsigned char *path, + char **symlinkinfo) { int rc; - int oplock = 0; - __u16 netfid = 0; - u8 *buf; - char *pbuf; - unsigned int bytes_read = 0; - int buf_type = CIFS_NO_BUFFER; + u8 *buf = NULL; unsigned int link_len = 0; - struct cifs_io_parms io_parms; - FILE_ALL_INFO file_info; - - rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ, - CREATE_NOT_DIR, &netfid, &oplock, &file_info, - nls_codepage, remap); - if (rc != 0) - return rc; - - if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { - CIFSSMBClose(xid, tcon, netfid); - /* it's not a symlink */ - return -EINVAL; - } + unsigned int bytes_read = 0; buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; - 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, &io_parms, &bytes_read, &pbuf, &buf_type); - CIFSSMBClose(xid, tcon, netfid); - if (rc != 0) { - kfree(buf); - return rc; + if (tcon->ses->server->ops->query_mf_symlink) + rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, + cifs_sb, path, buf, &bytes_read); + else + rc = -ENOSYS; + + if (rc) + goto out; + + if (bytes_read == 0) { /* not a symlink */ + rc = -EINVAL; + goto out; } rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo); +out: kfree(buf); - if (rc != 0) - return rc; - - return 0; + return rc; } bool @@ -517,10 +498,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) * and fallback to UNIX Extensions Symlinks. */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) - rc = query_mf_symlink(xid, tcon, full_path, &target_path, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + rc = query_mf_symlink(xid, tcon, cifs_sb, full_path, + &target_path); if ((rc != 0) && cap_unix(tcon->ses)) rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, -- cgit v1.2.3 From cbb0aba6ff3ff5b64f094f81f4d99d2323c0afcc Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Mon, 25 Nov 2013 17:09:52 +0000 Subject: cifs: Add create MFSymlinks to protocol ops struct Add a new protocol ops function create_mf_symlink and have create_mf_symlink() use it. This patchset moves the MFSymlink operations completely to the ops structure so that we only use the right protocol versions when querying or creating MFSymlinks. Signed-off-by: Sachin Prabhu Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsglob.h | 3 ++ fs/cifs/cifsproto.h | 4 +++ fs/cifs/link.c | 88 ++++++++++++++++++++++++++++------------------------- fs/cifs/smb1ops.c | 1 + 4 files changed, 54 insertions(+), 42 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index fba4d1341f88..61228b7f6b67 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -373,6 +373,9 @@ struct smb_version_operations { int (*query_mf_symlink)(unsigned int, struct cifs_tcon *, struct cifs_sb_info *, const unsigned char *, char *, unsigned int *); + int (*create_mf_symlink)(unsigned int, struct cifs_tcon *, + struct cifs_sb_info *, const unsigned char *, + char *, unsigned int *); /* if we can do cache read operations */ bool (*is_read_op)(__u32); /* set oplock level for the inode */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 78bb6d6ad06a..e88c3b192ef5 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -500,4 +500,8 @@ int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const unsigned char *path, char *pbuf, unsigned int *pbytes_read); +int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, + const unsigned char *path, char *pbuf, + unsigned int *pbytes_written); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 77dbd55795d8..3f259aad361d 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -180,59 +180,31 @@ format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str) static int create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, - const char *fromName, const char *toName, - struct cifs_sb_info *cifs_sb) + struct cifs_sb_info *cifs_sb, const char *fromName, + const char *toName) { int rc; - int oplock = 0; - int remap; - int create_options = CREATE_NOT_DIR; - __u16 netfid = 0; u8 *buf; unsigned int bytes_written = 0; - struct cifs_io_parms io_parms; - struct nls_table *nls_codepage; - - nls_codepage = cifs_sb->local_nls; - remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); - if (rc != 0) { - kfree(buf); - return rc; - } - - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - - rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE, - create_options, &netfid, &oplock, NULL, - nls_codepage, remap); - if (rc != 0) { - kfree(buf); - return rc; - } - - 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; + if (rc) + goto out; - rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0); - CIFSSMBClose(xid, tcon, netfid); - kfree(buf); - if (rc != 0) - return rc; + rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb, + fromName, buf, &bytes_written); + if (rc) + goto out; if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE) - return -EIO; - - return 0; + rc = -EIO; +out: + kfree(buf); + return rc; } static int @@ -319,6 +291,39 @@ out: return rc; } +int +cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, const unsigned char *path, + char *pbuf, unsigned int *pbytes_written) +{ + int rc; + int oplock = 0; + __u16 netfid = 0; + struct cifs_io_parms io_parms; + int create_options = CREATE_NOT_DIR; + + if (backup_cred(cifs_sb)) + create_options |= CREATE_OPEN_BACKUP_INTENT; + + rc = CIFSSMBOpen(xid, tcon, path, FILE_CREATE, GENERIC_WRITE, + create_options, &netfid, &oplock, NULL, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + if (rc) + return rc; + + 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 = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0); + CIFSSMBClose(xid, tcon, netfid); + return rc; +} + int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, @@ -553,8 +558,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) /* BB what if DFS and this volume is on different share? BB */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) - rc = create_mf_symlink(xid, pTcon, full_path, symname, - cifs_sb); + rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname); else if (pTcon->unix_ext) rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, cifs_sb->local_nls); diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 099c27602257..1470ec4fc39d 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -1010,6 +1010,7 @@ struct smb_version_operations smb1_operations = { .mand_unlock_range = cifs_unlock_range, .push_mand_locks = cifs_push_mandatory_locks, .query_mf_symlink = cifs_query_mf_symlink, + .create_mf_symlink = cifs_create_mf_symlink, .is_read_op = cifs_is_read_op, }; -- cgit v1.2.3 From 0f8dce1cb7454f8795b73c5695a28e7a21a57ba0 Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Mon, 25 Nov 2013 17:09:53 +0000 Subject: cifs: Re-order M-F Symlink code This patch makes cosmetic changes. We group similar functions together and separate out the protocol specific functions. Signed-off-by: Sachin Prabhu Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/link.c | 124 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 56 deletions(-) (limited to 'fs') diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 3f259aad361d..5988b6060e8a 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -29,6 +29,10 @@ #include "cifs_debug.h" #include "cifs_fs_sb.h" +/* + * M-F Symlink Functions - Begin + */ + #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1)) @@ -178,6 +182,20 @@ format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str) return 0; } +bool +couldbe_mf_symlink(const struct cifs_fattr *fattr) +{ + if (!(fattr->cf_mode & S_IFREG)) + /* it's not a symlink */ + return false; + + if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) + /* it's not a symlink */ + return false; + + return true; +} + static int create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *fromName, @@ -241,20 +259,60 @@ out: return rc; } -bool -couldbe_mf_symlink(const struct cifs_fattr *fattr) +int +check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, + const unsigned char *path) { - if (!(fattr->cf_mode & S_IFREG)) + int rc; + u8 *buf = NULL; + unsigned int link_len = 0; + unsigned int bytes_read = 0; + + if (!couldbe_mf_symlink(fattr)) /* it's not a symlink */ - return false; + return 0; - if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) + buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (tcon->ses->server->ops->query_mf_symlink) + rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, + cifs_sb, path, buf, &bytes_read); + else + rc = -ENOSYS; + + if (rc) + goto out; + + if (bytes_read == 0) /* not a symlink */ + goto out; + + rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL); + if (rc == -EINVAL) { /* it's not a symlink */ - return false; + rc = 0; + goto out; + } - return true; + if (rc != 0) + goto out; + + /* it is a symlink */ + fattr->cf_eof = link_len; + fattr->cf_mode &= ~S_IFMT; + fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; + fattr->cf_dtype = DT_LNK; +out: + kfree(buf); + return rc; } +/* + * SMB 1.0 Protocol specific functions + */ + int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const unsigned char *path, @@ -324,55 +382,9 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, return rc; } -int -check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, - const unsigned char *path) -{ - int rc; - u8 *buf = NULL; - unsigned int link_len = 0; - unsigned int bytes_read = 0; - - if (!couldbe_mf_symlink(fattr)) - /* it's not a symlink */ - return 0; - - buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (tcon->ses->server->ops->query_mf_symlink) - rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, - cifs_sb, path, buf, &bytes_read); - else - rc = -ENOSYS; - - if (rc) - goto out; - - if (bytes_read == 0) /* not a symlink */ - goto out; - - rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL); - if (rc == -EINVAL) { - /* it's not a symlink */ - rc = 0; - goto out; - } - - if (rc != 0) - goto out; - - /* it is a symlink */ - fattr->cf_eof = link_len; - fattr->cf_mode &= ~S_IFMT; - fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; - fattr->cf_dtype = DT_LNK; -out: - kfree(buf); - return rc; -} +/* + * M-F Symlink Functions - End + */ int cifs_hardlink(struct dentry *old_file, struct inode *inode, -- cgit v1.2.3 From 0ecdb4f572f6ab2219a01e3af349863f6e8b45af Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Wed, 27 Nov 2013 13:27:12 +0000 Subject: cifs: move unix extension call to cifs_query_symlink() Unix extensions rigth now are only applicable to smb1 operations. Move the check and subsequent unix extension call to the smb1 specific call to query_symlink() ie. cifs_query_symlink(). Signed-off-by: Sachin Prabhu Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/link.c | 5 +---- fs/cifs/smb1ops.c | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 5988b6060e8a..38b9bf4f5a6b 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -518,10 +518,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) rc = query_mf_symlink(xid, tcon, cifs_sb, full_path, &target_path); - if ((rc != 0) && cap_unix(tcon->ses)) - rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, - cifs_sb->local_nls); - else if (rc != 0 && server->ops->query_symlink) + if (rc != 0 && server->ops->query_symlink) rc = server->ops->query_symlink(xid, tcon, full_path, &target_path, cifs_sb); diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 1470ec4fc39d..988fddb72025 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -918,23 +918,31 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); + /* Check for unix extensions */ + if (cap_unix(tcon->ses)) { + rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, + cifs_sb->local_nls); + goto out; + } + rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, FILE_READ_ATTRIBUTES, OPEN_REPARSE_POINT, &netfid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) - return rc; + goto out; rc = CIFSSMBQuerySymLink(xid, tcon, netfid, target_path, cifs_sb->local_nls); - if (rc) { - CIFSSMBClose(xid, tcon, netfid); - return rc; - } + if (rc) + goto out_close; convert_delimiter(*target_path, '/'); +out_close: CIFSSMBClose(xid, tcon, netfid); - cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); +out: + if (!rc) + cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); return rc; } -- cgit v1.2.3 From 924e3fa48c627ad45d3be9412a93df34ab0fb482 Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Mon, 2 Dec 2013 16:37:43 +0000 Subject: cifs: Add support for follow_link on dfs shares under posix extensions When using posix extensions, dfs shares in the dfs root show up as symlinks resulting in userland tools such as 'ls' calling readlink() on these shares. Since these are dfs shares, we end up returning -EREMOTE. $ ls -l /mnt ls: cannot read symbolic link /mnt/test: Object is remote total 0 lrwxrwxrwx. 1 root root 19 Nov 6 09:47 test With added follow_link() support for dfs shares, when using unix extensions, we call GET_DFS_REFERRAL to obtain the DFS referral and return the first node returned. The dfs share in the dfs root is now displayed in the following manner. $ ls -l /mnt total 0 lrwxrwxrwx. 1 root root 19 Nov 6 09:47 test -> \vm140-31\test Signed-off-by: Sachin Prabhu Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/smb1ops.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'fs') diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 988fddb72025..abd2cc9515c9 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -907,6 +907,33 @@ cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset, (__u8)type, wait, 0); } +static int +cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon, + const unsigned char *searchName, char **symlinkinfo, + const struct nls_table *nls_codepage) +{ +#ifdef CONFIG_CIFS_DFS_UPCALL + int rc; + unsigned int num_referrals = 0; + struct dfs_info3_param *referrals = NULL; + + rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage, + &num_referrals, &referrals, 0); + + if (!rc && num_referrals > 0) { + *symlinkinfo = kstrndup(referrals->node_name, + strlen(referrals->node_name), + GFP_KERNEL); + if (!*symlinkinfo) + rc = -ENOMEM; + free_dfs_info_array(referrals, num_referrals); + } + return rc; +#else /* No DFS support */ + return -EREMOTE; +#endif +} + static int cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, const char *full_path, char **target_path, @@ -922,6 +949,11 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, if (cap_unix(tcon->ses)) { rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, cifs_sb->local_nls); + if (rc == -EREMOTE) + rc = cifs_unix_dfs_readlink(xid, tcon, full_path, + target_path, + cifs_sb->local_nls); + goto out; } -- cgit v1.2.3 From 9bf4fa01f9aaf240bc6e40b3ed186039472c5298 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 16 Jan 2014 15:53:33 +0400 Subject: CIFS: Cleanup CIFSSMBOpen Remove indentation, fix comment style, rename camel case variables in preparation to make it work with cifs_open_parms structure as a parm. Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 8 +-- fs/cifs/cifssmb.c | 150 ++++++++++++++++++++++++++++------------------------ 2 files changed, 86 insertions(+), 72 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index e88c3b192ef5..582ae61f45b6 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -363,10 +363,10 @@ extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, extern int CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid); extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, - const char *fileName, const int disposition, - const int access_flags, const int omode, - __u16 *netfid, int *pOplock, FILE_ALL_INFO *, - const struct nls_table *nls_codepage, int remap); + const char *path, const int disposition, + const int desired_access, const int create_options, + __u16 *netfid, int *oplock, FILE_ALL_INFO *buf, + const struct nls_table *nls, int remap); extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, const char *fileName, const int disposition, const int access_flags, const int omode, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index d707edb6b852..8e1ebc2dc0db 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1274,103 +1274,117 @@ OldOpenRetry: int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, - const char *fileName, const int openDisposition, - const int access_flags, const int create_options, __u16 *netfid, - int *pOplock, FILE_ALL_INFO *pfile_info, - const struct nls_table *nls_codepage, int remap) + const char *path, const int disposition, const int desired_access, + const int create_options, __u16 *netfid, int *oplock, + FILE_ALL_INFO *buf, const struct nls_table *nls, int remap) { int rc = -EACCES; - OPEN_REQ *pSMB = NULL; - OPEN_RSP *pSMBr = NULL; + OPEN_REQ *req = NULL; + OPEN_RSP *rsp = NULL; int bytes_returned; int name_len; __u16 count; openRetry: - rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB, - (void **) &pSMBr); + rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req, + (void **)&rsp); if (rc) return rc; - pSMB->AndXCommand = 0xFF; /* none */ + /* no commands go after this */ + req->AndXCommand = 0xFF; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - count = 1; /* account for one byte pad to word boundary */ - name_len = - cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1), - fileName, PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ + if (req->hdr.Flags2 & SMBFLG2_UNICODE) { + /* account for one byte pad to word boundary */ + count = 1; + name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1), + path, PATH_MAX, nls, remap); + /* trailing null */ + name_len++; name_len *= 2; - pSMB->NameLength = cpu_to_le16(name_len); - } else { /* BB improve check for buffer overruns BB */ - count = 0; /* no pad */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - pSMB->NameLength = cpu_to_le16(name_len); - strncpy(pSMB->fileName, fileName, name_len); + req->NameLength = cpu_to_le16(name_len); + } else { + /* BB improve check for buffer overruns BB */ + /* no pad */ + count = 0; + name_len = strnlen(path, PATH_MAX); + /* trailing null */ + name_len++; + req->NameLength = cpu_to_le16(name_len); + strncpy(req->fileName, path, name_len); } - if (*pOplock & REQ_OPLOCK) - pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); - else if (*pOplock & REQ_BATCHOPLOCK) - pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); - pSMB->DesiredAccess = cpu_to_le32(access_flags); - pSMB->AllocationSize = 0; - /* set file as system file if special file such - as fifo and server expecting SFU style and - no Unix extensions */ + + if (*oplock & REQ_OPLOCK) + req->OpenFlags = cpu_to_le32(REQ_OPLOCK); + else if (*oplock & REQ_BATCHOPLOCK) + req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); + + req->DesiredAccess = cpu_to_le32(desired_access); + req->AllocationSize = 0; + + /* + * Set file as system file if special file such as fifo and server + * expecting SFU style and no Unix extensions. + */ if (create_options & CREATE_OPTION_SPECIAL) - pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); + req->FileAttributes = cpu_to_le32(ATTR_SYSTEM); else - pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); + req->FileAttributes = cpu_to_le32(ATTR_NORMAL); - /* XP does not handle ATTR_POSIX_SEMANTICS */ - /* but it helps speed up case sensitive checks for other - servers such as Samba */ + /* + * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case + * sensitive checks for other servers such as Samba. + */ if (tcon->ses->capabilities & CAP_UNIX) - pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); + req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); if (create_options & CREATE_OPTION_READONLY) - pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY); + req->FileAttributes |= cpu_to_le32(ATTR_READONLY); + + req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); + req->CreateDisposition = cpu_to_le32(disposition); + req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); - pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); - pSMB->CreateDisposition = cpu_to_le32(openDisposition); - pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); /* BB Expirement with various impersonation levels and verify */ - pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); - pSMB->SecurityFlags = - SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; + req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); + req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY; count += name_len; - inc_rfc1001_len(pSMB, count); + inc_rfc1001_len(req, count); - pSMB->ByteCount = cpu_to_le16(count); - /* long_op set to 1 to allow for oplock break timeouts */ - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *)pSMBr, &bytes_returned, 0); + req->ByteCount = cpu_to_le16(count); + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req, + (struct smb_hdr *)rsp, &bytes_returned, 0); cifs_stats_inc(&tcon->stats.cifs_stats.num_opens); if (rc) { cifs_dbg(FYI, "Error in Open = %d\n", rc); - } else { - *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */ - *netfid = pSMBr->Fid; /* cifs fid stays in le */ - /* Let caller know file was created so we can set the mode. */ - /* Do we care about the CreateAction in any other cases? */ - if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction) - *pOplock |= CIFS_CREATE_ACTION; - if (pfile_info) { - memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime, - 36 /* CreationTime to Attributes */); - /* the file_info buf is endian converted by caller */ - pfile_info->AllocationSize = pSMBr->AllocationSize; - pfile_info->EndOfFile = pSMBr->EndOfFile; - pfile_info->NumberOfLinks = cpu_to_le32(1); - pfile_info->DeletePending = 0; - } + cifs_buf_release(req); + if (rc == -EAGAIN) + goto openRetry; + return rc; } - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto openRetry; + /* 1 byte no need to le_to_cpu */ + *oplock = rsp->OplockLevel; + /* cifs fid stays in le */ + *netfid = rsp->Fid; + + /* Let caller know file was created so we can set the mode. */ + /* Do we care about the CreateAction in any other cases? */ + if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction) + *oplock |= CIFS_CREATE_ACTION; + + if (buf) { + /* copy from CreationTime to Attributes */ + memcpy((char *)buf, (char *)&rsp->CreationTime, 36); + /* the file_info buf is endian converted by caller */ + buf->AllocationSize = rsp->AllocationSize; + buf->EndOfFile = rsp->EndOfFile; + buf->NumberOfLinks = cpu_to_le32(1); + buf->DeletePending = 0; + } + + cifs_buf_release(req); return rc; } -- cgit v1.2.3 From dd12067156b442801a7d636de354efe1d4dc467c Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 16 Jan 2014 15:53:34 +0400 Subject: CIFS: Cleanup cifs_mknod Rename camel case variable and fix comment style. Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/dir.c | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) (limited to 'fs') diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index a514e0a65f69..0850325c3b44 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -565,12 +565,12 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; struct cifs_sb_info *cifs_sb; struct tcon_link *tlink; - struct cifs_tcon *pTcon; + struct cifs_tcon *tcon; struct cifs_io_parms io_parms; char *full_path = NULL; struct inode *newinode = NULL; int oplock = 0; - u16 fileHandle; + u16 netfid; FILE_ALL_INFO *buf = NULL; unsigned int bytes_written; struct win_dev *pdev; @@ -583,7 +583,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, if (IS_ERR(tlink)) return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); + tcon = tlink_tcon(tlink); xid = get_xid(); @@ -593,7 +593,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, goto mknod_out; } - if (pTcon->unix_ext) { + if (tcon->unix_ext) { struct cifs_unix_set_info_args args = { .mode = mode & ~current_umask(), .ctime = NO_CHANGE_64, @@ -608,7 +608,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, args.uid = INVALID_UID; /* no change */ args.gid = INVALID_GID; /* no change */ } - rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, + rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -640,42 +640,38 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, if (backup_cred(cifs_sb)) create_options |= CREATE_OPEN_BACKUP_INTENT; - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, + rc = CIFSSMBOpen(xid, tcon, full_path, FILE_CREATE, GENERIC_WRITE, create_options, - &fileHandle, &oplock, buf, cifs_sb->local_nls, + &netfid, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) goto mknod_out; - /* BB Do not bother to decode buf since no local inode yet to put - * timestamps in, but we can reuse it safely */ + /* + * BB Do not bother to decode buf since no local inode yet to put + * timestamps in, but we can reuse it safely. + */ pdev = (struct win_dev *)buf; - io_parms.netfid = fileHandle; + io_parms.netfid = netfid; io_parms.pid = current->tgid; - io_parms.tcon = pTcon; + io_parms.tcon = tcon; io_parms.offset = 0; io_parms.length = sizeof(struct win_dev); if (S_ISCHR(mode)) { memcpy(pdev->type, "IntxCHR", 8); - pdev->major = - cpu_to_le64(MAJOR(device_number)); - pdev->minor = - cpu_to_le64(MINOR(device_number)); - rc = CIFSSMBWrite(xid, &io_parms, - &bytes_written, (char *)pdev, - NULL, 0); + pdev->major = cpu_to_le64(MAJOR(device_number)); + pdev->minor = cpu_to_le64(MINOR(device_number)); + rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, + NULL, 0); } else if (S_ISBLK(mode)) { memcpy(pdev->type, "IntxBLK", 8); - pdev->major = - cpu_to_le64(MAJOR(device_number)); - pdev->minor = - cpu_to_le64(MINOR(device_number)); - rc = CIFSSMBWrite(xid, &io_parms, - &bytes_written, (char *)pdev, - NULL, 0); + pdev->major = cpu_to_le64(MAJOR(device_number)); + pdev->minor = cpu_to_le64(MINOR(device_number)); + rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, + NULL, 0); } /* else if (S_ISFIFO) */ - CIFSSMBClose(xid, pTcon, fileHandle); + CIFSSMBClose(xid, tcon, netfid); d_drop(direntry); /* FIXME: add code here to set EAs */ -- cgit v1.2.3 From 0360d605a236355f9501d21175e405536e2acd48 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 16 Jan 2014 15:53:35 +0400 Subject: CIFS: Remove extra indentation in cifs_sfu_type Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/inode.c | 97 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 50 insertions(+), 47 deletions(-) (limited to 'fs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 6f7f57a3a46a..5793b5a557e9 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -404,7 +404,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, } static int -cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, +cifs_sfu_type(struct cifs_fattr *fattr, const char *path, struct cifs_sb_info *cifs_sb, unsigned int xid) { int rc; @@ -416,6 +416,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, char buf[24]; unsigned int bytes_read; char *pbuf; + int buf_type = CIFS_NO_BUFFER; pbuf = buf; @@ -441,57 +442,59 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc == 0) { - int buf_type = CIFS_NO_BUFFER; - /* Read header */ - 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 (memcmp("IntxBLK", pbuf, 8) == 0) { - cifs_dbg(FYI, "Block device\n"); - fattr->cf_mode |= S_IFBLK; - fattr->cf_dtype = DT_BLK; - if (bytes_read == 24) { - /* we have enough to decode dev num */ - __u64 mjr; /* major */ - __u64 mnr; /* minor */ - mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); - mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); - fattr->cf_rdev = MKDEV(mjr, mnr); - } - } else if (memcmp("IntxCHR", pbuf, 8) == 0) { - cifs_dbg(FYI, "Char device\n"); - fattr->cf_mode |= S_IFCHR; - fattr->cf_dtype = DT_CHR; - if (bytes_read == 24) { - /* we have enough to decode dev num */ - __u64 mjr; /* major */ - __u64 mnr; /* minor */ - mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); - mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); - fattr->cf_rdev = MKDEV(mjr, mnr); - } - } else if (memcmp("IntxLNK", pbuf, 7) == 0) { - cifs_dbg(FYI, "Symlink\n"); - fattr->cf_mode |= S_IFLNK; - fattr->cf_dtype = DT_LNK; - } else { - fattr->cf_mode |= S_IFREG; /* file? */ - fattr->cf_dtype = DT_REG; - rc = -EOPNOTSUPP; + if (rc) { + cifs_put_tlink(tlink); + return rc; + } + + /* Read header */ + 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 (memcmp("IntxBLK", pbuf, 8) == 0) { + cifs_dbg(FYI, "Block device\n"); + fattr->cf_mode |= S_IFBLK; + fattr->cf_dtype = DT_BLK; + if (bytes_read == 24) { + /* we have enough to decode dev num */ + __u64 mjr; /* major */ + __u64 mnr; /* minor */ + mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); + mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); + fattr->cf_rdev = MKDEV(mjr, mnr); + } + } else if (memcmp("IntxCHR", pbuf, 8) == 0) { + cifs_dbg(FYI, "Char device\n"); + fattr->cf_mode |= S_IFCHR; + fattr->cf_dtype = DT_CHR; + if (bytes_read == 24) { + /* we have enough to decode dev num */ + __u64 mjr; /* major */ + __u64 mnr; /* minor */ + mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); + mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); + fattr->cf_rdev = MKDEV(mjr, mnr); } + } else if (memcmp("IntxLNK", pbuf, 7) == 0) { + cifs_dbg(FYI, "Symlink\n"); + fattr->cf_mode |= S_IFLNK; + fattr->cf_dtype = DT_LNK; } else { - fattr->cf_mode |= S_IFREG; /* then it is a file */ + fattr->cf_mode |= S_IFREG; /* file? */ fattr->cf_dtype = DT_REG; - rc = -EOPNOTSUPP; /* or some unknown SFU type */ + rc = -EOPNOTSUPP; } - CIFSSMBClose(xid, tcon, netfid); + } else { + fattr->cf_mode |= S_IFREG; /* then it is a file */ + fattr->cf_dtype = DT_REG; + rc = -EOPNOTSUPP; /* or some unknown SFU type */ } + CIFSSMBClose(xid, tcon, netfid); cifs_put_tlink(tlink); return rc; } -- cgit v1.2.3 From d81b8a40e2ece0a9ab57b1fe1798e291e75bf8fc Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 16 Jan 2014 15:53:36 +0400 Subject: CIFS: Cleanup cifs open codepath Rename CIFSSMBOpen to CIFS_open and make it take cifs_open_parms structure as a parm. Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/cifsacl.c | 40 ++++++++++++++++++++--------- fs/cifs/cifsproto.h | 7 ++--- fs/cifs/cifssmb.c | 16 ++++++++---- fs/cifs/dir.c | 21 ++++++++++----- fs/cifs/file.c | 2 +- fs/cifs/inode.c | 73 ++++++++++++++++++++++++++++++++++------------------- fs/cifs/link.c | 44 ++++++++++++++++++++------------ fs/cifs/smb1ops.c | 71 +++++++++++++++++++++++++++++++-------------------- 8 files changed, 174 insertions(+), 100 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 51f5e0ee7237..8f9b4f710d4a 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -895,9 +895,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, int oplock = 0; unsigned int xid; int rc, create_options = 0; - __u16 fid; struct cifs_tcon *tcon; struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + struct cifs_fid fid; + struct cifs_open_parms oparms; if (IS_ERR(tlink)) return ERR_CAST(tlink); @@ -908,12 +909,19 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, if (backup_cred(cifs_sb)) create_options |= CREATE_OPEN_BACKUP_INTENT; - rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, - create_options, &fid, &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = READ_CONTROL; + oparms.create_options = create_options; + oparms.disposition = FILE_OPEN; + oparms.path = path; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); if (!rc) { - rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); - CIFSSMBClose(xid, tcon, fid); + rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen); + CIFSSMBClose(xid, tcon, fid.netfid); } cifs_put_tlink(tlink); @@ -950,10 +958,11 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, int oplock = 0; unsigned int xid; int rc, access_flags, create_options = 0; - __u16 fid; struct cifs_tcon *tcon; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + struct cifs_fid fid; + struct cifs_open_parms oparms; if (IS_ERR(tlink)) return PTR_ERR(tlink); @@ -969,18 +978,25 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, else access_flags = WRITE_DAC; - rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags, - create_options, &fid, &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = access_flags; + oparms.create_options = create_options; + oparms.disposition = FILE_OPEN; + oparms.path = path; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); if (rc) { cifs_dbg(VFS, "Unable to open file to set ACL\n"); goto out; } - rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag); + rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag); cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc); - CIFSSMBClose(xid, tcon, fid); + CIFSSMBClose(xid, tcon, fid.netfid); out: free_xid(xid); cifs_put_tlink(tlink); diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 582ae61f45b6..79e6e9a93a8c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -362,11 +362,8 @@ extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nls_codepage); extern int CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid); -extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, - const char *path, const int disposition, - const int desired_access, const int create_options, - __u16 *netfid, int *oplock, FILE_ALL_INFO *buf, - const struct nls_table *nls, int remap); +extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, + int *oplock, FILE_ALL_INFO *buf); extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, const char *fileName, const int disposition, const int access_flags, const int omode, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 8e1ebc2dc0db..4d881c35eeca 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1273,10 +1273,8 @@ OldOpenRetry: } int -CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, - const char *path, const int disposition, const int desired_access, - const int create_options, __u16 *netfid, int *oplock, - FILE_ALL_INFO *buf, const struct nls_table *nls, int remap) +CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, + FILE_ALL_INFO *buf) { int rc = -EACCES; OPEN_REQ *req = NULL; @@ -1284,6 +1282,14 @@ CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, int bytes_returned; int name_len; __u16 count; + struct cifs_sb_info *cifs_sb = oparms->cifs_sb; + struct cifs_tcon *tcon = oparms->tcon; + int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; + const struct nls_table *nls = cifs_sb->local_nls; + int create_options = oparms->create_options; + int desired_access = oparms->desired_access; + int disposition = oparms->disposition; + const char *path = oparms->path; openRetry: rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req, @@ -1367,7 +1373,7 @@ openRetry: /* 1 byte no need to le_to_cpu */ *oplock = rsp->OplockLevel; /* cifs fid stays in le */ - *netfid = rsp->Fid; + oparms->fid->netfid = rsp->Fid; /* Let caller know file was created so we can set the mode. */ /* Do we care about the CreateAction in any other cases? */ diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 0850325c3b44..d3a6796caa5a 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -570,7 +570,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, char *full_path = NULL; struct inode *newinode = NULL; int oplock = 0; - u16 netfid; + struct cifs_fid fid; + struct cifs_open_parms oparms; FILE_ALL_INFO *buf = NULL; unsigned int bytes_written; struct win_dev *pdev; @@ -640,10 +641,16 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, if (backup_cred(cifs_sb)) create_options |= CREATE_OPEN_BACKUP_INTENT; - rc = CIFSSMBOpen(xid, tcon, full_path, FILE_CREATE, - GENERIC_WRITE, create_options, - &netfid, &oplock, buf, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_WRITE; + oparms.create_options = create_options; + oparms.disposition = FILE_CREATE; + oparms.path = full_path; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, buf); if (rc) goto mknod_out; @@ -653,7 +660,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, */ pdev = (struct win_dev *)buf; - io_parms.netfid = netfid; + io_parms.netfid = fid.netfid; io_parms.pid = current->tgid; io_parms.tcon = tcon; io_parms.offset = 0; @@ -671,7 +678,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, NULL, 0); } /* else if (S_ISFIFO) */ - CIFSSMBClose(xid, tcon, netfid); + CIFSSMBClose(xid, tcon, fid.netfid); d_drop(direntry); /* FIXME: add code here to set EAs */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5a5a87240fe2..853d6d1cc822 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -678,7 +678,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) /* * Can not refresh inode by passing in file_info buf to be returned by - * CIFSSMBOpen and then calling get_inode_info with returned buf since + * ops->open and then calling get_inode_info with returned buf since * file might have write behind data that needs to be flushed and server * version of file size can be stale. If we knew for sure that inode was * not dirty locally we could do this. diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 5793b5a557e9..9cb9679d7357 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -409,9 +409,10 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path, { int rc; int oplock = 0; - __u16 netfid; struct tcon_link *tlink; struct cifs_tcon *tcon; + struct cifs_fid fid; + struct cifs_open_parms oparms; struct cifs_io_parms io_parms; char buf[24]; unsigned int bytes_read; @@ -437,18 +438,23 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path, return PTR_ERR(tlink); tcon = tlink_tcon(tlink); - rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, - CREATE_NOT_DIR, &netfid, &oplock, NULL, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_READ; + oparms.create_options = CREATE_NOT_DIR; + oparms.disposition = FILE_OPEN; + oparms.path = path; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); if (rc) { cifs_put_tlink(tlink); return rc; } /* Read header */ - io_parms.netfid = netfid; + io_parms.netfid = fid.netfid; io_parms.pid = current->tgid; io_parms.tcon = tcon; io_parms.offset = 0; @@ -494,7 +500,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path, fattr->cf_dtype = DT_REG; rc = -EOPNOTSUPP; /* or some unknown SFU type */ } - CIFSSMBClose(xid, tcon, netfid); + CIFSSMBClose(xid, tcon, fid.netfid); cifs_put_tlink(tlink); return rc; } @@ -1035,7 +1041,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, { int oplock = 0; int rc; - __u16 netfid; + struct cifs_fid fid; + struct cifs_open_parms oparms; struct inode *inode = dentry->d_inode; struct cifsInodeInfo *cifsInode = CIFS_I(inode); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); @@ -1058,10 +1065,16 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, goto out; } - rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, - DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, - &netfid, &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES; + oparms.create_options = CREATE_NOT_DIR; + oparms.disposition = FILE_OPEN; + oparms.path = full_path; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); if (rc != 0) goto out; @@ -1082,7 +1095,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, goto out_close; } info_buf->Attributes = cpu_to_le32(dosattr); - rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, + rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid, current->tgid); /* although we would like to mark the file hidden if that fails we will still try to rename it */ @@ -1093,7 +1106,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, } /* rename the file */ - rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, + rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc != 0) { @@ -1103,7 +1117,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, /* try to set DELETE_ON_CLOSE */ if (!cifsInode->delete_pending) { - rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid, + rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid, current->tgid); /* * some samba versions return -ENOENT when we try to set the @@ -1123,7 +1137,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, } out_close: - CIFSSMBClose(xid, tcon, netfid); + CIFSSMBClose(xid, tcon, fid.netfid); out: kfree(info_buf); cifs_put_tlink(tlink); @@ -1135,13 +1149,13 @@ out: * them anyway. */ undo_rename: - CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name, + CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); undo_setattr: if (dosattr != origattr) { info_buf->Attributes = cpu_to_le32(origattr); - if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, + if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid, current->tgid)) cifsInode->cifsAttrs = origattr; } @@ -1552,7 +1566,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, struct tcon_link *tlink; struct cifs_tcon *tcon; struct TCP_Server_Info *server; - __u16 srcfid; + struct cifs_fid fid; + struct cifs_open_parms oparms; int oplock, rc; tlink = cifs_sb_tlink(cifs_sb); @@ -1579,17 +1594,23 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, if (to_dentry->d_parent != from_dentry->d_parent) goto do_rename_exit; + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; /* open the file to be renamed -- we need DELETE perms */ - rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE, - CREATE_NOT_DIR, &srcfid, &oplock, NULL, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + oparms.desired_access = DELETE; + oparms.create_options = CREATE_NOT_DIR; + oparms.disposition = FILE_OPEN; + oparms.path = from_path; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); if (rc == 0) { - rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid, + rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, (const char *) to_dentry->d_name.name, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - CIFSSMBClose(xid, tcon, srcfid); + CIFSSMBClose(xid, tcon, fid.netfid); } do_rename_exit: cifs_put_tlink(tlink); diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 38b9bf4f5a6b..52f41f9f7def 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -320,16 +320,22 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, { int rc; int oplock = 0; - __u16 netfid = 0; + struct cifs_fid fid; + struct cifs_open_parms oparms; struct cifs_io_parms io_parms; int buf_type = CIFS_NO_BUFFER; FILE_ALL_INFO file_info; - rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, - CREATE_NOT_DIR, &netfid, &oplock, &file_info, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_READ; + oparms.create_options = CREATE_NOT_DIR; + oparms.disposition = FILE_OPEN; + oparms.path = path; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, &file_info); if (rc) return rc; @@ -337,7 +343,7 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, /* it's not a symlink */ goto out; - io_parms.netfid = netfid; + io_parms.netfid = fid.netfid; io_parms.pid = current->tgid; io_parms.tcon = tcon; io_parms.offset = 0; @@ -345,7 +351,7 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); out: - CIFSSMBClose(xid, tcon, netfid); + CIFSSMBClose(xid, tcon, fid.netfid); return rc; } @@ -356,29 +362,35 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, { int rc; int oplock = 0; - __u16 netfid = 0; + struct cifs_fid fid; + struct cifs_open_parms oparms; struct cifs_io_parms io_parms; int create_options = CREATE_NOT_DIR; if (backup_cred(cifs_sb)) create_options |= CREATE_OPEN_BACKUP_INTENT; - rc = CIFSSMBOpen(xid, tcon, path, FILE_CREATE, GENERIC_WRITE, - create_options, &netfid, &oplock, NULL, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_WRITE; + oparms.create_options = create_options; + oparms.disposition = FILE_OPEN; + oparms.path = path; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); if (rc) return rc; - io_parms.netfid = netfid; + io_parms.netfid = fid.netfid; io_parms.pid = current->tgid; io_parms.tcon = tcon; io_parms.offset = 0; io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0); - CIFSSMBClose(xid, tcon, netfid); + CIFSSMBClose(xid, tcon, fid.netfid); return rc; } diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index abd2cc9515c9..9ac5bfc9cc56 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -560,17 +560,24 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) { int tmprc; int oplock = 0; - __u16 netfid; + struct cifs_fid fid; + struct cifs_open_parms oparms; + + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = FILE_READ_ATTRIBUTES; + oparms.create_options = 0; + oparms.disposition = FILE_OPEN; + oparms.path = full_path; + oparms.fid = &fid; + oparms.reconnect = false; /* Need to check if this is a symbolic link or not */ - tmprc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, - FILE_READ_ATTRIBUTES, 0, &netfid, &oplock, - NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + tmprc = CIFS_open(xid, &oparms, &oplock, NULL); if (tmprc == -EOPNOTSUPP) *symlink = true; else - CIFSSMBClose(xid, tcon, netfid); + CIFSSMBClose(xid, tcon, fid.netfid); } return rc; @@ -705,12 +712,7 @@ cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, oparms->cifs_sb->local_nls, oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - return CIFSSMBOpen(xid, oparms->tcon, oparms->path, - oparms->disposition, oparms->desired_access, - oparms->create_options, &oparms->fid->netfid, oplock, - buf, oparms->cifs_sb->local_nls, - oparms->cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + return CIFS_open(xid, oparms, oplock, buf); } static void @@ -761,8 +763,9 @@ smb_set_file_info(struct inode *inode, const char *full_path, { int oplock = 0; int rc; - __u16 netfid; __u32 netpid; + struct cifs_fid fid; + struct cifs_open_parms oparms; struct cifsFileInfo *open_file; struct cifsInodeInfo *cinode = CIFS_I(inode); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); @@ -772,7 +775,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, /* if the file is already open for write, just use that fileid */ open_file = find_writable_file(cinode, true); if (open_file) { - netfid = open_file->fid.netfid; + fid.netfid = open_file->fid.netfid; netpid = open_file->pid; tcon = tlink_tcon(open_file->tlink); goto set_via_filehandle; @@ -796,12 +799,17 @@ smb_set_file_info(struct inode *inode, const char *full_path, goto out; } - cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); - rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, - SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, - &netfid, &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES; + oparms.create_options = CREATE_NOT_DIR; + oparms.disposition = FILE_OPEN; + oparms.path = full_path; + oparms.fid = &fid; + oparms.reconnect = false; + cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); + rc = CIFS_open(xid, &oparms, &oplock, NULL); if (rc != 0) { if (rc == -EIO) rc = -EINVAL; @@ -811,12 +819,12 @@ smb_set_file_info(struct inode *inode, const char *full_path, netpid = current->tgid; set_via_filehandle: - rc = CIFSSMBSetFileInfo(xid, tcon, buf, netfid, netpid); + rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid); if (!rc) cinode->cifsAttrs = le32_to_cpu(buf->Attributes); if (open_file == NULL) - CIFSSMBClose(xid, tcon, netfid); + CIFSSMBClose(xid, tcon, fid.netfid); else cifsFileInfo_put(open_file); out: @@ -941,7 +949,8 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, { int rc; int oplock = 0; - __u16 netfid; + struct cifs_fid fid; + struct cifs_open_parms oparms; cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); @@ -957,21 +966,27 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, goto out; } - rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, - FILE_READ_ATTRIBUTES, OPEN_REPARSE_POINT, &netfid, - &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = FILE_READ_ATTRIBUTES; + oparms.create_options = OPEN_REPARSE_POINT; + oparms.disposition = FILE_OPEN; + oparms.path = full_path; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); if (rc) goto out; - rc = CIFSSMBQuerySymLink(xid, tcon, netfid, target_path, + rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path, cifs_sb->local_nls); if (rc) goto out_close; convert_delimiter(*target_path, '/'); out_close: - CIFSSMBClose(xid, tcon, netfid); + CIFSSMBClose(xid, tcon, fid.netfid); out: if (!rc) cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); -- cgit v1.2.3 From 666753c3ef8fc88b0ddd5be4865d0aa66428ac35 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 26 Jan 2014 23:53:43 -0600 Subject: [CIFS] Fix SMB2 mounts so they don't try to set or get xattrs via cifs When mounting with smb2 (or smb2.1 or smb3) we need to check to make sure that attempts to query or set extended attributes do not attempt to send the request with the older cifs protocol instead (eventually we also need to add the support in SMB2 to query/set extended attributes but this patch prevents us from using the wrong protocol for extended attribute operations). Signed-off-by: Steve French --- fs/cifs/cifsglob.h | 6 ++++++ fs/cifs/xattr.c | 49 ++++++++++++++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 61228b7f6b67..a245d1809ed8 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -389,6 +389,12 @@ struct smb_version_operations { struct cifsFileInfo *target_file, u64 src_off, u64 len, u64 dest_off); int (*validate_negotiate)(const unsigned int, struct cifs_tcon *); + ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *, + const unsigned char *, const unsigned char *, char *, + size_t, const struct nls_table *, int); + int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, + const char *, const void *, const __u16, + const struct nls_table *, int); }; struct smb_version_values { diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 09afda4cc58e..95c43bb20335 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -82,9 +82,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) goto remove_ea_exit; ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ - rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL, - (__u16)0, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + if (pTcon->ses->server->ops->set_EA) + rc = pTcon->ses->server->ops->set_EA(xid, pTcon, + full_path, ea_name, NULL, (__u16)0, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } remove_ea_exit: kfree(full_path); @@ -149,18 +151,22 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, cifs_dbg(FYI, "attempt to set cifs inode metadata\n"); ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ - rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, - (__u16)value_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + if (pTcon->ses->server->ops->set_EA) + rc = pTcon->ses->server->ops->set_EA(xid, pTcon, + full_path, ea_name, ea_value, (__u16)value_size, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto set_ea_exit; ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ - rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, - (__u16)value_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + if (pTcon->ses->server->ops->set_EA) + rc = pTcon->ses->server->ops->set_EA(xid, pTcon, + full_path, ea_name, ea_value, (__u16)value_size, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, strlen(CIFS_XATTR_CIFS_ACL)) == 0) { #ifdef CONFIG_CIFS_ACL @@ -272,17 +278,21 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, /* revalidate/getattr then populate from inode */ } /* BB add else when above is implemented */ ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ - rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, - buf_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + if (pTcon->ses->server->ops->query_all_EAs) + rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, + full_path, ea_name, ea_value, buf_size, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto get_ea_exit; ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ - rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, - buf_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + if (pTcon->ses->server->ops->query_all_EAs) + rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, + full_path, ea_name, ea_value, buf_size, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { #ifdef CONFIG_CIFS_POSIX @@ -400,11 +410,12 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) /* if proc/fs/cifs/streamstoxattr is set then search server for EAs or streams to returns as xattrs */ - rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data, - buf_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + if (pTcon->ses->server->ops->query_all_EAs) + rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, + full_path, NULL, data, buf_size, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); list_ea_exit: kfree(full_path); free_xid(xid); -- cgit v1.2.3 From a9a315d41407cd1079eb815f4adae897cc08b0d2 Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Fri, 31 Jan 2014 14:27:16 +0000 Subject: cifs: Fix check for regular file in couldbe_mf_symlink() MF Symlinks are regular files containing content in a specified format. The function couldbe_mf_symlink() checks the mode for a set S_IFREG bit as a test to confirm that it is a regular file. This bit is also set for other filetypes and simply checking for this bit being set may return false positives. We ensure that we are actually checking for a regular file by using the S_ISREG macro to test instead. Signed-off-by: Sachin Prabhu Reviewed-by: Jeff Layton Reported-by: Neil Brown Reported-by: Dan Carpenter Signed-off-by: Steve French --- fs/cifs/link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 52f41f9f7def..264ece71bdb2 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -185,7 +185,7 @@ format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str) bool couldbe_mf_symlink(const struct cifs_fattr *fattr) { - if (!(fattr->cf_mode & S_IFREG)) + if (!S_ISREG(fattr->cf_mode)) /* it's not a symlink */ return false; -- cgit v1.2.3