[linux-cifs-client] [PATCH 07/11] cifs: allow for cifs_sb_tcon() to return an error
Jeff Layton
jlayton at redhat.com
Tue Apr 20 14:07:15 MDT 2010
Fix the callers to expect and handle it properly.
Signed-off-by: Jeff Layton <jlayton at redhat.com>
---
fs/cifs/cifs_dfs_ref.c | 10 ++--
fs/cifs/cifsacl.c | 32 ++++++++++---
fs/cifs/cifsfs.c | 69 ++++++++++------------------
fs/cifs/cifsglob.h | 6 --
fs/cifs/cifsproto.h | 5 ++-
fs/cifs/dir.c | 47 +++++++++++--------
fs/cifs/file.c | 12 +++--
fs/cifs/inode.c | 120 +++++++++++++++++++++++++++++++++++++----------
fs/cifs/link.c | 13 +++++-
fs/cifs/misc.c | 2 +-
fs/cifs/readdir.c | 12 +++--
fs/cifs/xattr.c | 23 +++++++++-
12 files changed, 229 insertions(+), 122 deletions(-)
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index fc7035a..f3edaf3 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -308,6 +308,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
struct dfs_info3_param *referrals = NULL;
unsigned int num_referrals = 0;
struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *tcon;
struct cifsSesInfo *ses;
char *full_path = NULL;
int xid, i;
@@ -323,13 +324,14 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
nd->path.dentry = dget(dentry);
cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
- ses = cifs_sb_tcon(cifs_sb)->ses;
-
- if (!ses) {
- rc = -EINVAL;
+ tcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
goto out_err;
}
+ ses = tcon->ses;
+
/*
* The MSDFS spec states that paths in DFS referral requests and
* responses must be prefixed by a single '\' character instead of
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index c2fb35c..673a0dc 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -556,10 +556,14 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
__u16 fid, u32 *pacllen)
{
struct cifs_ntsd *pntsd = NULL;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
int xid, rc;
+ if (IS_ERR(tcon))
+ return (struct cifs_ntsd *) tcon;
+
xid = GetXid();
- rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen);
+ rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
FreeXid(xid);
@@ -571,13 +575,17 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
const char *path, u32 *pacllen)
{
struct cifs_ntsd *pntsd = NULL;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
int oplock = 0;
int xid, rc;
__u16 fid;
+ if (IS_ERR(tcon))
+ return (struct cifs_ntsd *) tcon;
+
xid = GetXid();
- rc = CIFSSMBOpen(xid, cifs_sb_tcon(cifs_sb), path, FILE_OPEN, READ_CONTROL, 0,
+ rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
&fid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
@@ -585,10 +593,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
goto out;
}
- rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen);
+ rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
- CIFSSMBClose(xid, cifs_sb_tcon(cifs_sb), fid);
+ CIFSSMBClose(xid, tcon, fid);
out:
FreeXid(xid);
return pntsd;
@@ -616,9 +624,13 @@ static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
struct cifs_ntsd *pnntsd, u32 acllen)
{
int xid, rc;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen);
+ rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
FreeXid(xid);
cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
@@ -631,10 +643,14 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
int oplock = 0;
int xid, rc;
__u16 fid;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- rc = CIFSSMBOpen(xid, cifs_sb_tcon(cifs_sb), path, FILE_OPEN, WRITE_DAC, 0,
+ rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0,
&fid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
@@ -642,10 +658,10 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
goto out;
}
- rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen);
+ rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
- CIFSSMBClose(xid, cifs_sb_tcon(cifs_sb), fid);
+ CIFSSMBClose(xid, tcon, fid);
out:
FreeXid(xid);
return rc;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index b9ceec0..10137f4 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -102,6 +102,8 @@ cifs_read_super(struct super_block *sb, void *data,
cifs_sb = CIFS_SB(sb);
if (cifs_sb == NULL)
return -ENOMEM;
+ INIT_RADIX_TREE(&cifs_sb->tcon_tree, GFP_KERNEL);
+ spin_lock_init(&cifs_sb->tcon_tree_lock);
#ifdef CONFIG_CIFS_DFS_UPCALL
/* copy mount params to sb for use in submounts */
@@ -228,6 +230,9 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
int rc = -EOPNOTSUPP;
int xid;
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
+
xid = GetXid();
buf->f_type = CIFS_MAGIC_NUMBER;
@@ -359,7 +364,7 @@ static int
cifs_show_options(struct seq_file *s, struct vfsmount *m)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb);
- struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+ struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
seq_printf(s, ",unc=%s", tcon->treeName);
@@ -433,20 +438,13 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
-
- if (cifs_sb)
- pTcon = cifs_sb_tcon(cifs_sb);
- else
- return -EIO;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- if (pTcon) {
- cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
- } else
- rc = -EIO;
-
+ cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
FreeXid(xid);
return rc;
}
@@ -457,19 +455,13 @@ int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid,
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
- if (cifs_sb)
- pTcon = cifs_sb_tcon(cifs_sb);
- else
- return -EIO;
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- if (pTcon) {
- cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
- } else
- rc = -EIO;
-
+ cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
FreeXid(xid);
return rc;
}
@@ -479,19 +471,13 @@ int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation)
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
- if (cifs_sb)
- pTcon = cifs_sb_tcon(cifs_sb);
- else
- return -EIO;
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- if (pTcon) {
- cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
- } else
- rc = -EIO;
-
+ cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
FreeXid(xid);
return rc;
}
@@ -501,19 +487,13 @@ int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats)
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
- if (cifs_sb)
- pTcon = cifs_sb_tcon(cifs_sb);
- else
- return -EIO;
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- if (pTcon) {
- cFYI(1, ("pqstats %p", qstats));
- } else
- rc = -EIO;
-
+ cFYI(1, ("pqstats %p", qstats));
FreeXid(xid);
return rc;
}
@@ -534,9 +514,8 @@ static void cifs_umount_begin(struct super_block *sb)
if (cifs_sb == NULL)
return;
- tcon = cifs_sb_tcon(cifs_sb);
- if (tcon == NULL)
- return;
+ /* FIXME: handle multisession case properly */
+ tcon = cifs_sb_master_tcon(cifs_sb);
read_lock(&cifs_tcp_ses_lock);
if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index ca9dd9d..2e3c489 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -401,12 +401,6 @@ CIFS_SB(struct super_block *sb)
return sb->s_fs_info;
}
-static inline struct cifsTconInfo *
-cifs_sb_tcon(struct cifs_sb_info *cifs_sb)
-{
- return cifs_sb->tcon;
-}
-
static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
{
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index ca341fc..301566e 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -92,7 +92,8 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
__u16 fileHandle, struct file *file,
- struct vfsmount *mnt, unsigned int oflags);
+ struct vfsmount *mnt, struct cifsTconInfo *tcon,
+ unsigned int oflags);
extern int cifs_posix_open(char *full_path, struct inode **pinode,
struct vfsmount *mnt, int mode, int oflags,
__u32 *poplock, __u16 *pnetfid, int xid);
@@ -117,6 +118,8 @@ extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
const char *path, const __u16 *pfid);
extern int mode_to_acl(struct inode *inode, const char *path, __u64);
+extern struct cifsTconInfo *cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb);
+extern struct cifsTconInfo *cifs_sb_tcon(struct cifs_sb_info *cifs_sb);
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
const char *);
extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 05ee024..90184cd 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -53,18 +53,19 @@ build_path_from_dentry(struct dentry *direntry)
int dfsplen;
char *full_path;
char dirsep;
- struct cifs_sb_info *cifs_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+ struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
+ /* FIXME: this is racy -- need to take proper references */
if (direntry == NULL)
return NULL; /* not much we can do if dentry is freed and
we need to reopen the file after it was closed implicitly
when the server crashed */
- cifs_sb = CIFS_SB(direntry->d_sb);
dirsep = CIFS_DIR_SEP(cifs_sb);
pplen = cifs_sb->prepathlen;
- if (cifs_sb_tcon(cifs_sb) && (cifs_sb_tcon(cifs_sb)->Flags & SMB_SHARE_IS_IN_DFS))
- dfsplen = strnlen(cifs_sb_tcon(cifs_sb)->treeName, MAX_TREE_SIZE + 1);
+ if (tcon && (tcon->Flags & SMB_SHARE_IS_IN_DFS))
+ dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
else
dfsplen = 0;
cifs_bp_rename_retry:
@@ -117,7 +118,7 @@ cifs_bp_rename_retry:
/* BB test paths to Windows with '/' in the midst of prepath */
if (dfsplen) {
- strncpy(full_path, cifs_sb_tcon(cifs_sb)->treeName, dfsplen);
+ strncpy(full_path, tcon->treeName, dfsplen);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
int i;
for (i = 0; i < dfsplen; i++) {
@@ -126,7 +127,7 @@ cifs_bp_rename_retry:
}
}
}
- strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
+ strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
return full_path;
}
@@ -138,7 +139,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
int oplock = 0;
struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode;
- struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (pCifsFile == NULL)
@@ -163,7 +163,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops);
write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist, &cifs_sb_tcon(cifs_sb)->openFileList);
+ list_add(&pCifsFile->tlist, &tcon->openFileList);
pCifsInode = CIFS_I(newinode);
if (pCifsInode) {
/* if readable file instance put first in list*/
@@ -193,14 +193,17 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
FILE_UNIX_BASIC_INFO *presp_data;
__u32 posix_flags = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
- struct cifs_fattr fattr;
struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+ struct cifs_fattr fattr;
if (IS_ERR(tcon))
return PTR_ERR(tcon);
cFYI(1, ("posix open %s", full_path));
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
+
presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
if (presp_data == NULL)
return -ENOMEM;
@@ -297,17 +300,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
*/
int desiredAccess = GENERIC_READ | GENERIC_WRITE;
__u16 fileHandle;
- struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *tcon;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
char *full_path = NULL;
FILE_ALL_INFO *buf = NULL;
struct inode *newinode = NULL;
int disposition = FILE_OVERWRITE_IF;
- xid = GetXid();
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
- cifs_sb = CIFS_SB(inode->i_sb);
- tcon = cifs_sb_tcon(cifs_sb);
+ xid = GetXid();
if (IS_ERR(tcon)) {
FreeXid(xid);
@@ -390,7 +393,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
create_options |= CREATE_OPTION_READONLY;
- if (cifs_sb_tcon(cifs_sb)->ses->capabilities & CAP_NT_SMBS)
+ if (tcon->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
desiredAccess, create_options,
&fileHandle, &oplock, buf, cifs_sb->local_nls,
@@ -491,18 +494,18 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
{
int rc = -EPERM;
int xid;
- struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *pTcon;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
char *full_path = NULL;
struct inode *newinode = NULL;
if (!old_valid_dev(device_number))
return -EINVAL;
- xid = GetXid();
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
- cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb_tcon(cifs_sb);
+ xid = GetXid();
full_path = build_path_from_dentry(direntry);
if (full_path == NULL)
@@ -635,6 +638,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ FreeXid(xid);
+ return (struct dentry *) pTcon;
+ }
/*
* Don't allow the separator character in a path component.
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 26665b8..b56913a 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -265,9 +265,9 @@ int cifs_open(struct inode *inode, struct file *file)
__u16 netfid;
FILE_ALL_INFO *buf = NULL;
- xid = GetXid();
-
cifs_sb = CIFS_SB(inode->i_sb);
+
+ xid = GetXid();
tcon = cifs_sb_tcon(cifs_sb);
if (IS_ERR(tcon)) {
FreeXid(xid);
@@ -374,7 +374,7 @@ int cifs_open(struct inode *inode, struct file *file)
goto out;
}
- if (cifs_sb_tcon(cifs_sb)->ses->capabilities & CAP_NT_SMBS)
+ if (tcon->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
@@ -1399,6 +1399,7 @@ static int cifs_writepages(struct address_space *mapping,
int xid, long_op;
cifs_sb = CIFS_SB(mapping->host->i_sb);
+ tcon = cifs_sb_master_tcon(cifs_sb);
/*
* If wsize is smaller that the page cache size, default to writing
@@ -1407,7 +1408,10 @@ static int cifs_writepages(struct address_space *mapping,
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
return generic_writepages(mapping, wbc);
- if (cifs_sb_tcon(cifs_sb)->ses->sign && !experimEnabled)
+ /* FIXME: not quite right -- we need to determine this once we know
+ * what tcon we're going to use.
+ */
+ if (tcon->ses->sign && !experimEnabled)
return generic_writepages(mapping, wbc);
iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index e21feaa..100ad85 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -51,7 +51,7 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
/* check if server can support readpages */
- if (cifs_sb_tcon(cifs_sb)->ses->server->maxBuf <
+ if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else
@@ -301,12 +301,14 @@ int cifs_get_inode_info_unix(struct inode **pinode,
int rc;
FILE_UNIX_BASIC_INFO find_data;
struct cifs_fattr fattr;
- struct cifsTconInfo *tcon;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
- tcon = cifs_sb_tcon(cifs_sb);
cFYI(1, ("Getting info on %s", full_path));
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
+
/* could have done a find first instead but this returns more info */
rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -341,11 +343,14 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
int rc;
int oplock = 0;
__u16 netfid;
- struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
char buf[24];
unsigned int bytes_read;
char *pbuf;
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
+
pbuf = buf;
fattr->cf_mode &= ~S_IFMT;
@@ -360,7 +365,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
return -EINVAL; /* EOPNOTSUPP? */
}
- rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
+ rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
CREATE_NOT_DIR, &netfid, &oplock, NULL,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
@@ -368,7 +373,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, pTcon, netfid,
+ rc = CIFSSMBRead(xid, tcon, netfid,
24 /* length */, 0 /* offset */,
&bytes_read, &pbuf, &buf_type);
if ((rc == 0) && (bytes_read >= 8)) {
@@ -410,7 +415,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
fattr->cf_dtype = DT_REG;
rc = -EOPNOTSUPP; /* or some unknown SFU type */
}
- CIFSSMBClose(xid, pTcon, netfid);
+ CIFSSMBClose(xid, tcon, netfid);
}
return rc;
}
@@ -429,8 +434,12 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
ssize_t rc;
char ea_value[4];
__u32 mode;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
- rc = CIFSSMBQAllEAs(xid, cifs_sb_tcon(cifs_sb), path, "SETFILEBITS",
+ rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
ea_value, 4 /* size of buf */, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -456,6 +465,8 @@ static void
cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
struct cifs_sb_info *cifs_sb, bool adjust_tz)
{
+ struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
+
memset(fattr, 0, sizeof(*fattr));
fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
if (info->DeletePending)
@@ -470,8 +481,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
if (adjust_tz) {
- fattr->cf_ctime.tv_sec += cifs_sb_tcon(cifs_sb)->ses->server->timeAdj;
- fattr->cf_mtime.tv_sec += cifs_sb_tcon(cifs_sb)->ses->server->timeAdj;
+ fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
+ fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
}
fattr->cf_eof = le64_to_cpu(info->EndOfFile);
@@ -541,15 +552,17 @@ int cifs_get_inode_info(struct inode **pinode,
struct super_block *sb, int xid, const __u16 *pfid)
{
int rc = 0, tmprc;
- struct cifsTconInfo *pTcon;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
char *buf = NULL;
bool adjustTZ = false;
struct cifs_fattr fattr;
- pTcon = cifs_sb_tcon(cifs_sb);
cFYI(1, ("Getting info on %s", full_path));
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
+
if ((pfindData == NULL) && (*pinode != NULL)) {
if (CIFS_I(*pinode)->clientCanCacheRead) {
cFYI(1, ("No need to revalidate cached inode sizes"));
@@ -671,6 +684,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
int pplen = cifs_sb->prepathlen;
int dfsplen;
char *full_path = NULL;
+ struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
/* if no prefix path, simply set path to the root of share to "" */
if (pplen == 0) {
@@ -680,8 +694,8 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
return full_path;
}
- if (cifs_sb_tcon(cifs_sb) && (cifs_sb_tcon(cifs_sb)->Flags & SMB_SHARE_IS_IN_DFS))
- dfsplen = strnlen(cifs_sb_tcon(cifs_sb)->treeName, MAX_TREE_SIZE + 1);
+ if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
+ dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
else
dfsplen = 0;
@@ -690,7 +704,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
return full_path;
if (dfsplen) {
- strncpy(full_path, cifs_sb_tcon(cifs_sb)->treeName, dfsplen);
+ strncpy(full_path, tcon->treeName, dfsplen);
/* switch slash direction in prepath depending on whether
* windows or posix style path names
*/
@@ -759,18 +773,21 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
{
int xid;
- struct cifs_sb_info *cifs_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
struct inode *inode = NULL;
long rc;
char *full_path;
- cifs_sb = CIFS_SB(sb);
+ if (IS_ERR(tcon))
+ return (struct inode *) tcon;
+
full_path = cifs_build_path_to_root(cifs_sb);
if (full_path == NULL)
return ERR_PTR(-ENOMEM);
xid = GetXid();
- if (cifs_sb_tcon(cifs_sb)->unix_ext)
+ if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
else
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
@@ -779,7 +796,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
if (!inode)
return ERR_PTR(-ENOMEM);
- if (rc && cifs_sb_tcon(cifs_sb)->ipc) {
+ if (rc && tcon->ipc) {
cFYI(1, ("ipc connection - fake read inode"));
inode->i_mode |= S_IFDIR;
inode->i_nlink = 2;
@@ -862,7 +879,11 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
goto set_via_filehandle;
}
- pTcon = open_file->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ goto out;
+ }
/*
* NT4 apparently returns success on this call, but it doesn't
@@ -928,6 +949,11 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
__u32 dosattr, origattr;
FILE_BASIC_INFO *info_buf = NULL;
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ goto out;
+ }
+
rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
&netfid, &oplock, NULL, cifs_sb->local_nls,
@@ -1042,6 +1068,11 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry));
xid = GetXid();
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ FreeXid(xid);
+ return rc;
+ }
/* Unlink can be called from rename so we can not take the
* sb->s_vfs_rename_mutex here */
@@ -1138,6 +1169,11 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -1318,6 +1354,11 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -1362,6 +1403,9 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
__u16 srcfid;
int oplock, rc;
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
+
/* try path-based rename first */
rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
@@ -1400,14 +1444,21 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
char *toName = NULL;
struct cifs_sb_info *cifs_sb_source;
struct cifs_sb_info *cifs_sb_target;
- struct cifsTconInfo *tcon;
+ struct cifsTconInfo *source_tcon, *target_tcon;
FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
FILE_UNIX_BASIC_INFO *info_buf_target;
int xid, rc, tmprc;
cifs_sb_target = CIFS_SB(target_dir->i_sb);
cifs_sb_source = CIFS_SB(source_dir->i_sb);
- tcon = cifs_sb_tcon(cifs_sb_source);
+ source_tcon = cifs_sb_tcon(cifs_sb_source);
+ target_tcon = cifs_sb_tcon(cifs_sb_target);
+
+ if (IS_ERR(source_tcon))
+ return PTR_ERR(source_tcon);
+
+ if (IS_ERR(target_tcon))
+ return PTR_ERR(target_tcon);
xid = GetXid();
@@ -1415,7 +1466,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
* BB: this might be allowed if same server, but different share.
* Consider adding support for this
*/
- if (tcon != cifs_sb_tcon(cifs_sb_target)) {
+ if (source_tcon != target_tcon) {
rc = -EXDEV;
goto cifs_rename_exit;
}
@@ -1439,7 +1490,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
rc = cifs_do_rename(xid, source_dentry, fromName,
target_dentry, toName);
- if (rc == -EEXIST && tcon->unix_ext) {
+ if (rc == -EEXIST && source_tcon->unix_ext) {
/*
* Are src and dst hardlinks of same inode? We can
* only tell with unix extensions enabled
@@ -1453,7 +1504,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
}
info_buf_target = info_buf_source + 1;
- tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
+ tmprc = CIFSSMBUnixQPathInfo(xid, source_tcon, fromName,
info_buf_source,
cifs_sb_source->local_nls,
cifs_sb_source->mnt_cifs_flags &
@@ -1461,7 +1512,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
if (tmprc != 0)
goto unlink_target;
- tmprc = CIFSSMBUnixQPathInfo(xid, tcon,
+ tmprc = CIFSSMBUnixQPathInfo(xid, source_tcon,
toName, info_buf_target,
cifs_sb_target->local_nls,
/* remap based on source sb */
@@ -1564,12 +1615,19 @@ int cifs_revalidate_dentry(struct dentry *dentry)
char *full_path = NULL;
struct inode *inode = dentry->d_inode;
struct super_block *sb = dentry->d_sb;
+ struct cifsTconInfo *tcon;
if (inode == NULL)
return -ENOENT;
xid = GetXid();
+ tcon = cifs_sb_tcon(CIFS_SB(sb));
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ goto check_inval;
+ }
+
if (!cifs_inode_needs_reval(inode))
goto check_inval;
@@ -1692,6 +1750,9 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
if (pTcon == NULL)
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
+
/* Set file size by pathname rather than by handle
either because no valid, writeable file handle for
it was found or because there was an error setting
@@ -1839,6 +1900,10 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
cifsFileInfo_put(open_file);
} else {
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ goto out;
+ }
rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
@@ -2011,6 +2076,9 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
+
if (pTcon->unix_ext)
return cifs_setattr_unix(direntry, attrs);
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index deff001..72be30c 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -45,6 +45,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
cifs_sb_target = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb_target);
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
/* No need to check for cross device links since server will do that
BB note DFS case in future though (when we may have to check) */
@@ -117,6 +119,11 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
xid = GetXid();
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ goto out;
+ }
+
/*
* For now, we just handle symlinks with unix extensions enabled.
* Eventually we should handle NTFS reparse points, and MacOS
@@ -169,9 +176,13 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
-
if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 789cf12..28cfccd 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -724,6 +724,6 @@ cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
"properly. Hardlinks will not be recognized on this "
"mount. Consider mounting with the \"noserverino\" "
"option to silence this message.",
- cifs_sb_tcon(cifs_sb)->treeName));
+ cifs_sb_master_tcon(cifs_sb)->treeName));
}
}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 17effab..10b987b 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -102,7 +102,7 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
return NULL;
}
- if (cifs_sb_tcon(CIFS_SB(sb))->nocase)
+ if (cifs_sb_master_tcon(CIFS_SB(sb))->nocase)
dentry->d_op = &cifs_ci_dentry_ops;
else
dentry->d_op = &cifs_dentry_ops;
@@ -171,7 +171,7 @@ static void
cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
struct cifs_sb_info *cifs_sb)
{
- int offset = cifs_sb_tcon(cifs_sb)->ses->server->timeAdj;
+ int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj;
memset(fattr, 0, sizeof(*fattr));
fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
@@ -232,6 +232,10 @@ static int initiate_cifs_search(const int xid, struct file *file)
if (cifs_sb == NULL)
return -EINVAL;
+ pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
+
if (file->private_data == NULL)
file->private_data =
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
@@ -241,11 +245,9 @@ static int initiate_cifs_search(const int xid, struct file *file)
cifsFile = file->private_data;
cifsFile->invalidHandle = true;
cifsFile->srch_inf.endOfSearch = false;
- cifsFile->tcon = cifs_sb_tcon(cifs_sb);
+ cifsFile->tcon = pTcon;
pTcon = cifsFile->tcon;
- if (pTcon == NULL)
- return -EINVAL;
full_path = build_path_from_dentry(file->f_path.dentry);
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 2161019..77ee3b6 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -62,6 +62,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -117,6 +122,11 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -225,6 +235,11 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -346,13 +361,19 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
return -EIO;
cifs_sb = CIFS_SB(sb);
- pTcon = cifs_sb_tcon(cifs_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
return -EOPNOTSUPP;
xid = GetXid();
+ pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
+
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
rc = -ENOMEM;
--
1.6.6.1
More information about the linux-cifs-client
mailing list