cifs: add refcounted and timestamped container for holding tcons
[deliverable/linux.git] / fs / cifs / dir.c
index 23ec28a4c11fa5236032766cfae505bfdd769a03..bb3ea06ca6f4e2e39451aea77ec05010dba6889c 100644 (file)
@@ -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);
 }
This page took 0.026802 seconds and 5 git commands to generate.