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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Just in case we're not in a build environment, make sure that 31 * TEXT_DOMAIN gets set to something. 32 */ 33 #if !defined(TEXT_DOMAIN) 34 #define TEXT_DOMAIN "SYS_TEST" 35 #endif 36 37 /* 38 * setup utility 39 */ 40 41 #include "meta_set_prv.h" 42 #include <sys/resource.h> 43 #include <syslog.h> 44 45 46 /* globals */ 47 char *myname = ""; 48 FILE *metalogfp = NULL; 49 int metasyslog = 0; 50 uint_t verbosity = 0; 51 hrtime_t start_time = 0; 52 sigset_t allsigs; 53 54 /* locals */ 55 static int rb_signal_handling = FALSE; 56 static int rb_signal_caught = FALSE; 57 static int rb_signal_which = 0; 58 static size_t metansig = 0; 59 static struct sigaction *metahandlers = NULL; 60 #ifdef _DEBUG_MALLOC_INC 61 static ulong_t malloc_histid_begin; 62 static ulong_t malloc_histid_end; 63 static ulong_t malloc_inuse_begin; 64 static ulong_t malloc_inuse_end; 65 #endif /* _DEBUG_MALLOC_INC */ 66 67 /* forwards */ 68 static void md_catcher(int sig); 69 70 /* 71 * push/pop signal handlers 72 */ 73 static int 74 md_pushsig( 75 unsigned sig, 76 void (*handler)(int sig), 77 md_error_t *ep 78 ) 79 { 80 struct sigaction newhandler; 81 82 /* expand vector as neccessary */ 83 if (sig >= metansig) { 84 if (metahandlers == NULL) { 85 metahandlers = Zalloc( 86 (sig + 1) * sizeof (metahandlers[0])); 87 } else { 88 metahandlers = Realloc(metahandlers, 89 ((sig + 1) * sizeof (metahandlers[0]))); 90 (void) memset(&metahandlers[metansig], 0, 91 ((sig - metansig) * sizeof (metahandlers[0]))); 92 } 93 metansig = sig; 94 } 95 96 /* We need to have a seperate stack to handle rollback properly */ 97 newhandler.sa_flags = 0; 98 if (sigfillset(&newhandler.sa_mask) < 0) 99 return (mdsyserror(ep, errno, 100 "sigfillset(&newhandler.sa_mask)")); 101 newhandler.sa_handler = handler; 102 103 /* push handler */ 104 if (sigaction(sig, &newhandler, &metahandlers[sig]) < 0) 105 return (mdsyserror(ep, errno, "sigaction(&newhandler)")); 106 107 /* return success */ 108 return (0); 109 } 110 111 static int 112 md_popsig( 113 unsigned sig, 114 md_error_t *ep 115 ) 116 { 117 /* can't pop what isn't pushed */ 118 assert(sig <= metansig); 119 assert(metahandlers[sig].sa_handler != md_catcher); 120 121 /* pop handler */ 122 if (sigaction(sig, &metahandlers[sig], NULL) < 0) 123 return (mdsyserror(ep, errno, "sigaction(&metahandlers)")); 124 125 /* return success */ 126 return (0); 127 } 128 129 char * 130 meta_lock_name( 131 set_t setno 132 ) 133 { 134 char lockname[30]; 135 136 if (setno == MD_LOCAL_SET) 137 return (strdup(METALOCK)); 138 139 (void) snprintf(lockname, sizeof (lockname), "%s.%ld", METALOCK, setno); 140 return (strdup(lockname)); 141 } 142 143 #define META_LOCK_FD(sp) ((sp)->lockfd) 144 #define META_LOCK_NAME(sp) (meta_lock_name((sp)->setno)) 145 146 /* 147 * open lock 148 */ 149 static int 150 meta_lock_open( 151 mdsetname_t *sp, 152 md_error_t *ep 153 ) 154 { 155 int lockfd = META_LOCK_FD(sp); 156 char *lockname = META_LOCK_NAME(sp); 157 158 /* check for already open */ 159 if (lockfd >= 0) 160 goto success; 161 assert(lockfd == MD_NO_LOCK); 162 163 /* open and/or create lock file */ 164 if ((lockfd = open(lockname, O_WRONLY, 0)) < 0) { 165 if (errno == EROFS) { 166 lockfd = MD_NO_LOCK; 167 goto success; 168 } 169 if (errno != ENOENT) { 170 (void) mdsyserror(ep, errno, lockname); 171 goto failure; 172 } 173 if ((lockfd = open(lockname, (O_WRONLY|O_CREAT), 174 0644)) < 0) { 175 (void) mdsyserror(ep, errno, lockname); 176 goto failure; 177 } 178 if (fchmod(lockfd, 0644) != 0) { 179 (void) mdsyserror(ep, errno, lockname); 180 goto failure; 181 } 182 } 183 184 /* return success */ 185 success: 186 if (lockname != NULL) 187 free(lockname); 188 META_LOCK_FD(sp) = lockfd; 189 return (0); 190 191 /* flag failure */ 192 failure: 193 if (lockname != NULL) 194 free(lockname); 195 if (lockfd >= 0) 196 (void) close(lockfd); 197 return (-1); 198 } 199 200 static int 201 meta_lock_close( 202 mdsetname_t *sp, 203 md_error_t *ep 204 ) 205 { 206 int retval = 0; 207 208 if (close(META_LOCK_FD(sp)) != 0) { 209 if (ep != NULL) { 210 char *lockname = META_LOCK_NAME(sp); 211 (void) mdsyserror(ep, errno, lockname); 212 if (lockname != NULL) 213 free(lockname); 214 } 215 216 retval = -1; 217 } 218 META_LOCK_FD(sp) = MD_NO_LOCK; 219 return (retval); 220 } 221 222 /* 223 * unlock 224 */ 225 int 226 meta_unlock( 227 mdsetname_t *sp, 228 md_error_t *ep 229 ) 230 { 231 int lockfd = META_LOCK_FD(sp); 232 233 /* ignore read-only filesystem */ 234 if (lockfd == MD_NO_LOCK) 235 return (0); 236 237 assert(lockfd >= 0); 238 239 /* unlock and discard */ 240 if (lockf(lockfd, F_ULOCK, 0) != 0) { 241 (void) mdsyserror(ep, errno, METALOCK); 242 (void) meta_lock_close(sp, NULL); 243 return (-1); 244 } 245 return (meta_lock_close(sp, ep)); 246 } 247 248 /* 249 * lock 250 */ 251 int 252 meta_lock( 253 mdsetname_t *sp, 254 int print_status, 255 md_error_t *ep 256 ) 257 { 258 int lockfd; 259 char *lockname = NULL; 260 261 /* open lock file */ 262 if (meta_lock_open(sp, ep) != 0) { 263 assert(META_LOCK_FD(sp) == MD_NO_LOCK); 264 goto failure; 265 } 266 267 /* ignore read-only filesystem */ 268 if ((lockfd = META_LOCK_FD(sp)) == MD_NO_LOCK) 269 goto success; 270 assert(lockfd >= 0); 271 272 lockname = META_LOCK_NAME(sp); 273 274 /* grab lock */ 275 if (lockf(lockfd, F_TLOCK, 0) != 0) { 276 if ((errno != EACCES) && (errno != EAGAIN)) { 277 (void) mdsyserror(ep, errno, lockname); 278 goto failure; 279 } 280 if (print_status) 281 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 282 "%s: waiting on %s\n"), 283 myname, lockname); 284 if (lockf(lockfd, F_LOCK, 0) != 0) { 285 (void) mdsyserror(ep, errno, lockname); 286 goto failure; 287 } 288 } 289 290 /* return success */ 291 success: 292 if (lockname != NULL) 293 free(lockname); 294 return (0); 295 296 /* flag failure */ 297 failure: 298 if (lockname != NULL) 299 free(lockname); 300 if (lockfd >= 0) 301 (void) meta_lock_close(sp, ep); 302 return (-1); 303 } 304 305 int 306 meta_lock_nowait( 307 mdsetname_t *sp, 308 md_error_t *ep 309 ) 310 { 311 int lockfd; 312 char *lockname = NULL; 313 314 /* open lock file */ 315 if (meta_lock_open(sp, ep) != 0) { 316 assert(META_LOCK_FD(sp) == MD_NO_LOCK); 317 goto failure; 318 } 319 320 /* ignore read-only filesystem */ 321 if ((lockfd = META_LOCK_FD(sp)) == MD_NO_LOCK) 322 goto success; 323 assert(lockfd >= 0); 324 325 lockname = META_LOCK_NAME(sp); 326 327 /* grab lock */ 328 if (lockf(lockfd, F_TLOCK, 0) != 0) { 329 if ((errno != EACCES) && (errno != EAGAIN)) { 330 (void) mdsyserror(ep, errno, lockname); 331 goto failure; 332 } 333 (void) mdsyserror(ep, EAGAIN, lockname); 334 goto failure; 335 } 336 337 /* return success */ 338 success: 339 if (lockname != NULL) 340 free(lockname); 341 return (0); 342 343 /* flag failure */ 344 failure: 345 if (lockname != NULL) 346 free(lockname); 347 if (lockfd >= 0) 348 (void) meta_lock_close(sp, ep); 349 return (-1); 350 } 351 352 /* 353 * lock status 354 */ 355 int 356 meta_lock_status( 357 mdsetname_t *sp, 358 md_error_t *ep 359 ) 360 { 361 int lockfd; 362 363 /* open lock file */ 364 if (meta_lock_open(sp, ep) != 0) { 365 assert(META_LOCK_FD(sp) == MD_NO_LOCK); 366 return (-1); 367 } 368 369 lockfd = META_LOCK_FD(sp); 370 /* ignore read-only filesystem */ 371 if (lockfd == MD_NO_LOCK) 372 return (0); 373 assert(lockfd >= 0); 374 375 /* test lock */ 376 if (lockf(lockfd, F_TEST, 0) != 0) { 377 char *lockname = META_LOCK_NAME(sp); 378 (void) mdsyserror(ep, errno, lockname); 379 if (lockname != NULL) 380 free(lockname); 381 return (-1); 382 } 383 384 return (0); 385 } 386 387 /* 388 * setup for syslog daemon output 389 */ 390 static void 391 md_syslog( 392 char *name /* name of program */ 393 ) 394 { 395 if ((name == NULL) || (*name == '\0')) 396 name = "md"; 397 openlog(name, LOG_CONS, LOG_DAEMON); 398 metasyslog = 1; 399 } 400 401 /* 402 * daemonize: put in background 403 */ 404 int 405 md_daemonize( 406 mdsetname_t *sp, 407 md_error_t *ep 408 ) 409 { 410 char *p; 411 struct rlimit rlim; 412 pid_t pid; 413 int i; 414 415 /* debug */ 416 if (((p = getenv("MD_DEBUG")) != NULL) && 417 (strstr(p, "NODAEMON") != NULL)) { 418 return (0); /* do nothing */ 419 } 420 421 /* get number of file descriptors */ 422 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) { 423 return (mdsyserror(ep, errno, "getrlimit(RLIMIT_NOFILE)")); 424 } 425 426 /* fork and kill parent */ 427 if ((pid = fork()) == -1) 428 return (mdsyserror(ep, errno, "fork")); 429 else if (pid != 0) 430 return (pid); 431 432 /* 433 * We need to close the admin device and reset the specialfd to force 434 * the child process to reopen it, since we are going to close all 435 * descriptors from 3 up to RLIMIT_NOFILE in the child. 436 */ 437 if (close_admin(ep) != 0) 438 return (-1); 439 440 /* close RPC connections */ 441 metarpccloseall(); 442 443 /* drop lock */ 444 if (meta_unlock(sp, ep) != 0) 445 return (-1); 446 447 if (rlim.rlim_cur != RLIM_INFINITY) { 448 /* 449 * close all but stdout, stderr, and metalogfp 450 */ 451 452 for (i = 0; (i < rlim.rlim_cur); ++i) { 453 if ((i == fileno(stdout)) || 454 (i == fileno(stderr)) || 455 ((metalogfp != NULL) && 456 (i == fileno(metalogfp)))) { 457 continue; 458 } 459 (void) close(i); 460 } 461 } 462 463 /* put in own process group */ 464 if (setsid() == -1) 465 return (mdsyserror(ep, errno, "setsid")); 466 467 /* setup syslog */ 468 md_syslog(myname); 469 470 /* return success */ 471 return (0); 472 } 473 474 /* 475 * flush and sync fp 476 */ 477 static void 478 flushfp( 479 FILE *fp 480 ) 481 { 482 (void) fflush(fp); 483 (void) fsync(fileno(fp)); 484 } 485 486 /* 487 * reset and exit utility 488 */ 489 void 490 md_exit( 491 mdsetname_t *sp, 492 int eval 493 ) 494 { 495 md_error_t status = mdnullerror; 496 md_error_t *ep = &status; 497 498 499 /* close RPC connections */ 500 metarpccloseall(); 501 502 if (sp != NULL) { 503 if (meta_unlock(sp, ep) != 0) { 504 mde_perror(ep, ""); 505 mdclrerror(ep); 506 if (eval == 0) 507 eval = 1; 508 } 509 } 510 511 /* flush name caches */ 512 #ifdef DEBUG 513 metaflushnames(1); 514 #endif /* DEBUG */ 515 516 /* log exit */ 517 if (metalogfp != NULL) { 518 md_logpfx(metalogfp); 519 (void) fprintf(metalogfp, dgettext(TEXT_DOMAIN, 520 "exiting with %d\n"), eval); 521 flushfp(metalogfp); 522 (void) fclose(metalogfp); 523 metalogfp = NULL; 524 } 525 if ((metasyslog) && (eval != 0)) { 526 syslog(LOG_ERR, dgettext(TEXT_DOMAIN, 527 "exiting with %d\n"), eval); 528 closelog(); 529 metasyslog = 0; 530 } 531 532 /* check arena, print malloc usage */ 533 #ifdef _DEBUG_MALLOC_INC 534 (void) malloc_chain_check(1); 535 { 536 char *p; 537 538 if (((p = getenv("MD_DEBUG")) != NULL) && 539 (strstr(p, "MALLOC") != NULL)) { 540 malloc_inuse_end = malloc_inuse(&malloc_histid_end); 541 (void) fprintf(stderr, "%s: end malloc_inuse %lu\n", 542 myname, malloc_inuse_end); 543 if (malloc_inuse_end != malloc_inuse_begin) { 544 malloc_list(fileno(stderr), 545 malloc_histid_begin, malloc_histid_end); 546 } 547 } 548 } 549 #endif /* _DEBUG_MALLOC_INC */ 550 551 /* exit with value */ 552 exit(eval); 553 } 554 555 /* 556 * signal catcher 557 */ 558 static void 559 md_catcher( 560 int sig 561 ) 562 { 563 char buf[128]; 564 char *msg; 565 md_error_t status = mdnullerror; 566 md_error_t *ep = &status; 567 struct sigaction defhandler; 568 569 /* log signal */ 570 if ((msg = strsignal(sig)) == NULL) { 571 (void) snprintf(buf, sizeof (buf), 572 dgettext(TEXT_DOMAIN, "unknown signal %d"), sig); 573 msg = buf; 574 } 575 md_eprintf("%s\n", msg); 576 577 /* 578 * In roll_back crtical section handling, the first instance of a user 579 * generated signal is caught, a flag is set to allow preemption at a 580 * "convenient" point and md_catcher returns. If the user continues 581 * generate the signal, the second instance will invoke the default 582 * handler and exit. 583 */ 584 if (rb_signal_handling == TRUE) { 585 if (sig != SIGABRT && sig != SIGBUS && sig != SIGSEGV) { 586 if (rb_signal_caught == FALSE) { 587 rb_signal_caught = TRUE; 588 rb_signal_which = sig; 589 return; 590 } 591 } 592 } 593 594 /* let default handler do it's thing */ 595 if (md_popsig(sig, ep) != 0) { 596 mde_perror(ep, ""); 597 mdclrerror(ep); 598 defhandler.sa_flags = 0; 599 if (sigfillset(&defhandler.sa_mask) < 0) { 600 (void) mdsyserror(ep, errno, 601 "sigfillset(&defhandler.sa_mask)"); 602 mde_perror(ep, ""); 603 md_exit(NULL, 1); 604 } 605 defhandler.sa_handler = SIG_DFL; 606 if (sigaction(sig, &defhandler, NULL) < 0) { 607 (void) mdsyserror(ep, errno, "sigaction(&defhandler)"); 608 mde_perror(ep, ""); 609 md_exit(NULL, 1); 610 } 611 } 612 613 md_post_sig(sig); 614 } 615 616 void 617 md_post_sig(int sig) 618 { 619 if (kill(getpid(), sig) != 0) { 620 md_perror("kill(getpid())"); 621 md_exit(NULL, -sig); 622 } 623 } 624 625 int 626 md_got_sig(void) 627 { 628 return (rb_signal_caught); 629 } 630 631 int 632 md_which_sig(void) 633 { 634 return (rb_signal_which); 635 } 636 637 void 638 md_rb_sig_handling_on(void) 639 { 640 rb_signal_handling = TRUE; 641 } 642 643 void 644 md_rb_sig_handling_off(int sig_seen, int sig) 645 { 646 rb_signal_handling = FALSE; 647 rb_signal_caught = FALSE; 648 rb_signal_which = 0; 649 if (sig_seen) 650 md_post_sig(sig); 651 } 652 653 /* 654 * setup metaclust variables 655 */ 656 void 657 setup_mc_log( 658 uint_t level 659 ) 660 { 661 /* initialise externals */ 662 verbosity = level; 663 start_time = gethrtime(); 664 } 665 666 /* 667 * initilize utility 668 */ 669 int 670 md_init( 671 int argc, 672 char *argv[], 673 int dosyslog, 674 int doadmin, 675 md_error_t *ep 676 ) 677 { 678 int ret = 0; 679 680 /* initialize everything but the signals */ 681 if ((ret = md_init_nosig(argc, argv, dosyslog, 682 doadmin, ep)) != 0) 683 return (ret); 684 685 686 if (sigfillset(&allsigs) < 0) 687 return (mdsyserror(ep, errno, "sigfillset(&allsigs)")); 688 689 /* catch common signals */ 690 if ((md_pushsig(SIGHUP, md_catcher, ep) != 0) || 691 (md_pushsig(SIGINT, md_catcher, ep) != 0) || 692 (md_pushsig(SIGQUIT, md_catcher, ep) != 0) || 693 (md_pushsig(SIGABRT, md_catcher, ep) != 0) || 694 (md_pushsig(SIGBUS, md_catcher, ep) != 0) || 695 (md_pushsig(SIGSEGV, md_catcher, ep) != 0) || 696 (md_pushsig(SIGPIPE, md_catcher, ep) != 0) || 697 (md_pushsig(SIGTERM, md_catcher, ep) != 0)) { 698 return (-1); 699 } 700 701 /* return success */ 702 return (0); 703 } 704 705 706 /* 707 * initilize utility without setting up sighandlers 708 * setting up signal handlers in libmeta can affect others 709 * programs that link with libmeta but have their own handlers 710 */ 711 int 712 md_init_nosig( 713 int argc, 714 char *argv[], 715 int dosyslog, 716 int doadmin, 717 md_error_t *ep 718 ) 719 { 720 /* setup myname */ 721 if ((myname = strrchr(argv[0], '/')) != NULL) 722 ++myname; 723 else 724 myname = argv[0]; 725 726 #if !defined(TEXT_DOMAIN) 727 #define TEXT_DOMAIN "SYS_TEST" 728 #endif 729 730 /* print malloc usage */ 731 #ifdef _DEBUG_MALLOC_INC 732 { 733 char *p; 734 735 if (((p = getenv("MD_DEBUG")) != NULL) && 736 (strstr(p, "MALLOC") != NULL)) { 737 malloc_inuse_begin = 738 malloc_inuse(&malloc_histid_begin); 739 (void) fprintf(stderr, "%s: begin malloc_inuse %lu\n", 740 myname, malloc_inuse_begin); 741 } 742 } 743 #endif /* _DEBUG_MALLOC_INC */ 744 745 /* open syslog */ 746 if (dosyslog) 747 md_syslog(myname); 748 749 /* log command */ 750 if (getenv(METALOGENV) != NULL) { 751 if ((metalogfp = fopen(METALOG, "a")) != NULL) { 752 int i; 753 754 (void) fchmod(fileno(metalogfp), 0664); 755 md_logpfx(metalogfp); 756 for (i = 1; (i < argc); ++i) 757 (void) fprintf(metalogfp, " %s", argv[i]); 758 (void) fprintf(metalogfp, "\n"); 759 flushfp(metalogfp); 760 } 761 } 762 763 /* make sure we can open the admin device before we do anything else */ 764 if (doadmin) 765 if (open_admin(ep) < 0) 766 return (-1); 767 768 /* flush name caches */ 769 metaflushnames(1); 770 771 /* return success */ 772 return (0); 773 } 774 775 /* 776 * (re)initilize daemon 777 */ 778 int 779 md_init_daemon( 780 char *name, 781 md_error_t *ep 782 ) 783 { 784 static int already = 0; 785 int dosyslog = 1; 786 int doadmin = 1; 787 788 /* setup */ 789 if (! already) { 790 if (md_init(1, &name, dosyslog, doadmin, ep) != 0) 791 return (-1); 792 already = 1; 793 } 794 795 /* return success */ 796 return (0); 797 } 798 799 /* 800 * Roll back functions for handling sync and async cleanup. 801 */ 802 803 int 804 procsigs(int block, sigset_t *oldsigs, md_error_t *ep) 805 { 806 if (block == TRUE) { 807 if (sigprocmask(SIG_BLOCK, &allsigs, oldsigs) < 0) { 808 (void) mdsyserror(ep, errno, "sigprocmask(SIG_BLOCK)"); 809 return (-1); 810 } 811 } else { 812 if (sigprocmask(SIG_SETMASK, oldsigs, NULL) < 0) { 813 (void) mdsyserror(ep, errno, 814 "sigprocmask(SIG_SETMASK)"); 815 return (-1); 816 } 817 } 818 return (0); 819 } 820 821 #ifdef DEBUG 822 int 823 rb_test( 824 int rbt_sel_tpt, 825 char *rbt_sel_tag, 826 md_error_t *ep 827 ) 828 { 829 char *rbt_env_tpt = getenv("META_RBT_TPT"); 830 char *rbt_env_tag = getenv("META_RBT_TAG"); 831 int sig = 0; 832 int rbt_int_tpt; 833 int rbt_tag_match = 1; 834 sigset_t curmask; 835 md_error_t xep = mdnullerror; 836 837 if (rbt_env_tpt) { 838 rbt_int_tpt = atoi(rbt_env_tpt); 839 if (rbt_int_tpt < 0) { 840 sig = 1; 841 rbt_int_tpt = -1 * rbt_int_tpt; 842 } 843 844 assert(rbt_sel_tpt != 0); 845 846 if (rbt_int_tpt == 0) 847 return (0); 848 849 if (rbt_env_tag && rbt_sel_tag) 850 if (strcmp(rbt_env_tag, rbt_sel_tag) != 0) 851 rbt_tag_match = 0; 852 853 if (rbt_int_tpt == rbt_sel_tpt && rbt_tag_match) { 854 md_eprintf( 855 "******************** RB_TEST(%s, %d, sig=%s)\n", 856 rbt_sel_tag, rbt_sel_tpt, 857 (sig != 0) ? "True" : "False"); 858 if (sig) { 859 md_eprintf("********** sigsuspend()\n"); 860 if (sigprocmask(NULL, NULL, &curmask) < 0) { 861 (void) mdsyserror(&xep, errno, NULL); 862 mde_perror(&xep, "sigprocmask(GET)"); 863 md_exit(NULL, 1); 864 } 865 866 if (sigsuspend(&curmask) < 0) { 867 (void) mdsyserror(&xep, errno, NULL); 868 mde_perror(&xep, 869 "sigsuspend(&curmask)"); 870 md_exit(NULL, 1); 871 } 872 873 if (md_got_sig()) 874 return (-1); 875 } 876 (void) mderror(ep, MDE_TESTERROR, 877 "********** rb_test()"); 878 md_eprintf("******************** rollback\n"); 879 return (-1); 880 } 881 } 882 return (0); 883 } 884 #else 885 /* ARGSUSED */ 886 int 887 rb_test( 888 int rbt_sel_tpt, 889 char *rbt_sel_tag, 890 md_error_t *ep 891 ) 892 { 893 (void) mderror(ep, MDE_TESTERROR, "******** rb_test:Not supported\n"); 894 return (-1); 895 896 } 897 #endif /* DEBUG */ 898