1/* 2 Unix SMB/CIFS implementation. 3 Blocking Locking functions 4 Copyright (C) Jeremy Allison 1998-2003 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#include "includes.h" 22#undef DBGC_CLASS 23#define DBGC_CLASS DBGC_LOCKING 24 25extern int max_send; 26 27/**************************************************************************** 28 This is the structure to queue to implement blocking locks. 29 notify. It consists of the requesting SMB and the expiry time. 30*****************************************************************************/ 31 32typedef struct _blocking_lock_record { 33 struct _blocking_lock_record *next; 34 struct _blocking_lock_record *prev; 35 int com_type; 36 files_struct *fsp; 37 struct timeval expire_time; 38 int lock_num; 39 SMB_BIG_UINT offset; 40 SMB_BIG_UINT count; 41 uint32 lock_pid; 42 uint32 blocking_pid; /* PID that blocks us. */ 43 enum brl_flavour lock_flav; 44 enum brl_type lock_type; 45 char *inbuf; 46 int length; 47} blocking_lock_record; 48 49/* dlink list we store pending lock records on. */ 50static blocking_lock_record *blocking_lock_queue; 51 52/* dlink list we move cancelled lock records onto. */ 53static blocking_lock_record *blocking_lock_cancelled_queue; 54 55/**************************************************************************** 56 Destructor for the above structure. 57****************************************************************************/ 58 59static void free_blocking_lock_record(blocking_lock_record *blr) 60{ 61 SAFE_FREE(blr->inbuf); 62 SAFE_FREE(blr); 63} 64 65/**************************************************************************** 66 Determine if this is a secondary element of a chained SMB. 67 **************************************************************************/ 68 69static BOOL in_chained_smb(void) 70{ 71 return (chain_size != 0); 72} 73 74static void received_unlock_msg(int msg_type, struct process_id src, 75 void *buf, size_t len, 76 void *private_data); 77 78/**************************************************************************** 79 Function to push a blocking lock request onto the lock queue. 80****************************************************************************/ 81 82BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, 83 char *inbuf, int length, 84 files_struct *fsp, 85 int lock_timeout, 86 int lock_num, 87 uint32 lock_pid, 88 enum brl_type lock_type, 89 enum brl_flavour lock_flav, 90 SMB_BIG_UINT offset, 91 SMB_BIG_UINT count, 92 uint32 blocking_pid) 93{ 94 static BOOL set_lock_msg; 95 blocking_lock_record *blr; 96 NTSTATUS status; 97 98 if(in_chained_smb() ) { 99 DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); 100 return False; 101 } 102 103 /* 104 * Now queue an entry on the blocking lock queue. We setup 105 * the expiration time here. 106 */ 107 108 if((blr = SMB_MALLOC_P(blocking_lock_record)) == NULL) { 109 DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); 110 return False; 111 } 112 113 blr->next = NULL; 114 blr->prev = NULL; 115 116 if((blr->inbuf = (char *)SMB_MALLOC(length)) == NULL) { 117 DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); 118 SAFE_FREE(blr); 119 return False; 120 } 121 122 blr->com_type = CVAL(inbuf,smb_com); 123 blr->fsp = fsp; 124 if (lock_timeout == -1) { 125 blr->expire_time.tv_sec = 0; 126 blr->expire_time.tv_usec = 0; /* Never expire. */ 127 } else { 128 blr->expire_time = timeval_current_ofs(lock_timeout/1000, 129 (lock_timeout % 1000) * 1000); 130 } 131 blr->lock_num = lock_num; 132 blr->lock_pid = lock_pid; 133 blr->blocking_pid = blocking_pid; 134 blr->lock_flav = lock_flav; 135 blr->lock_type = lock_type; 136 blr->offset = offset; 137 blr->count = count; 138 memcpy(blr->inbuf, inbuf, length); 139 blr->length = length; 140 141 /* Add a pending lock record for this. */ 142 status = brl_lock(br_lck, 143 lock_pid, 144 procid_self(), 145 offset, 146 count, 147 lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK, 148 blr->lock_flav, 149 lock_timeout ? True : False, /* blocking_lock. */ 150 NULL); 151 152 if (!NT_STATUS_IS_OK(status)) { 153 DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); 154 DLIST_REMOVE(blocking_lock_queue, blr); 155 free_blocking_lock_record(blr); 156 return False; 157 } 158 159 DLIST_ADD_END(blocking_lock_queue, blr, blocking_lock_record *); 160 161 /* Ensure we'll receive messages when this is unlocked. */ 162 if (!set_lock_msg) { 163 message_register(MSG_SMB_UNLOCK, received_unlock_msg, 164 NULL); 165 set_lock_msg = True; 166 } 167 168 DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with " 169 "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n", 170 length, (unsigned int)blr->expire_time.tv_sec, 171 (unsigned int)blr->expire_time.tv_usec, lock_timeout, 172 blr->fsp->fnum, blr->fsp->fsp_name )); 173 174 /* Push the MID of this packet on the signing queue. */ 175 srv_defer_sign_response(SVAL(inbuf,smb_mid)); 176 177 return True; 178} 179 180/**************************************************************************** 181 Return a smd with a given size. 182*****************************************************************************/ 183 184static void send_blocking_reply(char *outbuf, int outsize) 185{ 186 if(outsize > 4) 187 smb_setlen(outbuf,outsize - 4); 188 189 if (!send_smb(smbd_server_fd(),outbuf)) 190 exit_server_cleanly("send_blocking_reply: send_smb failed."); 191} 192 193/**************************************************************************** 194 Return a lockingX success SMB. 195*****************************************************************************/ 196 197static void reply_lockingX_success(blocking_lock_record *blr) 198{ 199 char *outbuf = get_OutBuffer(); 200 int bufsize = BUFFER_SIZE; 201 char *inbuf = blr->inbuf; 202 int outsize = 0; 203 204 construct_reply_common(inbuf, outbuf); 205 set_message(outbuf,2,0,True); 206 207 /* 208 * As this message is a lockingX call we must handle 209 * any following chained message correctly. 210 * This is normally handled in construct_reply(), 211 * but as that calls switch_message, we can't use 212 * that here and must set up the chain info manually. 213 */ 214 215 outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); 216 217 outsize += chain_size; 218 219 send_blocking_reply(outbuf,outsize); 220} 221 222/**************************************************************************** 223 Return a generic lock fail error blocking call. 224*****************************************************************************/ 225 226static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS status) 227{ 228 char *outbuf = get_OutBuffer(); 229 char *inbuf = blr->inbuf; 230 construct_reply_common(inbuf, outbuf); 231 232 /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to 233 FILE_LOCK_CONFLICT! (tridge) */ 234 if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) { 235 status = NT_STATUS_FILE_LOCK_CONFLICT; 236 } 237 238 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { 239 /* Store the last lock error. */ 240 files_struct *fsp = blr->fsp; 241 242 fsp->last_lock_failure.context.smbpid = blr->lock_pid; 243 fsp->last_lock_failure.context.tid = fsp->conn->cnum; 244 fsp->last_lock_failure.context.pid = procid_self(); 245 fsp->last_lock_failure.start = blr->offset; 246 fsp->last_lock_failure.size = blr->count; 247 fsp->last_lock_failure.fnum = fsp->fnum; 248 fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */ 249 fsp->last_lock_failure.lock_flav = blr->lock_flav; 250 } 251 252 ERROR_NT(status); 253 if (!send_smb(smbd_server_fd(),outbuf)) { 254 exit_server_cleanly("generic_blocking_lock_error: send_smb failed."); 255 } 256} 257 258/**************************************************************************** 259 Return a lock fail error for a lockingX call. Undo all the locks we have 260 obtained first. 261*****************************************************************************/ 262 263static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) 264{ 265 char *inbuf = blr->inbuf; 266 files_struct *fsp = blr->fsp; 267 uint16 num_ulocks = SVAL(inbuf,smb_vwv6); 268 SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0; 269 uint32 lock_pid; 270 unsigned char locktype = CVAL(inbuf,smb_vwv3); 271 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); 272 char *data; 273 int i; 274 275 data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); 276 277 /* 278 * Data now points at the beginning of the list 279 * of smb_lkrng structs. 280 */ 281 282 /* 283 * Ensure we don't do a remove on the lock that just failed, 284 * as under POSIX rules, if we have a lock already there, we 285 * will delete it (and we shouldn't) ..... 286 */ 287 288 for(i = blr->lock_num - 1; i >= 0; i--) { 289 BOOL err; 290 291 lock_pid = get_lock_pid( data, i, large_file_format); 292 count = get_lock_count( data, i, large_file_format); 293 offset = get_lock_offset( data, i, large_file_format, &err); 294 295 /* 296 * We know err cannot be set as if it was the lock 297 * request would never have been queued. JRA. 298 */ 299 300 do_unlock(fsp, 301 lock_pid, 302 count, 303 offset, 304 WINDOWS_LOCK); 305 } 306 307 generic_blocking_lock_error(blr, status); 308} 309 310/**************************************************************************** 311 Return a lock fail error. 312*****************************************************************************/ 313 314static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status) 315{ 316 switch(blr->com_type) { 317 case SMBlockingX: 318 reply_lockingX_error(blr, status); 319 break; 320 case SMBtrans2: 321 case SMBtranss2: 322 { 323 char *outbuf = get_OutBuffer(); 324 char *inbuf = blr->inbuf; 325 construct_reply_common(inbuf, outbuf); 326 /* construct_reply_common has done us the favor to pre-fill the 327 * command field with SMBtranss2 which is wrong :-) 328 */ 329 SCVAL(outbuf,smb_com,SMBtrans2); 330 ERROR_NT(status); 331 if (!send_smb(smbd_server_fd(),outbuf)) { 332 exit_server_cleanly("blocking_lock_reply_error: send_smb failed."); 333 } 334 break; 335 } 336 default: 337 DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n")); 338 exit_server("PANIC - unknown type on blocking lock queue"); 339 } 340} 341 342/**************************************************************************** 343 Attempt to finish off getting all pending blocking locks for a lockingX call. 344 Returns True if we want to be removed from the list. 345*****************************************************************************/ 346 347static BOOL process_lockingX(blocking_lock_record *blr) 348{ 349 char *inbuf = blr->inbuf; 350 unsigned char locktype = CVAL(inbuf,smb_vwv3); 351 files_struct *fsp = blr->fsp; 352 uint16 num_ulocks = SVAL(inbuf,smb_vwv6); 353 uint16 num_locks = SVAL(inbuf,smb_vwv7); 354 SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; 355 uint32 lock_pid; 356 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); 357 char *data; 358 NTSTATUS status = NT_STATUS_OK; 359 360 data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); 361 362 /* 363 * Data now points at the beginning of the list 364 * of smb_lkrng structs. 365 */ 366 367 for(; blr->lock_num < num_locks; blr->lock_num++) { 368 struct byte_range_lock *br_lck = NULL; 369 BOOL err; 370 371 lock_pid = get_lock_pid( data, blr->lock_num, large_file_format); 372 count = get_lock_count( data, blr->lock_num, large_file_format); 373 offset = get_lock_offset( data, blr->lock_num, large_file_format, &err); 374 375 /* 376 * We know err cannot be set as if it was the lock 377 * request would never have been queued. JRA. 378 */ 379 errno = 0; 380 br_lck = do_lock(fsp, 381 lock_pid, 382 count, 383 offset, 384 ((locktype & LOCKING_ANDX_SHARED_LOCK) ? 385 READ_LOCK : WRITE_LOCK), 386 WINDOWS_LOCK, 387 True, 388 &status, 389 &blr->blocking_pid); 390 391 TALLOC_FREE(br_lck); 392 393 if (NT_STATUS_IS_ERR(status)) { 394 break; 395 } 396 } 397 398 if(blr->lock_num == num_locks) { 399 /* 400 * Success - we got all the locks. 401 */ 402 403 DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d num_locks=%d\n", 404 fsp->fsp_name, fsp->fnum, (unsigned int)locktype, num_locks) ); 405 406 reply_lockingX_success(blr); 407 return True; 408 } else if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && 409 !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { 410 /* 411 * We have other than a "can't get lock" 412 * error. Free any locks we had and return an error. 413 * Return True so we get dequeued. 414 */ 415 416 blocking_lock_reply_error(blr, status); 417 return True; 418 } 419 420 /* 421 * Still can't get all the locks - keep waiting. 422 */ 423 424 DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \ 425Waiting....\n", 426 blr->lock_num, num_locks, fsp->fsp_name, fsp->fnum)); 427 428 return False; 429} 430 431/**************************************************************************** 432 Attempt to get the posix lock request from a SMBtrans2 call. 433 Returns True if we want to be removed from the list. 434*****************************************************************************/ 435 436static BOOL process_trans2(blocking_lock_record *blr) 437{ 438 char *inbuf = blr->inbuf; 439 char *outbuf; 440 char params[2]; 441 NTSTATUS status; 442 struct byte_range_lock *br_lck = do_lock(blr->fsp, 443 blr->lock_pid, 444 blr->count, 445 blr->offset, 446 blr->lock_type, 447 blr->lock_flav, 448 True, 449 &status, 450 &blr->blocking_pid); 451 TALLOC_FREE(br_lck); 452 453 if (!NT_STATUS_IS_OK(status)) { 454 if (ERROR_WAS_LOCK_DENIED(status)) { 455 /* Still can't get the lock, just keep waiting. */ 456 return False; 457 } 458 /* 459 * We have other than a "can't get lock" 460 * error. Send an error and return True so we get dequeued. 461 */ 462 blocking_lock_reply_error(blr, status); 463 return True; 464 } 465 466 /* We finally got the lock, return success. */ 467 outbuf = get_OutBuffer(); 468 construct_reply_common(inbuf, outbuf); 469 SCVAL(outbuf,smb_com,SMBtrans2); 470 SSVAL(params,0,0); 471 /* Fake up max_data_bytes here - we know it fits. */ 472 send_trans2_replies(outbuf, max_send, params, 2, NULL, 0, 0xffff); 473 return True; 474} 475 476 477/**************************************************************************** 478 Process a blocking lock SMB. 479 Returns True if we want to be removed from the list. 480*****************************************************************************/ 481 482static BOOL blocking_lock_record_process(blocking_lock_record *blr) 483{ 484 switch(blr->com_type) { 485 case SMBlockingX: 486 return process_lockingX(blr); 487 case SMBtrans2: 488 case SMBtranss2: 489 return process_trans2(blr); 490 default: 491 DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); 492 exit_server("PANIC - unknown type on blocking lock queue"); 493 } 494 return False; /* Keep compiler happy. */ 495} 496 497/**************************************************************************** 498 Cancel entries by fnum from the blocking lock pending queue. 499*****************************************************************************/ 500 501void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck) 502{ 503 blocking_lock_record *blr, *next = NULL; 504 505 for(blr = blocking_lock_queue; blr; blr = next) { 506 next = blr->next; 507 if(blr->fsp->fnum == fsp->fnum) { 508 unsigned char locktype = 0; 509 510 if (blr->com_type == SMBlockingX) { 511 locktype = CVAL(blr->inbuf,smb_vwv3); 512 } 513 514 if (br_lck) { 515 DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ 516file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); 517 518 brl_lock_cancel(br_lck, 519 blr->lock_pid, 520 procid_self(), 521 blr->offset, 522 blr->count, 523 blr->lock_flav); 524 525 blocking_lock_cancel(fsp, 526 blr->lock_pid, 527 blr->offset, 528 blr->count, 529 blr->lock_flav, 530 locktype, 531 NT_STATUS_RANGE_NOT_LOCKED); 532 } 533 } 534 } 535} 536 537/**************************************************************************** 538 Delete entries by mid from the blocking lock pending queue. Always send reply. 539*****************************************************************************/ 540 541void remove_pending_lock_requests_by_mid(int mid) 542{ 543 blocking_lock_record *blr, *next = NULL; 544 545 for(blr = blocking_lock_queue; blr; blr = next) { 546 next = blr->next; 547 if(SVAL(blr->inbuf,smb_mid) == mid) { 548 files_struct *fsp = blr->fsp; 549 struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); 550 551 if (br_lck) { 552 DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ 553file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); 554 555 brl_lock_cancel(br_lck, 556 blr->lock_pid, 557 procid_self(), 558 blr->offset, 559 blr->count, 560 blr->lock_flav); 561 TALLOC_FREE(br_lck); 562 } 563 564 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); 565 DLIST_REMOVE(blocking_lock_queue, blr); 566 free_blocking_lock_record(blr); 567 } 568 } 569} 570 571/**************************************************************************** 572 Is this mid a blocking lock request on the queue ? 573*****************************************************************************/ 574 575BOOL blocking_lock_was_deferred(int mid) 576{ 577 blocking_lock_record *blr, *next = NULL; 578 579 for(blr = blocking_lock_queue; blr; blr = next) { 580 next = blr->next; 581 if(SVAL(blr->inbuf,smb_mid) == mid) { 582 return True; 583 } 584 } 585 return False; 586} 587 588/**************************************************************************** 589 Set a flag as an unlock request affects one of our pending locks. 590*****************************************************************************/ 591 592static void received_unlock_msg(int msg_type, struct process_id src, 593 void *buf, size_t len, 594 void *private_data) 595{ 596 DEBUG(10,("received_unlock_msg\n")); 597 process_blocking_lock_queue(); 598} 599 600/**************************************************************************** 601 Return the number of milliseconds to the next blocking locks timeout, or default_timeout 602*****************************************************************************/ 603 604unsigned int blocking_locks_timeout_ms(unsigned int default_timeout_ms) 605{ 606 unsigned int timeout_ms = default_timeout_ms; 607 struct timeval tv_curr; 608 SMB_BIG_INT min_tv_dif_us = default_timeout_ms * 1000; 609 blocking_lock_record *blr = blocking_lock_queue; 610 611 /* note that we avoid the GetTimeOfDay() syscall if there are no blocking locks */ 612 if (!blr) { 613 return timeout_ms; 614 } 615 616 tv_curr = timeval_current(); 617 618 for (; blr; blr = blr->next) { 619 SMB_BIG_INT tv_dif_us; 620 621 if (timeval_is_zero(&blr->expire_time)) { 622 /* 623 * If we're blocked on pid 0xFFFFFFFF this is 624 * a POSIX lock, so calculate a timeout of 625 * 10 seconds. 626 */ 627 if (blr->blocking_pid == 0xFFFFFFFF) { 628 tv_dif_us = 10 * 1000 * 1000; 629 min_tv_dif_us = MIN(min_tv_dif_us, tv_dif_us); 630 } 631 continue; /* Never timeout. */ 632 } 633 634 tv_dif_us = usec_time_diff(&blr->expire_time, &tv_curr); 635 min_tv_dif_us = MIN(min_tv_dif_us, tv_dif_us); 636 } 637 638 if (min_tv_dif_us < 0) { 639 min_tv_dif_us = 0; 640 } 641 642 timeout_ms = (unsigned int)(min_tv_dif_us / (SMB_BIG_INT)1000); 643 644 if (timeout_ms < 1) { 645 timeout_ms = 1; 646 } 647 648 DEBUG(10,("blocking_locks_timeout_ms: returning %u\n", timeout_ms)); 649 650 return timeout_ms; 651} 652 653/**************************************************************************** 654 Process the blocking lock queue. Note that this is only called as root. 655*****************************************************************************/ 656 657void process_blocking_lock_queue(void) 658{ 659 struct timeval tv_curr = timeval_current(); 660 blocking_lock_record *blr, *next = NULL; 661 662 /* 663 * Go through the queue and see if we can get any of the locks. 664 */ 665 666 for (blr = blocking_lock_queue; blr; blr = next) { 667 connection_struct *conn = NULL; 668 uint16 vuid; 669 files_struct *fsp = NULL; 670 671 next = blr->next; 672 673 /* 674 * Ensure we don't have any old chain_fsp values 675 * sitting around.... 676 */ 677 chain_size = 0; 678 file_chain_reset(); 679 fsp = blr->fsp; 680 681 conn = conn_find(SVAL(blr->inbuf,smb_tid)); 682 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : 683 SVAL(blr->inbuf,smb_uid); 684 685 DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", 686 fsp->fnum, fsp->fsp_name )); 687 688 if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { 689 struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); 690 691 /* 692 * Lock expired - throw away all previously 693 * obtained locks and return lock error. 694 */ 695 696 if (br_lck) { 697 DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", 698 fsp->fnum, fsp->fsp_name )); 699 700 brl_lock_cancel(br_lck, 701 blr->lock_pid, 702 procid_self(), 703 blr->offset, 704 blr->count, 705 blr->lock_flav); 706 TALLOC_FREE(br_lck); 707 } 708 709 blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); 710 DLIST_REMOVE(blocking_lock_queue, blr); 711 free_blocking_lock_record(blr); 712 continue; 713 } 714 715 if(!change_to_user(conn,vuid)) { 716 struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); 717 718 /* 719 * Remove the entry and return an error to the client. 720 */ 721 722 if (br_lck) { 723 brl_lock_cancel(br_lck, 724 blr->lock_pid, 725 procid_self(), 726 blr->offset, 727 blr->count, 728 blr->lock_flav); 729 TALLOC_FREE(br_lck); 730 } 731 732 DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", 733 vuid )); 734 blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); 735 DLIST_REMOVE(blocking_lock_queue, blr); 736 free_blocking_lock_record(blr); 737 continue; 738 } 739 740 if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { 741 struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); 742 743 /* 744 * Remove the entry and return an error to the client. 745 */ 746 747 if (br_lck) { 748 brl_lock_cancel(br_lck, 749 blr->lock_pid, 750 procid_self(), 751 blr->offset, 752 blr->count, 753 blr->lock_flav); 754 TALLOC_FREE(br_lck); 755 } 756 757 DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); 758 blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); 759 DLIST_REMOVE(blocking_lock_queue, blr); 760 free_blocking_lock_record(blr); 761 change_to_root_user(); 762 continue; 763 } 764 765 /* 766 * Go through the remaining locks and try and obtain them. 767 * The call returns True if all locks were obtained successfully 768 * and False if we still need to wait. 769 */ 770 771 if(blocking_lock_record_process(blr)) { 772 struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); 773 774 if (br_lck) { 775 brl_lock_cancel(br_lck, 776 blr->lock_pid, 777 procid_self(), 778 blr->offset, 779 blr->count, 780 blr->lock_flav); 781 TALLOC_FREE(br_lck); 782 } 783 784 DLIST_REMOVE(blocking_lock_queue, blr); 785 free_blocking_lock_record(blr); 786 } 787 change_to_root_user(); 788 } 789} 790 791/**************************************************************************** 792 Handle a cancel message. Lock already moved onto the cancel queue. 793*****************************************************************************/ 794 795#define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(blocking_lock_record *) + sizeof(NTSTATUS)) 796 797static void process_blocking_lock_cancel_message(int msg_type, 798 struct process_id src, 799 void *buf, size_t len, 800 void *private_data) 801{ 802 NTSTATUS err; 803 const char *msg = (const char *)buf; 804 blocking_lock_record *blr; 805 806 if (buf == NULL) { 807 smb_panic("process_blocking_lock_cancel_message: null msg\n"); 808 } 809 810 if (len != MSG_BLOCKING_LOCK_CANCEL_SIZE) { 811 DEBUG(0, ("process_blocking_lock_cancel_message: " 812 "Got invalid msg len %d\n", (int)len)); 813 smb_panic("process_blocking_lock_cancel_message: bad msg\n"); 814 } 815 816 memcpy(&blr, msg, sizeof(blr)); 817 memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS)); 818 819 DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n", 820 nt_errstr(err) )); 821 822 blocking_lock_reply_error(blr, err); 823 DLIST_REMOVE(blocking_lock_cancelled_queue, blr); 824 free_blocking_lock_record(blr); 825} 826 827/**************************************************************************** 828 Send ourselves a blocking lock cancelled message. Handled asynchronously above. 829*****************************************************************************/ 830 831BOOL blocking_lock_cancel(files_struct *fsp, 832 uint32 lock_pid, 833 SMB_BIG_UINT offset, 834 SMB_BIG_UINT count, 835 enum brl_flavour lock_flav, 836 unsigned char locktype, 837 NTSTATUS err) 838{ 839 static BOOL initialized; 840 char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE]; 841 blocking_lock_record *blr; 842 843 if (!initialized) { 844 /* Register our message. */ 845 message_register(MSG_SMB_BLOCKING_LOCK_CANCEL, 846 process_blocking_lock_cancel_message, 847 NULL); 848 849 initialized = True; 850 } 851 852 for (blr = blocking_lock_queue; blr; blr = blr->next) { 853 if (fsp == blr->fsp && 854 lock_pid == blr->lock_pid && 855 offset == blr->offset && 856 count == blr->count && 857 lock_flav == blr->lock_flav) { 858 break; 859 } 860 } 861 862 if (!blr) { 863 return False; 864 } 865 866 /* Check the flags are right. */ 867 if (blr->com_type == SMBlockingX && 868 (locktype & LOCKING_ANDX_LARGE_FILES) != 869 (CVAL(blr->inbuf,smb_vwv3) & LOCKING_ANDX_LARGE_FILES)) { 870 return False; 871 } 872 873 /* Move to cancelled queue. */ 874 DLIST_REMOVE(blocking_lock_queue, blr); 875 DLIST_ADD(blocking_lock_cancelled_queue, blr); 876 877 /* Create the message. */ 878 memcpy(msg, &blr, sizeof(blr)); 879 memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS)); 880 881 message_send_pid(pid_to_procid(sys_getpid()), 882 MSG_SMB_BLOCKING_LOCK_CANCEL, 883 &msg, sizeof(msg), True); 884 885 return True; 886} 887