diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/connect.c | 158 |
1 files changed, 93 insertions, 65 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index eb85dd8d510e..74c222ed83dd 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1616,6 +1616,7 @@ cifs_put_smb_ses(struct cifsSesInfo *ses) | |||
1616 | int xid; | 1616 | int xid; |
1617 | struct TCP_Server_Info *server = ses->server; | 1617 | struct TCP_Server_Info *server = ses->server; |
1618 | 1618 | ||
1619 | cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count); | ||
1619 | write_lock(&cifs_tcp_ses_lock); | 1620 | write_lock(&cifs_tcp_ses_lock); |
1620 | if (--ses->ses_count > 0) { | 1621 | if (--ses->ses_count > 0) { |
1621 | write_unlock(&cifs_tcp_ses_lock); | 1622 | write_unlock(&cifs_tcp_ses_lock); |
@@ -1634,6 +1635,92 @@ cifs_put_smb_ses(struct cifsSesInfo *ses) | |||
1634 | cifs_put_tcp_session(server); | 1635 | cifs_put_tcp_session(server); |
1635 | } | 1636 | } |
1636 | 1637 | ||
1638 | static struct cifsSesInfo * | ||
1639 | cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | ||
1640 | { | ||
1641 | int rc = -ENOMEM, xid; | ||
1642 | struct cifsSesInfo *ses; | ||
1643 | |||
1644 | xid = GetXid(); | ||
1645 | |||
1646 | ses = cifs_find_smb_ses(server, volume_info->username); | ||
1647 | if (ses) { | ||
1648 | cFYI(1, "Existing smb sess found (status=%d)", ses->status); | ||
1649 | |||
1650 | /* existing SMB ses has a server reference already */ | ||
1651 | cifs_put_tcp_session(server); | ||
1652 | |||
1653 | mutex_lock(&ses->session_mutex); | ||
1654 | if (ses->need_reconnect) { | ||
1655 | cFYI(1, "Session needs reconnect"); | ||
1656 | rc = cifs_setup_session(xid, ses, | ||
1657 | volume_info->local_nls); | ||
1658 | if (rc) { | ||
1659 | mutex_unlock(&ses->session_mutex); | ||
1660 | /* problem -- put our reference */ | ||
1661 | cifs_put_smb_ses(ses); | ||
1662 | FreeXid(xid); | ||
1663 | return ERR_PTR(rc); | ||
1664 | } | ||
1665 | } | ||
1666 | mutex_unlock(&ses->session_mutex); | ||
1667 | FreeXid(xid); | ||
1668 | return ses; | ||
1669 | } | ||
1670 | |||
1671 | cFYI(1, "Existing smb sess not found"); | ||
1672 | ses = sesInfoAlloc(); | ||
1673 | if (ses == NULL) | ||
1674 | goto get_ses_fail; | ||
1675 | |||
1676 | /* new SMB session uses our server ref */ | ||
1677 | ses->server = server; | ||
1678 | if (server->addr.sockAddr6.sin6_family == AF_INET6) | ||
1679 | sprintf(ses->serverName, "%pI6", | ||
1680 | &server->addr.sockAddr6.sin6_addr); | ||
1681 | else | ||
1682 | sprintf(ses->serverName, "%pI4", | ||
1683 | &server->addr.sockAddr.sin_addr.s_addr); | ||
1684 | |||
1685 | if (volume_info->username) | ||
1686 | strncpy(ses->userName, volume_info->username, | ||
1687 | MAX_USERNAME_SIZE); | ||
1688 | |||
1689 | /* volume_info->password freed at unmount */ | ||
1690 | if (volume_info->password) { | ||
1691 | ses->password = kstrdup(volume_info->password, GFP_KERNEL); | ||
1692 | if (!ses->password) | ||
1693 | goto get_ses_fail; | ||
1694 | } | ||
1695 | if (volume_info->domainname) { | ||
1696 | int len = strlen(volume_info->domainname); | ||
1697 | ses->domainName = kmalloc(len + 1, GFP_KERNEL); | ||
1698 | if (ses->domainName) | ||
1699 | strcpy(ses->domainName, volume_info->domainname); | ||
1700 | } | ||
1701 | ses->linux_uid = volume_info->linux_uid; | ||
1702 | ses->overrideSecFlg = volume_info->secFlg; | ||
1703 | |||
1704 | mutex_lock(&ses->session_mutex); | ||
1705 | rc = cifs_setup_session(xid, ses, volume_info->local_nls); | ||
1706 | mutex_unlock(&ses->session_mutex); | ||
1707 | if (rc) | ||
1708 | goto get_ses_fail; | ||
1709 | |||
1710 | /* success, put it on the list */ | ||
1711 | write_lock(&cifs_tcp_ses_lock); | ||
1712 | list_add(&ses->smb_ses_list, &server->smb_ses_list); | ||
1713 | write_unlock(&cifs_tcp_ses_lock); | ||
1714 | |||
1715 | FreeXid(xid); | ||
1716 | return ses; | ||
1717 | |||
1718 | get_ses_fail: | ||
1719 | sesInfoFree(ses); | ||
1720 | FreeXid(xid); | ||
1721 | return ERR_PTR(rc); | ||
1722 | } | ||
1723 | |||
1637 | static struct cifsTconInfo * | 1724 | static struct cifsTconInfo * |
1638 | cifs_find_tcon(struct cifsSesInfo *ses, const char *unc) | 1725 | cifs_find_tcon(struct cifsSesInfo *ses, const char *unc) |
1639 | { | 1726 | { |
@@ -2376,71 +2463,12 @@ try_mount_again: | |||
2376 | goto out; | 2463 | goto out; |
2377 | } | 2464 | } |
2378 | 2465 | ||
2379 | pSesInfo = cifs_find_smb_ses(srvTcp, volume_info->username); | 2466 | /* get a reference to a SMB session */ |
2380 | if (pSesInfo) { | 2467 | pSesInfo = cifs_get_smb_ses(srvTcp, volume_info); |
2381 | cFYI(1, "Existing smb sess found (status=%d)", | 2468 | if (IS_ERR(pSesInfo)) { |
2382 | pSesInfo->status); | 2469 | rc = PTR_ERR(pSesInfo); |
2383 | /* | 2470 | pSesInfo = NULL; |
2384 | * The existing SMB session already has a reference to srvTcp, | 2471 | goto mount_fail_check; |
2385 | * so we can put back the extra one we got before | ||
2386 | */ | ||
2387 | cifs_put_tcp_session(srvTcp); | ||
2388 | |||
2389 | mutex_lock(&pSesInfo->session_mutex); | ||
2390 | if (pSesInfo->need_reconnect) { | ||
2391 | cFYI(1, "Session needs reconnect"); | ||
2392 | rc = cifs_setup_session(xid, pSesInfo, | ||
2393 | cifs_sb->local_nls); | ||
2394 | } | ||
2395 | mutex_unlock(&pSesInfo->session_mutex); | ||
2396 | } else if (!rc) { | ||
2397 | cFYI(1, "Existing smb sess not found"); | ||
2398 | pSesInfo = sesInfoAlloc(); | ||
2399 | if (pSesInfo == NULL) { | ||
2400 | rc = -ENOMEM; | ||
2401 | goto mount_fail_check; | ||
2402 | } | ||
2403 | |||
2404 | /* new SMB session uses our srvTcp ref */ | ||
2405 | pSesInfo->server = srvTcp; | ||
2406 | if (srvTcp->addr.sockAddr6.sin6_family == AF_INET6) | ||
2407 | sprintf(pSesInfo->serverName, "%pI6", | ||
2408 | &srvTcp->addr.sockAddr6.sin6_addr); | ||
2409 | else | ||
2410 | sprintf(pSesInfo->serverName, "%pI4", | ||
2411 | &srvTcp->addr.sockAddr.sin_addr.s_addr); | ||
2412 | |||
2413 | write_lock(&cifs_tcp_ses_lock); | ||
2414 | list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list); | ||
2415 | write_unlock(&cifs_tcp_ses_lock); | ||
2416 | |||
2417 | /* volume_info->password freed at unmount */ | ||
2418 | if (volume_info->password) { | ||
2419 | pSesInfo->password = kstrdup(volume_info->password, | ||
2420 | GFP_KERNEL); | ||
2421 | if (!pSesInfo->password) { | ||
2422 | rc = -ENOMEM; | ||
2423 | goto mount_fail_check; | ||
2424 | } | ||
2425 | } | ||
2426 | if (volume_info->username) | ||
2427 | strncpy(pSesInfo->userName, volume_info->username, | ||
2428 | MAX_USERNAME_SIZE); | ||
2429 | if (volume_info->domainname) { | ||
2430 | int len = strlen(volume_info->domainname); | ||
2431 | pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL); | ||
2432 | if (pSesInfo->domainName) | ||
2433 | strcpy(pSesInfo->domainName, | ||
2434 | volume_info->domainname); | ||
2435 | } | ||
2436 | pSesInfo->linux_uid = volume_info->linux_uid; | ||
2437 | pSesInfo->overrideSecFlg = volume_info->secFlg; | ||
2438 | mutex_lock(&pSesInfo->session_mutex); | ||
2439 | |||
2440 | /* BB FIXME need to pass vol->secFlgs BB */ | ||
2441 | rc = cifs_setup_session(xid, pSesInfo, | ||
2442 | cifs_sb->local_nls); | ||
2443 | mutex_unlock(&pSesInfo->session_mutex); | ||
2444 | } | 2472 | } |
2445 | 2473 | ||
2446 | /* search for existing tcon to this server share */ | 2474 | /* search for existing tcon to this server share */ |