1 // 2 // CDDL HEADER START 3 // 4 // The contents of this file are subject to the terms of the 5 // Common Development and Distribution License (the License). 6 // You may not use this file except in compliance with the License. 7 // 8 // You can obtain a copy of the license at usr/src/CDDL.txt 9 // or http://www.opensolaris.org/os/licensing. 10 // See the License for the specific language governing permissions 11 // and limitations under the License. 12 // 13 // When distributing Covered Code, include this CDDL HEADER in each 14 // file and include the License file at usr/src/CDDL.txt. 15 // If applicable, add the following below this CDDL HEADER, with the 16 // fields enclosed by brackets [] replaced with your own identifying 17 // information: Portions Copyright [yyyy] [name of copyright owner] 18 // 19 // CDDL HEADER END 20 // 21 22 // 23 // Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 // Use is subject to license terms. 25 // 26 27 #pragma ident "@(#)mount_replica_impl.cc 1.45 08/05/20 SMI" 28 29 #include <sys/vm_util.h> 30 #include <orb/infrastructure/orb_conf.h> 31 #include <nslib/ns.h> 32 #include <pxfs/common/pxfslib.h> 33 #include <pxfs/mount/mount_replica_impl.h> 34 #include <pxfs/mount/mount_server_impl.h> 35 #include <pxfs/mount/mount_debug.h> 36 37 // 38 // The struct has an entry for each IDL interface which is being versioned. For 39 // a given VP major and minor version, we get the IDL version of those 40 // interfaces. 41 // 42 mount_ver_map_t mount_vp_to_idl[MOUNT_VP_MAX_MAJOR + 1][MOUNT_VP_MAX_MINOR +1] = 43 { 44 { { 0, 0 }, // VP Version 0.0 defined for indexing 45 { 0, 0 }, // VP Version 0.1 " " " 46 { 0, 0 } }, // VP Version 0.2 " " " 47 { { 0, 0 }, // VP Version 1.0 48 { 1, 1 }, // VP Version 1.1 49 { 1, 1 } }, // VP Version 1.2 50 { { 2, 2 }, // VP Version 2.0 Object Consolidation 51 { 2, 2}, // VP Version 2.1 currently unused 52 { 2, 2 } } // VP Version 2.2 currently unused 53 }; 54 55 // 56 // Create a mount_replica_impl object. 57 // 58 mount_replica_impl::mount_replica_impl(const char *id) : 59 repl_server<repl_pxfs::mount_replica>("mount", id), 60 _ckpt_proxy(NULL) 61 { 62 mount_serverp = NULL; 63 64 // 65 // We initialize the current version to an invalid version. 66 // mount_replica_impl::startup() will query the version manager 67 // for the correct values. 68 // 69 current_version.major_num = 0; 70 current_version.minor_num = 0; 71 pending_version.major_num = 0; 72 pending_version.minor_num = 0; 73 } 74 75 mount_replica_impl::~mount_replica_impl() 76 { 77 mount_serverp = NULL; 78 _ckpt_proxy = NULL; 79 } 80 81 repl_pxfs::mount_replica_ptr 82 mount_replica_impl::get_checkpoint_mount_replica() 83 { 84 ASSERT(!CORBA::is_nil(_ckpt_proxy)); 85 return (_ckpt_proxy); 86 } 87 88 // 89 // Become the primary. 90 // Note that previously we might have been newly created or 91 // a secondary that is switching to primary. 92 // 93 void 94 mount_replica_impl::become_primary(const replica::repl_name_seq &, 95 Environment &_environment) 96 { 97 // 98 // The following environment is for checkpointing to the secondary 99 // We use a different environment for checkpointing because 100 // mount_server_impl::upgrade_client_reference() clears the 101 // environment context passed to it. 102 // 103 Environment ckpt_environment; 104 105 // 106 // Create a primary context so the provider can send 107 // checkpoints while the service is frozen. 108 // XXX change the primary_ctx::invoke_env type. 109 // 110 primary_ctx ctx(NULL, primary_ctx::ADD_SECONDARY_CKPT, 111 ckpt_environment); 112 113 // First, initialize the checkpoint proxy. 114 version_lock.wrlock(); 115 116 // Callback may have occured when this replica was a secondary 117 if (pending_version.major_num != 0) { 118 current_version = pending_version; 119 } 120 CORBA::type_info_t *typ = repl_pxfs::mount_replica::_get_type_info( 121 mount_vp_to_idl[current_version.major_num] 122 [current_version.minor_num].ms_ckpt); 123 replica::checkpoint_var tmp_ckpt_v = set_checkpoint(typ); 124 _ckpt_proxy = repl_pxfs::mount_replica::_narrow(tmp_ckpt_v); 125 126 ASSERT(!CORBA::is_nil(_ckpt_proxy)); 127 128 // 129 // If we were a secondary. 130 // 131 if (mount_serverp != NULL) { 132 // 133 // If there was an unprocessed upgrade callback pending, 134 // finish the work and send a checkpoint to notify the 135 // other secondaries. 136 // 137 if (pending_version.major_num != 0) { 138 pending_version.major_num = 0; 139 140 // Update the server reference. 141 typ = fs::mount_server::_get_type_info( 142 mount_vp_to_idl[current_version.major_num] 143 [current_version.minor_num].ms); 144 mount_server_v = mount_serverp->get_objref(typ); 145 146 // Update the client reference in the mount_server_impl 147 mount_serverp->upgrade_client_reference(_environment); 148 149 // Checkpoint current version. 150 _ckpt_proxy->ckpt_service_version( 151 current_version.major_num, 152 current_version.minor_num, ckpt_environment); 153 ckpt_environment.clear(); 154 } 155 version_lock.unlock(); 156 157 mount_serverp->convert_to_primary(); 158 159 // 160 // Show that the context is no longer there, 161 // so that the destructor will see that everything is clean. 162 // 163 ckpt_environment.trans_ctxp = NULL; 164 165 return; 166 } 167 168 // 169 // Create a new mount server implementation object. 170 // 171 mount_serverp = new mount_server_impl(this); 172 typ = fs::mount_server::_get_type_info( 173 mount_vp_to_idl[current_version.major_num] 174 [current_version.minor_num].ms); 175 mount_server_v = mount_serverp->get_objref(typ); 176 177 // Checkpoint the creation of the first mount server object. 178 mount_serverp->get_checkpoint()->ckpt_new_server(mount_server_v, 179 ckpt_environment); 180 ckpt_environment.clear(); 181 182 // 183 // If an old primary failed while an upgrade callback was in 184 // progress and before the service version was checkpointed, we 185 // do the service version checkpointing now. 186 // 187 if (pending_version.major_num != 0) { 188 pending_version.major_num = 0; 189 _ckpt_proxy->ckpt_service_version( 190 current_version.major_num, 191 current_version.minor_num, ckpt_environment); 192 } 193 version_lock.unlock(); 194 195 // 196 // Show that the context is no longer there, 197 // so that the destructor will see that everything is clean. 198 // 199 ckpt_environment.trans_ctxp = NULL; 200 } 201 202 // 203 // Become the secondary. 204 // 205 void 206 mount_replica_impl::become_secondary(Environment &) 207 { 208 ASSERT(mount_serverp != NULL); 209 mount_serverp->convert_to_secondary(); 210 211 version_lock.wrlock(); 212 ASSERT(!CORBA::is_nil(_ckpt_proxy)); 213 214 // Release the reference to the multi_ckpt_handler. 215 CORBA::release(_ckpt_proxy); 216 _ckpt_proxy = nil; 217 version_lock.unlock(); 218 } 219 220 void 221 mount_replica_impl::add_secondary(replica::checkpoint_ptr sec_chkpt, 222 const char *, Environment &_environment) 223 { 224 ASSERT(mount_serverp != NULL); 225 226 repl_pxfs::mount_replica_var ckpt = 227 repl_pxfs::mount_replica::_narrow(sec_chkpt); 228 ASSERT(!CORBA::is_nil(ckpt)); 229 230 // dump current state to the new secondary 231 mount_serverp->dump_state(ckpt, _environment); 232 if (_environment.exception()) { 233 MOUNT_DBPRINTF( 234 MOUNT_TRACE_REPLICA, 235 MOUNT_RED, 236 ("replica:exception '%s' in dump_state() \n", 237 _environment.exception()->_name())); 238 } 239 _environment.clear(); 240 } 241 242 void 243 mount_replica_impl::remove_secondary(const char *, Environment &) 244 { 245 } 246 247 void 248 mount_replica_impl::freeze_primary_prepare(Environment &) 249 { 250 } 251 252 void 253 mount_replica_impl::freeze_primary(Environment &) 254 { 255 // 256 // Start freezing. The situation we are trying to prevent is 257 // where a call to devlock() is waiting for the lock and 258 // then a swithover is requested. The switchover won't complete 259 // until the devlock() returns but that can't happen since the 260 // devunlock() is blocked until the switchover completes. 261 // 262 if (mount_serverp != NULL) { 263 mount_serverp->freeze_primary(); 264 } 265 } 266 267 void 268 mount_replica_impl::unfreeze_primary(Environment &) 269 { 270 if (mount_serverp != NULL) { 271 mount_serverp->unfreeze_primary(); 272 } 273 } 274 275 void 276 mount_replica_impl::become_spare(Environment &) 277 { 278 if (mount_serverp != NULL) { 279 // Drop our reference to the object before doing a delete. 280 mount_server_v = fs::mount_server::_nil(); 281 mount_serverp->convert_to_spare(); 282 // 283 // mount_serverp is cleaned up in convert_to_spare(), 284 // so the next line is not a memory leak. 285 //lint -e423 286 mount_serverp = NULL; 287 //lint +e423 288 } 289 } 290 291 // 292 // This is called on the primary when the service is requested to shutdown. 293 // 294 void 295 mount_replica_impl::shutdown(Environment &_environment) 296 { 297 // We should never shut down. 298 _environment.exception(new replica::service_busy); 299 300 // 301 // Since we are returning an exception, we will remain primary, 302 // so don't release _ckpt_proxy. 303 // 304 } 305 306 // 307 // This is called on the primary to return a reference to the root 308 // HA object (in this case, fs::mount_server). 309 // 310 CORBA::Object_ptr 311 mount_replica_impl::get_root_obj(Environment &) 312 { 313 ASSERT(mount_serverp != NULL); 314 version_lock.wrlock(); 315 CORBA::type_info_t *typ = fs::mount_server::_get_type_info( 316 mount_vp_to_idl[current_version.major_num] 317 [current_version.minor_num].ms); 318 version_lock.unlock(); 319 return (mount_serverp->get_objref(typ)); 320 } 321 322 // 323 // Process an upgrade callback from the version manager. 324 // This call can happen before the HA replica is registered with the 325 // replica manager (i.e., the HA sevice is not started yet or is a spare), 326 // or as primary or secondary. The callback is not synchronized with 327 // calls to become_primary(), become_secondary(), etc. and failovers can 328 // happen while the service is frozen so we need to make sure that the 329 // "upgrade work" is done if there are node failures. 330 // If this replica is the primary, we do the work and send a checkpoint 331 // to indicate the work is complete. If this replica is a secondary and 332 // the callback happens before we get the checkpoint from the primary, 333 // we record that the callback happened so that become_primary() can 334 // do the "upgrade work" and send the checkpoint. If this replica is a 335 // secondary and the callback happens after the checkpoint is received, 336 // we ignore the callback. The checkpoint routine on the secondary clears 337 // the "flag" that the callback sets so no extra work is done in 338 // become_primary() if the old primary fails after completing the upgrade 339 // callback work. 340 // 341 void 342 mount_replica_impl::upgrade_callback( 343 const version_manager::vp_version_t &version, Environment &e) 344 { 345 CORBA::type_info_t *typ; 346 347 // 348 // Note that upgrade callbacks are not synchronized with 349 // calls to become_primary(), add_secondary(), etc. 350 // Getting this lock makes sure the replica state doesn't change. 351 // 352 version_lock.wrlock(); 353 if (current_version.major_num > version.major_num || 354 (current_version.major_num == version.major_num && 355 current_version.minor_num >= version.minor_num)) { 356 // Version isn't changing so just return. 357 version_lock.unlock(); 358 return; 359 } 360 361 // 362 // If this replica is not the primary, set the pending version 363 // to be used if there is a failover before the primary checkpoints 364 // a new version. 365 // 366 if (CORBA::is_nil(_ckpt_proxy)) { 367 // If this replica is a secondary, set the pending version. 368 if (mount_serverp != NULL) { 369 pending_version = version; 370 } else { 371 // Replica must be a spare. 372 current_version = version; 373 } 374 version_lock.unlock(); 375 return; 376 } 377 378 // We are the primary and the version has changed. 379 current_version = version; 380 MOUNT_DBPRINTF( 381 MOUNT_TRACE_REPLICA, 382 MOUNT_GREEN, 383 ("replica:upgrade_callback major = %d minor = %d ", 384 current_version.major_num, current_version.minor_num)); 385 386 // 387 // Switch the checkpoint interface to the new protocol. Save 388 // the current _ckpt_proxy and release it after we get a new one 389 // 390 repl_pxfs::mount_replica_ptr old_ckpt_p = _ckpt_proxy; 391 392 typ = repl_pxfs::mount_replica::_get_type_info( 393 mount_vp_to_idl[current_version.major_num] 394 [current_version.minor_num].ms_ckpt); 395 396 MOUNT_DBPRINTF( 397 MOUNT_TRACE_REPLICA, 398 MOUNT_GREEN, 399 ("replica:upgrade_callback type_info_t ptr = %x", 400 typ)); 401 402 replica::checkpoint_var tmp_ckpt_v = set_checkpoint(typ); 403 _ckpt_proxy = repl_pxfs::mount_replica::_narrow(tmp_ckpt_v); 404 ASSERT(!CORBA::is_nil(_ckpt_proxy)); 405 406 CORBA::release(old_ckpt_p); 407 408 // Update the server reference. 409 typ = fs::mount_server::_get_type_info( 410 mount_vp_to_idl[current_version.major_num] 411 [current_version.minor_num].ms); 412 mount_server_v = mount_serverp->get_objref(typ); 413 414 // Update the client reference in the mount_server_impl 415 mount_serverp->upgrade_client_reference(e); 416 417 // 418 // Create and add a primary context so the provider can send 419 // checkpoints while the service is frozen. 420 // XXX change the primary_ctx::invoke_env type. 421 // 422 primary_ctx ctx(NULL, primary_ctx::ADD_SECONDARY_CKPT, e); 423 424 // Checkpoint the current version number. 425 _ckpt_proxy->ckpt_service_version( 426 current_version.major_num, 427 current_version.minor_num, e); 428 429 e.trans_ctxp = NULL; 430 431 version_lock.unlock(); 432 } 433 434 // 435 // Checkpoint the creation of a new mount server. 436 // 437 void 438 mount_replica_impl::ckpt_new_server(fs::mount_server_ptr server, 439 Environment &) 440 { 441 // 442 // Create a new mount server (we are a secondary). 443 // 444 if (mount_serverp == NULL) { 445 //lint -e423 446 mount_serverp = new mount_server_impl(this, server); 447 mount_server_v = fs::mount_server::_duplicate(server); 448 //lint +e423 449 } 450 } 451 452 // 453 // Checkpoint the addition of a new mount client. 454 // 455 void 456 mount_replica_impl::ckpt_add_client(fs::mount_client_died_ptr clobj, 457 fs::mount_client_ptr client, sol::nodeid_t nodeid, bool is_shutdown, 458 Environment &) 459 { 460 ASSERT(mount_serverp != NULL); 461 mount_serverp->ckpt_add_client(clobj, client, nodeid, is_shutdown); 462 } 463 464 // 465 // Checkpoint the removal of a mount_client. 466 // 467 void 468 mount_replica_impl::ckpt_remove_client(fs::mount_client_ptr client, 469 Environment &) 470 { 471 ASSERT(mount_serverp != NULL); 472 mount_serverp->ckpt_remove_client(client); 473 } 474 475 // 476 // Checkpoint the start of a mount or remount. 477 // 478 void 479 mount_replica_impl::ckpt_mount_start(const sol::mounta &ma, 480 fs::mount_client_ptr client, Environment &_environment) 481 { 482 CL_PANIC(0); 483 } 484 485 // 486 // Checkpoint the start of a mount or remount. 487 // 488 void 489 mount_replica_impl::ckpt_mount_start_v1(const sol::mounta &ma, 490 fs::mount_client_ptr client, Environment &_environment) 491 { 492 ASSERT(mount_serverp != NULL); 493 mount_serverp->ckpt_mount_start_v1(ma, client, _environment); 494 } 495 496 // 497 // Checkpoint a mount error. 498 // This is used to complete a ckpt_mount_start(). 499 // 500 void 501 mount_replica_impl::ckpt_mount_err(sol::error_t error, 502 Environment &_environment) 503 { 504 ASSERT(mount_serverp != NULL); 505 mount_serverp->ckpt_mount_err(error, _environment); 506 } 507 508 // 509 // Checkpoint the addition of a new file system (mount). 510 // This is used to dump state to a newly joining secondary. 511 // 512 void 513 mount_replica_impl::ckpt_mount(fs::filesystem_ptr fsptr, 514 const fs::fs_info &fsinfo, const sol::mounta &ma, const char *mntoptions, 515 bool dev_is_ha, const char *dev_name, 516 const sol::nodeid_seq_t &dev_nids, Environment &) 517 { 518 CL_PANIC(0); 519 } 520 521 // 522 // Checkpoint the addition of a new file system (mount). 523 // This is used to dump state to a newly joining secondary. 524 // 525 void 526 mount_replica_impl::ckpt_mount_v1(pxfs_v1::filesystem_ptr fsptr, 527 const pxfs_v1::fs_info &fsinfo, const sol::mounta &ma, 528 const char *mntoptions, bool dev_is_ha, const char *dev_name, 529 const sol::nodeid_seq_t &dev_nids, Environment &) 530 { 531 ASSERT(mount_serverp != NULL); 532 mount_serverp->ckpt_mount_v1(fsptr, fsinfo, ma, mntoptions, dev_is_ha, 533 dev_name, dev_nids); 534 } 535 536 // 537 // Checkpoint the creation of a new file system object. 538 // 539 void 540 mount_replica_impl::ckpt_mount_middle(fs::filesystem_ptr fsptr, 541 const fs::fs_info &fsinfo, const char *mntoptions, bool dev_is_ha, 542 const char *dev_name, const sol::nodeid_seq_t &dev_nids, 543 Environment &_environment) 544 { 545 CL_PANIC(0); 546 } 547 548 // 549 // Checkpoint the creation of a new file system object. 550 // 551 void 552 mount_replica_impl::ckpt_mount_middle_v1(pxfs_v1::filesystem_ptr fsptr, 553 const pxfs_v1::fs_info &fsinfo, const char *mntoptions, bool dev_is_ha, 554 const char *dev_name, const sol::nodeid_seq_t &dev_nids, 555 Environment &_environment) 556 { 557 ASSERT(mount_serverp != NULL); 558 mount_serverp->ckpt_mount_middle_v1(fsptr, fsinfo, mntoptions, 559 dev_is_ha, dev_name, dev_nids, _environment); 560 } 561 562 // 563 // Checkpoint the changes to vfs_flag and /etc/mnttab due to a remount. 564 // 565 void 566 mount_replica_impl::ckpt_remount_middle(fs::filesystem_ptr fsptr, 567 uint32_t vfsflags, const char *mntoptions, Environment &_environment) 568 { 569 CL_PANIC(0); 570 } 571 572 // 573 // Checkpoint the changes to vfs_flag and /etc/mnttab due to a remount. 574 // 575 void 576 mount_replica_impl::ckpt_remount_middle_v1(pxfs_v1::filesystem_ptr fsptr, 577 uint32_t vfsflags, const char *mntoptions, Environment &_environment) 578 { 579 ASSERT(mount_serverp != NULL); 580 mount_serverp->ckpt_remount_middle_v1(fsptr, vfsflags, mntoptions, 581 _environment); 582 } 583 584 // 585 // Checkpoint the start of an unmount. 586 // 587 void 588 mount_replica_impl::ckpt_unmount_start(fs::filesystem_ptr fsptr, 589 solobj::cred_ptr credobj, fs::mount_client_ptr client, 590 bool is_shutdown, Environment &_environment) 591 { 592 CL_PANIC(0); 593 } 594 595 // 596 // Checkpoint the start of an unmount. 597 // 598 // mount_replica_impl(repl_pxfs::mount_replica::ckpt_unmount_start) 599 void 600 mount_replica_impl::ckpt_unmount_start_1(fs::filesystem_ptr fsptr, 601 int32_t flags, solobj::cred_ptr credobj, fs::mount_client_ptr client, 602 bool is_shutdown, Environment &_environment) 603 { 604 CL_PANIC(0); 605 } 606 607 // 608 // Checkpoint the start of an unmount. 609 // 610 void 611 mount_replica_impl::ckpt_unmount_start_v1(pxfs_v1::filesystem_ptr fsptr, 612 int32_t flags, solobj::cred_ptr credobj, fs::mount_client_ptr client, 613 bool is_shutdown, Environment &_environment) 614 { 615 ASSERT(mount_serverp != NULL); 616 mount_serverp->ckpt_unmount_start_v1(fsptr, flags, 617 credobj, client, is_shutdown, _environment); 618 } 619 620 // 621 // Checkpoint that the mount points have been locked 622 // and the file system has been unmounted but the 623 // client nodes haven't been notified yet. 624 // 625 void 626 mount_replica_impl::ckpt_unmount_middle(sol::error_t error, 627 Environment &_environment) 628 { 629 ASSERT(mount_serverp != NULL); 630 mount_serverp->ckpt_unmount_middle(error, _environment); 631 } 632 633 // 634 // Checkpoint that all the client nodes have been 635 // notified (if there was no unmount error) before shutting 636 // down the file system service. 637 // 638 void 639 mount_replica_impl::ckpt_unmount_notified(Environment &_environment) 640 { 641 ASSERT(mount_serverp != NULL); 642 mount_serverp->ckpt_unmount_notified(_environment); 643 } 644 645 // 646 // Checkpoint that all the client nodes have been notified 647 // (if there was an unmount error) or the file system 648 // service has been shut down. We can't use a commit() call 649 // since this may be called more than once when unmounting 650 // multiple file systems. 651 // 652 void 653 mount_replica_impl::ckpt_unmount_end(Environment &_environment) 654 { 655 ASSERT(mount_serverp != NULL); 656 mount_serverp->ckpt_unmount_end(_environment); 657 } 658 659 // 660 // Checkpoint a node being shut down as part of unmount(). 661 // 662 void 663 mount_replica_impl::ckpt_unmount_shutdown(fs::mount_client_ptr client, 664 Environment &) 665 { 666 ASSERT(mount_serverp != NULL); 667 mount_serverp->ckpt_unmount_shutdown(client); 668 } 669 670 // 671 // Checkpoint a new device lock. 672 // 673 void 674 mount_replica_impl::ckpt_devlock(fs::mount_client_ptr client, 675 sol::nodeid_t nodeid, const char *dev_name, Environment &) 676 { 677 ASSERT(mount_serverp != NULL); 678 mount_serverp->ckpt_devlock(client, nodeid, dev_name); 679 } 680 681 // 682 // Checkpoint a device unlock. 683 // 684 void 685 mount_replica_impl::ckpt_devunlock(const char *dev_name, Environment &) 686 { 687 ASSERT(mount_serverp != NULL); 688 mount_serverp->ckpt_devunlock(dev_name); 689 } 690 691 // 692 // Checkpoint the creation of a dc_callback object. 693 // 694 void 695 mount_replica_impl::ckpt_get_dc_callback(fs::dc_callback_ptr cb, 696 Environment &) 697 { 698 ASSERT(mount_serverp != NULL); 699 mount_serverp->ckpt_get_dc_callback(cb); 700 } 701 702 // 703 // Checkpoint a change in the disk connection list. 704 // 705 void 706 mount_replica_impl::ckpt_notify_change(sol::dev_t gdev, 707 const sol::nodeid_seq_t &dev_nids, Environment &) 708 { 709 ASSERT(mount_serverp != NULL); 710 mount_serverp->ckpt_notify_change(gdev, dev_nids); 711 } 712 713 // 714 // Checkpoint a new service version 715 // 716 void 717 mount_replica_impl::ckpt_service_version(unsigned short new_major, 718 unsigned short new_minor, Environment &) 719 { 720 version_lock.wrlock(); 721 current_version.major_num = new_major; 722 current_version.minor_num = new_minor; 723 pending_version.major_num = 0; 724 version_lock.unlock(); 725 } 726 727 // 728 // Checkpoint the upgrade of a mount_client in client list. 729 // 730 void 731 mount_replica_impl::ckpt_upgrade_client_list(fs::mount_client_ptr client, 732 sol::nodeid_t nodeid, Environment &) 733 { 734 ASSERT(mount_serverp != NULL); 735 mount_serverp->ckpt_upgrade_client_list(client, nodeid); 736 } 737 738 // 739 // Checkpoint the upgrade of a mount_client in devlock list. 740 // 741 void 742 mount_replica_impl::ckpt_upgrade_devlock_list(const char *dev_name, 743 fs::mount_client_ptr client, Environment &) 744 { 745 ASSERT(mount_serverp != NULL); 746 mount_serverp->ckpt_upgrade_devlock_list(dev_name, client); 747 } 748 749 // 750 // Start up the mount service. We create a replica on every node 751 // so that the service is always available. 752 // 753 int 754 mount_replica_impl::startup() 755 { 756 Environment e; 757 char *svc_desc = "mount"; 758 char *vpname = "px_mount"; 759 760 // Create a new mount replica for This node. 761 char id[20]; 762 os::sprintf(id, "%u", orb_conf::node_number()); 763 mount_replica_impl *repl = new mount_replica_impl(id); 764 765 // Get a pointer to the local version manager 766 version_manager::vm_admin_var vmgr_v = vm_util::get_vm(NODEID_UNKNOWN); 767 768 // Build a UCC for support of version upgrade callbacks 769 version_manager::ucc_seq_t ucc_seq(1, 1); 770 ucc_seq[0].ucc_name = os::strdup(svc_desc); 771 ucc_seq[0].vp_name = os::strdup(vpname); 772 version_manager::string_seq_t fseq(1, 1); 773 fseq[0] = os::strdup(svc_desc); 774 ucc_seq[0].freeze = fseq; 775 776 // Create a version upgrade callback object for this mount replica. 777 version_manager::vp_version_t callback_limit; 778 version_manager::vp_version_t cur_version; 779 version_manager::upgrade_callback_var cbobj = 780 (new mount_version_callback_impl(*repl))->get_objref(); 781 782 // 783 // Register the callback object with the Version Manager. The 784 // tmp_version will be returned. The version lock is not held 785 // since the replica is not yet registered with the HA framework 786 // so there can not be a call to become_primary. The current version 787 // is returned regardless. 788 // 789 // If the running version is less than the callback_limit 790 // a callback will be registerd, otherwise a callback is not 791 // registered (currently no way to tell). The current running 792 // version is returned regardless. 793 // 794 callback_limit.major_num = 2; 795 callback_limit.minor_num = 0; 796 vmgr_v->register_upgrade_callbacks(ucc_seq, cbobj, callback_limit, 797 cur_version, e); 798 if (e.exception()) { 799 MOUNT_DBPRINTF( 800 MOUNT_TRACE_REPLICA, 801 MOUNT_RED, 802 ("replica:startup: version exception" 803 "on attemping to register for upgrade callback, id %s", 804 id)); 805 return (1); 806 } 807 808 // establish the current version in the provider 809 repl->set_version(cur_version); 810 811 repl->register_with_rm(1, true, e); 812 if (e.exception()) { 813 MOUNT_DBPRINTF( 814 MOUNT_TRACE_REPLICA, 815 MOUNT_RED, 816 ("replica:startup exception register with RM id %s\n", 817 id)); 818 e.clear(); 819 return (EIO); 820 } 821 return (0); 822 } 823 824 int 825 mount_replica_impl::shutdown() 826 { 827 return (0); 828 } 829 830 // 831 // Set the initial version number. 832 // 833 void 834 mount_replica_impl::set_version(const version_manager::vp_version_t &version) 835 { 836 // 837 // We could have had a callback between the time that we called 838 // register_upgrade_callbacks() and the time that it returned and 839 // set tmp_version. The callback may have set a newer version than 840 // current version, so don't clobber it. 841 // 842 version_lock.wrlock(); 843 if (current_version.major_num < version.major_num || 844 (current_version.major_num == version.major_num && 845 current_version.minor_num < version.minor_num)) { 846 current_version = version; 847 } 848 version_lock.unlock(); 849 } 850 851 852 853 mount_version_callback_impl::mount_version_callback_impl( 854 mount_replica_impl &mount_replica) : 855 prov(mount_replica) 856 { 857 } 858 859 mount_version_callback_impl::~mount_version_callback_impl() 860 { 861 } 862 863 void 864 mount_version_callback_impl::_unreferenced(unref_t arg) 865 { 866 if (!_last_unref(arg)) { 867 // _last_unref() should always be true since we don't use 0->1. 868 ASSERT(0); 869 return; 870 } 871 delete this; 872 } 873 874 void 875 mount_version_callback_impl::do_callback(const char *, 876 const version_manager::vp_version_t ¤t_version, Environment &e) 877 { 878 // Call the provider to update the version and checkpoint it. 879 prov.upgrade_callback(current_version, e); 880 } 881