diff options
| -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 */ |
