aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSuresh Jayaraman <sjayaraman@suse.de>2009-08-20 03:33:34 -0400
committerSteve French <sfrench@us.ibm.com>2009-09-01 13:08:48 -0400
commitbdb97adcdf0993adbd2eef44b4533620d43792de (patch)
tree5d2a120233c93d6a372d26d5ce3fc6cb6525fa6e /fs/cifs
parent1b3859bc9e20d764316346665fc93ecea2d2b176 (diff)
PATCH] cifs: fix broken mounts when a SSH tunnel is used (try #4)
One more try.. It seems there is a regression that got introduced while Jeff fixed all the mount/umount races. While attempting to find whether a tcp session is already existing, we were not checking whether the "port" used are the same. When a second mount is attempted with a different "port=" option, it is being ignored. Because of this the cifs mounts that uses a SSH tunnel appears to be broken. Steps to reproduce: 1. create 2 shares # SSH Tunnel a SMB session 2. ssh -f -L 6111:127.0.0.1:445 root@localhost "sleep 86400" 3. ssh -f -L 6222:127.0.0.1:445 root@localhost "sleep 86400" 4. tcpdump -i lo 6111 & 5. mkdir -p /mnt/mnt1 6. mkdir -p /mnt/mnt2 7. mount.cifs //localhost/a /mnt/mnt1 -o username=guest,ip=127.0.0.1,port=6111 #(shows tcpdump activity on port 6111) 8. mount.cifs //localhost/b /mnt/mnt2 -o username=guest,ip=127.0.0.1,port=6222 #(shows tcpdump activity only on port 6111 and not on 6222 Fix by adding a check to compare the port _only_ if the user tries to override the tcp port with "port=" option, before deciding that an existing tcp session is found. Also, clean up a bit by replacing if-else if by a switch statment while at it as suggested by Jeff. Reviewed-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Shirish Pargaonkar <shirishp@us.ibm.com> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/connect.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 1f3345d7fa79..4e47a9b800ce 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1377,7 +1377,7 @@ cifs_parse_mount_options(char *options, const char *devname,
1377} 1377}
1378 1378
1379static struct TCP_Server_Info * 1379static struct TCP_Server_Info *
1380cifs_find_tcp_session(struct sockaddr_storage *addr) 1380cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port)
1381{ 1381{
1382 struct list_head *tmp; 1382 struct list_head *tmp;
1383 struct TCP_Server_Info *server; 1383 struct TCP_Server_Info *server;
@@ -1397,16 +1397,37 @@ cifs_find_tcp_session(struct sockaddr_storage *addr)
1397 if (server->tcpStatus == CifsNew) 1397 if (server->tcpStatus == CifsNew)
1398 continue; 1398 continue;
1399 1399
1400 if (addr->ss_family == AF_INET && 1400 switch (addr->ss_family) {
1401 (addr4->sin_addr.s_addr != 1401 case AF_INET:
1402 server->addr.sockAddr.sin_addr.s_addr)) 1402 if (addr4->sin_addr.s_addr ==
1403 continue; 1403 server->addr.sockAddr.sin_addr.s_addr) {
1404 else if (addr->ss_family == AF_INET6 && 1404 addr4->sin_port = htons(port);
1405 (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, 1405 /* user overrode default port? */
1406 &addr6->sin6_addr) || 1406 if (addr4->sin_port) {
1407 server->addr.sockAddr6.sin6_scope_id != 1407 if (addr4->sin_port !=
1408 addr6->sin6_scope_id)) 1408 server->addr.sockAddr.sin_port)
1409 continue; 1409 continue;
1410 }
1411 break;
1412 } else
1413 continue;
1414
1415 case AF_INET6:
1416 if (ipv6_addr_equal(&addr6->sin6_addr,
1417 &server->addr.sockAddr6.sin6_addr) &&
1418 (addr6->sin6_scope_id ==
1419 server->addr.sockAddr6.sin6_scope_id)) {
1420 addr6->sin6_port = htons(port);
1421 /* user overrode default port? */
1422 if (addr6->sin6_port) {
1423 if (addr6->sin6_port !=
1424 server->addr.sockAddr6.sin6_port)
1425 continue;
1426 }
1427 break;
1428 } else
1429 continue;
1430 }
1410 1431
1411 ++server->srv_count; 1432 ++server->srv_count;
1412 write_unlock(&cifs_tcp_ses_lock); 1433 write_unlock(&cifs_tcp_ses_lock);
@@ -1475,7 +1496,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1475 } 1496 }
1476 1497
1477 /* see if we already have a matching tcp_ses */ 1498 /* see if we already have a matching tcp_ses */
1478 tcp_ses = cifs_find_tcp_session(&addr); 1499 tcp_ses = cifs_find_tcp_session(&addr, volume_info->port);
1479 if (tcp_ses) 1500 if (tcp_ses)
1480 return tcp_ses; 1501 return tcp_ses;
1481 1502