aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c156
1 files changed, 86 insertions, 70 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 74c222ed83dd..c104f54cadfe 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1749,6 +1749,7 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
1749 int xid; 1749 int xid;
1750 struct cifsSesInfo *ses = tcon->ses; 1750 struct cifsSesInfo *ses = tcon->ses;
1751 1751
1752 cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
1752 write_lock(&cifs_tcp_ses_lock); 1753 write_lock(&cifs_tcp_ses_lock);
1753 if (--tcon->tc_count > 0) { 1754 if (--tcon->tc_count > 0) {
1754 write_unlock(&cifs_tcp_ses_lock); 1755 write_unlock(&cifs_tcp_ses_lock);
@@ -1766,6 +1767,80 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
1766 cifs_put_smb_ses(ses); 1767 cifs_put_smb_ses(ses);
1767} 1768}
1768 1769
1770static struct cifsTconInfo *
1771cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info)
1772{
1773 int rc, xid;
1774 struct cifsTconInfo *tcon;
1775
1776 tcon = cifs_find_tcon(ses, volume_info->UNC);
1777 if (tcon) {
1778 cFYI(1, "Found match on UNC path");
1779 /* existing tcon already has a reference */
1780 cifs_put_smb_ses(ses);
1781 if (tcon->seal != volume_info->seal)
1782 cERROR(1, "transport encryption setting "
1783 "conflicts with existing tid");
1784 return tcon;
1785 }
1786
1787 tcon = tconInfoAlloc();
1788 if (tcon == NULL) {
1789 rc = -ENOMEM;
1790 goto out_fail;
1791 }
1792
1793 tcon->ses = ses;
1794 if (volume_info->password) {
1795 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
1796 if (!tcon->password) {
1797 rc = -ENOMEM;
1798 goto out_fail;
1799 }
1800 }
1801
1802 if (strchr(volume_info->UNC + 3, '\\') == NULL
1803 && strchr(volume_info->UNC + 3, '/') == NULL) {
1804 cERROR(1, "Missing share name");
1805 rc = -ENODEV;
1806 goto out_fail;
1807 }
1808
1809 /* BB Do we need to wrap session_mutex around
1810 * this TCon call and Unix SetFS as
1811 * we do on SessSetup and reconnect? */
1812 xid = GetXid();
1813 rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
1814 FreeXid(xid);
1815 cFYI(1, "CIFS Tcon rc = %d", rc);
1816 if (rc)
1817 goto out_fail;
1818
1819 if (volume_info->nodfs) {
1820 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
1821 cFYI(1, "DFS disabled (%d)", tcon->Flags);
1822 }
1823 tcon->seal = volume_info->seal;
1824 /* we can have only one retry value for a connection
1825 to a share so for resources mounted more than once
1826 to the same server share the last value passed in
1827 for the retry flag is used */
1828 tcon->retry = volume_info->retry;
1829 tcon->nocase = volume_info->nocase;
1830 tcon->local_lease = volume_info->local_lease;
1831
1832 write_lock(&cifs_tcp_ses_lock);
1833 list_add(&tcon->tcon_list, &ses->tcon_list);
1834 write_unlock(&cifs_tcp_ses_lock);
1835
1836 return tcon;
1837
1838out_fail:
1839 tconInfoFree(tcon);
1840 return ERR_PTR(rc);
1841}
1842
1843
1769int 1844int
1770get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, 1845get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
1771 const struct nls_table *nls_codepage, unsigned int *pnum_referrals, 1846 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
@@ -2471,81 +2546,22 @@ try_mount_again:
2471 goto mount_fail_check; 2546 goto mount_fail_check;
2472 } 2547 }
2473 2548
2474 /* search for existing tcon to this server share */ 2549 setup_cifs_sb(volume_info, cifs_sb);
2475 if (!rc) { 2550 if (pSesInfo->capabilities & CAP_LARGE_FILES)
2476 setup_cifs_sb(volume_info, cifs_sb); 2551 sb->s_maxbytes = MAX_LFS_FILESIZE;
2477 2552 else
2478 tcon = cifs_find_tcon(pSesInfo, volume_info->UNC); 2553 sb->s_maxbytes = MAX_NON_LFS;
2479 if (tcon) {
2480 cFYI(1, "Found match on UNC path");
2481 /* existing tcon already has a reference */
2482 cifs_put_smb_ses(pSesInfo);
2483 if (tcon->seal != volume_info->seal)
2484 cERROR(1, "transport encryption setting "
2485 "conflicts with existing tid");
2486 } else {
2487 tcon = tconInfoAlloc();
2488 if (tcon == NULL) {
2489 rc = -ENOMEM;
2490 goto mount_fail_check;
2491 }
2492
2493 tcon->ses = pSesInfo;
2494 if (volume_info->password) {
2495 tcon->password = kstrdup(volume_info->password,
2496 GFP_KERNEL);
2497 if (!tcon->password) {
2498 rc = -ENOMEM;
2499 goto mount_fail_check;
2500 }
2501 }
2502
2503 if ((strchr(volume_info->UNC + 3, '\\') == NULL)
2504 && (strchr(volume_info->UNC + 3, '/') == NULL)) {
2505 cERROR(1, "Missing share name");
2506 rc = -ENODEV;
2507 goto mount_fail_check;
2508 } else {
2509 /* BB Do we need to wrap sesSem around
2510 * this TCon call and Unix SetFS as
2511 * we do on SessSetup and reconnect? */
2512 rc = CIFSTCon(xid, pSesInfo, volume_info->UNC,
2513 tcon, cifs_sb->local_nls);
2514 cFYI(1, "CIFS Tcon rc = %d", rc);
2515 if (volume_info->nodfs) {
2516 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2517 cFYI(1, "DFS disabled (%d)",
2518 tcon->Flags);
2519 }
2520 }
2521 if (rc)
2522 goto remote_path_check;
2523 tcon->seal = volume_info->seal;
2524 write_lock(&cifs_tcp_ses_lock);
2525 list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
2526 write_unlock(&cifs_tcp_ses_lock);
2527 }
2528
2529 /* we can have only one retry value for a connection
2530 to a share so for resources mounted more than once
2531 to the same server share the last value passed in
2532 for the retry flag is used */
2533 tcon->retry = volume_info->retry;
2534 tcon->nocase = volume_info->nocase;
2535 tcon->local_lease = volume_info->local_lease;
2536 }
2537 if (pSesInfo) {
2538 if (pSesInfo->capabilities & CAP_LARGE_FILES)
2539 sb->s_maxbytes = MAX_LFS_FILESIZE;
2540 else
2541 sb->s_maxbytes = MAX_NON_LFS;
2542 }
2543 2554
2544 /* BB FIXME fix time_gran to be larger for LANMAN sessions */ 2555 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
2545 sb->s_time_gran = 100; 2556 sb->s_time_gran = 100;
2546 2557
2547 if (rc) 2558 /* search for existing tcon to this server share */
2559 tcon = cifs_get_tcon(pSesInfo, volume_info);
2560 if (IS_ERR(tcon)) {
2561 rc = PTR_ERR(tcon);
2562 tcon = NULL;
2548 goto remote_path_check; 2563 goto remote_path_check;
2564 }
2549 2565
2550 cifs_sb->tcon = tcon; 2566 cifs_sb->tcon = tcon;
2551 2567