Changeset 988 for vendor/current/source3/smbd/oplock.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/smbd/oplock.c
r740 r988 5 5 Copyright (C) Jeremy Allison 1998 - 2001 6 6 Copyright (C) Volker Lendecke 2005 7 7 8 8 This program is free software; you can redistribute it and/or modify 9 9 it under the terms of the GNU General Public License as published by 10 10 the Free Software Foundation; either version 3 of the License, or 11 11 (at your option) any later version. 12 12 13 13 This program is distributed in the hope that it will be useful, 14 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 16 GNU General Public License for more details. 17 17 18 18 You should have received a copy of the GNU General Public License 19 19 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 25 25 #include "smbd/globals.h" 26 26 #include "messages.h" 27 28 /**************************************************************************** 29 Get the number of current exclusive oplocks. 30 ****************************************************************************/ 31 32 int32 get_number_of_exclusive_open_oplocks(void) 33 { 34 return exclusive_oplocks_open; 35 } 27 #include "../librpc/gen_ndr/open_files.h" 36 28 37 29 /* … … 56 48 /**************************************************************************** 57 49 Attempt to set an oplock on a file. Succeeds if kernel oplocks are 58 disabled (just sets flags) and no byte-range locks in the file. Returns True 59 if oplock set. 50 disabled (just sets flags). 60 51 ****************************************************************************/ 61 52 62 bool set_file_oplock(files_struct *fsp, int oplock_type) 63 { 53 NTSTATUS set_file_oplock(files_struct *fsp) 54 { 55 struct smbd_server_connection *sconn = fsp->conn->sconn; 56 struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops; 57 bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) && koplocks; 58 64 59 if (fsp->oplock_type == LEVEL_II_OPLOCK) { 65 if ( koplocks&&60 if (use_kernel && 66 61 !(koplocks->flags & KOPLOCKS_LEVEL2_SUPPORTED)) { 67 62 DEBUG(10, ("Refusing level2 oplock, kernel oplocks " 68 63 "don't support them\n")); 69 return false;64 return NT_STATUS_NOT_SUPPORTED; 70 65 } 71 66 } 72 67 73 68 if ((fsp->oplock_type != NO_OPLOCK) && 74 (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK) && 75 koplocks && 76 !koplocks->ops->set_oplock(koplocks, fsp, oplock_type)) { 77 return False; 78 } 79 80 fsp->oplock_type = oplock_type; 69 use_kernel && 70 !koplocks->ops->set_oplock(koplocks, fsp, fsp->oplock_type)) 71 { 72 return map_nt_error_from_unix(errno); 73 } 74 81 75 fsp->sent_oplock_break = NO_BREAK_SENT; 82 if ( oplock_type == LEVEL_II_OPLOCK) {83 level_II_oplocks_open++;76 if (fsp->oplock_type == LEVEL_II_OPLOCK) { 77 sconn->oplocks.level_II_open++; 84 78 } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { 85 exclusive_oplocks_open++;79 sconn->oplocks.exclusive_open++; 86 80 } 87 81 … … 92 86 (int)fsp->open_time.tv_usec )); 93 87 94 return True;88 return NT_STATUS_OK; 95 89 } 96 90 … … 99 93 ****************************************************************************/ 100 94 101 void release_file_oplock(files_struct *fsp) 102 { 95 static void release_file_oplock(files_struct *fsp) 96 { 97 struct smbd_server_connection *sconn = fsp->conn->sconn; 98 struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops; 99 bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) && koplocks; 100 103 101 if ((fsp->oplock_type != NO_OPLOCK) && 104 (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK) && 105 koplocks) { 102 use_kernel) { 106 103 koplocks->ops->release_oplock(koplocks, fsp, NO_OPLOCK); 107 104 } 108 105 109 106 if (fsp->oplock_type == LEVEL_II_OPLOCK) { 110 level_II_oplocks_open--;107 sconn->oplocks.level_II_open--; 111 108 } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { 112 exclusive_oplocks_open--; 113 } 114 115 SMB_ASSERT(exclusive_oplocks_open>=0); 116 SMB_ASSERT(level_II_oplocks_open>=0); 117 118 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { 119 /* This doesn't matter for close. */ 120 fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; 121 } else { 122 fsp->oplock_type = NO_OPLOCK; 123 } 109 sconn->oplocks.exclusive_open--; 110 } 111 112 SMB_ASSERT(sconn->oplocks.exclusive_open>=0); 113 SMB_ASSERT(sconn->oplocks.level_II_open>=0); 114 115 fsp->oplock_type = NO_OPLOCK; 124 116 fsp->sent_oplock_break = NO_BREAK_SENT; 125 117 126 flush_write_cache(fsp, OPLOCK_RELEASE_FLUSH);118 flush_write_cache(fsp, SAMBA_OPLOCK_RELEASE_FLUSH); 127 119 delete_write_cache(fsp); 128 120 … … 136 128 static void downgrade_file_oplock(files_struct *fsp) 137 129 { 130 struct smbd_server_connection *sconn = fsp->conn->sconn; 131 struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops; 132 138 133 if (!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { 139 134 DEBUG(0, ("trying to downgrade an already-downgraded oplock!\n")); … … 145 140 } 146 141 fsp->oplock_type = LEVEL_II_OPLOCK; 147 exclusive_oplocks_open--;148 level_II_oplocks_open++;142 sconn->oplocks.exclusive_open--; 143 sconn->oplocks.level_II_open++; 149 144 fsp->sent_oplock_break = NO_BREAK_SENT; 145 146 flush_write_cache(fsp, SAMBA_OPLOCK_RELEASE_FLUSH); 147 delete_write_cache(fsp); 148 149 TALLOC_FREE(fsp->oplock_timeout); 150 } 151 152 uint32_t map_oplock_to_lease_type(uint16_t op_type) 153 { 154 uint32_t ret; 155 156 switch(op_type) { 157 case BATCH_OPLOCK: 158 case BATCH_OPLOCK|EXCLUSIVE_OPLOCK: 159 ret = SMB2_LEASE_READ|SMB2_LEASE_WRITE|SMB2_LEASE_HANDLE; 160 break; 161 case EXCLUSIVE_OPLOCK: 162 ret = SMB2_LEASE_READ|SMB2_LEASE_WRITE; 163 break; 164 case LEVEL_II_OPLOCK: 165 ret = SMB2_LEASE_READ; 166 break; 167 default: 168 ret = SMB2_LEASE_NONE; 169 break; 170 } 171 return ret; 172 } 173 174 uint32_t get_lease_type(struct share_mode_data *d, struct share_mode_entry *e) 175 { 176 if (e->op_type == LEASE_OPLOCK) { 177 return d->leases[e->lease_idx].current_state; 178 } 179 return map_oplock_to_lease_type(e->op_type); 180 } 181 182 bool update_num_read_oplocks(files_struct *fsp, struct share_mode_lock *lck) 183 { 184 struct share_mode_data *d = lck->data; 185 struct byte_range_lock *br_lck; 186 uint32_t num_read_oplocks = 0; 187 uint32_t i; 188 189 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { 190 /* 191 * If we're the only one, we don't need a brlock entry 192 */ 193 SMB_ASSERT(d->num_share_modes == 1); 194 SMB_ASSERT(EXCLUSIVE_OPLOCK_TYPE(d->share_modes[0].op_type)); 195 return true; 196 } 197 198 for (i=0; i<d->num_share_modes; i++) { 199 struct share_mode_entry *e = &d->share_modes[i]; 200 uint32_t e_lease_type = get_lease_type(d, e); 201 202 if (e_lease_type & SMB2_LEASE_READ) { 203 num_read_oplocks += 1; 204 } 205 } 206 207 br_lck = brl_get_locks_readonly(fsp); 208 if (br_lck == NULL) { 209 return false; 210 } 211 if (brl_num_read_oplocks(br_lck) == num_read_oplocks) { 212 return true; 213 } 214 215 br_lck = brl_get_locks(talloc_tos(), fsp); 216 if (br_lck == NULL) { 217 return false; 218 } 219 brl_set_num_read_oplocks(br_lck, num_read_oplocks); 220 TALLOC_FREE(br_lck); 221 return true; 150 222 } 151 223 … … 161 233 struct share_mode_lock *lck; 162 234 235 DEBUG(10, ("remove_oplock called for %s\n", 236 fsp_str_dbg(fsp))); 237 163 238 /* Remove the oplock flag from the sharemode. */ 164 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, 165 NULL); 239 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); 166 240 if (lck == NULL) { 167 241 DEBUG(0,("remove_oplock: failed to lock share entry for " … … 169 243 return False; 170 244 } 245 171 246 ret = remove_share_oplock(lck, fsp); 172 247 if (!ret) { 173 248 DEBUG(0,("remove_oplock: failed to remove share oplock for " 174 "file %s fnum %d, %s\n",175 fsp_str_dbg(fsp), fsp ->fnum,249 "file %s, %s, %s\n", 250 fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), 176 251 file_id_string_tos(&fsp->file_id))); 177 252 } 178 253 release_file_oplock(fsp); 254 255 ret = update_num_read_oplocks(fsp, lck); 256 if (!ret) { 257 DEBUG(0, ("%s: update_num_read_oplocks failed for " 258 "file %s, %s, %s\n", 259 __func__, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), 260 file_id_string_tos(&fsp->file_id))); 261 } 262 179 263 TALLOC_FREE(lck); 180 264 return ret; … … 189 273 struct share_mode_lock *lck; 190 274 191 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, 192 NULL); 275 DEBUG(10, ("downgrade_oplock called for %s\n", 276 fsp_str_dbg(fsp))); 277 278 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); 193 279 if (lck == NULL) { 194 280 DEBUG(0,("downgrade_oplock: failed to lock share entry for " … … 199 285 if (!ret) { 200 286 DEBUG(0,("downgrade_oplock: failed to downgrade share oplock " 201 "for file %s fnum %d, file_id %s\n",202 fsp_str_dbg(fsp), fsp ->fnum,287 "for file %s, %s, file_id %s\n", 288 fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), 203 289 file_id_string_tos(&fsp->file_id))); 204 290 } 205 206 291 downgrade_file_oplock(fsp); 292 293 ret = update_num_read_oplocks(fsp, lck); 294 if (!ret) { 295 DEBUG(0, ("%s: update_num_read_oplocks failed for " 296 "file %s, %s, %s\n", 297 __func__, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), 298 file_id_string_tos(&fsp->file_id))); 299 } 300 207 301 TALLOC_FREE(lck); 208 302 return ret; 209 303 } 210 304 211 /* 212 * Some kernel oplock implementations handle the notification themselves. 213 */ 214 bool should_notify_deferred_opens() 215 { 216 return !(koplocks && 217 (koplocks->flags & KOPLOCKS_DEFERRED_OPEN_NOTIFICATION)); 305 static void lease_timeout_handler(struct tevent_context *ctx, 306 struct tevent_timer *te, 307 struct timeval now, 308 void *private_data) 309 { 310 struct fsp_lease *lease = 311 talloc_get_type_abort(private_data, 312 struct fsp_lease); 313 struct files_struct *fsp; 314 struct share_mode_lock *lck; 315 uint16_t old_epoch = lease->lease.lease_epoch; 316 317 fsp = file_find_one_fsp_from_lease_key(lease->sconn, 318 &lease->lease.lease_key); 319 if (fsp == NULL) { 320 /* race? */ 321 TALLOC_FREE(lease->timeout); 322 return; 323 } 324 325 lck = get_existing_share_mode_lock( 326 talloc_tos(), fsp->file_id); 327 if (lck == NULL) { 328 /* race? */ 329 TALLOC_FREE(lease->timeout); 330 return; 331 } 332 333 fsp_lease_update(lck, fsp_client_guid(fsp), lease); 334 335 if (lease->lease.lease_epoch != old_epoch) { 336 /* 337 * If the epoch changed we need to wait for 338 * the next timeout to happen. 339 */ 340 DEBUG(10, ("lease break timeout race (epoch) for file %s - ignoring\n", 341 fsp_str_dbg(fsp))); 342 TALLOC_FREE(lck); 343 return; 344 } 345 346 if (!(lease->lease.lease_flags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)) { 347 /* 348 * If the epoch changed we need to wait for 349 * the next timeout to happen. 350 */ 351 DEBUG(10, ("lease break timeout race (flags) for file %s - ignoring\n", 352 fsp_str_dbg(fsp))); 353 TALLOC_FREE(lck); 354 return; 355 } 356 357 DEBUG(1, ("lease break timed out for file %s -- replying anyway\n", 358 fsp_str_dbg(fsp))); 359 (void)downgrade_lease(lease->sconn->client->connections, 360 1, 361 &fsp->file_id, 362 &lease->lease.lease_key, 363 SMB2_LEASE_NONE); 364 365 TALLOC_FREE(lck); 366 } 367 368 bool fsp_lease_update(struct share_mode_lock *lck, 369 const struct GUID *client_guid, 370 struct fsp_lease *lease) 371 { 372 struct share_mode_data *d = lck->data; 373 int idx; 374 struct share_mode_lease *l = NULL; 375 376 idx = find_share_mode_lease(d, client_guid, &lease->lease.lease_key); 377 if (idx != -1) { 378 l = &d->leases[idx]; 379 } 380 381 if (l == NULL) { 382 DEBUG(1, ("%s: Could not find lease entry\n", __func__)); 383 TALLOC_FREE(lease->timeout); 384 lease->lease.lease_state = SMB2_LEASE_NONE; 385 lease->lease.lease_epoch += 1; 386 lease->lease.lease_flags = 0; 387 return false; 388 } 389 390 DEBUG(10,("%s: refresh lease state\n", __func__)); 391 392 /* Ensure we're in sync with current lease state. */ 393 if (lease->lease.lease_epoch != l->epoch) { 394 DEBUG(10,("%s: cancel outdated timeout\n", __func__)); 395 TALLOC_FREE(lease->timeout); 396 } 397 lease->lease.lease_epoch = l->epoch; 398 lease->lease.lease_state = l->current_state; 399 400 if (l->breaking) { 401 lease->lease.lease_flags |= SMB2_LEASE_FLAG_BREAK_IN_PROGRESS; 402 403 if (lease->timeout == NULL) { 404 struct timeval t = timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0); 405 406 DEBUG(10,("%s: setup timeout handler\n", __func__)); 407 408 lease->timeout = tevent_add_timer(lease->sconn->ev_ctx, 409 lease, t, 410 lease_timeout_handler, 411 lease); 412 if (lease->timeout == NULL) { 413 DEBUG(0, ("%s: Could not add lease timeout handler\n", 414 __func__)); 415 } 416 } 417 } else { 418 lease->lease.lease_flags &= ~SMB2_LEASE_FLAG_BREAK_IN_PROGRESS; 419 TALLOC_FREE(lease->timeout); 420 } 421 422 return true; 423 } 424 425 struct downgrade_lease_additional_state { 426 struct tevent_immediate *im; 427 struct smbXsrv_connection *xconn; 428 uint32_t break_flags; 429 struct smb2_lease_key lease_key; 430 uint32_t break_from; 431 uint32_t break_to; 432 uint16_t new_epoch; 433 }; 434 435 static void downgrade_lease_additional_trigger(struct tevent_context *ev, 436 struct tevent_immediate *im, 437 void *private_data) 438 { 439 struct downgrade_lease_additional_state *state = 440 talloc_get_type_abort(private_data, 441 struct downgrade_lease_additional_state); 442 struct smbXsrv_connection *xconn = state->xconn; 443 NTSTATUS status; 444 445 status = smbd_smb2_send_lease_break(xconn, 446 state->new_epoch, 447 state->break_flags, 448 &state->lease_key, 449 state->break_from, 450 state->break_to); 451 TALLOC_FREE(state); 452 if (!NT_STATUS_IS_OK(status)) { 453 smbd_server_connection_terminate(xconn, 454 nt_errstr(status)); 455 return; 456 } 457 } 458 459 struct downgrade_lease_fsps_state { 460 struct file_id id; 461 struct share_mode_lock *lck; 462 const struct smb2_lease_key *key; 463 }; 464 465 static struct files_struct *downgrade_lease_fsps(struct files_struct *fsp, 466 void *private_data) 467 { 468 struct downgrade_lease_fsps_state *state = 469 (struct downgrade_lease_fsps_state *)private_data; 470 471 if (fsp->oplock_type != LEASE_OPLOCK) { 472 return NULL; 473 } 474 if (!smb2_lease_key_equal(&fsp->lease->lease.lease_key, state->key)) { 475 return NULL; 476 } 477 if (!file_id_equal(&fsp->file_id, &state->id)) { 478 return NULL; 479 } 480 481 fsp_lease_update(state->lck, fsp_client_guid(fsp), fsp->lease); 482 483 return NULL; 484 } 485 486 NTSTATUS downgrade_lease(struct smbXsrv_connection *xconn, 487 uint32_t num_file_ids, 488 const struct file_id *ids, 489 const struct smb2_lease_key *key, 490 uint32_t lease_state) 491 { 492 struct smbd_server_connection *sconn = xconn->client->sconn; 493 struct share_mode_lock *lck; 494 struct share_mode_lease *l = NULL; 495 const struct file_id id = ids[0]; 496 uint32_t i; 497 NTSTATUS status; 498 499 DEBUG(10, ("%s: Downgrading %s to %x\n", __func__, 500 file_id_string_tos(&id), (unsigned)lease_state)); 501 502 lck = get_existing_share_mode_lock(talloc_tos(), id); 503 if (lck == NULL) { 504 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 505 } 506 status = downgrade_share_lease(sconn, lck, key, lease_state, &l); 507 508 DEBUG(10, ("%s: Downgrading %s to %x => %s\n", __func__, 509 file_id_string_tos(&id), (unsigned)lease_state, nt_errstr(status))); 510 511 if (NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_BREAK_IN_PROGRESS)) { 512 struct downgrade_lease_additional_state *state; 513 514 state = talloc_zero(xconn, 515 struct downgrade_lease_additional_state); 516 if (state == NULL) { 517 TALLOC_FREE(lck); 518 return NT_STATUS_NO_MEMORY; 519 } 520 521 state->im = tevent_create_immediate(state); 522 if (state->im == NULL) { 523 TALLOC_FREE(state); 524 TALLOC_FREE(lck); 525 return NT_STATUS_NO_MEMORY; 526 } 527 528 state->xconn = xconn; 529 if (l->current_state & (~SMB2_LEASE_READ)) { 530 state->break_flags = SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED; 531 } 532 state->lease_key = l->lease_key; 533 state->break_from = l->current_state; 534 state->break_to = l->breaking_to_requested; 535 if (l->lease_version > 1) { 536 state->new_epoch = l->epoch; 537 } 538 539 if (state->break_flags == 0) { 540 /* 541 * This is an async break without 542 * SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED 543 * 544 * we need to store NONE state in the 545 * database. 546 */ 547 l->current_state = 0; 548 l->breaking_to_requested = 0; 549 l->breaking_to_required = 0; 550 l->breaking = false; 551 552 lck->data->modified = true; 553 } 554 555 tevent_schedule_immediate(state->im, xconn->ev_ctx, 556 downgrade_lease_additional_trigger, 557 state); 558 } 559 560 { 561 struct downgrade_lease_fsps_state state = { 562 .id = id, .lck = lck, .key = key, 563 }; 564 565 files_forall(sconn, downgrade_lease_fsps, &state); 566 } 567 568 TALLOC_FREE(lck); 569 DEBUG(10, ("%s: Downgrading %s to %x => %s\n", __func__, 570 file_id_string_tos(&id), (unsigned)lease_state, nt_errstr(status))); 571 572 /* 573 * Dynamic share case. Ensure other opens are copies. 574 * This will only be breaking to NONE. 575 */ 576 577 for (i = 1; i < num_file_ids; i++) { 578 lck = get_existing_share_mode_lock(talloc_tos(), ids[i]); 579 if (lck == NULL) { 580 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 581 } 582 583 { 584 struct downgrade_lease_fsps_state state = { 585 .id = ids[i], .lck = lck, .key = key, 586 }; 587 588 files_forall(sconn, downgrade_lease_fsps, &state); 589 } 590 591 DEBUG(10, ("%s: Downgrading %s to %x => %s\n", __func__, 592 file_id_string_tos(&ids[i]), (unsigned)lease_state, nt_errstr(status))); 593 594 TALLOC_FREE(lck); 595 } 596 597 return status; 218 598 } 219 599 … … 222 602 ****************************************************************************/ 223 603 224 static char *new_break_message_smb1(TALLOC_CTX *mem_ctx, 225 files_struct *fsp, int cmd) 226 { 227 char *result = TALLOC_ARRAY(mem_ctx, char, smb_size + 8*2 + 0); 228 229 if (result == NULL) { 230 DEBUG(0, ("talloc failed\n")); 231 return NULL; 232 } 233 604 #define SMB1_BREAK_MESSAGE_LENGTH (smb_size + 8*2) 605 606 static void new_break_message_smb1(files_struct *fsp, int cmd, 607 char result[SMB1_BREAK_MESSAGE_LENGTH]) 608 { 234 609 memset(result,'\0',smb_size); 235 610 srv_set_message(result,8,0,true); … … 243 618 SCVAL(result,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); 244 619 SCVAL(result,smb_vwv3+1,cmd); 245 return result;246 620 } 247 621 … … 269 643 files_struct *fsp = NULL; 270 644 271 if( DEBUGLVL( 3 ) ) { 272 dbgtext( "initial_break_processing: called for %s/%u\n", 273 file_id_string_tos(&id), (int)file_id); 274 dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n", 275 exclusive_oplocks_open, level_II_oplocks_open ); 276 } 645 DEBUG(3, ("initial_break_processing: called for %s/%u\n" 646 "Current oplocks_open (exclusive = %d, levelII = %d)\n", 647 file_id_string_tos(&id), (int)file_id, 648 sconn->oplocks.exclusive_open, 649 sconn->oplocks.level_II_open)); 277 650 278 651 /* … … 286 659 if(fsp == NULL) { 287 660 /* The file could have been closed in the meantime - return success. */ 288 if( DEBUGLVL( 3 ) ) { 289 dbgtext( "initial_break_processing: cannot find open file with " ); 290 dbgtext( "file_id %s gen_id = %lu", file_id_string_tos(&id), file_id); 291 dbgtext( "allowing break to succeed.\n" ); 292 } 661 DEBUG(3, ("initial_break_processing: cannot find open file " 662 "with file_id %s gen_id = %lu, allowing break to " 663 "succeed.\n", file_id_string_tos(&id), file_id)); 293 664 return NULL; 294 665 } … … 305 676 306 677 if(fsp->oplock_type == NO_OPLOCK) { 307 if( DEBUGLVL( 3 ) ) { 308 dbgtext( "initial_break_processing: file %s ", 309 fsp_str_dbg(fsp)); 310 dbgtext( "(file_id = %s gen_id = %lu) has no oplock.\n", 311 file_id_string_tos(&id), fsp->fh->gen_id ); 312 dbgtext( "Allowing break to succeed regardless.\n" ); 313 } 678 DEBUG(3, ("initial_break_processing: file %s (file_id = %s " 679 "gen_id = %lu) has no oplock. Allowing break to " 680 "succeed regardless.\n", fsp_str_dbg(fsp), 681 file_id_string_tos(&id), fsp->fh->gen_id)); 314 682 return NULL; 315 683 } … … 318 686 } 319 687 320 static void oplock_timeout_handler(struct event_context *ctx,321 struct t imed_event*te,688 static void oplock_timeout_handler(struct tevent_context *ctx, 689 struct tevent_timer *te, 322 690 struct timeval now, 323 691 void *private_data) 324 692 { 325 693 files_struct *fsp = (files_struct *)private_data; 694 695 SMB_ASSERT(fsp->sent_oplock_break != NO_BREAK_SENT); 326 696 327 697 /* Remove the timed event handler. */ … … 330 700 fsp_str_dbg(fsp))); 331 701 remove_oplock(fsp); 332 reply_to_oplock_break_requests(fsp);333 702 } 334 703 … … 339 708 static void add_oplock_timeout_handler(files_struct *fsp) 340 709 { 710 struct smbd_server_connection *sconn = fsp->conn->sconn; 711 struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops; 712 341 713 /* 342 714 * If kernel oplocks already notifies smbds when an oplock break times … … 354 726 355 727 fsp->oplock_timeout = 356 event_add_timed(smbd_event_context(), fsp,357 timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),358 oplock_timeout_handler, fsp);728 tevent_add_timer(fsp->conn->sconn->ev_ctx, fsp, 729 timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0), 730 oplock_timeout_handler, fsp); 359 731 360 732 if (fsp->oplock_timeout == NULL) { … … 365 737 static void send_break_message_smb1(files_struct *fsp, int level) 366 738 { 367 char *break_msg = new_break_message_smb1(talloc_tos(), 368 fsp, 369 level); 370 if (break_msg == NULL) { 371 exit_server("Could not talloc break_msg\n"); 372 } 739 struct smbXsrv_connection *xconn = NULL; 740 char break_msg[SMB1_BREAK_MESSAGE_LENGTH]; 741 742 /* 743 * For SMB1 we only have one connection 744 */ 745 xconn = fsp->conn->sconn->client->connections; 746 747 new_break_message_smb1(fsp, level, break_msg); 373 748 374 749 show_msg(break_msg); 375 if (!srv_send_smb( fsp->conn->sconn,750 if (!srv_send_smb(xconn, 376 751 break_msg, false, 0, 377 752 IS_CONN_ENCRYPTED(fsp->conn), … … 380 755 "srv_send_smb failed."); 381 756 } 382 383 TALLOC_FREE(break_msg);384 }385 386 void break_level2_to_none_async(files_struct *fsp)387 {388 struct smbd_server_connection *sconn = fsp->conn->sconn;389 390 if (fsp->oplock_type == NO_OPLOCK) {391 /* We already got a "break to none" message and we've handled392 * it. just ignore. */393 DEBUG(3, ("process_oplock_async_level2_break_message: already "394 "broken to none, ignoring.\n"));395 return;396 }397 398 if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) {399 /* Don't tell the client, just downgrade. */400 DEBUG(3, ("process_oplock_async_level2_break_message: "401 "downgrading fake level 2 oplock.\n"));402 remove_oplock(fsp);403 return;404 }405 406 /* Ensure we're really at level2 state. */407 SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK);408 409 DEBUG(10,("process_oplock_async_level2_break_message: sending break "410 "to none message for fid %d, file %s\n", fsp->fnum,411 fsp_str_dbg(fsp)));412 413 /* Now send a break to none message to our client. */414 if (sconn->using_smb2) {415 send_break_message_smb2(fsp, OPLOCKLEVEL_NONE);416 } else {417 send_break_message_smb1(fsp, OPLOCKLEVEL_NONE);418 }419 420 /* Async level2 request, don't send a reply, just remove the oplock. */421 remove_oplock(fsp);422 }423 424 /*******************************************************************425 This handles the case of a write triggering a break to none426 message on a level2 oplock.427 When we get this message we may be in any of three states :428 NO_OPLOCK, LEVEL_II, FAKE_LEVEL2. We only send a message to429 the client for LEVEL2.430 *******************************************************************/431 432 void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx,433 void *private_data,434 uint32_t msg_type,435 struct server_id src,436 DATA_BLOB *data)437 {438 struct smbd_server_connection *sconn;439 struct share_mode_entry msg;440 files_struct *fsp;441 442 if (data->data == NULL) {443 DEBUG(0, ("Got NULL buffer\n"));444 return;445 }446 447 sconn = msg_ctx_to_sconn(msg_ctx);448 if (sconn == NULL) {449 DEBUG(1, ("could not find sconn\n"));450 return;451 }452 453 if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {454 DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));455 return;456 }457 458 /* De-linearize incoming message. */459 message_to_share_mode_entry(&msg, (char *)data->data);460 461 DEBUG(10, ("Got oplock async level 2 break message from pid %s: "462 "%s/%lu\n", procid_str(talloc_tos(), &src),463 file_id_string_tos(&msg.id), msg.share_file_id));464 465 fsp = initial_break_processing(sconn, msg.id, msg.share_file_id);466 467 if (fsp == NULL) {468 /* We hit a race here. Break messages are sent, and before we469 * get to process this message, we have closed the file.470 * No need to reply as this is an async message. */471 DEBUG(3, ("process_oplock_async_level2_break_message: Did not find fsp, ignoring\n"));472 return;473 }474 475 break_level2_to_none_async(fsp);476 757 } 477 758 … … 486 767 DATA_BLOB *data) 487 768 { 488 struct smbd_server_connection *sconn;489 769 struct share_mode_entry msg; 490 770 files_struct *fsp; 491 bool break_to_level2 = False; 771 bool use_kernel; 772 struct smbd_server_connection *sconn = 773 talloc_get_type_abort(private_data, 774 struct smbd_server_connection); 775 struct server_id self = messaging_server_id(sconn->msg_ctx); 776 struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops; 777 uint16_t break_from; 778 uint16_t break_to; 779 bool break_needed = true; 780 struct server_id_buf tmp; 492 781 493 782 if (data->data == NULL) { … … 496 785 } 497 786 498 sconn = msg_ctx_to_sconn(msg_ctx);499 if (sconn == NULL) {500 DEBUG(1, ("could not find sconn\n"));501 return;502 }503 504 787 if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { 505 788 DEBUG(0, ("Got invalid msg len %d\n", (int)data->length)); … … 509 792 /* De-linearize incoming message. */ 510 793 message_to_share_mode_entry(&msg, (char *)data->data); 511 512 DEBUG(10, ("Got oplock break message from pid %s: %s/%lu\n", 513 procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id), 514 msg.share_file_id)); 794 break_to = msg.op_type; 795 796 DEBUG(10, ("Got oplock break to %u message from pid %s: %s/%llu\n", 797 (unsigned)break_to, server_id_str_buf(src, &tmp), 798 file_id_string_tos(&msg.id), 799 (unsigned long long)msg.share_file_id)); 515 800 516 801 fsp = initial_break_processing(sconn, msg.id, msg.share_file_id); … … 518 803 if (fsp == NULL) { 519 804 /* We hit a race here. Break messages are sent, and before we 520 * get to process this message, we have closed the file. Reply 521 * with 'ok, oplock broken' */ 805 * get to process this message, we have closed the file. */ 522 806 DEBUG(3, ("Did not find fsp\n")); 523 524 /* We just send the same message back. */ 525 messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE, 526 (uint8 *)data->data, 527 MSG_SMB_SHARE_MODE_ENTRY_SIZE); 528 return; 529 } 530 531 if (fsp->sent_oplock_break != NO_BREAK_SENT) { 532 /* Remember we have to inform the requesting PID when the 533 * client replies */ 534 msg.pid = src; 535 ADD_TO_ARRAY(NULL, struct share_mode_entry, msg, 536 &fsp->pending_break_messages, 537 &fsp->num_pending_break_messages); 538 return; 539 } 540 541 if (EXCLUSIVE_OPLOCK_TYPE(msg.op_type) && 542 !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { 543 DEBUG(3, ("Already downgraded oplock on %s: %s\n", 807 return; 808 } 809 810 break_from = fsp_lease_type(fsp); 811 812 if (fsp->oplock_type != LEASE_OPLOCK) { 813 if (fsp->sent_oplock_break != NO_BREAK_SENT) { 814 /* 815 * Nothing to do anymore 816 */ 817 DEBUG(10, ("fsp->sent_oplock_break = %d\n", 818 fsp->sent_oplock_break)); 819 return; 820 } 821 } 822 823 if (!(global_client_caps & CAP_LEVEL_II_OPLOCKS)) { 824 DEBUG(10, ("client_caps without level2 oplocks\n")); 825 break_to &= ~SMB2_LEASE_READ; 826 } 827 828 use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) && koplocks; 829 if (use_kernel && !(koplocks->flags & KOPLOCKS_LEVEL2_SUPPORTED)) { 830 DEBUG(10, ("Kernel oplocks don't allow level2\n")); 831 break_to &= ~SMB2_LEASE_READ; 832 } 833 834 if (!lp_level2_oplocks(SNUM(fsp->conn))) { 835 DEBUG(10, ("no level2 oplocks by config\n")); 836 break_to &= ~SMB2_LEASE_READ; 837 } 838 839 if (fsp->oplock_type == LEASE_OPLOCK) { 840 struct share_mode_lock *lck; 841 int idx; 842 843 lck = get_existing_share_mode_lock( 844 talloc_tos(), fsp->file_id); 845 if (lck == NULL) { 846 /* 847 * We hit a race here. Break messages are sent, and 848 * before we get to process this message, we have closed 849 * the file. 850 */ 851 DEBUG(3, ("Did not find share_mode\n")); 852 return; 853 } 854 855 idx = find_share_mode_lease( 856 lck->data, 857 fsp_client_guid(fsp), 858 &fsp->lease->lease.lease_key); 859 if (idx != -1) { 860 struct share_mode_lease *l; 861 l = &lck->data->leases[idx]; 862 863 break_from = l->current_state; 864 break_to &= l->current_state; 865 866 if (l->breaking) { 867 break_to &= l->breaking_to_required; 868 if (l->breaking_to_required != break_to) { 869 /* 870 * Note we don't increment the epoch 871 * here, which might be a bug in 872 * Windows too... 873 */ 874 l->breaking_to_required = break_to; 875 lck->data->modified = true; 876 } 877 break_needed = false; 878 } else if (l->current_state == break_to) { 879 break_needed = false; 880 } else if (l->current_state == SMB2_LEASE_READ) { 881 l->current_state = SMB2_LEASE_NONE; 882 /* Need to increment the epoch */ 883 l->epoch += 1; 884 lck->data->modified = true; 885 } else { 886 l->breaking = true; 887 l->breaking_to_required = break_to; 888 l->breaking_to_requested = break_to; 889 /* Need to increment the epoch */ 890 l->epoch += 1; 891 lck->data->modified = true; 892 } 893 894 /* Ensure we're in sync with current lease state. */ 895 fsp_lease_update(lck, fsp_client_guid(fsp), fsp->lease); 896 } 897 898 TALLOC_FREE(lck); 899 } 900 901 if (!break_needed) { 902 DEBUG(10,("%s: skip break\n", __func__)); 903 return; 904 } 905 906 if ((break_from == SMB2_LEASE_NONE) && !break_needed) { 907 DEBUG(3, ("Already downgraded oplock to none on %s: %s\n", 544 908 file_id_string_tos(&fsp->file_id), 545 909 fsp_str_dbg(fsp))); 546 /* We just send the same message back. */547 messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE,548 (uint8 *)data->data, 549 MSG_SMB_SHARE_MODE_ENTRY_SIZE);550 return;551 } 552 553 if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) &&554 !(msg.op_type & FORCE_OPLOCK_BREAK_TO_NONE) &&555 !(koplocks && !(koplocks->flags & KOPLOCKS_LEVEL2_SUPPORTED)) &&556 lp_level2_oplocks(SNUM(fsp->conn))) {557 break_to_level2 = True;910 return; 911 } 912 913 DEBUG(10, ("break_from=%u, break_to=%u\n", 914 (unsigned)break_from, (unsigned)break_to)); 915 916 if ((break_from == break_to) && !break_needed) { 917 DEBUG(3, ("Already downgraded oplock to %u on %s: %s\n", 918 (unsigned)break_to, 919 file_id_string_tos(&fsp->file_id), 920 fsp_str_dbg(fsp))); 921 return; 558 922 } 559 923 560 924 /* Need to wait before sending a break 561 925 message if we sent ourselves this message. */ 562 if ( procid_is_me(&src)) {926 if (serverid_equal(&self, &src)) { 563 927 wait_before_sending_break(); 564 928 } 565 929 566 930 if (sconn->using_smb2) { 567 send_break_message_smb2(fsp, break_to_level2 ? 568 OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); 931 send_break_message_smb2(fsp, break_from, break_to); 569 932 } else { 570 send_break_message_smb1(fsp, break_to_level2 ? 571 OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); 572 } 573 574 fsp->sent_oplock_break = break_to_level2 ? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; 575 576 msg.pid = src; 577 ADD_TO_ARRAY(NULL, struct share_mode_entry, msg, 578 &fsp->pending_break_messages, 579 &fsp->num_pending_break_messages); 933 send_break_message_smb1(fsp, (break_to & SMB2_LEASE_READ) ? 934 OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); 935 } 936 937 if ((break_from == SMB2_LEASE_READ) && 938 (break_to == SMB2_LEASE_NONE)) { 939 /* 940 * This is an async break without a reply and thus no timeout 941 * 942 * leases are handled above. 943 */ 944 if (fsp->oplock_type != LEASE_OPLOCK) { 945 remove_oplock(fsp); 946 } 947 return; 948 } 949 if (fsp->oplock_type == LEASE_OPLOCK) { 950 return; 951 } 952 953 fsp->sent_oplock_break = (break_to & SMB2_LEASE_READ) ? 954 LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; 580 955 581 956 add_oplock_timeout_handler(fsp); … … 592 967 DATA_BLOB *data) 593 968 { 594 struct smbd_server_connection *sconn;595 969 struct file_id id; 596 970 unsigned long file_id; 597 971 files_struct *fsp; 972 struct smbd_server_connection *sconn = 973 talloc_get_type_abort(private_data, 974 struct smbd_server_connection); 975 struct server_id_buf tmp; 598 976 599 977 if (data->data == NULL) { … … 604 982 if (data->length != MSG_SMB_KERNEL_BREAK_SIZE) { 605 983 DEBUG(0, ("Got invalid msg len %d\n", (int)data->length)); 606 return;607 }608 609 sconn = msg_ctx_to_sconn(msg_ctx);610 if (sconn == NULL) {611 DEBUG(1, ("could not find sconn\n"));612 984 return; 613 985 } … … 618 990 619 991 DEBUG(10, ("Got kernel oplock break message from pid %s: %s/%u\n", 620 procid_str(talloc_tos(), &src), file_id_string_tos(&id),992 server_id_str_buf(src, &tmp), file_id_string_tos(&id), 621 993 (unsigned int)file_id)); 622 994 … … 637 1009 638 1010 if (sconn->using_smb2) { 639 send_break_message_smb2(fsp, OPLOCKLEVEL_NONE);1011 send_break_message_smb2(fsp, 0, OPLOCKLEVEL_NONE); 640 1012 } else { 641 1013 send_break_message_smb1(fsp, OPLOCKLEVEL_NONE); … … 647 1019 } 648 1020 649 void reply_to_oplock_break_requests(files_struct *fsp) 650 { 651 int i; 652 653 /* 654 * If kernel oplocks already notifies smbds when oplocks are 655 * broken/removed, just return. 656 */ 657 if (koplocks && 658 (koplocks->flags & KOPLOCKS_OPLOCK_BROKEN_NOTIFICATION)) { 659 return; 660 } 661 662 for (i=0; i<fsp->num_pending_break_messages; i++) { 663 struct share_mode_entry *e = &fsp->pending_break_messages[i]; 664 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; 665 666 share_mode_entry_to_message(msg, e); 667 668 messaging_send_buf(fsp->conn->sconn->msg_ctx, e->pid, 669 MSG_SMB_BREAK_RESPONSE, 670 (uint8 *)msg, 671 MSG_SMB_SHARE_MODE_ENTRY_SIZE); 672 } 673 674 SAFE_FREE(fsp->pending_break_messages); 675 fsp->num_pending_break_messages = 0; 676 if (fsp->oplock_timeout != NULL) { 677 /* Remove the timed event handler. */ 678 TALLOC_FREE(fsp->oplock_timeout); 679 fsp->oplock_timeout = NULL; 680 } 681 return; 682 } 683 684 static void process_oplock_break_response(struct messaging_context *msg_ctx, 685 void *private_data, 686 uint32_t msg_type, 687 struct server_id src, 688 DATA_BLOB *data) 689 { 690 struct share_mode_entry msg; 691 692 if (data->data == NULL) { 693 DEBUG(0, ("Got NULL buffer\n")); 694 return; 695 } 696 697 if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { 698 DEBUG(0, ("Got invalid msg len %u\n", 699 (unsigned int)data->length)); 700 return; 701 } 702 703 /* De-linearize incoming message. */ 704 message_to_share_mode_entry(&msg, (char *)data->data); 705 706 DEBUG(10, ("Got oplock break response from pid %s: %s/%lu mid %llu\n", 707 procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id), 708 msg.share_file_id, (unsigned long long)msg.op_mid)); 709 710 schedule_deferred_open_message_smb(msg.op_mid); 711 } 712 713 static void process_open_retry_message(struct messaging_context *msg_ctx, 714 void *private_data, 715 uint32_t msg_type, 716 struct server_id src, 717 DATA_BLOB *data) 718 { 719 struct share_mode_entry msg; 720 721 if (data->data == NULL) { 722 DEBUG(0, ("Got NULL buffer\n")); 723 return; 724 } 725 726 if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { 727 DEBUG(0, ("Got invalid msg len %d\n", (int)data->length)); 728 return; 729 } 730 731 /* De-linearize incoming message. */ 732 message_to_share_mode_entry(&msg, (char *)data->data); 733 734 DEBUG(10, ("Got open retry msg from pid %s: %s mid %llu\n", 735 procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id), 736 (unsigned long long)msg.op_mid)); 737 738 schedule_deferred_open_message_smb(msg.op_mid); 739 } 1021 struct break_to_none_state { 1022 struct smbd_server_connection *sconn; 1023 struct file_id id; 1024 struct smb2_lease_key lease_key; 1025 struct GUID client_guid; 1026 }; 1027 static void do_break_to_none(struct tevent_context *ctx, 1028 struct tevent_immediate *im, 1029 void *private_data); 740 1030 741 1031 /**************************************************************************** … … 748 1038 enum level2_contention_type type) 749 1039 { 750 int i; 751 struct share_mode_lock *lck; 1040 struct smbd_server_connection *sconn = fsp->conn->sconn; 1041 struct tevent_immediate *im; 1042 struct break_to_none_state *state; 1043 struct byte_range_lock *brl; 1044 uint32_t num_read_oplocks = 0; 752 1045 753 1046 /* … … 759 1052 */ 760 1053 761 if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) 762 return; 763 764 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, 765 NULL); 1054 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { 1055 /* 1056 * There can't be any level2 oplocks, we're alone. 1057 */ 1058 return; 1059 } 1060 1061 brl = brl_get_locks_readonly(fsp); 1062 if (brl != NULL) { 1063 num_read_oplocks = brl_num_read_oplocks(brl); 1064 } 1065 1066 DEBUG(10, ("num_read_oplocks = %"PRIu32"\n", num_read_oplocks)); 1067 1068 if (num_read_oplocks == 0) { 1069 DEBUG(10, ("No read oplocks around\n")); 1070 return; 1071 } 1072 1073 /* 1074 * When we get here we might have a brlock entry locked. Also 1075 * locking the share mode entry would violate the locking 1076 * order. Breaking level2 oplocks to none is asynchronous 1077 * anyway, so we postpone this into an immediate event. 1078 */ 1079 1080 state = talloc_zero(sconn, struct break_to_none_state); 1081 if (state == NULL) { 1082 DEBUG(1, ("talloc failed\n")); 1083 return; 1084 } 1085 state->sconn = sconn; 1086 state->id = fsp->file_id; 1087 1088 if (fsp->oplock_type == LEASE_OPLOCK) { 1089 state->client_guid = *fsp_client_guid(fsp); 1090 state->lease_key = fsp->lease->lease.lease_key; 1091 DEBUG(10, ("Breaking through lease key %"PRIu64"/%"PRIu64"\n", 1092 state->lease_key.data[0], 1093 state->lease_key.data[1])); 1094 } 1095 1096 im = tevent_create_immediate(state); 1097 if (im == NULL) { 1098 DEBUG(1, ("tevent_create_immediate failed\n")); 1099 TALLOC_FREE(state); 1100 return; 1101 } 1102 tevent_schedule_immediate(im, sconn->ev_ctx, do_break_to_none, state); 1103 } 1104 1105 static void send_break_to_none(struct messaging_context *msg_ctx, 1106 const struct share_mode_entry *e) 1107 { 1108 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; 1109 1110 share_mode_entry_to_message(msg, e); 1111 /* Overload entry->op_type */ 1112 SSVAL(msg, OP_BREAK_MSG_OP_TYPE_OFFSET, NO_OPLOCK); 1113 1114 messaging_send_buf(msg_ctx, e->pid, MSG_SMB_BREAK_REQUEST, 1115 (uint8_t *)msg, sizeof(msg)); 1116 } 1117 1118 static void do_break_to_none(struct tevent_context *ctx, 1119 struct tevent_immediate *im, 1120 void *private_data) 1121 { 1122 struct break_to_none_state *state = talloc_get_type_abort( 1123 private_data, struct break_to_none_state); 1124 uint32_t i; 1125 struct share_mode_lock *lck; 1126 struct share_mode_data *d; 1127 1128 lck = get_existing_share_mode_lock(talloc_tos(), state->id); 766 1129 if (lck == NULL) { 767 DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " 768 "share mode entry for file %s.\n", fsp_str_dbg(fsp))); 769 return; 770 } 771 772 DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n", 773 lck->num_share_modes )); 774 775 for(i = 0; i < lck->num_share_modes; i++) { 776 struct share_mode_entry *share_entry = &lck->share_modes[i]; 777 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; 778 779 if (!is_valid_share_mode_entry(share_entry)) { 1130 DEBUG(1, ("%s: failed to lock share mode entry for file %s.\n", 1131 __func__, file_id_string_tos(&state->id))); 1132 goto done; 1133 } 1134 d = lck->data; 1135 1136 /* 1137 * Walk leases and oplocks separately: We have to send one break per 1138 * lease. If we have multiple share_mode_entry having a common lease, 1139 * we would break the lease twice if we don't walk the leases list 1140 * separately. 1141 */ 1142 1143 for (i=0; i<d->num_leases; i++) { 1144 struct share_mode_lease *l = &d->leases[i]; 1145 struct share_mode_entry *e; 1146 uint32_t j; 1147 1148 if ((l->current_state & SMB2_LEASE_READ) == 0) { 1149 continue; 1150 } 1151 if (smb2_lease_equal(&state->client_guid, 1152 &state->lease_key, 1153 &l->client_guid, 1154 &l->lease_key)) { 1155 DEBUG(10, ("Don't break our own lease\n")); 1156 continue; 1157 } 1158 1159 for (j=0; j<d->num_share_modes; j++) { 1160 e = &d->share_modes[j]; 1161 1162 if (!is_valid_share_mode_entry(e)) { 1163 continue; 1164 } 1165 if (e->lease_idx == i) { 1166 break; 1167 } 1168 } 1169 if (j == d->num_share_modes) { 1170 DEBUG(0, ("leases[%"PRIu32"] has no share mode\n", 1171 i)); 1172 continue; 1173 } 1174 1175 DEBUG(10, ("Breaking lease# %"PRIu32" with share_entry# " 1176 "%"PRIu32"\n", i, j)); 1177 1178 send_break_to_none(state->sconn->msg_ctx, e); 1179 } 1180 1181 for(i = 0; i < d->num_share_modes; i++) { 1182 struct share_mode_entry *e = &d->share_modes[i]; 1183 1184 if (!is_valid_share_mode_entry(e)) { 1185 continue; 1186 } 1187 if (e->op_type == LEASE_OPLOCK) { 1188 /* 1189 * Took care of those in the loop above 1190 */ 780 1191 continue; 781 1192 } … … 785 1196 * lock_share_entry gate we may not be the first to 786 1197 * enter. Hence the state of the op_types in the share mode 787 * entries may be partly NO_OPLOCK and partly LEVEL_II or FAKE_LEVEL_II1198 * entries may be partly NO_OPLOCK and partly LEVEL_II 788 1199 * oplock. It will do no harm to re-send break messages to 789 1200 * those smbd's that are still waiting their turn to remove … … 792 1203 */ 793 1204 794 DEBUG(10,("release_level_2_oplocks_on_change: " 795 "share_entry[%i]->op_type == %d\n", 796 i, share_entry->op_type )); 797 798 if (share_entry->op_type == NO_OPLOCK) { 1205 DEBUG(10, ("%s: share_entry[%i]->op_type == %d\n", __func__, 1206 i, e->op_type )); 1207 1208 if (e->op_type == NO_OPLOCK) { 799 1209 continue; 800 1210 } 801 1211 802 1212 /* Paranoia .... */ 803 if (EXCLUSIVE_OPLOCK_TYPE( share_entry->op_type)) {804 DEBUG(0,(" release_level_2_oplocks_on_change: PANIC. "805 "share mode entry %d is an ex lusive "806 "oplock !\n", i ));1213 if (EXCLUSIVE_OPLOCK_TYPE(e->op_type)) { 1214 DEBUG(0,("%s: PANIC. " 1215 "share mode entry %d is an exclusive " 1216 "oplock !\n", __func__, i )); 807 1217 TALLOC_FREE(lck); 808 1218 abort(); 809 1219 } 810 1220 811 share_mode_entry_to_message(msg, share_entry); 812 813 /* 814 * Deal with a race condition when breaking level2 815 * oplocks. Don't send all the messages and release 816 * the lock, this allows someone else to come in and 817 * get a level2 lock before any of the messages are 818 * processed, and thus miss getting a break message. 819 * Ensure at least one entry (the one we're breaking) 820 * is processed immediately under the lock and becomes 821 * set as NO_OPLOCK to stop any waiter getting a level2. 822 * Bugid #5980. 823 */ 824 825 if (procid_is_me(&share_entry->pid)) { 826 struct files_struct *cur_fsp = 827 initial_break_processing(fsp->conn->sconn, 828 share_entry->id, 829 share_entry->share_file_id); 830 wait_before_sending_break(); 831 if (cur_fsp != NULL) { 832 break_level2_to_none_async(cur_fsp); 833 } else { 834 DEBUG(3, ("release_level_2_oplocks_on_change: " 835 "Did not find fsp, ignoring\n")); 836 } 837 } else { 838 messaging_send_buf(fsp->conn->sconn->msg_ctx, 839 share_entry->pid, 840 MSG_SMB_ASYNC_LEVEL2_BREAK, 841 (uint8 *)msg, 842 MSG_SMB_SHARE_MODE_ENTRY_SIZE); 843 } 1221 send_break_to_none(state->sconn->msg_ctx, e); 844 1222 } 845 1223 … … 848 1226 849 1227 TALLOC_FREE(lck); 850 } 851 852 void contend_level2_oplocks_begin(files_struct *fsp, 1228 done: 1229 TALLOC_FREE(state); 1230 return; 1231 } 1232 1233 void smbd_contend_level2_oplocks_begin(files_struct *fsp, 853 1234 enum level2_contention_type type) 854 1235 { 1236 struct smbd_server_connection *sconn = fsp->conn->sconn; 1237 struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops; 1238 855 1239 if (koplocks && koplocks->ops->contend_level2_oplocks_begin) { 856 1240 koplocks->ops->contend_level2_oplocks_begin(fsp, type); … … 861 1245 } 862 1246 863 void contend_level2_oplocks_end(files_struct *fsp,1247 void smbd_contend_level2_oplocks_end(files_struct *fsp, 864 1248 enum level2_contention_type type) 865 1249 { 1250 struct smbd_server_connection *sconn = fsp->conn->sconn; 1251 struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops; 1252 866 1253 /* Only kernel oplocks implement this so far */ 867 1254 if (koplocks && koplocks->ops->contend_level2_oplocks_end) { … … 876 1263 void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e) 877 1264 { 878 SIVAL(msg,OP_BREAK_MSG_PID_OFFSET,(uint32 )e->pid.pid);1265 SIVAL(msg,OP_BREAK_MSG_PID_OFFSET,(uint32_t)e->pid.pid); 879 1266 SBVAL(msg,OP_BREAK_MSG_MID_OFFSET,e->op_mid); 880 1267 SSVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET,e->op_type); … … 896 1283 ****************************************************************************/ 897 1284 898 void message_to_share_mode_entry(struct share_mode_entry *e, c har *msg)1285 void message_to_share_mode_entry(struct share_mode_entry *e, const char *msg) 899 1286 { 900 1287 e->pid.pid = (pid_t)IVAL(msg,OP_BREAK_MSG_PID_OFFSET); … … 908 1295 pull_file_id_24(msg+OP_BREAK_MSG_DEV_OFFSET, &e->id); 909 1296 e->share_file_id = (unsigned long)IVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET); 910 e->uid = (uint32 )IVAL(msg,OP_BREAK_MSG_UID_OFFSET);911 e->flags = (uint16 )SVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET);1297 e->uid = (uint32_t)IVAL(msg,OP_BREAK_MSG_UID_OFFSET); 1298 e->flags = (uint16_t)SVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET); 912 1299 e->name_hash = IVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET); 913 1300 e->pid.vnn = IVAL(msg,OP_BREAK_MSG_VNN_OFFSET); … … 918 1305 ****************************************************************************/ 919 1306 920 bool init_oplocks(struct messaging_context *msg_ctx)1307 bool init_oplocks(struct smbd_server_connection *sconn) 921 1308 { 922 1309 DEBUG(3,("init_oplocks: initializing messages.\n")); 923 1310 924 messaging_register( msg_ctx, NULL, MSG_SMB_BREAK_REQUEST,1311 messaging_register(sconn->msg_ctx, sconn, MSG_SMB_BREAK_REQUEST, 925 1312 process_oplock_break_message); 926 messaging_register(msg_ctx, NULL, MSG_SMB_ASYNC_LEVEL2_BREAK, 927 process_oplock_async_level2_break_message); 928 messaging_register(msg_ctx, NULL, MSG_SMB_BREAK_RESPONSE, 929 process_oplock_break_response); 930 messaging_register(msg_ctx, NULL, MSG_SMB_KERNEL_BREAK, 1313 messaging_register(sconn->msg_ctx, sconn, MSG_SMB_KERNEL_BREAK, 931 1314 process_kernel_oplock_break); 932 messaging_register(msg_ctx, NULL, MSG_SMB_OPEN_RETRY, 933 process_open_retry_message); 934 935 if (lp_kernel_oplocks()) { 1315 return true; 1316 } 1317 1318 void init_kernel_oplocks(struct smbd_server_connection *sconn) 1319 { 1320 struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops; 1321 1322 /* only initialize once */ 1323 if (koplocks == NULL) { 936 1324 #if HAVE_KERNEL_OPLOCKS_IRIX 937 koplocks = irix_init_kernel_oplocks( NULL);1325 koplocks = irix_init_kernel_oplocks(sconn); 938 1326 #elif HAVE_KERNEL_OPLOCKS_LINUX 939 koplocks = linux_init_kernel_oplocks(NULL); 940 #elif HAVE_ONEFS 941 #error Isilon, please check if the NULL context is okay here. Thanks! 942 koplocks = onefs_init_kernel_oplocks(NULL); 1327 koplocks = linux_init_kernel_oplocks(sconn); 943 1328 #endif 944 } 945 946 return True; 947 } 1329 sconn->oplocks.kernel_ops = koplocks; 1330 } 1331 }
Note:
See TracChangeset
for help on using the changeset viewer.