diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 63ea83ff687f..d9566bf8f917 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/wait.h> | 25 | #include <linux/wait.h> |
26 | #include <linux/slab.h> | ||
26 | #include <linux/pagemap.h> | 27 | #include <linux/pagemap.h> |
27 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
28 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
@@ -98,7 +99,7 @@ struct smb_vol { | |||
98 | bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ | 99 | bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ |
99 | unsigned int rsize; | 100 | unsigned int rsize; |
100 | unsigned int wsize; | 101 | unsigned int wsize; |
101 | unsigned int sockopt; | 102 | bool sockopt_tcp_nodelay:1; |
102 | unsigned short int port; | 103 | unsigned short int port; |
103 | char *prepath; | 104 | char *prepath; |
104 | }; | 105 | }; |
@@ -1142,9 +1143,11 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1142 | simple_strtoul(value, &value, 0); | 1143 | simple_strtoul(value, &value, 0); |
1143 | } | 1144 | } |
1144 | } else if (strnicmp(data, "sockopt", 5) == 0) { | 1145 | } else if (strnicmp(data, "sockopt", 5) == 0) { |
1145 | if (value && *value) { | 1146 | if (!value || !*value) { |
1146 | vol->sockopt = | 1147 | cERROR(1, ("no socket option specified")); |
1147 | simple_strtoul(value, &value, 0); | 1148 | continue; |
1149 | } else if (strnicmp(value, "TCP_NODELAY", 11) == 0) { | ||
1150 | vol->sockopt_tcp_nodelay = 1; | ||
1148 | } | 1151 | } |
1149 | } else if (strnicmp(data, "netbiosname", 4) == 0) { | 1152 | } else if (strnicmp(data, "netbiosname", 4) == 0) { |
1150 | if (!value || !*value || (*value == ' ')) { | 1153 | if (!value || !*value || (*value == ' ')) { |
@@ -1514,6 +1517,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1514 | 1517 | ||
1515 | tcp_ses->noblocksnd = volume_info->noblocksnd; | 1518 | tcp_ses->noblocksnd = volume_info->noblocksnd; |
1516 | tcp_ses->noautotune = volume_info->noautotune; | 1519 | tcp_ses->noautotune = volume_info->noautotune; |
1520 | tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; | ||
1517 | atomic_set(&tcp_ses->inFlight, 0); | 1521 | atomic_set(&tcp_ses->inFlight, 0); |
1518 | init_waitqueue_head(&tcp_ses->response_q); | 1522 | init_waitqueue_head(&tcp_ses->response_q); |
1519 | init_waitqueue_head(&tcp_ses->request_q); | 1523 | init_waitqueue_head(&tcp_ses->request_q); |
@@ -1764,6 +1768,7 @@ static int | |||
1764 | ipv4_connect(struct TCP_Server_Info *server) | 1768 | ipv4_connect(struct TCP_Server_Info *server) |
1765 | { | 1769 | { |
1766 | int rc = 0; | 1770 | int rc = 0; |
1771 | int val; | ||
1767 | bool connected = false; | 1772 | bool connected = false; |
1768 | __be16 orig_port = 0; | 1773 | __be16 orig_port = 0; |
1769 | struct socket *socket = server->ssocket; | 1774 | struct socket *socket = server->ssocket; |
@@ -1845,6 +1850,14 @@ ipv4_connect(struct TCP_Server_Info *server) | |||
1845 | socket->sk->sk_rcvbuf = 140 * 1024; | 1850 | socket->sk->sk_rcvbuf = 140 * 1024; |
1846 | } | 1851 | } |
1847 | 1852 | ||
1853 | if (server->tcp_nodelay) { | ||
1854 | val = 1; | ||
1855 | rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY, | ||
1856 | (char *)&val, sizeof(val)); | ||
1857 | if (rc) | ||
1858 | cFYI(1, ("set TCP_NODELAY socket option error %d", rc)); | ||
1859 | } | ||
1860 | |||
1848 | cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx", | 1861 | cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx", |
1849 | socket->sk->sk_sndbuf, | 1862 | socket->sk->sk_sndbuf, |
1850 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo)); | 1863 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo)); |
@@ -1916,6 +1929,7 @@ static int | |||
1916 | ipv6_connect(struct TCP_Server_Info *server) | 1929 | ipv6_connect(struct TCP_Server_Info *server) |
1917 | { | 1930 | { |
1918 | int rc = 0; | 1931 | int rc = 0; |
1932 | int val; | ||
1919 | bool connected = false; | 1933 | bool connected = false; |
1920 | __be16 orig_port = 0; | 1934 | __be16 orig_port = 0; |
1921 | struct socket *socket = server->ssocket; | 1935 | struct socket *socket = server->ssocket; |
@@ -1987,6 +2001,15 @@ ipv6_connect(struct TCP_Server_Info *server) | |||
1987 | */ | 2001 | */ |
1988 | socket->sk->sk_rcvtimeo = 7 * HZ; | 2002 | socket->sk->sk_rcvtimeo = 7 * HZ; |
1989 | socket->sk->sk_sndtimeo = 5 * HZ; | 2003 | socket->sk->sk_sndtimeo = 5 * HZ; |
2004 | |||
2005 | if (server->tcp_nodelay) { | ||
2006 | val = 1; | ||
2007 | rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY, | ||
2008 | (char *)&val, sizeof(val)); | ||
2009 | if (rc) | ||
2010 | cFYI(1, ("set TCP_NODELAY socket option error %d", rc)); | ||
2011 | } | ||
2012 | |||
1990 | server->ssocket = socket; | 2013 | server->ssocket = socket; |
1991 | 2014 | ||
1992 | return rc; | 2015 | return rc; |
@@ -2287,12 +2310,12 @@ int | |||
2287 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 2310 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, |
2288 | char *mount_data_global, const char *devname) | 2311 | char *mount_data_global, const char *devname) |
2289 | { | 2312 | { |
2290 | int rc = 0; | 2313 | int rc; |
2291 | int xid; | 2314 | int xid; |
2292 | struct smb_vol *volume_info; | 2315 | struct smb_vol *volume_info; |
2293 | struct cifsSesInfo *pSesInfo = NULL; | 2316 | struct cifsSesInfo *pSesInfo; |
2294 | struct cifsTconInfo *tcon = NULL; | 2317 | struct cifsTconInfo *tcon; |
2295 | struct TCP_Server_Info *srvTcp = NULL; | 2318 | struct TCP_Server_Info *srvTcp; |
2296 | char *full_path; | 2319 | char *full_path; |
2297 | char *mount_data = mount_data_global; | 2320 | char *mount_data = mount_data_global; |
2298 | #ifdef CONFIG_CIFS_DFS_UPCALL | 2321 | #ifdef CONFIG_CIFS_DFS_UPCALL |
@@ -2301,6 +2324,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2301 | int referral_walks_count = 0; | 2324 | int referral_walks_count = 0; |
2302 | try_mount_again: | 2325 | try_mount_again: |
2303 | #endif | 2326 | #endif |
2327 | rc = 0; | ||
2328 | tcon = NULL; | ||
2329 | pSesInfo = NULL; | ||
2330 | srvTcp = NULL; | ||
2304 | full_path = NULL; | 2331 | full_path = NULL; |
2305 | 2332 | ||
2306 | xid = GetXid(); | 2333 | xid = GetXid(); |
@@ -2362,13 +2389,13 @@ try_mount_again: | |||
2362 | */ | 2389 | */ |
2363 | cifs_put_tcp_session(srvTcp); | 2390 | cifs_put_tcp_session(srvTcp); |
2364 | 2391 | ||
2365 | down(&pSesInfo->sesSem); | 2392 | mutex_lock(&pSesInfo->session_mutex); |
2366 | if (pSesInfo->need_reconnect) { | 2393 | if (pSesInfo->need_reconnect) { |
2367 | cFYI(1, ("Session needs reconnect")); | 2394 | cFYI(1, ("Session needs reconnect")); |
2368 | rc = cifs_setup_session(xid, pSesInfo, | 2395 | rc = cifs_setup_session(xid, pSesInfo, |
2369 | cifs_sb->local_nls); | 2396 | cifs_sb->local_nls); |
2370 | } | 2397 | } |
2371 | up(&pSesInfo->sesSem); | 2398 | mutex_unlock(&pSesInfo->session_mutex); |
2372 | } else if (!rc) { | 2399 | } else if (!rc) { |
2373 | cFYI(1, ("Existing smb sess not found")); | 2400 | cFYI(1, ("Existing smb sess not found")); |
2374 | pSesInfo = sesInfoAlloc(); | 2401 | pSesInfo = sesInfoAlloc(); |
@@ -2411,12 +2438,12 @@ try_mount_again: | |||
2411 | } | 2438 | } |
2412 | pSesInfo->linux_uid = volume_info->linux_uid; | 2439 | pSesInfo->linux_uid = volume_info->linux_uid; |
2413 | pSesInfo->overrideSecFlg = volume_info->secFlg; | 2440 | pSesInfo->overrideSecFlg = volume_info->secFlg; |
2414 | down(&pSesInfo->sesSem); | 2441 | mutex_lock(&pSesInfo->session_mutex); |
2415 | 2442 | ||
2416 | /* BB FIXME need to pass vol->secFlgs BB */ | 2443 | /* BB FIXME need to pass vol->secFlgs BB */ |
2417 | rc = cifs_setup_session(xid, pSesInfo, | 2444 | rc = cifs_setup_session(xid, pSesInfo, |
2418 | cifs_sb->local_nls); | 2445 | cifs_sb->local_nls); |
2419 | up(&pSesInfo->sesSem); | 2446 | mutex_unlock(&pSesInfo->session_mutex); |
2420 | } | 2447 | } |
2421 | 2448 | ||
2422 | /* search for existing tcon to this server share */ | 2449 | /* search for existing tcon to this server share */ |
@@ -2597,6 +2624,7 @@ remote_path_check: | |||
2597 | 2624 | ||
2598 | cleanup_volume_info(&volume_info); | 2625 | cleanup_volume_info(&volume_info); |
2599 | referral_walks_count++; | 2626 | referral_walks_count++; |
2627 | FreeXid(xid); | ||
2600 | goto try_mount_again; | 2628 | goto try_mount_again; |
2601 | } | 2629 | } |
2602 | #else /* No DFS support, return error on mount */ | 2630 | #else /* No DFS support, return error on mount */ |