[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)

authored by Jeremy Allison and committed by Steve French 7ee1af76 6c3d8909

+523 -307
+9 -6
fs/cifs/cifsglob.h
··· 3 * 4 * Copyright (C) International Business Machines Corp., 2002,2006 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 * 7 * 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 ··· 268 }; 269 270 /* 271 - * This info hangs off the cifsFileInfo structure. This is used to track 272 - * byte stream locks on the file 273 */ 274 struct cifsLockInfo { 275 - struct cifsLockInfo *next; 276 - int start; 277 - int length; 278 - int type; 279 }; 280 281 /* ··· 306 /* lock scope id (0 if none) */ 307 struct file * pfile; /* needed for writepage */ 308 struct inode * pInode; /* needed for oplock break */ 309 unsigned closePend:1; /* file is marked to close */ 310 unsigned invalidHandle:1; /* file closed via session abend */ 311 atomic_t wrtPending; /* handle in use - defer close */
··· 3 * 4 * Copyright (C) International Business Machines Corp., 2002,2006 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 + * Jeremy Allison (jra@samba.org) 7 * 8 * This library is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published ··· 267 }; 268 269 /* 270 + * This info hangs off the cifsFileInfo structure, pointed to by llist. 271 + * This is used to track byte stream locks on the file 272 */ 273 struct cifsLockInfo { 274 + struct list_head llist; /* pointer to next cifsLockInfo */ 275 + __u64 offset; 276 + __u64 length; 277 + __u8 type; 278 }; 279 280 /* ··· 305 /* lock scope id (0 if none) */ 306 struct file * pfile; /* needed for writepage */ 307 struct inode * pInode; /* needed for oplock break */ 308 + struct semaphore lock_sem; 309 + struct list_head llist; /* list of byte range locks we have. */ 310 unsigned closePend:1; /* file is marked to close */ 311 unsigned invalidHandle:1; /* file closed via session abend */ 312 atomic_t wrtPending; /* handle in use - defer close */
+4
fs/cifs/cifsproto.h
··· 50 extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, 51 struct kvec *, int /* nvec to send */, 52 int * /* type of buf returned */ , const int long_op); 53 extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); 54 extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); 55 extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
··· 50 extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, 51 struct kvec *, int /* nvec to send */, 52 int * /* type of buf returned */ , const int long_op); 53 + extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *, 54 + struct smb_hdr * /* input */ , 55 + struct smb_hdr * /* out */ , 56 + int * /* bytes returned */); 57 extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); 58 extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); 59 extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
+13 -2
fs/cifs/cifssmb.c
··· 1460 pSMB->hdr.smb_buf_length += count; 1461 pSMB->ByteCount = cpu_to_le16(count); 1462 1463 - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1464 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1465 cifs_stats_inc(&tcon->num_locks); 1466 if (rc) { 1467 cFYI(1, ("Send error in Lock = %d", rc)); ··· 1551 pSMB->Reserved4 = 0; 1552 pSMB->hdr.smb_buf_length += byte_count; 1553 pSMB->ByteCount = cpu_to_le16(byte_count); 1554 - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1555 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1556 if (rc) { 1557 cFYI(1, ("Send error in Posix Lock = %d", rc)); 1558 } else if (get_flag) {
··· 1460 pSMB->hdr.smb_buf_length += count; 1461 pSMB->ByteCount = cpu_to_le16(count); 1462 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, 1468 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1469 + } 1470 cifs_stats_inc(&tcon->num_locks); 1471 if (rc) { 1472 cFYI(1, ("Send error in Lock = %d", rc)); ··· 1546 pSMB->Reserved4 = 0; 1547 pSMB->hdr.smb_buf_length += byte_count; 1548 pSMB->ByteCount = cpu_to_le16(byte_count); 1549 + if (waitFlag) { 1550 + rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, 1551 + (struct smb_hdr *) pSMBr, &bytes_returned); 1552 + } else { 1553 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1554 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1555 + } 1556 + 1557 if (rc) { 1558 cFYI(1, ("Send error in Posix Lock = %d", rc)); 1559 } else if (get_flag) {
+80 -15
fs/cifs/file.c
··· 5 * 6 * Copyright (C) International Business Machines Corp., 2002,2003 7 * Author(s): Steve French (sfrench@us.ibm.com) 8 * 9 * 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 ··· 48 private_data->netfid = netfid; 49 private_data->pid = current->tgid; 50 init_MUTEX(&private_data->fh_sem); 51 private_data->pfile = file; /* needed for writepage */ 52 private_data->pInode = inode; 53 private_data->invalidHandle = FALSE; ··· 476 cifs_sb = CIFS_SB(inode->i_sb); 477 pTcon = cifs_sb->tcon; 478 if (pSMBFile) { 479 pSMBFile->closePend = TRUE; 480 if (pTcon) { 481 /* no sense reconnecting to close a file that is ··· 501 pSMBFile->netfid); 502 } 503 } 504 write_lock(&GlobalSMBSeslock); 505 list_del(&pSMBFile->flist); 506 list_del(&pSMBFile->tlist); ··· 585 return rc; 586 } 587 588 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 589 { 590 int rc, xid; ··· 611 struct cifsTconInfo *pTcon; 612 __u16 netfid; 613 __u8 lockType = LOCKING_ANDX_LARGE_FILES; 614 615 length = 1 + pfLock->fl_end - pfLock->fl_start; 616 rc = -EACCES; ··· 670 } 671 netfid = ((struct cifsFileInfo *)file->private_data)->netfid; 672 673 674 /* BB add code here to normalize offset and length to 675 account for negative length which we can not accept over the 676 wire */ 677 if (IS_GETLK(cmd)) { 678 - if((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && 679 - (CIFS_UNIX_FCNTL_CAP & 680 - le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { 681 int posix_lock_type; 682 if(lockType & LOCKING_ANDX_SHARED_LOCK) 683 posix_lock_type = CIFS_RDLCK; ··· 713 FreeXid(xid); 714 return rc; 715 } 716 - if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && 717 - (CIFS_UNIX_FCNTL_CAP & 718 - le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { 719 int posix_lock_type; 720 if(lockType & LOCKING_ANDX_SHARED_LOCK) 721 posix_lock_type = CIFS_RDLCK; ··· 730 731 if(numUnlock == 1) 732 posix_lock_type = CIFS_UNLCK; 733 - else if(numLock == 0) { 734 - /* if no lock or unlock then nothing 735 - to do since we do not know what it is */ 736 - FreeXid(xid); 737 - return -EOPNOTSUPP; 738 - } 739 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, 740 length, pfLock, 741 posix_lock_type, wait_flag); 742 - } else 743 - rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, 744 - numUnlock, numLock, lockType, wait_flag); 745 if (pfLock->fl_flags & FL_POSIX) 746 posix_lock_file_wait(file, pfLock); 747 FreeXid(xid);
··· 5 * 6 * Copyright (C) International Business Machines Corp., 2002,2003 7 * Author(s): Steve French (sfrench@us.ibm.com) 8 + * Jeremy Allison (jra@samba.org) 9 * 10 * This library is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU Lesser General Public License as published ··· 47 private_data->netfid = netfid; 48 private_data->pid = current->tgid; 49 init_MUTEX(&private_data->fh_sem); 50 + init_MUTEX(&private_data->lock_sem); 51 + INIT_LIST_HEAD(&private_data->llist); 52 private_data->pfile = file; /* needed for writepage */ 53 private_data->pInode = inode; 54 private_data->invalidHandle = FALSE; ··· 473 cifs_sb = CIFS_SB(inode->i_sb); 474 pTcon = cifs_sb->tcon; 475 if (pSMBFile) { 476 + struct cifsLockInfo *li, *tmp; 477 + 478 pSMBFile->closePend = TRUE; 479 if (pTcon) { 480 /* no sense reconnecting to close a file that is ··· 496 pSMBFile->netfid); 497 } 498 } 499 + 500 + /* Delete any outstanding lock records. 501 + We'll lose them when the file is closed anyway. */ 502 + down(&pSMBFile->lock_sem); 503 + list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) { 504 + list_del(&li->llist); 505 + kfree(li); 506 + } 507 + up(&pSMBFile->lock_sem); 508 + 509 write_lock(&GlobalSMBSeslock); 510 list_del(&pSMBFile->flist); 511 list_del(&pSMBFile->tlist); ··· 570 return rc; 571 } 572 573 + static int store_file_lock(struct cifsFileInfo *fid, __u64 len, 574 + __u64 offset, __u8 lockType) 575 + { 576 + struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); 577 + if (li == NULL) 578 + return -ENOMEM; 579 + li->offset = offset; 580 + li->length = len; 581 + li->type = lockType; 582 + down(&fid->lock_sem); 583 + list_add(&li->llist, &fid->llist); 584 + up(&fid->lock_sem); 585 + return 0; 586 + } 587 + 588 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 589 { 590 int rc, xid; ··· 581 struct cifsTconInfo *pTcon; 582 __u16 netfid; 583 __u8 lockType = LOCKING_ANDX_LARGE_FILES; 584 + int posix_locking; 585 586 length = 1 + pfLock->fl_end - pfLock->fl_start; 587 rc = -EACCES; ··· 639 } 640 netfid = ((struct cifsFileInfo *)file->private_data)->netfid; 641 642 + posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && 643 + (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability)); 644 645 /* BB add code here to normalize offset and length to 646 account for negative length which we can not accept over the 647 wire */ 648 if (IS_GETLK(cmd)) { 649 + if(posix_locking) { 650 int posix_lock_type; 651 if(lockType & LOCKING_ANDX_SHARED_LOCK) 652 posix_lock_type = CIFS_RDLCK; ··· 682 FreeXid(xid); 683 return rc; 684 } 685 + 686 + if (!numLock && !numUnlock) { 687 + /* if no lock or unlock then nothing 688 + to do since we do not know what it is */ 689 + FreeXid(xid); 690 + return -EOPNOTSUPP; 691 + } 692 + 693 + if (posix_locking) { 694 int posix_lock_type; 695 if(lockType & LOCKING_ANDX_SHARED_LOCK) 696 posix_lock_type = CIFS_RDLCK; ··· 693 694 if(numUnlock == 1) 695 posix_lock_type = CIFS_UNLCK; 696 + 697 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, 698 length, pfLock, 699 posix_lock_type, wait_flag); 700 + } else { 701 + struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data; 702 + 703 + if (numLock) { 704 + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, 705 + 0, numLock, lockType, wait_flag); 706 + 707 + if (rc == 0) { 708 + /* For Windows locks we must store them. */ 709 + rc = store_file_lock(fid, length, 710 + pfLock->fl_start, lockType); 711 + } 712 + } else if (numUnlock) { 713 + /* For each stored lock that this unlock overlaps 714 + completely, unlock it. */ 715 + int stored_rc = 0; 716 + struct cifsLockInfo *li, *tmp; 717 + 718 + down(&fid->lock_sem); 719 + list_for_each_entry_safe(li, tmp, &fid->llist, llist) { 720 + if (pfLock->fl_start <= li->offset && 721 + length >= li->length) { 722 + stored_rc = CIFSSMBLock(xid, pTcon, netfid, 723 + li->length, li->offset, 724 + 1, 0, li->type, FALSE); 725 + if (stored_rc) 726 + rc = stored_rc; 727 + 728 + list_del(&li->llist); 729 + kfree(li); 730 + } 731 + } 732 + up(&fid->lock_sem); 733 + } 734 + } 735 + 736 if (pfLock->fl_flags & FL_POSIX) 737 posix_lock_file_wait(file, pfLock); 738 FreeXid(xid);
+1
fs/cifs/netmisc.c
··· 72 {ERRinvlevel,-EOPNOTSUPP}, 73 {ERRdirnotempty, -ENOTEMPTY}, 74 {ERRnotlocked, -ENOLCK}, 75 {ERRalreadyexists, -EEXIST}, 76 {ERRmoredata, -EOVERFLOW}, 77 {ERReasnotsupported,-EOPNOTSUPP},
··· 72 {ERRinvlevel,-EOPNOTSUPP}, 73 {ERRdirnotempty, -ENOTEMPTY}, 74 {ERRnotlocked, -ENOLCK}, 75 + {ERRcancelviolation, -ENOLCK}, 76 {ERRalreadyexists, -EEXIST}, 77 {ERRmoredata, -EOVERFLOW}, 78 {ERReasnotsupported,-EOPNOTSUPP},
+1
fs/cifs/smberr.h
··· 95 #define ERRinvlevel 124 96 #define ERRdirnotempty 145 97 #define ERRnotlocked 158 98 #define ERRalreadyexists 183 99 #define ERRbadpipe 230 100 #define ERRpipebusy 231
··· 95 #define ERRinvlevel 124 96 #define ERRdirnotempty 145 97 #define ERRnotlocked 158 98 + #define ERRcancelviolation 173 99 #define ERRalreadyexists 183 100 #define ERRbadpipe 230 101 #define ERRpipebusy 231
+415 -284
fs/cifs/transport.c
··· 37 extern kmem_cache_t *cifs_oplock_cachep; 38 39 static struct mid_q_entry * 40 - AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) 41 { 42 struct mid_q_entry *temp; 43 ··· 204 rc = 0; 205 } 206 207 return rc; 208 } 209 ··· 222 unsigned int len = iov[0].iov_len; 223 unsigned int total_len; 224 int first_vec = 0; 225 226 if(ssocket == NULL) 227 return -ENOTSOCK; /* BB eventually add reconnect code here */ ··· 299 } else 300 rc = 0; 301 302 return rc; 303 } 304 305 int ··· 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 - if(long_op == -1) { 447 - /* oplock breaks must not be held up */ 448 - atomic_inc(&ses->server->inFlight); 449 - } else { 450 - spin_lock(&GlobalMid_Lock); 451 - while(1) { 452 - if(atomic_read(&ses->server->inFlight) >= 453 - cifs_max_pending){ 454 - spin_unlock(&GlobalMid_Lock); 455 - #ifdef CONFIG_CIFS_STATS2 456 - atomic_inc(&ses->server->num_waiters); 457 - #endif 458 - wait_event(ses->server->request_q, 459 - atomic_read(&ses->server->inFlight) 460 - < cifs_max_pending); 461 - #ifdef CONFIG_CIFS_STATS2 462 - atomic_dec(&ses->server->num_waiters); 463 - #endif 464 - spin_lock(&GlobalMid_Lock); 465 - } else { 466 - if(ses->server->tcpStatus == CifsExiting) { 467 - spin_unlock(&GlobalMid_Lock); 468 - cifs_small_buf_release(in_buf); 469 - return -ENOENT; 470 - } 471 472 - /* can not count locking commands against total since 473 - they are allowed to block on server */ 474 - 475 - if(long_op < 3) { 476 - /* update # of requests on the wire to server */ 477 - atomic_inc(&ses->server->inFlight); 478 - } 479 - spin_unlock(&GlobalMid_Lock); 480 - break; 481 - } 482 - } 483 } 484 /* make sure that we sign in the same order that we send on this socket 485 and avoid races inside tcp sendmsg code that could cause corruption 486 of smb data */ 487 488 down(&ses->server->tcpSem); 489 490 - if (ses->server->tcpStatus == CifsExiting) { 491 - rc = -ENOENT; 492 - goto out_unlock2; 493 - } else if (ses->server->tcpStatus == CifsNeedReconnect) { 494 - cFYI(1,("tcp session dead - return to caller to retry")); 495 - rc = -EAGAIN; 496 - goto out_unlock2; 497 - } else if (ses->status != CifsGood) { 498 - /* check if SMB session is bad because we are setting it up */ 499 - if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 500 - (in_buf->Command != SMB_COM_NEGOTIATE)) { 501 - rc = -EAGAIN; 502 - goto out_unlock2; 503 - } /* else ok - we are setting up session */ 504 - } 505 - midQ = AllocMidQEntry(in_buf, ses); 506 - if (midQ == NULL) { 507 up(&ses->server->tcpSem); 508 cifs_small_buf_release(in_buf); 509 - /* If not lock req, update # of requests on wire to server */ 510 - if(long_op < 3) { 511 - atomic_dec(&ses->server->inFlight); 512 - wake_up(&ses->server->request_q); 513 - } 514 - return -ENOMEM; 515 } 516 517 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); ··· 478 atomic_dec(&ses->server->inSend); 479 midQ->when_sent = jiffies; 480 #endif 481 - if(rc < 0) { 482 - DeleteMidQEntry(midQ); 483 - up(&ses->server->tcpSem); 484 - cifs_small_buf_release(in_buf); 485 - /* If not lock req, update # of requests on wire to server */ 486 - if(long_op < 3) { 487 - atomic_dec(&ses->server->inFlight); 488 - wake_up(&ses->server->request_q); 489 - } 490 - return rc; 491 - } else { 492 - up(&ses->server->tcpSem); 493 - cifs_small_buf_release(in_buf); 494 - } 495 496 if (long_op == -1) 497 - goto cifs_no_response_exit2; 498 else if (long_op == 2) /* writes past end of file can take loong time */ 499 timeout = 180 * HZ; 500 else if (long_op == 1) 501 timeout = 45 * HZ; /* should be greater than 502 servers oplock break timeout (about 43 seconds) */ 503 - else if (long_op > 2) { 504 - timeout = MAX_SCHEDULE_TIMEOUT; 505 - } else 506 timeout = 15 * HZ; 507 /* wait for 15 seconds or until woken up due to response arriving or 508 due to last connection to this server being unmounted */ 509 if (signal_pending(current)) { ··· 504 } 505 506 /* No user interrupts in wait - wreaks havoc with performance */ 507 - if(timeout != MAX_SCHEDULE_TIMEOUT) { 508 - unsigned long curr_timeout; 509 - 510 - for (;;) { 511 - curr_timeout = timeout + jiffies; 512 - wait_event(ses->server->response_q, 513 - (!(midQ->midState == MID_REQUEST_SUBMITTED)) || 514 - time_after(jiffies, curr_timeout) || 515 - ((ses->server->tcpStatus != CifsGood) && 516 - (ses->server->tcpStatus != CifsNew))); 517 - 518 - if (time_after(jiffies, curr_timeout) && 519 - (midQ->midState == MID_REQUEST_SUBMITTED) && 520 - ((ses->server->tcpStatus == CifsGood) || 521 - (ses->server->tcpStatus == CifsNew))) { 522 - 523 - unsigned long lrt; 524 - 525 - /* We timed out. Is the server still 526 - sending replies ? */ 527 - spin_lock(&GlobalMid_Lock); 528 - lrt = ses->server->lstrp; 529 - spin_unlock(&GlobalMid_Lock); 530 - 531 - /* Calculate 10 seconds past last receive time. 532 - Although we prefer not to time out if the 533 - server is still responding - we will time 534 - out if the server takes more than 15 (or 45 535 - or 180) seconds to respond to this request 536 - and has not responded to any request from 537 - other threads on the client within 10 seconds */ 538 - lrt += (10 * HZ); 539 - if (time_after(jiffies, lrt)) { 540 - /* No replies for 10 seconds. */ 541 - cERROR(1,("server not responding")); 542 - break; 543 - } 544 - } else { 545 - break; 546 - } 547 - } 548 - } else { 549 - wait_event(ses->server->response_q, 550 - (!(midQ->midState == MID_REQUEST_SUBMITTED)) || 551 - ((ses->server->tcpStatus != CifsGood) && 552 - (ses->server->tcpStatus != CifsNew))); 553 - } 554 555 spin_lock(&GlobalMid_Lock); 556 if (midQ->resp_buf) { ··· 532 } 533 spin_unlock(&GlobalMid_Lock); 534 DeleteMidQEntry(midQ); 535 - /* If not lock req, update # of requests on wire to server */ 536 - if(long_op < 3) { 537 - atomic_dec(&ses->server->inFlight); 538 - wake_up(&ses->server->request_q); 539 - } 540 return rc; 541 } 542 ··· 585 cFYI(1,("Bad MID state?")); 586 } 587 } 588 - cifs_no_response_exit2: 589 DeleteMidQEntry(midQ); 590 - 591 - if(long_op < 3) { 592 - atomic_dec(&ses->server->inFlight); 593 - wake_up(&ses->server->request_q); 594 - } 595 - 596 - return rc; 597 - 598 - out_unlock2: 599 - up(&ses->server->tcpSem); 600 - cifs_small_buf_release(in_buf); 601 - /* If not lock req, update # of requests on wire to server */ 602 - if(long_op < 3) { 603 - atomic_dec(&ses->server->inFlight); 604 - wake_up(&ses->server->request_q); 605 - } 606 607 return rc; 608 } ··· 620 /* Ensure that we do not send more than 50 overlapping requests 621 to the same server. We may make this configurable later or 622 use ses->maxReq */ 623 - if(long_op == -1) { 624 - /* oplock breaks must not be held up */ 625 - atomic_inc(&ses->server->inFlight); 626 - } else { 627 - spin_lock(&GlobalMid_Lock); 628 - while(1) { 629 - if(atomic_read(&ses->server->inFlight) >= 630 - cifs_max_pending){ 631 - spin_unlock(&GlobalMid_Lock); 632 - #ifdef CONFIG_CIFS_STATS2 633 - atomic_inc(&ses->server->num_waiters); 634 - #endif 635 - wait_event(ses->server->request_q, 636 - atomic_read(&ses->server->inFlight) 637 - < cifs_max_pending); 638 - #ifdef CONFIG_CIFS_STATS2 639 - atomic_dec(&ses->server->num_waiters); 640 - #endif 641 - spin_lock(&GlobalMid_Lock); 642 - } else { 643 - if(ses->server->tcpStatus == CifsExiting) { 644 - spin_unlock(&GlobalMid_Lock); 645 - return -ENOENT; 646 - } 647 648 - /* can not count locking commands against total since 649 - they are allowed to block on server */ 650 - 651 - if(long_op < 3) { 652 - /* update # of requests on the wire to server */ 653 - atomic_inc(&ses->server->inFlight); 654 - } 655 - spin_unlock(&GlobalMid_Lock); 656 - break; 657 - } 658 - } 659 - } 660 /* make sure that we sign in the same order that we send on this socket 661 and avoid races inside tcp sendmsg code that could cause corruption 662 of smb data */ 663 664 down(&ses->server->tcpSem); 665 666 - if (ses->server->tcpStatus == CifsExiting) { 667 - rc = -ENOENT; 668 - goto out_unlock; 669 - } else if (ses->server->tcpStatus == CifsNeedReconnect) { 670 - cFYI(1,("tcp session dead - return to caller to retry")); 671 - rc = -EAGAIN; 672 - goto out_unlock; 673 - } else if (ses->status != CifsGood) { 674 - /* check if SMB session is bad because we are setting it up */ 675 - if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 676 - (in_buf->Command != SMB_COM_NEGOTIATE)) { 677 - rc = -EAGAIN; 678 - goto out_unlock; 679 - } /* else ok - we are setting up session */ 680 - } 681 - midQ = AllocMidQEntry(in_buf, ses); 682 - if (midQ == NULL) { 683 up(&ses->server->tcpSem); 684 - /* If not lock req, update # of requests on wire to server */ 685 - if(long_op < 3) { 686 - atomic_dec(&ses->server->inFlight); 687 - wake_up(&ses->server->request_q); 688 - } 689 - return -ENOMEM; 690 } 691 692 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 693 - up(&ses->server->tcpSem); 694 cERROR(1, ("Illegal length, greater than maximum frame, %d", 695 in_buf->smb_buf_length)); 696 DeleteMidQEntry(midQ); 697 - /* If not lock req, update # of requests on wire to server */ 698 - if(long_op < 3) { 699 - atomic_dec(&ses->server->inFlight); 700 - wake_up(&ses->server->request_q); 701 - } 702 return -EIO; 703 } 704 ··· 663 atomic_dec(&ses->server->inSend); 664 midQ->when_sent = jiffies; 665 #endif 666 - if(rc < 0) { 667 - DeleteMidQEntry(midQ); 668 - up(&ses->server->tcpSem); 669 - /* If not lock req, update # of requests on wire to server */ 670 - if(long_op < 3) { 671 - atomic_dec(&ses->server->inFlight); 672 - wake_up(&ses->server->request_q); 673 - } 674 - return rc; 675 - } else 676 - up(&ses->server->tcpSem); 677 if (long_op == -1) 678 - goto cifs_no_response_exit; 679 else if (long_op == 2) /* writes past end of file can take loong time */ 680 timeout = 180 * HZ; 681 else if (long_op == 1) 682 timeout = 45 * HZ; /* should be greater than 683 servers oplock break timeout (about 43 seconds) */ 684 - else if (long_op > 2) { 685 - timeout = MAX_SCHEDULE_TIMEOUT; 686 - } else 687 timeout = 15 * HZ; 688 /* wait for 15 seconds or until woken up due to response arriving or 689 due to last connection to this server being unmounted */ ··· 686 } 687 688 /* No user interrupts in wait - wreaks havoc with performance */ 689 - if(timeout != MAX_SCHEDULE_TIMEOUT) { 690 - unsigned long curr_timeout; 691 - 692 - for (;;) { 693 - curr_timeout = timeout + jiffies; 694 - wait_event(ses->server->response_q, 695 - (!(midQ->midState == MID_REQUEST_SUBMITTED)) || 696 - time_after(jiffies, curr_timeout) || 697 - ((ses->server->tcpStatus != CifsGood) && 698 - (ses->server->tcpStatus != CifsNew))); 699 - 700 - if (time_after(jiffies, curr_timeout) && 701 - (midQ->midState == MID_REQUEST_SUBMITTED) && 702 - ((ses->server->tcpStatus == CifsGood) || 703 - (ses->server->tcpStatus == CifsNew))) { 704 - 705 - unsigned long lrt; 706 - 707 - /* We timed out. Is the server still 708 - sending replies ? */ 709 - spin_lock(&GlobalMid_Lock); 710 - lrt = ses->server->lstrp; 711 - spin_unlock(&GlobalMid_Lock); 712 - 713 - /* Calculate 10 seconds past last receive time*/ 714 - lrt += (10 * HZ); 715 - if (time_after(jiffies, lrt)) { 716 - /* Server sent no reply in 10 seconds */ 717 - cERROR(1,("Server not responding")); 718 - break; 719 - } 720 - } else { 721 - break; 722 - } 723 - } 724 - } else { 725 - wait_event(ses->server->response_q, 726 - (!(midQ->midState == MID_REQUEST_SUBMITTED)) || 727 - ((ses->server->tcpStatus != CifsGood) && 728 - (ses->server->tcpStatus != CifsNew))); 729 - } 730 731 spin_lock(&GlobalMid_Lock); 732 if (midQ->resp_buf) { ··· 714 } 715 spin_unlock(&GlobalMid_Lock); 716 DeleteMidQEntry(midQ); 717 - /* If not lock req, update # of requests on wire to server */ 718 - if(long_op < 3) { 719 - atomic_dec(&ses->server->inFlight); 720 - wake_up(&ses->server->request_q); 721 - } 722 return rc; 723 } 724 ··· 763 cERROR(1,("Bad MID state?")); 764 } 765 } 766 - cifs_no_response_exit: 767 - DeleteMidQEntry(midQ); 768 769 - if(long_op < 3) { 770 - atomic_dec(&ses->server->inFlight); 771 - wake_up(&ses->server->request_q); 772 - } 773 774 return rc; 775 776 - out_unlock: 777 up(&ses->server->tcpSem); 778 - /* If not lock req, update # of requests on wire to server */ 779 - if(long_op < 3) { 780 - atomic_dec(&ses->server->inFlight); 781 - wake_up(&ses->server->request_q); 782 } 783 784 return rc; 785 }
··· 37 extern kmem_cache_t *cifs_oplock_cachep; 38 39 static struct mid_q_entry * 40 + AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) 41 { 42 struct mid_q_entry *temp; 43 ··· 204 rc = 0; 205 } 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 + 211 return rc; 212 } 213 ··· 218 unsigned int len = iov[0].iov_len; 219 unsigned int total_len; 220 int first_vec = 0; 221 + unsigned int smb_buf_length = smb_buffer->smb_buf_length; 222 223 if(ssocket == NULL) 224 return -ENOTSOCK; /* BB eventually add reconnect code here */ ··· 294 } else 295 rc = 0; 296 297 + /* Don't want to modify the buffer as a 298 + side effect of this call. */ 299 + smb_buffer->smb_buf_length = smb_buf_length; 300 + 301 return rc; 302 + } 303 + 304 + static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) 305 + { 306 + if(long_op == -1) { 307 + /* oplock breaks must not be held up */ 308 + atomic_inc(&ses->server->inFlight); 309 + } else { 310 + spin_lock(&GlobalMid_Lock); 311 + while(1) { 312 + if(atomic_read(&ses->server->inFlight) >= 313 + cifs_max_pending){ 314 + spin_unlock(&GlobalMid_Lock); 315 + #ifdef CONFIG_CIFS_STATS2 316 + atomic_inc(&ses->server->num_waiters); 317 + #endif 318 + wait_event(ses->server->request_q, 319 + atomic_read(&ses->server->inFlight) 320 + < cifs_max_pending); 321 + #ifdef CONFIG_CIFS_STATS2 322 + atomic_dec(&ses->server->num_waiters); 323 + #endif 324 + spin_lock(&GlobalMid_Lock); 325 + } else { 326 + if(ses->server->tcpStatus == CifsExiting) { 327 + spin_unlock(&GlobalMid_Lock); 328 + return -ENOENT; 329 + } 330 + 331 + /* can not count locking commands against total since 332 + they are allowed to block on server */ 333 + 334 + /* update # of requests on the wire to server */ 335 + if (long_op < 3) 336 + atomic_inc(&ses->server->inFlight); 337 + spin_unlock(&GlobalMid_Lock); 338 + break; 339 + } 340 + } 341 + } 342 + return 0; 343 + } 344 + 345 + static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf, 346 + struct mid_q_entry **ppmidQ) 347 + { 348 + if (ses->server->tcpStatus == CifsExiting) { 349 + return -ENOENT; 350 + } else if (ses->server->tcpStatus == CifsNeedReconnect) { 351 + cFYI(1,("tcp session dead - return to caller to retry")); 352 + return -EAGAIN; 353 + } else if (ses->status != CifsGood) { 354 + /* check if SMB session is bad because we are setting it up */ 355 + if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 356 + (in_buf->Command != SMB_COM_NEGOTIATE)) { 357 + return -EAGAIN; 358 + } /* else ok - we are setting up session */ 359 + } 360 + *ppmidQ = AllocMidQEntry(in_buf, ses); 361 + if (*ppmidQ == NULL) { 362 + return -ENOMEM; 363 + } 364 + return 0; 365 + } 366 + 367 + static int wait_for_response(struct cifsSesInfo *ses, 368 + struct mid_q_entry *midQ, 369 + unsigned long timeout, 370 + unsigned long time_to_wait) 371 + { 372 + unsigned long curr_timeout; 373 + 374 + for (;;) { 375 + curr_timeout = timeout + jiffies; 376 + wait_event(ses->server->response_q, 377 + (!(midQ->midState == MID_REQUEST_SUBMITTED)) || 378 + time_after(jiffies, curr_timeout) || 379 + ((ses->server->tcpStatus != CifsGood) && 380 + (ses->server->tcpStatus != CifsNew))); 381 + 382 + if (time_after(jiffies, curr_timeout) && 383 + (midQ->midState == MID_REQUEST_SUBMITTED) && 384 + ((ses->server->tcpStatus == CifsGood) || 385 + (ses->server->tcpStatus == CifsNew))) { 386 + 387 + unsigned long lrt; 388 + 389 + /* We timed out. Is the server still 390 + sending replies ? */ 391 + spin_lock(&GlobalMid_Lock); 392 + lrt = ses->server->lstrp; 393 + spin_unlock(&GlobalMid_Lock); 394 + 395 + /* Calculate time_to_wait past last receive time. 396 + Although we prefer not to time out if the 397 + server is still responding - we will time 398 + out if the server takes more than 15 (or 45 399 + or 180) seconds to respond to this request 400 + and has not responded to any request from 401 + other threads on the client within 10 seconds */ 402 + lrt += time_to_wait; 403 + if (time_after(jiffies, lrt)) { 404 + /* No replies for time_to_wait. */ 405 + cERROR(1,("server not responding")); 406 + return -1; 407 + } 408 + } else { 409 + return 0; 410 + } 411 + } 412 } 413 414 int ··· 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 328 + rc = wait_for_free_request(ses, long_op); 329 + if (rc) { 330 + cifs_small_buf_release(in_buf); 331 + return rc; 332 } 333 + 334 /* make sure that we sign in the same order that we send on this socket 335 and avoid races inside tcp sendmsg code that could cause corruption 336 of smb data */ 337 338 down(&ses->server->tcpSem); 339 340 + rc = allocate_mid(ses, in_buf, &midQ); 341 + if (rc) { 342 up(&ses->server->tcpSem); 343 cifs_small_buf_release(in_buf); 344 + /* Update # of requests on wire to server */ 345 + atomic_dec(&ses->server->inFlight); 346 + wake_up(&ses->server->request_q); 347 + return rc; 348 } 349 350 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); ··· 407 atomic_dec(&ses->server->inSend); 408 midQ->when_sent = jiffies; 409 #endif 410 + 411 + up(&ses->server->tcpSem); 412 + cifs_small_buf_release(in_buf); 413 + 414 + if(rc < 0) 415 + goto out; 416 417 if (long_op == -1) 418 + goto out; 419 else if (long_op == 2) /* writes past end of file can take loong time */ 420 timeout = 180 * HZ; 421 else if (long_op == 1) 422 timeout = 45 * HZ; /* should be greater than 423 servers oplock break timeout (about 43 seconds) */ 424 + else 425 timeout = 15 * HZ; 426 + 427 /* wait for 15 seconds or until woken up due to response arriving or 428 due to last connection to this server being unmounted */ 429 if (signal_pending(current)) { ··· 442 } 443 444 /* No user interrupts in wait - wreaks havoc with performance */ 445 + wait_for_response(ses, midQ, timeout, 10 * HZ); 446 447 spin_lock(&GlobalMid_Lock); 448 if (midQ->resp_buf) { ··· 516 } 517 spin_unlock(&GlobalMid_Lock); 518 DeleteMidQEntry(midQ); 519 + /* Update # of requests on wire to server */ 520 + atomic_dec(&ses->server->inFlight); 521 + wake_up(&ses->server->request_q); 522 return rc; 523 } 524 ··· 571 cFYI(1,("Bad MID state?")); 572 } 573 } 574 + 575 + out: 576 + 577 DeleteMidQEntry(midQ); 578 + atomic_dec(&ses->server->inFlight); 579 + wake_up(&ses->server->request_q); 580 581 return rc; 582 } ··· 618 /* Ensure that we do not send more than 50 overlapping requests 619 to the same server. We may make this configurable later or 620 use ses->maxReq */ 621 622 + rc = wait_for_free_request(ses, long_op); 623 + if (rc) 624 + return rc; 625 + 626 /* make sure that we sign in the same order that we send on this socket 627 and avoid races inside tcp sendmsg code that could cause corruption 628 of smb data */ 629 630 down(&ses->server->tcpSem); 631 632 + rc = allocate_mid(ses, in_buf, &midQ); 633 + if (rc) { 634 up(&ses->server->tcpSem); 635 + /* Update # of requests on wire to server */ 636 + atomic_dec(&ses->server->inFlight); 637 + wake_up(&ses->server->request_q); 638 + return rc; 639 } 640 641 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 642 cERROR(1, ("Illegal length, greater than maximum frame, %d", 643 in_buf->smb_buf_length)); 644 DeleteMidQEntry(midQ); 645 + up(&ses->server->tcpSem); 646 + /* Update # of requests on wire to server */ 647 + atomic_dec(&ses->server->inFlight); 648 + wake_up(&ses->server->request_q); 649 return -EIO; 650 } 651 ··· 712 atomic_dec(&ses->server->inSend); 713 midQ->when_sent = jiffies; 714 #endif 715 + up(&ses->server->tcpSem); 716 + 717 + if(rc < 0) 718 + goto out; 719 + 720 if (long_op == -1) 721 + goto out; 722 else if (long_op == 2) /* writes past end of file can take loong time */ 723 timeout = 180 * HZ; 724 else if (long_op == 1) 725 timeout = 45 * HZ; /* should be greater than 726 servers oplock break timeout (about 43 seconds) */ 727 + else 728 timeout = 15 * HZ; 729 /* wait for 15 seconds or until woken up due to response arriving or 730 due to last connection to this server being unmounted */ ··· 743 } 744 745 /* No user interrupts in wait - wreaks havoc with performance */ 746 + wait_for_response(ses, midQ, timeout, 10 * HZ); 747 748 spin_lock(&GlobalMid_Lock); 749 if (midQ->resp_buf) { ··· 811 } 812 spin_unlock(&GlobalMid_Lock); 813 DeleteMidQEntry(midQ); 814 + /* Update # of requests on wire to server */ 815 + atomic_dec(&ses->server->inFlight); 816 + wake_up(&ses->server->request_q); 817 return rc; 818 } 819 ··· 862 cERROR(1,("Bad MID state?")); 863 } 864 } 865 866 + out: 867 + 868 + DeleteMidQEntry(midQ); 869 + atomic_dec(&ses->server->inFlight); 870 + wake_up(&ses->server->request_q); 871 872 return rc; 873 + } 874 875 + /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */ 876 + 877 + static int 878 + send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf, 879 + struct mid_q_entry *midQ) 880 + { 881 + int rc = 0; 882 + struct cifsSesInfo *ses = tcon->ses; 883 + __u16 mid = in_buf->Mid; 884 + 885 + header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0); 886 + in_buf->Mid = mid; 887 + down(&ses->server->tcpSem); 888 + rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 889 + if (rc) { 890 + up(&ses->server->tcpSem); 891 + return rc; 892 + } 893 + rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 894 + (struct sockaddr *) &(ses->server->addr.sockAddr)); 895 up(&ses->server->tcpSem); 896 + return rc; 897 + } 898 + 899 + /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows 900 + blocking lock to return. */ 901 + 902 + static int 903 + send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon, 904 + struct smb_hdr *in_buf, 905 + struct smb_hdr *out_buf) 906 + { 907 + int bytes_returned; 908 + struct cifsSesInfo *ses = tcon->ses; 909 + LOCK_REQ *pSMB = (LOCK_REQ *)in_buf; 910 + 911 + /* We just modify the current in_buf to change 912 + the type of lock from LOCKING_ANDX_SHARED_LOCK 913 + or LOCKING_ANDX_EXCLUSIVE_LOCK to 914 + LOCKING_ANDX_CANCEL_LOCK. */ 915 + 916 + pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; 917 + pSMB->Timeout = 0; 918 + pSMB->hdr.Mid = GetNextMid(ses->server); 919 + 920 + return SendReceive(xid, ses, in_buf, out_buf, 921 + &bytes_returned, 0); 922 + } 923 + 924 + int 925 + SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, 926 + struct smb_hdr *in_buf, struct smb_hdr *out_buf, 927 + int *pbytes_returned) 928 + { 929 + int rc = 0; 930 + int rstart = 0; 931 + unsigned int receive_len; 932 + struct mid_q_entry *midQ; 933 + struct cifsSesInfo *ses; 934 + 935 + if (tcon == NULL || tcon->ses == NULL) { 936 + cERROR(1,("Null smb session")); 937 + return -EIO; 938 + } 939 + ses = tcon->ses; 940 + 941 + if(ses->server == NULL) { 942 + cERROR(1,("Null tcp session")); 943 + return -EIO; 944 } 945 946 + if(ses->server->tcpStatus == CifsExiting) 947 + return -ENOENT; 948 + 949 + /* Ensure that we do not send more than 50 overlapping requests 950 + to the same server. We may make this configurable later or 951 + use ses->maxReq */ 952 + 953 + rc = wait_for_free_request(ses, 3); 954 + if (rc) 955 + return rc; 956 + 957 + /* make sure that we sign in the same order that we send on this socket 958 + and avoid races inside tcp sendmsg code that could cause corruption 959 + of smb data */ 960 + 961 + down(&ses->server->tcpSem); 962 + 963 + rc = allocate_mid(ses, in_buf, &midQ); 964 + if (rc) { 965 + up(&ses->server->tcpSem); 966 + return rc; 967 + } 968 + 969 + if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 970 + up(&ses->server->tcpSem); 971 + cERROR(1, ("Illegal length, greater than maximum frame, %d", 972 + in_buf->smb_buf_length)); 973 + DeleteMidQEntry(midQ); 974 + return -EIO; 975 + } 976 + 977 + rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 978 + 979 + midQ->midState = MID_REQUEST_SUBMITTED; 980 + #ifdef CONFIG_CIFS_STATS2 981 + atomic_inc(&ses->server->inSend); 982 + #endif 983 + rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 984 + (struct sockaddr *) &(ses->server->addr.sockAddr)); 985 + #ifdef CONFIG_CIFS_STATS2 986 + atomic_dec(&ses->server->inSend); 987 + midQ->when_sent = jiffies; 988 + #endif 989 + up(&ses->server->tcpSem); 990 + 991 + if(rc < 0) { 992 + DeleteMidQEntry(midQ); 993 + return rc; 994 + } 995 + 996 + /* Wait for a reply - allow signals to interrupt. */ 997 + rc = wait_event_interruptible(ses->server->response_q, 998 + (!(midQ->midState == MID_REQUEST_SUBMITTED)) || 999 + ((ses->server->tcpStatus != CifsGood) && 1000 + (ses->server->tcpStatus != CifsNew))); 1001 + 1002 + /* Were we interrupted by a signal ? */ 1003 + if ((rc == -ERESTARTSYS) && 1004 + (midQ->midState == MID_REQUEST_SUBMITTED) && 1005 + ((ses->server->tcpStatus == CifsGood) || 1006 + (ses->server->tcpStatus == CifsNew))) { 1007 + 1008 + if (in_buf->Command == SMB_COM_TRANSACTION2) { 1009 + /* POSIX lock. We send a NT_CANCEL SMB to cause the 1010 + blocking lock to return. */ 1011 + 1012 + rc = send_nt_cancel(tcon, in_buf, midQ); 1013 + if (rc) { 1014 + DeleteMidQEntry(midQ); 1015 + return rc; 1016 + } 1017 + } else { 1018 + /* Windows lock. We send a LOCKINGX_CANCEL_LOCK 1019 + to cause the blocking lock to return. */ 1020 + 1021 + rc = send_lock_cancel(xid, tcon, in_buf, out_buf); 1022 + 1023 + /* If we get -ENOLCK back the lock may have 1024 + already been removed. Don't exit in this case. */ 1025 + if (rc && rc != -ENOLCK) { 1026 + DeleteMidQEntry(midQ); 1027 + return rc; 1028 + } 1029 + } 1030 + 1031 + /* Wait 5 seconds for the response. */ 1032 + if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ)==0) { 1033 + /* We got the response - restart system call. */ 1034 + rstart = 1; 1035 + } 1036 + } 1037 + 1038 + spin_lock(&GlobalMid_Lock); 1039 + if (midQ->resp_buf) { 1040 + spin_unlock(&GlobalMid_Lock); 1041 + receive_len = midQ->resp_buf->smb_buf_length; 1042 + } else { 1043 + cERROR(1,("No response for cmd %d mid %d", 1044 + midQ->command, midQ->mid)); 1045 + if(midQ->midState == MID_REQUEST_SUBMITTED) { 1046 + if(ses->server->tcpStatus == CifsExiting) 1047 + rc = -EHOSTDOWN; 1048 + else { 1049 + ses->server->tcpStatus = CifsNeedReconnect; 1050 + midQ->midState = MID_RETRY_NEEDED; 1051 + } 1052 + } 1053 + 1054 + if (rc != -EHOSTDOWN) { 1055 + if(midQ->midState == MID_RETRY_NEEDED) { 1056 + rc = -EAGAIN; 1057 + cFYI(1,("marking request for retry")); 1058 + } else { 1059 + rc = -EIO; 1060 + } 1061 + } 1062 + spin_unlock(&GlobalMid_Lock); 1063 + DeleteMidQEntry(midQ); 1064 + return rc; 1065 + } 1066 + 1067 + if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 1068 + cERROR(1, ("Frame too large received. Length: %d Xid: %d", 1069 + receive_len, xid)); 1070 + rc = -EIO; 1071 + } else { /* rcvd frame is ok */ 1072 + 1073 + if (midQ->resp_buf && out_buf 1074 + && (midQ->midState == MID_RESPONSE_RECEIVED)) { 1075 + out_buf->smb_buf_length = receive_len; 1076 + memcpy((char *)out_buf + 4, 1077 + (char *)midQ->resp_buf + 4, 1078 + receive_len); 1079 + 1080 + dump_smb(out_buf, 92); 1081 + /* convert the length into a more usable form */ 1082 + if((receive_len > 24) && 1083 + (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 1084 + SECMODE_SIGN_ENABLED))) { 1085 + rc = cifs_verify_signature(out_buf, 1086 + ses->server->mac_signing_key, 1087 + midQ->sequence_number+1); 1088 + if(rc) { 1089 + cERROR(1,("Unexpected SMB signature")); 1090 + /* BB FIXME add code to kill session */ 1091 + } 1092 + } 1093 + 1094 + *pbytes_returned = out_buf->smb_buf_length; 1095 + 1096 + /* BB special case reconnect tid and uid here? */ 1097 + rc = map_smb_to_linux_error(out_buf); 1098 + 1099 + /* convert ByteCount if necessary */ 1100 + if (receive_len >= 1101 + sizeof (struct smb_hdr) - 1102 + 4 /* do not count RFC1001 header */ + 1103 + (2 * out_buf->WordCount) + 2 /* bcc */ ) 1104 + BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 1105 + } else { 1106 + rc = -EIO; 1107 + cERROR(1,("Bad MID state?")); 1108 + } 1109 + } 1110 + DeleteMidQEntry(midQ); 1111 + if (rstart && rc == -EACCES) 1112 + return -ERESTARTSYS; 1113 return rc; 1114 }