diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-09-29 19:51:11 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-10-06 16:12:44 +0000 |
commit | 7ffec372458d163492e56e663a1b3a2d7be0a0a2 (patch) | |
tree | e404e3d1000ff41e9b27d0ecb4d6a47187e110d7 /fs/cifs/dir.c | |
parent | f3983c2133e9bea9c8b4f690737d15e3e9b02491 (diff) | |
download | linux-7ffec372458d163492e56e663a1b3a2d7be0a0a2.tar.gz linux-7ffec372458d163492e56e663a1b3a2d7be0a0a2.tar.bz2 linux-7ffec372458d163492e56e663a1b3a2d7be0a0a2.zip |
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: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 23ec28a4c11f..bb3ea06ca6f4 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -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) @@ -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); @@ -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; @@ -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; @@ -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; @@ -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))) { @@ -481,6 +497,7 @@ cifs_create_set_dentry: cifs_create_out: kfree(buf); kfree(full_path); + cifs_put_tlink(tlink); FreeXid(xid); return rc; } @@ -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; @@ -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) { @@ -606,6 +628,7 @@ mknod_out: kfree(full_path); kfree(buf); FreeXid(xid); + cifs_put_tlink(tlink); return rc; } @@ -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; @@ -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. @@ -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; } } @@ -655,7 +684,8 @@ 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 @@ -663,8 +693,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, 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) { @@ -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); } |