1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * RCM module for managing dump device during dynamic 31*7c478bd9Sstevel@tonic-gate * reconfiguration. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 34*7c478bd9Sstevel@tonic-gate #include <unistd.h> 35*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 36*7c478bd9Sstevel@tonic-gate #include <string.h> 37*7c478bd9Sstevel@tonic-gate #include <thread.h> 38*7c478bd9Sstevel@tonic-gate #include <synch.h> 39*7c478bd9Sstevel@tonic-gate #include <assert.h> 40*7c478bd9Sstevel@tonic-gate #include <errno.h> 41*7c478bd9Sstevel@tonic-gate #include <libintl.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/dumpadm.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 47*7c478bd9Sstevel@tonic-gate #include "rcm_module.h" 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate /* cache flags */ 50*7c478bd9Sstevel@tonic-gate #define DUMP_CACHE_NEW 0x01 51*7c478bd9Sstevel@tonic-gate #define DUMP_CACHE_STALE 0x02 52*7c478bd9Sstevel@tonic-gate #define DUMP_CACHE_OFFLINED 0x04 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #define DUMPADM "/usr/sbin/dumpadm -d " 55*7c478bd9Sstevel@tonic-gate #define DUMPADM_SWAP DUMPADM"swap" 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate typedef struct dump_conf { 58*7c478bd9Sstevel@tonic-gate char device[MAXPATHLEN]; 59*7c478bd9Sstevel@tonic-gate int conf_flags; /* defs in <sys/dumpadm.h> */ 60*7c478bd9Sstevel@tonic-gate int cache_flags; 61*7c478bd9Sstevel@tonic-gate struct dump_conf *next; 62*7c478bd9Sstevel@tonic-gate struct dump_conf *prev; 63*7c478bd9Sstevel@tonic-gate } dump_conf_t; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * Registration cache. 67*7c478bd9Sstevel@tonic-gate * 68*7c478bd9Sstevel@tonic-gate * N.B. Although we currently only support a single 69*7c478bd9Sstevel@tonic-gate * dump device, the cache is multi-entry since there 70*7c478bd9Sstevel@tonic-gate * may be multiple outstanding registrations. 71*7c478bd9Sstevel@tonic-gate */ 72*7c478bd9Sstevel@tonic-gate static dump_conf_t *cache; 73*7c478bd9Sstevel@tonic-gate static mutex_t cache_lock; 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate static int dump_register(rcm_handle_t *); 76*7c478bd9Sstevel@tonic-gate static int dump_unregister(rcm_handle_t *); 77*7c478bd9Sstevel@tonic-gate static int dump_getinfo(rcm_handle_t *, char *, id_t, uint_t, 78*7c478bd9Sstevel@tonic-gate char **, char **, nvlist_t *, rcm_info_t **); 79*7c478bd9Sstevel@tonic-gate static int dump_suspend(rcm_handle_t *, char *, id_t, timespec_t *, 80*7c478bd9Sstevel@tonic-gate uint_t, char **, rcm_info_t **); 81*7c478bd9Sstevel@tonic-gate static int dump_resume(rcm_handle_t *, char *, id_t, uint_t, 82*7c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 83*7c478bd9Sstevel@tonic-gate static int dump_offline(rcm_handle_t *, char *, id_t, uint_t, 84*7c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 85*7c478bd9Sstevel@tonic-gate static int dump_online(rcm_handle_t *, char *, id_t, uint_t, 86*7c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 87*7c478bd9Sstevel@tonic-gate static int dump_remove(rcm_handle_t *, char *, id_t, uint_t, 88*7c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate static int alloc_usage(char **, int); 91*7c478bd9Sstevel@tonic-gate static void cache_insert(dump_conf_t *); 92*7c478bd9Sstevel@tonic-gate static dump_conf_t *cache_lookup(char *); 93*7c478bd9Sstevel@tonic-gate static void cache_remove(dump_conf_t *); 94*7c478bd9Sstevel@tonic-gate static dump_conf_t *dump_conf_alloc(void); 95*7c478bd9Sstevel@tonic-gate static int dump_configure(dump_conf_t *, char **); 96*7c478bd9Sstevel@tonic-gate static int dump_relocate(dump_conf_t *, char **); 97*7c478bd9Sstevel@tonic-gate static void free_cache(void); 98*7c478bd9Sstevel@tonic-gate static void log_cmd_status(int); 99*7c478bd9Sstevel@tonic-gate static int update_cache(rcm_handle_t *); 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate static struct rcm_mod_ops dump_ops = 102*7c478bd9Sstevel@tonic-gate { 103*7c478bd9Sstevel@tonic-gate RCM_MOD_OPS_VERSION, 104*7c478bd9Sstevel@tonic-gate dump_register, 105*7c478bd9Sstevel@tonic-gate dump_unregister, 106*7c478bd9Sstevel@tonic-gate dump_getinfo, 107*7c478bd9Sstevel@tonic-gate dump_suspend, 108*7c478bd9Sstevel@tonic-gate dump_resume, 109*7c478bd9Sstevel@tonic-gate dump_offline, 110*7c478bd9Sstevel@tonic-gate dump_online, 111*7c478bd9Sstevel@tonic-gate dump_remove, 112*7c478bd9Sstevel@tonic-gate NULL, 113*7c478bd9Sstevel@tonic-gate NULL, 114*7c478bd9Sstevel@tonic-gate NULL 115*7c478bd9Sstevel@tonic-gate }; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate struct rcm_mod_ops * 118*7c478bd9Sstevel@tonic-gate rcm_mod_init() 119*7c478bd9Sstevel@tonic-gate { 120*7c478bd9Sstevel@tonic-gate return (&dump_ops); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate const char * 124*7c478bd9Sstevel@tonic-gate rcm_mod_info() 125*7c478bd9Sstevel@tonic-gate { 126*7c478bd9Sstevel@tonic-gate return ("RCM Dump module %I%"); 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate int 130*7c478bd9Sstevel@tonic-gate rcm_mod_fini() 131*7c478bd9Sstevel@tonic-gate { 132*7c478bd9Sstevel@tonic-gate free_cache(); 133*7c478bd9Sstevel@tonic-gate (void) mutex_destroy(&cache_lock); 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate static int 139*7c478bd9Sstevel@tonic-gate dump_register(rcm_handle_t *hdl) 140*7c478bd9Sstevel@tonic-gate { 141*7c478bd9Sstevel@tonic-gate return (update_cache(hdl)); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate static int 145*7c478bd9Sstevel@tonic-gate dump_unregister(rcm_handle_t *hdl) 146*7c478bd9Sstevel@tonic-gate { 147*7c478bd9Sstevel@tonic-gate dump_conf_t *dc; 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 150*7c478bd9Sstevel@tonic-gate while ((dc = cache) != NULL) { 151*7c478bd9Sstevel@tonic-gate cache = cache->next; 152*7c478bd9Sstevel@tonic-gate (void) rcm_unregister_interest(hdl, dc->device, 0); 153*7c478bd9Sstevel@tonic-gate free(dc); 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 161*7c478bd9Sstevel@tonic-gate static int 162*7c478bd9Sstevel@tonic-gate dump_getinfo(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 163*7c478bd9Sstevel@tonic-gate char **infostr, char **errstr, nvlist_t *props, rcm_info_t **dependent) 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate dump_conf_t *dc; 166*7c478bd9Sstevel@tonic-gate int conf_flags; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && infostr != NULL); 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 171*7c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 172*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 173*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "unknown resource: %s\n", 174*7c478bd9Sstevel@tonic-gate rsrcname); 175*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate conf_flags = dc->conf_flags; 178*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate return ((alloc_usage(infostr, conf_flags) == 0) ? 181*7c478bd9Sstevel@tonic-gate RCM_SUCCESS : RCM_FAILURE); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate /* 185*7c478bd9Sstevel@tonic-gate * Relocate dump device to maintain availability during suspension. 186*7c478bd9Sstevel@tonic-gate * Fail request if unable to relocate. 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 189*7c478bd9Sstevel@tonic-gate static int 190*7c478bd9Sstevel@tonic-gate dump_suspend(rcm_handle_t *hdl, char *rsrcname, id_t id, timespec_t *interval, 191*7c478bd9Sstevel@tonic-gate uint_t flags, char **errstr, rcm_info_t **dependent) 192*7c478bd9Sstevel@tonic-gate { 193*7c478bd9Sstevel@tonic-gate dump_conf_t *dc; 194*7c478bd9Sstevel@tonic-gate int rv; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate if (flags & RCM_QUERY) 199*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 202*7c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 203*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 204*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate rv = dump_relocate(dc, errstr); 208*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate return (rv); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 214*7c478bd9Sstevel@tonic-gate static int 215*7c478bd9Sstevel@tonic-gate dump_resume(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 216*7c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 217*7c478bd9Sstevel@tonic-gate { 218*7c478bd9Sstevel@tonic-gate dump_conf_t *dc; 219*7c478bd9Sstevel@tonic-gate int rv; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 224*7c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 225*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 226*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate rv = dump_configure(dc, errstr); 230*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate return (rv); 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate /* 236*7c478bd9Sstevel@tonic-gate * By default, reject offline. If offline request is 237*7c478bd9Sstevel@tonic-gate * forced, attempt to relocate the dump device. 238*7c478bd9Sstevel@tonic-gate */ 239*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 240*7c478bd9Sstevel@tonic-gate static int 241*7c478bd9Sstevel@tonic-gate dump_offline(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 242*7c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate dump_conf_t *dc; 245*7c478bd9Sstevel@tonic-gate int conf_flags; 246*7c478bd9Sstevel@tonic-gate int rv; 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate if ((flags & RCM_FORCE) && (flags & RCM_QUERY)) 251*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 254*7c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 255*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 256*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate if (flags & RCM_FORCE) { 260*7c478bd9Sstevel@tonic-gate rv = dump_relocate(dc, errstr); 261*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 262*7c478bd9Sstevel@tonic-gate return (rv); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate /* default */ 266*7c478bd9Sstevel@tonic-gate conf_flags = dc->conf_flags; 267*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 268*7c478bd9Sstevel@tonic-gate (void) alloc_usage(errstr, conf_flags); 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 274*7c478bd9Sstevel@tonic-gate static int 275*7c478bd9Sstevel@tonic-gate dump_online(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 276*7c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 277*7c478bd9Sstevel@tonic-gate { 278*7c478bd9Sstevel@tonic-gate dump_conf_t *dc; 279*7c478bd9Sstevel@tonic-gate int rv; 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 284*7c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 285*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 286*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate rv = dump_configure(dc, errstr); 290*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate return (rv); 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 296*7c478bd9Sstevel@tonic-gate static int 297*7c478bd9Sstevel@tonic-gate dump_remove(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 298*7c478bd9Sstevel@tonic-gate char **errstr, rcm_info_t **dependent) 299*7c478bd9Sstevel@tonic-gate { 300*7c478bd9Sstevel@tonic-gate dump_conf_t *dc; 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate assert(rsrcname != NULL && errstr != NULL); 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 305*7c478bd9Sstevel@tonic-gate if ((dc = cache_lookup(rsrcname)) == NULL) { 306*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 307*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate cache_remove(dc); 310*7c478bd9Sstevel@tonic-gate free(dc); 311*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* 317*7c478bd9Sstevel@tonic-gate * For dedicated dump devices, invoke dumpadm(1M) 318*7c478bd9Sstevel@tonic-gate * to relocate dump to swap. For dump device on 319*7c478bd9Sstevel@tonic-gate * swap, this is a no-op as the RCM swap module 320*7c478bd9Sstevel@tonic-gate * will relocate by invoking swap(1M). 321*7c478bd9Sstevel@tonic-gate * 322*7c478bd9Sstevel@tonic-gate * Call with cache_lock held. 323*7c478bd9Sstevel@tonic-gate */ 324*7c478bd9Sstevel@tonic-gate static int 325*7c478bd9Sstevel@tonic-gate dump_relocate(dump_conf_t *dc, char **errstr) 326*7c478bd9Sstevel@tonic-gate { 327*7c478bd9Sstevel@tonic-gate int stat; 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate /* 330*7c478bd9Sstevel@tonic-gate * This state may get out of sync for a dump device on swap, 331*7c478bd9Sstevel@tonic-gate * since we will will not know if the swap module succeeds. 332*7c478bd9Sstevel@tonic-gate * Worst case is we end up invoking dumpadm to configure 333*7c478bd9Sstevel@tonic-gate * the same device during a rollback. 334*7c478bd9Sstevel@tonic-gate */ 335*7c478bd9Sstevel@tonic-gate dc->cache_flags |= DUMP_CACHE_OFFLINED; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* RCM swap module will handle non-dedicated */ 338*7c478bd9Sstevel@tonic-gate if (!(dc->conf_flags & DUMP_EXCL)) 339*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "%s\n", DUMPADM_SWAP); 342*7c478bd9Sstevel@tonic-gate if ((stat = rcm_exec_cmd(DUMPADM_SWAP)) != 0) { 343*7c478bd9Sstevel@tonic-gate log_cmd_status(stat); 344*7c478bd9Sstevel@tonic-gate *errstr = strdup(gettext("unable to relocate dump device")); 345*7c478bd9Sstevel@tonic-gate dc->cache_flags &= ~DUMP_CACHE_OFFLINED; 346*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * (Re)Configure dump device. 354*7c478bd9Sstevel@tonic-gate * Call with cache_lock held. 355*7c478bd9Sstevel@tonic-gate */ 356*7c478bd9Sstevel@tonic-gate static int 357*7c478bd9Sstevel@tonic-gate dump_configure(dump_conf_t *dc, char **errstr) 358*7c478bd9Sstevel@tonic-gate { 359*7c478bd9Sstevel@tonic-gate char cmd[sizeof (DUMPADM) + MAXPATHLEN]; 360*7c478bd9Sstevel@tonic-gate int stat; 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate assert(dc != NULL && dc->device != NULL); 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate /* minor optimization */ 365*7c478bd9Sstevel@tonic-gate if (!(dc->cache_flags & DUMP_CACHE_OFFLINED)) 366*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate (void) snprintf(cmd, sizeof (cmd), "%s%s", DUMPADM, dc->device); 369*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "%s\n", cmd); 370*7c478bd9Sstevel@tonic-gate if ((stat = rcm_exec_cmd(cmd)) != 0) { 371*7c478bd9Sstevel@tonic-gate log_cmd_status(stat); 372*7c478bd9Sstevel@tonic-gate *errstr = strdup(gettext("unable to configure dump device")); 373*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate dc->cache_flags &= ~DUMP_CACHE_OFFLINED; 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /* 381*7c478bd9Sstevel@tonic-gate * Returns current dump configuration 382*7c478bd9Sstevel@tonic-gate */ 383*7c478bd9Sstevel@tonic-gate static dump_conf_t * 384*7c478bd9Sstevel@tonic-gate dump_conf_alloc(void) 385*7c478bd9Sstevel@tonic-gate { 386*7c478bd9Sstevel@tonic-gate dump_conf_t *dc; 387*7c478bd9Sstevel@tonic-gate struct stat sbuf; 388*7c478bd9Sstevel@tonic-gate int fd; 389*7c478bd9Sstevel@tonic-gate char *err; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate if ((dc = calloc(1, sizeof (*dc))) == NULL) { 392*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "calloc failure\n"); 393*7c478bd9Sstevel@tonic-gate return (NULL); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate if ((fd = open("/dev/dump", O_RDONLY)) == -1) { 397*7c478bd9Sstevel@tonic-gate /* 398*7c478bd9Sstevel@tonic-gate * Suppress reporting if no logical link. 399*7c478bd9Sstevel@tonic-gate */ 400*7c478bd9Sstevel@tonic-gate if (stat("/dev/dump", &sbuf) == 0 && 401*7c478bd9Sstevel@tonic-gate (fd = open("/dev/dump", O_RDONLY)) == -1) { 402*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 403*7c478bd9Sstevel@tonic-gate "failed to open /dev/dump: %s\n", 404*7c478bd9Sstevel@tonic-gate ((err = strerror(errno)) == NULL) ? "" : err); 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate if (fd == -1) { 408*7c478bd9Sstevel@tonic-gate free(dc); 409*7c478bd9Sstevel@tonic-gate return (NULL); 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate if (ioctl(fd, DIOCGETDEV, dc->device) == -1) { 414*7c478bd9Sstevel@tonic-gate if (errno == ENODEV) { 415*7c478bd9Sstevel@tonic-gate dc->device[0] = '\0'; 416*7c478bd9Sstevel@tonic-gate } else { 417*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "ioctl: %s\n", 418*7c478bd9Sstevel@tonic-gate ((err = strerror(errno)) == NULL) ? "" : err); 419*7c478bd9Sstevel@tonic-gate (void) close(fd); 420*7c478bd9Sstevel@tonic-gate free(dc); 421*7c478bd9Sstevel@tonic-gate return (NULL); 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate if (dc->device[0] != '\0') { 426*7c478bd9Sstevel@tonic-gate if ((dc->conf_flags = ioctl(fd, DIOCGETCONF, 0)) == -1) { 427*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "ioctl: %s\n", 428*7c478bd9Sstevel@tonic-gate ((err = strerror(errno)) == NULL) ? "" : err); 429*7c478bd9Sstevel@tonic-gate (void) close(fd); 430*7c478bd9Sstevel@tonic-gate free(dc); 431*7c478bd9Sstevel@tonic-gate return (NULL); 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate (void) close(fd); 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate return (dc); 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate static int 440*7c478bd9Sstevel@tonic-gate update_cache(rcm_handle_t *hdl) 441*7c478bd9Sstevel@tonic-gate { 442*7c478bd9Sstevel@tonic-gate dump_conf_t *ent, *curr_dump, *tmp; 443*7c478bd9Sstevel@tonic-gate int rv = RCM_SUCCESS; 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate if ((curr_dump = dump_conf_alloc()) == NULL) 446*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate /* 451*7c478bd9Sstevel@tonic-gate * pass 1 - mark all current registrations stale 452*7c478bd9Sstevel@tonic-gate */ 453*7c478bd9Sstevel@tonic-gate for (ent = cache; ent != NULL; ent = ent->next) { 454*7c478bd9Sstevel@tonic-gate ent->cache_flags |= DUMP_CACHE_STALE; 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate /* 458*7c478bd9Sstevel@tonic-gate * update current dump conf 459*7c478bd9Sstevel@tonic-gate */ 460*7c478bd9Sstevel@tonic-gate if (curr_dump->device[0] == '\0') { 461*7c478bd9Sstevel@tonic-gate free(curr_dump); 462*7c478bd9Sstevel@tonic-gate } else if ((ent = cache_lookup(curr_dump->device)) != NULL) { 463*7c478bd9Sstevel@tonic-gate ent->cache_flags &= ~DUMP_CACHE_STALE; 464*7c478bd9Sstevel@tonic-gate ent->conf_flags = curr_dump->conf_flags; 465*7c478bd9Sstevel@tonic-gate free(curr_dump); 466*7c478bd9Sstevel@tonic-gate } else { 467*7c478bd9Sstevel@tonic-gate curr_dump->cache_flags |= DUMP_CACHE_NEW; 468*7c478bd9Sstevel@tonic-gate cache_insert(curr_dump); 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate /* 472*7c478bd9Sstevel@tonic-gate * pass 2 - register, unregister, or no-op based on cache flags 473*7c478bd9Sstevel@tonic-gate */ 474*7c478bd9Sstevel@tonic-gate ent = cache; 475*7c478bd9Sstevel@tonic-gate while (ent != NULL) { 476*7c478bd9Sstevel@tonic-gate if (ent->cache_flags & DUMP_CACHE_OFFLINED) { 477*7c478bd9Sstevel@tonic-gate ent = ent->next; 478*7c478bd9Sstevel@tonic-gate continue; 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate if (ent->cache_flags & DUMP_CACHE_STALE) { 482*7c478bd9Sstevel@tonic-gate if (rcm_unregister_interest(hdl, ent->device, 0) != 483*7c478bd9Sstevel@tonic-gate RCM_SUCCESS) { 484*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "failed to " 485*7c478bd9Sstevel@tonic-gate "unregister %s\n", ent->device); 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate tmp = ent; 488*7c478bd9Sstevel@tonic-gate ent = ent->next; 489*7c478bd9Sstevel@tonic-gate cache_remove(tmp); 490*7c478bd9Sstevel@tonic-gate free(tmp); 491*7c478bd9Sstevel@tonic-gate continue; 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate if (!(ent->cache_flags & DUMP_CACHE_NEW)) { 495*7c478bd9Sstevel@tonic-gate ent = ent->next; 496*7c478bd9Sstevel@tonic-gate continue; 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate if (rcm_register_interest(hdl, ent->device, 0, NULL) != 500*7c478bd9Sstevel@tonic-gate RCM_SUCCESS) { 501*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "failed to register " 502*7c478bd9Sstevel@tonic-gate "%s\n", ent->device); 503*7c478bd9Sstevel@tonic-gate rv = RCM_FAILURE; 504*7c478bd9Sstevel@tonic-gate } else { 505*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "registered %s\n", 506*7c478bd9Sstevel@tonic-gate ent->device); 507*7c478bd9Sstevel@tonic-gate ent->cache_flags &= ~DUMP_CACHE_NEW; 508*7c478bd9Sstevel@tonic-gate } 509*7c478bd9Sstevel@tonic-gate ent = ent->next; 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate return (rv); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate /* 517*7c478bd9Sstevel@tonic-gate * Call with cache_lock held. 518*7c478bd9Sstevel@tonic-gate */ 519*7c478bd9Sstevel@tonic-gate static dump_conf_t * 520*7c478bd9Sstevel@tonic-gate cache_lookup(char *rsrc) 521*7c478bd9Sstevel@tonic-gate { 522*7c478bd9Sstevel@tonic-gate dump_conf_t *dc; 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate for (dc = cache; dc != NULL; dc = dc->next) { 525*7c478bd9Sstevel@tonic-gate if (strcmp(rsrc, dc->device) == 0) { 526*7c478bd9Sstevel@tonic-gate return (dc); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate return (NULL); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate /* 533*7c478bd9Sstevel@tonic-gate * Link to front of list. 534*7c478bd9Sstevel@tonic-gate * Call with cache_lock held. 535*7c478bd9Sstevel@tonic-gate */ 536*7c478bd9Sstevel@tonic-gate static void 537*7c478bd9Sstevel@tonic-gate cache_insert(dump_conf_t *ent) 538*7c478bd9Sstevel@tonic-gate { 539*7c478bd9Sstevel@tonic-gate ent->next = cache; 540*7c478bd9Sstevel@tonic-gate if (ent->next) 541*7c478bd9Sstevel@tonic-gate ent->next->prev = ent; 542*7c478bd9Sstevel@tonic-gate ent->prev = NULL; 543*7c478bd9Sstevel@tonic-gate cache = ent; 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate /* 547*7c478bd9Sstevel@tonic-gate * Call with cache_lock held. 548*7c478bd9Sstevel@tonic-gate */ 549*7c478bd9Sstevel@tonic-gate static void 550*7c478bd9Sstevel@tonic-gate cache_remove(dump_conf_t *ent) 551*7c478bd9Sstevel@tonic-gate { 552*7c478bd9Sstevel@tonic-gate if (ent->next != NULL) { 553*7c478bd9Sstevel@tonic-gate ent->next->prev = ent->prev; 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate if (ent->prev != NULL) { 556*7c478bd9Sstevel@tonic-gate ent->prev->next = ent->next; 557*7c478bd9Sstevel@tonic-gate } else { 558*7c478bd9Sstevel@tonic-gate cache = ent->next; 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate ent->next = NULL; 561*7c478bd9Sstevel@tonic-gate ent->prev = NULL; 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate static void 565*7c478bd9Sstevel@tonic-gate free_cache(void) 566*7c478bd9Sstevel@tonic-gate { 567*7c478bd9Sstevel@tonic-gate dump_conf_t *dc; 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 570*7c478bd9Sstevel@tonic-gate while ((dc = cache) != NULL) { 571*7c478bd9Sstevel@tonic-gate cache = cache->next; 572*7c478bd9Sstevel@tonic-gate free(dc); 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate static int 578*7c478bd9Sstevel@tonic-gate alloc_usage(char **cpp, int conf_flags) 579*7c478bd9Sstevel@tonic-gate { 580*7c478bd9Sstevel@tonic-gate /* simplifies message translation */ 581*7c478bd9Sstevel@tonic-gate if (conf_flags & DUMP_EXCL) { 582*7c478bd9Sstevel@tonic-gate *cpp = strdup(gettext("dump device (dedicated)")); 583*7c478bd9Sstevel@tonic-gate } else { 584*7c478bd9Sstevel@tonic-gate *cpp = strdup(gettext("dump device (swap)")); 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate if (*cpp == NULL) { 588*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "strdup failure\n"); 589*7c478bd9Sstevel@tonic-gate return (-1); 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate return (0); 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate static void 595*7c478bd9Sstevel@tonic-gate log_cmd_status(int stat) 596*7c478bd9Sstevel@tonic-gate { 597*7c478bd9Sstevel@tonic-gate char *err; 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate if (stat == -1) { 600*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "wait: %s\n", 601*7c478bd9Sstevel@tonic-gate ((err = strerror(errno)) == NULL) ? "" : err); 602*7c478bd9Sstevel@tonic-gate } else if (WIFEXITED(stat)) { 603*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "exit status: %d\n", 604*7c478bd9Sstevel@tonic-gate WEXITSTATUS(stat)); 605*7c478bd9Sstevel@tonic-gate } else { 606*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, "wait status: %d\n", stat); 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate } 609