cifs: move tcon find/create into separate function
authorJeff Layton <jlayton@redhat.com>
Sat, 24 Apr 2010 11:57:44 +0000 (07:57 -0400)
committerSteve French <sfrench@us.ibm.com>
Mon, 26 Apr 2010 18:55:31 +0000 (18:55 +0000)
...and out of cifs_mount.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/connect.c

index 74c222e..c104f54 100644 (file)
@@ -1749,6 +1749,7 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
        int xid;
        struct cifsSesInfo *ses = tcon->ses;
 
+       cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
        write_lock(&cifs_tcp_ses_lock);
        if (--tcon->tc_count > 0) {
                write_unlock(&cifs_tcp_ses_lock);
@@ -1766,6 +1767,80 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
        cifs_put_smb_ses(ses);
 }
 
+static struct cifsTconInfo *
+cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info)
+{
+       int rc, xid;
+       struct cifsTconInfo *tcon;
+
+       tcon = cifs_find_tcon(ses, volume_info->UNC);
+       if (tcon) {
+               cFYI(1, "Found match on UNC path");
+               /* existing tcon already has a reference */
+               cifs_put_smb_ses(ses);
+               if (tcon->seal != volume_info->seal)
+                       cERROR(1, "transport encryption setting "
+                                  "conflicts with existing tid");
+               return tcon;
+       }
+
+       tcon = tconInfoAlloc();
+       if (tcon == NULL) {
+               rc = -ENOMEM;
+               goto out_fail;
+       }
+
+       tcon->ses = ses;
+       if (volume_info->password) {
+               tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
+               if (!tcon->password) {
+                       rc = -ENOMEM;
+                       goto out_fail;
+               }
+       }
+
+       if (strchr(volume_info->UNC + 3, '\\') == NULL
+           && strchr(volume_info->UNC + 3, '/') == NULL) {
+               cERROR(1, "Missing share name");
+               rc = -ENODEV;
+               goto out_fail;
+       }
+
+       /* BB Do we need to wrap session_mutex around
+        * this TCon call and Unix SetFS as
+        * we do on SessSetup and reconnect? */
+       xid = GetXid();
+       rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
+       FreeXid(xid);
+       cFYI(1, "CIFS Tcon rc = %d", rc);
+       if (rc)
+               goto out_fail;
+
+       if (volume_info->nodfs) {
+               tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
+               cFYI(1, "DFS disabled (%d)", tcon->Flags);
+       }
+       tcon->seal = volume_info->seal;
+       /* we can have only one retry value for a connection
+          to a share so for resources mounted more than once
+          to the same server share the last value passed in
+          for the retry flag is used */
+       tcon->retry = volume_info->retry;
+       tcon->nocase = volume_info->nocase;
+       tcon->local_lease = volume_info->local_lease;
+
+       write_lock(&cifs_tcp_ses_lock);
+       list_add(&tcon->tcon_list, &ses->tcon_list);
+       write_unlock(&cifs_tcp_ses_lock);
+
+       return tcon;
+
+out_fail:
+       tconInfoFree(tcon);
+       return ERR_PTR(rc);
+}
+
+
 int
 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
             const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
@@ -2471,81 +2546,22 @@ try_mount_again:
                goto mount_fail_check;
        }
 
-       /* search for existing tcon to this server share */
-       if (!rc) {
-               setup_cifs_sb(volume_info, cifs_sb);
-
-               tcon = cifs_find_tcon(pSesInfo, volume_info->UNC);
-               if (tcon) {
-                       cFYI(1, "Found match on UNC path");
-                       /* existing tcon already has a reference */
-                       cifs_put_smb_ses(pSesInfo);
-                       if (tcon->seal != volume_info->seal)
-                               cERROR(1, "transport encryption setting "
-                                          "conflicts with existing tid");
-               } else {
-                       tcon = tconInfoAlloc();
-                       if (tcon == NULL) {
-                               rc = -ENOMEM;
-                               goto mount_fail_check;
-                       }
-
-                       tcon->ses = pSesInfo;
-                       if (volume_info->password) {
-                               tcon->password = kstrdup(volume_info->password,
-                                                        GFP_KERNEL);
-                               if (!tcon->password) {
-                                       rc = -ENOMEM;
-                                       goto mount_fail_check;
-                               }
-                       }
-
-                       if ((strchr(volume_info->UNC + 3, '\\') == NULL)
-                           && (strchr(volume_info->UNC + 3, '/') == NULL)) {
-                               cERROR(1, "Missing share name");
-                               rc = -ENODEV;
-                               goto mount_fail_check;
-                       } else {
-                               /* BB Do we need to wrap sesSem around
-                                * this TCon call and Unix SetFS as
-                                * we do on SessSetup and reconnect? */
-                               rc = CIFSTCon(xid, pSesInfo, volume_info->UNC,
-                                             tcon, cifs_sb->local_nls);
-                               cFYI(1, "CIFS Tcon rc = %d", rc);
-                               if (volume_info->nodfs) {
-                                       tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
-                                       cFYI(1, "DFS disabled (%d)",
-                                               tcon->Flags);
-                               }
-                       }
-                       if (rc)
-                               goto remote_path_check;
-                       tcon->seal = volume_info->seal;
-                       write_lock(&cifs_tcp_ses_lock);
-                       list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
-                       write_unlock(&cifs_tcp_ses_lock);
-               }
-
-               /* we can have only one retry value for a connection
-                  to a share so for resources mounted more than once
-                  to the same server share the last value passed in
-                  for the retry flag is used */
-               tcon->retry = volume_info->retry;
-               tcon->nocase = volume_info->nocase;
-               tcon->local_lease = volume_info->local_lease;
-       }
-       if (pSesInfo) {
-               if (pSesInfo->capabilities & CAP_LARGE_FILES)
-                       sb->s_maxbytes = MAX_LFS_FILESIZE;
-               else
-                       sb->s_maxbytes = MAX_NON_LFS;
-       }
+       setup_cifs_sb(volume_info, cifs_sb);
+       if (pSesInfo->capabilities & CAP_LARGE_FILES)
+               sb->s_maxbytes = MAX_LFS_FILESIZE;
+       else
+               sb->s_maxbytes = MAX_NON_LFS;
 
        /* BB FIXME fix time_gran to be larger for LANMAN sessions */
        sb->s_time_gran = 100;
 
-       if (rc)
+       /* search for existing tcon to this server share */
+       tcon = cifs_get_tcon(pSesInfo, volume_info);
+       if (IS_ERR(tcon)) {
+               rc = PTR_ERR(tcon);
+               tcon = NULL;
                goto remote_path_check;
+       }
 
        cifs_sb->tcon = tcon;