Commit 7ffec372 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

cifs: add refcounted and timestamped container for holding tcons

Eventually, we'll need to track the use of tcons on a per-sb basis, so that
we know when it's ok to tear them down. Begin this conversion by adding a
new "tcon_link" struct and accessors that get it. For now, the core data
structures are untouched -- cifs_sb still just points to a single tcon and
the pointers are just cast to deal with the accessor functions. A later
patch will flesh this out.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent f3983c21
...@@ -306,6 +306,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) ...@@ -306,6 +306,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
int xid, i; int xid, i;
int rc = 0; int rc = 0;
struct vfsmount *mnt = ERR_PTR(-ENOENT); struct vfsmount *mnt = ERR_PTR(-ENOENT);
struct tcon_link *tlink;
cFYI(1, "in %s", __func__); cFYI(1, "in %s", __func__);
BUG_ON(IS_ROOT(dentry)); BUG_ON(IS_ROOT(dentry));
...@@ -315,14 +316,6 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) ...@@ -315,14 +316,6 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
dput(nd->path.dentry); dput(nd->path.dentry);
nd->path.dentry = dget(dentry); 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;
goto out_err;
}
/* /*
* The MSDFS spec states that paths in DFS referral requests and * The MSDFS spec states that paths in DFS referral requests and
* responses must be prefixed by a single '\' character instead of * responses must be prefixed by a single '\' character instead of
...@@ -335,10 +328,20 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) ...@@ -335,10 +328,20 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
goto out_err; goto out_err;
} }
rc = get_dfs_path(xid, ses , full_path + 1, cifs_sb->local_nls, cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
rc = PTR_ERR(tlink);
goto out_err;
}
ses = tlink_tcon(tlink)->ses;
rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls,
&num_referrals, &referrals, &num_referrals, &referrals,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
cifs_put_tlink(tlink);
for (i = 0; i < num_referrals; i++) { for (i = 0; i < num_referrals; i++) {
int len; int len;
dump_referral(referrals+i); dump_referral(referrals+i);
......
...@@ -557,11 +557,16 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, ...@@ -557,11 +557,16 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
{ {
struct cifs_ntsd *pntsd = NULL; struct cifs_ntsd *pntsd = NULL;
int xid, rc; int xid, rc;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return NULL;
xid = GetXid(); xid = GetXid();
rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen); rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
return pntsd; return pntsd;
...@@ -574,10 +579,16 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, ...@@ -574,10 +579,16 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
int oplock = 0; int oplock = 0;
int xid, rc; int xid, rc;
__u16 fid; __u16 fid;
struct cifsTconInfo *tcon;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return NULL;
tcon = tlink_tcon(tlink);
xid = GetXid(); 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, &fid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) { if (rc) {
...@@ -585,11 +596,12 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, ...@@ -585,11 +596,12 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
goto out; 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); cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
CIFSSMBClose(xid, cifs_sb_tcon(cifs_sb), fid); CIFSSMBClose(xid, tcon, fid);
out: out:
cifs_put_tlink(tlink);
FreeXid(xid); FreeXid(xid);
return pntsd; return pntsd;
} }
...@@ -616,10 +628,15 @@ static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid, ...@@ -616,10 +628,15 @@ static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
struct cifs_ntsd *pnntsd, u32 acllen) struct cifs_ntsd *pnntsd, u32 acllen)
{ {
int xid, rc; int xid, rc;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
xid = GetXid(); xid = GetXid();
rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen); rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
cFYI(DBG2, "SetCIFSACL rc = %d", rc); cFYI(DBG2, "SetCIFSACL rc = %d", rc);
return rc; return rc;
...@@ -631,10 +648,16 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path, ...@@ -631,10 +648,16 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
int oplock = 0; int oplock = 0;
int xid, rc; int xid, rc;
__u16 fid; __u16 fid;
struct cifsTconInfo *tcon;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
tcon = tlink_tcon(tlink);
xid = GetXid(); 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, &fid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) { if (rc) {
...@@ -642,12 +665,13 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path, ...@@ -642,12 +665,13 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
goto out; 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); cFYI(DBG2, "SetCIFSACL rc = %d", rc);
CIFSSMBClose(xid, cifs_sb_tcon(cifs_sb), fid); CIFSSMBClose(xid, tcon, fid);
out: out:
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
return rc; return rc;
} }
......
...@@ -310,6 +310,44 @@ struct cifsTconInfo { ...@@ -310,6 +310,44 @@ struct cifsTconInfo {
/* BB add field for back pointer to sb struct(s)? */ /* BB add field for back pointer to sb struct(s)? */
}; };
/*
* This is a refcounted and timestamped container for a tcon pointer. The
* container holds a tcon reference. It is considered safe to free one of
* these when the tl_count goes to 0. The tl_time is the time of the last
* "get" on the container.
*/
struct tcon_link {
spinlock_t tl_lock;
u32 tl_count;
u64 tl_time;
struct cifsTconInfo *tl_tcon;
};
static inline struct tcon_link *
cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
{
return (struct tcon_link *)cifs_sb->ptcon;
}
static inline struct cifsTconInfo *
tlink_tcon(struct tcon_link *tlink)
{
return (struct cifsTconInfo *)tlink;
}
static inline void
cifs_put_tlink(struct tcon_link *tlink)
{
return;
}
/* This function is always expected to succeed */
static inline struct cifsTconInfo *
cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
{
return cifs_sb->ptcon;
}
/* /*
* This info hangs off the cifsFileInfo structure, pointed to by llist. * This info hangs off the cifsFileInfo structure, pointed to by llist.
* This is used to track byte stream locks on the file * This is used to track byte stream locks on the file
...@@ -413,19 +451,6 @@ CIFS_SB(struct super_block *sb) ...@@ -413,19 +451,6 @@ CIFS_SB(struct super_block *sb)
return sb->s_fs_info; return sb->s_fs_info;
} }
static inline struct cifsTconInfo *
cifs_sb_tcon(struct cifs_sb_info *cifs_sb)
{
return cifs_sb->ptcon;
}
/* This function is always expected to succeed */
static inline struct cifsTconInfo *
cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
{
return cifs_sb->ptcon;
}
static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb) static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
{ {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
......
...@@ -137,7 +137,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, ...@@ -137,7 +137,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
{ {
struct cifsFileInfo *pCifsFile; struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode; struct cifsInodeInfo *pCifsInode;
struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (pCifsFile == NULL) if (pCifsFile == NULL)
...@@ -191,7 +190,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode, ...@@ -191,7 +190,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
__u32 posix_flags = 0; __u32 posix_flags = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifs_fattr fattr; struct cifs_fattr fattr;
struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb); struct tcon_link *tlink;
struct cifsTconInfo *tcon;
cFYI(1, "posix open %s", full_path); cFYI(1, "posix open %s", full_path);
...@@ -226,10 +226,20 @@ int cifs_posix_open(char *full_path, struct inode **pinode, ...@@ -226,10 +226,20 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
posix_flags |= SMB_O_DIRECT; posix_flags |= SMB_O_DIRECT;
mode &= ~current_umask(); mode &= ~current_umask();
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
rc = PTR_ERR(tlink);
goto posix_open_ret;
}
tcon = tlink_tcon(tlink);
rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data, rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
poplock, full_path, cifs_sb->local_nls, poplock, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
cifs_put_tlink(tlink);
if (rc) if (rc)
goto posix_open_ret; goto posix_open_ret;
...@@ -290,6 +300,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -290,6 +300,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
int desiredAccess = GENERIC_READ | GENERIC_WRITE; int desiredAccess = GENERIC_READ | GENERIC_WRITE;
__u16 fileHandle; __u16 fileHandle;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
char *full_path = NULL; char *full_path = NULL;
FILE_ALL_INFO *buf = NULL; FILE_ALL_INFO *buf = NULL;
...@@ -299,13 +310,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -299,13 +310,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
xid = GetXid(); xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
tcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
full_path = build_path_from_dentry(direntry); FreeXid(xid);
if (full_path == NULL) { return PTR_ERR(tlink);
rc = -ENOMEM;
goto cifs_create_out;
} }
tcon = tlink_tcon(tlink);
if (oplockEnabled) if (oplockEnabled)
oplock = REQ_OPLOCK; oplock = REQ_OPLOCK;
...@@ -315,6 +325,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -315,6 +325,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
else else
oflags = FMODE_READ | SMB_O_CREAT; oflags = FMODE_READ | SMB_O_CREAT;
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
rc = -ENOMEM;
goto cifs_create_out;
}
if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_POSIX_PATH_OPS_CAP & (CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) { le64_to_cpu(tcon->fsUnixInfo.Capability))) {
...@@ -481,6 +497,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -481,6 +497,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
cifs_create_out: cifs_create_out:
kfree(buf); kfree(buf);
kfree(full_path); kfree(full_path);
cifs_put_tlink(tlink);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
...@@ -491,6 +508,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -491,6 +508,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
int rc = -EPERM; int rc = -EPERM;
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
struct inode *newinode = NULL; struct inode *newinode = NULL;
...@@ -503,10 +521,14 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -503,10 +521,14 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
if (!old_valid_dev(device_number)) if (!old_valid_dev(device_number))
return -EINVAL; return -EINVAL;
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
pTcon = tlink_tcon(tlink);
xid = GetXid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
...@@ -606,6 +628,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -606,6 +628,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
kfree(full_path); kfree(full_path);
kfree(buf); kfree(buf);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
return rc; return rc;
} }
...@@ -619,6 +642,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -619,6 +642,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
__u16 fileHandle = 0; __u16 fileHandle = 0;
bool posix_open = false; bool posix_open = false;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct cifsFileInfo *cfile; struct cifsFileInfo *cfile;
struct inode *newInode = NULL; struct inode *newInode = NULL;
...@@ -633,7 +657,12 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -633,7 +657,12 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
/* check whether path exists */ /* check whether path exists */
cifs_sb = CIFS_SB(parent_dir_inode->i_sb); cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
FreeXid(xid);
return (struct dentry *)tlink;
}
pTcon = tlink_tcon(tlink);
/* /*
* Don't allow the separator character in a path component. * Don't allow the separator character in a path component.
...@@ -644,8 +673,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -644,8 +673,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
for (i = 0; i < direntry->d_name.len; i++) for (i = 0; i < direntry->d_name.len; i++)
if (direntry->d_name.name[i] == '\\') { if (direntry->d_name.name[i] == '\\') {
cFYI(1, "Invalid file name"); cFYI(1, "Invalid file name");
FreeXid(xid); rc = -EINVAL;
return ERR_PTR(-EINVAL); goto lookup_out;
} }
} }
...@@ -655,7 +684,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -655,7 +684,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
*/ */
if (nd && (nd->flags & LOOKUP_EXCL)) { if (nd && (nd->flags & LOOKUP_EXCL)) {
d_instantiate(direntry, NULL); d_instantiate(direntry, NULL);
return NULL; rc = 0;
goto lookup_out;
} }
/* can not grab the rename sem here since it would /* can not grab the rename sem here since it would
...@@ -663,8 +693,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -663,8 +693,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
in which we already have the sb rename sem */ in which we already have the sb rename sem */
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
FreeXid(xid); rc = -ENOMEM;
return ERR_PTR(-ENOMEM); goto lookup_out;
} }
if (direntry->d_inode != NULL) { if (direntry->d_inode != NULL) {
...@@ -760,6 +790,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -760,6 +790,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
lookup_out: lookup_out:
kfree(full_path); kfree(full_path);
cifs_put_tlink(tlink);
FreeXid(xid); FreeXid(xid);
return ERR_PTR(rc); return ERR_PTR(rc);
} }
......
...@@ -224,6 +224,7 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -224,6 +224,7 @@ int cifs_open(struct inode *inode, struct file *file)
__u32 oplock; __u32 oplock;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
struct tcon_link *tlink;
struct cifsFileInfo *pCifsFile = NULL; struct cifsFileInfo *pCifsFile = NULL;
struct cifsInodeInfo *pCifsInode; struct cifsInodeInfo *pCifsInode;
char *full_path = NULL; char *full_path = NULL;
...@@ -235,7 +236,12 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -235,7 +236,12 @@ int cifs_open(struct inode *inode, struct file *file)
xid = GetXid(); xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
tcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
FreeXid(xid);
return PTR_ERR(tlink);
}
tcon = tlink_tcon(tlink);
pCifsInode = CIFS_I(file->f_path.dentry->d_inode); pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
...@@ -402,6 +408,7 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -402,6 +408,7 @@ int cifs_open(struct inode *inode, struct file *file)
kfree(buf); kfree(buf);
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
return rc; return rc;
} }
......
...@@ -313,16 +313,21 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -313,16 +313,21 @@ int cifs_get_inode_info_unix(struct inode **pinode,
FILE_UNIX_BASIC_INFO find_data; FILE_UNIX_BASIC_INFO find_data;
struct cifs_fattr fattr; struct cifs_fattr fattr;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
struct tcon_link *tlink;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
tcon = cifs_sb_tcon(cifs_sb);
cFYI(1, "Getting info on %s", full_path); cFYI(1, "Getting info on %s", full_path);
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
tcon = tlink_tcon(tlink);
/* could have done a find first instead but this returns more info */ /* could have done a find first instead but this returns more info */
rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
cifs_put_tlink(tlink);
if (!rc) { if (!rc) {
cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
...@@ -361,7 +366,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, ...@@ -361,7 +366,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
int rc; int rc;
int oplock = 0; int oplock = 0;
__u16 netfid; __u16 netfid;
struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb); struct tcon_link *tlink;
struct cifsTconInfo *tcon;
char buf[24]; char buf[24];
unsigned int bytes_read; unsigned int bytes_read;
char *pbuf; char *pbuf;
...@@ -380,7 +386,12 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, ...@@ -380,7 +386,12 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
return -EINVAL; /* EOPNOTSUPP? */ return -EINVAL; /* EOPNOTSUPP? */
} }
rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
tcon = tlink_tcon(tlink);
rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
CREATE_NOT_DIR, &netfid, &oplock, NULL, CREATE_NOT_DIR, &netfid, &oplock, NULL,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
...@@ -388,7 +399,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, ...@@ -388,7 +399,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
if (rc == 0) { if (rc == 0) {
int buf_type = CIFS_NO_BUFFER; int buf_type = CIFS_NO_BUFFER;
/* Read header */ /* Read header */
rc = CIFSSMBRead(xid, pTcon, netfid, rc = CIFSSMBRead(xid, tcon, netfid,
24 /* length */, 0 /* offset */, 24 /* length */, 0 /* offset */,
&bytes_read, &pbuf, &buf_type); &bytes_read, &pbuf, &buf_type);
if ((rc == 0) && (bytes_read >= 8)) { if ((rc == 0) && (bytes_read >= 8)) {
...@@ -430,8 +441,9 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, ...@@ -430,8 +441,9 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
fattr->cf_dtype = DT_REG; fattr->cf_dtype = DT_REG;
rc = -EOPNOTSUPP; /* or some unknown SFU type */ rc = -EOPNOTSUPP; /* or some unknown SFU type */
} }
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, tcon, netfid);
} }
cifs_put_tlink(tlink);
return rc; return rc;
} }
...@@ -449,11 +461,19 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, ...@@ -449,11 +461,19 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
ssize_t rc; ssize_t rc;
char ea_value[4]; char ea_value[4];
__u32 mode; __u32 mode;
struct tcon_link *tlink;
struct cifsTconInfo *tcon;
rc = CIFSSMBQAllEAs(xid, cifs_sb_tcon(cifs_sb), path, "SETFILEBITS", tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
tcon = tlink_tcon(tlink);
rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
ea_value, 4 /* size of buf */, cifs_sb->local_nls, ea_value, 4 /* size of buf */, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
cifs_put_tlink(tlink);
if (rc < 0) if (rc < 0)
return (int)rc; return (int)rc;
else if (rc > 3) { else if (rc > 3) {
...@@ -564,26 +584,33 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -564,26 +584,33 @@ int cifs_get_inode_info(struct inode **pinode,
{ {
int rc = 0, tmprc; int rc = 0, tmprc;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct tcon_link *tlink;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
char *buf = NULL; char *buf = NULL;
bool adjustTZ = false; bool adjustTZ = false;
struct cifs_fattr fattr; struct cifs_fattr fattr;
pTcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
pTcon = tlink_tcon(tlink);
cFYI(1, "Getting info on %s", full_path); cFYI(1, "Getting info on %s", full_path);
if ((pfindData == NULL) && (*pinode != NULL)) { if ((pfindData == NULL) && (*pinode != NULL)) {
if (CIFS_I(*pinode)->clientCanCacheRead) { if (CIFS_I(*pinode)->clientCanCacheRead) {
cFYI(1, "No need to revalidate cached inode sizes"); cFYI(1, "No need to revalidate cached inode sizes");
return rc; goto cgii_exit;
} }
} }
/* if file info not passed in then get it from server */ /* if file info not passed in then get it from server */
if (pfindData == NULL) { if (pfindData == NULL) {
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (buf == NULL) if (buf == NULL) {
return -ENOMEM; rc = -ENOMEM;
goto cgii_exit;
}
pfindData = (FILE_ALL_INFO *)buf; pfindData = (FILE_ALL_INFO *)buf;
/* could do find first instead but this returns more info */ /* could do find first instead but this returns more info */
...@@ -688,6 +715,7 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -688,6 +715,7 @@ int cifs_get_inode_info(struct inode **pinode,
cgii_exit: cgii_exit:
kfree(buf); kfree(buf);
cifs_put_tlink(tlink);
return rc; return rc;
} }
...@@ -895,6 +923,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, ...@@ -895,6 +923,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
struct cifsFileInfo *open_file; struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsInode = CIFS_I(inode); struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink = NULL;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
FILE_BASIC_INFO info_buf; FILE_BASIC_INFO info_buf;
...@@ -942,7 +971,13 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, ...@@ -942,7 +971,13 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
goto set_via_filehandle; goto set_via_filehandle;
} }
pTcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
rc = PTR_ERR(tlink);
tlink = NULL;
goto out;
}
pTcon = tlink_tcon(tlink);
/* /*
* NT4 apparently returns success on this call, but it doesn't * NT4 apparently returns success on this call, but it doesn't
...@@ -987,6 +1022,8 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, ...@@ -987,6 +1022,8 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
else else
cifsFileInfo_put(open_file); cifsFileInfo_put(open_file);
out: out:
if (tlink != NULL)
cifs_put_tlink(tlink);
return rc; return rc;
} }
...@@ -1004,10 +1041,16 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid) ...@@ -1004,10 +1041,16 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct cifsInodeInfo *cifsInode = CIFS_I(inode); struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb); struct tcon_link *tlink;
struct cifsTconInfo *tcon;
__u32 dosattr, origattr; __u32 dosattr, origattr;
FILE_BASIC_INFO *info_buf = NULL; FILE_BASIC_INFO *info_buf = NULL;
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
tcon = tlink_tcon(tlink);
rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
&netfid, &oplock, NULL, cifs_sb->local_nls, &netfid, &oplock, NULL, cifs_sb->local_nls,
...@@ -1076,6 +1119,7 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid) ...@@ -1076,6 +1119,7 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
CIFSSMBClose(xid, tcon, netfid); CIFSSMBClose(xid, tcon, netfid);
out: out:
kfree(info_buf); kfree(info_buf);
cifs_put_tlink(tlink);
return rc; return rc;
/* /*
...@@ -1115,12 +1159,18 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1115,12 +1159,18 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
struct cifsInodeInfo *cifs_inode; struct cifsInodeInfo *cifs_inode;
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb); struct tcon_link *tlink;
struct cifsTconInfo *tcon;
struct iattr *attrs = NULL; struct iattr *attrs = NULL;
__u32 dosattr = 0, origattr = 0; __u32 dosattr = 0, origattr = 0;
cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry);
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
tcon = tlink_tcon(tlink);
xid = GetXid(); xid = GetXid();
/* Unlink can be called from rename so we can not take the /* Unlink can be called from rename so we can not take the
...@@ -1128,8 +1178,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1128,8 +1178,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
full_path = build_path_from_dentry(dentry); full_path = build_path_from_dentry(dentry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
FreeXid(xid); goto unlink_out;
return rc;
} }
if ((tcon->ses->capabilities & CAP_UNIX) && if ((tcon->ses->capabilities & CAP_UNIX) &&
...@@ -1195,10 +1244,11 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1195,10 +1244,11 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
dir->i_ctime = dir->i_mtime = current_fs_time(sb); dir->i_ctime = dir->i_mtime = current_fs_time(sb);
cifs_inode = CIFS_I(dir); cifs_inode = CIFS_I(dir);
CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
unlink_out:
kfree(full_path); kfree(full_path);
kfree(attrs); kfree(attrs);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
return rc; return rc;
} }
...@@ -1207,6 +1257,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -1207,6 +1257,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
int rc = 0, tmprc; int rc = 0, tmprc;
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
struct inode *newinode = NULL; struct inode *newinode = NULL;
...@@ -1214,16 +1265,18 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -1214,16 +1265,18 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode); cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode);
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
pTcon = tlink_tcon(tlink);
xid = GetXid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
FreeXid(xid); goto mkdir_out;
return rc;
} }
if ((pTcon->ses->capabilities & CAP_UNIX) && if ((pTcon->ses->capabilities & CAP_UNIX) &&
...@@ -1381,6 +1434,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -1381,6 +1434,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
mkdir_out: mkdir_out:
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
return rc; return rc;
} }
...@@ -1389,6 +1443,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1389,6 +1443,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
int rc = 0; int rc = 0;
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
struct cifsInodeInfo *cifsInode; struct cifsInodeInfo *cifsInode;
...@@ -1397,18 +1452,23 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1397,18 +1452,23 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
xid = GetXid(); xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb);
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
FreeXid(xid); goto rmdir_exit;
return rc; }
cifs_sb = CIFS_SB(inode->i_sb);
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
rc = PTR_ERR(tlink);
goto rmdir_exit;
} }
pTcon = tlink_tcon(tlink);
rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
cifs_put_tlink(tlink);
if (!rc) { if (!rc) {
drop_nlink(inode); drop_nlink(inode);
...@@ -1429,6 +1489,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1429,6 +1489,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
current_fs_time(inode->i_sb); current_fs_time(inode->i_sb);
rmdir_exit:
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
...@@ -1439,10 +1500,16 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, ...@@ -1439,10 +1500,16 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
struct dentry *to_dentry, const char *toPath) struct dentry *to_dentry, const char *toPath)
{ {
struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb); struct tcon_link *tlink;
struct cifsTconInfo *pTcon;
__u16 srcfid; __u16 srcfid;
int oplock, rc; int oplock, rc;
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
pTcon = tlink_tcon(tlink);
/* try path-based rename first */ /* try path-based rename first */
rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
...@@ -1454,11 +1521,11 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, ...@@ -1454,11 +1521,11 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
* rename by filehandle to various Windows servers. * rename by filehandle to various Windows servers.
*/ */
if (rc == 0 || rc != -ETXTBSY) if (rc == 0 || rc != -ETXTBSY)
return rc; goto do_rename_exit;
/* open-file renames don't work across directories */ /* open-file renames don't work across directories */
if (to_dentry->d_parent != from_dentry->d_parent) if (to_dentry->d_parent != from_dentry->d_parent)
return rc; goto do_rename_exit;
/* open the file to be renamed -- we need DELETE perms */ /* open the file to be renamed -- we need DELETE perms */
rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
...@@ -1474,7 +1541,8 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, ...@@ -1474,7 +1541,8 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
CIFSSMBClose(xid, pTcon, srcfid); CIFSSMBClose(xid, pTcon, srcfid);
} }
do_rename_exit:
cifs_put_tlink(tlink);
return rc; return rc;
} }
...@@ -1484,13 +1552,17 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, ...@@ -1484,13 +1552,17 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
char *fromName = NULL; char *fromName = NULL;
char *toName = NULL; char *toName = NULL;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
FILE_UNIX_BASIC_INFO *info_buf_source = NULL; FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
FILE_UNIX_BASIC_INFO *info_buf_target; FILE_UNIX_BASIC_INFO *info_buf_target;
int xid, rc, tmprc; int xid, rc, tmprc;
cifs_sb = CIFS_SB(source_dir->i_sb); cifs_sb = CIFS_SB(source_dir->i_sb);
tcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
tcon = tlink_tcon(tlink);
xid = GetXid(); xid = GetXid();
...@@ -1566,6 +1638,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, ...@@ -1566,6 +1638,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
kfree(fromName); kfree(fromName);
kfree(toName); kfree(toName);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
return rc; return rc;
} }
...@@ -1728,6 +1801,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, ...@@ -1728,6 +1801,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
struct cifsFileInfo *open_file; struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsInode = CIFS_I(inode); struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink = NULL;
struct cifsTconInfo *pTcon = NULL; struct cifsTconInfo *pTcon = NULL;
/* /*
...@@ -1758,8 +1832,12 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, ...@@ -1758,8 +1832,12 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
rc = -EINVAL; rc = -EINVAL;
if (rc != 0) { if (rc != 0) {
if (pTcon == NULL) if (pTcon == NULL) {
pTcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
pTcon = tlink_tcon(tlink);
}
/* Set file size by pathname rather than by handle /* Set file size by pathname rather than by handle
either because no valid, writeable file handle for either because no valid, writeable file handle for
...@@ -1790,6 +1868,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, ...@@ -1790,6 +1868,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
} }
} }
if (tlink)
cifs_put_tlink(tlink);
} }
if (rc == 0) { if (rc == 0) {
...@@ -1810,6 +1890,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) ...@@ -1810,6 +1890,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
struct inode *inode = direntry->d_inode; struct inode *inode = direntry->d_inode;
struct cifsInodeInfo *cifsInode = CIFS_I(inode); struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct cifs_unix_set_info_args *args = NULL; struct cifs_unix_set_info_args *args = NULL;
struct cifsFileInfo *open_file; struct cifsFileInfo *open_file;
...@@ -1905,11 +1986,17 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) ...@@ -1905,11 +1986,17 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
cifsFileInfo_put(open_file); cifsFileInfo_put(open_file);
} else { } else {
pTcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
rc = PTR_ERR(tlink);
goto out;
}
pTcon = tlink_tcon(tlink);
rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
cifs_put_tlink(tlink);
} }
if (rc) if (rc)
......
...@@ -249,7 +249,8 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, ...@@ -249,7 +249,8 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
int rc; int rc;
int oplock = 0; int oplock = 0;
__u16 netfid = 0; __u16 netfid = 0;
struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb); struct tcon_link *tlink;
struct cifsTconInfo *pTcon;
u8 *buf; u8 *buf;
char *pbuf; char *pbuf;
unsigned int bytes_read = 0; unsigned int bytes_read = 0;
...@@ -261,23 +262,30 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, ...@@ -261,23 +262,30 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
/* it's not a symlink */ /* it's not a symlink */
return 0; return 0;
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, pTcon, path, FILE_OPEN, GENERIC_READ,
CREATE_NOT_DIR, &netfid, &oplock, &file_info, CREATE_NOT_DIR, &netfid, &oplock, &file_info,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc != 0) if (rc != 0)
return rc; goto out;
if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) { if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
/* it's not a symlink */ /* it's not a symlink */
return 0; goto out;
} }
buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
if (!buf) if (!buf) {
return -ENOMEM; rc = -ENOMEM;
goto out;
}
pbuf = buf; pbuf = buf;
rc = CIFSSMBRead(xid, pTcon, netfid, rc = CIFSSMBRead(xid, pTcon, netfid,
...@@ -287,23 +295,28 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, ...@@ -287,23 +295,28 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
if (rc != 0) { if (rc != 0) {
kfree(buf); kfree(buf);
return rc; goto out;
} }
rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
kfree(buf); kfree(buf);
if (rc == -EINVAL) if (rc == -EINVAL) {
/* it's not a symlink */ /* it's not a symlink */
return 0; rc = 0;
goto out;
}
if (rc != 0) if (rc != 0)
return rc; goto out;
/* it is a symlink */ /* it is a symlink */
fattr->cf_eof = link_len; fattr->cf_eof = link_len;
fattr->cf_mode &= ~S_IFMT; fattr->cf_mode &= ~S_IFMT;
fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
fattr->cf_dtype = DT_LNK; fattr->cf_dtype = DT_LNK;
return 0; out:
cifs_put_tlink(tlink);
return rc;
} }
int int
...@@ -314,17 +327,17 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -314,17 +327,17 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
int xid; int xid;
char *fromName = NULL; char *fromName = NULL;
char *toName = NULL; char *toName = NULL;
struct cifs_sb_info *cifs_sb_target; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct cifsInodeInfo *cifsInode; struct cifsInodeInfo *cifsInode;
xid = GetXid(); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
cifs_sb_target = CIFS_SB(inode->i_sb); return PTR_ERR(tlink);
pTcon = cifs_sb_tcon(cifs_sb_target); pTcon = tlink_tcon(tlink);
/* No need to check for cross device links since server will do that xid = GetXid();
BB note DFS case in future though (when we may have to check) */
fromName = build_path_from_dentry(old_file); fromName = build_path_from_dentry(old_file);
toName = build_path_from_dentry(direntry); toName = build_path_from_dentry(direntry);
...@@ -336,13 +349,13 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -336,13 +349,13 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
/* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/ /* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/
if (pTcon->unix_ext) if (pTcon->unix_ext)
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls, cifs_sb->local_nls,
cifs_sb_target->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
else { else {
rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls, cifs_sb->local_nls,
cifs_sb_target->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if ((rc == -EIO) || (rc == -EINVAL)) if ((rc == -EIO) || (rc == -EINVAL))
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
...@@ -378,6 +391,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -378,6 +391,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
kfree(fromName); kfree(fromName);
kfree(toName); kfree(toName);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
return rc; return rc;
} }
...@@ -390,10 +404,19 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) ...@@ -390,10 +404,19 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
char *full_path = NULL; char *full_path = NULL;
char *target_path = NULL; char *target_path = NULL;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb); struct tcon_link *tlink = NULL;
struct cifsTconInfo *tcon;
xid = GetXid(); xid = GetXid();
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
rc = PTR_ERR(tlink);
tlink = NULL;
goto out;
}
tcon = tlink_tcon(tlink);
/* /*
* For now, we just handle symlinks with unix extensions enabled. * For now, we just handle symlinks with unix extensions enabled.
* Eventually we should handle NTFS reparse points, and MacOS * Eventually we should handle NTFS reparse points, and MacOS
...@@ -442,6 +465,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) ...@@ -442,6 +465,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
} }
FreeXid(xid); FreeXid(xid);
if (tlink)
cifs_put_tlink(tlink);
nd_set_link(nd, target_path); nd_set_link(nd, target_path);
return NULL; return NULL;
} }
...@@ -451,22 +476,25 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) ...@@ -451,22 +476,25 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
{ {
int rc = -EOPNOTSUPP; int rc = -EOPNOTSUPP;
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
struct inode *newinode = NULL; struct inode *newinode = NULL;
xid = GetXid(); xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb); tlink = cifs_sb_tlink(cifs_sb);
pTcon = cifs_sb_tcon(cifs_sb); if (IS_ERR(tlink)) {
rc = PTR_ERR(tlink);
goto symlink_exit;
}
pTcon = tlink_tcon(tlink);
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
FreeXid(xid); goto symlink_exit;
return rc;
} }
cFYI(1, "Full path: %s", full_path); cFYI(1, "Full path: %s", full_path);
...@@ -504,8 +532,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) ...@@ -504,8 +532,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
d_instantiate(direntry, newinode); d_instantiate(direntry, newinode);
} }
} }
symlink_exit:
kfree(full_path); kfree(full_path);
cifs_put_tlink(tlink);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
......
...@@ -223,33 +223,35 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, ...@@ -223,33 +223,35 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
static int initiate_cifs_search(const int xid, struct file *file) static int initiate_cifs_search(const int xid, struct file *file)
{ {
int rc = 0; int rc = 0;
char *full_path; char *full_path = NULL;
struct cifsFileInfo *cifsFile; struct cifsFileInfo *cifsFile;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); tlink = cifs_sb_tlink(cifs_sb);
if (cifs_sb == NULL) if (IS_ERR(tlink))
return -EINVAL; return PTR_ERR(tlink);
pTcon = tlink_tcon(tlink);
if (file->private_data == NULL) if (file->private_data == NULL)
file->private_data = file->private_data =
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (file->private_data == NULL) {
rc = -ENOMEM;
goto error_exit;
}
if (file->private_data == NULL)
return -ENOMEM;
cifsFile = file->private_data; cifsFile = file->private_data;
cifsFile->invalidHandle = true; cifsFile->invalidHandle = true;
cifsFile->srch_inf.endOfSearch = false; 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); full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) {
if (full_path == NULL) rc = -ENOMEM;
return -ENOMEM; goto error_exit;
}
cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos); cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos);
...@@ -282,7 +284,9 @@ static int initiate_cifs_search(const int xid, struct file *file) ...@@ -282,7 +284,9 @@ static int initiate_cifs_search(const int xid, struct file *file)
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
goto ffirst_retry; goto ffirst_retry;
} }
error_exit:
kfree(full_path); kfree(full_path);
cifs_put_tlink(tlink);
return rc; return rc;
} }
......
...@@ -47,9 +47,10 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) ...@@ -47,9 +47,10 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
#ifdef CONFIG_CIFS_XATTR #ifdef CONFIG_CIFS_XATTR
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct super_block *sb; struct super_block *sb;
char *full_path; char *full_path = NULL;
if (direntry == NULL) if (direntry == NULL)
return -EIO; return -EIO;
...@@ -58,16 +59,19 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) ...@@ -58,16 +59,19 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
sb = direntry->d_inode->i_sb; sb = direntry->d_inode->i_sb;
if (sb == NULL) if (sb == NULL)
return -EIO; return -EIO;
xid = GetXid();
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
pTcon = tlink_tcon(tlink);
xid = GetXid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
FreeXid(xid); goto remove_ea_exit;
return rc;
} }
if (ea_name == NULL) { if (ea_name == NULL) {
cFYI(1, "Null xattr names not supported"); cFYI(1, "Null xattr names not supported");
...@@ -91,6 +95,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) ...@@ -91,6 +95,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
remove_ea_exit: remove_ea_exit:
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
#endif #endif
return rc; return rc;
} }
...@@ -102,6 +107,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, ...@@ -102,6 +107,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
#ifdef CONFIG_CIFS_XATTR #ifdef CONFIG_CIFS_XATTR
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct super_block *sb; struct super_block *sb;
char *full_path; char *full_path;
...@@ -113,16 +119,19 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, ...@@ -113,16 +119,19 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
sb = direntry->d_inode->i_sb; sb = direntry->d_inode->i_sb;
if (sb == NULL) if (sb == NULL)
return -EIO; return -EIO;
xid = GetXid();
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
pTcon = tlink_tcon(tlink);
xid = GetXid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
FreeXid(xid); goto set_ea_exit;
return rc;
} }
/* return dos attributes as pseudo xattr */ /* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */ /* return alt name if available as pseudo attr */
...@@ -132,9 +141,8 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, ...@@ -132,9 +141,8 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
returns as xattrs */ returns as xattrs */
if (value_size > MAX_EA_VALUE_SIZE) { if (value_size > MAX_EA_VALUE_SIZE) {
cFYI(1, "size of EA value too large"); cFYI(1, "size of EA value too large");
kfree(full_path); rc = -EOPNOTSUPP;
FreeXid(xid); goto set_ea_exit;
return -EOPNOTSUPP;
} }
if (ea_name == NULL) { if (ea_name == NULL) {
...@@ -198,6 +206,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, ...@@ -198,6 +206,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
set_ea_exit: set_ea_exit:
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
#endif #endif
return rc; return rc;
} }
...@@ -209,6 +218,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, ...@@ -209,6 +218,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
#ifdef CONFIG_CIFS_XATTR #ifdef CONFIG_CIFS_XATTR
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct super_block *sb; struct super_block *sb;
char *full_path; char *full_path;
...@@ -221,16 +231,18 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, ...@@ -221,16 +231,18 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
if (sb == NULL) if (sb == NULL)
return -EIO; return -EIO;
xid = GetXid();
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb_tcon(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
pTcon = tlink_tcon(tlink);
xid = GetXid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
FreeXid(xid); goto get_ea_exit;
return rc;
} }
/* return dos attributes as pseudo xattr */ /* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */ /* return alt name if available as pseudo attr */
...@@ -323,6 +335,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, ...@@ -323,6 +335,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
get_ea_exit: get_ea_exit:
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
#endif #endif
return rc; return rc;
} }
...@@ -333,6 +346,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) ...@@ -333,6 +346,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
#ifdef CONFIG_CIFS_XATTR #ifdef CONFIG_CIFS_XATTR
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct super_block *sb; struct super_block *sb;
char *full_path; char *full_path;
...@@ -346,18 +360,20 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) ...@@ -346,18 +360,20 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
return -EIO; return -EIO;
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb_tcon(cifs_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
return -EOPNOTSUPP; return -EOPNOTSUPP;
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
pTcon = tlink_tcon(tlink);
xid = GetXid(); xid = GetXid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
FreeXid(xid); goto list_ea_exit;
return rc;
} }
/* return dos attributes as pseudo xattr */ /* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */ /* return alt name if available as pseudo attr */
...@@ -370,8 +386,10 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) ...@@ -370,8 +386,10 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
list_ea_exit:
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
cifs_put_tlink(tlink);
#endif #endif
return rc; return rc;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment