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/OPENSOLARIS.LICENSE 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/OPENSOLARIS.LICENSE. 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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * RCM module providing support for swap areas 30 * during reconfiguration operations. 31 */ 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <fcntl.h> 35 #include <thread.h> 36 #include <synch.h> 37 #include <strings.h> 38 #include <assert.h> 39 #include <errno.h> 40 #include <libintl.h> 41 #include <sys/types.h> 42 #include <sys/swap.h> 43 #include <sys/stat.h> 44 #include <sys/param.h> 45 #include <sys/dumpadm.h> 46 #include <sys/wait.h> 47 #include "rcm_module.h" 48 49 /* cache flags */ 50 #define SWAP_CACHE_NEW 0x01 51 #define SWAP_CACHE_STALE 0x02 52 #define SWAP_CACHE_OFFLINED 0x04 53 54 #define SWAP_CMD "/usr/sbin/swap" 55 #define SWAP_DELETE SWAP_CMD" -d %s %ld" 56 #define SWAP_ADD SWAP_CMD" -a %s %ld %ld" 57 58 /* LP64 hard code */ 59 #define MAXOFFSET_STRLEN 20 60 61 typedef struct swap_file { 62 char path[MAXPATHLEN]; 63 int cache_flags; 64 struct swap_area *areas; 65 struct swap_file *next; 66 struct swap_file *prev; 67 } swap_file_t; 68 69 /* swap file may have multiple swap areas */ 70 typedef struct swap_area { 71 off_t start; 72 off_t len; 73 int cache_flags; 74 struct swap_area *next; 75 struct swap_area *prev; 76 } swap_area_t; 77 78 static swap_file_t *cache; 79 static mutex_t cache_lock; 80 81 static int swap_register(rcm_handle_t *); 82 static int swap_unregister(rcm_handle_t *); 83 static int swap_getinfo(rcm_handle_t *, char *, id_t, uint_t, 84 char **, char **, nvlist_t *, rcm_info_t **); 85 static int swap_suspend(rcm_handle_t *, char *, id_t, timespec_t *, 86 uint_t, char **, rcm_info_t **); 87 static int swap_resume(rcm_handle_t *, char *, id_t, uint_t, 88 char **, rcm_info_t **); 89 static int swap_offline(rcm_handle_t *, char *, id_t, uint_t, 90 char **, rcm_info_t **); 91 static int swap_online(rcm_handle_t *, char *, id_t, uint_t, 92 char **, rcm_info_t **); 93 static int swap_remove(rcm_handle_t *, char *, id_t, uint_t, 94 char **, rcm_info_t **); 95 96 static int alloc_usage(char **); 97 static void cache_insert(swap_file_t *); 98 static swap_file_t *cache_lookup(char *); 99 static void cache_remove(swap_file_t *); 100 static void free_cache(void); 101 static int get_dumpdev(char []); 102 static void log_cmd_status(int); 103 static int swap_add(swap_file_t *, char **); 104 static void swap_area_add(swap_file_t *, swap_area_t *); 105 static swap_area_t *swap_area_alloc(swapent_t *); 106 static swap_area_t *swap_area_lookup(swap_file_t *, swapent_t *); 107 static void swap_area_remove(swap_file_t *, swap_area_t *); 108 static int swap_delete(swap_file_t *, char **); 109 static swap_file_t *swap_file_alloc(char *); 110 static void swap_file_free(swap_file_t *); 111 static swaptbl_t *sys_swaptbl(void); 112 static int update_cache(rcm_handle_t *); 113 114 static struct rcm_mod_ops swap_ops = 115 { 116 RCM_MOD_OPS_VERSION, 117 swap_register, 118 swap_unregister, 119 swap_getinfo, 120 swap_suspend, 121 swap_resume, 122 swap_offline, 123 swap_online, 124 swap_remove, 125 NULL, 126 NULL, 127 NULL 128 }; 129 130 struct rcm_mod_ops * 131 rcm_mod_init() 132 { 133 return (&swap_ops); 134 } 135 136 const char * 137 rcm_mod_info() 138 { 139 return ("RCM Swap module 1.5"); 140 } 141 142 int 143 rcm_mod_fini() 144 { 145 free_cache(); 146 (void) mutex_destroy(&cache_lock); 147 148 return (RCM_SUCCESS); 149 } 150 151 static int 152 swap_register(rcm_handle_t *hdl) 153 { 154 return (update_cache(hdl)); 155 } 156 157 static int 158 swap_unregister(rcm_handle_t *hdl) 159 { 160 swap_file_t *sf; 161 162 (void) mutex_lock(&cache_lock); 163 while ((sf = cache) != NULL) { 164 cache = cache->next; 165 (void) rcm_unregister_interest(hdl, sf->path, 0); 166 swap_file_free(sf); 167 } 168 (void) mutex_unlock(&cache_lock); 169 170 return (RCM_SUCCESS); 171 } 172 173 /*ARGSUSED*/ 174 static int 175 swap_getinfo(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 176 char **infostr, char **errstr, nvlist_t *props, rcm_info_t **dependent) 177 { 178 assert(rsrcname != NULL && infostr != NULL); 179 180 (void) mutex_lock(&cache_lock); 181 if (cache_lookup(rsrcname) == NULL) { 182 rcm_log_message(RCM_ERROR, "unknown resource: %s\n", 183 rsrcname); 184 (void) mutex_unlock(&cache_lock); 185 return (RCM_FAILURE); 186 } 187 (void) mutex_unlock(&cache_lock); 188 (void) alloc_usage(infostr); 189 190 return (RCM_SUCCESS); 191 } 192 193 /* 194 * Remove swap space to maintain availability of anonymous pages 195 * during device suspension. Swap will be reconfigured upon resume. 196 * Fail if operation will unconfigure dump device. 197 */ 198 /*ARGSUSED*/ 199 static int 200 swap_suspend(rcm_handle_t *hdl, char *rsrcname, id_t id, timespec_t *interval, 201 uint_t flags, char **errstr, rcm_info_t **dependent) 202 { 203 swap_file_t *sf; 204 int rv; 205 206 assert(rsrcname != NULL && errstr != NULL); 207 208 if (flags & RCM_QUERY) 209 return (RCM_SUCCESS); 210 211 (void) mutex_lock(&cache_lock); 212 if ((sf = cache_lookup(rsrcname)) == NULL) { 213 (void) mutex_unlock(&cache_lock); 214 return (RCM_SUCCESS); 215 } 216 217 rv = swap_delete(sf, errstr); 218 (void) mutex_unlock(&cache_lock); 219 220 return (rv); 221 } 222 223 /*ARGSUSED*/ 224 static int 225 swap_resume(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 226 char **errstr, rcm_info_t **dependent) 227 { 228 swap_file_t *sf; 229 int rv; 230 231 assert(rsrcname != NULL && errstr != NULL); 232 233 (void) mutex_lock(&cache_lock); 234 if ((sf = cache_lookup(rsrcname)) == NULL) { 235 (void) mutex_unlock(&cache_lock); 236 return (RCM_SUCCESS); 237 } 238 239 rv = swap_add(sf, errstr); 240 (void) mutex_unlock(&cache_lock); 241 242 return (rv); 243 } 244 245 /* 246 * By default, reject offline request. If forced, attempt to 247 * delete swap. Fail if operation will unconfigure dump device. 248 */ 249 /*ARGSUSED*/ 250 static int 251 swap_offline(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 252 char **errstr, rcm_info_t **dependent) 253 { 254 swap_file_t *sf; 255 int rv; 256 257 assert(rsrcname != NULL && errstr != NULL); 258 259 if ((flags & RCM_FORCE) && (flags & RCM_QUERY)) 260 return (RCM_SUCCESS); 261 262 (void) mutex_lock(&cache_lock); 263 if ((sf = cache_lookup(rsrcname)) == NULL) { 264 (void) mutex_unlock(&cache_lock); 265 return (RCM_SUCCESS); 266 } 267 268 if (flags & RCM_FORCE) { 269 rv = swap_delete(sf, errstr); 270 (void) mutex_unlock(&cache_lock); 271 return (rv); 272 } 273 /* default reject */ 274 (void) mutex_unlock(&cache_lock); 275 (void) alloc_usage(errstr); 276 277 return (RCM_FAILURE); 278 } 279 280 /*ARGSUSED*/ 281 static int 282 swap_online(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 283 char **errstr, rcm_info_t **dependent) 284 { 285 swap_file_t *sf; 286 int rv; 287 288 assert(rsrcname != NULL && errstr != NULL); 289 290 (void) mutex_lock(&cache_lock); 291 if ((sf = cache_lookup(rsrcname)) == NULL) { 292 (void) mutex_unlock(&cache_lock); 293 return (RCM_SUCCESS); 294 } 295 296 rv = swap_add(sf, errstr); 297 (void) mutex_unlock(&cache_lock); 298 299 return (rv); 300 } 301 302 /*ARGSUSED*/ 303 static int 304 swap_remove(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 305 char **errstr, rcm_info_t **dependent) 306 { 307 swap_file_t *sf; 308 309 assert(rsrcname != NULL); 310 311 (void) mutex_lock(&cache_lock); 312 if ((sf = cache_lookup(rsrcname)) == NULL) { 313 (void) mutex_unlock(&cache_lock); 314 return (RCM_SUCCESS); 315 } 316 /* RCM framework handles unregistration */ 317 cache_remove(sf); 318 swap_file_free(sf); 319 (void) mutex_unlock(&cache_lock); 320 321 return (RCM_SUCCESS); 322 } 323 324 /* 325 * Delete all swap areas for swap file. 326 * Invoke swap(1M) instead of swapctl(2) to 327 * handle relocation of dump device. 328 * If dump device is configured, fail if 329 * unable to relocate dump. 330 * 331 * Call with cache_lock held. 332 */ 333 static int 334 swap_delete(swap_file_t *sf, char **errstr) 335 { 336 swap_area_t *sa; 337 char cmd[sizeof (SWAP_DELETE) + MAXPATHLEN + 338 MAXOFFSET_STRLEN]; 339 char dumpdev[MAXPATHLEN]; 340 int have_dump = 1; 341 int stat; 342 int rv = RCM_SUCCESS; 343 344 if (get_dumpdev(dumpdev) == 0 && dumpdev[0] == '\0') 345 have_dump = 0; 346 347 for (sa = sf->areas; sa != NULL; sa = sa->next) { 348 /* swap(1M) is not idempotent */ 349 if (sa->cache_flags & SWAP_CACHE_OFFLINED) { 350 continue; 351 } 352 353 (void) snprintf(cmd, sizeof (cmd), SWAP_DELETE, sf->path, 354 sa->start); 355 rcm_log_message(RCM_TRACE1, "%s\n", cmd); 356 if ((stat = rcm_exec_cmd(cmd)) != 0) { 357 log_cmd_status(stat); 358 *errstr = strdup(gettext("unable to delete swap")); 359 rv = RCM_FAILURE; 360 goto out; 361 } 362 sa->cache_flags |= SWAP_CACHE_OFFLINED; 363 364 /* 365 * Fail on removal of dump device. 366 */ 367 if (have_dump == 0) 368 continue; 369 370 if (get_dumpdev(dumpdev) != 0) { 371 rcm_log_message(RCM_WARNING, "unable to " 372 "check for removal of dump device\n"); 373 } else if (dumpdev[0] == '\0') { 374 rcm_log_message(RCM_DEBUG, "removed dump: " 375 "attempting recovery\n"); 376 377 /* 378 * Restore dump 379 */ 380 (void) snprintf(cmd, sizeof (cmd), SWAP_ADD, 381 sf->path, sa->start, sa->len); 382 rcm_log_message(RCM_TRACE1, "%s\n", cmd); 383 if ((stat = rcm_exec_cmd(cmd)) != 0) { 384 log_cmd_status(stat); 385 rcm_log_message(RCM_ERROR, 386 "failed to restore dump\n"); 387 } else { 388 sa->cache_flags &= ~SWAP_CACHE_OFFLINED; 389 rcm_log_message(RCM_DEBUG, "dump restored\n"); 390 } 391 *errstr = strdup(gettext("unable to relocate dump")); 392 rv = RCM_FAILURE; 393 goto out; 394 } 395 } 396 sf->cache_flags |= SWAP_CACHE_OFFLINED; 397 out: 398 return (rv); 399 } 400 401 /* 402 * Invoke swap(1M) to add each registered swap area. 403 * 404 * Call with cache_lock held. 405 */ 406 static int 407 swap_add(swap_file_t *sf, char **errstr) 408 { 409 swap_area_t *sa; 410 char cmd[sizeof (SWAP_ADD) + MAXPATHLEN + 411 (2 * MAXOFFSET_STRLEN)]; 412 int stat; 413 int rv = RCM_SUCCESS; 414 415 for (sa = sf->areas; sa != NULL; sa = sa->next) { 416 /* swap(1M) is not idempotent */ 417 if (!(sa->cache_flags & SWAP_CACHE_OFFLINED)) { 418 continue; 419 } 420 421 (void) snprintf(cmd, sizeof (cmd), 422 SWAP_ADD, sf->path, sa->start, sa->len); 423 rcm_log_message(RCM_TRACE1, "%s\n", cmd); 424 if ((stat = rcm_exec_cmd(cmd)) != 0) { 425 log_cmd_status(stat); 426 *errstr = strdup(gettext("unable to add swap")); 427 rv = RCM_FAILURE; 428 break; 429 } else { 430 sa->cache_flags &= ~SWAP_CACHE_OFFLINED; 431 sf->cache_flags &= ~SWAP_CACHE_OFFLINED; 432 } 433 } 434 435 return (rv); 436 } 437 438 static int 439 update_cache(rcm_handle_t *hdl) 440 { 441 swaptbl_t *swt; 442 swap_file_t *sf, *stale_sf; 443 swap_area_t *sa, *stale_sa; 444 int i; 445 int rv = RCM_SUCCESS; 446 447 if ((swt = sys_swaptbl()) == NULL) { 448 rcm_log_message(RCM_ERROR, "failed to read " 449 "current swap configuration\n"); 450 return (RCM_FAILURE); 451 } 452 453 (void) mutex_lock(&cache_lock); 454 455 /* 456 * cache pass 1 - mark everyone stale 457 */ 458 for (sf = cache; sf != NULL; sf = sf->next) { 459 sf->cache_flags |= SWAP_CACHE_STALE; 460 for (sa = sf->areas; sa != NULL; sa = sa->next) { 461 sa->cache_flags |= SWAP_CACHE_STALE; 462 } 463 } 464 465 /* 466 * add new entries 467 */ 468 for (i = 0; i < swt->swt_n; i++) { 469 if (swt->swt_ent[i].ste_flags & (ST_INDEL|ST_DOINGDEL)) { 470 continue; 471 } 472 473 /* 474 * assure swap_file_t 475 */ 476 if ((sf = cache_lookup(swt->swt_ent[i].ste_path)) == NULL) { 477 if ((sf = swap_file_alloc(swt->swt_ent[i].ste_path)) == 478 NULL) { 479 free(swt); 480 return (RCM_FAILURE); 481 } 482 sf->cache_flags |= SWAP_CACHE_NEW; 483 cache_insert(sf); 484 } else { 485 sf->cache_flags &= ~SWAP_CACHE_STALE; 486 } 487 488 /* 489 * assure swap_area_t 490 */ 491 if ((sa = swap_area_lookup(sf, &swt->swt_ent[i])) == NULL) { 492 if ((sa = swap_area_alloc(&swt->swt_ent[i])) == NULL) { 493 free(swt); 494 return (RCM_FAILURE); 495 } 496 swap_area_add(sf, sa); 497 } else { 498 sa->cache_flags &= ~SWAP_CACHE_STALE; 499 } 500 } 501 502 free(swt); 503 504 /* 505 * cache pass 2 506 * 507 * swap_file_t - skip offlined, register new, unregister/remove stale 508 * swap_area_t - skip offlined, remove stale 509 */ 510 sf = cache; 511 while (sf != NULL) { 512 sa = sf->areas; 513 while (sa != NULL) { 514 if (sa->cache_flags & SWAP_CACHE_OFFLINED) { 515 sa->cache_flags &= ~SWAP_CACHE_STALE; 516 sa = sa->next; 517 continue; 518 } 519 if (sa->cache_flags & SWAP_CACHE_STALE) { 520 stale_sa = sa; 521 sa = sa->next; 522 swap_area_remove(sf, stale_sa); 523 free(stale_sa); 524 continue; 525 } 526 sa = sa->next; 527 } 528 529 if (sf->cache_flags & SWAP_CACHE_OFFLINED) { 530 sf->cache_flags &= ~SWAP_CACHE_STALE; 531 sf = sf->next; 532 continue; 533 } 534 535 if (sf->cache_flags & SWAP_CACHE_STALE) { 536 if (rcm_unregister_interest(hdl, sf->path, 0) != 537 RCM_SUCCESS) { 538 rcm_log_message(RCM_ERROR, "failed to register " 539 "%s\n", sf->path); 540 } 541 stale_sf = sf; 542 sf = sf->next; 543 cache_remove(stale_sf); 544 swap_file_free(stale_sf); 545 continue; 546 } 547 548 if (!(sf->cache_flags & SWAP_CACHE_NEW)) { 549 sf = sf->next; 550 continue; 551 } 552 553 if (rcm_register_interest(hdl, sf->path, 0, NULL) != 554 RCM_SUCCESS) { 555 rcm_log_message(RCM_ERROR, "failed to register %s\n", 556 sf->path); 557 rv = RCM_FAILURE; 558 } else { 559 rcm_log_message(RCM_DEBUG, "registered %s\n", 560 sf->path); 561 sf->cache_flags &= ~SWAP_CACHE_NEW; 562 } 563 sf = sf->next; 564 } 565 (void) mutex_unlock(&cache_lock); 566 567 return (rv); 568 } 569 570 /* 571 * Returns system swap table. 572 */ 573 static swaptbl_t * 574 sys_swaptbl() 575 { 576 swaptbl_t *swt; 577 char *cp; 578 int i, n; 579 size_t tbl_size; 580 581 if ((n = swapctl(SC_GETNSWP, NULL)) == -1) 582 return (NULL); 583 584 tbl_size = sizeof (int) + n * sizeof (swapent_t) + n * MAXPATHLEN; 585 if ((swt = (swaptbl_t *)malloc(tbl_size)) == NULL) 586 return (NULL); 587 588 swt->swt_n = n; 589 cp = (char *)swt + (sizeof (int) + n * sizeof (swapent_t)); 590 for (i = 0; i < n; i++) { 591 swt->swt_ent[i].ste_path = cp; 592 cp += MAXPATHLEN; 593 } 594 595 if ((n = swapctl(SC_LIST, swt)) == -1) { 596 free(swt); 597 return (NULL); 598 } 599 600 if (n != swt->swt_n) { 601 /* mismatch, try again */ 602 free(swt); 603 return (sys_swaptbl()); 604 } 605 606 return (swt); 607 } 608 609 static int 610 get_dumpdev(char dumpdev[]) 611 { 612 int fd; 613 int rv = 0; 614 char *err; 615 616 if ((fd = open("/dev/dump", O_RDONLY)) == -1) { 617 rcm_log_message(RCM_ERROR, "failed to open /dev/dump\n"); 618 return (-1); 619 } 620 621 if (ioctl(fd, DIOCGETDEV, dumpdev) == -1) { 622 if (errno == ENODEV) { 623 dumpdev[0] = '\0'; 624 } else { 625 rcm_log_message(RCM_ERROR, "ioctl: %s\n", 626 ((err = strerror(errno)) == NULL) ? "" : err); 627 rv = -1; 628 } 629 } 630 (void) close(fd); 631 632 return (rv); 633 } 634 635 static void 636 free_cache(void) 637 { 638 swap_file_t *sf; 639 640 (void) mutex_lock(&cache_lock); 641 while ((sf = cache) != NULL) { 642 cache = cache->next; 643 swap_file_free(sf); 644 } 645 (void) mutex_unlock(&cache_lock); 646 647 } 648 649 /* 650 * Call with cache_lock held. 651 */ 652 static void 653 swap_file_free(swap_file_t *sf) 654 { 655 swap_area_t *sa; 656 657 assert(sf != NULL); 658 659 while ((sa = sf->areas) != NULL) { 660 sf->areas = sf->areas->next; 661 free(sa); 662 } 663 free(sf); 664 } 665 666 /* 667 * Call with cache_lock held. 668 */ 669 static void 670 cache_insert(swap_file_t *ent) 671 { 672 ent->next = cache; 673 if (ent->next) 674 ent->next->prev = ent; 675 ent->prev = NULL; 676 cache = ent; 677 } 678 679 /* 680 * Call with cache_lock held. 681 */ 682 static swap_file_t * 683 cache_lookup(char *rsrc) 684 { 685 swap_file_t *sf; 686 687 for (sf = cache; sf != NULL; sf = sf->next) { 688 if (strcmp(rsrc, sf->path) == 0) { 689 return (sf); 690 } 691 } 692 return (NULL); 693 } 694 695 /* 696 * Call with cache_lock held. 697 */ 698 static void 699 cache_remove(swap_file_t *ent) 700 { 701 assert(ent != NULL); 702 703 if (ent->next != NULL) { 704 ent->next->prev = ent->prev; 705 } 706 if (ent->prev != NULL) { 707 ent->prev->next = ent->next; 708 } else { 709 cache = ent->next; 710 } 711 ent->next = NULL; 712 ent->prev = NULL; 713 } 714 715 /* 716 * Call with cache_lock held. 717 */ 718 static void 719 swap_area_add(swap_file_t *sf, swap_area_t *sa) 720 { 721 sa->next = sf->areas; 722 if (sa->next) 723 sa->next->prev = sa; 724 sa->prev = NULL; 725 sf->areas = sa; 726 } 727 728 /* 729 * Call with cache_lock held. 730 */ 731 static void 732 swap_area_remove(swap_file_t *sf, swap_area_t *ent) 733 { 734 assert(sf != NULL && ent != NULL); 735 736 if (ent->next != NULL) { 737 ent->next->prev = ent->prev; 738 } 739 if (ent->prev != NULL) { 740 ent->prev->next = ent->next; 741 } else { 742 sf->areas = ent->next; 743 } 744 ent->next = NULL; 745 ent->prev = NULL; 746 } 747 748 static swap_file_t * 749 swap_file_alloc(char *rsrc) 750 { 751 swap_file_t *sf; 752 753 if ((sf = calloc(1, sizeof (*sf))) == NULL) { 754 rcm_log_message(RCM_ERROR, "calloc failure\n"); 755 return (NULL); 756 } 757 (void) strlcpy(sf->path, rsrc, sizeof (sf->path)); 758 759 return (sf); 760 } 761 762 static swap_area_t * 763 swap_area_alloc(swapent_t *swt_ent) 764 { 765 swap_area_t *sa; 766 767 if ((sa = calloc(1, sizeof (*sa))) == NULL) { 768 rcm_log_message(RCM_ERROR, "calloc failure\n"); 769 return (NULL); 770 } 771 sa->start = swt_ent->ste_start; 772 sa->len = swt_ent->ste_length; 773 774 return (sa); 775 } 776 777 /* 778 * Call with cache_lock held. 779 */ 780 static swap_area_t * 781 swap_area_lookup(swap_file_t *sf, swapent_t *swt_ent) 782 { 783 swap_area_t *sa; 784 785 assert(sf != NULL && swt_ent != NULL); 786 assert(strcmp(sf->path, swt_ent->ste_path) == 0); 787 788 for (sa = sf->areas; sa != NULL; sa = sa->next) { 789 if (sa->start == swt_ent->ste_start && 790 sa->len == swt_ent->ste_length) { 791 return (sa); 792 } 793 } 794 return (NULL); 795 } 796 797 /* 798 * All-purpose usage string. 799 */ 800 static int 801 alloc_usage(char **cpp) 802 { 803 if ((*cpp = strdup(gettext("swap area"))) == NULL) { 804 rcm_log_message(RCM_ERROR, "strdup failure\n"); 805 return (-1); 806 } 807 return (0); 808 } 809 810 static void 811 log_cmd_status(int stat) 812 { 813 char *err; 814 815 if (stat == -1) { 816 rcm_log_message(RCM_ERROR, "wait: %s\n", 817 ((err = strerror(errno)) == NULL) ? "" : err); 818 } else if (WIFEXITED(stat)) { 819 rcm_log_message(RCM_ERROR, "exit status: %d\n", 820 WEXITSTATUS(stat)); 821 } else { 822 rcm_log_message(RCM_ERROR, "wait status: %d\n", stat); 823 } 824 } 825