aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-20 19:36:38 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-20 19:36:38 -0500
commit5cdec1fca2ff128ca0716dc1ef0fc0043e4ae8ab (patch)
tree35dbfed2dc57b80d18276413361c34905fe8312c /fs
parente55fdbd7414a3ee991d7081a256153f61ea98b9f (diff)
parent76dcc26f1d7f1c98c3f595379dcd9562f01bf38d (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: cifs: mangle existing header for SMB_COM_NT_CANCEL cifs: remove code for setting timeouts on requests [CIFS] cifs: reconnect unresponsive servers cifs: set up recurring workqueue job to do SMB echo requests cifs: add ability to send an echo request cifs: add cifs_call_async cifs: allow for different handling of received response cifs: clean up sync_mid_result cifs: don't reconnect server when we don't get a response cifs: wait indefinitely for responses cifs: Use mask of ACEs for SID Everyone to calculate all three permissions user, group, and other cifs: Fix regression during share-level security mounts (Repost) [CIFS] Update cifs version number cifs: move mid result processing into common function cifs: move locked sections out of DeleteMidQEntry and AllocMidQEntry cifs: clean up accesses to midCount cifs: make wait_for_free_request take a TCP_Server_Info pointer cifs: no need to mark smb_ses_list as cifs_demultiplex_thread is exiting cifs: don't fail writepages on -EAGAIN errors CIFS: Fix oplock break handling (try #2)
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifs_debug.c10
-rw-r--r--fs/cifs/cifsacl.c13
-rw-r--r--fs/cifs/cifsfs.c6
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h28
-rw-r--r--fs/cifs/cifspdu.h15
-rw-r--r--fs/cifs/cifsproto.h9
-rw-r--r--fs/cifs/cifssmb.c59
-rw-r--r--fs/cifs/connect.c149
-rw-r--r--fs/cifs/file.c114
-rw-r--r--fs/cifs/misc.c2
-rw-r--r--fs/cifs/sess.c2
-rw-r--r--fs/cifs/transport.c427
13 files changed, 455 insertions, 381 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index ede98300a8cd..65829d32128c 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -79,11 +79,11 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
79 spin_lock(&GlobalMid_Lock); 79 spin_lock(&GlobalMid_Lock);
80 list_for_each(tmp, &server->pending_mid_q) { 80 list_for_each(tmp, &server->pending_mid_q) {
81 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 81 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
82 cERROR(1, "State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", 82 cERROR(1, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %d",
83 mid_entry->midState, 83 mid_entry->midState,
84 (int)mid_entry->command, 84 (int)mid_entry->command,
85 mid_entry->pid, 85 mid_entry->pid,
86 mid_entry->tsk, 86 mid_entry->callback_data,
87 mid_entry->mid); 87 mid_entry->mid);
88#ifdef CONFIG_CIFS_STATS2 88#ifdef CONFIG_CIFS_STATS2
89 cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld", 89 cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld",
@@ -218,11 +218,11 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
218 mid_entry = list_entry(tmp3, struct mid_q_entry, 218 mid_entry = list_entry(tmp3, struct mid_q_entry,
219 qhead); 219 qhead);
220 seq_printf(m, "\tState: %d com: %d pid:" 220 seq_printf(m, "\tState: %d com: %d pid:"
221 " %d tsk: %p mid %d\n", 221 " %d cbdata: %p mid %d\n",
222 mid_entry->midState, 222 mid_entry->midState,
223 (int)mid_entry->command, 223 (int)mid_entry->command,
224 mid_entry->pid, 224 mid_entry->pid,
225 mid_entry->tsk, 225 mid_entry->callback_data,
226 mid_entry->mid); 226 mid_entry->mid);
227 } 227 }
228 spin_unlock(&GlobalMid_Lock); 228 spin_unlock(&GlobalMid_Lock);
@@ -331,7 +331,7 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
331 atomic_read(&totSmBufAllocCount)); 331 atomic_read(&totSmBufAllocCount));
332#endif /* CONFIG_CIFS_STATS2 */ 332#endif /* CONFIG_CIFS_STATS2 */
333 333
334 seq_printf(m, "Operations (MIDs): %d\n", midCount.counter); 334 seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&midCount));
335 seq_printf(m, 335 seq_printf(m,
336 "\n%d session %d share reconnects\n", 336 "\n%d session %d share reconnects\n",
337 tcpSesReconnectCount.counter, tconInfoReconnectCount.counter); 337 tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index a437ec391a01..1e7636b145a8 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -41,9 +41,12 @@ static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
41; 41;
42 42
43 43
44/* security id for everyone */ 44/* security id for everyone/world system group */
45static const struct cifs_sid sid_everyone = { 45static const struct cifs_sid sid_everyone = {
46 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; 46 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
47/* security id for Authenticated Users system group */
48static const struct cifs_sid sid_authusers = {
49 1, 1, {0, 0, 0, 0, 0, 5}, {11} };
47/* group users */ 50/* group users */
48static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; 51static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
49 52
@@ -365,7 +368,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
365 if (num_aces > 0) { 368 if (num_aces > 0) {
366 umode_t user_mask = S_IRWXU; 369 umode_t user_mask = S_IRWXU;
367 umode_t group_mask = S_IRWXG; 370 umode_t group_mask = S_IRWXG;
368 umode_t other_mask = S_IRWXO; 371 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
369 372
370 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), 373 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
371 GFP_KERNEL); 374 GFP_KERNEL);
@@ -390,6 +393,12 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
390 ppace[i]->type, 393 ppace[i]->type,
391 &fattr->cf_mode, 394 &fattr->cf_mode,
392 &other_mask); 395 &other_mask);
396 if (compare_sids(&(ppace[i]->sid), &sid_authusers))
397 access_flags_to_mode(ppace[i]->access_req,
398 ppace[i]->type,
399 &fattr->cf_mode,
400 &other_mask);
401
393 402
394/* memcpy((void *)(&(cifscred->aces[i])), 403/* memcpy((void *)(&(cifscred->aces[i])),
395 (void *)ppace[i], 404 (void *)ppace[i],
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index d9f652a522a6..99d777a03dd0 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -77,7 +77,11 @@ unsigned int cifs_max_pending = CIFS_MAX_REQ;
77module_param(cifs_max_pending, int, 0); 77module_param(cifs_max_pending, int, 0);
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: 50 Range: 2 to 256");
80 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.");
81extern mempool_t *cifs_sm_req_poolp; 85extern mempool_t *cifs_sm_req_poolp;
82extern mempool_t *cifs_req_poolp; 86extern mempool_t *cifs_req_poolp;
83extern mempool_t *cifs_mid_poolp; 87extern mempool_t *cifs_mid_poolp;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 851030f74939..4739a531cded 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -118,5 +118,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
118extern const struct export_operations cifs_export_ops; 118extern const struct export_operations cifs_export_ops;
119#endif /* EXPERIMENTAL */ 119#endif /* EXPERIMENTAL */
120 120
121#define CIFS_VERSION "1.68" 121#define CIFS_VERSION "1.69"
122#endif /* _CIFSFS_H */ 122#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 606ca8bb7102..571132c95231 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -218,6 +218,7 @@ struct TCP_Server_Info {
218 bool sec_kerberosu2u; /* supports U2U Kerberos */ 218 bool sec_kerberosu2u; /* supports U2U Kerberos */
219 bool sec_ntlmssp; /* supports NTLMSSP */ 219 bool sec_ntlmssp; /* supports NTLMSSP */
220 bool session_estab; /* mark when very first sess is established */ 220 bool session_estab; /* mark when very first sess is established */
221 struct delayed_work echo; /* echo ping workqueue job */
221#ifdef CONFIG_CIFS_FSCACHE 222#ifdef CONFIG_CIFS_FSCACHE
222 struct fscache_cookie *fscache; /* client index cache cookie */ 223 struct fscache_cookie *fscache; /* client index cache cookie */
223#endif 224#endif
@@ -508,6 +509,18 @@ static inline void cifs_stats_bytes_read(struct cifsTconInfo *tcon,
508 509
509#endif 510#endif
510 511
512struct mid_q_entry;
513
514/*
515 * This is the prototype for the mid callback function. When creating one,
516 * take special care to avoid deadlocks. Things to bear in mind:
517 *
518 * - it will be called by cifsd
519 * - the GlobalMid_Lock will be held
520 * - the mid will be removed from the pending_mid_q list
521 */
522typedef void (mid_callback_t)(struct mid_q_entry *mid);
523
511/* one of these for every pending CIFS request to the server */ 524/* one of these for every pending CIFS request to the server */
512struct mid_q_entry { 525struct mid_q_entry {
513 struct list_head qhead; /* mids waiting on reply from this server */ 526 struct list_head qhead; /* mids waiting on reply from this server */
@@ -519,7 +532,8 @@ struct mid_q_entry {
519 unsigned long when_sent; /* time when smb send finished */ 532 unsigned long when_sent; /* time when smb send finished */
520 unsigned long when_received; /* when demux complete (taken off wire) */ 533 unsigned long when_received; /* when demux complete (taken off wire) */
521#endif 534#endif
522 struct task_struct *tsk; /* task waiting for response */ 535 mid_callback_t *callback; /* call completion callback */
536 void *callback_data; /* general purpose pointer for callback */
523 struct smb_hdr *resp_buf; /* response buffer */ 537 struct smb_hdr *resp_buf; /* response buffer */
524 int midState; /* wish this were enum but can not pass to wait_event */ 538 int midState; /* wish this were enum but can not pass to wait_event */
525 __u8 command; /* smb command code */ 539 __u8 command; /* smb command code */
@@ -622,12 +636,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
622#define CIFS_IOVEC 4 /* array of response buffers */ 636#define CIFS_IOVEC 4 /* array of response buffers */
623 637
624/* Type of Request to SendReceive2 */ 638/* Type of Request to SendReceive2 */
625#define CIFS_STD_OP 0 /* normal request timeout */ 639#define CIFS_BLOCKING_OP 1 /* operation can block */
626#define CIFS_LONG_OP 1 /* long op (up to 45 sec, oplock time) */ 640#define CIFS_ASYNC_OP 2 /* do not wait for response */
627#define CIFS_VLONG_OP 2 /* sloow op - can take up to 180 seconds */ 641#define CIFS_TIMEOUT_MASK 0x003 /* only one of above set in req */
628#define CIFS_BLOCKING_OP 4 /* operation can block */
629#define CIFS_ASYNC_OP 8 /* do not wait for response */
630#define CIFS_TIMEOUT_MASK 0x00F /* only one of 5 above set in req */
631#define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */ 642#define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */
632#define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */ 643#define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */
633#define CIFS_NO_RESP 0x040 /* no response buffer required */ 644#define CIFS_NO_RESP 0x040 /* no response buffer required */
@@ -790,6 +801,9 @@ GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
790GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ 801GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */
791GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ 802GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
792 803
804/* reconnect after this many failed echo attempts */
805GLOBAL_EXTERN unsigned short echo_retries;
806
793void cifs_oplock_break(struct work_struct *work); 807void cifs_oplock_break(struct work_struct *work);
794void cifs_oplock_break_get(struct cifsFileInfo *cfile); 808void cifs_oplock_break_get(struct cifsFileInfo *cfile);
795void cifs_oplock_break_put(struct cifsFileInfo *cfile); 809void cifs_oplock_break_put(struct cifsFileInfo *cfile);
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index de36b09763a8..ea205b4fcad2 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -50,6 +50,7 @@
50#define SMB_COM_SETATTR 0x09 /* trivial response */ 50#define SMB_COM_SETATTR 0x09 /* trivial response */
51#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ 51#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */
52#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ 52#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/
53#define SMB_COM_ECHO 0x2B /* echo request */
53#define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */ 54#define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */
54#define SMB_COM_READ_ANDX 0x2E 55#define SMB_COM_READ_ANDX 0x2E
55#define SMB_COM_WRITE_ANDX 0x2F 56#define SMB_COM_WRITE_ANDX 0x2F
@@ -760,6 +761,20 @@ typedef struct smb_com_tconx_rsp_ext {
760 * 761 *
761 */ 762 */
762 763
764typedef struct smb_com_echo_req {
765 struct smb_hdr hdr;
766 __le16 EchoCount;
767 __le16 ByteCount;
768 char Data[1];
769} __attribute__((packed)) ECHO_REQ;
770
771typedef struct smb_com_echo_rsp {
772 struct smb_hdr hdr;
773 __le16 SequenceNumber;
774 __le16 ByteCount;
775 char Data[1];
776} __attribute__((packed)) ECHO_RSP;
777
763typedef struct smb_com_logoff_andx_req { 778typedef struct smb_com_logoff_andx_req {
764 struct smb_hdr hdr; /* wct = 2 */ 779 struct smb_hdr hdr; /* wct = 2 */
765 __u8 AndXCommand; 780 __u8 AndXCommand;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index e6d1481b16c1..982895fa7615 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -61,6 +61,12 @@ extern char *cifs_compose_mount_options(const char *sb_mountdata,
61 const char *fullpath, const struct dfs_info3_param *ref, 61 const char *fullpath, const struct dfs_info3_param *ref,
62 char **devname); 62 char **devname);
63/* extern void renew_parental_timestamps(struct dentry *direntry);*/ 63/* extern void renew_parental_timestamps(struct dentry *direntry);*/
64extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
65 struct TCP_Server_Info *server);
66extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
67extern int cifs_call_async(struct TCP_Server_Info *server,
68 struct smb_hdr *in_buf, mid_callback_t *callback,
69 void *cbdata);
64extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, 70extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
65 struct smb_hdr * /* input */ , 71 struct smb_hdr * /* input */ ,
66 struct smb_hdr * /* out */ , 72 struct smb_hdr * /* out */ ,
@@ -347,12 +353,13 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
347 const __u16 netfid, const __u64 len, 353 const __u16 netfid, const __u64 len,
348 const __u64 offset, const __u32 numUnlock, 354 const __u64 offset, const __u32 numUnlock,
349 const __u32 numLock, const __u8 lockType, 355 const __u32 numLock, const __u8 lockType,
350 const bool waitFlag); 356 const bool waitFlag, const __u8 oplock_level);
351extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, 357extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
352 const __u16 smb_file_id, const int get_flag, 358 const __u16 smb_file_id, const int get_flag,
353 const __u64 len, struct file_lock *, 359 const __u64 len, struct file_lock *,
354 const __u16 lock_type, const bool waitFlag); 360 const __u16 lock_type, const bool waitFlag);
355extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); 361extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
362extern int CIFSSMBEcho(struct TCP_Server_Info *server);
356extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); 363extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
357 364
358extern struct cifsSesInfo *sesInfoAlloc(void); 365extern struct cifsSesInfo *sesInfoAlloc(void);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 2f6795e524d3..37113450757b 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -706,6 +706,53 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
706 return rc; 706 return rc;
707} 707}
708 708
709/*
710 * This is a no-op for now. We're not really interested in the reply, but
711 * rather in the fact that the server sent one and that server->lstrp
712 * gets updated.
713 *
714 * FIXME: maybe we should consider checking that the reply matches request?
715 */
716static void
717cifs_echo_callback(struct mid_q_entry *mid)
718{
719 struct TCP_Server_Info *server = mid->callback_data;
720
721 DeleteMidQEntry(mid);
722 atomic_dec(&server->inFlight);
723 wake_up(&server->request_q);
724}
725
726int
727CIFSSMBEcho(struct TCP_Server_Info *server)
728{
729 ECHO_REQ *smb;
730 int rc = 0;
731
732 cFYI(1, "In echo request");
733
734 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
735 if (rc)
736 return rc;
737
738 /* set up echo request */
739 smb->hdr.Tid = cpu_to_le16(0xffff);
740 smb->hdr.WordCount = cpu_to_le16(1);
741 smb->EchoCount = cpu_to_le16(1);
742 smb->ByteCount = cpu_to_le16(1);
743 smb->Data[0] = 'a';
744 smb->hdr.smb_buf_length += 3;
745
746 rc = cifs_call_async(server, (struct smb_hdr *)smb,
747 cifs_echo_callback, server);
748 if (rc)
749 cFYI(1, "Echo request failed: %d", rc);
750
751 cifs_small_buf_release(smb);
752
753 return rc;
754}
755
709int 756int
710CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) 757CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
711{ 758{
@@ -1193,7 +1240,7 @@ OldOpenRetry:
1193 pSMB->ByteCount = cpu_to_le16(count); 1240 pSMB->ByteCount = cpu_to_le16(count);
1194 /* long_op set to 1 to allow for oplock break timeouts */ 1241 /* long_op set to 1 to allow for oplock break timeouts */
1195 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1242 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1196 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); 1243 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1197 cifs_stats_inc(&tcon->num_opens); 1244 cifs_stats_inc(&tcon->num_opens);
1198 if (rc) { 1245 if (rc) {
1199 cFYI(1, "Error in Open = %d", rc); 1246 cFYI(1, "Error in Open = %d", rc);
@@ -1306,7 +1353,7 @@ openRetry:
1306 pSMB->ByteCount = cpu_to_le16(count); 1353 pSMB->ByteCount = cpu_to_le16(count);
1307 /* long_op set to 1 to allow for oplock break timeouts */ 1354 /* long_op set to 1 to allow for oplock break timeouts */
1308 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1355 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1309 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); 1356 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1310 cifs_stats_inc(&tcon->num_opens); 1357 cifs_stats_inc(&tcon->num_opens);
1311 if (rc) { 1358 if (rc) {
1312 cFYI(1, "Error in Open = %d", rc); 1359 cFYI(1, "Error in Open = %d", rc);
@@ -1388,7 +1435,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1388 iov[0].iov_base = (char *)pSMB; 1435 iov[0].iov_base = (char *)pSMB;
1389 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; 1436 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1390 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, 1437 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1391 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR); 1438 &resp_buf_type, CIFS_LOG_ERROR);
1392 cifs_stats_inc(&tcon->num_reads); 1439 cifs_stats_inc(&tcon->num_reads);
1393 pSMBr = (READ_RSP *)iov[0].iov_base; 1440 pSMBr = (READ_RSP *)iov[0].iov_base;
1394 if (rc) { 1441 if (rc) {
@@ -1663,7 +1710,8 @@ int
1663CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, 1710CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1664 const __u16 smb_file_id, const __u64 len, 1711 const __u16 smb_file_id, const __u64 len,
1665 const __u64 offset, const __u32 numUnlock, 1712 const __u64 offset, const __u32 numUnlock,
1666 const __u32 numLock, const __u8 lockType, const bool waitFlag) 1713 const __u32 numLock, const __u8 lockType,
1714 const bool waitFlag, const __u8 oplock_level)
1667{ 1715{
1668 int rc = 0; 1716 int rc = 0;
1669 LOCK_REQ *pSMB = NULL; 1717 LOCK_REQ *pSMB = NULL;
@@ -1691,6 +1739,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1691 pSMB->NumberOfLocks = cpu_to_le16(numLock); 1739 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1692 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); 1740 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1693 pSMB->LockType = lockType; 1741 pSMB->LockType = lockType;
1742 pSMB->OplockLevel = oplock_level;
1694 pSMB->AndXCommand = 0xFF; /* none */ 1743 pSMB->AndXCommand = 0xFF; /* none */
1695 pSMB->Fid = smb_file_id; /* netfid stays le */ 1744 pSMB->Fid = smb_file_id; /* netfid stays le */
1696 1745
@@ -3087,7 +3136,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3087 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; 3136 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3088 3137
3089 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 3138 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3090 CIFS_STD_OP); 3139 0);
3091 cifs_stats_inc(&tcon->num_acl_get); 3140 cifs_stats_inc(&tcon->num_acl_get);
3092 if (rc) { 3141 if (rc) {
3093 cFYI(1, "Send error in QuerySecDesc = %d", rc); 3142 cFYI(1, "Send error in QuerySecDesc = %d", rc);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 9f59887badd2..8d4657596301 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -52,6 +52,9 @@
52#define CIFS_PORT 445 52#define CIFS_PORT 445
53#define RFC1001_PORT 139 53#define RFC1001_PORT 139
54 54
55/* SMB echo "timeout" -- FIXME: tunable? */
56#define SMB_ECHO_INTERVAL (60 * HZ)
57
55extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 58extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
56 unsigned char *p24); 59 unsigned char *p24);
57 60
@@ -152,6 +155,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
152 155
153 /* before reconnecting the tcp session, mark the smb session (uid) 156 /* before reconnecting the tcp session, mark the smb session (uid)
154 and the tid bad so they are not used until reconnected */ 157 and the tid bad so they are not used until reconnected */
158 cFYI(1, "%s: marking sessions and tcons for reconnect", __func__);
155 spin_lock(&cifs_tcp_ses_lock); 159 spin_lock(&cifs_tcp_ses_lock);
156 list_for_each(tmp, &server->smb_ses_list) { 160 list_for_each(tmp, &server->smb_ses_list) {
157 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); 161 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
@@ -163,7 +167,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
163 } 167 }
164 } 168 }
165 spin_unlock(&cifs_tcp_ses_lock); 169 spin_unlock(&cifs_tcp_ses_lock);
170
166 /* do not want to be sending data on a socket we are freeing */ 171 /* do not want to be sending data on a socket we are freeing */
172 cFYI(1, "%s: tearing down socket", __func__);
167 mutex_lock(&server->srv_mutex); 173 mutex_lock(&server->srv_mutex);
168 if (server->ssocket) { 174 if (server->ssocket) {
169 cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state, 175 cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state,
@@ -180,22 +186,20 @@ cifs_reconnect(struct TCP_Server_Info *server)
180 kfree(server->session_key.response); 186 kfree(server->session_key.response);
181 server->session_key.response = NULL; 187 server->session_key.response = NULL;
182 server->session_key.len = 0; 188 server->session_key.len = 0;
189 server->lstrp = jiffies;
190 mutex_unlock(&server->srv_mutex);
183 191
192 /* mark submitted MIDs for retry and issue callback */
193 cFYI(1, "%s: issuing mid callbacks", __func__);
184 spin_lock(&GlobalMid_Lock); 194 spin_lock(&GlobalMid_Lock);
185 list_for_each(tmp, &server->pending_mid_q) { 195 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
186 mid_entry = list_entry(tmp, struct 196 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
187 mid_q_entry, 197 if (mid_entry->midState == MID_REQUEST_SUBMITTED)
188 qhead);
189 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
190 /* Mark other intransit requests as needing
191 retry so we do not immediately mark the
192 session bad again (ie after we reconnect
193 below) as they timeout too */
194 mid_entry->midState = MID_RETRY_NEEDED; 198 mid_entry->midState = MID_RETRY_NEEDED;
195 } 199 list_del_init(&mid_entry->qhead);
200 mid_entry->callback(mid_entry);
196 } 201 }
197 spin_unlock(&GlobalMid_Lock); 202 spin_unlock(&GlobalMid_Lock);
198 mutex_unlock(&server->srv_mutex);
199 203
200 while ((server->tcpStatus != CifsExiting) && 204 while ((server->tcpStatus != CifsExiting) &&
201 (server->tcpStatus != CifsGood)) { 205 (server->tcpStatus != CifsGood)) {
@@ -212,10 +216,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
212 if (server->tcpStatus != CifsExiting) 216 if (server->tcpStatus != CifsExiting)
213 server->tcpStatus = CifsGood; 217 server->tcpStatus = CifsGood;
214 spin_unlock(&GlobalMid_Lock); 218 spin_unlock(&GlobalMid_Lock);
215 /* atomic_set(&server->inFlight,0);*/
216 wake_up(&server->response_q);
217 } 219 }
218 } 220 }
221
219 return rc; 222 return rc;
220} 223}
221 224
@@ -334,6 +337,26 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
334 337
335} 338}
336 339
340static void
341cifs_echo_request(struct work_struct *work)
342{
343 int rc;
344 struct TCP_Server_Info *server = container_of(work,
345 struct TCP_Server_Info, echo.work);
346
347 /* no need to ping if we got a response recently */
348 if (time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
349 goto requeue_echo;
350
351 rc = CIFSSMBEcho(server);
352 if (rc)
353 cFYI(1, "Unable to send echo request to server: %s",
354 server->hostname);
355
356requeue_echo:
357 queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL);
358}
359
337static int 360static int
338cifs_demultiplex_thread(struct TCP_Server_Info *server) 361cifs_demultiplex_thread(struct TCP_Server_Info *server)
339{ 362{
@@ -345,8 +368,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
345 struct msghdr smb_msg; 368 struct msghdr smb_msg;
346 struct kvec iov; 369 struct kvec iov;
347 struct socket *csocket = server->ssocket; 370 struct socket *csocket = server->ssocket;
348 struct list_head *tmp; 371 struct list_head *tmp, *tmp2;
349 struct cifsSesInfo *ses;
350 struct task_struct *task_to_wake = NULL; 372 struct task_struct *task_to_wake = NULL;
351 struct mid_q_entry *mid_entry; 373 struct mid_q_entry *mid_entry;
352 char temp; 374 char temp;
@@ -399,7 +421,20 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
399 smb_msg.msg_control = NULL; 421 smb_msg.msg_control = NULL;
400 smb_msg.msg_controllen = 0; 422 smb_msg.msg_controllen = 0;
401 pdu_length = 4; /* enough to get RFC1001 header */ 423 pdu_length = 4; /* enough to get RFC1001 header */
424
402incomplete_rcv: 425incomplete_rcv:
426 if (echo_retries > 0 &&
427 time_after(jiffies, server->lstrp +
428 (echo_retries * SMB_ECHO_INTERVAL))) {
429 cERROR(1, "Server %s has not responded in %d seconds. "
430 "Reconnecting...", server->hostname,
431 (echo_retries * SMB_ECHO_INTERVAL / HZ));
432 cifs_reconnect(server);
433 csocket = server->ssocket;
434 wake_up(&server->response_q);
435 continue;
436 }
437
403 length = 438 length =
404 kernel_recvmsg(csocket, &smb_msg, 439 kernel_recvmsg(csocket, &smb_msg,
405 &iov, 1, pdu_length, 0 /* BB other flags? */); 440 &iov, 1, pdu_length, 0 /* BB other flags? */);
@@ -559,10 +594,11 @@ incomplete_rcv:
559 continue; 594 continue;
560 } 595 }
561 596
597 mid_entry = NULL;
598 server->lstrp = jiffies;
562 599
563 task_to_wake = NULL;
564 spin_lock(&GlobalMid_Lock); 600 spin_lock(&GlobalMid_Lock);
565 list_for_each(tmp, &server->pending_mid_q) { 601 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
566 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 602 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
567 603
568 if ((mid_entry->mid == smb_buffer->Mid) && 604 if ((mid_entry->mid == smb_buffer->Mid) &&
@@ -603,20 +639,19 @@ incomplete_rcv:
603 mid_entry->resp_buf = smb_buffer; 639 mid_entry->resp_buf = smb_buffer;
604 mid_entry->largeBuf = isLargeBuf; 640 mid_entry->largeBuf = isLargeBuf;
605multi_t2_fnd: 641multi_t2_fnd:
606 task_to_wake = mid_entry->tsk;
607 mid_entry->midState = MID_RESPONSE_RECEIVED; 642 mid_entry->midState = MID_RESPONSE_RECEIVED;
643 list_del_init(&mid_entry->qhead);
644 mid_entry->callback(mid_entry);
608#ifdef CONFIG_CIFS_STATS2 645#ifdef CONFIG_CIFS_STATS2
609 mid_entry->when_received = jiffies; 646 mid_entry->when_received = jiffies;
610#endif 647#endif
611 /* so we do not time out requests to server
612 which is still responding (since server could
613 be busy but not dead) */
614 server->lstrp = jiffies;
615 break; 648 break;
616 } 649 }
650 mid_entry = NULL;
617 } 651 }
618 spin_unlock(&GlobalMid_Lock); 652 spin_unlock(&GlobalMid_Lock);
619 if (task_to_wake) { 653
654 if (mid_entry != NULL) {
620 /* Was previous buf put in mpx struct for multi-rsp? */ 655 /* Was previous buf put in mpx struct for multi-rsp? */
621 if (!isMultiRsp) { 656 if (!isMultiRsp) {
622 /* smb buffer will be freed by user thread */ 657 /* smb buffer will be freed by user thread */
@@ -625,11 +660,10 @@ multi_t2_fnd:
625 else 660 else
626 smallbuf = NULL; 661 smallbuf = NULL;
627 } 662 }
628 wake_up_process(task_to_wake);
629 } else if (!is_valid_oplock_break(smb_buffer, server) && 663 } else if (!is_valid_oplock_break(smb_buffer, server) &&
630 !isMultiRsp) { 664 !isMultiRsp) {
631 cERROR(1, "No task to wake, unknown frame received! " 665 cERROR(1, "No task to wake, unknown frame received! "
632 "NumMids %d", midCount.counter); 666 "NumMids %d", atomic_read(&midCount));
633 cifs_dump_mem("Received Data is: ", (char *)smb_buffer, 667 cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
634 sizeof(struct smb_hdr)); 668 sizeof(struct smb_hdr));
635#ifdef CONFIG_CIFS_DEBUG2 669#ifdef CONFIG_CIFS_DEBUG2
@@ -677,44 +711,16 @@ multi_t2_fnd:
677 if (smallbuf) /* no sense logging a debug message if NULL */ 711 if (smallbuf) /* no sense logging a debug message if NULL */
678 cifs_small_buf_release(smallbuf); 712 cifs_small_buf_release(smallbuf);
679 713
680 /* 714 if (!list_empty(&server->pending_mid_q)) {
681 * BB: we shouldn't have to do any of this. It shouldn't be
682 * possible to exit from the thread with active SMB sessions
683 */
684 spin_lock(&cifs_tcp_ses_lock);
685 if (list_empty(&server->pending_mid_q)) {
686 /* loop through server session structures attached to this and
687 mark them dead */
688 list_for_each(tmp, &server->smb_ses_list) {
689 ses = list_entry(tmp, struct cifsSesInfo,
690 smb_ses_list);
691 ses->status = CifsExiting;
692 ses->server = NULL;
693 }
694 spin_unlock(&cifs_tcp_ses_lock);
695 } else {
696 /* although we can not zero the server struct pointer yet,
697 since there are active requests which may depnd on them,
698 mark the corresponding SMB sessions as exiting too */
699 list_for_each(tmp, &server->smb_ses_list) {
700 ses = list_entry(tmp, struct cifsSesInfo,
701 smb_ses_list);
702 ses->status = CifsExiting;
703 }
704
705 spin_lock(&GlobalMid_Lock); 715 spin_lock(&GlobalMid_Lock);
706 list_for_each(tmp, &server->pending_mid_q) { 716 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
707 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 717 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
708 if (mid_entry->midState == MID_REQUEST_SUBMITTED) { 718 cFYI(1, "Clearing Mid 0x%x - issuing callback",
709 cFYI(1, "Clearing Mid 0x%x - waking up ",
710 mid_entry->mid); 719 mid_entry->mid);
711 task_to_wake = mid_entry->tsk; 720 list_del_init(&mid_entry->qhead);
712 if (task_to_wake) 721 mid_entry->callback(mid_entry);
713 wake_up_process(task_to_wake);
714 }
715 } 722 }
716 spin_unlock(&GlobalMid_Lock); 723 spin_unlock(&GlobalMid_Lock);
717 spin_unlock(&cifs_tcp_ses_lock);
718 /* 1/8th of sec is more than enough time for them to exit */ 724 /* 1/8th of sec is more than enough time for them to exit */
719 msleep(125); 725 msleep(125);
720 } 726 }
@@ -732,18 +738,6 @@ multi_t2_fnd:
732 coming home not much else we can do but free the memory */ 738 coming home not much else we can do but free the memory */
733 } 739 }
734 740
735 /* last chance to mark ses pointers invalid
736 if there are any pointing to this (e.g
737 if a crazy root user tried to kill cifsd
738 kernel thread explicitly this might happen) */
739 /* BB: This shouldn't be necessary, see above */
740 spin_lock(&cifs_tcp_ses_lock);
741 list_for_each(tmp, &server->smb_ses_list) {
742 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
743 ses->server = NULL;
744 }
745 spin_unlock(&cifs_tcp_ses_lock);
746
747 kfree(server->hostname); 741 kfree(server->hostname);
748 task_to_wake = xchg(&server->tsk, NULL); 742 task_to_wake = xchg(&server->tsk, NULL);
749 kfree(server); 743 kfree(server);
@@ -1612,6 +1606,8 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
1612 list_del_init(&server->tcp_ses_list); 1606 list_del_init(&server->tcp_ses_list);
1613 spin_unlock(&cifs_tcp_ses_lock); 1607 spin_unlock(&cifs_tcp_ses_lock);
1614 1608
1609 cancel_delayed_work_sync(&server->echo);
1610
1615 spin_lock(&GlobalMid_Lock); 1611 spin_lock(&GlobalMid_Lock);
1616 server->tcpStatus = CifsExiting; 1612 server->tcpStatus = CifsExiting;
1617 spin_unlock(&GlobalMid_Lock); 1613 spin_unlock(&GlobalMid_Lock);
@@ -1701,8 +1697,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1701 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); 1697 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
1702 tcp_ses->session_estab = false; 1698 tcp_ses->session_estab = false;
1703 tcp_ses->sequence_number = 0; 1699 tcp_ses->sequence_number = 0;
1700 tcp_ses->lstrp = jiffies;
1704 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); 1701 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
1705 INIT_LIST_HEAD(&tcp_ses->smb_ses_list); 1702 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
1703 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
1706 1704
1707 /* 1705 /*
1708 * at this point we are the only ones with the pointer 1706 * at this point we are the only ones with the pointer
@@ -1751,6 +1749,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1751 1749
1752 cifs_fscache_get_client_cookie(tcp_ses); 1750 cifs_fscache_get_client_cookie(tcp_ses);
1753 1751
1752 /* queue echo request delayed work */
1753 queue_delayed_work(system_nrt_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
1754
1754 return tcp_ses; 1755 return tcp_ses;
1755 1756
1756out_err_crypto_release: 1757out_err_crypto_release:
@@ -2965,7 +2966,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2965 bcc_ptr++; /* skip password */ 2966 bcc_ptr++; /* skip password */
2966 /* already aligned so no need to do it below */ 2967 /* already aligned so no need to do it below */
2967 } else { 2968 } else {
2968 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); 2969 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
2969 /* BB FIXME add code to fail this if NTLMv2 or Kerberos 2970 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
2970 specified as required (when that support is added to 2971 specified as required (when that support is added to
2971 the vfs in the future) as only NTLM or the much 2972 the vfs in the future) as only NTLM or the much
@@ -2983,7 +2984,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2983#endif /* CIFS_WEAK_PW_HASH */ 2984#endif /* CIFS_WEAK_PW_HASH */
2984 SMBNTencrypt(tcon->password, ses->server->cryptkey, bcc_ptr); 2985 SMBNTencrypt(tcon->password, ses->server->cryptkey, bcc_ptr);
2985 2986
2986 bcc_ptr += CIFS_SESS_KEY_SIZE; 2987 bcc_ptr += CIFS_AUTH_RESP_SIZE;
2987 if (ses->capabilities & CAP_UNICODE) { 2988 if (ses->capabilities & CAP_UNICODE) {
2988 /* must align unicode strings */ 2989 /* must align unicode strings */
2989 *bcc_ptr = 0; /* null byte password */ 2990 *bcc_ptr = 0; /* null byte password */
@@ -3021,7 +3022,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3021 pSMB->ByteCount = cpu_to_le16(count); 3022 pSMB->ByteCount = cpu_to_le16(count);
3022 3023
3023 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 3024 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
3024 CIFS_STD_OP); 3025 0);
3025 3026
3026 /* above now done in SendReceive */ 3027 /* above now done in SendReceive */
3027 if ((rc == 0) && (tcon != NULL)) { 3028 if ((rc == 0) && (tcon != NULL)) {
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index d843631c028d..bd2a028af833 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -726,12 +726,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
726 726
727 /* BB we could chain these into one lock request BB */ 727 /* BB we could chain these into one lock request BB */
728 rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, 728 rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start,
729 0, 1, lockType, 0 /* wait flag */ ); 729 0, 1, lockType, 0 /* wait flag */, 0);
730 if (rc == 0) { 730 if (rc == 0) {
731 rc = CIFSSMBLock(xid, tcon, netfid, length, 731 rc = CIFSSMBLock(xid, tcon, netfid, length,
732 pfLock->fl_start, 1 /* numUnlock */ , 732 pfLock->fl_start, 1 /* numUnlock */ ,
733 0 /* numLock */ , lockType, 733 0 /* numLock */ , lockType,
734 0 /* wait flag */ ); 734 0 /* wait flag */, 0);
735 pfLock->fl_type = F_UNLCK; 735 pfLock->fl_type = F_UNLCK;
736 if (rc != 0) 736 if (rc != 0)
737 cERROR(1, "Error unlocking previously locked " 737 cERROR(1, "Error unlocking previously locked "
@@ -748,13 +748,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
748 rc = CIFSSMBLock(xid, tcon, netfid, length, 748 rc = CIFSSMBLock(xid, tcon, netfid, length,
749 pfLock->fl_start, 0, 1, 749 pfLock->fl_start, 0, 1,
750 lockType | LOCKING_ANDX_SHARED_LOCK, 750 lockType | LOCKING_ANDX_SHARED_LOCK,
751 0 /* wait flag */); 751 0 /* wait flag */, 0);
752 if (rc == 0) { 752 if (rc == 0) {
753 rc = CIFSSMBLock(xid, tcon, netfid, 753 rc = CIFSSMBLock(xid, tcon, netfid,
754 length, pfLock->fl_start, 1, 0, 754 length, pfLock->fl_start, 1, 0,
755 lockType | 755 lockType |
756 LOCKING_ANDX_SHARED_LOCK, 756 LOCKING_ANDX_SHARED_LOCK,
757 0 /* wait flag */); 757 0 /* wait flag */, 0);
758 pfLock->fl_type = F_RDLCK; 758 pfLock->fl_type = F_RDLCK;
759 if (rc != 0) 759 if (rc != 0)
760 cERROR(1, "Error unlocking " 760 cERROR(1, "Error unlocking "
@@ -797,8 +797,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
797 797
798 if (numLock) { 798 if (numLock) {
799 rc = CIFSSMBLock(xid, tcon, netfid, length, 799 rc = CIFSSMBLock(xid, tcon, netfid, length,
800 pfLock->fl_start, 800 pfLock->fl_start, 0, numLock, lockType,
801 0, numLock, lockType, wait_flag); 801 wait_flag, 0);
802 802
803 if (rc == 0) { 803 if (rc == 0) {
804 /* For Windows locks we must store them. */ 804 /* For Windows locks we must store them. */
@@ -818,9 +818,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
818 (pfLock->fl_start + length) >= 818 (pfLock->fl_start + length) >=
819 (li->offset + li->length)) { 819 (li->offset + li->length)) {
820 stored_rc = CIFSSMBLock(xid, tcon, 820 stored_rc = CIFSSMBLock(xid, tcon,
821 netfid, 821 netfid, li->length,
822 li->length, li->offset, 822 li->offset, 1, 0,
823 1, 0, li->type, false); 823 li->type, false, 0);
824 if (stored_rc) 824 if (stored_rc)
825 rc = stored_rc; 825 rc = stored_rc;
826 else { 826 else {
@@ -839,29 +839,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
839 return rc; 839 return rc;
840} 840}
841 841
842/*
843 * Set the timeout on write requests past EOF. For some servers (Windows)
844 * these calls can be very long.
845 *
846 * If we're writing >10M past the EOF we give a 180s timeout. Anything less
847 * than that gets a 45s timeout. Writes not past EOF get 15s timeouts.
848 * The 10M cutoff is totally arbitrary. A better scheme for this would be
849 * welcome if someone wants to suggest one.
850 *
851 * We may be able to do a better job with this if there were some way to
852 * declare that a file should be sparse.
853 */
854static int
855cifs_write_timeout(struct cifsInodeInfo *cifsi, loff_t offset)
856{
857 if (offset <= cifsi->server_eof)
858 return CIFS_STD_OP;
859 else if (offset > (cifsi->server_eof + (10 * 1024 * 1024)))
860 return CIFS_VLONG_OP;
861 else
862 return CIFS_LONG_OP;
863}
864
865/* update the file size (if needed) after a write */ 842/* update the file size (if needed) after a write */
866static void 843static void
867cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, 844cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
@@ -882,7 +859,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
882 unsigned int total_written; 859 unsigned int total_written;
883 struct cifs_sb_info *cifs_sb; 860 struct cifs_sb_info *cifs_sb;
884 struct cifsTconInfo *pTcon; 861 struct cifsTconInfo *pTcon;
885 int xid, long_op; 862 int xid;
886 struct cifsFileInfo *open_file; 863 struct cifsFileInfo *open_file;
887 struct cifsInodeInfo *cifsi = CIFS_I(inode); 864 struct cifsInodeInfo *cifsi = CIFS_I(inode);
888 865
@@ -903,7 +880,6 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
903 880
904 xid = GetXid(); 881 xid = GetXid();
905 882
906 long_op = cifs_write_timeout(cifsi, *poffset);
907 for (total_written = 0; write_size > total_written; 883 for (total_written = 0; write_size > total_written;
908 total_written += bytes_written) { 884 total_written += bytes_written) {
909 rc = -EAGAIN; 885 rc = -EAGAIN;
@@ -931,7 +907,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
931 min_t(const int, cifs_sb->wsize, 907 min_t(const int, cifs_sb->wsize,
932 write_size - total_written), 908 write_size - total_written),
933 *poffset, &bytes_written, 909 *poffset, &bytes_written,
934 NULL, write_data + total_written, long_op); 910 NULL, write_data + total_written, 0);
935 } 911 }
936 if (rc || (bytes_written == 0)) { 912 if (rc || (bytes_written == 0)) {
937 if (total_written) 913 if (total_written)
@@ -944,8 +920,6 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
944 cifs_update_eof(cifsi, *poffset, bytes_written); 920 cifs_update_eof(cifsi, *poffset, bytes_written);
945 *poffset += bytes_written; 921 *poffset += bytes_written;
946 } 922 }
947 long_op = CIFS_STD_OP; /* subsequent writes fast -
948 15 seconds is plenty */
949 } 923 }
950 924
951 cifs_stats_bytes_written(pTcon, total_written); 925 cifs_stats_bytes_written(pTcon, total_written);
@@ -974,7 +948,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
974 unsigned int total_written; 948 unsigned int total_written;
975 struct cifs_sb_info *cifs_sb; 949 struct cifs_sb_info *cifs_sb;
976 struct cifsTconInfo *pTcon; 950 struct cifsTconInfo *pTcon;
977 int xid, long_op; 951 int xid;
978 struct dentry *dentry = open_file->dentry; 952 struct dentry *dentry = open_file->dentry;
979 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); 953 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
980 954
@@ -987,7 +961,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
987 961
988 xid = GetXid(); 962 xid = GetXid();
989 963
990 long_op = cifs_write_timeout(cifsi, *poffset);
991 for (total_written = 0; write_size > total_written; 964 for (total_written = 0; write_size > total_written;
992 total_written += bytes_written) { 965 total_written += bytes_written) {
993 rc = -EAGAIN; 966 rc = -EAGAIN;
@@ -1017,7 +990,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
1017 rc = CIFSSMBWrite2(xid, pTcon, 990 rc = CIFSSMBWrite2(xid, pTcon,
1018 open_file->netfid, len, 991 open_file->netfid, len,
1019 *poffset, &bytes_written, 992 *poffset, &bytes_written,
1020 iov, 1, long_op); 993 iov, 1, 0);
1021 } else 994 } else
1022 rc = CIFSSMBWrite(xid, pTcon, 995 rc = CIFSSMBWrite(xid, pTcon,
1023 open_file->netfid, 996 open_file->netfid,
@@ -1025,7 +998,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
1025 write_size - total_written), 998 write_size - total_written),
1026 *poffset, &bytes_written, 999 *poffset, &bytes_written,
1027 write_data + total_written, 1000 write_data + total_written,
1028 NULL, long_op); 1001 NULL, 0);
1029 } 1002 }
1030 if (rc || (bytes_written == 0)) { 1003 if (rc || (bytes_written == 0)) {
1031 if (total_written) 1004 if (total_written)
@@ -1038,8 +1011,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
1038 cifs_update_eof(cifsi, *poffset, bytes_written); 1011 cifs_update_eof(cifsi, *poffset, bytes_written);
1039 *poffset += bytes_written; 1012 *poffset += bytes_written;
1040 } 1013 }
1041 long_op = CIFS_STD_OP; /* subsequent writes fast -
1042 15 seconds is plenty */
1043 } 1014 }
1044 1015
1045 cifs_stats_bytes_written(pTcon, total_written); 1016 cifs_stats_bytes_written(pTcon, total_written);
@@ -1239,7 +1210,7 @@ static int cifs_writepages(struct address_space *mapping,
1239 struct pagevec pvec; 1210 struct pagevec pvec;
1240 int rc = 0; 1211 int rc = 0;
1241 int scanned = 0; 1212 int scanned = 0;
1242 int xid, long_op; 1213 int xid;
1243 1214
1244 cifs_sb = CIFS_SB(mapping->host->i_sb); 1215 cifs_sb = CIFS_SB(mapping->host->i_sb);
1245 1216
@@ -1377,43 +1348,67 @@ retry:
1377 break; 1348 break;
1378 } 1349 }
1379 if (n_iov) { 1350 if (n_iov) {
1351retry_write:
1380 open_file = find_writable_file(CIFS_I(mapping->host), 1352 open_file = find_writable_file(CIFS_I(mapping->host),
1381 false); 1353 false);
1382 if (!open_file) { 1354 if (!open_file) {
1383 cERROR(1, "No writable handles for inode"); 1355 cERROR(1, "No writable handles for inode");
1384 rc = -EBADF; 1356 rc = -EBADF;
1385 } else { 1357 } else {
1386 long_op = cifs_write_timeout(cifsi, offset);
1387 rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, 1358 rc = CIFSSMBWrite2(xid, tcon, open_file->netfid,
1388 bytes_to_write, offset, 1359 bytes_to_write, offset,
1389 &bytes_written, iov, n_iov, 1360 &bytes_written, iov, n_iov,
1390 long_op); 1361 0);
1391 cifsFileInfo_put(open_file); 1362 cifsFileInfo_put(open_file);
1392 cifs_update_eof(cifsi, offset, bytes_written);
1393 } 1363 }
1394 1364
1395 if (rc || bytes_written < bytes_to_write) { 1365 cFYI(1, "Write2 rc=%d, wrote=%u", rc, bytes_written);
1396 cERROR(1, "Write2 ret %d, wrote %d", 1366
1397 rc, bytes_written); 1367 /*
1398 mapping_set_error(mapping, rc); 1368 * For now, treat a short write as if nothing got
1399 } else { 1369 * written. A zero length write however indicates
1370 * ENOSPC or EFBIG. We have no way to know which
1371 * though, so call it ENOSPC for now. EFBIG would
1372 * get translated to AS_EIO anyway.
1373 *
1374 * FIXME: make it take into account the data that did
1375 * get written
1376 */
1377 if (rc == 0) {
1378 if (bytes_written == 0)
1379 rc = -ENOSPC;
1380 else if (bytes_written < bytes_to_write)
1381 rc = -EAGAIN;
1382 }
1383
1384 /* retry on data-integrity flush */
1385 if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN)
1386 goto retry_write;
1387
1388 /* fix the stats and EOF */
1389 if (bytes_written > 0) {
1400 cifs_stats_bytes_written(tcon, bytes_written); 1390 cifs_stats_bytes_written(tcon, bytes_written);
1391 cifs_update_eof(cifsi, offset, bytes_written);
1401 } 1392 }
1402 1393
1403 for (i = 0; i < n_iov; i++) { 1394 for (i = 0; i < n_iov; i++) {
1404 page = pvec.pages[first + i]; 1395 page = pvec.pages[first + i];
1405 /* Should we also set page error on 1396 /* on retryable write error, redirty page */
1406 success rc but too little data written? */ 1397 if (rc == -EAGAIN)
1407 /* BB investigate retry logic on temporary 1398 redirty_page_for_writepage(wbc, page);
1408 server crash cases and how recovery works 1399 else if (rc != 0)
1409 when page marked as error */
1410 if (rc)
1411 SetPageError(page); 1400 SetPageError(page);
1412 kunmap(page); 1401 kunmap(page);
1413 unlock_page(page); 1402 unlock_page(page);
1414 end_page_writeback(page); 1403 end_page_writeback(page);
1415 page_cache_release(page); 1404 page_cache_release(page);
1416 } 1405 }
1406
1407 if (rc != -EAGAIN)
1408 mapping_set_error(mapping, rc);
1409 else
1410 rc = 0;
1411
1417 if ((wbc->nr_to_write -= n_iov) <= 0) 1412 if ((wbc->nr_to_write -= n_iov) <= 0)
1418 done = 1; 1413 done = 1;
1419 index = next; 1414 index = next;
@@ -2192,7 +2187,8 @@ void cifs_oplock_break(struct work_struct *work)
2192 */ 2187 */
2193 if (!cfile->oplock_break_cancelled) { 2188 if (!cfile->oplock_break_cancelled) {
2194 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, 2189 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0,
2195 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false); 2190 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false,
2191 cinode->clientCanCacheRead ? 1 : 0);
2196 cFYI(1, "Oplock release rc = %d", rc); 2192 cFYI(1, "Oplock release rc = %d", rc);
2197 } 2193 }
2198 2194
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 43f10281bc19..09bfcf08a90f 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -571,7 +571,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
571 pCifsInode = CIFS_I(netfile->dentry->d_inode); 571 pCifsInode = CIFS_I(netfile->dentry->d_inode);
572 572
573 cifs_set_oplock_level(pCifsInode, 573 cifs_set_oplock_level(pCifsInode,
574 pSMB->OplockLevel); 574 pSMB->OplockLevel ? OPLOCK_READ : 0);
575 /* 575 /*
576 * cifs_oplock_break_put() can't be called 576 * cifs_oplock_break_put() can't be called
577 * from here. Get reference after queueing 577 * from here. Get reference after queueing
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index eb746486e49e..1cffd82c4f13 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -879,7 +879,7 @@ ssetup_ntlmssp_authenticate:
879 BCC_LE(smb_buf) = cpu_to_le16(count); 879 BCC_LE(smb_buf) = cpu_to_le16(count);
880 880
881 rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, 881 rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type,
882 CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR); 882 CIFS_LOG_ERROR);
883 /* SMB request buf freed in SendReceive2 */ 883 /* SMB request buf freed in SendReceive2 */
884 884
885 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; 885 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 59ca81b16919..c8e2808cd5e6 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -36,7 +36,13 @@
36 36
37extern mempool_t *cifs_mid_poolp; 37extern mempool_t *cifs_mid_poolp;
38 38
39static struct mid_q_entry * 39static void
40wake_up_task(struct mid_q_entry *mid)
41{
42 wake_up_process(mid->callback_data);
43}
44
45struct mid_q_entry *
40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) 46AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
41{ 47{
42 struct mid_q_entry *temp; 48 struct mid_q_entry *temp;
@@ -58,28 +64,28 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
58 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ 64 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
59 /* when mid allocated can be before when sent */ 65 /* when mid allocated can be before when sent */
60 temp->when_alloc = jiffies; 66 temp->when_alloc = jiffies;
61 temp->tsk = current; 67
68 /*
69 * The default is for the mid to be synchronous, so the
70 * default callback just wakes up the current task.
71 */
72 temp->callback = wake_up_task;
73 temp->callback_data = current;
62 } 74 }
63 75
64 spin_lock(&GlobalMid_Lock);
65 list_add_tail(&temp->qhead, &server->pending_mid_q);
66 atomic_inc(&midCount); 76 atomic_inc(&midCount);
67 temp->midState = MID_REQUEST_ALLOCATED; 77 temp->midState = MID_REQUEST_ALLOCATED;
68 spin_unlock(&GlobalMid_Lock);
69 return temp; 78 return temp;
70} 79}
71 80
72static void 81void
73DeleteMidQEntry(struct mid_q_entry *midEntry) 82DeleteMidQEntry(struct mid_q_entry *midEntry)
74{ 83{
75#ifdef CONFIG_CIFS_STATS2 84#ifdef CONFIG_CIFS_STATS2
76 unsigned long now; 85 unsigned long now;
77#endif 86#endif
78 spin_lock(&GlobalMid_Lock);
79 midEntry->midState = MID_FREE; 87 midEntry->midState = MID_FREE;
80 list_del(&midEntry->qhead);
81 atomic_dec(&midCount); 88 atomic_dec(&midCount);
82 spin_unlock(&GlobalMid_Lock);
83 if (midEntry->largeBuf) 89 if (midEntry->largeBuf)
84 cifs_buf_release(midEntry->resp_buf); 90 cifs_buf_release(midEntry->resp_buf);
85 else 91 else
@@ -103,6 +109,16 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
103 mempool_free(midEntry, cifs_mid_poolp); 109 mempool_free(midEntry, cifs_mid_poolp);
104} 110}
105 111
112static void
113delete_mid(struct mid_q_entry *mid)
114{
115 spin_lock(&GlobalMid_Lock);
116 list_del(&mid->qhead);
117 spin_unlock(&GlobalMid_Lock);
118
119 DeleteMidQEntry(mid);
120}
121
106static int 122static int
107smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) 123smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
108{ 124{
@@ -244,31 +260,31 @@ smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
244 return smb_sendv(server, &iov, 1); 260 return smb_sendv(server, &iov, 1);
245} 261}
246 262
247static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) 263static int wait_for_free_request(struct TCP_Server_Info *server,
264 const int long_op)
248{ 265{
249 if (long_op == CIFS_ASYNC_OP) { 266 if (long_op == CIFS_ASYNC_OP) {
250 /* oplock breaks must not be held up */ 267 /* oplock breaks must not be held up */
251 atomic_inc(&ses->server->inFlight); 268 atomic_inc(&server->inFlight);
252 return 0; 269 return 0;
253 } 270 }
254 271
255 spin_lock(&GlobalMid_Lock); 272 spin_lock(&GlobalMid_Lock);
256 while (1) { 273 while (1) {
257 if (atomic_read(&ses->server->inFlight) >= 274 if (atomic_read(&server->inFlight) >= cifs_max_pending) {
258 cifs_max_pending){
259 spin_unlock(&GlobalMid_Lock); 275 spin_unlock(&GlobalMid_Lock);
260#ifdef CONFIG_CIFS_STATS2 276#ifdef CONFIG_CIFS_STATS2
261 atomic_inc(&ses->server->num_waiters); 277 atomic_inc(&server->num_waiters);
262#endif 278#endif
263 wait_event(ses->server->request_q, 279 wait_event(server->request_q,
264 atomic_read(&ses->server->inFlight) 280 atomic_read(&server->inFlight)
265 < cifs_max_pending); 281 < cifs_max_pending);
266#ifdef CONFIG_CIFS_STATS2 282#ifdef CONFIG_CIFS_STATS2
267 atomic_dec(&ses->server->num_waiters); 283 atomic_dec(&server->num_waiters);
268#endif 284#endif
269 spin_lock(&GlobalMid_Lock); 285 spin_lock(&GlobalMid_Lock);
270 } else { 286 } else {
271 if (ses->server->tcpStatus == CifsExiting) { 287 if (server->tcpStatus == CifsExiting) {
272 spin_unlock(&GlobalMid_Lock); 288 spin_unlock(&GlobalMid_Lock);
273 return -ENOENT; 289 return -ENOENT;
274 } 290 }
@@ -278,7 +294,7 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
278 294
279 /* update # of requests on the wire to server */ 295 /* update # of requests on the wire to server */
280 if (long_op != CIFS_BLOCKING_OP) 296 if (long_op != CIFS_BLOCKING_OP)
281 atomic_inc(&ses->server->inFlight); 297 atomic_inc(&server->inFlight);
282 spin_unlock(&GlobalMid_Lock); 298 spin_unlock(&GlobalMid_Lock);
283 break; 299 break;
284 } 300 }
@@ -308,53 +324,81 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
308 *ppmidQ = AllocMidQEntry(in_buf, ses->server); 324 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
309 if (*ppmidQ == NULL) 325 if (*ppmidQ == NULL)
310 return -ENOMEM; 326 return -ENOMEM;
327 spin_lock(&GlobalMid_Lock);
328 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
329 spin_unlock(&GlobalMid_Lock);
311 return 0; 330 return 0;
312} 331}
313 332
314static int wait_for_response(struct cifsSesInfo *ses, 333static int
315 struct mid_q_entry *midQ, 334wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
316 unsigned long timeout,
317 unsigned long time_to_wait)
318{ 335{
319 unsigned long curr_timeout; 336 int error;
320 337
321 for (;;) { 338 error = wait_event_killable(server->response_q,
322 curr_timeout = timeout + jiffies; 339 midQ->midState != MID_REQUEST_SUBMITTED);
323 wait_event_timeout(ses->server->response_q, 340 if (error < 0)
324 midQ->midState != MID_REQUEST_SUBMITTED, timeout); 341 return -ERESTARTSYS;
325 342
326 if (time_after(jiffies, curr_timeout) && 343 return 0;
327 (midQ->midState == MID_REQUEST_SUBMITTED) && 344}
328 ((ses->server->tcpStatus == CifsGood) ||
329 (ses->server->tcpStatus == CifsNew))) {
330 345
331 unsigned long lrt;
332 346
333 /* We timed out. Is the server still 347/*
334 sending replies ? */ 348 * Send a SMB request and set the callback function in the mid to handle
335 spin_lock(&GlobalMid_Lock); 349 * the result. Caller is responsible for dealing with timeouts.
336 lrt = ses->server->lstrp; 350 */
337 spin_unlock(&GlobalMid_Lock); 351int
352cifs_call_async(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
353 mid_callback_t *callback, void *cbdata)
354{
355 int rc;
356 struct mid_q_entry *mid;
338 357
339 /* Calculate time_to_wait past last receive time. 358 rc = wait_for_free_request(server, CIFS_ASYNC_OP);
340 Although we prefer not to time out if the 359 if (rc)
341 server is still responding - we will time 360 return rc;
342 out if the server takes more than 15 (or 45 361
343 or 180) seconds to respond to this request 362 mutex_lock(&server->srv_mutex);
344 and has not responded to any request from 363 mid = AllocMidQEntry(in_buf, server);
345 other threads on the client within 10 seconds */ 364 if (mid == NULL) {
346 lrt += time_to_wait; 365 mutex_unlock(&server->srv_mutex);
347 if (time_after(jiffies, lrt)) { 366 return -ENOMEM;
348 /* No replies for time_to_wait. */
349 cERROR(1, "server not responding");
350 return -1;
351 }
352 } else {
353 return 0;
354 }
355 } 367 }
356}
357 368
369 /* put it on the pending_mid_q */
370 spin_lock(&GlobalMid_Lock);
371 list_add_tail(&mid->qhead, &server->pending_mid_q);
372 spin_unlock(&GlobalMid_Lock);
373
374 rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
375 if (rc) {
376 mutex_unlock(&server->srv_mutex);
377 goto out_err;
378 }
379
380 mid->callback = callback;
381 mid->callback_data = cbdata;
382 mid->midState = MID_REQUEST_SUBMITTED;
383#ifdef CONFIG_CIFS_STATS2
384 atomic_inc(&server->inSend);
385#endif
386 rc = smb_send(server, in_buf, in_buf->smb_buf_length);
387#ifdef CONFIG_CIFS_STATS2
388 atomic_dec(&server->inSend);
389 mid->when_sent = jiffies;
390#endif
391 mutex_unlock(&server->srv_mutex);
392 if (rc)
393 goto out_err;
394
395 return rc;
396out_err:
397 delete_mid(mid);
398 atomic_dec(&server->inFlight);
399 wake_up(&server->request_q);
400 return rc;
401}
358 402
359/* 403/*
360 * 404 *
@@ -382,6 +426,81 @@ SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
382 return rc; 426 return rc;
383} 427}
384 428
429static int
430sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
431{
432 int rc = 0;
433
434 cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command,
435 mid->mid, mid->midState);
436
437 spin_lock(&GlobalMid_Lock);
438 /* ensure that it's no longer on the pending_mid_q */
439 list_del_init(&mid->qhead);
440
441 switch (mid->midState) {
442 case MID_RESPONSE_RECEIVED:
443 spin_unlock(&GlobalMid_Lock);
444 return rc;
445 case MID_REQUEST_SUBMITTED:
446 /* socket is going down, reject all calls */
447 if (server->tcpStatus == CifsExiting) {
448 cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d",
449 __func__, mid->mid, mid->command, mid->midState);
450 rc = -EHOSTDOWN;
451 break;
452 }
453 case MID_RETRY_NEEDED:
454 rc = -EAGAIN;
455 break;
456 default:
457 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
458 mid->mid, mid->midState);
459 rc = -EIO;
460 }
461 spin_unlock(&GlobalMid_Lock);
462
463 DeleteMidQEntry(mid);
464 return rc;
465}
466
467/*
468 * An NT cancel request header looks just like the original request except:
469 *
470 * The Command is SMB_COM_NT_CANCEL
471 * The WordCount is zeroed out
472 * The ByteCount is zeroed out
473 *
474 * This function mangles an existing request buffer into a
475 * SMB_COM_NT_CANCEL request and then sends it.
476 */
477static int
478send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
479 struct mid_q_entry *mid)
480{
481 int rc = 0;
482
483 /* -4 for RFC1001 length and +2 for BCC field */
484 in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4 + 2;
485 in_buf->Command = SMB_COM_NT_CANCEL;
486 in_buf->WordCount = 0;
487 BCC_LE(in_buf) = 0;
488
489 mutex_lock(&server->srv_mutex);
490 rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
491 if (rc) {
492 mutex_unlock(&server->srv_mutex);
493 return rc;
494 }
495 rc = smb_send(server, in_buf, in_buf->smb_buf_length);
496 mutex_unlock(&server->srv_mutex);
497
498 cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
499 in_buf->Mid, rc);
500
501 return rc;
502}
503
385int 504int
386SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, 505SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
387 struct kvec *iov, int n_vec, int *pRespBufType /* ret */, 506 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
@@ -390,7 +509,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
390 int rc = 0; 509 int rc = 0;
391 int long_op; 510 int long_op;
392 unsigned int receive_len; 511 unsigned int receive_len;
393 unsigned long timeout;
394 struct mid_q_entry *midQ; 512 struct mid_q_entry *midQ;
395 struct smb_hdr *in_buf = iov[0].iov_base; 513 struct smb_hdr *in_buf = iov[0].iov_base;
396 514
@@ -413,7 +531,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
413 to the same server. We may make this configurable later or 531 to the same server. We may make this configurable later or
414 use ses->maxReq */ 532 use ses->maxReq */
415 533
416 rc = wait_for_free_request(ses, long_op); 534 rc = wait_for_free_request(ses->server, long_op);
417 if (rc) { 535 if (rc) {
418 cifs_small_buf_release(in_buf); 536 cifs_small_buf_release(in_buf);
419 return rc; 537 return rc;
@@ -457,65 +575,20 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
457 if (rc < 0) 575 if (rc < 0)
458 goto out; 576 goto out;
459 577
460 if (long_op == CIFS_STD_OP) 578 if (long_op == CIFS_ASYNC_OP)
461 timeout = 15 * HZ;
462 else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
463 timeout = 180 * HZ;
464 else if (long_op == CIFS_LONG_OP)
465 timeout = 45 * HZ; /* should be greater than
466 servers oplock break timeout (about 43 seconds) */
467 else if (long_op == CIFS_ASYNC_OP)
468 goto out; 579 goto out;
469 else if (long_op == CIFS_BLOCKING_OP)
470 timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
471 else {
472 cERROR(1, "unknown timeout flag %d", long_op);
473 rc = -EIO;
474 goto out;
475 }
476
477 /* wait for 15 seconds or until woken up due to response arriving or
478 due to last connection to this server being unmounted */
479 if (signal_pending(current)) {
480 /* if signal pending do not hold up user for full smb timeout
481 but we still give response a chance to complete */
482 timeout = 2 * HZ;
483 }
484
485 /* No user interrupts in wait - wreaks havoc with performance */
486 wait_for_response(ses, midQ, timeout, 10 * HZ);
487
488 spin_lock(&GlobalMid_Lock);
489 580
490 if (midQ->resp_buf == NULL) { 581 rc = wait_for_response(ses->server, midQ);
491 cERROR(1, "No response to cmd %d mid %d", 582 if (rc != 0)
492 midQ->command, midQ->mid); 583 goto out;
493 if (midQ->midState == MID_REQUEST_SUBMITTED) {
494 if (ses->server->tcpStatus == CifsExiting)
495 rc = -EHOSTDOWN;
496 else {
497 ses->server->tcpStatus = CifsNeedReconnect;
498 midQ->midState = MID_RETRY_NEEDED;
499 }
500 }
501 584
502 if (rc != -EHOSTDOWN) { 585 rc = sync_mid_result(midQ, ses->server);
503 if (midQ->midState == MID_RETRY_NEEDED) { 586 if (rc != 0) {
504 rc = -EAGAIN;
505 cFYI(1, "marking request for retry");
506 } else {
507 rc = -EIO;
508 }
509 }
510 spin_unlock(&GlobalMid_Lock);
511 DeleteMidQEntry(midQ);
512 /* Update # of requests on wire to server */
513 atomic_dec(&ses->server->inFlight); 587 atomic_dec(&ses->server->inFlight);
514 wake_up(&ses->server->request_q); 588 wake_up(&ses->server->request_q);
515 return rc; 589 return rc;
516 } 590 }
517 591
518 spin_unlock(&GlobalMid_Lock);
519 receive_len = midQ->resp_buf->smb_buf_length; 592 receive_len = midQ->resp_buf->smb_buf_length;
520 593
521 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 594 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
@@ -564,14 +637,14 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
564 if ((flags & CIFS_NO_RESP) == 0) 637 if ((flags & CIFS_NO_RESP) == 0)
565 midQ->resp_buf = NULL; /* mark it so buf will 638 midQ->resp_buf = NULL; /* mark it so buf will
566 not be freed by 639 not be freed by
567 DeleteMidQEntry */ 640 delete_mid */
568 } else { 641 } else {
569 rc = -EIO; 642 rc = -EIO;
570 cFYI(1, "Bad MID state?"); 643 cFYI(1, "Bad MID state?");
571 } 644 }
572 645
573out: 646out:
574 DeleteMidQEntry(midQ); 647 delete_mid(midQ);
575 atomic_dec(&ses->server->inFlight); 648 atomic_dec(&ses->server->inFlight);
576 wake_up(&ses->server->request_q); 649 wake_up(&ses->server->request_q);
577 650
@@ -585,7 +658,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
585{ 658{
586 int rc = 0; 659 int rc = 0;
587 unsigned int receive_len; 660 unsigned int receive_len;
588 unsigned long timeout;
589 struct mid_q_entry *midQ; 661 struct mid_q_entry *midQ;
590 662
591 if (ses == NULL) { 663 if (ses == NULL) {
@@ -610,7 +682,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
610 return -EIO; 682 return -EIO;
611 } 683 }
612 684
613 rc = wait_for_free_request(ses, long_op); 685 rc = wait_for_free_request(ses->server, long_op);
614 if (rc) 686 if (rc)
615 return rc; 687 return rc;
616 688
@@ -649,64 +721,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
649 if (rc < 0) 721 if (rc < 0)
650 goto out; 722 goto out;
651 723
652 if (long_op == CIFS_STD_OP) 724 if (long_op == CIFS_ASYNC_OP)
653 timeout = 15 * HZ;
654 /* wait for 15 seconds or until woken up due to response arriving or
655 due to last connection to this server being unmounted */
656 else if (long_op == CIFS_ASYNC_OP)
657 goto out; 725 goto out;
658 else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
659 timeout = 180 * HZ;
660 else if (long_op == CIFS_LONG_OP)
661 timeout = 45 * HZ; /* should be greater than
662 servers oplock break timeout (about 43 seconds) */
663 else if (long_op == CIFS_BLOCKING_OP)
664 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
665 else {
666 cERROR(1, "unknown timeout flag %d", long_op);
667 rc = -EIO;
668 goto out;
669 }
670 726
671 if (signal_pending(current)) { 727 rc = wait_for_response(ses->server, midQ);
672 /* if signal pending do not hold up user for full smb timeout 728 if (rc != 0)
673 but we still give response a chance to complete */ 729 goto out;
674 timeout = 2 * HZ;
675 }
676
677 /* No user interrupts in wait - wreaks havoc with performance */
678 wait_for_response(ses, midQ, timeout, 10 * HZ);
679
680 spin_lock(&GlobalMid_Lock);
681 if (midQ->resp_buf == NULL) {
682 cERROR(1, "No response for cmd %d mid %d",
683 midQ->command, midQ->mid);
684 if (midQ->midState == MID_REQUEST_SUBMITTED) {
685 if (ses->server->tcpStatus == CifsExiting)
686 rc = -EHOSTDOWN;
687 else {
688 ses->server->tcpStatus = CifsNeedReconnect;
689 midQ->midState = MID_RETRY_NEEDED;
690 }
691 }
692 730
693 if (rc != -EHOSTDOWN) { 731 rc = sync_mid_result(midQ, ses->server);
694 if (midQ->midState == MID_RETRY_NEEDED) { 732 if (rc != 0) {
695 rc = -EAGAIN;
696 cFYI(1, "marking request for retry");
697 } else {
698 rc = -EIO;
699 }
700 }
701 spin_unlock(&GlobalMid_Lock);
702 DeleteMidQEntry(midQ);
703 /* Update # of requests on wire to server */
704 atomic_dec(&ses->server->inFlight); 733 atomic_dec(&ses->server->inFlight);
705 wake_up(&ses->server->request_q); 734 wake_up(&ses->server->request_q);
706 return rc; 735 return rc;
707 } 736 }
708 737
709 spin_unlock(&GlobalMid_Lock);
710 receive_len = midQ->resp_buf->smb_buf_length; 738 receive_len = midQ->resp_buf->smb_buf_length;
711 739
712 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 740 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
@@ -755,36 +783,13 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
755 } 783 }
756 784
757out: 785out:
758 DeleteMidQEntry(midQ); 786 delete_mid(midQ);
759 atomic_dec(&ses->server->inFlight); 787 atomic_dec(&ses->server->inFlight);
760 wake_up(&ses->server->request_q); 788 wake_up(&ses->server->request_q);
761 789
762 return rc; 790 return rc;
763} 791}
764 792
765/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
766
767static int
768send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
769 struct mid_q_entry *midQ)
770{
771 int rc = 0;
772 struct cifsSesInfo *ses = tcon->ses;
773 __u16 mid = in_buf->Mid;
774
775 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
776 in_buf->Mid = mid;
777 mutex_lock(&ses->server->srv_mutex);
778 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
779 if (rc) {
780 mutex_unlock(&ses->server->srv_mutex);
781 return rc;
782 }
783 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
784 mutex_unlock(&ses->server->srv_mutex);
785 return rc;
786}
787
788/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows 793/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
789 blocking lock to return. */ 794 blocking lock to return. */
790 795
@@ -807,7 +812,7 @@ send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
807 pSMB->hdr.Mid = GetNextMid(ses->server); 812 pSMB->hdr.Mid = GetNextMid(ses->server);
808 813
809 return SendReceive(xid, ses, in_buf, out_buf, 814 return SendReceive(xid, ses, in_buf, out_buf,
810 &bytes_returned, CIFS_STD_OP); 815 &bytes_returned, 0);
811} 816}
812 817
813int 818int
@@ -845,7 +850,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
845 return -EIO; 850 return -EIO;
846 } 851 }
847 852
848 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP); 853 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
849 if (rc) 854 if (rc)
850 return rc; 855 return rc;
851 856
@@ -863,7 +868,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
863 868
864 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 869 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
865 if (rc) { 870 if (rc) {
866 DeleteMidQEntry(midQ); 871 delete_mid(midQ);
867 mutex_unlock(&ses->server->srv_mutex); 872 mutex_unlock(&ses->server->srv_mutex);
868 return rc; 873 return rc;
869 } 874 }
@@ -880,7 +885,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
880 mutex_unlock(&ses->server->srv_mutex); 885 mutex_unlock(&ses->server->srv_mutex);
881 886
882 if (rc < 0) { 887 if (rc < 0) {
883 DeleteMidQEntry(midQ); 888 delete_mid(midQ);
884 return rc; 889 return rc;
885 } 890 }
886 891
@@ -899,10 +904,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
899 if (in_buf->Command == SMB_COM_TRANSACTION2) { 904 if (in_buf->Command == SMB_COM_TRANSACTION2) {
900 /* POSIX lock. We send a NT_CANCEL SMB to cause the 905 /* POSIX lock. We send a NT_CANCEL SMB to cause the
901 blocking lock to return. */ 906 blocking lock to return. */
902 907 rc = send_nt_cancel(ses->server, in_buf, midQ);
903 rc = send_nt_cancel(tcon, in_buf, midQ);
904 if (rc) { 908 if (rc) {
905 DeleteMidQEntry(midQ); 909 delete_mid(midQ);
906 return rc; 910 return rc;
907 } 911 }
908 } else { 912 } else {
@@ -914,47 +918,22 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
914 /* If we get -ENOLCK back the lock may have 918 /* If we get -ENOLCK back the lock may have
915 already been removed. Don't exit in this case. */ 919 already been removed. Don't exit in this case. */
916 if (rc && rc != -ENOLCK) { 920 if (rc && rc != -ENOLCK) {
917 DeleteMidQEntry(midQ); 921 delete_mid(midQ);
918 return rc; 922 return rc;
919 } 923 }
920 } 924 }
921 925
922 /* Wait 5 seconds for the response. */ 926 if (wait_for_response(ses->server, midQ) == 0) {
923 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
924 /* We got the response - restart system call. */ 927 /* We got the response - restart system call. */
925 rstart = 1; 928 rstart = 1;
926 } 929 }
927 } 930 }
928 931
929 spin_lock(&GlobalMid_Lock); 932 rc = sync_mid_result(midQ, ses->server);
930 if (midQ->resp_buf) { 933 if (rc != 0)
931 spin_unlock(&GlobalMid_Lock);
932 receive_len = midQ->resp_buf->smb_buf_length;
933 } else {
934 cERROR(1, "No response for cmd %d mid %d",
935 midQ->command, midQ->mid);
936 if (midQ->midState == MID_REQUEST_SUBMITTED) {
937 if (ses->server->tcpStatus == CifsExiting)
938 rc = -EHOSTDOWN;
939 else {
940 ses->server->tcpStatus = CifsNeedReconnect;
941 midQ->midState = MID_RETRY_NEEDED;
942 }
943 }
944
945 if (rc != -EHOSTDOWN) {
946 if (midQ->midState == MID_RETRY_NEEDED) {
947 rc = -EAGAIN;
948 cFYI(1, "marking request for retry");
949 } else {
950 rc = -EIO;
951 }
952 }
953 spin_unlock(&GlobalMid_Lock);
954 DeleteMidQEntry(midQ);
955 return rc; 934 return rc;
956 }
957 935
936 receive_len = midQ->resp_buf->smb_buf_length;
958 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 937 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
959 cERROR(1, "Frame too large received. Length: %d Xid: %d", 938 cERROR(1, "Frame too large received. Length: %d Xid: %d",
960 receive_len, xid); 939 receive_len, xid);
@@ -1001,7 +980,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
1001 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 980 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1002 981
1003out: 982out:
1004 DeleteMidQEntry(midQ); 983 delete_mid(midQ);
1005 if (rstart && rc == -EACCES) 984 if (rstart && rc == -EACCES)
1006 return -ERESTARTSYS; 985 return -ERESTARTSYS;
1007 return rc; 986 return rc;