Skip to content

Commit

Permalink
cifs: add refcounted and timestamped container for holding tcons
Browse files Browse the repository at this point in the history
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: Jeff Layton <[email protected]>
Signed-off-by: Steve French <[email protected]>
  • Loading branch information
jtlayton authored and Steve French committed Oct 6, 2010
1 parent f3983c2 commit 7ffec37
Show file tree
Hide file tree
Showing 9 changed files with 376 additions and 148 deletions.
21 changes: 12 additions & 9 deletions fs/cifs/cifs_dfs_ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
int xid, i;
int rc = 0;
struct vfsmount *mnt = ERR_PTR(-ENOENT);
struct tcon_link *tlink;

cFYI(1, "in %s", __func__);
BUG_ON(IS_ROOT(dentry));
Expand All @@ -315,14 +316,6 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
dput(nd->path.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
* responses must be prefixed by a single '\' character instead of
Expand All @@ -335,10 +328,20 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
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,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);

cifs_put_tlink(tlink);

for (i = 0; i < num_referrals; i++) {
int len;
dump_referral(referrals+i);
Expand Down
42 changes: 33 additions & 9 deletions fs/cifs/cifsacl.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,11 +557,16 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
{
struct cifs_ntsd *pntsd = NULL;
int xid, rc;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);

if (IS_ERR(tlink))
return NULL;

xid = GetXid();
rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen);
rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
FreeXid(xid);

cifs_put_tlink(tlink);

cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
return pntsd;
Expand All @@ -574,22 +579,29 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
int oplock = 0;
int xid, rc;
__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();

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) {
cERROR(1, "Unable to open file to get ACL");
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:
cifs_put_tlink(tlink);
FreeXid(xid);
return pntsd;
}
Expand All @@ -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)
{
int xid, rc;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);

if (IS_ERR(tlink))
return PTR_ERR(tlink);

xid = GetXid();
rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen);
rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen);
FreeXid(xid);
cifs_put_tlink(tlink);

cFYI(DBG2, "SetCIFSACL rc = %d", rc);
return rc;
Expand All @@ -631,23 +648,30 @@ 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;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);

if (IS_ERR(tlink))
return PTR_ERR(tlink);

tcon = tlink_tcon(tlink);
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) {
cERROR(1, "Unable to open file to set ACL");
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);
out:
CIFSSMBClose(xid, tcon, fid);
out:
FreeXid(xid);
cifs_put_tlink(tlink);
return rc;
}

Expand Down
51 changes: 38 additions & 13 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,44 @@ struct cifsTconInfo {
/* 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 is used to track byte stream locks on the file
Expand Down Expand Up @@ -413,19 +451,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->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)
{
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
Expand Down
65 changes: 48 additions & 17 deletions fs/cifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
{
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)
Expand Down Expand Up @@ -191,7 +190,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
__u32 posix_flags = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
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);

Expand Down Expand Up @@ -226,10 +226,20 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
posix_flags |= SMB_O_DIRECT;

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,
poplock, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
cifs_put_tlink(tlink);

if (rc)
goto posix_open_ret;

Expand Down Expand Up @@ -290,6 +300,7 @@ 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 tcon_link *tlink;
struct cifsTconInfo *tcon;
char *full_path = NULL;
FILE_ALL_INFO *buf = NULL;
Expand All @@ -299,13 +310,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
xid = GetXid();

cifs_sb = CIFS_SB(inode->i_sb);
tcon = cifs_sb_tcon(cifs_sb);

full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
rc = -ENOMEM;
goto cifs_create_out;
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
FreeXid(xid);
return PTR_ERR(tlink);
}
tcon = tlink_tcon(tlink);

if (oplockEnabled)
oplock = REQ_OPLOCK;
Expand All @@ -315,6 +325,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
else
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) &&
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Expand Down Expand Up @@ -481,6 +497,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
cifs_create_out:
kfree(buf);
kfree(full_path);
cifs_put_tlink(tlink);
FreeXid(xid);
return rc;
}
Expand All @@ -491,6 +508,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
int rc = -EPERM;
int xid;
struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *pTcon;
char *full_path = NULL;
struct inode *newinode = NULL;
Expand All @@ -503,10 +521,14 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
if (!old_valid_dev(device_number))
return -EINVAL;

xid = GetXid();

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);
if (full_path == NULL) {
Expand Down Expand Up @@ -606,6 +628,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
kfree(full_path);
kfree(buf);
FreeXid(xid);
cifs_put_tlink(tlink);
return rc;
}

Expand All @@ -619,6 +642,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
__u16 fileHandle = 0;
bool posix_open = false;
struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifsTconInfo *pTcon;
struct cifsFileInfo *cfile;
struct inode *newInode = NULL;
Expand All @@ -633,7 +657,12 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
/* check whether path exists */

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.
Expand All @@ -644,8 +673,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
for (i = 0; i < direntry->d_name.len; i++)
if (direntry->d_name.name[i] == '\\') {
cFYI(1, "Invalid file name");
FreeXid(xid);
return ERR_PTR(-EINVAL);
rc = -EINVAL;
goto lookup_out;
}
}

Expand All @@ -655,16 +684,17 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
*/
if (nd && (nd->flags & LOOKUP_EXCL)) {
d_instantiate(direntry, NULL);
return NULL;
rc = 0;
goto lookup_out;
}

/* can not grab the rename sem here since it would
deadlock in the cases (beginning of sys_rename itself)
in which we already have the sb rename sem */
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
FreeXid(xid);
return ERR_PTR(-ENOMEM);
rc = -ENOMEM;
goto lookup_out;
}

if (direntry->d_inode != NULL) {
Expand Down Expand Up @@ -760,6 +790,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,

lookup_out:
kfree(full_path);
cifs_put_tlink(tlink);
FreeXid(xid);
return ERR_PTR(rc);
}
Expand Down
Loading

0 comments on commit 7ffec37

Please sign in to comment.