aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/README6
-rw-r--r--fs/cifs/cifs_debug.c3
-rw-r--r--fs/cifs/cifsfs.c25
-rw-r--r--fs/cifs/cifsglob.h47
-rw-r--r--fs/cifs/cifsproto.h9
-rw-r--r--fs/cifs/cifssmb.c18
-rw-r--r--fs/cifs/connect.c44
-rw-r--r--fs/cifs/dir.c6
-rw-r--r--fs/cifs/file.c23
-rw-r--r--fs/cifs/misc.c19
-rw-r--r--fs/cifs/transport.c78
11 files changed, 169 insertions, 109 deletions
diff --git a/fs/cifs/README b/fs/cifs/README
index 895da1dc1550..b7d782bab797 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -753,10 +753,6 @@ module loading or during the runtime by using the interface
753 753
754i.e. echo "value" > /sys/module/cifs/parameters/<param> 754i.e. echo "value" > /sys/module/cifs/parameters/<param>
755 755
7561. echo_retries - The number of echo attempts before giving up and 7561. enable_oplocks - Enable or disable oplocks. Oplocks are enabled by default.
757 reconnecting to the server. The default is 5. The value 0
758 means never reconnect.
759
7602. enable_oplocks - Enable or disable oplocks. Oplocks are enabled by default.
761 [Y/y/1]. To disable use any of [N/n/0]. 757 [Y/y/1]. To disable use any of [N/n/0].
762 758
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 24b3dfc05282..573b899b5a5d 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -171,8 +171,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
171 seq_printf(m, "TCP status: %d\n\tLocal Users To " 171 seq_printf(m, "TCP status: %d\n\tLocal Users To "
172 "Server: %d SecMode: 0x%x Req On Wire: %d", 172 "Server: %d SecMode: 0x%x Req On Wire: %d",
173 server->tcpStatus, server->srv_count, 173 server->tcpStatus, server->srv_count,
174 server->sec_mode, 174 server->sec_mode, in_flight(server));
175 atomic_read(&server->inFlight));
176 175
177#ifdef CONFIG_CIFS_STATS2 176#ifdef CONFIG_CIFS_STATS2
178 seq_printf(m, " In Send: %d In MaxReq Wait: %d", 177 seq_printf(m, " In Send: %d In MaxReq Wait: %d",
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 418fc42fb8b2..eee522c56ef0 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -76,12 +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;
81module_param(echo_retries, ushort, 0644);
82MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
83 "reconnecting server. Default: 5. 0 means "
84 "never reconnect.");
85module_param(enable_oplocks, bool, 0644); 80module_param(enable_oplocks, bool, 0644);
86MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks (bool). Default:" 81MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks (bool). Default:"
87 "y/Y/1"); 82 "y/Y/1");
@@ -1111,9 +1106,9 @@ init_cifs(void)
1111 if (cifs_max_pending < 2) { 1106 if (cifs_max_pending < 2) {
1112 cifs_max_pending = 2; 1107 cifs_max_pending = 2;
1113 cFYI(1, "cifs_max_pending set to min of 2"); 1108 cFYI(1, "cifs_max_pending set to min of 2");
1114 } else if (cifs_max_pending > 256) { 1109 } else if (cifs_max_pending > CIFS_MAX_REQ) {
1115 cifs_max_pending = 256; 1110 cifs_max_pending = CIFS_MAX_REQ;
1116 cFYI(1, "cifs_max_pending set to max of 256"); 1111 cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ);
1117 } 1112 }
1118 1113
1119 rc = cifs_fscache_register(); 1114 rc = cifs_fscache_register();
@@ -1175,11 +1170,8 @@ static void __exit
1175exit_cifs(void) 1170exit_cifs(void)
1176{ 1171{
1177 cFYI(DBG2, "exit_cifs"); 1172 cFYI(DBG2, "exit_cifs");
1178 cifs_proc_clean(); 1173 unregister_filesystem(&cifs_fs_type);
1179 cifs_fscache_unregister();
1180#ifdef CONFIG_CIFS_DFS_UPCALL
1181 cifs_dfs_release_automount_timer(); 1174 cifs_dfs_release_automount_timer();
1182#endif
1183#ifdef CONFIG_CIFS_ACL 1175#ifdef CONFIG_CIFS_ACL
1184 cifs_destroy_idmaptrees(); 1176 cifs_destroy_idmaptrees();
1185 exit_cifs_idmap(); 1177 exit_cifs_idmap();
@@ -1187,10 +1179,11 @@ exit_cifs(void)
1187#ifdef CONFIG_CIFS_UPCALL 1179#ifdef CONFIG_CIFS_UPCALL
1188 unregister_key_type(&cifs_spnego_key_type); 1180 unregister_key_type(&cifs_spnego_key_type);
1189#endif 1181#endif
1190 unregister_filesystem(&cifs_fs_type);
1191 cifs_destroy_inodecache();
1192 cifs_destroy_mids();
1193 cifs_destroy_request_bufs(); 1182 cifs_destroy_request_bufs();
1183 cifs_destroy_mids();
1184 cifs_destroy_inodecache();
1185 cifs_fscache_unregister();
1186 cifs_proc_clean();
1194} 1187}
1195 1188
1196MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); 1189MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 76e7d8b6da17..339ebe3ebc0d 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)
@@ -255,7 +250,9 @@ struct TCP_Server_Info {
255 bool noblocksnd; /* use blocking sendmsg */ 250 bool noblocksnd; /* use blocking sendmsg */
256 bool noautotune; /* do not autotune send buf sizes */ 251 bool noautotune; /* do not autotune send buf sizes */
257 bool tcp_nodelay; 252 bool tcp_nodelay;
258 atomic_t inFlight; /* number of requests on the wire to server */ 253 int credits; /* send no more requests at once */
254 unsigned int in_flight; /* number of requests on the wire to server */
255 spinlock_t req_lock; /* protect the two values above */
259 struct mutex srv_mutex; 256 struct mutex srv_mutex;
260 struct task_struct *tsk; 257 struct task_struct *tsk;
261 char server_GUID[16]; 258 char server_GUID[16];
@@ -263,6 +260,7 @@ struct TCP_Server_Info {
263 bool session_estab; /* mark when very first sess is established */ 260 bool session_estab; /* mark when very first sess is established */
264 u16 dialect; /* dialect index that server chose */ 261 u16 dialect; /* dialect index that server chose */
265 enum securityEnum secType; 262 enum securityEnum secType;
263 bool oplocks:1; /* enable oplocks */
266 unsigned int maxReq; /* Clients should submit no more */ 264 unsigned int maxReq; /* Clients should submit no more */
267 /* than maxReq distinct unanswered SMBs to the server when using */ 265 /* than maxReq distinct unanswered SMBs to the server when using */
268 /* multiplexed reads or writes */ 266 /* multiplexed reads or writes */
@@ -307,6 +305,36 @@ struct TCP_Server_Info {
307#endif 305#endif
308}; 306};
309 307
308static inline unsigned int
309in_flight(struct TCP_Server_Info *server)
310{
311 unsigned int num;
312 spin_lock(&server->req_lock);
313 num = server->in_flight;
314 spin_unlock(&server->req_lock);
315 return num;
316}
317
318static inline int*
319get_credits_field(struct TCP_Server_Info *server)
320{
321 /*
322 * This will change to switch statement when we reserve slots for echos
323 * and oplock breaks.
324 */
325 return &server->credits;
326}
327
328static inline bool
329has_credits(struct TCP_Server_Info *server, int *credits)
330{
331 int num;
332 spin_lock(&server->req_lock);
333 num = *credits;
334 spin_unlock(&server->req_lock);
335 return num > 0;
336}
337
310/* 338/*
311 * Macros to allow the TCP_Server_Info->net field and related code to drop out 339 * Macros to allow the TCP_Server_Info->net field and related code to drop out
312 * when CONFIG_NET_NS isn't set. 340 * when CONFIG_NET_NS isn't set.
@@ -1010,9 +1038,6 @@ GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
1010GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ 1038GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */
1011GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ 1039GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
1012 1040
1013/* reconnect after this many failed echo attempts */
1014GLOBAL_EXTERN unsigned short echo_retries;
1015
1016#ifdef CONFIG_CIFS_ACL 1041#ifdef CONFIG_CIFS_ACL
1017GLOBAL_EXTERN struct rb_root uidtree; 1042GLOBAL_EXTERN struct rb_root uidtree;
1018GLOBAL_EXTERN struct rb_root gidtree; 1043GLOBAL_EXTERN struct rb_root gidtree;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 6f4e243e0f62..503e73d8bdb7 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -88,6 +88,9 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
88 struct smb_hdr *in_buf , 88 struct smb_hdr *in_buf ,
89 struct smb_hdr *out_buf, 89 struct smb_hdr *out_buf,
90 int *bytes_returned); 90 int *bytes_returned);
91extern void cifs_add_credits(struct TCP_Server_Info *server,
92 const unsigned int add);
93extern void cifs_set_credits(struct TCP_Server_Info *server, const int val);
91extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); 94extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
92extern bool is_valid_oplock_break(struct smb_hdr *smb, 95extern bool is_valid_oplock_break(struct smb_hdr *smb,
93 struct TCP_Server_Info *); 96 struct TCP_Server_Info *);
@@ -168,7 +171,13 @@ extern struct smb_vol *cifs_get_volume_info(char *mount_data,
168 const char *devname); 171 const char *devname);
169extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); 172extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
170extern void cifs_umount(struct cifs_sb_info *); 173extern void cifs_umount(struct cifs_sb_info *);
174
175#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
171extern void cifs_dfs_release_automount_timer(void); 176extern void cifs_dfs_release_automount_timer(void);
177#else /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */
178#define cifs_dfs_release_automount_timer() do { } while (0)
179#endif /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */
180
172void cifs_proc_init(void); 181void cifs_proc_init(void);
173void cifs_proc_clean(void); 182void cifs_proc_clean(void);
174 183
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 8b7794c31591..70aac35c398f 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 cifs_set_credits(server, server->maxReq);
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 cifs_set_credits(server, server->maxReq);
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);
@@ -716,8 +721,7 @@ cifs_echo_callback(struct mid_q_entry *mid)
716 struct TCP_Server_Info *server = mid->callback_data; 721 struct TCP_Server_Info *server = mid->callback_data;
717 722
718 DeleteMidQEntry(mid); 723 DeleteMidQEntry(mid);
719 atomic_dec(&server->inFlight); 724 cifs_add_credits(server, 1);
720 wake_up(&server->request_q);
721} 725}
722 726
723int 727int
@@ -1669,8 +1673,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
1669 1673
1670 queue_work(system_nrt_wq, &rdata->work); 1674 queue_work(system_nrt_wq, &rdata->work);
1671 DeleteMidQEntry(mid); 1675 DeleteMidQEntry(mid);
1672 atomic_dec(&server->inFlight); 1676 cifs_add_credits(server, 1);
1673 wake_up(&server->request_q);
1674} 1677}
1675 1678
1676/* cifs_async_readv - send an async write, and set up mid to handle result */ 1679/* cifs_async_readv - send an async write, and set up mid to handle result */
@@ -2110,8 +2113,7 @@ cifs_writev_callback(struct mid_q_entry *mid)
2110 2113
2111 queue_work(system_nrt_wq, &wdata->work); 2114 queue_work(system_nrt_wq, &wdata->work);
2112 DeleteMidQEntry(mid); 2115 DeleteMidQEntry(mid);
2113 atomic_dec(&tcon->ses->server->inFlight); 2116 cifs_add_credits(tcon->ses->server, 1);
2114 wake_up(&tcon->ses->server->request_q);
2115} 2117}
2116 2118
2117/* cifs_async_writev - send an async write, and set up mid to handle result */ 2119/* cifs_async_writev - send an async write, and set up mid to handle result */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 602f77c304c9..5560e1d5e54b 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -373,12 +373,22 @@ allocate_buffers(struct TCP_Server_Info *server)
373static bool 373static bool
374server_unresponsive(struct TCP_Server_Info *server) 374server_unresponsive(struct TCP_Server_Info *server)
375{ 375{
376 if (echo_retries > 0 && server->tcpStatus == CifsGood && 376 /*
377 time_after(jiffies, server->lstrp + 377 * We need to wait 2 echo intervals to make sure we handle such
378 (echo_retries * SMB_ECHO_INTERVAL))) { 378 * situations right:
379 * 1s client sends a normal SMB request
380 * 2s client gets a response
381 * 30s echo workqueue job pops, and decides we got a response recently
382 * and don't need to send another
383 * ...
384 * 65s kernel_recvmsg times out, and we see that we haven't gotten
385 * a response in >60s.
386 */
387 if (server->tcpStatus == CifsGood &&
388 time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
379 cERROR(1, "Server %s has not responded in %d seconds. " 389 cERROR(1, "Server %s has not responded in %d seconds. "
380 "Reconnecting...", server->hostname, 390 "Reconnecting...", server->hostname,
381 (echo_retries * SMB_ECHO_INTERVAL / HZ)); 391 (2 * SMB_ECHO_INTERVAL) / HZ);
382 cifs_reconnect(server); 392 cifs_reconnect(server);
383 wake_up(&server->response_q); 393 wake_up(&server->response_q);
384 return true; 394 return true;
@@ -642,19 +652,11 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
642 spin_unlock(&GlobalMid_Lock); 652 spin_unlock(&GlobalMid_Lock);
643 wake_up_all(&server->response_q); 653 wake_up_all(&server->response_q);
644 654
645 /* 655 /* check if we have blocked requests that need to free */
646 * Check if we have blocked requests that need to free. Note that 656 spin_lock(&server->req_lock);
647 * cifs_max_pending is normally 50, but can be set at module install 657 if (server->credits <= 0)
648 * time to as little as two. 658 server->credits = 1;
649 */ 659 spin_unlock(&server->req_lock);
650 spin_lock(&GlobalMid_Lock);
651 if (atomic_read(&server->inFlight) >= cifs_max_pending)
652 atomic_set(&server->inFlight, cifs_max_pending - 1);
653 /*
654 * We do not want to set the max_pending too low or we could end up
655 * with the counter going negative.
656 */
657 spin_unlock(&GlobalMid_Lock);
658 /* 660 /*
659 * Although there should not be any requests blocked on this queue it 661 * Although there should not be any requests blocked on this queue it
660 * can not hurt to be paranoid and try to wake up requests that may 662 * can not hurt to be paranoid and try to wake up requests that may
@@ -1909,7 +1911,8 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1909 tcp_ses->noblocksnd = volume_info->noblocksnd; 1911 tcp_ses->noblocksnd = volume_info->noblocksnd;
1910 tcp_ses->noautotune = volume_info->noautotune; 1912 tcp_ses->noautotune = volume_info->noautotune;
1911 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; 1913 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
1912 atomic_set(&tcp_ses->inFlight, 0); 1914 tcp_ses->in_flight = 0;
1915 tcp_ses->credits = 1;
1913 init_waitqueue_head(&tcp_ses->response_q); 1916 init_waitqueue_head(&tcp_ses->response_q);
1914 init_waitqueue_head(&tcp_ses->request_q); 1917 init_waitqueue_head(&tcp_ses->request_q);
1915 INIT_LIST_HEAD(&tcp_ses->pending_mid_q); 1918 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
@@ -3371,7 +3374,7 @@ cifs_ra_pages(struct cifs_sb_info *cifs_sb)
3371int 3374int
3372cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) 3375cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
3373{ 3376{
3374 int rc = 0; 3377 int rc;
3375 int xid; 3378 int xid;
3376 struct cifs_ses *pSesInfo; 3379 struct cifs_ses *pSesInfo;
3377 struct cifs_tcon *tcon; 3380 struct cifs_tcon *tcon;
@@ -3398,6 +3401,7 @@ try_mount_again:
3398 FreeXid(xid); 3401 FreeXid(xid);
3399 } 3402 }
3400#endif 3403#endif
3404 rc = 0;
3401 tcon = NULL; 3405 tcon = NULL;
3402 pSesInfo = NULL; 3406 pSesInfo = NULL;
3403 srvTcp = NULL; 3407 srvTcp = NULL;
@@ -3759,9 +3763,11 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
3759 if (server->maxBuf != 0) 3763 if (server->maxBuf != 0)
3760 return 0; 3764 return 0;
3761 3765
3766 cifs_set_credits(server, 1);
3762 rc = CIFSSMBNegotiate(xid, ses); 3767 rc = CIFSSMBNegotiate(xid, ses);
3763 if (rc == -EAGAIN) { 3768 if (rc == -EAGAIN) {
3764 /* retry only once on 1st time connection */ 3769 /* retry only once on 1st time connection */
3770 cifs_set_credits(server, 1);
3765 rc = CIFSSMBNegotiate(xid, ses); 3771 rc = CIFSSMBNegotiate(xid, ses);
3766 if (rc == -EAGAIN) 3772 if (rc == -EAGAIN)
3767 rc = -EHOSTDOWN; 3773 rc = -EHOSTDOWN;
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 5e64748a2917..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;
@@ -960,9 +960,9 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
960 INIT_LIST_HEAD(&locks_to_send); 960 INIT_LIST_HEAD(&locks_to_send);
961 961
962 /* 962 /*
963 * Allocating count locks is enough because no locks can be added to 963 * Allocating count locks is enough because no FL_POSIX locks can be
964 * the list while we are holding cinode->lock_mutex that protects 964 * added to the list while we are holding cinode->lock_mutex that
965 * locking operations of this inode. 965 * protects locking operations of this inode.
966 */ 966 */
967 for (; i < count; i++) { 967 for (; i < count; i++) {
968 lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL); 968 lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
@@ -973,18 +973,20 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
973 list_add_tail(&lck->llist, &locks_to_send); 973 list_add_tail(&lck->llist, &locks_to_send);
974 } 974 }
975 975
976 i = 0;
977 el = locks_to_send.next; 976 el = locks_to_send.next;
978 lock_flocks(); 977 lock_flocks();
979 cifs_for_each_lock(cfile->dentry->d_inode, before) { 978 cifs_for_each_lock(cfile->dentry->d_inode, before) {
979 flock = *before;
980 if ((flock->fl_flags & FL_POSIX) == 0)
981 continue;
980 if (el == &locks_to_send) { 982 if (el == &locks_to_send) {
981 /* something is really wrong */ 983 /*
984 * The list ended. We don't have enough allocated
985 * structures - something is really wrong.
986 */
982 cERROR(1, "Can't push all brlocks!"); 987 cERROR(1, "Can't push all brlocks!");
983 break; 988 break;
984 } 989 }
985 flock = *before;
986 if ((flock->fl_flags & FL_POSIX) == 0)
987 continue;
988 length = 1 + flock->fl_end - flock->fl_start; 990 length = 1 + flock->fl_end - flock->fl_start;
989 if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK) 991 if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
990 type = CIFS_RDLCK; 992 type = CIFS_RDLCK;
@@ -996,7 +998,6 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
996 lck->length = length; 998 lck->length = length;
997 lck->type = type; 999 lck->type = type;
998 lck->offset = flock->fl_start; 1000 lck->offset = flock->fl_start;
999 i++;
1000 el = el->next; 1001 el = el->next;
1001 } 1002 }
1002 unlock_flocks(); 1003 unlock_flocks();
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 703ef5c6fdb1..c273c12de98e 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -690,3 +690,22 @@ backup_cred(struct cifs_sb_info *cifs_sb)
690 690
691 return false; 691 return false;
692} 692}
693
694void
695cifs_add_credits(struct TCP_Server_Info *server, const unsigned int add)
696{
697 spin_lock(&server->req_lock);
698 server->credits += add;
699 server->in_flight--;
700 spin_unlock(&server->req_lock);
701 wake_up(&server->request_q);
702}
703
704void
705cifs_set_credits(struct TCP_Server_Info *server, const int val)
706{
707 spin_lock(&server->req_lock);
708 server->credits = val;
709 server->oplocks = val > 1 ? enable_oplocks : false;
710 spin_unlock(&server->req_lock);
711}
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 0cc9584f5889..310918b6fcb4 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -254,44 +254,60 @@ smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
254 return smb_sendv(server, &iov, 1); 254 return smb_sendv(server, &iov, 1);
255} 255}
256 256
257static int wait_for_free_request(struct TCP_Server_Info *server, 257static int
258 const int long_op) 258wait_for_free_credits(struct TCP_Server_Info *server, const int optype,
259 int *credits)
259{ 260{
260 if (long_op == CIFS_ASYNC_OP) { 261 int rc;
262
263 spin_lock(&server->req_lock);
264 if (optype == CIFS_ASYNC_OP) {
261 /* oplock breaks must not be held up */ 265 /* oplock breaks must not be held up */
262 atomic_inc(&server->inFlight); 266 server->in_flight++;
267 *credits -= 1;
268 spin_unlock(&server->req_lock);
263 return 0; 269 return 0;
264 } 270 }
265 271
266 spin_lock(&GlobalMid_Lock);
267 while (1) { 272 while (1) {
268 if (atomic_read(&server->inFlight) >= cifs_max_pending) { 273 if (*credits <= 0) {
269 spin_unlock(&GlobalMid_Lock); 274 spin_unlock(&server->req_lock);
270 cifs_num_waiters_inc(server); 275 cifs_num_waiters_inc(server);
271 wait_event(server->request_q, 276 rc = wait_event_killable(server->request_q,
272 atomic_read(&server->inFlight) 277 has_credits(server, credits));
273 < cifs_max_pending);
274 cifs_num_waiters_dec(server); 278 cifs_num_waiters_dec(server);
275 spin_lock(&GlobalMid_Lock); 279 if (rc)
280 return rc;
281 spin_lock(&server->req_lock);
276 } else { 282 } else {
277 if (server->tcpStatus == CifsExiting) { 283 if (server->tcpStatus == CifsExiting) {
278 spin_unlock(&GlobalMid_Lock); 284 spin_unlock(&server->req_lock);
279 return -ENOENT; 285 return -ENOENT;
280 } 286 }
281 287
282 /* can not count locking commands against total 288 /*
283 as they are allowed to block on server */ 289 * Can not count locking commands against total
290 * as they are allowed to block on server.
291 */
284 292
285 /* update # of requests on the wire to server */ 293 /* update # of requests on the wire to server */
286 if (long_op != CIFS_BLOCKING_OP) 294 if (optype != CIFS_BLOCKING_OP) {
287 atomic_inc(&server->inFlight); 295 *credits -= 1;
288 spin_unlock(&GlobalMid_Lock); 296 server->in_flight++;
297 }
298 spin_unlock(&server->req_lock);
289 break; 299 break;
290 } 300 }
291 } 301 }
292 return 0; 302 return 0;
293} 303}
294 304
305static int
306wait_for_free_request(struct TCP_Server_Info *server, const int optype)
307{
308 return wait_for_free_credits(server, optype, get_credits_field(server));
309}
310
295static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, 311static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
296 struct mid_q_entry **ppmidQ) 312 struct mid_q_entry **ppmidQ)
297{ 313{
@@ -359,7 +375,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
359 mid = AllocMidQEntry(hdr, server); 375 mid = AllocMidQEntry(hdr, server);
360 if (mid == NULL) { 376 if (mid == NULL) {
361 mutex_unlock(&server->srv_mutex); 377 mutex_unlock(&server->srv_mutex);
362 atomic_dec(&server->inFlight); 378 cifs_add_credits(server, 1);
363 wake_up(&server->request_q); 379 wake_up(&server->request_q);
364 return -ENOMEM; 380 return -ENOMEM;
365 } 381 }
@@ -392,7 +408,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
392 return rc; 408 return rc;
393out_err: 409out_err:
394 delete_mid(mid); 410 delete_mid(mid);
395 atomic_dec(&server->inFlight); 411 cifs_add_credits(server, 1);
396 wake_up(&server->request_q); 412 wake_up(&server->request_q);
397 return rc; 413 return rc;
398} 414}
@@ -564,8 +580,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
564 mutex_unlock(&ses->server->srv_mutex); 580 mutex_unlock(&ses->server->srv_mutex);
565 cifs_small_buf_release(in_buf); 581 cifs_small_buf_release(in_buf);
566 /* Update # of requests on wire to server */ 582 /* Update # of requests on wire to server */
567 atomic_dec(&ses->server->inFlight); 583 cifs_add_credits(ses->server, 1);
568 wake_up(&ses->server->request_q);
569 return rc; 584 return rc;
570 } 585 }
571 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); 586 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
@@ -601,8 +616,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
601 midQ->callback = DeleteMidQEntry; 616 midQ->callback = DeleteMidQEntry;
602 spin_unlock(&GlobalMid_Lock); 617 spin_unlock(&GlobalMid_Lock);
603 cifs_small_buf_release(in_buf); 618 cifs_small_buf_release(in_buf);
604 atomic_dec(&ses->server->inFlight); 619 cifs_add_credits(ses->server, 1);
605 wake_up(&ses->server->request_q);
606 return rc; 620 return rc;
607 } 621 }
608 spin_unlock(&GlobalMid_Lock); 622 spin_unlock(&GlobalMid_Lock);
@@ -612,8 +626,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
612 626
613 rc = cifs_sync_mid_result(midQ, ses->server); 627 rc = cifs_sync_mid_result(midQ, ses->server);
614 if (rc != 0) { 628 if (rc != 0) {
615 atomic_dec(&ses->server->inFlight); 629 cifs_add_credits(ses->server, 1);
616 wake_up(&ses->server->request_q);
617 return rc; 630 return rc;
618 } 631 }
619 632
@@ -637,8 +650,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
637 midQ->resp_buf = NULL; 650 midQ->resp_buf = NULL;
638out: 651out:
639 delete_mid(midQ); 652 delete_mid(midQ);
640 atomic_dec(&ses->server->inFlight); 653 cifs_add_credits(ses->server, 1);
641 wake_up(&ses->server->request_q);
642 654
643 return rc; 655 return rc;
644} 656}
@@ -688,8 +700,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
688 if (rc) { 700 if (rc) {
689 mutex_unlock(&ses->server->srv_mutex); 701 mutex_unlock(&ses->server->srv_mutex);
690 /* Update # of requests on wire to server */ 702 /* Update # of requests on wire to server */
691 atomic_dec(&ses->server->inFlight); 703 cifs_add_credits(ses->server, 1);
692 wake_up(&ses->server->request_q);
693 return rc; 704 return rc;
694 } 705 }
695 706
@@ -721,8 +732,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
721 /* no longer considered to be "in-flight" */ 732 /* no longer considered to be "in-flight" */
722 midQ->callback = DeleteMidQEntry; 733 midQ->callback = DeleteMidQEntry;
723 spin_unlock(&GlobalMid_Lock); 734 spin_unlock(&GlobalMid_Lock);
724 atomic_dec(&ses->server->inFlight); 735 cifs_add_credits(ses->server, 1);
725 wake_up(&ses->server->request_q);
726 return rc; 736 return rc;
727 } 737 }
728 spin_unlock(&GlobalMid_Lock); 738 spin_unlock(&GlobalMid_Lock);
@@ -730,8 +740,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
730 740
731 rc = cifs_sync_mid_result(midQ, ses->server); 741 rc = cifs_sync_mid_result(midQ, ses->server);
732 if (rc != 0) { 742 if (rc != 0) {
733 atomic_dec(&ses->server->inFlight); 743 cifs_add_credits(ses->server, 1);
734 wake_up(&ses->server->request_q);
735 return rc; 744 return rc;
736 } 745 }
737 746
@@ -747,8 +756,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
747 rc = cifs_check_receive(midQ, ses->server, 0); 756 rc = cifs_check_receive(midQ, ses->server, 0);
748out: 757out:
749 delete_mid(midQ); 758 delete_mid(midQ);
750 atomic_dec(&ses->server->inFlight); 759 cifs_add_credits(ses->server, 1);
751 wake_up(&ses->server->request_q);
752 760
753 return rc; 761 return rc;
754} 762}