aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorPavel Shilovsky <piastry@etersoft.ru>2012-03-20 05:55:09 -0400
committerSteve French <stevef@smf-gateway.(none)>2012-03-20 11:17:40 -0400
commit10b9b98e41ba248a899f6175ce96ee91431b6194 (patch)
tree8734af1f3e16d1836b2ce16f848828d4ac200f5f /fs/cifs
parentce85852b90a214cf577fc1b4f49d99fd7e98784a (diff)
CIFS: Respect negotiated MaxMpxCount
Some servers sets this value less than 50 that was hardcoded and we lost the connection if when we exceed this limit. Fix this by respecting this value - not sending more than the server allows. Cc: stable@kernel.org Reviewed-by: Jeff Layton <jlayton@samba.org> Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <stevef@smf-gateway.(none)>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsfs.c8
-rw-r--r--fs/cifs/cifsglob.h10
-rw-r--r--fs/cifs/cifssmb.c9
-rw-r--r--fs/cifs/connect.c11
-rw-r--r--fs/cifs/dir.c6
-rw-r--r--fs/cifs/file.c4
-rw-r--r--fs/cifs/transport.c4
7 files changed, 26 insertions, 26 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index b1fd382d1952..6ee1cb45ca0d 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -76,7 +76,7 @@ MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
76unsigned int cifs_max_pending = CIFS_MAX_REQ; 76unsigned int cifs_max_pending = CIFS_MAX_REQ;
77module_param(cifs_max_pending, int, 0444); 77module_param(cifs_max_pending, int, 0444);
78MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " 78MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
79 "Default: 50 Range: 2 to 256"); 79 "Default: 32767 Range: 2 to 32767.");
80unsigned short echo_retries = 5; 80unsigned short echo_retries = 5;
81module_param(echo_retries, ushort, 0644); 81module_param(echo_retries, ushort, 0644);
82MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and " 82MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
@@ -1116,9 +1116,9 @@ init_cifs(void)
1116 if (cifs_max_pending < 2) { 1116 if (cifs_max_pending < 2) {
1117 cifs_max_pending = 2; 1117 cifs_max_pending = 2;
1118 cFYI(1, "cifs_max_pending set to min of 2"); 1118 cFYI(1, "cifs_max_pending set to min of 2");
1119 } else if (cifs_max_pending > 256) { 1119 } else if (cifs_max_pending > CIFS_MAX_REQ) {
1120 cifs_max_pending = 256; 1120 cifs_max_pending = CIFS_MAX_REQ;
1121 cFYI(1, "cifs_max_pending set to max of 256"); 1121 cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ);
1122 } 1122 }
1123 1123
1124 rc = cifs_fscache_register(); 1124 rc = cifs_fscache_register();
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 76e7d8b6da17..d47d20aac670 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -55,14 +55,9 @@
55 55
56/* 56/*
57 * MAX_REQ is the maximum number of requests that WE will send 57 * MAX_REQ is the maximum number of requests that WE will send
58 * on one socket concurrently. It also matches the most common 58 * on one socket concurrently.
59 * value of max multiplex returned by servers. We may
60 * eventually want to use the negotiated value (in case
61 * future servers can handle more) when we are more confident that
62 * we will not have problems oveloading the socket with pending
63 * write data.
64 */ 59 */
65#define CIFS_MAX_REQ 50 60#define CIFS_MAX_REQ 32767
66 61
67#define RFC1001_NAME_LEN 15 62#define RFC1001_NAME_LEN 15
68#define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1) 63#define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1)
@@ -263,6 +258,7 @@ struct TCP_Server_Info {
263 bool session_estab; /* mark when very first sess is established */ 258 bool session_estab; /* mark when very first sess is established */
264 u16 dialect; /* dialect index that server chose */ 259 u16 dialect; /* dialect index that server chose */
265 enum securityEnum secType; 260 enum securityEnum secType;
261 bool oplocks:1; /* enable oplocks */
266 unsigned int maxReq; /* Clients should submit no more */ 262 unsigned int maxReq; /* Clients should submit no more */
267 /* than maxReq distinct unanswered SMBs to the server when using */ 263 /* than maxReq distinct unanswered SMBs to the server when using */
268 /* multiplexed reads or writes */ 264 /* multiplexed reads or writes */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 8b7794c31591..cd66b76e3282 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -458,7 +458,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
458 goto neg_err_exit; 458 goto neg_err_exit;
459 } 459 }
460 server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode); 460 server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
461 server->maxReq = le16_to_cpu(rsp->MaxMpxCount); 461 server->maxReq = min_t(unsigned int,
462 le16_to_cpu(rsp->MaxMpxCount),
463 cifs_max_pending);
464 server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
462 server->maxBuf = le16_to_cpu(rsp->MaxBufSize); 465 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
463 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); 466 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
464 /* even though we do not use raw we might as well set this 467 /* even though we do not use raw we might as well set this
@@ -564,7 +567,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
564 567
565 /* one byte, so no need to convert this or EncryptionKeyLen from 568 /* one byte, so no need to convert this or EncryptionKeyLen from
566 little endian */ 569 little endian */
567 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); 570 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
571 cifs_max_pending);
572 server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
568 /* probably no need to store and check maxvcs */ 573 /* probably no need to store and check maxvcs */
569 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize); 574 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
570 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); 575 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 602f77c304c9..03f71fb40a8a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -642,14 +642,10 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
642 spin_unlock(&GlobalMid_Lock); 642 spin_unlock(&GlobalMid_Lock);
643 wake_up_all(&server->response_q); 643 wake_up_all(&server->response_q);
644 644
645 /* 645 /* Check if we have blocked requests that need to free. */
646 * Check if we have blocked requests that need to free. Note that
647 * cifs_max_pending is normally 50, but can be set at module install
648 * time to as little as two.
649 */
650 spin_lock(&GlobalMid_Lock); 646 spin_lock(&GlobalMid_Lock);
651 if (atomic_read(&server->inFlight) >= cifs_max_pending) 647 if (atomic_read(&server->inFlight) >= server->maxReq)
652 atomic_set(&server->inFlight, cifs_max_pending - 1); 648 atomic_set(&server->inFlight, server->maxReq - 1);
653 /* 649 /*
654 * We do not want to set the max_pending too low or we could end up 650 * We do not want to set the max_pending too low or we could end up
655 * with the counter going negative. 651 * with the counter going negative.
@@ -1910,6 +1906,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1910 tcp_ses->noautotune = volume_info->noautotune; 1906 tcp_ses->noautotune = volume_info->noautotune;
1911 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; 1907 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
1912 atomic_set(&tcp_ses->inFlight, 0); 1908 atomic_set(&tcp_ses->inFlight, 0);
1909 tcp_ses->maxReq = 1; /* enough to send negotiate request */
1913 init_waitqueue_head(&tcp_ses->response_q); 1910 init_waitqueue_head(&tcp_ses->response_q);
1914 init_waitqueue_head(&tcp_ses->request_q); 1911 init_waitqueue_head(&tcp_ses->request_q);
1915 INIT_LIST_HEAD(&tcp_ses->pending_mid_q); 1912 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index bc7e24420ac0..d172c8ed9017 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -171,7 +171,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
171 } 171 }
172 tcon = tlink_tcon(tlink); 172 tcon = tlink_tcon(tlink);
173 173
174 if (enable_oplocks) 174 if (tcon->ses->server->oplocks)
175 oplock = REQ_OPLOCK; 175 oplock = REQ_OPLOCK;
176 176
177 if (nd) 177 if (nd)
@@ -492,7 +492,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
492{ 492{
493 int xid; 493 int xid;
494 int rc = 0; /* to get around spurious gcc warning, set to zero here */ 494 int rc = 0; /* to get around spurious gcc warning, set to zero here */
495 __u32 oplock = enable_oplocks ? REQ_OPLOCK : 0; 495 __u32 oplock;
496 __u16 fileHandle = 0; 496 __u16 fileHandle = 0;
497 bool posix_open = false; 497 bool posix_open = false;
498 struct cifs_sb_info *cifs_sb; 498 struct cifs_sb_info *cifs_sb;
@@ -518,6 +518,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
518 } 518 }
519 pTcon = tlink_tcon(tlink); 519 pTcon = tlink_tcon(tlink);
520 520
521 oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0;
522
521 /* 523 /*
522 * Don't allow the separator character in a path component. 524 * Don't allow the separator character in a path component.
523 * The VFS will not allow "/", but "\" is allowed by posix. 525 * The VFS will not allow "/", but "\" is allowed by posix.
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 8e02dbd88ae1..159fcc56dc2d 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -380,7 +380,7 @@ int cifs_open(struct inode *inode, struct file *file)
380 cFYI(1, "inode = 0x%p file flags are 0x%x for %s", 380 cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
381 inode, file->f_flags, full_path); 381 inode, file->f_flags, full_path);
382 382
383 if (enable_oplocks) 383 if (tcon->ses->server->oplocks)
384 oplock = REQ_OPLOCK; 384 oplock = REQ_OPLOCK;
385 else 385 else
386 oplock = 0; 386 oplock = 0;
@@ -505,7 +505,7 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
505 cFYI(1, "inode = 0x%p file flags 0x%x for %s", 505 cFYI(1, "inode = 0x%p file flags 0x%x for %s",
506 inode, pCifsFile->f_flags, full_path); 506 inode, pCifsFile->f_flags, full_path);
507 507
508 if (enable_oplocks) 508 if (tcon->ses->server->oplocks)
509 oplock = REQ_OPLOCK; 509 oplock = REQ_OPLOCK;
510 else 510 else
511 oplock = 0; 511 oplock = 0;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 0cc9584f5889..99a27cfa6cd2 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -265,12 +265,12 @@ static int wait_for_free_request(struct TCP_Server_Info *server,
265 265
266 spin_lock(&GlobalMid_Lock); 266 spin_lock(&GlobalMid_Lock);
267 while (1) { 267 while (1) {
268 if (atomic_read(&server->inFlight) >= cifs_max_pending) { 268 if (atomic_read(&server->inFlight) >= server->maxReq) {
269 spin_unlock(&GlobalMid_Lock); 269 spin_unlock(&GlobalMid_Lock);
270 cifs_num_waiters_inc(server); 270 cifs_num_waiters_inc(server);
271 wait_event(server->request_q, 271 wait_event(server->request_q,
272 atomic_read(&server->inFlight) 272 atomic_read(&server->inFlight)
273 < cifs_max_pending); 273 < server->maxReq);
274 cifs_num_waiters_dec(server); 274 cifs_num_waiters_dec(server);
275 spin_lock(&GlobalMid_Lock); 275 spin_lock(&GlobalMid_Lock);
276 } else { 276 } else {