aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-02-01 18:22:40 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-02-01 18:22:40 -0500
commit405b864d3fd579d3e8a1002f7452343fbb6dbe99 (patch)
treed5e70f3c337fa20363cd090a7bb4d664d495b275
parentfdf4c587a793ba87935e38e7f25a9540bc9a7b95 (diff)
parent6284644e8de1f4005166c918c3d2aa4c510ab9f6 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: cifs: fix length checks in checkSMB [CIFS] Update cifs minor version cifs: No need to check crypto blockcipher allocation cifs: clean up some compiler warnings cifs: make CIFS depend on CRYPTO_MD4 cifs: force a reconnect if there are too many MIDs in flight cifs: don't pop a printk when sending on a socket is interrupted cifs: simplify SMB header check routine cifs: send an NT_CANCEL request when a process is signalled cifs: handle cancelled requests better cifs: fix two compiler warning about uninitialized vars
-rw-r--r--fs/cifs/Kconfig1
-rw-r--r--fs/cifs/cifs_dfs_ref.c9
-rw-r--r--fs/cifs/cifsencrypt.c5
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifssmb.c3
-rw-r--r--fs/cifs/file.c8
-rw-r--r--fs/cifs/link.c3
-rw-r--r--fs/cifs/misc.c116
-rw-r--r--fs/cifs/readdir.c3
-rw-r--r--fs/cifs/smbencrypt.c3
-rw-r--r--fs/cifs/transport.c62
11 files changed, 130 insertions, 85 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index ee45648b0d1a..7cb0f7f847e4 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -3,6 +3,7 @@ config CIFS
3 depends on INET 3 depends on INET
4 select NLS 4 select NLS
5 select CRYPTO 5 select CRYPTO
6 select CRYPTO_MD4
6 select CRYPTO_MD5 7 select CRYPTO_MD5
7 select CRYPTO_HMAC 8 select CRYPTO_HMAC
8 select CRYPTO_ARC4 9 select CRYPTO_ARC4
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index f1c68629f277..0a265ad9e426 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -282,8 +282,6 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
282 cFYI(1, "in %s", __func__); 282 cFYI(1, "in %s", __func__);
283 BUG_ON(IS_ROOT(mntpt)); 283 BUG_ON(IS_ROOT(mntpt));
284 284
285 xid = GetXid();
286
287 /* 285 /*
288 * The MSDFS spec states that paths in DFS referral requests and 286 * The MSDFS spec states that paths in DFS referral requests and
289 * responses must be prefixed by a single '\' character instead of 287 * responses must be prefixed by a single '\' character instead of
@@ -293,7 +291,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
293 mnt = ERR_PTR(-ENOMEM); 291 mnt = ERR_PTR(-ENOMEM);
294 full_path = build_path_from_dentry(mntpt); 292 full_path = build_path_from_dentry(mntpt);
295 if (full_path == NULL) 293 if (full_path == NULL)
296 goto free_xid; 294 goto cdda_exit;
297 295
298 cifs_sb = CIFS_SB(mntpt->d_inode->i_sb); 296 cifs_sb = CIFS_SB(mntpt->d_inode->i_sb);
299 tlink = cifs_sb_tlink(cifs_sb); 297 tlink = cifs_sb_tlink(cifs_sb);
@@ -303,9 +301,11 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
303 } 301 }
304 ses = tlink_tcon(tlink)->ses; 302 ses = tlink_tcon(tlink)->ses;
305 303
304 xid = GetXid();
306 rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls, 305 rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls,
307 &num_referrals, &referrals, 306 &num_referrals, &referrals,
308 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 307 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
308 FreeXid(xid);
309 309
310 cifs_put_tlink(tlink); 310 cifs_put_tlink(tlink);
311 311
@@ -338,8 +338,7 @@ success:
338 free_dfs_info_array(referrals, num_referrals); 338 free_dfs_info_array(referrals, num_referrals);
339free_full_path: 339free_full_path:
340 kfree(full_path); 340 kfree(full_path);
341free_xid: 341cdda_exit:
342 FreeXid(xid);
343 cFYI(1, "leaving %s" , __func__); 342 cFYI(1, "leaving %s" , __func__);
344 return mnt; 343 return mnt;
345} 344}
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 0db5f1de0227..a51585f9852b 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -657,9 +657,10 @@ calc_seckey(struct cifsSesInfo *ses)
657 get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE); 657 get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
658 658
659 tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); 659 tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
660 if (!tfm_arc4 || IS_ERR(tfm_arc4)) { 660 if (IS_ERR(tfm_arc4)) {
661 rc = PTR_ERR(tfm_arc4);
661 cERROR(1, "could not allocate crypto API arc4\n"); 662 cERROR(1, "could not allocate crypto API arc4\n");
662 return PTR_ERR(tfm_arc4); 663 return rc;
663 } 664 }
664 665
665 desc.tfm = tfm_arc4; 666 desc.tfm = tfm_arc4;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 14789a97304e..4a3330235d55 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -127,5 +127,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
127extern const struct export_operations cifs_export_ops; 127extern const struct export_operations cifs_export_ops;
128#endif /* EXPERIMENTAL */ 128#endif /* EXPERIMENTAL */
129 129
130#define CIFS_VERSION "1.69" 130#define CIFS_VERSION "1.70"
131#endif /* _CIFSFS_H */ 131#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 3106f5e5c633..46c66ed01af4 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -4914,7 +4914,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4914 __u16 fid, __u32 pid_of_opener, bool SetAllocation) 4914 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4915{ 4915{
4916 struct smb_com_transaction2_sfi_req *pSMB = NULL; 4916 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4917 char *data_offset;
4918 struct file_end_of_file_info *parm_data; 4917 struct file_end_of_file_info *parm_data;
4919 int rc = 0; 4918 int rc = 0;
4920 __u16 params, param_offset, offset, byte_count, count; 4919 __u16 params, param_offset, offset, byte_count, count;
@@ -4938,8 +4937,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4938 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; 4937 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4939 offset = param_offset + params; 4938 offset = param_offset + params;
4940 4939
4941 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4942
4943 count = sizeof(struct file_end_of_file_info); 4940 count = sizeof(struct file_end_of_file_info);
4944 pSMB->MaxParameterCount = cpu_to_le16(2); 4941 pSMB->MaxParameterCount = cpu_to_le16(2);
4945 /* BB find exact max SMB PDU from sess structure BB */ 4942 /* BB find exact max SMB PDU from sess structure BB */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 0de17c1db608..74c0a282d012 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -346,7 +346,6 @@ int cifs_open(struct inode *inode, struct file *file)
346 struct cifsTconInfo *tcon; 346 struct cifsTconInfo *tcon;
347 struct tcon_link *tlink; 347 struct tcon_link *tlink;
348 struct cifsFileInfo *pCifsFile = NULL; 348 struct cifsFileInfo *pCifsFile = NULL;
349 struct cifsInodeInfo *pCifsInode;
350 char *full_path = NULL; 349 char *full_path = NULL;
351 bool posix_open_ok = false; 350 bool posix_open_ok = false;
352 __u16 netfid; 351 __u16 netfid;
@@ -361,8 +360,6 @@ int cifs_open(struct inode *inode, struct file *file)
361 } 360 }
362 tcon = tlink_tcon(tlink); 361 tcon = tlink_tcon(tlink);
363 362
364 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
365
366 full_path = build_path_from_dentry(file->f_path.dentry); 363 full_path = build_path_from_dentry(file->f_path.dentry);
367 if (full_path == NULL) { 364 if (full_path == NULL) {
368 rc = -ENOMEM; 365 rc = -ENOMEM;
@@ -1146,7 +1143,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1146 char *write_data; 1143 char *write_data;
1147 int rc = -EFAULT; 1144 int rc = -EFAULT;
1148 int bytes_written = 0; 1145 int bytes_written = 0;
1149 struct cifs_sb_info *cifs_sb;
1150 struct inode *inode; 1146 struct inode *inode;
1151 struct cifsFileInfo *open_file; 1147 struct cifsFileInfo *open_file;
1152 1148
@@ -1154,7 +1150,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1154 return -EFAULT; 1150 return -EFAULT;
1155 1151
1156 inode = page->mapping->host; 1152 inode = page->mapping->host;
1157 cifs_sb = CIFS_SB(inode->i_sb);
1158 1153
1159 offset += (loff_t)from; 1154 offset += (loff_t)from;
1160 write_data = kmap(page); 1155 write_data = kmap(page);
@@ -1667,7 +1662,8 @@ static ssize_t
1667cifs_iovec_write(struct file *file, const struct iovec *iov, 1662cifs_iovec_write(struct file *file, const struct iovec *iov,
1668 unsigned long nr_segs, loff_t *poffset) 1663 unsigned long nr_segs, loff_t *poffset)
1669{ 1664{
1670 size_t total_written = 0, written = 0; 1665 size_t total_written = 0;
1666 unsigned int written = 0;
1671 unsigned long num_pages, npages; 1667 unsigned long num_pages, npages;
1672 size_t copied, len, cur_len, i; 1668 size_t copied, len, cur_len, i;
1673 struct kvec *to_send; 1669 struct kvec *to_send;
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 02cd60aefbff..e8804d373404 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -55,8 +55,9 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
55 55
56 md5 = crypto_alloc_shash("md5", 0, 0); 56 md5 = crypto_alloc_shash("md5", 0, 0);
57 if (IS_ERR(md5)) { 57 if (IS_ERR(md5)) {
58 rc = PTR_ERR(md5);
58 cERROR(1, "%s: Crypto md5 allocation error %d\n", __func__, rc); 59 cERROR(1, "%s: Crypto md5 allocation error %d\n", __func__, rc);
59 return PTR_ERR(md5); 60 return rc;
60 } 61 }
61 size = sizeof(struct shash_desc) + crypto_shash_descsize(md5); 62 size = sizeof(struct shash_desc) + crypto_shash_descsize(md5);
62 sdescmd5 = kmalloc(size, GFP_KERNEL); 63 sdescmd5 = kmalloc(size, GFP_KERNEL);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index a09e077ba925..2a930a752a78 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -236,10 +236,7 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
236{ 236{
237 __u16 mid = 0; 237 __u16 mid = 0;
238 __u16 last_mid; 238 __u16 last_mid;
239 int collision; 239 bool collision;
240
241 if (server == NULL)
242 return mid;
243 240
244 spin_lock(&GlobalMid_Lock); 241 spin_lock(&GlobalMid_Lock);
245 last_mid = server->CurrentMid; /* we do not want to loop forever */ 242 last_mid = server->CurrentMid; /* we do not want to loop forever */
@@ -252,24 +249,38 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
252 (and it would also have to have been a request that 249 (and it would also have to have been a request that
253 did not time out) */ 250 did not time out) */
254 while (server->CurrentMid != last_mid) { 251 while (server->CurrentMid != last_mid) {
255 struct list_head *tmp;
256 struct mid_q_entry *mid_entry; 252 struct mid_q_entry *mid_entry;
253 unsigned int num_mids;
257 254
258 collision = 0; 255 collision = false;
259 if (server->CurrentMid == 0) 256 if (server->CurrentMid == 0)
260 server->CurrentMid++; 257 server->CurrentMid++;
261 258
262 list_for_each(tmp, &server->pending_mid_q) { 259 num_mids = 0;
263 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 260 list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
264 261 ++num_mids;
265 if ((mid_entry->mid == server->CurrentMid) && 262 if (mid_entry->mid == server->CurrentMid &&
266 (mid_entry->midState == MID_REQUEST_SUBMITTED)) { 263 mid_entry->midState == MID_REQUEST_SUBMITTED) {
267 /* This mid is in use, try a different one */ 264 /* This mid is in use, try a different one */
268 collision = 1; 265 collision = true;
269 break; 266 break;
270 } 267 }
271 } 268 }
272 if (collision == 0) { 269
270 /*
271 * if we have more than 32k mids in the list, then something
272 * is very wrong. Possibly a local user is trying to DoS the
273 * box by issuing long-running calls and SIGKILL'ing them. If
274 * we get to 2^16 mids then we're in big trouble as this
275 * function could loop forever.
276 *
277 * Go ahead and assign out the mid in this situation, but force
278 * an eventual reconnect to clean out the pending_mid_q.
279 */
280 if (num_mids > 32768)
281 server->tcpStatus = CifsNeedReconnect;
282
283 if (!collision) {
273 mid = server->CurrentMid; 284 mid = server->CurrentMid;
274 break; 285 break;
275 } 286 }
@@ -381,29 +392,31 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
381} 392}
382 393
383static int 394static int
384checkSMBhdr(struct smb_hdr *smb, __u16 mid) 395check_smb_hdr(struct smb_hdr *smb, __u16 mid)
385{ 396{
386 /* Make sure that this really is an SMB, that it is a response, 397 /* does it have the right SMB "signature" ? */
387 and that the message ids match */ 398 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) {
388 if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) && 399 cERROR(1, "Bad protocol string signature header 0x%x",
389 (mid == smb->Mid)) { 400 *(unsigned int *)smb->Protocol);
390 if (smb->Flags & SMBFLG_RESPONSE) 401 return 1;
391 return 0; 402 }
392 else { 403
393 /* only one valid case where server sends us request */ 404 /* Make sure that message ids match */
394 if (smb->Command == SMB_COM_LOCKING_ANDX) 405 if (mid != smb->Mid) {
395 return 0; 406 cERROR(1, "Mids do not match. received=%u expected=%u",
396 else 407 smb->Mid, mid);
397 cERROR(1, "Received Request not response"); 408 return 1;
398 }
399 } else { /* bad signature or mid */
400 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
401 cERROR(1, "Bad protocol string signature header %x",
402 *(unsigned int *) smb->Protocol);
403 if (mid != smb->Mid)
404 cERROR(1, "Mids do not match");
405 } 409 }
406 cERROR(1, "bad smb detected. The Mid=%d", smb->Mid); 410
411 /* if it's a response then accept */
412 if (smb->Flags & SMBFLG_RESPONSE)
413 return 0;
414
415 /* only one valid case where server sends us request */
416 if (smb->Command == SMB_COM_LOCKING_ANDX)
417 return 0;
418
419 cERROR(1, "Server sent request, not response. mid=%u", smb->Mid);
407 return 1; 420 return 1;
408} 421}
409 422
@@ -448,7 +461,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
448 return 1; 461 return 1;
449 } 462 }
450 463
451 if (checkSMBhdr(smb, mid)) 464 if (check_smb_hdr(smb, mid))
452 return 1; 465 return 1;
453 clc_len = smbCalcSize_LE(smb); 466 clc_len = smbCalcSize_LE(smb);
454 467
@@ -465,25 +478,26 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
465 if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) 478 if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
466 return 0; /* bcc wrapped */ 479 return 0; /* bcc wrapped */
467 } 480 }
468 cFYI(1, "Calculated size %d vs length %d mismatch for mid %d", 481 cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u",
469 clc_len, 4 + len, smb->Mid); 482 clc_len, 4 + len, smb->Mid);
470 /* Windows XP can return a few bytes too much, presumably 483
471 an illegal pad, at the end of byte range lock responses 484 if (4 + len < clc_len) {
472 so we allow for that three byte pad, as long as actual 485 cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u",
473 received length is as long or longer than calculated length */
474 /* We have now had to extend this more, since there is a
475 case in which it needs to be bigger still to handle a
476 malformed response to transact2 findfirst from WinXP when
477 access denied is returned and thus bcc and wct are zero
478 but server says length is 0x21 bytes too long as if the server
479 forget to reset the smb rfc1001 length when it reset the
480 wct and bcc to minimum size and drop the t2 parms and data */
481 if ((4+len > clc_len) && (len <= clc_len + 512))
482 return 0;
483 else {
484 cERROR(1, "RFC1001 size %d bigger than SMB for Mid=%d",
485 len, smb->Mid); 486 len, smb->Mid);
486 return 1; 487 return 1;
488 } else if (len > clc_len + 512) {
489 /*
490 * Some servers (Windows XP in particular) send more
491 * data than the lengths in the SMB packet would
492 * indicate on certain calls (byte range locks and
493 * trans2 find first calls in particular). While the
494 * client can handle such a frame by ignoring the
495 * trailing data, we choose limit the amount of extra
496 * data to 512 bytes.
497 */
498 cERROR(1, "RFC1001 size %u more than 512 bytes larger "
499 "than SMB for mid=%u", len, smb->Mid);
500 return 1;
487 } 501 }
488 } 502 }
489 return 0; 503 return 0;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 7f25cc3d2256..f8e4cd2a7912 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -764,7 +764,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
764{ 764{
765 int rc = 0; 765 int rc = 0;
766 int xid, i; 766 int xid, i;
767 struct cifs_sb_info *cifs_sb;
768 struct cifsTconInfo *pTcon; 767 struct cifsTconInfo *pTcon;
769 struct cifsFileInfo *cifsFile = NULL; 768 struct cifsFileInfo *cifsFile = NULL;
770 char *current_entry; 769 char *current_entry;
@@ -775,8 +774,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
775 774
776 xid = GetXid(); 775 xid = GetXid();
777 776
778 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
779
780 /* 777 /*
781 * Ensure FindFirst doesn't fail before doing filldir() for '.' and 778 * Ensure FindFirst doesn't fail before doing filldir() for '.' and
782 * '..'. Otherwise we won't be able to notify VFS in case of failure. 779 * '..'. Otherwise we won't be able to notify VFS in case of failure.
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index b5450e9f40c0..b5041c849981 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -58,8 +58,9 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
58 58
59 md4 = crypto_alloc_shash("md4", 0, 0); 59 md4 = crypto_alloc_shash("md4", 0, 0);
60 if (IS_ERR(md4)) { 60 if (IS_ERR(md4)) {
61 rc = PTR_ERR(md4);
61 cERROR(1, "%s: Crypto md4 allocation error %d\n", __func__, rc); 62 cERROR(1, "%s: Crypto md4 allocation error %d\n", __func__, rc);
62 return PTR_ERR(md4); 63 return rc;
63 } 64 }
64 size = sizeof(struct shash_desc) + crypto_shash_descsize(md4); 65 size = sizeof(struct shash_desc) + crypto_shash_descsize(md4);
65 sdescmd4 = kmalloc(size, GFP_KERNEL); 66 sdescmd4 = kmalloc(size, GFP_KERNEL);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index c1ccca1a933f..b8c5e2eb43d0 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -236,9 +236,9 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
236 server->tcpStatus = CifsNeedReconnect; 236 server->tcpStatus = CifsNeedReconnect;
237 } 237 }
238 238
239 if (rc < 0) { 239 if (rc < 0 && rc != -EINTR)
240 cERROR(1, "Error %d sending data on socket to server", rc); 240 cERROR(1, "Error %d sending data on socket to server", rc);
241 } else 241 else
242 rc = 0; 242 rc = 0;
243 243
244 /* Don't want to modify the buffer as a 244 /* Don't want to modify the buffer as a
@@ -570,17 +570,33 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
570#endif 570#endif
571 571
572 mutex_unlock(&ses->server->srv_mutex); 572 mutex_unlock(&ses->server->srv_mutex);
573 cifs_small_buf_release(in_buf);
574 573
575 if (rc < 0) 574 if (rc < 0) {
575 cifs_small_buf_release(in_buf);
576 goto out; 576 goto out;
577 }
577 578
578 if (long_op == CIFS_ASYNC_OP) 579 if (long_op == CIFS_ASYNC_OP) {
580 cifs_small_buf_release(in_buf);
579 goto out; 581 goto out;
582 }
580 583
581 rc = wait_for_response(ses->server, midQ); 584 rc = wait_for_response(ses->server, midQ);
582 if (rc != 0) 585 if (rc != 0) {
583 goto out; 586 send_nt_cancel(ses->server, in_buf, midQ);
587 spin_lock(&GlobalMid_Lock);
588 if (midQ->midState == MID_REQUEST_SUBMITTED) {
589 midQ->callback = DeleteMidQEntry;
590 spin_unlock(&GlobalMid_Lock);
591 cifs_small_buf_release(in_buf);
592 atomic_dec(&ses->server->inFlight);
593 wake_up(&ses->server->request_q);
594 return rc;
595 }
596 spin_unlock(&GlobalMid_Lock);
597 }
598
599 cifs_small_buf_release(in_buf);
584 600
585 rc = sync_mid_result(midQ, ses->server); 601 rc = sync_mid_result(midQ, ses->server);
586 if (rc != 0) { 602 if (rc != 0) {
@@ -724,8 +740,19 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
724 goto out; 740 goto out;
725 741
726 rc = wait_for_response(ses->server, midQ); 742 rc = wait_for_response(ses->server, midQ);
727 if (rc != 0) 743 if (rc != 0) {
728 goto out; 744 send_nt_cancel(ses->server, in_buf, midQ);
745 spin_lock(&GlobalMid_Lock);
746 if (midQ->midState == MID_REQUEST_SUBMITTED) {
747 /* no longer considered to be "in-flight" */
748 midQ->callback = DeleteMidQEntry;
749 spin_unlock(&GlobalMid_Lock);
750 atomic_dec(&ses->server->inFlight);
751 wake_up(&ses->server->request_q);
752 return rc;
753 }
754 spin_unlock(&GlobalMid_Lock);
755 }
729 756
730 rc = sync_mid_result(midQ, ses->server); 757 rc = sync_mid_result(midQ, ses->server);
731 if (rc != 0) { 758 if (rc != 0) {
@@ -922,10 +949,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
922 } 949 }
923 } 950 }
924 951
925 if (wait_for_response(ses->server, midQ) == 0) { 952 rc = wait_for_response(ses->server, midQ);
926 /* We got the response - restart system call. */ 953 if (rc) {
927 rstart = 1; 954 send_nt_cancel(ses->server, in_buf, midQ);
955 spin_lock(&GlobalMid_Lock);
956 if (midQ->midState == MID_REQUEST_SUBMITTED) {
957 /* no longer considered to be "in-flight" */
958 midQ->callback = DeleteMidQEntry;
959 spin_unlock(&GlobalMid_Lock);
960 return rc;
961 }
962 spin_unlock(&GlobalMid_Lock);
928 } 963 }
964
965 /* We got the response - restart system call. */
966 rstart = 1;
929 } 967 }
930 968
931 rc = sync_mid_result(midQ, ses->server); 969 rc = sync_mid_result(midQ, ses->server);