[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 3 * 4 4 * Copyright (C) International Business Machines Corp., 2002,2006 5 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 + * Jeremy Allison (jra@samba.org) 6 7 * 7 8 * This library is free software; you can redistribute it and/or modify 8 9 * it under the terms of the GNU Lesser General Public License as published ··· 268 267 }; 269 268 270 269 /* 271 - * This info hangs off the cifsFileInfo structure. This is used to track 272 - * byte stream locks on the file 270 + * This info hangs off the cifsFileInfo structure, pointed to by llist. 271 + * This is used to track byte stream locks on the file 273 272 */ 274 273 struct cifsLockInfo { 275 - struct cifsLockInfo *next; 276 - int start; 277 - int length; 278 - int type; 274 + struct list_head llist; /* pointer to next cifsLockInfo */ 275 + __u64 offset; 276 + __u64 length; 277 + __u8 type; 279 278 }; 280 279 281 280 /* ··· 306 305 /* lock scope id (0 if none) */ 307 306 struct file * pfile; /* needed for writepage */ 308 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. */ 309 310 unsigned closePend:1; /* file is marked to close */ 310 311 unsigned invalidHandle:1; /* file closed via session abend */ 311 312 atomic_t wrtPending; /* handle in use - defer close */
+4
fs/cifs/cifsproto.h
··· 50 50 extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, 51 51 struct kvec *, int /* nvec to send */, 52 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 */); 53 57 extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); 54 58 extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); 55 59 extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
+13 -2
fs/cifs/cifssmb.c
··· 1460 1460 pSMB->hdr.smb_buf_length += count; 1461 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 1468 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1469 + } 1465 1470 cifs_stats_inc(&tcon->num_locks); 1466 1471 if (rc) { 1467 1472 cFYI(1, ("Send error in Lock = %d", rc)); ··· 1551 1546 pSMB->Reserved4 = 0; 1552 1547 pSMB->hdr.smb_buf_length += byte_count; 1553 1548 pSMB->ByteCount = cpu_to_le16(byte_count); 1554 - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 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, 1555 1554 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1555 + } 1556 + 1556 1557 if (rc) { 1557 1558 cFYI(1, ("Send error in Posix Lock = %d", rc)); 1558 1559 } else if (get_flag) {
+80 -15
fs/cifs/file.c
··· 5 5 * 6 6 * Copyright (C) International Business Machines Corp., 2002,2003 7 7 * Author(s): Steve French (sfrench@us.ibm.com) 8 + * Jeremy Allison (jra@samba.org) 8 9 * 9 10 * This library is free software; you can redistribute it and/or modify 10 11 * it under the terms of the GNU Lesser General Public License as published ··· 48 47 private_data->netfid = netfid; 49 48 private_data->pid = current->tgid; 50 49 init_MUTEX(&private_data->fh_sem); 50 + init_MUTEX(&private_data->lock_sem); 51 + INIT_LIST_HEAD(&private_data->llist); 51 52 private_data->pfile = file; /* needed for writepage */ 52 53 private_data->pInode = inode; 53 54 private_data->invalidHandle = FALSE; ··· 476 473 cifs_sb = CIFS_SB(inode->i_sb); 477 474 pTcon = cifs_sb->tcon; 478 475 if (pSMBFile) { 476 + struct cifsLockInfo *li, *tmp; 477 + 479 478 pSMBFile->closePend = TRUE; 480 479 if (pTcon) { 481 480 /* no sense reconnecting to close a file that is ··· 501 496 pSMBFile->netfid); 502 497 } 503 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 + 504 509 write_lock(&GlobalSMBSeslock); 505 510 list_del(&pSMBFile->flist); 506 511 list_del(&pSMBFile->tlist); ··· 585 570 return rc; 586 571 } 587 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 588 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 589 589 { 590 590 int rc, xid; ··· 611 581 struct cifsTconInfo *pTcon; 612 582 __u16 netfid; 613 583 __u8 lockType = LOCKING_ANDX_LARGE_FILES; 584 + int posix_locking; 614 585 615 586 length = 1 + pfLock->fl_end - pfLock->fl_start; 616 587 rc = -EACCES; ··· 670 639 } 671 640 netfid = ((struct cifsFileInfo *)file->private_data)->netfid; 672 641 642 + posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && 643 + (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability)); 673 644 674 645 /* BB add code here to normalize offset and length to 675 646 account for negative length which we can not accept over the 676 647 wire */ 677 648 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))) { 649 + if(posix_locking) { 681 650 int posix_lock_type; 682 651 if(lockType & LOCKING_ANDX_SHARED_LOCK) 683 652 posix_lock_type = CIFS_RDLCK; ··· 713 682 FreeXid(xid); 714 683 return rc; 715 684 } 716 - if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && 717 - (CIFS_UNIX_FCNTL_CAP & 718 - le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { 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) { 719 694 int posix_lock_type; 720 695 if(lockType & LOCKING_ANDX_SHARED_LOCK) 721 696 posix_lock_type = CIFS_RDLCK; ··· 730 693 731 694 if(numUnlock == 1) 732 695 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 - } 696 + 739 697 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, 740 698 length, pfLock, 741 699 posix_lock_type, wait_flag); 742 - } else 743 - rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, 744 - numUnlock, numLock, lockType, 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 + 745 736 if (pfLock->fl_flags & FL_POSIX) 746 737 posix_lock_file_wait(file, pfLock); 747 738 FreeXid(xid);
+1
fs/cifs/netmisc.c
··· 72 72 {ERRinvlevel,-EOPNOTSUPP}, 73 73 {ERRdirnotempty, -ENOTEMPTY}, 74 74 {ERRnotlocked, -ENOLCK}, 75 + {ERRcancelviolation, -ENOLCK}, 75 76 {ERRalreadyexists, -EEXIST}, 76 77 {ERRmoredata, -EOVERFLOW}, 77 78 {ERReasnotsupported,-EOPNOTSUPP},
+1
fs/cifs/smberr.h
··· 95 95 #define ERRinvlevel 124 96 96 #define ERRdirnotempty 145 97 97 #define ERRnotlocked 158 98 + #define ERRcancelviolation 173 98 99 #define ERRalreadyexists 183 99 100 #define ERRbadpipe 230 100 101 #define ERRpipebusy 231
+415 -284
fs/cifs/transport.c
··· 37 37 extern kmem_cache_t *cifs_oplock_cachep; 38 38 39 39 static struct mid_q_entry * 40 - AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) 40 + AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) 41 41 { 42 42 struct mid_q_entry *temp; 43 43 ··· 204 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 211 return rc; 208 212 } 209 213 ··· 222 218 unsigned int len = iov[0].iov_len; 223 219 unsigned int total_len; 224 220 int first_vec = 0; 221 + unsigned int smb_buf_length = smb_buffer->smb_buf_length; 225 222 226 223 if(ssocket == NULL) 227 224 return -ENOTSOCK; /* BB eventually add reconnect code here */ ··· 299 294 } else 300 295 rc = 0; 301 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 + 302 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 + } 303 412 } 304 413 305 414 int ··· 443 324 /* Ensure that we do not send more than 50 overlapping requests 444 325 to the same server. We may make this configurable later or 445 326 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 327 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 - } 328 + rc = wait_for_free_request(ses, long_op); 329 + if (rc) { 330 + cifs_small_buf_release(in_buf); 331 + return rc; 483 332 } 333 + 484 334 /* make sure that we sign in the same order that we send on this socket 485 335 and avoid races inside tcp sendmsg code that could cause corruption 486 336 of smb data */ 487 337 488 338 down(&ses->server->tcpSem); 489 339 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) { 340 + rc = allocate_mid(ses, in_buf, &midQ); 341 + if (rc) { 507 342 up(&ses->server->tcpSem); 508 343 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; 344 + /* Update # of requests on wire to server */ 345 + atomic_dec(&ses->server->inFlight); 346 + wake_up(&ses->server->request_q); 347 + return rc; 515 348 } 516 349 517 350 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); ··· 478 407 atomic_dec(&ses->server->inSend); 479 408 midQ->when_sent = jiffies; 480 409 #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 - } 410 + 411 + up(&ses->server->tcpSem); 412 + cifs_small_buf_release(in_buf); 413 + 414 + if(rc < 0) 415 + goto out; 495 416 496 417 if (long_op == -1) 497 - goto cifs_no_response_exit2; 418 + goto out; 498 419 else if (long_op == 2) /* writes past end of file can take loong time */ 499 420 timeout = 180 * HZ; 500 421 else if (long_op == 1) 501 422 timeout = 45 * HZ; /* should be greater than 502 423 servers oplock break timeout (about 43 seconds) */ 503 - else if (long_op > 2) { 504 - timeout = MAX_SCHEDULE_TIMEOUT; 505 - } else 424 + else 506 425 timeout = 15 * HZ; 426 + 507 427 /* wait for 15 seconds or until woken up due to response arriving or 508 428 due to last connection to this server being unmounted */ 509 429 if (signal_pending(current)) { ··· 504 442 } 505 443 506 444 /* 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 - } 445 + wait_for_response(ses, midQ, timeout, 10 * HZ); 554 446 555 447 spin_lock(&GlobalMid_Lock); 556 448 if (midQ->resp_buf) { ··· 532 516 } 533 517 spin_unlock(&GlobalMid_Lock); 534 518 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 - } 519 + /* Update # of requests on wire to server */ 520 + atomic_dec(&ses->server->inFlight); 521 + wake_up(&ses->server->request_q); 540 522 return rc; 541 523 } 542 524 ··· 585 571 cFYI(1,("Bad MID state?")); 586 572 } 587 573 } 588 - cifs_no_response_exit2: 574 + 575 + out: 576 + 589 577 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 - } 578 + atomic_dec(&ses->server->inFlight); 579 + wake_up(&ses->server->request_q); 606 580 607 581 return rc; 608 582 } ··· 620 618 /* Ensure that we do not send more than 50 overlapping requests 621 619 to the same server. We may make this configurable later or 622 620 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 621 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 - } 622 + rc = wait_for_free_request(ses, long_op); 623 + if (rc) 624 + return rc; 625 + 660 626 /* make sure that we sign in the same order that we send on this socket 661 627 and avoid races inside tcp sendmsg code that could cause corruption 662 628 of smb data */ 663 629 664 630 down(&ses->server->tcpSem); 665 631 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) { 632 + rc = allocate_mid(ses, in_buf, &midQ); 633 + if (rc) { 683 634 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; 635 + /* Update # of requests on wire to server */ 636 + atomic_dec(&ses->server->inFlight); 637 + wake_up(&ses->server->request_q); 638 + return rc; 690 639 } 691 640 692 641 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 693 - up(&ses->server->tcpSem); 694 642 cERROR(1, ("Illegal length, greater than maximum frame, %d", 695 643 in_buf->smb_buf_length)); 696 644 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 - } 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); 702 649 return -EIO; 703 650 } 704 651 ··· 663 712 atomic_dec(&ses->server->inSend); 664 713 midQ->when_sent = jiffies; 665 714 #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); 715 + up(&ses->server->tcpSem); 716 + 717 + if(rc < 0) 718 + goto out; 719 + 677 720 if (long_op == -1) 678 - goto cifs_no_response_exit; 721 + goto out; 679 722 else if (long_op == 2) /* writes past end of file can take loong time */ 680 723 timeout = 180 * HZ; 681 724 else if (long_op == 1) 682 725 timeout = 45 * HZ; /* should be greater than 683 726 servers oplock break timeout (about 43 seconds) */ 684 - else if (long_op > 2) { 685 - timeout = MAX_SCHEDULE_TIMEOUT; 686 - } else 727 + else 687 728 timeout = 15 * HZ; 688 729 /* wait for 15 seconds or until woken up due to response arriving or 689 730 due to last connection to this server being unmounted */ ··· 686 743 } 687 744 688 745 /* 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 - } 746 + wait_for_response(ses, midQ, timeout, 10 * HZ); 730 747 731 748 spin_lock(&GlobalMid_Lock); 732 749 if (midQ->resp_buf) { ··· 714 811 } 715 812 spin_unlock(&GlobalMid_Lock); 716 813 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 - } 814 + /* Update # of requests on wire to server */ 815 + atomic_dec(&ses->server->inFlight); 816 + wake_up(&ses->server->request_q); 722 817 return rc; 723 818 } 724 819 ··· 763 862 cERROR(1,("Bad MID state?")); 764 863 } 765 864 } 766 - cifs_no_response_exit: 767 - DeleteMidQEntry(midQ); 768 865 769 - if(long_op < 3) { 770 - atomic_dec(&ses->server->inFlight); 771 - wake_up(&ses->server->request_q); 772 - } 866 + out: 867 + 868 + DeleteMidQEntry(midQ); 869 + atomic_dec(&ses->server->inFlight); 870 + wake_up(&ses->server->request_q); 773 871 774 872 return rc; 873 + } 775 874 776 - out_unlock: 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)); 777 895 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); 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; 782 944 } 783 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; 784 1113 return rc; 785 1114 }