aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.com>2006-08-02 17:56:33 -0400
committerSteve French <sfrench@us.ibm.com>2006-08-11 17:28:47 -0400
commit7ee1af765dfa3146aef958258003245e082284e5 (patch)
tree90ab87a136d63c937064e595fd8062e5bc721e03 /fs
parent6c3d8909d85b2c18fd7a6e64f0ca757a257b40fa (diff)
[CIFS]
Allow Windows blocking locks to be cancelled via a CANCEL_LOCK call. TODO - restrict this to servers that support NT_STATUS codes (Win9x will probably not support this call). Signed-off-by: Jeremy Allison <jra@samba.org> Signed-off-by: Steve French <sfrench@us.ibm.com> (cherry picked from 570d4d2d895569825d0d017d4e76b51138f68864 commit)
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsglob.h15
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/cifssmb.c15
-rw-r--r--fs/cifs/file.c95
-rw-r--r--fs/cifs/netmisc.c1
-rw-r--r--fs/cifs/smberr.h1
-rw-r--r--fs/cifs/transport.c677
7 files changed, 512 insertions, 296 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 39b43e6a7509..b24006c47df1 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2006 4 * Copyright (C) International Business Machines Corp., 2002,2006
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * Jeremy Allison (jra@samba.org)
6 * 7 *
7 * This library is free software; you can redistribute it and/or modify 8 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published 9 * it under the terms of the GNU Lesser General Public License as published
@@ -267,14 +268,14 @@ struct cifsTconInfo {
267}; 268};
268 269
269/* 270/*
270 * This info hangs off the cifsFileInfo structure. This is used to track 271 * This info hangs off the cifsFileInfo structure, pointed to by llist.
271 * byte stream locks on the file 272 * This is used to track byte stream locks on the file
272 */ 273 */
273struct cifsLockInfo { 274struct cifsLockInfo {
274 struct cifsLockInfo *next; 275 struct list_head llist; /* pointer to next cifsLockInfo */
275 int start; 276 __u64 offset;
276 int length; 277 __u64 length;
277 int type; 278 __u8 type;
278}; 279};
279 280
280/* 281/*
@@ -305,6 +306,8 @@ struct cifsFileInfo {
305 /* lock scope id (0 if none) */ 306 /* lock scope id (0 if none) */
306 struct file * pfile; /* needed for writepage */ 307 struct file * pfile; /* needed for writepage */
307 struct inode * pInode; /* needed for oplock break */ 308 struct inode * pInode; /* needed for oplock break */
309 struct semaphore lock_sem;
310 struct list_head llist; /* list of byte range locks we have. */
308 unsigned closePend:1; /* file is marked to close */ 311 unsigned closePend:1; /* file is marked to close */
309 unsigned invalidHandle:1; /* file closed via session abend */ 312 unsigned invalidHandle:1; /* file closed via session abend */
310 atomic_t wrtPending; /* handle in use - defer close */ 313 atomic_t wrtPending; /* handle in use - defer close */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index a5ddc62d6fe6..b35c55c3c8bb 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -50,6 +50,10 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
50extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, 50extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
51 struct kvec *, int /* nvec to send */, 51 struct kvec *, int /* nvec to send */,
52 int * /* type of buf returned */ , const int long_op); 52 int * /* type of buf returned */ , const int long_op);
53extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *,
54 struct smb_hdr * /* input */ ,
55 struct smb_hdr * /* out */ ,
56 int * /* bytes returned */);
53extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); 57extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
54extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); 58extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
55extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); 59extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index c03c42ee9eb9..dcbc3e075e81 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1460,8 +1460,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1460 pSMB->hdr.smb_buf_length += count; 1460 pSMB->hdr.smb_buf_length += count;
1461 pSMB->ByteCount = cpu_to_le16(count); 1461 pSMB->ByteCount = cpu_to_le16(count);
1462 1462
1463 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1463 if (waitFlag) {
1464 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1465 (struct smb_hdr *) pSMBr, &bytes_returned);
1466 } else {
1467 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1464 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1468 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1469 }
1465 cifs_stats_inc(&tcon->num_locks); 1470 cifs_stats_inc(&tcon->num_locks);
1466 if (rc) { 1471 if (rc) {
1467 cFYI(1, ("Send error in Lock = %d", rc)); 1472 cFYI(1, ("Send error in Lock = %d", rc));
@@ -1546,8 +1551,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1546 pSMB->Reserved4 = 0; 1551 pSMB->Reserved4 = 0;
1547 pSMB->hdr.smb_buf_length += byte_count; 1552 pSMB->hdr.smb_buf_length += byte_count;
1548 pSMB->ByteCount = cpu_to_le16(byte_count); 1553 pSMB->ByteCount = cpu_to_le16(byte_count);
1549 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1554 if (waitFlag) {
1555 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1556 (struct smb_hdr *) pSMBr, &bytes_returned);
1557 } else {
1558 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1550 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1559 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1560 }
1561
1551 if (rc) { 1562 if (rc) {
1552 cFYI(1, ("Send error in Posix Lock = %d", rc)); 1563 cFYI(1, ("Send error in Posix Lock = %d", rc));
1553 } else if (get_flag) { 1564 } else if (get_flag) {
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 52e2e4c8794b..e9c5ba9084fc 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2002,2003 6 * Copyright (C) International Business Machines Corp., 2002,2003
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * Jeremy Allison (jra@samba.org)
8 * 9 *
9 * This library is free software; you can redistribute it and/or modify 10 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published 11 * it under the terms of the GNU Lesser General Public License as published
@@ -47,6 +48,8 @@ static inline struct cifsFileInfo *cifs_init_private(
47 private_data->netfid = netfid; 48 private_data->netfid = netfid;
48 private_data->pid = current->tgid; 49 private_data->pid = current->tgid;
49 init_MUTEX(&private_data->fh_sem); 50 init_MUTEX(&private_data->fh_sem);
51 init_MUTEX(&private_data->lock_sem);
52 INIT_LIST_HEAD(&private_data->llist);
50 private_data->pfile = file; /* needed for writepage */ 53 private_data->pfile = file; /* needed for writepage */
51 private_data->pInode = inode; 54 private_data->pInode = inode;
52 private_data->invalidHandle = FALSE; 55 private_data->invalidHandle = FALSE;
@@ -473,6 +476,8 @@ int cifs_close(struct inode *inode, struct file *file)
473 cifs_sb = CIFS_SB(inode->i_sb); 476 cifs_sb = CIFS_SB(inode->i_sb);
474 pTcon = cifs_sb->tcon; 477 pTcon = cifs_sb->tcon;
475 if (pSMBFile) { 478 if (pSMBFile) {
479 struct cifsLockInfo *li, *tmp;
480
476 pSMBFile->closePend = TRUE; 481 pSMBFile->closePend = TRUE;
477 if (pTcon) { 482 if (pTcon) {
478 /* no sense reconnecting to close a file that is 483 /* no sense reconnecting to close a file that is
@@ -496,6 +501,16 @@ int cifs_close(struct inode *inode, struct file *file)
496 pSMBFile->netfid); 501 pSMBFile->netfid);
497 } 502 }
498 } 503 }
504
505 /* Delete any outstanding lock records.
506 We'll lose them when the file is closed anyway. */
507 down(&pSMBFile->lock_sem);
508 list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
509 list_del(&li->llist);
510 kfree(li);
511 }
512 up(&pSMBFile->lock_sem);
513
499 write_lock(&GlobalSMBSeslock); 514 write_lock(&GlobalSMBSeslock);
500 list_del(&pSMBFile->flist); 515 list_del(&pSMBFile->flist);
501 list_del(&pSMBFile->tlist); 516 list_del(&pSMBFile->tlist);
@@ -570,6 +585,21 @@ int cifs_closedir(struct inode *inode, struct file *file)
570 return rc; 585 return rc;
571} 586}
572 587
588static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
589 __u64 offset, __u8 lockType)
590{
591 struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
592 if (li == NULL)
593 return -ENOMEM;
594 li->offset = offset;
595 li->length = len;
596 li->type = lockType;
597 down(&fid->lock_sem);
598 list_add(&li->llist, &fid->llist);
599 up(&fid->lock_sem);
600 return 0;
601}
602
573int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 603int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
574{ 604{
575 int rc, xid; 605 int rc, xid;
@@ -581,6 +611,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
581 struct cifsTconInfo *pTcon; 611 struct cifsTconInfo *pTcon;
582 __u16 netfid; 612 __u16 netfid;
583 __u8 lockType = LOCKING_ANDX_LARGE_FILES; 613 __u8 lockType = LOCKING_ANDX_LARGE_FILES;
614 int posix_locking;
584 615
585 length = 1 + pfLock->fl_end - pfLock->fl_start; 616 length = 1 + pfLock->fl_end - pfLock->fl_start;
586 rc = -EACCES; 617 rc = -EACCES;
@@ -639,14 +670,14 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
639 } 670 }
640 netfid = ((struct cifsFileInfo *)file->private_data)->netfid; 671 netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
641 672
673 posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
674 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability));
642 675
643 /* BB add code here to normalize offset and length to 676 /* BB add code here to normalize offset and length to
644 account for negative length which we can not accept over the 677 account for negative length which we can not accept over the
645 wire */ 678 wire */
646 if (IS_GETLK(cmd)) { 679 if (IS_GETLK(cmd)) {
647 if((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && 680 if(posix_locking) {
648 (CIFS_UNIX_FCNTL_CAP &
649 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
650 int posix_lock_type; 681 int posix_lock_type;
651 if(lockType & LOCKING_ANDX_SHARED_LOCK) 682 if(lockType & LOCKING_ANDX_SHARED_LOCK)
652 posix_lock_type = CIFS_RDLCK; 683 posix_lock_type = CIFS_RDLCK;
@@ -682,9 +713,15 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
682 FreeXid(xid); 713 FreeXid(xid);
683 return rc; 714 return rc;
684 } 715 }
685 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && 716
686 (CIFS_UNIX_FCNTL_CAP & 717 if (!numLock && !numUnlock) {
687 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { 718 /* if no lock or unlock then nothing
719 to do since we do not know what it is */
720 FreeXid(xid);
721 return -EOPNOTSUPP;
722 }
723
724 if (posix_locking) {
688 int posix_lock_type; 725 int posix_lock_type;
689 if(lockType & LOCKING_ANDX_SHARED_LOCK) 726 if(lockType & LOCKING_ANDX_SHARED_LOCK)
690 posix_lock_type = CIFS_RDLCK; 727 posix_lock_type = CIFS_RDLCK;
@@ -693,18 +730,46 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
693 730
694 if(numUnlock == 1) 731 if(numUnlock == 1)
695 posix_lock_type = CIFS_UNLCK; 732 posix_lock_type = CIFS_UNLCK;
696 else if(numLock == 0) { 733
697 /* if no lock or unlock then nothing
698 to do since we do not know what it is */
699 FreeXid(xid);
700 return -EOPNOTSUPP;
701 }
702 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, 734 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
703 length, pfLock, 735 length, pfLock,
704 posix_lock_type, wait_flag); 736 posix_lock_type, wait_flag);
705 } else 737 } else {
706 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, 738 struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;
707 numUnlock, numLock, lockType, wait_flag); 739
740 if (numLock) {
741 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
742 0, numLock, lockType, wait_flag);
743
744 if (rc == 0) {
745 /* For Windows locks we must store them. */
746 rc = store_file_lock(fid, length,
747 pfLock->fl_start, lockType);
748 }
749 } else if (numUnlock) {
750 /* For each stored lock that this unlock overlaps
751 completely, unlock it. */
752 int stored_rc = 0;
753 struct cifsLockInfo *li, *tmp;
754
755 down(&fid->lock_sem);
756 list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
757 if (pfLock->fl_start <= li->offset &&
758 length >= li->length) {
759 stored_rc = CIFSSMBLock(xid, pTcon, netfid,
760 li->length, li->offset,
761 1, 0, li->type, FALSE);
762 if (stored_rc)
763 rc = stored_rc;
764
765 list_del(&li->llist);
766 kfree(li);
767 }
768 }
769 up(&fid->lock_sem);
770 }
771 }
772
708 if (pfLock->fl_flags & FL_POSIX) 773 if (pfLock->fl_flags & FL_POSIX)
709 posix_lock_file_wait(file, pfLock); 774 posix_lock_file_wait(file, pfLock);
710 FreeXid(xid); 775 FreeXid(xid);
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index b66eff5dc624..ce87550e918f 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -72,6 +72,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
72 {ERRinvlevel,-EOPNOTSUPP}, 72 {ERRinvlevel,-EOPNOTSUPP},
73 {ERRdirnotempty, -ENOTEMPTY}, 73 {ERRdirnotempty, -ENOTEMPTY},
74 {ERRnotlocked, -ENOLCK}, 74 {ERRnotlocked, -ENOLCK},
75 {ERRcancelviolation, -ENOLCK},
75 {ERRalreadyexists, -EEXIST}, 76 {ERRalreadyexists, -EEXIST},
76 {ERRmoredata, -EOVERFLOW}, 77 {ERRmoredata, -EOVERFLOW},
77 {ERReasnotsupported,-EOPNOTSUPP}, 78 {ERReasnotsupported,-EOPNOTSUPP},
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index cd41c67ff8d3..212c3c296409 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -95,6 +95,7 @@
95#define ERRinvlevel 124 95#define ERRinvlevel 124
96#define ERRdirnotempty 145 96#define ERRdirnotempty 145
97#define ERRnotlocked 158 97#define ERRnotlocked 158
98#define ERRcancelviolation 173
98#define ERRalreadyexists 183 99#define ERRalreadyexists 183
99#define ERRbadpipe 230 100#define ERRbadpipe 230
100#define ERRpipebusy 231 101#define ERRpipebusy 231
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 748b0df07a73..48d47b46b1fb 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -37,7 +37,7 @@ extern mempool_t *cifs_mid_poolp;
37extern kmem_cache_t *cifs_oplock_cachep; 37extern kmem_cache_t *cifs_oplock_cachep;
38 38
39static struct mid_q_entry * 39static struct mid_q_entry *
40AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) 40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
41{ 41{
42 struct mid_q_entry *temp; 42 struct mid_q_entry *temp;
43 43
@@ -204,6 +204,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
204 rc = 0; 204 rc = 0;
205 } 205 }
206 206
207 /* Don't want to modify the buffer as a
208 side effect of this call. */
209 smb_buffer->smb_buf_length = smb_buf_length;
210
207 return rc; 211 return rc;
208} 212}
209 213
@@ -218,6 +222,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
218 unsigned int len = iov[0].iov_len; 222 unsigned int len = iov[0].iov_len;
219 unsigned int total_len; 223 unsigned int total_len;
220 int first_vec = 0; 224 int first_vec = 0;
225 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
221 226
222 if(ssocket == NULL) 227 if(ssocket == NULL)
223 return -ENOTSOCK; /* BB eventually add reconnect code here */ 228 return -ENOTSOCK; /* BB eventually add reconnect code here */
@@ -294,36 +299,15 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
294 } else 299 } else
295 rc = 0; 300 rc = 0;
296 301
302 /* Don't want to modify the buffer as a
303 side effect of this call. */
304 smb_buffer->smb_buf_length = smb_buf_length;
305
297 return rc; 306 return rc;
298} 307}
299 308
300int 309static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
301SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
302 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
303 const int long_op)
304{ 310{
305 int rc = 0;
306 unsigned int receive_len;
307 unsigned long timeout;
308 struct mid_q_entry *midQ;
309 struct smb_hdr *in_buf = iov[0].iov_base;
310
311 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
312
313 if ((ses == NULL) || (ses->server == NULL)) {
314 cifs_small_buf_release(in_buf);
315 cERROR(1,("Null session"));
316 return -EIO;
317 }
318
319 if(ses->server->tcpStatus == CifsExiting) {
320 cifs_small_buf_release(in_buf);
321 return -ENOENT;
322 }
323
324 /* Ensure that we do not send more than 50 overlapping requests
325 to the same server. We may make this configurable later or
326 use ses->maxReq */
327 if(long_op == -1) { 311 if(long_op == -1) {
328 /* oplock breaks must not be held up */ 312 /* oplock breaks must not be held up */
329 atomic_inc(&ses->server->inFlight); 313 atomic_inc(&ses->server->inFlight);
@@ -346,53 +330,140 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
346 } else { 330 } else {
347 if(ses->server->tcpStatus == CifsExiting) { 331 if(ses->server->tcpStatus == CifsExiting) {
348 spin_unlock(&GlobalMid_Lock); 332 spin_unlock(&GlobalMid_Lock);
349 cifs_small_buf_release(in_buf);
350 return -ENOENT; 333 return -ENOENT;
351 } 334 }
352 335
353 /* can not count locking commands against total since 336 /* can not count locking commands against total since
354 they are allowed to block on server */ 337 they are allowed to block on server */
355 338
356 if(long_op < 3) {
357 /* update # of requests on the wire to server */ 339 /* update # of requests on the wire to server */
340 if (long_op < 3)
358 atomic_inc(&ses->server->inFlight); 341 atomic_inc(&ses->server->inFlight);
359 }
360 spin_unlock(&GlobalMid_Lock); 342 spin_unlock(&GlobalMid_Lock);
361 break; 343 break;
362 } 344 }
363 } 345 }
364 } 346 }
365 /* make sure that we sign in the same order that we send on this socket 347 return 0;
366 and avoid races inside tcp sendmsg code that could cause corruption 348}
367 of smb data */
368
369 down(&ses->server->tcpSem);
370 349
350static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
351 struct mid_q_entry **ppmidQ)
352{
371 if (ses->server->tcpStatus == CifsExiting) { 353 if (ses->server->tcpStatus == CifsExiting) {
372 rc = -ENOENT; 354 return -ENOENT;
373 goto out_unlock2;
374 } else if (ses->server->tcpStatus == CifsNeedReconnect) { 355 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
375 cFYI(1,("tcp session dead - return to caller to retry")); 356 cFYI(1,("tcp session dead - return to caller to retry"));
376 rc = -EAGAIN; 357 return -EAGAIN;
377 goto out_unlock2;
378 } else if (ses->status != CifsGood) { 358 } else if (ses->status != CifsGood) {
379 /* check if SMB session is bad because we are setting it up */ 359 /* check if SMB session is bad because we are setting it up */
380 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 360 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
381 (in_buf->Command != SMB_COM_NEGOTIATE)) { 361 (in_buf->Command != SMB_COM_NEGOTIATE)) {
382 rc = -EAGAIN; 362 return -EAGAIN;
383 goto out_unlock2;
384 } /* else ok - we are setting up session */ 363 } /* else ok - we are setting up session */
385 } 364 }
386 midQ = AllocMidQEntry(in_buf, ses); 365 *ppmidQ = AllocMidQEntry(in_buf, ses);
387 if (midQ == NULL) { 366 if (*ppmidQ == NULL) {
367 return -ENOMEM;
368 }
369 return 0;
370}
371
372static int wait_for_response(struct cifsSesInfo *ses,
373 struct mid_q_entry *midQ,
374 unsigned long timeout,
375 unsigned long time_to_wait)
376{
377 unsigned long curr_timeout;
378
379 for (;;) {
380 curr_timeout = timeout + jiffies;
381 wait_event(ses->server->response_q,
382 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
383 time_after(jiffies, curr_timeout) ||
384 ((ses->server->tcpStatus != CifsGood) &&
385 (ses->server->tcpStatus != CifsNew)));
386
387 if (time_after(jiffies, curr_timeout) &&
388 (midQ->midState == MID_REQUEST_SUBMITTED) &&
389 ((ses->server->tcpStatus == CifsGood) ||
390 (ses->server->tcpStatus == CifsNew))) {
391
392 unsigned long lrt;
393
394 /* We timed out. Is the server still
395 sending replies ? */
396 spin_lock(&GlobalMid_Lock);
397 lrt = ses->server->lstrp;
398 spin_unlock(&GlobalMid_Lock);
399
400 /* Calculate time_to_wait past last receive time.
401 Although we prefer not to time out if the
402 server is still responding - we will time
403 out if the server takes more than 15 (or 45
404 or 180) seconds to respond to this request
405 and has not responded to any request from
406 other threads on the client within 10 seconds */
407 lrt += time_to_wait;
408 if (time_after(jiffies, lrt)) {
409 /* No replies for time_to_wait. */
410 cERROR(1,("server not responding"));
411 return -1;
412 }
413 } else {
414 return 0;
415 }
416 }
417}
418
419int
420SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
421 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
422 const int long_op)
423{
424 int rc = 0;
425 unsigned int receive_len;
426 unsigned long timeout;
427 struct mid_q_entry *midQ;
428 struct smb_hdr *in_buf = iov[0].iov_base;
429
430 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
431
432 if ((ses == NULL) || (ses->server == NULL)) {
433 cifs_small_buf_release(in_buf);
434 cERROR(1,("Null session"));
435 return -EIO;
436 }
437
438 if(ses->server->tcpStatus == CifsExiting) {
439 cifs_small_buf_release(in_buf);
440 return -ENOENT;
441 }
442
443 /* Ensure that we do not send more than 50 overlapping requests
444 to the same server. We may make this configurable later or
445 use ses->maxReq */
446
447 rc = wait_for_free_request(ses, long_op);
448 if (rc) {
449 cifs_small_buf_release(in_buf);
450 return rc;
451 }
452
453 /* make sure that we sign in the same order that we send on this socket
454 and avoid races inside tcp sendmsg code that could cause corruption
455 of smb data */
456
457 down(&ses->server->tcpSem);
458
459 rc = allocate_mid(ses, in_buf, &midQ);
460 if (rc) {
388 up(&ses->server->tcpSem); 461 up(&ses->server->tcpSem);
389 cifs_small_buf_release(in_buf); 462 cifs_small_buf_release(in_buf);
390 /* If not lock req, update # of requests on wire to server */ 463 /* Update # of requests on wire to server */
391 if(long_op < 3) { 464 atomic_dec(&ses->server->inFlight);
392 atomic_dec(&ses->server->inFlight); 465 wake_up(&ses->server->request_q);
393 wake_up(&ses->server->request_q); 466 return rc;
394 }
395 return -ENOMEM;
396 } 467 }
397 468
398 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); 469 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
@@ -407,32 +478,23 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
407 atomic_dec(&ses->server->inSend); 478 atomic_dec(&ses->server->inSend);
408 midQ->when_sent = jiffies; 479 midQ->when_sent = jiffies;
409#endif 480#endif
410 if(rc < 0) { 481
411 DeleteMidQEntry(midQ); 482 up(&ses->server->tcpSem);
412 up(&ses->server->tcpSem); 483 cifs_small_buf_release(in_buf);
413 cifs_small_buf_release(in_buf); 484
414 /* If not lock req, update # of requests on wire to server */ 485 if(rc < 0)
415 if(long_op < 3) { 486 goto out;
416 atomic_dec(&ses->server->inFlight);
417 wake_up(&ses->server->request_q);
418 }
419 return rc;
420 } else {
421 up(&ses->server->tcpSem);
422 cifs_small_buf_release(in_buf);
423 }
424 487
425 if (long_op == -1) 488 if (long_op == -1)
426 goto cifs_no_response_exit2; 489 goto out;
427 else if (long_op == 2) /* writes past end of file can take loong time */ 490 else if (long_op == 2) /* writes past end of file can take loong time */
428 timeout = 180 * HZ; 491 timeout = 180 * HZ;
429 else if (long_op == 1) 492 else if (long_op == 1)
430 timeout = 45 * HZ; /* should be greater than 493 timeout = 45 * HZ; /* should be greater than
431 servers oplock break timeout (about 43 seconds) */ 494 servers oplock break timeout (about 43 seconds) */
432 else if (long_op > 2) { 495 else
433 timeout = MAX_SCHEDULE_TIMEOUT;
434 } else
435 timeout = 15 * HZ; 496 timeout = 15 * HZ;
497
436 /* wait for 15 seconds or until woken up due to response arriving or 498 /* wait for 15 seconds or until woken up due to response arriving or
437 due to last connection to this server being unmounted */ 499 due to last connection to this server being unmounted */
438 if (signal_pending(current)) { 500 if (signal_pending(current)) {
@@ -442,53 +504,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
442 } 504 }
443 505
444 /* No user interrupts in wait - wreaks havoc with performance */ 506 /* No user interrupts in wait - wreaks havoc with performance */
445 if(timeout != MAX_SCHEDULE_TIMEOUT) { 507 wait_for_response(ses, midQ, timeout, 10 * HZ);
446 unsigned long curr_timeout;
447
448 for (;;) {
449 curr_timeout = timeout + jiffies;
450 wait_event(ses->server->response_q,
451 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
452 time_after(jiffies, curr_timeout) ||
453 ((ses->server->tcpStatus != CifsGood) &&
454 (ses->server->tcpStatus != CifsNew)));
455
456 if (time_after(jiffies, curr_timeout) &&
457 (midQ->midState == MID_REQUEST_SUBMITTED) &&
458 ((ses->server->tcpStatus == CifsGood) ||
459 (ses->server->tcpStatus == CifsNew))) {
460
461 unsigned long lrt;
462
463 /* We timed out. Is the server still
464 sending replies ? */
465 spin_lock(&GlobalMid_Lock);
466 lrt = ses->server->lstrp;
467 spin_unlock(&GlobalMid_Lock);
468
469 /* Calculate 10 seconds past last receive time.
470 Although we prefer not to time out if the
471 server is still responding - we will time
472 out if the server takes more than 15 (or 45
473 or 180) seconds to respond to this request
474 and has not responded to any request from
475 other threads on the client within 10 seconds */
476 lrt += (10 * HZ);
477 if (time_after(jiffies, lrt)) {
478 /* No replies for 10 seconds. */
479 cERROR(1,("server not responding"));
480 break;
481 }
482 } else {
483 break;
484 }
485 }
486 } else {
487 wait_event(ses->server->response_q,
488 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
489 ((ses->server->tcpStatus != CifsGood) &&
490 (ses->server->tcpStatus != CifsNew)));
491 }
492 508
493 spin_lock(&GlobalMid_Lock); 509 spin_lock(&GlobalMid_Lock);
494 if (midQ->resp_buf) { 510 if (midQ->resp_buf) {
@@ -516,11 +532,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
516 } 532 }
517 spin_unlock(&GlobalMid_Lock); 533 spin_unlock(&GlobalMid_Lock);
518 DeleteMidQEntry(midQ); 534 DeleteMidQEntry(midQ);
519 /* If not lock req, update # of requests on wire to server */ 535 /* Update # of requests on wire to server */
520 if(long_op < 3) { 536 atomic_dec(&ses->server->inFlight);
521 atomic_dec(&ses->server->inFlight); 537 wake_up(&ses->server->request_q);
522 wake_up(&ses->server->request_q);
523 }
524 return rc; 538 return rc;
525 } 539 }
526 540
@@ -571,24 +585,12 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
571 cFYI(1,("Bad MID state?")); 585 cFYI(1,("Bad MID state?"));
572 } 586 }
573 } 587 }
574cifs_no_response_exit2:
575 DeleteMidQEntry(midQ);
576
577 if(long_op < 3) {
578 atomic_dec(&ses->server->inFlight);
579 wake_up(&ses->server->request_q);
580 }
581 588
582 return rc; 589out:
583 590
584out_unlock2: 591 DeleteMidQEntry(midQ);
585 up(&ses->server->tcpSem); 592 atomic_dec(&ses->server->inFlight);
586 cifs_small_buf_release(in_buf); 593 wake_up(&ses->server->request_q);
587 /* If not lock req, update # of requests on wire to server */
588 if(long_op < 3) {
589 atomic_dec(&ses->server->inFlight);
590 wake_up(&ses->server->request_q);
591 }
592 594
593 return rc; 595 return rc;
594} 596}
@@ -618,85 +620,34 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
618 /* Ensure that we do not send more than 50 overlapping requests 620 /* Ensure that we do not send more than 50 overlapping requests
619 to the same server. We may make this configurable later or 621 to the same server. We may make this configurable later or
620 use ses->maxReq */ 622 use ses->maxReq */
621 if(long_op == -1) {
622 /* oplock breaks must not be held up */
623 atomic_inc(&ses->server->inFlight);
624 } else {
625 spin_lock(&GlobalMid_Lock);
626 while(1) {
627 if(atomic_read(&ses->server->inFlight) >=
628 cifs_max_pending){
629 spin_unlock(&GlobalMid_Lock);
630#ifdef CONFIG_CIFS_STATS2
631 atomic_inc(&ses->server->num_waiters);
632#endif
633 wait_event(ses->server->request_q,
634 atomic_read(&ses->server->inFlight)
635 < cifs_max_pending);
636#ifdef CONFIG_CIFS_STATS2
637 atomic_dec(&ses->server->num_waiters);
638#endif
639 spin_lock(&GlobalMid_Lock);
640 } else {
641 if(ses->server->tcpStatus == CifsExiting) {
642 spin_unlock(&GlobalMid_Lock);
643 return -ENOENT;
644 }
645 623
646 /* can not count locking commands against total since 624 rc = wait_for_free_request(ses, long_op);
647 they are allowed to block on server */ 625 if (rc)
648 626 return rc;
649 if(long_op < 3) { 627
650 /* update # of requests on the wire to server */
651 atomic_inc(&ses->server->inFlight);
652 }
653 spin_unlock(&GlobalMid_Lock);
654 break;
655 }
656 }
657 }
658 /* make sure that we sign in the same order that we send on this socket 628 /* make sure that we sign in the same order that we send on this socket
659 and avoid races inside tcp sendmsg code that could cause corruption 629 and avoid races inside tcp sendmsg code that could cause corruption
660 of smb data */ 630 of smb data */
661 631
662 down(&ses->server->tcpSem); 632 down(&ses->server->tcpSem);
663 633
664 if (ses->server->tcpStatus == CifsExiting) { 634 rc = allocate_mid(ses, in_buf, &midQ);
665 rc = -ENOENT; 635 if (rc) {
666 goto out_unlock;
667 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
668 cFYI(1,("tcp session dead - return to caller to retry"));
669 rc = -EAGAIN;
670 goto out_unlock;
671 } else if (ses->status != CifsGood) {
672 /* check if SMB session is bad because we are setting it up */
673 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
674 (in_buf->Command != SMB_COM_NEGOTIATE)) {
675 rc = -EAGAIN;
676 goto out_unlock;
677 } /* else ok - we are setting up session */
678 }
679 midQ = AllocMidQEntry(in_buf, ses);
680 if (midQ == NULL) {
681 up(&ses->server->tcpSem); 636 up(&ses->server->tcpSem);
682 /* If not lock req, update # of requests on wire to server */ 637 /* Update # of requests on wire to server */
683 if(long_op < 3) { 638 atomic_dec(&ses->server->inFlight);
684 atomic_dec(&ses->server->inFlight); 639 wake_up(&ses->server->request_q);
685 wake_up(&ses->server->request_q); 640 return rc;
686 }
687 return -ENOMEM;
688 } 641 }
689 642
690 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 643 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
691 up(&ses->server->tcpSem);
692 cERROR(1, ("Illegal length, greater than maximum frame, %d", 644 cERROR(1, ("Illegal length, greater than maximum frame, %d",
693 in_buf->smb_buf_length)); 645 in_buf->smb_buf_length));
694 DeleteMidQEntry(midQ); 646 DeleteMidQEntry(midQ);
695 /* If not lock req, update # of requests on wire to server */ 647 up(&ses->server->tcpSem);
696 if(long_op < 3) { 648 /* Update # of requests on wire to server */
697 atomic_dec(&ses->server->inFlight); 649 atomic_dec(&ses->server->inFlight);
698 wake_up(&ses->server->request_q); 650 wake_up(&ses->server->request_q);
699 }
700 return -EIO; 651 return -EIO;
701 } 652 }
702 653
@@ -712,27 +663,19 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
712 atomic_dec(&ses->server->inSend); 663 atomic_dec(&ses->server->inSend);
713 midQ->when_sent = jiffies; 664 midQ->when_sent = jiffies;
714#endif 665#endif
715 if(rc < 0) { 666 up(&ses->server->tcpSem);
716 DeleteMidQEntry(midQ); 667
717 up(&ses->server->tcpSem); 668 if(rc < 0)
718 /* If not lock req, update # of requests on wire to server */ 669 goto out;
719 if(long_op < 3) { 670
720 atomic_dec(&ses->server->inFlight);
721 wake_up(&ses->server->request_q);
722 }
723 return rc;
724 } else
725 up(&ses->server->tcpSem);
726 if (long_op == -1) 671 if (long_op == -1)
727 goto cifs_no_response_exit; 672 goto out;
728 else if (long_op == 2) /* writes past end of file can take loong time */ 673 else if (long_op == 2) /* writes past end of file can take loong time */
729 timeout = 180 * HZ; 674 timeout = 180 * HZ;
730 else if (long_op == 1) 675 else if (long_op == 1)
731 timeout = 45 * HZ; /* should be greater than 676 timeout = 45 * HZ; /* should be greater than
732 servers oplock break timeout (about 43 seconds) */ 677 servers oplock break timeout (about 43 seconds) */
733 else if (long_op > 2) { 678 else
734 timeout = MAX_SCHEDULE_TIMEOUT;
735 } else
736 timeout = 15 * HZ; 679 timeout = 15 * HZ;
737 /* wait for 15 seconds or until woken up due to response arriving or 680 /* wait for 15 seconds or until woken up due to response arriving or
738 due to last connection to this server being unmounted */ 681 due to last connection to this server being unmounted */
@@ -743,47 +686,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
743 } 686 }
744 687
745 /* No user interrupts in wait - wreaks havoc with performance */ 688 /* No user interrupts in wait - wreaks havoc with performance */
746 if(timeout != MAX_SCHEDULE_TIMEOUT) { 689 wait_for_response(ses, midQ, timeout, 10 * HZ);
747 unsigned long curr_timeout;
748
749 for (;;) {
750 curr_timeout = timeout + jiffies;
751 wait_event(ses->server->response_q,
752 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
753 time_after(jiffies, curr_timeout) ||
754 ((ses->server->tcpStatus != CifsGood) &&
755 (ses->server->tcpStatus != CifsNew)));
756
757 if (time_after(jiffies, curr_timeout) &&
758 (midQ->midState == MID_REQUEST_SUBMITTED) &&
759 ((ses->server->tcpStatus == CifsGood) ||
760 (ses->server->tcpStatus == CifsNew))) {
761
762 unsigned long lrt;
763
764 /* We timed out. Is the server still
765 sending replies ? */
766 spin_lock(&GlobalMid_Lock);
767 lrt = ses->server->lstrp;
768 spin_unlock(&GlobalMid_Lock);
769
770 /* Calculate 10 seconds past last receive time*/
771 lrt += (10 * HZ);
772 if (time_after(jiffies, lrt)) {
773 /* Server sent no reply in 10 seconds */
774 cERROR(1,("Server not responding"));
775 break;
776 }
777 } else {
778 break;
779 }
780 }
781 } else {
782 wait_event(ses->server->response_q,
783 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
784 ((ses->server->tcpStatus != CifsGood) &&
785 (ses->server->tcpStatus != CifsNew)));
786 }
787 690
788 spin_lock(&GlobalMid_Lock); 691 spin_lock(&GlobalMid_Lock);
789 if (midQ->resp_buf) { 692 if (midQ->resp_buf) {
@@ -811,11 +714,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
811 } 714 }
812 spin_unlock(&GlobalMid_Lock); 715 spin_unlock(&GlobalMid_Lock);
813 DeleteMidQEntry(midQ); 716 DeleteMidQEntry(midQ);
814 /* If not lock req, update # of requests on wire to server */ 717 /* Update # of requests on wire to server */
815 if(long_op < 3) { 718 atomic_dec(&ses->server->inFlight);
816 atomic_dec(&ses->server->inFlight); 719 wake_up(&ses->server->request_q);
817 wake_up(&ses->server->request_q);
818 }
819 return rc; 720 return rc;
820 } 721 }
821 722
@@ -862,23 +763,253 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
862 cERROR(1,("Bad MID state?")); 763 cERROR(1,("Bad MID state?"));
863 } 764 }
864 } 765 }
865cifs_no_response_exit: 766
767out:
768
866 DeleteMidQEntry(midQ); 769 DeleteMidQEntry(midQ);
770 atomic_dec(&ses->server->inFlight);
771 wake_up(&ses->server->request_q);
867 772
868 if(long_op < 3) { 773 return rc;
869 atomic_dec(&ses->server->inFlight); 774}
870 wake_up(&ses->server->request_q);
871 }
872 775
776/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
777
778static int
779send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
780 struct mid_q_entry *midQ)
781{
782 int rc = 0;
783 struct cifsSesInfo *ses = tcon->ses;
784 __u16 mid = in_buf->Mid;
785
786 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
787 in_buf->Mid = mid;
788 down(&ses->server->tcpSem);
789 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
790 if (rc) {
791 up(&ses->server->tcpSem);
792 return rc;
793 }
794 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
795 (struct sockaddr *) &(ses->server->addr.sockAddr));
796 up(&ses->server->tcpSem);
873 return rc; 797 return rc;
798}
799
800/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
801 blocking lock to return. */
802
803static int
804send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
805 struct smb_hdr *in_buf,
806 struct smb_hdr *out_buf)
807{
808 int bytes_returned;
809 struct cifsSesInfo *ses = tcon->ses;
810 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
811
812 /* We just modify the current in_buf to change
813 the type of lock from LOCKING_ANDX_SHARED_LOCK
814 or LOCKING_ANDX_EXCLUSIVE_LOCK to
815 LOCKING_ANDX_CANCEL_LOCK. */
816
817 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
818 pSMB->Timeout = 0;
819 pSMB->hdr.Mid = GetNextMid(ses->server);
820
821 return SendReceive(xid, ses, in_buf, out_buf,
822 &bytes_returned, 0);
823}
824
825int
826SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
827 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
828 int *pbytes_returned)
829{
830 int rc = 0;
831 int rstart = 0;
832 unsigned int receive_len;
833 struct mid_q_entry *midQ;
834 struct cifsSesInfo *ses;
835
836 if (tcon == NULL || tcon->ses == NULL) {
837 cERROR(1,("Null smb session"));
838 return -EIO;
839 }
840 ses = tcon->ses;
841
842 if(ses->server == NULL) {
843 cERROR(1,("Null tcp session"));
844 return -EIO;
845 }
846
847 if(ses->server->tcpStatus == CifsExiting)
848 return -ENOENT;
849
850 /* Ensure that we do not send more than 50 overlapping requests
851 to the same server. We may make this configurable later or
852 use ses->maxReq */
853
854 rc = wait_for_free_request(ses, 3);
855 if (rc)
856 return rc;
857
858 /* make sure that we sign in the same order that we send on this socket
859 and avoid races inside tcp sendmsg code that could cause corruption
860 of smb data */
861
862 down(&ses->server->tcpSem);
863
864 rc = allocate_mid(ses, in_buf, &midQ);
865 if (rc) {
866 up(&ses->server->tcpSem);
867 return rc;
868 }
869
870 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
871 up(&ses->server->tcpSem);
872 cERROR(1, ("Illegal length, greater than maximum frame, %d",
873 in_buf->smb_buf_length));
874 DeleteMidQEntry(midQ);
875 return -EIO;
876 }
877
878 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
874 879
875out_unlock: 880 midQ->midState = MID_REQUEST_SUBMITTED;
881#ifdef CONFIG_CIFS_STATS2
882 atomic_inc(&ses->server->inSend);
883#endif
884 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
885 (struct sockaddr *) &(ses->server->addr.sockAddr));
886#ifdef CONFIG_CIFS_STATS2
887 atomic_dec(&ses->server->inSend);
888 midQ->when_sent = jiffies;
889#endif
876 up(&ses->server->tcpSem); 890 up(&ses->server->tcpSem);
877 /* If not lock req, update # of requests on wire to server */ 891
878 if(long_op < 3) { 892 if(rc < 0) {
879 atomic_dec(&ses->server->inFlight); 893 DeleteMidQEntry(midQ);
880 wake_up(&ses->server->request_q); 894 return rc;
895 }
896
897 /* Wait for a reply - allow signals to interrupt. */
898 rc = wait_event_interruptible(ses->server->response_q,
899 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
900 ((ses->server->tcpStatus != CifsGood) &&
901 (ses->server->tcpStatus != CifsNew)));
902
903 /* Were we interrupted by a signal ? */
904 if ((rc == -ERESTARTSYS) &&
905 (midQ->midState == MID_REQUEST_SUBMITTED) &&
906 ((ses->server->tcpStatus == CifsGood) ||
907 (ses->server->tcpStatus == CifsNew))) {
908
909 if (in_buf->Command == SMB_COM_TRANSACTION2) {
910 /* POSIX lock. We send a NT_CANCEL SMB to cause the
911 blocking lock to return. */
912
913 rc = send_nt_cancel(tcon, in_buf, midQ);
914 if (rc) {
915 DeleteMidQEntry(midQ);
916 return rc;
917 }
918 } else {
919 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
920 to cause the blocking lock to return. */
921
922 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
923
924 /* If we get -ENOLCK back the lock may have
925 already been removed. Don't exit in this case. */
926 if (rc && rc != -ENOLCK) {
927 DeleteMidQEntry(midQ);
928 return rc;
929 }
930 }
931
932 /* Wait 5 seconds for the response. */
933 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ)==0) {
934 /* We got the response - restart system call. */
935 rstart = 1;
936 }
937 }
938
939 spin_lock(&GlobalMid_Lock);
940 if (midQ->resp_buf) {
941 spin_unlock(&GlobalMid_Lock);
942 receive_len = midQ->resp_buf->smb_buf_length;
943 } else {
944 cERROR(1,("No response for cmd %d mid %d",
945 midQ->command, midQ->mid));
946 if(midQ->midState == MID_REQUEST_SUBMITTED) {
947 if(ses->server->tcpStatus == CifsExiting)
948 rc = -EHOSTDOWN;
949 else {
950 ses->server->tcpStatus = CifsNeedReconnect;
951 midQ->midState = MID_RETRY_NEEDED;
952 }
953 }
954
955 if (rc != -EHOSTDOWN) {
956 if(midQ->midState == MID_RETRY_NEEDED) {
957 rc = -EAGAIN;
958 cFYI(1,("marking request for retry"));
959 } else {
960 rc = -EIO;
961 }
962 }
963 spin_unlock(&GlobalMid_Lock);
964 DeleteMidQEntry(midQ);
965 return rc;
881 } 966 }
967
968 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
969 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
970 receive_len, xid));
971 rc = -EIO;
972 } else { /* rcvd frame is ok */
973
974 if (midQ->resp_buf && out_buf
975 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
976 out_buf->smb_buf_length = receive_len;
977 memcpy((char *)out_buf + 4,
978 (char *)midQ->resp_buf + 4,
979 receive_len);
980
981 dump_smb(out_buf, 92);
982 /* convert the length into a more usable form */
983 if((receive_len > 24) &&
984 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
985 SECMODE_SIGN_ENABLED))) {
986 rc = cifs_verify_signature(out_buf,
987 ses->server->mac_signing_key,
988 midQ->sequence_number+1);
989 if(rc) {
990 cERROR(1,("Unexpected SMB signature"));
991 /* BB FIXME add code to kill session */
992 }
993 }
994
995 *pbytes_returned = out_buf->smb_buf_length;
996
997 /* BB special case reconnect tid and uid here? */
998 rc = map_smb_to_linux_error(out_buf);
882 999
1000 /* convert ByteCount if necessary */
1001 if (receive_len >=
1002 sizeof (struct smb_hdr) -
1003 4 /* do not count RFC1001 header */ +
1004 (2 * out_buf->WordCount) + 2 /* bcc */ )
1005 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1006 } else {
1007 rc = -EIO;
1008 cERROR(1,("Bad MID state?"));
1009 }
1010 }
1011 DeleteMidQEntry(midQ);
1012 if (rstart && rc == -EACCES)
1013 return -ERESTARTSYS;
883 return rc; 1014 return rc;
884} 1015}