00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define DBGC_CLASS DBGC_LOCKING
00024 #include "includes.h"
00025
00026
00027 static int32 exclusive_oplocks_open = 0;
00028 static int32 level_II_oplocks_open = 0;
00029 BOOL global_client_failed_oplock_break = False;
00030
00031 extern uint32 global_client_caps;
00032 extern int smb_read_error;
00033
00034 static struct kernel_oplocks *koplocks;
00035
00036
00037
00038
00039
00040 int32 get_number_of_exclusive_open_oplocks(void)
00041 {
00042 return exclusive_oplocks_open;
00043 }
00044
00045
00046
00047
00048
00049 BOOL oplock_message_waiting(fd_set *fds)
00050 {
00051 if (koplocks && koplocks->msg_waiting(fds)) {
00052 return True;
00053 }
00054
00055 return False;
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065 void process_kernel_oplocks(fd_set *pfds)
00066 {
00067
00068
00069
00070
00071
00072
00073 if (!koplocks) {
00074 return;
00075 }
00076
00077 while (koplocks->msg_waiting(pfds)) {
00078 files_struct *fsp;
00079 char msg[MSG_SMB_KERNEL_BREAK_SIZE];
00080
00081 fsp = koplocks->receive_message(pfds);
00082
00083 if (fsp == NULL) {
00084 DEBUG(3, ("Kernel oplock message announced, but none "
00085 "received\n"));
00086 return;
00087 }
00088
00089
00090 SDEV_T_VAL(msg,0,fsp->dev);
00091 SINO_T_VAL(msg,8,fsp->inode);
00092 SIVAL(msg,16,fsp->fh->file_id);
00093
00094
00095
00096
00097 message_send_pid(pid_to_procid(sys_getpid()),
00098 MSG_SMB_KERNEL_BREAK,
00099 &msg, MSG_SMB_KERNEL_BREAK_SIZE, True);
00100 }
00101 }
00102
00103
00104
00105
00106
00107
00108 BOOL set_file_oplock(files_struct *fsp, int oplock_type)
00109 {
00110 if (koplocks && !koplocks->set_oplock(fsp, oplock_type)) {
00111 return False;
00112 }
00113
00114 fsp->oplock_type = oplock_type;
00115 fsp->sent_oplock_break = NO_BREAK_SENT;
00116 if (oplock_type == LEVEL_II_OPLOCK) {
00117 level_II_oplocks_open++;
00118 } else {
00119 exclusive_oplocks_open++;
00120 }
00121
00122 DEBUG(5,("set_file_oplock: granted oplock on file %s, 0x%x/%.0f/%lu, "
00123 "tv_sec = %x, tv_usec = %x\n",
00124 fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode,
00125 fsp->fh->file_id, (int)fsp->open_time.tv_sec,
00126 (int)fsp->open_time.tv_usec ));
00127
00128 return True;
00129 }
00130
00131
00132
00133
00134
00135 void release_file_oplock(files_struct *fsp)
00136 {
00137 if ((fsp->oplock_type != NO_OPLOCK) &&
00138 (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK) &&
00139 koplocks) {
00140 koplocks->release_oplock(fsp);
00141 }
00142
00143 if (fsp->oplock_type == LEVEL_II_OPLOCK) {
00144 level_II_oplocks_open--;
00145 } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
00146 exclusive_oplocks_open--;
00147 }
00148
00149 SMB_ASSERT(exclusive_oplocks_open>=0);
00150 SMB_ASSERT(level_II_oplocks_open>=0);
00151
00152 fsp->oplock_type = NO_OPLOCK;
00153 fsp->sent_oplock_break = NO_BREAK_SENT;
00154
00155 flush_write_cache(fsp, OPLOCK_RELEASE_FLUSH);
00156
00157 TALLOC_FREE(fsp->oplock_timeout);
00158 }
00159
00160
00161
00162
00163
00164 static void downgrade_file_oplock(files_struct *fsp)
00165 {
00166 if (koplocks) {
00167 koplocks->release_oplock(fsp);
00168 }
00169 fsp->oplock_type = LEVEL_II_OPLOCK;
00170 exclusive_oplocks_open--;
00171 level_II_oplocks_open++;
00172 fsp->sent_oplock_break = NO_BREAK_SENT;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181 BOOL remove_oplock(files_struct *fsp)
00182 {
00183 SMB_DEV_T dev = fsp->dev;
00184 SMB_INO_T inode = fsp->inode;
00185 BOOL ret;
00186 struct share_mode_lock *lck;
00187
00188
00189 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
00190 if (lck == NULL) {
00191 DEBUG(0,("remove_oplock: failed to lock share entry for "
00192 "file %s\n", fsp->fsp_name ));
00193 return False;
00194 }
00195 ret = remove_share_oplock(lck, fsp);
00196 if (!ret) {
00197 DEBUG(0,("remove_oplock: failed to remove share oplock for "
00198 "file %s fnum %d, 0x%x/%.0f\n",
00199 fsp->fsp_name, fsp->fnum, (unsigned int)dev,
00200 (double)inode));
00201 }
00202 release_file_oplock(fsp);
00203 TALLOC_FREE(lck);
00204 return ret;
00205 }
00206
00207
00208
00209
00210 BOOL downgrade_oplock(files_struct *fsp)
00211 {
00212 SMB_DEV_T dev = fsp->dev;
00213 SMB_INO_T inode = fsp->inode;
00214 BOOL ret;
00215 struct share_mode_lock *lck;
00216
00217 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
00218 if (lck == NULL) {
00219 DEBUG(0,("downgrade_oplock: failed to lock share entry for "
00220 "file %s\n", fsp->fsp_name ));
00221 return False;
00222 }
00223 ret = downgrade_share_oplock(lck, fsp);
00224 if (!ret) {
00225 DEBUG(0,("downgrade_oplock: failed to downgrade share oplock "
00226 "for file %s fnum %d, dev = %x, inode = %.0f\n",
00227 fsp->fsp_name, fsp->fnum, (unsigned int)dev,
00228 (double)inode));
00229 }
00230
00231 downgrade_file_oplock(fsp);
00232 TALLOC_FREE(lck);
00233 return ret;
00234 }
00235
00236
00237
00238
00239
00240 int oplock_notify_fd(void)
00241 {
00242 if (koplocks) {
00243 return koplocks->notification_fd;
00244 }
00245
00246 return -1;
00247 }
00248
00249
00250
00251
00252
00253 static char *new_break_smb_message(TALLOC_CTX *mem_ctx,
00254 files_struct *fsp, uint8 cmd)
00255 {
00256 char *result = TALLOC_ARRAY(mem_ctx, char, smb_size + 8*2 + 0);
00257
00258 if (result == NULL) {
00259 DEBUG(0, ("talloc failed\n"));
00260 return NULL;
00261 }
00262
00263 memset(result,'\0',smb_size);
00264 set_message(result,8,0,True);
00265 SCVAL(result,smb_com,SMBlockingX);
00266 SSVAL(result,smb_tid,fsp->conn->cnum);
00267 SSVAL(result,smb_pid,0xFFFF);
00268 SSVAL(result,smb_uid,0);
00269 SSVAL(result,smb_mid,0xFFFF);
00270 SCVAL(result,smb_vwv0,0xFF);
00271 SSVAL(result,smb_vwv2,fsp->fnum);
00272 SCVAL(result,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE);
00273 SCVAL(result,smb_vwv3+1,cmd);
00274 return result;
00275 }
00276
00277
00278
00279
00280
00281 static void wait_before_sending_break(void)
00282 {
00283 long wait_time = (long)lp_oplock_break_wait_time();
00284
00285 if (wait_time) {
00286 smb_msleep(wait_time);
00287 }
00288 }
00289
00290
00291
00292
00293
00294 static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id)
00295 {
00296 files_struct *fsp = NULL;
00297
00298 if( DEBUGLVL( 3 ) ) {
00299 dbgtext( "initial_break_processing: called for 0x%x/%.0f/%u\n",
00300 (unsigned int)dev, (double)inode, (int)file_id);
00301 dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n",
00302 exclusive_oplocks_open, level_II_oplocks_open );
00303 }
00304
00305
00306
00307
00308
00309
00310
00311 fsp = file_find_dif(dev, inode, file_id);
00312
00313 if(fsp == NULL) {
00314
00315 if( DEBUGLVL( 3 ) ) {
00316 dbgtext( "initial_break_processing: cannot find open file with " );
00317 dbgtext( "dev = 0x%x, inode = %.0f file_id = %lu", (unsigned int)dev,
00318 (double)inode, file_id);
00319 dbgtext( "allowing break to succeed.\n" );
00320 }
00321 return NULL;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 if(fsp->oplock_type == NO_OPLOCK) {
00335 if( DEBUGLVL( 3 ) ) {
00336 dbgtext( "initial_break_processing: file %s ", fsp->fsp_name );
00337 dbgtext( "(dev = %x, inode = %.0f, file_id = %lu) has no oplock.\n",
00338 (unsigned int)dev, (double)inode, fsp->fh->file_id );
00339 dbgtext( "Allowing break to succeed regardless.\n" );
00340 }
00341 return NULL;
00342 }
00343
00344 return fsp;
00345 }
00346
00347 static void oplock_timeout_handler(struct event_context *ctx,
00348 struct timed_event *te,
00349 const struct timeval *now,
00350 void *private_data)
00351 {
00352 files_struct *fsp = (files_struct *)private_data;
00353
00354
00355 TALLOC_FREE(fsp->oplock_timeout);
00356 DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", fsp->fsp_name));
00357 global_client_failed_oplock_break = True;
00358 remove_oplock(fsp);
00359 reply_to_oplock_break_requests(fsp);
00360 }
00361
00362
00363
00364
00365
00366 static void add_oplock_timeout_handler(files_struct *fsp)
00367 {
00368 if (fsp->oplock_timeout != NULL) {
00369 DEBUG(0, ("Logic problem -- have an oplock event hanging "
00370 "around\n"));
00371 }
00372
00373 fsp->oplock_timeout =
00374 event_add_timed(smbd_event_context(), NULL,
00375 timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
00376 "oplock_timeout_handler",
00377 oplock_timeout_handler, fsp);
00378
00379 if (fsp->oplock_timeout == NULL) {
00380 DEBUG(0, ("Could not add oplock timeout handler\n"));
00381 }
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 static void process_oplock_async_level2_break_message(int msg_type, struct process_id src,
00393 void *buf, size_t len,
00394 void *private_data)
00395 {
00396 struct share_mode_entry msg;
00397 files_struct *fsp;
00398 char *break_msg;
00399 BOOL sign_state;
00400
00401 if (buf == NULL) {
00402 DEBUG(0, ("Got NULL buffer\n"));
00403 return;
00404 }
00405
00406 if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
00407 DEBUG(0, ("Got invalid msg len %d\n", (int)len));
00408 return;
00409 }
00410
00411
00412 message_to_share_mode_entry(&msg, (char *)buf);
00413
00414 DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%lu\n",
00415 (int)procid_to_pid(&src), (unsigned int)msg.dev,
00416 (double)msg.inode, msg.share_file_id));
00417
00418 fsp = initial_break_processing(msg.dev, msg.inode,
00419 msg.share_file_id);
00420
00421 if (fsp == NULL) {
00422
00423
00424
00425 DEBUG(3, ("process_oplock_async_level2_break_message: Did not find fsp, ignoring\n"));
00426 return;
00427 }
00428
00429 if (fsp->oplock_type == NO_OPLOCK) {
00430
00431
00432 DEBUG(3, ("process_oplock_async_level2_break_message: already broken to none, ignoring.\n"));
00433 return;
00434 }
00435
00436 if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) {
00437
00438 DEBUG(3, ("process_oplock_async_level2_break_message: downgrading fake level 2 oplock.\n"));
00439 remove_oplock(fsp);
00440 return;
00441 }
00442
00443
00444 SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK);
00445
00446
00447
00448 break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE);
00449 if (break_msg == NULL) {
00450 exit_server("Could not talloc break_msg\n");
00451 }
00452
00453
00454 if (procid_to_pid(&src) == sys_getpid()) {
00455 wait_before_sending_break();
00456 }
00457
00458
00459 sign_state = srv_oplock_set_signing(False);
00460
00461 show_msg(break_msg);
00462 if (!send_smb(smbd_server_fd(), break_msg)) {
00463 exit_server_cleanly("oplock_break: send_smb failed.");
00464 }
00465
00466
00467 srv_oplock_set_signing(sign_state);
00468
00469 TALLOC_FREE(break_msg);
00470
00471
00472 remove_oplock(fsp);
00473 }
00474
00475
00476
00477
00478
00479 static void process_oplock_break_message(int msg_type, struct process_id src,
00480 void *buf, size_t len,
00481 void *private_data)
00482 {
00483 struct share_mode_entry msg;
00484 files_struct *fsp;
00485 char *break_msg;
00486 BOOL break_to_level2 = False;
00487 BOOL sign_state;
00488
00489 if (buf == NULL) {
00490 DEBUG(0, ("Got NULL buffer\n"));
00491 return;
00492 }
00493
00494 if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
00495 DEBUG(0, ("Got invalid msg len %d\n", (int)len));
00496 return;
00497 }
00498
00499
00500 message_to_share_mode_entry(&msg, (char *)buf);
00501
00502 DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%lu\n",
00503 (int)procid_to_pid(&src), (unsigned int)msg.dev,
00504 (double)msg.inode, msg.share_file_id));
00505
00506 fsp = initial_break_processing(msg.dev, msg.inode,
00507 msg.share_file_id);
00508
00509 if (fsp == NULL) {
00510
00511
00512
00513 DEBUG(3, ("Did not find fsp\n"));
00514
00515
00516 message_send_pid(src, MSG_SMB_BREAK_RESPONSE,
00517 buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
00518 return;
00519 }
00520
00521 if (fsp->sent_oplock_break != NO_BREAK_SENT) {
00522
00523
00524 msg.pid = src;
00525 ADD_TO_ARRAY(NULL, struct share_mode_entry, msg,
00526 &fsp->pending_break_messages,
00527 &fsp->num_pending_break_messages);
00528 return;
00529 }
00530
00531 if (EXCLUSIVE_OPLOCK_TYPE(msg.op_type) &&
00532 !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
00533 DEBUG(3, ("Already downgraded oplock on 0x%x/%.0f: %s\n",
00534 (unsigned int)fsp->dev, (double)fsp->inode,
00535 fsp->fsp_name));
00536
00537 message_send_pid(src, MSG_SMB_BREAK_RESPONSE,
00538 buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
00539 return;
00540 }
00541
00542 if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
00543 !(msg.op_type & FORCE_OPLOCK_BREAK_TO_NONE) &&
00544 !koplocks &&
00545
00546 lp_level2_oplocks(SNUM(fsp->conn))) {
00547 break_to_level2 = True;
00548 }
00549
00550 break_msg = new_break_smb_message(NULL, fsp, break_to_level2 ?
00551 OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
00552 if (break_msg == NULL) {
00553 exit_server("Could not talloc break_msg\n");
00554 }
00555
00556
00557 if (procid_to_pid(&src) == sys_getpid()) {
00558 wait_before_sending_break();
00559 }
00560
00561
00562 sign_state = srv_oplock_set_signing(False);
00563
00564 show_msg(break_msg);
00565 if (!send_smb(smbd_server_fd(), break_msg)) {
00566 exit_server_cleanly("oplock_break: send_smb failed.");
00567 }
00568
00569
00570 srv_oplock_set_signing(sign_state);
00571
00572 TALLOC_FREE(break_msg);
00573
00574 fsp->sent_oplock_break = break_to_level2 ? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
00575
00576 msg.pid = src;
00577 ADD_TO_ARRAY(NULL, struct share_mode_entry, msg,
00578 &fsp->pending_break_messages,
00579 &fsp->num_pending_break_messages);
00580
00581 add_oplock_timeout_handler(fsp);
00582 }
00583
00584
00585
00586
00587
00588 static void process_kernel_oplock_break(int msg_type, struct process_id src,
00589 void *buf, size_t len,
00590 void *private_data)
00591 {
00592 SMB_DEV_T dev;
00593 SMB_INO_T inode;
00594 unsigned long file_id;
00595 files_struct *fsp;
00596 char *break_msg;
00597 BOOL sign_state;
00598
00599 if (buf == NULL) {
00600 DEBUG(0, ("Got NULL buffer\n"));
00601 return;
00602 }
00603
00604 if (len != MSG_SMB_KERNEL_BREAK_SIZE) {
00605 DEBUG(0, ("Got invalid msg len %d\n", (int)len));
00606 return;
00607 }
00608
00609
00610 dev = DEV_T_VAL(buf, 0);
00611 inode = INO_T_VAL(buf, 8);
00612 file_id = (unsigned long)IVAL(buf, 16);
00613
00614 DEBUG(10, ("Got kernel oplock break message from pid %d: 0x%x/%.0f/%u\n",
00615 (int)procid_to_pid(&src), (unsigned int)dev, (double)inode,
00616 (unsigned int)file_id));
00617
00618 fsp = initial_break_processing(dev, inode, file_id);
00619
00620 if (fsp == NULL) {
00621 DEBUG(3, ("Got a kernel oplock break message for a file "
00622 "I don't know about\n"));
00623 return;
00624 }
00625
00626 if (fsp->sent_oplock_break != NO_BREAK_SENT) {
00627
00628 DEBUG(3, ("Got a kernel oplock request while waiting for a "
00629 "break reply\n"));
00630 return;
00631 }
00632
00633 break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE);
00634 if (break_msg == NULL) {
00635 exit_server("Could not talloc break_msg\n");
00636 }
00637
00638
00639 sign_state = srv_oplock_set_signing(False);
00640
00641 show_msg(break_msg);
00642 if (!send_smb(smbd_server_fd(), break_msg)) {
00643 exit_server_cleanly("oplock_break: send_smb failed.");
00644 }
00645
00646
00647 srv_oplock_set_signing(sign_state);
00648
00649 TALLOC_FREE(break_msg);
00650
00651 fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
00652
00653 add_oplock_timeout_handler(fsp);
00654 }
00655
00656 void reply_to_oplock_break_requests(files_struct *fsp)
00657 {
00658 int i;
00659
00660 for (i=0; i<fsp->num_pending_break_messages; i++) {
00661 struct share_mode_entry *e = &fsp->pending_break_messages[i];
00662 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
00663
00664 share_mode_entry_to_message(msg, e);
00665
00666 message_send_pid(e->pid, MSG_SMB_BREAK_RESPONSE,
00667 msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
00668 }
00669
00670 SAFE_FREE(fsp->pending_break_messages);
00671 fsp->num_pending_break_messages = 0;
00672 if (fsp->oplock_timeout != NULL) {
00673
00674 TALLOC_FREE(fsp->oplock_timeout);
00675 fsp->oplock_timeout = NULL;
00676 }
00677 return;
00678 }
00679
00680 static void process_oplock_break_response(int msg_type, struct process_id src,
00681 void *buf, size_t len,
00682 void *private_data)
00683 {
00684 struct share_mode_entry msg;
00685
00686 if (buf == NULL) {
00687 DEBUG(0, ("Got NULL buffer\n"));
00688 return;
00689 }
00690
00691 if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
00692 DEBUG(0, ("Got invalid msg len %u\n", (unsigned int)len));
00693 return;
00694 }
00695
00696
00697 message_to_share_mode_entry(&msg, (char *)buf);
00698
00699 DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%lu mid %u\n",
00700 (int)procid_to_pid(&src), (unsigned int)msg.dev,
00701 (double)msg.inode, msg.share_file_id,
00702 (unsigned int)msg.op_mid));
00703
00704
00705 schedule_deferred_open_smb_message(msg.op_mid);
00706 }
00707
00708 static void process_open_retry_message(int msg_type, struct process_id src,
00709 void *buf, size_t len,
00710 void *private_data)
00711 {
00712 struct share_mode_entry msg;
00713
00714 if (buf == NULL) {
00715 DEBUG(0, ("Got NULL buffer\n"));
00716 return;
00717 }
00718
00719 if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
00720 DEBUG(0, ("Got invalid msg len %d\n", (int)len));
00721 return;
00722 }
00723
00724
00725 message_to_share_mode_entry(&msg, (char *)buf);
00726
00727 DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f/%lu mid %u\n",
00728 (int)procid_to_pid(&src), (unsigned int)msg.dev,
00729 (double)msg.inode, msg.share_file_id,
00730 (unsigned int)msg.op_mid));
00731
00732 schedule_deferred_open_smb_message(msg.op_mid);
00733 }
00734
00735
00736
00737
00738
00739
00740
00741 void release_level_2_oplocks_on_change(files_struct *fsp)
00742 {
00743 int i;
00744 struct share_mode_lock *lck;
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754 if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
00755 return;
00756
00757 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
00758 if (lck == NULL) {
00759 DEBUG(0,("release_level_2_oplocks_on_change: failed to lock "
00760 "share mode entry for file %s.\n", fsp->fsp_name ));
00761 return;
00762 }
00763
00764 DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n",
00765 lck->num_share_modes ));
00766
00767 for(i = 0; i < lck->num_share_modes; i++) {
00768 struct share_mode_entry *share_entry = &lck->share_modes[i];
00769 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
00770
00771 if (!is_valid_share_mode_entry(share_entry)) {
00772 continue;
00773 }
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786 DEBUG(10,("release_level_2_oplocks_on_change: "
00787 "share_entry[%i]->op_type == %d\n",
00788 i, share_entry->op_type ));
00789
00790 if (share_entry->op_type == NO_OPLOCK) {
00791 continue;
00792 }
00793
00794
00795 if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) {
00796 DEBUG(0,("release_level_2_oplocks_on_change: PANIC. "
00797 "share mode entry %d is an exlusive "
00798 "oplock !\n", i ));
00799 TALLOC_FREE(lck);
00800 abort();
00801 }
00802
00803 share_mode_entry_to_message(msg, share_entry);
00804
00805 message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK,
00806 msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
00807 }
00808
00809
00810
00811
00812 TALLOC_FREE(lck);
00813 }
00814
00815
00816
00817
00818
00819 void share_mode_entry_to_message(char *msg, struct share_mode_entry *e)
00820 {
00821 SIVAL(msg,0,(uint32)e->pid.pid);
00822 SSVAL(msg,4,e->op_mid);
00823 SSVAL(msg,6,e->op_type);
00824 SIVAL(msg,8,e->access_mask);
00825 SIVAL(msg,12,e->share_access);
00826 SIVAL(msg,16,e->private_options);
00827 SIVAL(msg,20,(uint32)e->time.tv_sec);
00828 SIVAL(msg,24,(uint32)e->time.tv_usec);
00829 SDEV_T_VAL(msg,28,e->dev);
00830 SINO_T_VAL(msg,36,e->inode);
00831 SIVAL(msg,44,e->share_file_id);
00832 SIVAL(msg,48,e->uid);
00833 SSVAL(msg,52,e->flags);
00834 }
00835
00836
00837
00838
00839
00840 void message_to_share_mode_entry(struct share_mode_entry *e, char *msg)
00841 {
00842 e->pid.pid = (pid_t)IVAL(msg,0);
00843 e->op_mid = SVAL(msg,4);
00844 e->op_type = SVAL(msg,6);
00845 e->access_mask = IVAL(msg,8);
00846 e->share_access = IVAL(msg,12);
00847 e->private_options = IVAL(msg,16);
00848 e->time.tv_sec = (time_t)IVAL(msg,20);
00849 e->time.tv_usec = (int)IVAL(msg,24);
00850 e->dev = DEV_T_VAL(msg,28);
00851 e->inode = INO_T_VAL(msg,36);
00852 e->share_file_id = (unsigned long)IVAL(msg,44);
00853 e->uid = (uint32)IVAL(msg,48);
00854 e->flags = (uint16)SVAL(msg,52);
00855 }
00856
00857
00858
00859
00860
00861 BOOL init_oplocks(void)
00862 {
00863 DEBUG(3,("init_oplocks: initializing messages.\n"));
00864
00865 message_register(MSG_SMB_BREAK_REQUEST,
00866 process_oplock_break_message,
00867 NULL);
00868 message_register(MSG_SMB_ASYNC_LEVEL2_BREAK,
00869 process_oplock_async_level2_break_message,
00870 NULL);
00871 message_register(MSG_SMB_BREAK_RESPONSE,
00872 process_oplock_break_response,
00873 NULL);
00874 message_register(MSG_SMB_KERNEL_BREAK,
00875 process_kernel_oplock_break,
00876 NULL);
00877 message_register(MSG_SMB_OPEN_RETRY,
00878 process_open_retry_message,
00879 NULL);
00880
00881 if (lp_kernel_oplocks()) {
00882 #if HAVE_KERNEL_OPLOCKS_IRIX
00883 koplocks = irix_init_kernel_oplocks();
00884 #elif HAVE_KERNEL_OPLOCKS_LINUX
00885 koplocks = linux_init_kernel_oplocks();
00886 #endif
00887 }
00888
00889 return True;
00890 }