diff options
Diffstat (limited to 'fs/cifs/connect.c')
| -rw-r--r-- | fs/cifs/connect.c | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 71b7661e2260..e9f9248cb3fe 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -92,6 +92,8 @@ struct smb_vol { | |||
| 92 | bool seal:1; /* request transport encryption on share */ | 92 | bool seal:1; /* request transport encryption on share */ |
| 93 | bool nodfs:1; /* Do not request DFS, even if available */ | 93 | bool nodfs:1; /* Do not request DFS, even if available */ |
| 94 | bool local_lease:1; /* check leases only on local system, not remote */ | 94 | bool local_lease:1; /* check leases only on local system, not remote */ |
| 95 | bool noblocksnd:1; | ||
| 96 | bool noautotune:1; | ||
| 95 | unsigned int rsize; | 97 | unsigned int rsize; |
| 96 | unsigned int wsize; | 98 | unsigned int wsize; |
| 97 | unsigned int sockopt; | 99 | unsigned int sockopt; |
| @@ -102,9 +104,11 @@ struct smb_vol { | |||
| 102 | static int ipv4_connect(struct sockaddr_in *psin_server, | 104 | static int ipv4_connect(struct sockaddr_in *psin_server, |
| 103 | struct socket **csocket, | 105 | struct socket **csocket, |
| 104 | char *netb_name, | 106 | char *netb_name, |
| 105 | char *server_netb_name); | 107 | char *server_netb_name, |
| 108 | bool noblocksnd, | ||
| 109 | bool nosndbuf); /* ipv6 never set sndbuf size */ | ||
| 106 | static int ipv6_connect(struct sockaddr_in6 *psin_server, | 110 | static int ipv6_connect(struct sockaddr_in6 *psin_server, |
| 107 | struct socket **csocket); | 111 | struct socket **csocket, bool noblocksnd); |
| 108 | 112 | ||
| 109 | 113 | ||
| 110 | /* | 114 | /* |
| @@ -191,12 +195,13 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 191 | try_to_freeze(); | 195 | try_to_freeze(); |
| 192 | if (server->protocolType == IPV6) { | 196 | if (server->protocolType == IPV6) { |
| 193 | rc = ipv6_connect(&server->addr.sockAddr6, | 197 | rc = ipv6_connect(&server->addr.sockAddr6, |
| 194 | &server->ssocket); | 198 | &server->ssocket, server->noautotune); |
| 195 | } else { | 199 | } else { |
| 196 | rc = ipv4_connect(&server->addr.sockAddr, | 200 | rc = ipv4_connect(&server->addr.sockAddr, |
| 197 | &server->ssocket, | 201 | &server->ssocket, |
| 198 | server->workstation_RFC1001_name, | 202 | server->workstation_RFC1001_name, |
| 199 | server->server_RFC1001_name); | 203 | server->server_RFC1001_name, |
| 204 | server->noblocksnd, server->noautotune); | ||
| 200 | } | 205 | } |
| 201 | if (rc) { | 206 | if (rc) { |
| 202 | cFYI(1, ("reconnect error %d", rc)); | 207 | cFYI(1, ("reconnect error %d", rc)); |
| @@ -1192,6 +1197,10 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1192 | /* ignore */ | 1197 | /* ignore */ |
| 1193 | } else if (strnicmp(data, "rw", 2) == 0) { | 1198 | } else if (strnicmp(data, "rw", 2) == 0) { |
| 1194 | vol->rw = true; | 1199 | vol->rw = true; |
| 1200 | } else if (strnicmp(data, "noblocksend", 11) == 0) { | ||
| 1201 | vol->noblocksnd = 1; | ||
| 1202 | } else if (strnicmp(data, "noautotune", 10) == 0) { | ||
| 1203 | vol->noautotune = 1; | ||
| 1195 | } else if ((strnicmp(data, "suid", 4) == 0) || | 1204 | } else if ((strnicmp(data, "suid", 4) == 0) || |
| 1196 | (strnicmp(data, "nosuid", 6) == 0) || | 1205 | (strnicmp(data, "nosuid", 6) == 0) || |
| 1197 | (strnicmp(data, "exec", 4) == 0) || | 1206 | (strnicmp(data, "exec", 4) == 0) || |
| @@ -1518,7 +1527,8 @@ static void rfc1002mangle(char *target, char *source, unsigned int length) | |||
| 1518 | 1527 | ||
| 1519 | static int | 1528 | static int |
| 1520 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | 1529 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, |
| 1521 | char *netbios_name, char *target_name) | 1530 | char *netbios_name, char *target_name, |
| 1531 | bool noblocksnd, bool noautotune) | ||
| 1522 | { | 1532 | { |
| 1523 | int rc = 0; | 1533 | int rc = 0; |
| 1524 | int connected = 0; | 1534 | int connected = 0; |
| @@ -1590,11 +1600,16 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1590 | (*csocket)->sk->sk_sndbuf, | 1600 | (*csocket)->sk->sk_sndbuf, |
| 1591 | (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); | 1601 | (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); |
| 1592 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; | 1602 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; |
| 1603 | if (!noblocksnd) | ||
| 1604 | (*csocket)->sk->sk_sndtimeo = 3 * HZ; | ||
| 1605 | |||
| 1593 | /* make the bufsizes depend on wsize/rsize and max requests */ | 1606 | /* make the bufsizes depend on wsize/rsize and max requests */ |
| 1594 | if ((*csocket)->sk->sk_sndbuf < (200 * 1024)) | 1607 | if (noautotune) { |
| 1595 | (*csocket)->sk->sk_sndbuf = 200 * 1024; | 1608 | if ((*csocket)->sk->sk_sndbuf < (200 * 1024)) |
| 1596 | if ((*csocket)->sk->sk_rcvbuf < (140 * 1024)) | 1609 | (*csocket)->sk->sk_sndbuf = 200 * 1024; |
| 1597 | (*csocket)->sk->sk_rcvbuf = 140 * 1024; | 1610 | if ((*csocket)->sk->sk_rcvbuf < (140 * 1024)) |
| 1611 | (*csocket)->sk->sk_rcvbuf = 140 * 1024; | ||
| 1612 | } | ||
| 1598 | 1613 | ||
| 1599 | /* send RFC1001 sessinit */ | 1614 | /* send RFC1001 sessinit */ |
| 1600 | if (psin_server->sin_port == htons(RFC1001_PORT)) { | 1615 | if (psin_server->sin_port == htons(RFC1001_PORT)) { |
| @@ -1631,7 +1646,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1631 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ | 1646 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ |
| 1632 | smb_buf->smb_buf_length = 0x81000044; | 1647 | smb_buf->smb_buf_length = 0x81000044; |
| 1633 | rc = smb_send(*csocket, smb_buf, 0x44, | 1648 | rc = smb_send(*csocket, smb_buf, 0x44, |
| 1634 | (struct sockaddr *)psin_server); | 1649 | (struct sockaddr *)psin_server, noblocksnd); |
| 1635 | kfree(ses_init_buf); | 1650 | kfree(ses_init_buf); |
| 1636 | msleep(1); /* RFC1001 layer in at least one server | 1651 | msleep(1); /* RFC1001 layer in at least one server |
| 1637 | requires very short break before negprot | 1652 | requires very short break before negprot |
| @@ -1651,7 +1666,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1651 | } | 1666 | } |
| 1652 | 1667 | ||
| 1653 | static int | 1668 | static int |
| 1654 | ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | 1669 | ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket, |
| 1670 | bool noblocksnd) | ||
| 1655 | { | 1671 | { |
| 1656 | int rc = 0; | 1672 | int rc = 0; |
| 1657 | int connected = 0; | 1673 | int connected = 0; |
| @@ -1720,6 +1736,9 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
| 1720 | the default. sock_setsockopt not used because it expects | 1736 | the default. sock_setsockopt not used because it expects |
| 1721 | user space buffer */ | 1737 | user space buffer */ |
| 1722 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; | 1738 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; |
| 1739 | if (!noblocksnd) | ||
| 1740 | (*csocket)->sk->sk_sndtimeo = 3 * HZ; | ||
| 1741 | |||
| 1723 | 1742 | ||
| 1724 | return rc; | 1743 | return rc; |
| 1725 | } | 1744 | } |
| @@ -1983,11 +2002,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1983 | cFYI(1, ("attempting ipv6 connect")); | 2002 | cFYI(1, ("attempting ipv6 connect")); |
| 1984 | /* BB should we allow ipv6 on port 139? */ | 2003 | /* BB should we allow ipv6 on port 139? */ |
| 1985 | /* other OS never observed in Wild doing 139 with v6 */ | 2004 | /* other OS never observed in Wild doing 139 with v6 */ |
| 1986 | rc = ipv6_connect(&sin_server6, &csocket); | 2005 | rc = ipv6_connect(&sin_server6, &csocket, |
| 2006 | volume_info.noblocksnd); | ||
| 1987 | } else | 2007 | } else |
| 1988 | rc = ipv4_connect(&sin_server, &csocket, | 2008 | rc = ipv4_connect(&sin_server, &csocket, |
| 1989 | volume_info.source_rfc1001_name, | 2009 | volume_info.source_rfc1001_name, |
| 1990 | volume_info.target_rfc1001_name); | 2010 | volume_info.target_rfc1001_name, |
| 2011 | volume_info.noblocksnd, | ||
| 2012 | volume_info.noautotune); | ||
| 1991 | if (rc < 0) { | 2013 | if (rc < 0) { |
| 1992 | cERROR(1, ("Error connecting to IPv4 socket. " | 2014 | cERROR(1, ("Error connecting to IPv4 socket. " |
| 1993 | "Aborting operation")); | 2015 | "Aborting operation")); |
| @@ -2002,6 +2024,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2002 | sock_release(csocket); | 2024 | sock_release(csocket); |
| 2003 | goto out; | 2025 | goto out; |
| 2004 | } else { | 2026 | } else { |
| 2027 | srvTcp->noblocksnd = volume_info.noblocksnd; | ||
| 2028 | srvTcp->noautotune = volume_info.noautotune; | ||
| 2005 | memcpy(&srvTcp->addr.sockAddr, &sin_server, | 2029 | memcpy(&srvTcp->addr.sockAddr, &sin_server, |
| 2006 | sizeof(struct sockaddr_in)); | 2030 | sizeof(struct sockaddr_in)); |
| 2007 | atomic_set(&srvTcp->inFlight, 0); | 2031 | atomic_set(&srvTcp->inFlight, 0); |
