17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*648495d6Svikram * Common Development and Distribution License (the "License"). 6*648495d6Svikram * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*648495d6Svikram * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * RCM module providing support for swap areas 307c478bd9Sstevel@tonic-gate * during reconfiguration operations. 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <unistd.h> 347c478bd9Sstevel@tonic-gate #include <fcntl.h> 357c478bd9Sstevel@tonic-gate #include <thread.h> 367c478bd9Sstevel@tonic-gate #include <synch.h> 377c478bd9Sstevel@tonic-gate #include <strings.h> 387c478bd9Sstevel@tonic-gate #include <assert.h> 397c478bd9Sstevel@tonic-gate #include <errno.h> 407c478bd9Sstevel@tonic-gate #include <libintl.h> 417c478bd9Sstevel@tonic-gate #include <sys/types.h> 427c478bd9Sstevel@tonic-gate #include <sys/swap.h> 437c478bd9Sstevel@tonic-gate #include <sys/stat.h> 447c478bd9Sstevel@tonic-gate #include <sys/param.h> 457c478bd9Sstevel@tonic-gate #include <sys/dumpadm.h> 467c478bd9Sstevel@tonic-gate #include <sys/wait.h> 477c478bd9Sstevel@tonic-gate #include "rcm_module.h" 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* cache flags */ 507c478bd9Sstevel@tonic-gate #define SWAP_CACHE_NEW 0x01 517c478bd9Sstevel@tonic-gate #define SWAP_CACHE_STALE 0x02 527c478bd9Sstevel@tonic-gate #define SWAP_CACHE_OFFLINED 0x04 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #define SWAP_CMD "/usr/sbin/swap" 557c478bd9Sstevel@tonic-gate #define SWAP_DELETE SWAP_CMD" -d %s %ld" 567c478bd9Sstevel@tonic-gate #define SWAP_ADD SWAP_CMD" -a %s %ld %ld" 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate /* LP64 hard code */ 597c478bd9Sstevel@tonic-gate #define MAXOFFSET_STRLEN 20 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate typedef struct swap_file { 627c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 637c478bd9Sstevel@tonic-gate int cache_flags; 647c478bd9Sstevel@tonic-gate struct swap_area *areas; 657c478bd9Sstevel@tonic-gate struct swap_file *next; 667c478bd9Sstevel@tonic-gate struct swap_file *prev; 677c478bd9Sstevel@tonic-gate } swap_file_t; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate /* swap file may have multiple swap areas */ 707c478bd9Sstevel@tonic-gate typedef struct swap_area { 717c478bd9Sstevel@tonic-gate off_t start; 727c478bd9Sstevel@tonic-gate off_t len; 737c478bd9Sstevel@tonic-gate int cache_flags; 747c478bd9Sstevel@tonic-gate struct swap_area *next; 757c478bd9Sstevel@tonic-gate struct swap_area *prev; 767c478bd9Sstevel@tonic-gate } swap_area_t; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static swap_file_t *cache; 797c478bd9Sstevel@tonic-gate static mutex_t cache_lock; 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate static int swap_register(rcm_handle_t *); 827c478bd9Sstevel@tonic-gate static int swap_unregister(rcm_handle_t *); 837c478bd9Sstevel@tonic-gate static int swap_getinfo(rcm_handle_t *, char *, id_t, uint_t, 847c478bd9Sstevel@tonic-gate char **, char **, nvlist_t *, rcm_info_t **); 857c478bd9Sstevel@tonic-gate static int swap_suspend(rcm_handle_t *, char *, id_t, timespec_t *, 867c478bd9Sstevel@tonic-gate uint_t, char **, rcm_info_t **); 877c478bd9Sstevel@tonic-gate static int swap_resume(rcm_handle_t *, char *, id_t, uint_t, 887c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 897c478bd9Sstevel@tonic-gate static int swap_offline(rcm_handle_t *, char *, id_t, uint_t, 907c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 917c478bd9Sstevel@tonic-gate static int swap_online(rcm_handle_t *, char *, id_t, uint_t, 927c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 937c478bd9Sstevel@tonic-gate static int swap_remove(rcm_handle_t *, char *, id_t, uint_t, 947c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate static int alloc_usage(char **); 977c478bd9Sstevel@tonic-gate static void cache_insert(swap_file_t *); 987c478bd9Sstevel@tonic-gate static swap_file_t *cache_lookup(char *); 997c478bd9Sstevel@tonic-gate static void cache_remove(swap_file_t *); 1007c478bd9Sstevel@tonic-gate static void free_cache(void); 1017c478bd9Sstevel@tonic-gate static int get_dumpdev(char []); 1027c478bd9Sstevel@tonic-gate static void log_cmd_status(int); 1037c478bd9Sstevel@tonic-gate static int swap_add(swap_file_t *, char **); 1047c478bd9Sstevel@tonic-gate static void swap_area_add(swap_file_t *, swap_area_t *); 1057c478bd9Sstevel@tonic-gate static swap_area_t *swap_area_alloc(swapent_t *); 1067c478bd9Sstevel@tonic-gate static swap_area_t *swap_area_lookup(swap_file_t *, swapent_t *); 1077c478bd9Sstevel@tonic-gate static void swap_area_remove(swap_file_t *, swap_area_t *); 1087c478bd9Sstevel@tonic-gate static int swap_delete(swap_file_t *, char **); 1097c478bd9Sstevel@tonic-gate static swap_file_t *swap_file_alloc(char *); 1107c478bd9Sstevel@tonic-gate static void swap_file_free(swap_file_t *); 1117c478bd9Sstevel@tonic-gate static swaptbl_t *sys_swaptbl(void); 1127c478bd9Sstevel@tonic-gate static int update_cache(rcm_handle_t *); 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static struct rcm_mod_ops swap_ops = 1157c478bd9Sstevel@tonic-gate { 1167c478bd9Sstevel@tonic-gate RCM_MOD_OPS_VERSION, 1177c478bd9Sstevel@tonic-gate swap_register, 1187c478bd9Sstevel@tonic-gate swap_unregister, 1197c478bd9Sstevel@tonic-gate swap_getinfo, 1207c478bd9Sstevel@tonic-gate swap_suspend, 1217c478bd9Sstevel@tonic-gate swap_resume, 1227c478bd9Sstevel@tonic-gate swap_offline, 1237c478bd9Sstevel@tonic-gate swap_online, 1247c478bd9Sstevel@tonic-gate swap_remove, 1257c478bd9Sstevel@tonic-gate NULL, 1267c478bd9Sstevel@tonic-gate NULL, 1277c478bd9Sstevel@tonic-gate NULL 1287c478bd9Sstevel@tonic-gate }; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate struct rcm_mod_ops * 1317c478bd9Sstevel@tonic-gate rcm_mod_init() 1327c478bd9Sstevel@tonic-gate { 1337c478bd9Sstevel@tonic-gate return (&swap_ops); 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate const char * 1377c478bd9Sstevel@tonic-gate rcm_mod_info() 1387c478bd9Sstevel@tonic-gate { 139*648495d6Svikram return ("RCM Swap module 1.5"); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate int 1437c478bd9Sstevel@tonic-gate rcm_mod_fini() 1447c478bd9Sstevel@tonic-gate { 1457c478bd9Sstevel@tonic-gate free_cache(); 1467c478bd9Sstevel@tonic-gate (void) mutex_destroy(&cache_lock); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate static int 1527c478bd9Sstevel@tonic-gate swap_register(rcm_handle_t *hdl) 1537c478bd9Sstevel@tonic-gate { 1547c478bd9Sstevel@tonic-gate return (update_cache(hdl)); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate static int 1587c478bd9Sstevel@tonic-gate swap_unregister(rcm_handle_t *hdl) 1597c478bd9Sstevel@tonic-gate { 1607c478bd9Sstevel@tonic-gate swap_file_t *sf; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 1637c478bd9Sstevel@tonic-gate while ((sf = cache) != NULL) { 1647c478bd9Sstevel@tonic-gate cache = cache->next; 1657c478bd9Sstevel@tonic-gate (void) rcm_unregister_interest(hdl, sf->path, 0); 1667c478bd9Sstevel@tonic-gate swap_file_free(sf); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1747c478bd9Sstevel@tonic-gate static int 1757c478bd9Sstevel@tonic-gate swap_getinfo(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 1767c478bd9Sstevel@tonic-gate char **infostr, char **errstr, nvlist_t *props, rcm_info_t **dependent) 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && infostr != NULL); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 1817c478bd9Sstevel@tonic-gate if (cache_lookup(rsrcname) == NULL) { 1827c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "unknown resource: %s\n", 1837c478bd9Sstevel@tonic-gate rsrcname); 1847c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 1857c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 1887c478bd9Sstevel@tonic-gate (void) alloc_usage(infostr); 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate /* 1947c478bd9Sstevel@tonic-gate * Remove swap space to maintain availability of anonymous pages 1957c478bd9Sstevel@tonic-gate * during device suspension. Swap will be reconfigured upon resume. 1967c478bd9Sstevel@tonic-gate * Fail if operation will unconfigure dump device. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1997c478bd9Sstevel@tonic-gate static int 2007c478bd9Sstevel@tonic-gate swap_suspend(rcm_handle_t *hdl, char *rsrcname, id_t id, timespec_t *interval, 2017c478bd9Sstevel@tonic-gate uint_t flags, char **errstr, rcm_info_t **dependent) 2027c478bd9Sstevel@tonic-gate { 2037c478bd9Sstevel@tonic-gate swap_file_t *sf; 2047c478bd9Sstevel@tonic-gate int rv; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate if (flags & RCM_QUERY) 2097c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 2127c478bd9Sstevel@tonic-gate if ((sf = cache_lookup(rsrcname)) == NULL) { 2137c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2147c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate rv = swap_delete(sf, errstr); 2187c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate return (rv); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2247c478bd9Sstevel@tonic-gate static int 2257c478bd9Sstevel@tonic-gate swap_resume(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 2267c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 2277c478bd9Sstevel@tonic-gate { 2287c478bd9Sstevel@tonic-gate swap_file_t *sf; 2297c478bd9Sstevel@tonic-gate int rv; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 2347c478bd9Sstevel@tonic-gate if ((sf = cache_lookup(rsrcname)) == NULL) { 2357c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2367c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate rv = swap_add(sf, errstr); 2407c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate return (rv); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate /* 2467c478bd9Sstevel@tonic-gate * By default, reject offline request. If forced, attempt to 2477c478bd9Sstevel@tonic-gate * delete swap. Fail if operation will unconfigure dump device. 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2507c478bd9Sstevel@tonic-gate static int 2517c478bd9Sstevel@tonic-gate swap_offline(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 2527c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 2537c478bd9Sstevel@tonic-gate { 2547c478bd9Sstevel@tonic-gate swap_file_t *sf; 2557c478bd9Sstevel@tonic-gate int rv; 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate if ((flags & RCM_FORCE) && (flags & RCM_QUERY)) 2607c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 2637c478bd9Sstevel@tonic-gate if ((sf = cache_lookup(rsrcname)) == NULL) { 2647c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2657c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate if (flags & RCM_FORCE) { 2697c478bd9Sstevel@tonic-gate rv = swap_delete(sf, errstr); 2707c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2717c478bd9Sstevel@tonic-gate return (rv); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate /* default reject */ 2747c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2757c478bd9Sstevel@tonic-gate (void) alloc_usage(errstr); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2817c478bd9Sstevel@tonic-gate static int 2827c478bd9Sstevel@tonic-gate swap_online(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 2837c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 2847c478bd9Sstevel@tonic-gate { 2857c478bd9Sstevel@tonic-gate swap_file_t *sf; 2867c478bd9Sstevel@tonic-gate int rv; 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 2917c478bd9Sstevel@tonic-gate if ((sf = cache_lookup(rsrcname)) == NULL) { 2927c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2937c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate rv = swap_add(sf, errstr); 2977c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate return (rv); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3037c478bd9Sstevel@tonic-gate static int 3047c478bd9Sstevel@tonic-gate swap_remove(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 3057c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 3067c478bd9Sstevel@tonic-gate { 3077c478bd9Sstevel@tonic-gate swap_file_t *sf; 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate assert(rsrcname != NULL); 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 3127c478bd9Sstevel@tonic-gate if ((sf = cache_lookup(rsrcname)) == NULL) { 3137c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 3147c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate /* RCM framework handles unregistration */ 3177c478bd9Sstevel@tonic-gate cache_remove(sf); 3187c478bd9Sstevel@tonic-gate swap_file_free(sf); 3197c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /* 3257c478bd9Sstevel@tonic-gate * Delete all swap areas for swap file. 3267c478bd9Sstevel@tonic-gate * Invoke swap(1M) instead of swapctl(2) to 3277c478bd9Sstevel@tonic-gate * handle relocation of dump device. 3287c478bd9Sstevel@tonic-gate * If dump device is configured, fail if 3297c478bd9Sstevel@tonic-gate * unable to relocate dump. 3307c478bd9Sstevel@tonic-gate * 3317c478bd9Sstevel@tonic-gate * Call with cache_lock held. 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate static int 3347c478bd9Sstevel@tonic-gate swap_delete(swap_file_t *sf, char **errstr) 3357c478bd9Sstevel@tonic-gate { 3367c478bd9Sstevel@tonic-gate swap_area_t *sa; 3377c478bd9Sstevel@tonic-gate char cmd[sizeof (SWAP_DELETE) + MAXPATHLEN + 3387c478bd9Sstevel@tonic-gate MAXOFFSET_STRLEN]; 3397c478bd9Sstevel@tonic-gate char dumpdev[MAXPATHLEN]; 3407c478bd9Sstevel@tonic-gate int have_dump = 1; 3417c478bd9Sstevel@tonic-gate int stat; 3427c478bd9Sstevel@tonic-gate int rv = RCM_SUCCESS; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate if (get_dumpdev(dumpdev) == 0 && dumpdev[0] == '\0') 3457c478bd9Sstevel@tonic-gate have_dump = 0; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate for (sa = sf->areas; sa != NULL; sa = sa->next) { 3487c478bd9Sstevel@tonic-gate /* swap(1M) is not idempotent */ 3497c478bd9Sstevel@tonic-gate if (sa->cache_flags & SWAP_CACHE_OFFLINED) { 3507c478bd9Sstevel@tonic-gate continue; 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate (void) snprintf(cmd, sizeof (cmd), SWAP_DELETE, sf->path, 3547c478bd9Sstevel@tonic-gate sa->start); 3557c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "%s\n", cmd); 3567c478bd9Sstevel@tonic-gate if ((stat = rcm_exec_cmd(cmd)) != 0) { 3577c478bd9Sstevel@tonic-gate log_cmd_status(stat); 3587c478bd9Sstevel@tonic-gate *errstr = strdup(gettext("unable to delete swap")); 3597c478bd9Sstevel@tonic-gate rv = RCM_FAILURE; 3607c478bd9Sstevel@tonic-gate goto out; 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate sa->cache_flags |= SWAP_CACHE_OFFLINED; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * Fail on removal of dump device. 3667c478bd9Sstevel@tonic-gate */ 3677c478bd9Sstevel@tonic-gate if (have_dump == 0) 3687c478bd9Sstevel@tonic-gate continue; 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate if (get_dumpdev(dumpdev) != 0) { 3717c478bd9Sstevel@tonic-gate rcm_log_message(RCM_WARNING, "unable to " 3727c478bd9Sstevel@tonic-gate "check for removal of dump device\n"); 3737c478bd9Sstevel@tonic-gate } else if (dumpdev[0] == '\0') { 3747c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "removed dump: " 3757c478bd9Sstevel@tonic-gate "attempting recovery\n"); 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /* 3787c478bd9Sstevel@tonic-gate * Restore dump 3797c478bd9Sstevel@tonic-gate */ 3807c478bd9Sstevel@tonic-gate (void) snprintf(cmd, sizeof (cmd), SWAP_ADD, 3817c478bd9Sstevel@tonic-gate sf->path, sa->start, sa->len); 3827c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "%s\n", cmd); 3837c478bd9Sstevel@tonic-gate if ((stat = rcm_exec_cmd(cmd)) != 0) { 3847c478bd9Sstevel@tonic-gate log_cmd_status(stat); 3857c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 3867c478bd9Sstevel@tonic-gate "failed to restore dump\n"); 3877c478bd9Sstevel@tonic-gate } else { 3887c478bd9Sstevel@tonic-gate sa->cache_flags &= ~SWAP_CACHE_OFFLINED; 3897c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "dump restored\n"); 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate *errstr = strdup(gettext("unable to relocate dump")); 3927c478bd9Sstevel@tonic-gate rv = RCM_FAILURE; 3937c478bd9Sstevel@tonic-gate goto out; 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate sf->cache_flags |= SWAP_CACHE_OFFLINED; 3977c478bd9Sstevel@tonic-gate out: 3987c478bd9Sstevel@tonic-gate return (rv); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * Invoke swap(1M) to add each registered swap area. 4037c478bd9Sstevel@tonic-gate * 4047c478bd9Sstevel@tonic-gate * Call with cache_lock held. 4057c478bd9Sstevel@tonic-gate */ 4067c478bd9Sstevel@tonic-gate static int 4077c478bd9Sstevel@tonic-gate swap_add(swap_file_t *sf, char **errstr) 4087c478bd9Sstevel@tonic-gate { 4097c478bd9Sstevel@tonic-gate swap_area_t *sa; 4107c478bd9Sstevel@tonic-gate char cmd[sizeof (SWAP_ADD) + MAXPATHLEN + 4117c478bd9Sstevel@tonic-gate (2 * MAXOFFSET_STRLEN)]; 4127c478bd9Sstevel@tonic-gate int stat; 4137c478bd9Sstevel@tonic-gate int rv = RCM_SUCCESS; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate for (sa = sf->areas; sa != NULL; sa = sa->next) { 4167c478bd9Sstevel@tonic-gate /* swap(1M) is not idempotent */ 4177c478bd9Sstevel@tonic-gate if (!(sa->cache_flags & SWAP_CACHE_OFFLINED)) { 4187c478bd9Sstevel@tonic-gate continue; 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate (void) snprintf(cmd, sizeof (cmd), 4227c478bd9Sstevel@tonic-gate SWAP_ADD, sf->path, sa->start, sa->len); 4237c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "%s\n", cmd); 4247c478bd9Sstevel@tonic-gate if ((stat = rcm_exec_cmd(cmd)) != 0) { 4257c478bd9Sstevel@tonic-gate log_cmd_status(stat); 4267c478bd9Sstevel@tonic-gate *errstr = strdup(gettext("unable to add swap")); 4277c478bd9Sstevel@tonic-gate rv = RCM_FAILURE; 4287c478bd9Sstevel@tonic-gate break; 4297c478bd9Sstevel@tonic-gate } else { 4307c478bd9Sstevel@tonic-gate sa->cache_flags &= ~SWAP_CACHE_OFFLINED; 4317c478bd9Sstevel@tonic-gate sf->cache_flags &= ~SWAP_CACHE_OFFLINED; 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate return (rv); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate static int 4397c478bd9Sstevel@tonic-gate update_cache(rcm_handle_t *hdl) 4407c478bd9Sstevel@tonic-gate { 4417c478bd9Sstevel@tonic-gate swaptbl_t *swt; 4427c478bd9Sstevel@tonic-gate swap_file_t *sf, *stale_sf; 4437c478bd9Sstevel@tonic-gate swap_area_t *sa, *stale_sa; 4447c478bd9Sstevel@tonic-gate int i; 4457c478bd9Sstevel@tonic-gate int rv = RCM_SUCCESS; 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate if ((swt = sys_swaptbl()) == NULL) { 4487c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "failed to read " 4497c478bd9Sstevel@tonic-gate "current swap configuration\n"); 4507c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate /* 4567c478bd9Sstevel@tonic-gate * cache pass 1 - mark everyone stale 4577c478bd9Sstevel@tonic-gate */ 4587c478bd9Sstevel@tonic-gate for (sf = cache; sf != NULL; sf = sf->next) { 4597c478bd9Sstevel@tonic-gate sf->cache_flags |= SWAP_CACHE_STALE; 4607c478bd9Sstevel@tonic-gate for (sa = sf->areas; sa != NULL; sa = sa->next) { 4617c478bd9Sstevel@tonic-gate sa->cache_flags |= SWAP_CACHE_STALE; 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* 4667c478bd9Sstevel@tonic-gate * add new entries 4677c478bd9Sstevel@tonic-gate */ 4687c478bd9Sstevel@tonic-gate for (i = 0; i < swt->swt_n; i++) { 4697c478bd9Sstevel@tonic-gate if (swt->swt_ent[i].ste_flags & (ST_INDEL|ST_DOINGDEL)) { 4707c478bd9Sstevel@tonic-gate continue; 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate /* 4747c478bd9Sstevel@tonic-gate * assure swap_file_t 4757c478bd9Sstevel@tonic-gate */ 4767c478bd9Sstevel@tonic-gate if ((sf = cache_lookup(swt->swt_ent[i].ste_path)) == NULL) { 4777c478bd9Sstevel@tonic-gate if ((sf = swap_file_alloc(swt->swt_ent[i].ste_path)) == 4787c478bd9Sstevel@tonic-gate NULL) { 4797c478bd9Sstevel@tonic-gate free(swt); 4807c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate sf->cache_flags |= SWAP_CACHE_NEW; 4837c478bd9Sstevel@tonic-gate cache_insert(sf); 4847c478bd9Sstevel@tonic-gate } else { 4857c478bd9Sstevel@tonic-gate sf->cache_flags &= ~SWAP_CACHE_STALE; 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate /* 4897c478bd9Sstevel@tonic-gate * assure swap_area_t 4907c478bd9Sstevel@tonic-gate */ 4917c478bd9Sstevel@tonic-gate if ((sa = swap_area_lookup(sf, &swt->swt_ent[i])) == NULL) { 4927c478bd9Sstevel@tonic-gate if ((sa = swap_area_alloc(&swt->swt_ent[i])) == NULL) { 4937c478bd9Sstevel@tonic-gate free(swt); 4947c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate swap_area_add(sf, sa); 4977c478bd9Sstevel@tonic-gate } else { 4987c478bd9Sstevel@tonic-gate sa->cache_flags &= ~SWAP_CACHE_STALE; 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate free(swt); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate /* 5057c478bd9Sstevel@tonic-gate * cache pass 2 5067c478bd9Sstevel@tonic-gate * 5077c478bd9Sstevel@tonic-gate * swap_file_t - skip offlined, register new, unregister/remove stale 5087c478bd9Sstevel@tonic-gate * swap_area_t - skip offlined, remove stale 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate sf = cache; 5117c478bd9Sstevel@tonic-gate while (sf != NULL) { 5127c478bd9Sstevel@tonic-gate sa = sf->areas; 5137c478bd9Sstevel@tonic-gate while (sa != NULL) { 5147c478bd9Sstevel@tonic-gate if (sa->cache_flags & SWAP_CACHE_OFFLINED) { 5157c478bd9Sstevel@tonic-gate sa->cache_flags &= ~SWAP_CACHE_STALE; 5167c478bd9Sstevel@tonic-gate sa = sa->next; 5177c478bd9Sstevel@tonic-gate continue; 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate if (sa->cache_flags & SWAP_CACHE_STALE) { 5207c478bd9Sstevel@tonic-gate stale_sa = sa; 5217c478bd9Sstevel@tonic-gate sa = sa->next; 5227c478bd9Sstevel@tonic-gate swap_area_remove(sf, stale_sa); 5237c478bd9Sstevel@tonic-gate free(stale_sa); 5247c478bd9Sstevel@tonic-gate continue; 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate sa = sa->next; 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate if (sf->cache_flags & SWAP_CACHE_OFFLINED) { 5307c478bd9Sstevel@tonic-gate sf->cache_flags &= ~SWAP_CACHE_STALE; 5317c478bd9Sstevel@tonic-gate sf = sf->next; 5327c478bd9Sstevel@tonic-gate continue; 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate if (sf->cache_flags & SWAP_CACHE_STALE) { 5367c478bd9Sstevel@tonic-gate if (rcm_unregister_interest(hdl, sf->path, 0) != 5377c478bd9Sstevel@tonic-gate RCM_SUCCESS) { 5387c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "failed to register " 5397c478bd9Sstevel@tonic-gate "%s\n", sf->path); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate stale_sf = sf; 5427c478bd9Sstevel@tonic-gate sf = sf->next; 5437c478bd9Sstevel@tonic-gate cache_remove(stale_sf); 5447c478bd9Sstevel@tonic-gate swap_file_free(stale_sf); 5457c478bd9Sstevel@tonic-gate continue; 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate if (!(sf->cache_flags & SWAP_CACHE_NEW)) { 5497c478bd9Sstevel@tonic-gate sf = sf->next; 5507c478bd9Sstevel@tonic-gate continue; 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate if (rcm_register_interest(hdl, sf->path, 0, NULL) != 5547c478bd9Sstevel@tonic-gate RCM_SUCCESS) { 5557c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "failed to register %s\n", 5567c478bd9Sstevel@tonic-gate sf->path); 5577c478bd9Sstevel@tonic-gate rv = RCM_FAILURE; 5587c478bd9Sstevel@tonic-gate } else { 5597c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "registered %s\n", 5607c478bd9Sstevel@tonic-gate sf->path); 5617c478bd9Sstevel@tonic-gate sf->cache_flags &= ~SWAP_CACHE_NEW; 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate sf = sf->next; 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate return (rv); 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate /* 5717c478bd9Sstevel@tonic-gate * Returns system swap table. 5727c478bd9Sstevel@tonic-gate */ 5737c478bd9Sstevel@tonic-gate static swaptbl_t * 5747c478bd9Sstevel@tonic-gate sys_swaptbl() 5757c478bd9Sstevel@tonic-gate { 5767c478bd9Sstevel@tonic-gate swaptbl_t *swt; 5777c478bd9Sstevel@tonic-gate char *cp; 5787c478bd9Sstevel@tonic-gate int i, n; 5797c478bd9Sstevel@tonic-gate size_t tbl_size; 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate if ((n = swapctl(SC_GETNSWP, NULL)) == -1) 5827c478bd9Sstevel@tonic-gate return (NULL); 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate tbl_size = sizeof (int) + n * sizeof (swapent_t) + n * MAXPATHLEN; 5857c478bd9Sstevel@tonic-gate if ((swt = (swaptbl_t *)malloc(tbl_size)) == NULL) 5867c478bd9Sstevel@tonic-gate return (NULL); 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate swt->swt_n = n; 5897c478bd9Sstevel@tonic-gate cp = (char *)swt + (sizeof (int) + n * sizeof (swapent_t)); 5907c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 5917c478bd9Sstevel@tonic-gate swt->swt_ent[i].ste_path = cp; 5927c478bd9Sstevel@tonic-gate cp += MAXPATHLEN; 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate if ((n = swapctl(SC_LIST, swt)) == -1) { 5967c478bd9Sstevel@tonic-gate free(swt); 5977c478bd9Sstevel@tonic-gate return (NULL); 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate if (n != swt->swt_n) { 6017c478bd9Sstevel@tonic-gate /* mismatch, try again */ 6027c478bd9Sstevel@tonic-gate free(swt); 6037c478bd9Sstevel@tonic-gate return (sys_swaptbl()); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate return (swt); 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate static int 6107c478bd9Sstevel@tonic-gate get_dumpdev(char dumpdev[]) 6117c478bd9Sstevel@tonic-gate { 6127c478bd9Sstevel@tonic-gate int fd; 6137c478bd9Sstevel@tonic-gate int rv = 0; 6147c478bd9Sstevel@tonic-gate char *err; 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate if ((fd = open("/dev/dump", O_RDONLY)) == -1) { 6177c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "failed to open /dev/dump\n"); 6187c478bd9Sstevel@tonic-gate return (-1); 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate if (ioctl(fd, DIOCGETDEV, dumpdev) == -1) { 6227c478bd9Sstevel@tonic-gate if (errno == ENODEV) { 6237c478bd9Sstevel@tonic-gate dumpdev[0] = '\0'; 6247c478bd9Sstevel@tonic-gate } else { 6257c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "ioctl: %s\n", 6267c478bd9Sstevel@tonic-gate ((err = strerror(errno)) == NULL) ? "" : err); 6277c478bd9Sstevel@tonic-gate rv = -1; 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate (void) close(fd); 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate return (rv); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate static void 6367c478bd9Sstevel@tonic-gate free_cache(void) 6377c478bd9Sstevel@tonic-gate { 6387c478bd9Sstevel@tonic-gate swap_file_t *sf; 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 6417c478bd9Sstevel@tonic-gate while ((sf = cache) != NULL) { 6427c478bd9Sstevel@tonic-gate cache = cache->next; 6437c478bd9Sstevel@tonic-gate swap_file_free(sf); 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate /* 6507c478bd9Sstevel@tonic-gate * Call with cache_lock held. 6517c478bd9Sstevel@tonic-gate */ 6527c478bd9Sstevel@tonic-gate static void 6537c478bd9Sstevel@tonic-gate swap_file_free(swap_file_t *sf) 6547c478bd9Sstevel@tonic-gate { 6557c478bd9Sstevel@tonic-gate swap_area_t *sa; 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate assert(sf != NULL); 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate while ((sa = sf->areas) != NULL) { 6607c478bd9Sstevel@tonic-gate sf->areas = sf->areas->next; 6617c478bd9Sstevel@tonic-gate free(sa); 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate free(sf); 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate /* 6677c478bd9Sstevel@tonic-gate * Call with cache_lock held. 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate static void 6707c478bd9Sstevel@tonic-gate cache_insert(swap_file_t *ent) 6717c478bd9Sstevel@tonic-gate { 6727c478bd9Sstevel@tonic-gate ent->next = cache; 6737c478bd9Sstevel@tonic-gate if (ent->next) 6747c478bd9Sstevel@tonic-gate ent->next->prev = ent; 6757c478bd9Sstevel@tonic-gate ent->prev = NULL; 6767c478bd9Sstevel@tonic-gate cache = ent; 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate /* 6807c478bd9Sstevel@tonic-gate * Call with cache_lock held. 6817c478bd9Sstevel@tonic-gate */ 6827c478bd9Sstevel@tonic-gate static swap_file_t * 6837c478bd9Sstevel@tonic-gate cache_lookup(char *rsrc) 6847c478bd9Sstevel@tonic-gate { 6857c478bd9Sstevel@tonic-gate swap_file_t *sf; 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate for (sf = cache; sf != NULL; sf = sf->next) { 6887c478bd9Sstevel@tonic-gate if (strcmp(rsrc, sf->path) == 0) { 6897c478bd9Sstevel@tonic-gate return (sf); 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate return (NULL); 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate /* 6967c478bd9Sstevel@tonic-gate * Call with cache_lock held. 6977c478bd9Sstevel@tonic-gate */ 6987c478bd9Sstevel@tonic-gate static void 6997c478bd9Sstevel@tonic-gate cache_remove(swap_file_t *ent) 7007c478bd9Sstevel@tonic-gate { 7017c478bd9Sstevel@tonic-gate assert(ent != NULL); 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate if (ent->next != NULL) { 7047c478bd9Sstevel@tonic-gate ent->next->prev = ent->prev; 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate if (ent->prev != NULL) { 7077c478bd9Sstevel@tonic-gate ent->prev->next = ent->next; 7087c478bd9Sstevel@tonic-gate } else { 7097c478bd9Sstevel@tonic-gate cache = ent->next; 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate ent->next = NULL; 7127c478bd9Sstevel@tonic-gate ent->prev = NULL; 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate /* 7167c478bd9Sstevel@tonic-gate * Call with cache_lock held. 7177c478bd9Sstevel@tonic-gate */ 7187c478bd9Sstevel@tonic-gate static void 7197c478bd9Sstevel@tonic-gate swap_area_add(swap_file_t *sf, swap_area_t *sa) 7207c478bd9Sstevel@tonic-gate { 7217c478bd9Sstevel@tonic-gate sa->next = sf->areas; 7227c478bd9Sstevel@tonic-gate if (sa->next) 7237c478bd9Sstevel@tonic-gate sa->next->prev = sa; 7247c478bd9Sstevel@tonic-gate sa->prev = NULL; 7257c478bd9Sstevel@tonic-gate sf->areas = sa; 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate /* 7297c478bd9Sstevel@tonic-gate * Call with cache_lock held. 7307c478bd9Sstevel@tonic-gate */ 7317c478bd9Sstevel@tonic-gate static void 7327c478bd9Sstevel@tonic-gate swap_area_remove(swap_file_t *sf, swap_area_t *ent) 7337c478bd9Sstevel@tonic-gate { 7347c478bd9Sstevel@tonic-gate assert(sf != NULL && ent != NULL); 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate if (ent->next != NULL) { 7377c478bd9Sstevel@tonic-gate ent->next->prev = ent->prev; 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate if (ent->prev != NULL) { 7407c478bd9Sstevel@tonic-gate ent->prev->next = ent->next; 7417c478bd9Sstevel@tonic-gate } else { 7427c478bd9Sstevel@tonic-gate sf->areas = ent->next; 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate ent->next = NULL; 7457c478bd9Sstevel@tonic-gate ent->prev = NULL; 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate static swap_file_t * 7497c478bd9Sstevel@tonic-gate swap_file_alloc(char *rsrc) 7507c478bd9Sstevel@tonic-gate { 7517c478bd9Sstevel@tonic-gate swap_file_t *sf; 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate if ((sf = calloc(1, sizeof (*sf))) == NULL) { 7547c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "calloc failure\n"); 7557c478bd9Sstevel@tonic-gate return (NULL); 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate (void) strlcpy(sf->path, rsrc, sizeof (sf->path)); 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate return (sf); 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate static swap_area_t * 7637c478bd9Sstevel@tonic-gate swap_area_alloc(swapent_t *swt_ent) 7647c478bd9Sstevel@tonic-gate { 7657c478bd9Sstevel@tonic-gate swap_area_t *sa; 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate if ((sa = calloc(1, sizeof (*sa))) == NULL) { 7687c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "calloc failure\n"); 7697c478bd9Sstevel@tonic-gate return (NULL); 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate sa->start = swt_ent->ste_start; 7727c478bd9Sstevel@tonic-gate sa->len = swt_ent->ste_length; 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate return (sa); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * Call with cache_lock held. 7797c478bd9Sstevel@tonic-gate */ 7807c478bd9Sstevel@tonic-gate static swap_area_t * 7817c478bd9Sstevel@tonic-gate swap_area_lookup(swap_file_t *sf, swapent_t *swt_ent) 7827c478bd9Sstevel@tonic-gate { 7837c478bd9Sstevel@tonic-gate swap_area_t *sa; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate assert(sf != NULL && swt_ent != NULL); 7867c478bd9Sstevel@tonic-gate assert(strcmp(sf->path, swt_ent->ste_path) == 0); 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate for (sa = sf->areas; sa != NULL; sa = sa->next) { 7897c478bd9Sstevel@tonic-gate if (sa->start == swt_ent->ste_start && 7907c478bd9Sstevel@tonic-gate sa->len == swt_ent->ste_length) { 7917c478bd9Sstevel@tonic-gate return (sa); 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate return (NULL); 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate /* 7987c478bd9Sstevel@tonic-gate * All-purpose usage string. 7997c478bd9Sstevel@tonic-gate */ 8007c478bd9Sstevel@tonic-gate static int 8017c478bd9Sstevel@tonic-gate alloc_usage(char **cpp) 8027c478bd9Sstevel@tonic-gate { 8037c478bd9Sstevel@tonic-gate if ((*cpp = strdup(gettext("swap area"))) == NULL) { 8047c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "strdup failure\n"); 8057c478bd9Sstevel@tonic-gate return (-1); 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate return (0); 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate static void 8117c478bd9Sstevel@tonic-gate log_cmd_status(int stat) 8127c478bd9Sstevel@tonic-gate { 8137c478bd9Sstevel@tonic-gate char *err; 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate if (stat == -1) { 8167c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "wait: %s\n", 8177c478bd9Sstevel@tonic-gate ((err = strerror(errno)) == NULL) ? "" : err); 8187c478bd9Sstevel@tonic-gate } else if (WIFEXITED(stat)) { 8197c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "exit status: %d\n", 8207c478bd9Sstevel@tonic-gate WEXITSTATUS(stat)); 8217c478bd9Sstevel@tonic-gate } else { 8227c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "wait status: %d\n", stat); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate } 825