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.c825
1 files changed, 411 insertions, 414 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e9f9248cb3fe..c7d341714586 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -124,7 +124,7 @@ static int
124cifs_reconnect(struct TCP_Server_Info *server) 124cifs_reconnect(struct TCP_Server_Info *server)
125{ 125{
126 int rc = 0; 126 int rc = 0;
127 struct list_head *tmp; 127 struct list_head *tmp, *tmp2;
128 struct cifsSesInfo *ses; 128 struct cifsSesInfo *ses;
129 struct cifsTconInfo *tcon; 129 struct cifsTconInfo *tcon;
130 struct mid_q_entry *mid_entry; 130 struct mid_q_entry *mid_entry;
@@ -144,23 +144,17 @@ cifs_reconnect(struct TCP_Server_Info *server)
144 144
145 /* before reconnecting the tcp session, mark the smb session (uid) 145 /* before reconnecting the tcp session, mark the smb session (uid)
146 and the tid bad so they are not used until reconnected */ 146 and the tid bad so they are not used until reconnected */
147 read_lock(&GlobalSMBSeslock); 147 read_lock(&cifs_tcp_ses_lock);
148 list_for_each(tmp, &GlobalSMBSessionList) { 148 list_for_each(tmp, &server->smb_ses_list) {
149 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); 149 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
150 if (ses->server) { 150 ses->need_reconnect = true;
151 if (ses->server == server) { 151 ses->ipc_tid = 0;
152 ses->status = CifsNeedReconnect; 152 list_for_each(tmp2, &ses->tcon_list) {
153 ses->ipc_tid = 0; 153 tcon = list_entry(tmp2, struct cifsTconInfo, tcon_list);
154 } 154 tcon->need_reconnect = true;
155 } 155 }
156 /* else tcp and smb sessions need reconnection */
157 }
158 list_for_each(tmp, &GlobalTreeConnectionList) {
159 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
160 if ((tcon->ses) && (tcon->ses->server == server))
161 tcon->tidStatus = CifsNeedReconnect;
162 } 156 }
163 read_unlock(&GlobalSMBSeslock); 157 read_unlock(&cifs_tcp_ses_lock);
164 /* do not want to be sending data on a socket we are freeing */ 158 /* do not want to be sending data on a socket we are freeing */
165 down(&server->tcpSem); 159 down(&server->tcpSem);
166 if (server->ssocket) { 160 if (server->ssocket) {
@@ -193,7 +187,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
193 while ((server->tcpStatus != CifsExiting) && 187 while ((server->tcpStatus != CifsExiting) &&
194 (server->tcpStatus != CifsGood)) { 188 (server->tcpStatus != CifsGood)) {
195 try_to_freeze(); 189 try_to_freeze();
196 if (server->protocolType == IPV6) { 190 if (server->addr.sockAddr6.sin6_family == AF_INET6) {
197 rc = ipv6_connect(&server->addr.sockAddr6, 191 rc = ipv6_connect(&server->addr.sockAddr6,
198 &server->ssocket, server->noautotune); 192 &server->ssocket, server->noautotune);
199 } else { 193 } else {
@@ -417,9 +411,14 @@ incomplete_rcv:
417 msleep(1); /* minimum sleep to prevent looping 411 msleep(1); /* minimum sleep to prevent looping
418 allowing socket to clear and app threads to set 412 allowing socket to clear and app threads to set
419 tcpStatus CifsNeedReconnect if server hung */ 413 tcpStatus CifsNeedReconnect if server hung */
420 if (pdu_length < 4) 414 if (pdu_length < 4) {
415 iov.iov_base = (4 - pdu_length) +
416 (char *)smb_buffer;
417 iov.iov_len = pdu_length;
418 smb_msg.msg_control = NULL;
419 smb_msg.msg_controllen = 0;
421 goto incomplete_rcv; 420 goto incomplete_rcv;
422 else 421 } else
423 continue; 422 continue;
424 } else if (length <= 0) { 423 } else if (length <= 0) {
425 if (server->tcpStatus == CifsNew) { 424 if (server->tcpStatus == CifsNew) {
@@ -654,6 +653,11 @@ multi_t2_fnd:
654 } 653 }
655 } /* end while !EXITING */ 654 } /* end while !EXITING */
656 655
656 /* take it off the list, if it's not already */
657 write_lock(&cifs_tcp_ses_lock);
658 list_del_init(&server->tcp_ses_list);
659 write_unlock(&cifs_tcp_ses_lock);
660
657 spin_lock(&GlobalMid_Lock); 661 spin_lock(&GlobalMid_Lock);
658 server->tcpStatus = CifsExiting; 662 server->tcpStatus = CifsExiting;
659 spin_unlock(&GlobalMid_Lock); 663 spin_unlock(&GlobalMid_Lock);
@@ -686,29 +690,29 @@ multi_t2_fnd:
686 if (smallbuf) /* no sense logging a debug message if NULL */ 690 if (smallbuf) /* no sense logging a debug message if NULL */
687 cifs_small_buf_release(smallbuf); 691 cifs_small_buf_release(smallbuf);
688 692
689 read_lock(&GlobalSMBSeslock); 693 /*
694 * BB: we shouldn't have to do any of this. It shouldn't be
695 * possible to exit from the thread with active SMB sessions
696 */
697 read_lock(&cifs_tcp_ses_lock);
690 if (list_empty(&server->pending_mid_q)) { 698 if (list_empty(&server->pending_mid_q)) {
691 /* loop through server session structures attached to this and 699 /* loop through server session structures attached to this and
692 mark them dead */ 700 mark them dead */
693 list_for_each(tmp, &GlobalSMBSessionList) { 701 list_for_each(tmp, &server->smb_ses_list) {
694 ses = 702 ses = list_entry(tmp, struct cifsSesInfo,
695 list_entry(tmp, struct cifsSesInfo, 703 smb_ses_list);
696 cifsSessionList); 704 ses->status = CifsExiting;
697 if (ses->server == server) { 705 ses->server = NULL;
698 ses->status = CifsExiting;
699 ses->server = NULL;
700 }
701 } 706 }
702 read_unlock(&GlobalSMBSeslock); 707 read_unlock(&cifs_tcp_ses_lock);
703 } else { 708 } else {
704 /* although we can not zero the server struct pointer yet, 709 /* although we can not zero the server struct pointer yet,
705 since there are active requests which may depnd on them, 710 since there are active requests which may depnd on them,
706 mark the corresponding SMB sessions as exiting too */ 711 mark the corresponding SMB sessions as exiting too */
707 list_for_each(tmp, &GlobalSMBSessionList) { 712 list_for_each(tmp, &server->smb_ses_list) {
708 ses = list_entry(tmp, struct cifsSesInfo, 713 ses = list_entry(tmp, struct cifsSesInfo,
709 cifsSessionList); 714 smb_ses_list);
710 if (ses->server == server) 715 ses->status = CifsExiting;
711 ses->status = CifsExiting;
712 } 716 }
713 717
714 spin_lock(&GlobalMid_Lock); 718 spin_lock(&GlobalMid_Lock);
@@ -723,7 +727,7 @@ multi_t2_fnd:
723 } 727 }
724 } 728 }
725 spin_unlock(&GlobalMid_Lock); 729 spin_unlock(&GlobalMid_Lock);
726 read_unlock(&GlobalSMBSeslock); 730 read_unlock(&cifs_tcp_ses_lock);
727 /* 1/8th of sec is more than enough time for them to exit */ 731 /* 1/8th of sec is more than enough time for them to exit */
728 msleep(125); 732 msleep(125);
729 } 733 }
@@ -745,14 +749,13 @@ multi_t2_fnd:
745 if there are any pointing to this (e.g 749 if there are any pointing to this (e.g
746 if a crazy root user tried to kill cifsd 750 if a crazy root user tried to kill cifsd
747 kernel thread explicitly this might happen) */ 751 kernel thread explicitly this might happen) */
748 write_lock(&GlobalSMBSeslock); 752 /* BB: This shouldn't be necessary, see above */
749 list_for_each(tmp, &GlobalSMBSessionList) { 753 read_lock(&cifs_tcp_ses_lock);
750 ses = list_entry(tmp, struct cifsSesInfo, 754 list_for_each(tmp, &server->smb_ses_list) {
751 cifsSessionList); 755 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
752 if (ses->server == server) 756 ses->server = NULL;
753 ses->server = NULL;
754 } 757 }
755 write_unlock(&GlobalSMBSeslock); 758 read_unlock(&cifs_tcp_ses_lock);
756 759
757 kfree(server->hostname); 760 kfree(server->hostname);
758 task_to_wake = xchg(&server->tsk, NULL); 761 task_to_wake = xchg(&server->tsk, NULL);
@@ -1352,94 +1355,158 @@ cifs_parse_mount_options(char *options, const char *devname,
1352 return 0; 1355 return 0;
1353} 1356}
1354 1357
1355static struct cifsSesInfo * 1358static struct TCP_Server_Info *
1356cifs_find_tcp_session(struct in_addr *target_ip_addr, 1359cifs_find_tcp_session(struct sockaddr *addr)
1357 struct in6_addr *target_ip6_addr,
1358 char *userName, struct TCP_Server_Info **psrvTcp)
1359{ 1360{
1360 struct list_head *tmp; 1361 struct list_head *tmp;
1361 struct cifsSesInfo *ses; 1362 struct TCP_Server_Info *server;
1362 1363 struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
1363 *psrvTcp = NULL; 1364 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
1365
1366 write_lock(&cifs_tcp_ses_lock);
1367 list_for_each(tmp, &cifs_tcp_ses_list) {
1368 server = list_entry(tmp, struct TCP_Server_Info,
1369 tcp_ses_list);
1370 /*
1371 * the demux thread can exit on its own while still in CifsNew
1372 * so don't accept any sockets in that state. Since the
1373 * tcpStatus never changes back to CifsNew it's safe to check
1374 * for this without a lock.
1375 */
1376 if (server->tcpStatus == CifsNew)
1377 continue;
1364 1378
1365 read_lock(&GlobalSMBSeslock); 1379 if (addr->sa_family == AF_INET &&
1366 list_for_each(tmp, &GlobalSMBSessionList) { 1380 (addr4->sin_addr.s_addr !=
1367 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); 1381 server->addr.sockAddr.sin_addr.s_addr))
1368 if (!ses->server) 1382 continue;
1383 else if (addr->sa_family == AF_INET6 &&
1384 memcmp(&server->addr.sockAddr6.sin6_addr,
1385 &addr6->sin6_addr, sizeof(addr6->sin6_addr)))
1369 continue; 1386 continue;
1370 1387
1371 if (target_ip_addr && 1388 ++server->srv_count;
1372 ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr) 1389 write_unlock(&cifs_tcp_ses_lock);
1373 continue; 1390 cFYI(1, ("Existing tcp session with server found"));
1374 else if (target_ip6_addr && 1391 return server;
1375 memcmp(&ses->server->addr.sockAddr6.sin6_addr, 1392 }
1376 target_ip6_addr, sizeof(*target_ip6_addr))) 1393 write_unlock(&cifs_tcp_ses_lock);
1377 continue; 1394 return NULL;
1378 /* BB lock server and tcp session; increment use count here?? */ 1395}
1379 1396
1380 /* found a match on the TCP session */ 1397static void
1381 *psrvTcp = ses->server; 1398cifs_put_tcp_session(struct TCP_Server_Info *server)
1399{
1400 struct task_struct *task;
1382 1401
1383 /* BB check if reconnection needed */ 1402 write_lock(&cifs_tcp_ses_lock);
1384 if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) { 1403 if (--server->srv_count > 0) {
1385 read_unlock(&GlobalSMBSeslock); 1404 write_unlock(&cifs_tcp_ses_lock);
1386 /* Found exact match on both TCP and 1405 return;
1387 SMB sessions */
1388 return ses;
1389 }
1390 /* else tcp and smb sessions need reconnection */
1391 } 1406 }
1392 read_unlock(&GlobalSMBSeslock);
1393 1407
1394 return NULL; 1408 list_del_init(&server->tcp_ses_list);
1409 write_unlock(&cifs_tcp_ses_lock);
1410
1411 spin_lock(&GlobalMid_Lock);
1412 server->tcpStatus = CifsExiting;
1413 spin_unlock(&GlobalMid_Lock);
1414
1415 task = xchg(&server->tsk, NULL);
1416 if (task)
1417 force_sig(SIGKILL, task);
1395} 1418}
1396 1419
1397static struct cifsTconInfo * 1420static struct cifsSesInfo *
1398find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) 1421cifs_find_smb_ses(struct TCP_Server_Info *server, char *username)
1399{ 1422{
1400 struct list_head *tmp; 1423 struct list_head *tmp;
1401 struct cifsTconInfo *tcon; 1424 struct cifsSesInfo *ses;
1402 __be32 old_ip;
1403
1404 read_lock(&GlobalSMBSeslock);
1405 1425
1406 list_for_each(tmp, &GlobalTreeConnectionList) { 1426 write_lock(&cifs_tcp_ses_lock);
1407 cFYI(1, ("Next tcon")); 1427 list_for_each(tmp, &server->smb_ses_list) {
1408 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 1428 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
1409 if (!tcon->ses || !tcon->ses->server) 1429 if (strncmp(ses->userName, username, MAX_USERNAME_SIZE))
1410 continue; 1430 continue;
1411 1431
1412 old_ip = tcon->ses->server->addr.sockAddr.sin_addr.s_addr; 1432 ++ses->ses_count;
1413 cFYI(1, ("old ip addr: %x == new ip %x ?", 1433 write_unlock(&cifs_tcp_ses_lock);
1414 old_ip, new_target_ip_addr)); 1434 return ses;
1435 }
1436 write_unlock(&cifs_tcp_ses_lock);
1437 return NULL;
1438}
1415 1439
1416 if (old_ip != new_target_ip_addr) 1440static void
1417 continue; 1441cifs_put_smb_ses(struct cifsSesInfo *ses)
1442{
1443 int xid;
1444 struct TCP_Server_Info *server = ses->server;
1418 1445
1419 /* BB lock tcon, server, tcp session and increment use count? */ 1446 write_lock(&cifs_tcp_ses_lock);
1420 /* found a match on the TCP session */ 1447 if (--ses->ses_count > 0) {
1421 /* BB check if reconnection needed */ 1448 write_unlock(&cifs_tcp_ses_lock);
1422 cFYI(1, ("IP match, old UNC: %s new: %s", 1449 return;
1423 tcon->treeName, uncName)); 1450 }
1424 1451
1425 if (strncmp(tcon->treeName, uncName, MAX_TREE_SIZE)) 1452 list_del_init(&ses->smb_ses_list);
1426 continue; 1453 write_unlock(&cifs_tcp_ses_lock);
1427 1454
1428 cFYI(1, ("and old usr: %s new: %s", 1455 if (ses->status == CifsGood) {
1429 tcon->treeName, uncName)); 1456 xid = GetXid();
1457 CIFSSMBLogoff(xid, ses);
1458 _FreeXid(xid);
1459 }
1460 sesInfoFree(ses);
1461 cifs_put_tcp_session(server);
1462}
1430 1463
1431 if (strncmp(tcon->ses->userName, userName, MAX_USERNAME_SIZE)) 1464static struct cifsTconInfo *
1465cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
1466{
1467 struct list_head *tmp;
1468 struct cifsTconInfo *tcon;
1469
1470 write_lock(&cifs_tcp_ses_lock);
1471 list_for_each(tmp, &ses->tcon_list) {
1472 tcon = list_entry(tmp, struct cifsTconInfo, tcon_list);
1473 if (tcon->tidStatus == CifsExiting)
1474 continue;
1475 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
1432 continue; 1476 continue;
1433 1477
1434 /* matched smb session (user name) */ 1478 ++tcon->tc_count;
1435 read_unlock(&GlobalSMBSeslock); 1479 write_unlock(&cifs_tcp_ses_lock);
1436 return tcon; 1480 return tcon;
1437 } 1481 }
1438 1482 write_unlock(&cifs_tcp_ses_lock);
1439 read_unlock(&GlobalSMBSeslock);
1440 return NULL; 1483 return NULL;
1441} 1484}
1442 1485
1486static void
1487cifs_put_tcon(struct cifsTconInfo *tcon)
1488{
1489 int xid;
1490 struct cifsSesInfo *ses = tcon->ses;
1491
1492 write_lock(&cifs_tcp_ses_lock);
1493 if (--tcon->tc_count > 0) {
1494 write_unlock(&cifs_tcp_ses_lock);
1495 return;
1496 }
1497
1498 list_del_init(&tcon->tcon_list);
1499 write_unlock(&cifs_tcp_ses_lock);
1500
1501 xid = GetXid();
1502 CIFSSMBTDis(xid, tcon);
1503 _FreeXid(xid);
1504
1505 DeleteTconOplockQEntries(tcon);
1506 tconInfoFree(tcon);
1507 cifs_put_smb_ses(ses);
1508}
1509
1443int 1510int
1444get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, 1511get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
1445 const struct nls_table *nls_codepage, unsigned int *pnum_referrals, 1512 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
@@ -1876,14 +1943,90 @@ convert_delimiter(char *path, char delim)
1876 } 1943 }
1877} 1944}
1878 1945
1879static void 1946static void setup_cifs_sb(struct smb_vol *pvolume_info,
1880kill_cifsd(struct TCP_Server_Info *server) 1947 struct cifs_sb_info *cifs_sb)
1881{ 1948{
1882 struct task_struct *task; 1949 if (pvolume_info->rsize > CIFSMaxBufSize) {
1883 1950 cERROR(1, ("rsize %d too large, using MaxBufSize",
1884 task = xchg(&server->tsk, NULL); 1951 pvolume_info->rsize));
1885 if (task) 1952 cifs_sb->rsize = CIFSMaxBufSize;
1886 force_sig(SIGKILL, task); 1953 } else if ((pvolume_info->rsize) &&
1954 (pvolume_info->rsize <= CIFSMaxBufSize))
1955 cifs_sb->rsize = pvolume_info->rsize;
1956 else /* default */
1957 cifs_sb->rsize = CIFSMaxBufSize;
1958
1959 if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1960 cERROR(1, ("wsize %d too large, using 4096 instead",
1961 pvolume_info->wsize));
1962 cifs_sb->wsize = 4096;
1963 } else if (pvolume_info->wsize)
1964 cifs_sb->wsize = pvolume_info->wsize;
1965 else
1966 cifs_sb->wsize = min_t(const int,
1967 PAGEVEC_SIZE * PAGE_CACHE_SIZE,
1968 127*1024);
1969 /* old default of CIFSMaxBufSize was too small now
1970 that SMB Write2 can send multiple pages in kvec.
1971 RFC1001 does not describe what happens when frame
1972 bigger than 128K is sent so use that as max in
1973 conjunction with 52K kvec constraint on arch with 4K
1974 page size */
1975
1976 if (cifs_sb->rsize < 2048) {
1977 cifs_sb->rsize = 2048;
1978 /* Windows ME may prefer this */
1979 cFYI(1, ("readsize set to minimum: 2048"));
1980 }
1981 /* calculate prepath */
1982 cifs_sb->prepath = pvolume_info->prepath;
1983 if (cifs_sb->prepath) {
1984 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
1985 /* we can not convert the / to \ in the path
1986 separators in the prefixpath yet because we do not
1987 know (until reset_cifs_unix_caps is called later)
1988 whether POSIX PATH CAP is available. We normalize
1989 the / to \ after reset_cifs_unix_caps is called */
1990 pvolume_info->prepath = NULL;
1991 } else
1992 cifs_sb->prepathlen = 0;
1993 cifs_sb->mnt_uid = pvolume_info->linux_uid;
1994 cifs_sb->mnt_gid = pvolume_info->linux_gid;
1995 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
1996 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
1997 cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
1998 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
1999
2000 if (pvolume_info->noperm)
2001 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
2002 if (pvolume_info->setuids)
2003 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
2004 if (pvolume_info->server_ino)
2005 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
2006 if (pvolume_info->remap)
2007 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
2008 if (pvolume_info->no_xattr)
2009 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
2010 if (pvolume_info->sfu_emul)
2011 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2012 if (pvolume_info->nobrl)
2013 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2014 if (pvolume_info->cifs_acl)
2015 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2016 if (pvolume_info->override_uid)
2017 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2018 if (pvolume_info->override_gid)
2019 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2020 if (pvolume_info->dynperm)
2021 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
2022 if (pvolume_info->direct_io) {
2023 cFYI(1, ("mounting share using direct i/o"));
2024 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2025 }
2026
2027 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
2028 cERROR(1, ("mount option dynperm ignored if cifsacl "
2029 "mount option supported"));
1887} 2030}
1888 2031
1889int 2032int
@@ -1892,13 +2035,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1892{ 2035{
1893 int rc = 0; 2036 int rc = 0;
1894 int xid; 2037 int xid;
1895 int address_type = AF_INET;
1896 struct socket *csocket = NULL; 2038 struct socket *csocket = NULL;
1897 struct sockaddr_in sin_server; 2039 struct sockaddr addr;
1898 struct sockaddr_in6 sin_server6; 2040 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
2041 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
1899 struct smb_vol volume_info; 2042 struct smb_vol volume_info;
1900 struct cifsSesInfo *pSesInfo = NULL; 2043 struct cifsSesInfo *pSesInfo = NULL;
1901 struct cifsSesInfo *existingCifsSes = NULL;
1902 struct cifsTconInfo *tcon = NULL; 2044 struct cifsTconInfo *tcon = NULL;
1903 struct TCP_Server_Info *srvTcp = NULL; 2045 struct TCP_Server_Info *srvTcp = NULL;
1904 2046
@@ -1906,6 +2048,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1906 2048
1907/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */ 2049/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1908 2050
2051 memset(&addr, 0, sizeof(struct sockaddr));
1909 memset(&volume_info, 0, sizeof(struct smb_vol)); 2052 memset(&volume_info, 0, sizeof(struct smb_vol));
1910 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { 2053 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1911 rc = -EINVAL; 2054 rc = -EINVAL;
@@ -1928,16 +2071,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1928 2071
1929 if (volume_info.UNCip && volume_info.UNC) { 2072 if (volume_info.UNCip && volume_info.UNC) {
1930 rc = cifs_inet_pton(AF_INET, volume_info.UNCip, 2073 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
1931 &sin_server.sin_addr.s_addr); 2074 &sin_server->sin_addr.s_addr);
1932 2075
1933 if (rc <= 0) { 2076 if (rc <= 0) {
1934 /* not ipv4 address, try ipv6 */ 2077 /* not ipv4 address, try ipv6 */
1935 rc = cifs_inet_pton(AF_INET6, volume_info.UNCip, 2078 rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
1936 &sin_server6.sin6_addr.in6_u); 2079 &sin_server6->sin6_addr.in6_u);
1937 if (rc > 0) 2080 if (rc > 0)
1938 address_type = AF_INET6; 2081 addr.sa_family = AF_INET6;
1939 } else { 2082 } else {
1940 address_type = AF_INET; 2083 addr.sa_family = AF_INET;
1941 } 2084 }
1942 2085
1943 if (rc <= 0) { 2086 if (rc <= 0) {
@@ -1977,41 +2120,25 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1977 } 2120 }
1978 } 2121 }
1979 2122
1980 if (address_type == AF_INET) 2123 srvTcp = cifs_find_tcp_session(&addr);
1981 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr, 2124 if (!srvTcp) { /* create socket */
1982 NULL /* no ipv6 addr */, 2125 if (addr.sa_family == AF_INET6) {
1983 volume_info.username, &srvTcp);
1984 else if (address_type == AF_INET6) {
1985 cFYI(1, ("looking for ipv6 address"));
1986 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1987 &sin_server6.sin6_addr,
1988 volume_info.username, &srvTcp);
1989 } else {
1990 rc = -EINVAL;
1991 goto out;
1992 }
1993
1994 if (srvTcp) {
1995 cFYI(1, ("Existing tcp session with server found"));
1996 } else { /* create socket */
1997 if (volume_info.port)
1998 sin_server.sin_port = htons(volume_info.port);
1999 else
2000 sin_server.sin_port = 0;
2001 if (address_type == AF_INET6) {
2002 cFYI(1, ("attempting ipv6 connect")); 2126 cFYI(1, ("attempting ipv6 connect"));
2003 /* BB should we allow ipv6 on port 139? */ 2127 /* BB should we allow ipv6 on port 139? */
2004 /* other OS never observed in Wild doing 139 with v6 */ 2128 /* other OS never observed in Wild doing 139 with v6 */
2005 rc = ipv6_connect(&sin_server6, &csocket, 2129 sin_server6->sin6_port = htons(volume_info.port);
2130 rc = ipv6_connect(sin_server6, &csocket,
2006 volume_info.noblocksnd); 2131 volume_info.noblocksnd);
2007 } else 2132 } else {
2008 rc = ipv4_connect(&sin_server, &csocket, 2133 sin_server->sin_port = htons(volume_info.port);
2134 rc = ipv4_connect(sin_server, &csocket,
2009 volume_info.source_rfc1001_name, 2135 volume_info.source_rfc1001_name,
2010 volume_info.target_rfc1001_name, 2136 volume_info.target_rfc1001_name,
2011 volume_info.noblocksnd, 2137 volume_info.noblocksnd,
2012 volume_info.noautotune); 2138 volume_info.noautotune);
2139 }
2013 if (rc < 0) { 2140 if (rc < 0) {
2014 cERROR(1, ("Error connecting to IPv4 socket. " 2141 cERROR(1, ("Error connecting to socket. "
2015 "Aborting operation")); 2142 "Aborting operation"));
2016 if (csocket != NULL) 2143 if (csocket != NULL)
2017 sock_release(csocket); 2144 sock_release(csocket);
@@ -2026,12 +2153,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2026 } else { 2153 } else {
2027 srvTcp->noblocksnd = volume_info.noblocksnd; 2154 srvTcp->noblocksnd = volume_info.noblocksnd;
2028 srvTcp->noautotune = volume_info.noautotune; 2155 srvTcp->noautotune = volume_info.noautotune;
2029 memcpy(&srvTcp->addr.sockAddr, &sin_server, 2156 if (addr.sa_family == AF_INET6)
2030 sizeof(struct sockaddr_in)); 2157 memcpy(&srvTcp->addr.sockAddr6, sin_server6,
2158 sizeof(struct sockaddr_in6));
2159 else
2160 memcpy(&srvTcp->addr.sockAddr, sin_server,
2161 sizeof(struct sockaddr_in));
2031 atomic_set(&srvTcp->inFlight, 0); 2162 atomic_set(&srvTcp->inFlight, 0);
2032 /* BB Add code for ipv6 case too */ 2163 /* BB Add code for ipv6 case too */
2033 srvTcp->ssocket = csocket; 2164 srvTcp->ssocket = csocket;
2034 srvTcp->protocolType = IPV4;
2035 srvTcp->hostname = extract_hostname(volume_info.UNC); 2165 srvTcp->hostname = extract_hostname(volume_info.UNC);
2036 if (IS_ERR(srvTcp->hostname)) { 2166 if (IS_ERR(srvTcp->hostname)) {
2037 rc = PTR_ERR(srvTcp->hostname); 2167 rc = PTR_ERR(srvTcp->hostname);
@@ -2061,15 +2191,28 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2061 memcpy(srvTcp->server_RFC1001_name, 2191 memcpy(srvTcp->server_RFC1001_name,
2062 volume_info.target_rfc1001_name, 16); 2192 volume_info.target_rfc1001_name, 16);
2063 srvTcp->sequence_number = 0; 2193 srvTcp->sequence_number = 0;
2194 INIT_LIST_HEAD(&srvTcp->tcp_ses_list);
2195 INIT_LIST_HEAD(&srvTcp->smb_ses_list);
2196 ++srvTcp->srv_count;
2197 write_lock(&cifs_tcp_ses_lock);
2198 list_add(&srvTcp->tcp_ses_list,
2199 &cifs_tcp_ses_list);
2200 write_unlock(&cifs_tcp_ses_lock);
2064 } 2201 }
2065 } 2202 }
2066 2203
2067 if (existingCifsSes) { 2204 pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username);
2068 pSesInfo = existingCifsSes; 2205 if (pSesInfo) {
2069 cFYI(1, ("Existing smb sess found (status=%d)", 2206 cFYI(1, ("Existing smb sess found (status=%d)",
2070 pSesInfo->status)); 2207 pSesInfo->status));
2208 /*
2209 * The existing SMB session already has a reference to srvTcp,
2210 * so we can put back the extra one we got before
2211 */
2212 cifs_put_tcp_session(srvTcp);
2213
2071 down(&pSesInfo->sesSem); 2214 down(&pSesInfo->sesSem);
2072 if (pSesInfo->status == CifsNeedReconnect) { 2215 if (pSesInfo->need_reconnect) {
2073 cFYI(1, ("Session needs reconnect")); 2216 cFYI(1, ("Session needs reconnect"));
2074 rc = cifs_setup_session(xid, pSesInfo, 2217 rc = cifs_setup_session(xid, pSesInfo,
2075 cifs_sb->local_nls); 2218 cifs_sb->local_nls);
@@ -2078,187 +2221,101 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2078 } else if (!rc) { 2221 } else if (!rc) {
2079 cFYI(1, ("Existing smb sess not found")); 2222 cFYI(1, ("Existing smb sess not found"));
2080 pSesInfo = sesInfoAlloc(); 2223 pSesInfo = sesInfoAlloc();
2081 if (pSesInfo == NULL) 2224 if (pSesInfo == NULL) {
2082 rc = -ENOMEM; 2225 rc = -ENOMEM;
2083 else { 2226 goto mount_fail_check;
2084 pSesInfo->server = srvTcp; 2227 }
2085 sprintf(pSesInfo->serverName, "%u.%u.%u.%u", 2228
2086 NIPQUAD(sin_server.sin_addr.s_addr)); 2229 /* new SMB session uses our srvTcp ref */
2087 } 2230 pSesInfo->server = srvTcp;
2231 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
2232 NIPQUAD(sin_server->sin_addr.s_addr));
2233
2234 write_lock(&cifs_tcp_ses_lock);
2235 list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
2236 write_unlock(&cifs_tcp_ses_lock);
2237
2238 /* volume_info.password freed at unmount */
2239 if (volume_info.password) {
2240 pSesInfo->password = volume_info.password;
2241 /* set to NULL to prevent freeing on exit */
2242 volume_info.password = NULL;
2243 }
2244 if (volume_info.username)
2245 strncpy(pSesInfo->userName, volume_info.username,
2246 MAX_USERNAME_SIZE);
2247 if (volume_info.domainname) {
2248 int len = strlen(volume_info.domainname);
2249 pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
2250 if (pSesInfo->domainName)
2251 strcpy(pSesInfo->domainName,
2252 volume_info.domainname);
2253 }
2254 pSesInfo->linux_uid = volume_info.linux_uid;
2255 pSesInfo->overrideSecFlg = volume_info.secFlg;
2256 down(&pSesInfo->sesSem);
2088 2257
2089 if (!rc) { 2258 /* BB FIXME need to pass vol->secFlgs BB */
2090 /* volume_info.password freed at unmount */ 2259 rc = cifs_setup_session(xid, pSesInfo,
2091 if (volume_info.password) { 2260 cifs_sb->local_nls);
2092 pSesInfo->password = volume_info.password; 2261 up(&pSesInfo->sesSem);
2093 /* set to NULL to prevent freeing on exit */
2094 volume_info.password = NULL;
2095 }
2096 if (volume_info.username)
2097 strncpy(pSesInfo->userName,
2098 volume_info.username,
2099 MAX_USERNAME_SIZE);
2100 if (volume_info.domainname) {
2101 int len = strlen(volume_info.domainname);
2102 pSesInfo->domainName =
2103 kmalloc(len + 1, GFP_KERNEL);
2104 if (pSesInfo->domainName)
2105 strcpy(pSesInfo->domainName,
2106 volume_info.domainname);
2107 }
2108 pSesInfo->linux_uid = volume_info.linux_uid;
2109 pSesInfo->overrideSecFlg = volume_info.secFlg;
2110 down(&pSesInfo->sesSem);
2111 /* BB FIXME need to pass vol->secFlgs BB */
2112 rc = cifs_setup_session(xid, pSesInfo,
2113 cifs_sb->local_nls);
2114 up(&pSesInfo->sesSem);
2115 if (!rc)
2116 atomic_inc(&srvTcp->socketUseCount);
2117 }
2118 } 2262 }
2119 2263
2120 /* search for existing tcon to this server share */ 2264 /* search for existing tcon to this server share */
2121 if (!rc) { 2265 if (!rc) {
2122 if (volume_info.rsize > CIFSMaxBufSize) { 2266 setup_cifs_sb(&volume_info, cifs_sb);
2123 cERROR(1, ("rsize %d too large, using MaxBufSize",
2124 volume_info.rsize));
2125 cifs_sb->rsize = CIFSMaxBufSize;
2126 } else if ((volume_info.rsize) &&
2127 (volume_info.rsize <= CIFSMaxBufSize))
2128 cifs_sb->rsize = volume_info.rsize;
2129 else /* default */
2130 cifs_sb->rsize = CIFSMaxBufSize;
2131
2132 if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
2133 cERROR(1, ("wsize %d too large, using 4096 instead",
2134 volume_info.wsize));
2135 cifs_sb->wsize = 4096;
2136 } else if (volume_info.wsize)
2137 cifs_sb->wsize = volume_info.wsize;
2138 else
2139 cifs_sb->wsize =
2140 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
2141 127*1024);
2142 /* old default of CIFSMaxBufSize was too small now
2143 that SMB Write2 can send multiple pages in kvec.
2144 RFC1001 does not describe what happens when frame
2145 bigger than 128K is sent so use that as max in
2146 conjunction with 52K kvec constraint on arch with 4K
2147 page size */
2148
2149 if (cifs_sb->rsize < 2048) {
2150 cifs_sb->rsize = 2048;
2151 /* Windows ME may prefer this */
2152 cFYI(1, ("readsize set to minimum: 2048"));
2153 }
2154 /* calculate prepath */
2155 cifs_sb->prepath = volume_info.prepath;
2156 if (cifs_sb->prepath) {
2157 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
2158 /* we can not convert the / to \ in the path
2159 separators in the prefixpath yet because we do not
2160 know (until reset_cifs_unix_caps is called later)
2161 whether POSIX PATH CAP is available. We normalize
2162 the / to \ after reset_cifs_unix_caps is called */
2163 volume_info.prepath = NULL;
2164 } else
2165 cifs_sb->prepathlen = 0;
2166 cifs_sb->mnt_uid = volume_info.linux_uid;
2167 cifs_sb->mnt_gid = volume_info.linux_gid;
2168 cifs_sb->mnt_file_mode = volume_info.file_mode;
2169 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
2170 cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
2171 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
2172
2173 if (volume_info.noperm)
2174 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
2175 if (volume_info.setuids)
2176 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
2177 if (volume_info.server_ino)
2178 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
2179 if (volume_info.remap)
2180 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
2181 if (volume_info.no_xattr)
2182 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
2183 if (volume_info.sfu_emul)
2184 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2185 if (volume_info.nobrl)
2186 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2187 if (volume_info.cifs_acl)
2188 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2189 if (volume_info.override_uid)
2190 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2191 if (volume_info.override_gid)
2192 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2193 if (volume_info.dynperm)
2194 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
2195 if (volume_info.direct_io) {
2196 cFYI(1, ("mounting share using direct i/o"));
2197 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2198 }
2199 2267
2200 if ((volume_info.cifs_acl) && (volume_info.dynperm)) 2268 tcon = cifs_find_tcon(pSesInfo, volume_info.UNC);
2201 cERROR(1, ("mount option dynperm ignored if cifsacl "
2202 "mount option supported"));
2203
2204 tcon =
2205 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
2206 volume_info.username);
2207 if (tcon) { 2269 if (tcon) {
2208 cFYI(1, ("Found match on UNC path")); 2270 cFYI(1, ("Found match on UNC path"));
2209 /* we can have only one retry value for a connection 2271 /* existing tcon already has a reference */
2210 to a share so for resources mounted more than once 2272 cifs_put_smb_ses(pSesInfo);
2211 to the same server share the last value passed in
2212 for the retry flag is used */
2213 tcon->retry = volume_info.retry;
2214 tcon->nocase = volume_info.nocase;
2215 tcon->local_lease = volume_info.local_lease;
2216 if (tcon->seal != volume_info.seal) 2273 if (tcon->seal != volume_info.seal)
2217 cERROR(1, ("transport encryption setting " 2274 cERROR(1, ("transport encryption setting "
2218 "conflicts with existing tid")); 2275 "conflicts with existing tid"));
2219 } else { 2276 } else {
2220 tcon = tconInfoAlloc(); 2277 tcon = tconInfoAlloc();
2221 if (tcon == NULL) 2278 if (tcon == NULL) {
2222 rc = -ENOMEM; 2279 rc = -ENOMEM;
2223 else { 2280 goto mount_fail_check;
2224 /* check for null share name ie connecting to 2281 }
2225 * dfs root */ 2282 tcon->ses = pSesInfo;
2226 2283
2227 /* BB check if this works for exactly length 2284 /* check for null share name ie connect to dfs root */
2228 * three strings */ 2285 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
2229 if ((strchr(volume_info.UNC + 3, '\\') == NULL) 2286 && (strchr(volume_info.UNC + 3, '/') == NULL)) {
2230 && (strchr(volume_info.UNC + 3, '/') == 2287 /* rc = connect_to_dfs_path(...) */
2231 NULL)) { 2288 cFYI(1, ("DFS root not supported"));
2232/* rc = connect_to_dfs_path(xid, pSesInfo, 2289 rc = -ENODEV;
2233 "", cifs_sb->local_nls, 2290 goto mount_fail_check;
2234 cifs_sb->mnt_cifs_flags & 2291 } else {
2235 CIFS_MOUNT_MAP_SPECIAL_CHR);*/ 2292 /* BB Do we need to wrap sesSem around
2236 cFYI(1, ("DFS root not supported")); 2293 * this TCon call and Unix SetFS as
2237 rc = -ENODEV; 2294 * we do on SessSetup and reconnect? */
2238 goto out; 2295 rc = CIFSTCon(xid, pSesInfo, volume_info.UNC,
2239 } else { 2296 tcon, cifs_sb->local_nls);
2240 /* BB Do we need to wrap sesSem around 2297 cFYI(1, ("CIFS Tcon rc = %d", rc));
2241 * this TCon call and Unix SetFS as 2298 if (volume_info.nodfs) {
2242 * we do on SessSetup and reconnect? */ 2299 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2243 rc = CIFSTCon(xid, pSesInfo, 2300 cFYI(1, ("DFS disabled (%d)",
2244 volume_info.UNC, 2301 tcon->Flags));
2245 tcon, cifs_sb->local_nls);
2246 cFYI(1, ("CIFS Tcon rc = %d", rc));
2247 if (volume_info.nodfs) {
2248 tcon->Flags &=
2249 ~SMB_SHARE_IS_IN_DFS;
2250 cFYI(1, ("DFS disabled (%d)",
2251 tcon->Flags));
2252 }
2253 }
2254 if (!rc) {
2255 atomic_inc(&pSesInfo->inUse);
2256 tcon->retry = volume_info.retry;
2257 tcon->nocase = volume_info.nocase;
2258 tcon->seal = volume_info.seal;
2259 } 2302 }
2260 } 2303 }
2261 } 2304 if (rc)
2305 goto mount_fail_check;
2306 tcon->seal = volume_info.seal;
2307 write_lock(&cifs_tcp_ses_lock);
2308 list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
2309 write_unlock(&cifs_tcp_ses_lock);
2310 }
2311
2312 /* we can have only one retry value for a connection
2313 to a share so for resources mounted more than once
2314 to the same server share the last value passed in
2315 for the retry flag is used */
2316 tcon->retry = volume_info.retry;
2317 tcon->nocase = volume_info.nocase;
2318 tcon->local_lease = volume_info.local_lease;
2262 } 2319 }
2263 if (pSesInfo) { 2320 if (pSesInfo) {
2264 if (pSesInfo->capabilities & CAP_LARGE_FILES) { 2321 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
@@ -2270,80 +2327,49 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2270 /* BB FIXME fix time_gran to be larger for LANMAN sessions */ 2327 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
2271 sb->s_time_gran = 100; 2328 sb->s_time_gran = 100;
2272 2329
2273/* on error free sesinfo and tcon struct if needed */ 2330mount_fail_check:
2331 /* on error free sesinfo and tcon struct if needed */
2274 if (rc) { 2332 if (rc) {
2275 /* if session setup failed, use count is zero but 2333 /* If find_unc succeeded then rc == 0 so we can not end */
2276 we still need to free cifsd thread */ 2334 /* up accidently freeing someone elses tcon struct */
2277 if (atomic_read(&srvTcp->socketUseCount) == 0) { 2335 if (tcon)
2278 spin_lock(&GlobalMid_Lock); 2336 cifs_put_tcon(tcon);
2279 srvTcp->tcpStatus = CifsExiting; 2337 else if (pSesInfo)
2280 spin_unlock(&GlobalMid_Lock); 2338 cifs_put_smb_ses(pSesInfo);
2281 kill_cifsd(srvTcp);
2282 }
2283 /* If find_unc succeeded then rc == 0 so we can not end */
2284 if (tcon) /* up accidently freeing someone elses tcon struct */
2285 tconInfoFree(tcon);
2286 if (existingCifsSes == NULL) {
2287 if (pSesInfo) {
2288 if ((pSesInfo->server) &&
2289 (pSesInfo->status == CifsGood)) {
2290 int temp_rc;
2291 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
2292 /* if the socketUseCount is now zero */
2293 if ((temp_rc == -ESHUTDOWN) &&
2294 (pSesInfo->server))
2295 kill_cifsd(pSesInfo->server);
2296 } else {
2297 cFYI(1, ("No session or bad tcon"));
2298 if (pSesInfo->server) {
2299 spin_lock(&GlobalMid_Lock);
2300 srvTcp->tcpStatus = CifsExiting;
2301 spin_unlock(&GlobalMid_Lock);
2302 kill_cifsd(pSesInfo->server);
2303 }
2304 }
2305 sesInfoFree(pSesInfo);
2306 /* pSesInfo = NULL; */
2307 }
2308 }
2309 } else {
2310 atomic_inc(&tcon->useCount);
2311 cifs_sb->tcon = tcon;
2312 tcon->ses = pSesInfo;
2313
2314 /* do not care if following two calls succeed - informational */
2315 if (!tcon->ipc) {
2316 CIFSSMBQFSDeviceInfo(xid, tcon);
2317 CIFSSMBQFSAttributeInfo(xid, tcon);
2318 }
2319
2320 /* tell server which Unix caps we support */
2321 if (tcon->ses->capabilities & CAP_UNIX)
2322 /* reset of caps checks mount to see if unix extensions
2323 disabled for just this mount */
2324 reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
2325 else 2339 else
2326 tcon->unix_ext = 0; /* server does not support them */ 2340 cifs_put_tcp_session(srvTcp);
2341 goto out;
2342 }
2343 cifs_sb->tcon = tcon;
2327 2344
2328 /* convert forward to back slashes in prepath here if needed */ 2345 /* do not care if following two calls succeed - informational */
2329 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) 2346 if (!tcon->ipc) {
2330 convert_delimiter(cifs_sb->prepath, 2347 CIFSSMBQFSDeviceInfo(xid, tcon);
2331 CIFS_DIR_SEP(cifs_sb)); 2348 CIFSSMBQFSAttributeInfo(xid, tcon);
2349 }
2332 2350
2333 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) { 2351 /* tell server which Unix caps we support */
2334 cifs_sb->rsize = 1024 * 127; 2352 if (tcon->ses->capabilities & CAP_UNIX)
2335 cFYI(DBG2, 2353 /* reset of caps checks mount to see if unix extensions
2336 ("no very large read support, rsize now 127K")); 2354 disabled for just this mount */
2337 } 2355 reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
2338 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) 2356 else
2339 cifs_sb->wsize = min(cifs_sb->wsize, 2357 tcon->unix_ext = 0; /* server does not support them */
2340 (tcon->ses->server->maxBuf - 2358
2341 MAX_CIFS_HDR_SIZE)); 2359 /* convert forward to back slashes in prepath here if needed */
2342 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) 2360 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
2343 cifs_sb->rsize = min(cifs_sb->rsize, 2361 convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
2344 (tcon->ses->server->maxBuf - 2362
2345 MAX_CIFS_HDR_SIZE)); 2363 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
2364 cifs_sb->rsize = 1024 * 127;
2365 cFYI(DBG2, ("no very large read support, rsize now 127K"));
2346 } 2366 }
2367 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
2368 cifs_sb->wsize = min(cifs_sb->wsize,
2369 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2370 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
2371 cifs_sb->rsize = min(cifs_sb->rsize,
2372 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2347 2373
2348 /* volume_info.password is freed above when existing session found 2374 /* volume_info.password is freed above when existing session found
2349 (in which case it is not needed anymore) but when new sesion is created 2375 (in which case it is not needed anymore) but when new sesion is created
@@ -3513,6 +3539,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3513 /* above now done in SendReceive */ 3539 /* above now done in SendReceive */
3514 if ((rc == 0) && (tcon != NULL)) { 3540 if ((rc == 0) && (tcon != NULL)) {
3515 tcon->tidStatus = CifsGood; 3541 tcon->tidStatus = CifsGood;
3542 tcon->need_reconnect = false;
3516 tcon->tid = smb_buffer_response->Tid; 3543 tcon->tid = smb_buffer_response->Tid;
3517 bcc_ptr = pByteArea(smb_buffer_response); 3544 bcc_ptr = pByteArea(smb_buffer_response);
3518 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); 3545 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
@@ -3584,48 +3611,17 @@ int
3584cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) 3611cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3585{ 3612{
3586 int rc = 0; 3613 int rc = 0;
3587 int xid;
3588 struct cifsSesInfo *ses = NULL;
3589 char *tmp; 3614 char *tmp;
3590 3615
3591 xid = GetXid(); 3616 if (cifs_sb->tcon)
3592 3617 cifs_put_tcon(cifs_sb->tcon);
3593 if (cifs_sb->tcon) {
3594 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3595 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3596 if (rc == -EBUSY) {
3597 FreeXid(xid);
3598 return 0;
3599 }
3600 DeleteTconOplockQEntries(cifs_sb->tcon);
3601 tconInfoFree(cifs_sb->tcon);
3602 if ((ses) && (ses->server)) {
3603 /* save off task so we do not refer to ses later */
3604 cFYI(1, ("About to do SMBLogoff "));
3605 rc = CIFSSMBLogoff(xid, ses);
3606 if (rc == -EBUSY) {
3607 FreeXid(xid);
3608 return 0;
3609 } else if (rc == -ESHUTDOWN) {
3610 cFYI(1, ("Waking up socket by sending signal"));
3611 if (ses->server)
3612 kill_cifsd(ses->server);
3613 rc = 0;
3614 } /* else - we have an smb session
3615 left on this socket do not kill cifsd */
3616 } else
3617 cFYI(1, ("No session or bad tcon"));
3618 }
3619 3618
3620 cifs_sb->tcon = NULL; 3619 cifs_sb->tcon = NULL;
3621 tmp = cifs_sb->prepath; 3620 tmp = cifs_sb->prepath;
3622 cifs_sb->prepathlen = 0; 3621 cifs_sb->prepathlen = 0;
3623 cifs_sb->prepath = NULL; 3622 cifs_sb->prepath = NULL;
3624 kfree(tmp); 3623 kfree(tmp);
3625 if (ses)
3626 sesInfoFree(ses);
3627 3624
3628 FreeXid(xid);
3629 return rc; 3625 return rc;
3630} 3626}
3631 3627
@@ -3741,6 +3737,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3741 cFYI(1, ("CIFS Session Established successfully")); 3737 cFYI(1, ("CIFS Session Established successfully"));
3742 spin_lock(&GlobalMid_Lock); 3738 spin_lock(&GlobalMid_Lock);
3743 pSesInfo->status = CifsGood; 3739 pSesInfo->status = CifsGood;
3740 pSesInfo->need_reconnect = false;
3744 spin_unlock(&GlobalMid_Lock); 3741 spin_unlock(&GlobalMid_Lock);
3745 } 3742 }
3746 3743