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. 23*648495d6Svikram * 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 for managing dump device during dynamic 307c478bd9Sstevel@tonic-gate * reconfiguration. 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 <string.h> 367c478bd9Sstevel@tonic-gate #include <thread.h> 377c478bd9Sstevel@tonic-gate #include <synch.h> 387c478bd9Sstevel@tonic-gate #include <assert.h> 397c478bd9Sstevel@tonic-gate #include <errno.h> 407c478bd9Sstevel@tonic-gate #include <libintl.h> 417c478bd9Sstevel@tonic-gate #include <sys/dumpadm.h> 427c478bd9Sstevel@tonic-gate #include <sys/param.h> 437c478bd9Sstevel@tonic-gate #include <sys/wait.h> 447c478bd9Sstevel@tonic-gate #include <sys/types.h> 457c478bd9Sstevel@tonic-gate #include <sys/stat.h> 467c478bd9Sstevel@tonic-gate #include "rcm_module.h" 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* cache flags */ 497c478bd9Sstevel@tonic-gate #define DUMP_CACHE_NEW 0x01 507c478bd9Sstevel@tonic-gate #define DUMP_CACHE_STALE 0x02 517c478bd9Sstevel@tonic-gate #define DUMP_CACHE_OFFLINED 0x04 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #define DUMPADM "/usr/sbin/dumpadm -d " 547c478bd9Sstevel@tonic-gate #define DUMPADM_SWAP DUMPADM"swap" 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate typedef struct dump_conf { 577c478bd9Sstevel@tonic-gate char device[MAXPATHLEN]; 587c478bd9Sstevel@tonic-gate int conf_flags; /* defs in <sys/dumpadm.h> */ 597c478bd9Sstevel@tonic-gate int cache_flags; 607c478bd9Sstevel@tonic-gate struct dump_conf *next; 617c478bd9Sstevel@tonic-gate struct dump_conf *prev; 627c478bd9Sstevel@tonic-gate } dump_conf_t; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /* 657c478bd9Sstevel@tonic-gate * Registration cache. 667c478bd9Sstevel@tonic-gate * 677c478bd9Sstevel@tonic-gate * N.B. Although we currently only support a single 687c478bd9Sstevel@tonic-gate * dump device, the cache is multi-entry since there 697c478bd9Sstevel@tonic-gate * may be multiple outstanding registrations. 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate static dump_conf_t *cache; 727c478bd9Sstevel@tonic-gate static mutex_t cache_lock; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static int dump_register(rcm_handle_t *); 757c478bd9Sstevel@tonic-gate static int dump_unregister(rcm_handle_t *); 767c478bd9Sstevel@tonic-gate static int dump_getinfo(rcm_handle_t *, char *, id_t, uint_t, 777c478bd9Sstevel@tonic-gate char **, char **, nvlist_t *, rcm_info_t **); 787c478bd9Sstevel@tonic-gate static int dump_suspend(rcm_handle_t *, char *, id_t, timespec_t *, 797c478bd9Sstevel@tonic-gate uint_t, char **, rcm_info_t **); 807c478bd9Sstevel@tonic-gate static int dump_resume(rcm_handle_t *, char *, id_t, uint_t, 817c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 827c478bd9Sstevel@tonic-gate static int dump_offline(rcm_handle_t *, char *, id_t, uint_t, 837c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 847c478bd9Sstevel@tonic-gate static int dump_online(rcm_handle_t *, char *, id_t, uint_t, 857c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 867c478bd9Sstevel@tonic-gate static int dump_remove(rcm_handle_t *, char *, id_t, uint_t, 877c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate static int alloc_usage(char **, int); 907c478bd9Sstevel@tonic-gate static void cache_insert(dump_conf_t *); 917c478bd9Sstevel@tonic-gate static dump_conf_t *cache_lookup(char *); 927c478bd9Sstevel@tonic-gate static void cache_remove(dump_conf_t *); 937c478bd9Sstevel@tonic-gate static dump_conf_t *dump_conf_alloc(void); 947c478bd9Sstevel@tonic-gate static int dump_configure(dump_conf_t *, char **); 957c478bd9Sstevel@tonic-gate static int dump_relocate(dump_conf_t *, char **); 967c478bd9Sstevel@tonic-gate static void free_cache(void); 977c478bd9Sstevel@tonic-gate static void log_cmd_status(int); 987c478bd9Sstevel@tonic-gate static int update_cache(rcm_handle_t *); 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate static struct rcm_mod_ops dump_ops = 1017c478bd9Sstevel@tonic-gate { 1027c478bd9Sstevel@tonic-gate RCM_MOD_OPS_VERSION, 1037c478bd9Sstevel@tonic-gate dump_register, 1047c478bd9Sstevel@tonic-gate dump_unregister, 1057c478bd9Sstevel@tonic-gate dump_getinfo, 1067c478bd9Sstevel@tonic-gate dump_suspend, 1077c478bd9Sstevel@tonic-gate dump_resume, 1087c478bd9Sstevel@tonic-gate dump_offline, 1097c478bd9Sstevel@tonic-gate dump_online, 1107c478bd9Sstevel@tonic-gate dump_remove, 1117c478bd9Sstevel@tonic-gate NULL, 1127c478bd9Sstevel@tonic-gate NULL, 1137c478bd9Sstevel@tonic-gate NULL 1147c478bd9Sstevel@tonic-gate }; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate struct rcm_mod_ops * 1177c478bd9Sstevel@tonic-gate rcm_mod_init() 1187c478bd9Sstevel@tonic-gate { 1197c478bd9Sstevel@tonic-gate return (&dump_ops); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate const char * 1237c478bd9Sstevel@tonic-gate rcm_mod_info() 1247c478bd9Sstevel@tonic-gate { 125*648495d6Svikram return ("RCM Dump module 1.3"); 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate int 1297c478bd9Sstevel@tonic-gate rcm_mod_fini() 1307c478bd9Sstevel@tonic-gate { 1317c478bd9Sstevel@tonic-gate free_cache(); 1327c478bd9Sstevel@tonic-gate (void) mutex_destroy(&cache_lock); 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate static int 1387c478bd9Sstevel@tonic-gate dump_register(rcm_handle_t *hdl) 1397c478bd9Sstevel@tonic-gate { 1407c478bd9Sstevel@tonic-gate return (update_cache(hdl)); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate static int 1447c478bd9Sstevel@tonic-gate dump_unregister(rcm_handle_t *hdl) 1457c478bd9Sstevel@tonic-gate { 1467c478bd9Sstevel@tonic-gate dump_conf_t *dc; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 1497c478bd9Sstevel@tonic-gate while ((dc = cache) != NULL) { 1507c478bd9Sstevel@tonic-gate cache = cache->next; 1517c478bd9Sstevel@tonic-gate (void) rcm_unregister_interest(hdl, dc->device, 0); 1527c478bd9Sstevel@tonic-gate free(dc); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1607c478bd9Sstevel@tonic-gate static int 1617c478bd9Sstevel@tonic-gate dump_getinfo(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 1627c478bd9Sstevel@tonic-gate char **infostr, char **errstr, nvlist_t *props, rcm_info_t **dependent) 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate dump_conf_t *dc; 1657c478bd9Sstevel@tonic-gate int conf_flags; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && infostr != NULL); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 1707c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 1717c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 1727c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "unknown resource: %s\n", 1737c478bd9Sstevel@tonic-gate rsrcname); 1747c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate conf_flags = dc->conf_flags; 1777c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate return ((alloc_usage(infostr, conf_flags) == 0) ? 1807c478bd9Sstevel@tonic-gate RCM_SUCCESS : RCM_FAILURE); 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* 1847c478bd9Sstevel@tonic-gate * Relocate dump device to maintain availability during suspension. 1857c478bd9Sstevel@tonic-gate * Fail request if unable to relocate. 1867c478bd9Sstevel@tonic-gate */ 1877c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1887c478bd9Sstevel@tonic-gate static int 1897c478bd9Sstevel@tonic-gate dump_suspend(rcm_handle_t *hdl, char *rsrcname, id_t id, timespec_t *interval, 1907c478bd9Sstevel@tonic-gate uint_t flags, char **errstr, rcm_info_t **dependent) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate dump_conf_t *dc; 1937c478bd9Sstevel@tonic-gate int rv; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if (flags & RCM_QUERY) 1987c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 2017c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 2027c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2037c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate rv = dump_relocate(dc, errstr); 2077c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate return (rv); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2137c478bd9Sstevel@tonic-gate static int 2147c478bd9Sstevel@tonic-gate dump_resume(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 2157c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 2167c478bd9Sstevel@tonic-gate { 2177c478bd9Sstevel@tonic-gate dump_conf_t *dc; 2187c478bd9Sstevel@tonic-gate int rv; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 2237c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 2247c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2257c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate rv = dump_configure(dc, errstr); 2297c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate return (rv); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * By default, reject offline. If offline request is 2367c478bd9Sstevel@tonic-gate * forced, attempt to relocate the dump device. 2377c478bd9Sstevel@tonic-gate */ 2387c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2397c478bd9Sstevel@tonic-gate static int 2407c478bd9Sstevel@tonic-gate dump_offline(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 2417c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate dump_conf_t *dc; 2447c478bd9Sstevel@tonic-gate int conf_flags; 2457c478bd9Sstevel@tonic-gate int rv; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate if ((flags & RCM_FORCE) && (flags & RCM_QUERY)) 2507c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 2537c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 2547c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2557c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate if (flags & RCM_FORCE) { 2597c478bd9Sstevel@tonic-gate rv = dump_relocate(dc, errstr); 2607c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2617c478bd9Sstevel@tonic-gate return (rv); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate /* default */ 2657c478bd9Sstevel@tonic-gate conf_flags = dc->conf_flags; 2667c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2677c478bd9Sstevel@tonic-gate (void) alloc_usage(errstr, conf_flags); 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2737c478bd9Sstevel@tonic-gate static int 2747c478bd9Sstevel@tonic-gate dump_online(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 2757c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 2767c478bd9Sstevel@tonic-gate { 2777c478bd9Sstevel@tonic-gate dump_conf_t *dc; 2787c478bd9Sstevel@tonic-gate int rv; 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 2837c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 2847c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2857c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate rv = dump_configure(dc, errstr); 2897c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate return (rv); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2957c478bd9Sstevel@tonic-gate static int 2967c478bd9Sstevel@tonic-gate dump_remove(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 2977c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 2987c478bd9Sstevel@tonic-gate { 2997c478bd9Sstevel@tonic-gate dump_conf_t *dc; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 3047c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 3057c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 3067c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate cache_remove(dc); 3097c478bd9Sstevel@tonic-gate free(dc); 3107c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate /* 3167c478bd9Sstevel@tonic-gate * For dedicated dump devices, invoke dumpadm(1M) 3177c478bd9Sstevel@tonic-gate * to relocate dump to swap. For dump device on 3187c478bd9Sstevel@tonic-gate * swap, this is a no-op as the RCM swap module 3197c478bd9Sstevel@tonic-gate * will relocate by invoking swap(1M). 3207c478bd9Sstevel@tonic-gate * 3217c478bd9Sstevel@tonic-gate * Call with cache_lock held. 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate static int 3247c478bd9Sstevel@tonic-gate dump_relocate(dump_conf_t *dc, char **errstr) 3257c478bd9Sstevel@tonic-gate { 3267c478bd9Sstevel@tonic-gate int stat; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /* 3297c478bd9Sstevel@tonic-gate * This state may get out of sync for a dump device on swap, 3307c478bd9Sstevel@tonic-gate * since we will will not know if the swap module succeeds. 3317c478bd9Sstevel@tonic-gate * Worst case is we end up invoking dumpadm to configure 3327c478bd9Sstevel@tonic-gate * the same device during a rollback. 3337c478bd9Sstevel@tonic-gate */ 3347c478bd9Sstevel@tonic-gate dc->cache_flags |= DUMP_CACHE_OFFLINED; 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* RCM swap module will handle non-dedicated */ 3377c478bd9Sstevel@tonic-gate if (!(dc->conf_flags & DUMP_EXCL)) 3387c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "%s\n", DUMPADM_SWAP); 3417c478bd9Sstevel@tonic-gate if ((stat = rcm_exec_cmd(DUMPADM_SWAP)) != 0) { 3427c478bd9Sstevel@tonic-gate log_cmd_status(stat); 3437c478bd9Sstevel@tonic-gate *errstr = strdup(gettext("unable to relocate dump device")); 3447c478bd9Sstevel@tonic-gate dc->cache_flags &= ~DUMP_CACHE_OFFLINED; 3457c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate /* 3527c478bd9Sstevel@tonic-gate * (Re)Configure dump device. 3537c478bd9Sstevel@tonic-gate * Call with cache_lock held. 3547c478bd9Sstevel@tonic-gate */ 3557c478bd9Sstevel@tonic-gate static int 3567c478bd9Sstevel@tonic-gate dump_configure(dump_conf_t *dc, char **errstr) 3577c478bd9Sstevel@tonic-gate { 3587c478bd9Sstevel@tonic-gate char cmd[sizeof (DUMPADM) + MAXPATHLEN]; 3597c478bd9Sstevel@tonic-gate int stat; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate assert(dc != NULL && dc->device != NULL); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* minor optimization */ 3647c478bd9Sstevel@tonic-gate if (!(dc->cache_flags & DUMP_CACHE_OFFLINED)) 3657c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate (void) snprintf(cmd, sizeof (cmd), "%s%s", DUMPADM, dc->device); 3687c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "%s\n", cmd); 3697c478bd9Sstevel@tonic-gate if ((stat = rcm_exec_cmd(cmd)) != 0) { 3707c478bd9Sstevel@tonic-gate log_cmd_status(stat); 3717c478bd9Sstevel@tonic-gate *errstr = strdup(gettext("unable to configure dump device")); 3727c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate dc->cache_flags &= ~DUMP_CACHE_OFFLINED; 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate /* 3807c478bd9Sstevel@tonic-gate * Returns current dump configuration 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate static dump_conf_t * 3837c478bd9Sstevel@tonic-gate dump_conf_alloc(void) 3847c478bd9Sstevel@tonic-gate { 3857c478bd9Sstevel@tonic-gate dump_conf_t *dc; 3867c478bd9Sstevel@tonic-gate struct stat sbuf; 3877c478bd9Sstevel@tonic-gate int fd; 3887c478bd9Sstevel@tonic-gate char *err; 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate if ((dc = calloc(1, sizeof (*dc))) == NULL) { 3917c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "calloc failure\n"); 3927c478bd9Sstevel@tonic-gate return (NULL); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate if ((fd = open("/dev/dump", O_RDONLY)) == -1) { 3967c478bd9Sstevel@tonic-gate /* 3977c478bd9Sstevel@tonic-gate * Suppress reporting if no logical link. 3987c478bd9Sstevel@tonic-gate */ 3997c478bd9Sstevel@tonic-gate if (stat("/dev/dump", &sbuf) == 0 && 4007c478bd9Sstevel@tonic-gate (fd = open("/dev/dump", O_RDONLY)) == -1) { 4017c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 4027c478bd9Sstevel@tonic-gate "failed to open /dev/dump: %s\n", 4037c478bd9Sstevel@tonic-gate ((err = strerror(errno)) == NULL) ? "" : err); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate if (fd == -1) { 4077c478bd9Sstevel@tonic-gate free(dc); 4087c478bd9Sstevel@tonic-gate return (NULL); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate if (ioctl(fd, DIOCGETDEV, dc->device) == -1) { 4137c478bd9Sstevel@tonic-gate if (errno == ENODEV) { 4147c478bd9Sstevel@tonic-gate dc->device[0] = '\0'; 4157c478bd9Sstevel@tonic-gate } else { 4167c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "ioctl: %s\n", 4177c478bd9Sstevel@tonic-gate ((err = strerror(errno)) == NULL) ? "" : err); 4187c478bd9Sstevel@tonic-gate (void) close(fd); 4197c478bd9Sstevel@tonic-gate free(dc); 4207c478bd9Sstevel@tonic-gate return (NULL); 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate if (dc->device[0] != '\0') { 4257c478bd9Sstevel@tonic-gate if ((dc->conf_flags = ioctl(fd, DIOCGETCONF, 0)) == -1) { 4267c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "ioctl: %s\n", 4277c478bd9Sstevel@tonic-gate ((err = strerror(errno)) == NULL) ? "" : err); 4287c478bd9Sstevel@tonic-gate (void) close(fd); 4297c478bd9Sstevel@tonic-gate free(dc); 4307c478bd9Sstevel@tonic-gate return (NULL); 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate (void) close(fd); 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate return (dc); 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 dump_conf_t *ent, *curr_dump, *tmp; 4427c478bd9Sstevel@tonic-gate int rv = RCM_SUCCESS; 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate if ((curr_dump = dump_conf_alloc()) == NULL) 4457c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate /* 4507c478bd9Sstevel@tonic-gate * pass 1 - mark all current registrations stale 4517c478bd9Sstevel@tonic-gate */ 4527c478bd9Sstevel@tonic-gate for (ent = cache; ent != NULL; ent = ent->next) { 4537c478bd9Sstevel@tonic-gate ent->cache_flags |= DUMP_CACHE_STALE; 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* 4577c478bd9Sstevel@tonic-gate * update current dump conf 4587c478bd9Sstevel@tonic-gate */ 4597c478bd9Sstevel@tonic-gate if (curr_dump->device[0] == '\0') { 4607c478bd9Sstevel@tonic-gate free(curr_dump); 4617c478bd9Sstevel@tonic-gate } else if ((ent = cache_lookup(curr_dump->device)) != NULL) { 4627c478bd9Sstevel@tonic-gate ent->cache_flags &= ~DUMP_CACHE_STALE; 4637c478bd9Sstevel@tonic-gate ent->conf_flags = curr_dump->conf_flags; 4647c478bd9Sstevel@tonic-gate free(curr_dump); 4657c478bd9Sstevel@tonic-gate } else { 4667c478bd9Sstevel@tonic-gate curr_dump->cache_flags |= DUMP_CACHE_NEW; 4677c478bd9Sstevel@tonic-gate cache_insert(curr_dump); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * pass 2 - register, unregister, or no-op based on cache flags 4727c478bd9Sstevel@tonic-gate */ 4737c478bd9Sstevel@tonic-gate ent = cache; 4747c478bd9Sstevel@tonic-gate while (ent != NULL) { 4757c478bd9Sstevel@tonic-gate if (ent->cache_flags & DUMP_CACHE_OFFLINED) { 4767c478bd9Sstevel@tonic-gate ent = ent->next; 4777c478bd9Sstevel@tonic-gate continue; 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate if (ent->cache_flags & DUMP_CACHE_STALE) { 4817c478bd9Sstevel@tonic-gate if (rcm_unregister_interest(hdl, ent->device, 0) != 4827c478bd9Sstevel@tonic-gate RCM_SUCCESS) { 4837c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "failed to " 4847c478bd9Sstevel@tonic-gate "unregister %s\n", ent->device); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate tmp = ent; 4877c478bd9Sstevel@tonic-gate ent = ent->next; 4887c478bd9Sstevel@tonic-gate cache_remove(tmp); 4897c478bd9Sstevel@tonic-gate free(tmp); 4907c478bd9Sstevel@tonic-gate continue; 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate if (!(ent->cache_flags & DUMP_CACHE_NEW)) { 4947c478bd9Sstevel@tonic-gate ent = ent->next; 4957c478bd9Sstevel@tonic-gate continue; 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate if (rcm_register_interest(hdl, ent->device, 0, NULL) != 4997c478bd9Sstevel@tonic-gate RCM_SUCCESS) { 5007c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "failed to register " 5017c478bd9Sstevel@tonic-gate "%s\n", ent->device); 5027c478bd9Sstevel@tonic-gate rv = RCM_FAILURE; 5037c478bd9Sstevel@tonic-gate } else { 5047c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "registered %s\n", 5057c478bd9Sstevel@tonic-gate ent->device); 5067c478bd9Sstevel@tonic-gate ent->cache_flags &= ~DUMP_CACHE_NEW; 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate ent = ent->next; 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate return (rv); 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate /* 5167c478bd9Sstevel@tonic-gate * Call with cache_lock held. 5177c478bd9Sstevel@tonic-gate */ 5187c478bd9Sstevel@tonic-gate static dump_conf_t * 5197c478bd9Sstevel@tonic-gate cache_lookup(char *rsrc) 5207c478bd9Sstevel@tonic-gate { 5217c478bd9Sstevel@tonic-gate dump_conf_t *dc; 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate for (dc = cache; dc != NULL; dc = dc->next) { 5247c478bd9Sstevel@tonic-gate if (strcmp(rsrc, dc->device) == 0) { 5257c478bd9Sstevel@tonic-gate return (dc); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate return (NULL); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * Link to front of list. 5337c478bd9Sstevel@tonic-gate * Call with cache_lock held. 5347c478bd9Sstevel@tonic-gate */ 5357c478bd9Sstevel@tonic-gate static void 5367c478bd9Sstevel@tonic-gate cache_insert(dump_conf_t *ent) 5377c478bd9Sstevel@tonic-gate { 5387c478bd9Sstevel@tonic-gate ent->next = cache; 5397c478bd9Sstevel@tonic-gate if (ent->next) 5407c478bd9Sstevel@tonic-gate ent->next->prev = ent; 5417c478bd9Sstevel@tonic-gate ent->prev = NULL; 5427c478bd9Sstevel@tonic-gate cache = ent; 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate /* 5467c478bd9Sstevel@tonic-gate * Call with cache_lock held. 5477c478bd9Sstevel@tonic-gate */ 5487c478bd9Sstevel@tonic-gate static void 5497c478bd9Sstevel@tonic-gate cache_remove(dump_conf_t *ent) 5507c478bd9Sstevel@tonic-gate { 5517c478bd9Sstevel@tonic-gate if (ent->next != NULL) { 5527c478bd9Sstevel@tonic-gate ent->next->prev = ent->prev; 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate if (ent->prev != NULL) { 5557c478bd9Sstevel@tonic-gate ent->prev->next = ent->next; 5567c478bd9Sstevel@tonic-gate } else { 5577c478bd9Sstevel@tonic-gate cache = ent->next; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate ent->next = NULL; 5607c478bd9Sstevel@tonic-gate ent->prev = NULL; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate static void 5647c478bd9Sstevel@tonic-gate free_cache(void) 5657c478bd9Sstevel@tonic-gate { 5667c478bd9Sstevel@tonic-gate dump_conf_t *dc; 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 5697c478bd9Sstevel@tonic-gate while ((dc = cache) != NULL) { 5707c478bd9Sstevel@tonic-gate cache = cache->next; 5717c478bd9Sstevel@tonic-gate free(dc); 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate static int 5777c478bd9Sstevel@tonic-gate alloc_usage(char **cpp, int conf_flags) 5787c478bd9Sstevel@tonic-gate { 5797c478bd9Sstevel@tonic-gate /* simplifies message translation */ 5807c478bd9Sstevel@tonic-gate if (conf_flags & DUMP_EXCL) { 5817c478bd9Sstevel@tonic-gate *cpp = strdup(gettext("dump device (dedicated)")); 5827c478bd9Sstevel@tonic-gate } else { 5837c478bd9Sstevel@tonic-gate *cpp = strdup(gettext("dump device (swap)")); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate if (*cpp == NULL) { 5877c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "strdup failure\n"); 5887c478bd9Sstevel@tonic-gate return (-1); 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate return (0); 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate static void 5947c478bd9Sstevel@tonic-gate log_cmd_status(int stat) 5957c478bd9Sstevel@tonic-gate { 5967c478bd9Sstevel@tonic-gate char *err; 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate if (stat == -1) { 5997c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "wait: %s\n", 6007c478bd9Sstevel@tonic-gate ((err = strerror(errno)) == NULL) ? "" : err); 6017c478bd9Sstevel@tonic-gate } else if (WIFEXITED(stat)) { 6027c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "exit status: %d\n", 6037c478bd9Sstevel@tonic-gate WEXITSTATUS(stat)); 6047c478bd9Sstevel@tonic-gate } else { 6057c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "wait status: %d\n", stat); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate } 608