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 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 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 #include <fcntl.h> 30*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 31*7c478bd9Sstevel@tonic-gate #include <stdio.h> 32*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 33*7c478bd9Sstevel@tonic-gate #include <string.h> 34*7c478bd9Sstevel@tonic-gate #include <synch.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 37*7c478bd9Sstevel@tonic-gate #include <libgen.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include "libdiskmgt.h" 40*7c478bd9Sstevel@tonic-gate #include "disks_private.h" 41*7c478bd9Sstevel@tonic-gate #include "partition.h" 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #define ALIASES 0 44*7c478bd9Sstevel@tonic-gate #define DEVPATHS 1 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate /* 47*7c478bd9Sstevel@tonic-gate * Set DM_LIBDISKMGT_DEBUG in the environment. Two levels of debugging: 48*7c478bd9Sstevel@tonic-gate * 1 - errors, warnings and minimal tracing information 49*7c478bd9Sstevel@tonic-gate * 2 - verbose information 50*7c478bd9Sstevel@tonic-gate * All output prints on stderr. 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate int dm_debug = 0; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate /* Lock protecting the cached data */ 55*7c478bd9Sstevel@tonic-gate static rwlock_t cache_lock = DEFAULTRWLOCK; 56*7c478bd9Sstevel@tonic-gate static disk_t *disk_listp = NULL; 57*7c478bd9Sstevel@tonic-gate static controller_t *controller_listp = NULL; 58*7c478bd9Sstevel@tonic-gate static bus_t *bus_listp = NULL; 59*7c478bd9Sstevel@tonic-gate static int cache_loaded = 0; 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate descriptor_t *desc_listp = NULL; 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate static void clear_descriptors(void *gp); 64*7c478bd9Sstevel@tonic-gate static void clr_ctrl_disk_ptr(controller_t *cp, disk_t *dp); 65*7c478bd9Sstevel@tonic-gate static void clr_path_disk_ptr(path_t *pp, disk_t *dp); 66*7c478bd9Sstevel@tonic-gate static void del_drive(disk_t *dp); 67*7c478bd9Sstevel@tonic-gate static void del_drive_by_name(char *name); 68*7c478bd9Sstevel@tonic-gate static descriptor_t *have_desc(int type, void *gp, char *name, char *mname); 69*7c478bd9Sstevel@tonic-gate static int initialize(); 70*7c478bd9Sstevel@tonic-gate static int make_descriptors(int type); 71*7c478bd9Sstevel@tonic-gate static int match_disk(disk_t *oldp, disk_t *newp); 72*7c478bd9Sstevel@tonic-gate static int match_aliases(disk_t *d1p, disk_t *d2p); 73*7c478bd9Sstevel@tonic-gate static int match_alias(alias_t *ap, alias_t *listp); 74*7c478bd9Sstevel@tonic-gate static descriptor_t *new_descriptor(dm_desc_type_t type, void *op, 75*7c478bd9Sstevel@tonic-gate char *name, char *mname); 76*7c478bd9Sstevel@tonic-gate static void rewalk_tree(); 77*7c478bd9Sstevel@tonic-gate static void update_desc(descriptor_t *descp, disk_t *newdisksp, 78*7c478bd9Sstevel@tonic-gate controller_t *newctrlp, bus_t *newbusp); 79*7c478bd9Sstevel@tonic-gate static void update_desc_busp(descriptor_t *descp, bus_t *busp); 80*7c478bd9Sstevel@tonic-gate static void update_desc_ctrlp(descriptor_t *descp, 81*7c478bd9Sstevel@tonic-gate controller_t *newstrlp); 82*7c478bd9Sstevel@tonic-gate static void update_desc_diskp(descriptor_t *descp, 83*7c478bd9Sstevel@tonic-gate disk_t *newdisksp); 84*7c478bd9Sstevel@tonic-gate static void update_desc_pathp(descriptor_t *descp, 85*7c478bd9Sstevel@tonic-gate controller_t *newctrlp); 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * We only cache some of the data that we can obtain. For much of the data 89*7c478bd9Sstevel@tonic-gate * (e.g. slices & disks getting repartitioned) there are no events which would 90*7c478bd9Sstevel@tonic-gate * enable us to cache. As more events are added we can cache more information. 91*7c478bd9Sstevel@tonic-gate * 92*7c478bd9Sstevel@tonic-gate * Currently we cache the information we get from the dev tree walk. This is 93*7c478bd9Sstevel@tonic-gate * basically the information about the drives, aliases, devpaths, controllers 94*7c478bd9Sstevel@tonic-gate * and paths. We do not cache any information related to media, partitions 95*7c478bd9Sstevel@tonic-gate * or slices. 96*7c478bd9Sstevel@tonic-gate * 97*7c478bd9Sstevel@tonic-gate * A fundamental part of the API design is that the application can hold on 98*7c478bd9Sstevel@tonic-gate * to a set of descriptors for an indeterminate amount of time. Even if the 99*7c478bd9Sstevel@tonic-gate * application does not hold descriptors there is a window of time between the 100*7c478bd9Sstevel@tonic-gate * call that gets the descriptor and the use of the descriptor to get more 101*7c478bd9Sstevel@tonic-gate * information. Because of this, the cache design must work even if the object 102*7c478bd9Sstevel@tonic-gate * that the descriptor refers to no longer exists. 103*7c478bd9Sstevel@tonic-gate * 104*7c478bd9Sstevel@tonic-gate * Given this requirement, the code implements a two level cache. The 105*7c478bd9Sstevel@tonic-gate * descriptors that the application gets are really pointers into the first 106*7c478bd9Sstevel@tonic-gate * level of the cache. This first level contains the actual descriptors. 107*7c478bd9Sstevel@tonic-gate * These descriptors in turn refer to the objects we build from the dev tree 108*7c478bd9Sstevel@tonic-gate * walk which represent the drives and controllers. This is the second level 109*7c478bd9Sstevel@tonic-gate * in the cache. 110*7c478bd9Sstevel@tonic-gate * 111*7c478bd9Sstevel@tonic-gate * When we update the second level of the cache (the drives and controllers) 112*7c478bd9Sstevel@tonic-gate * we go through the first level (the descriptors) and update the pointers 113*7c478bd9Sstevel@tonic-gate * in those descriptors to refer to the new objects in the second level. If 114*7c478bd9Sstevel@tonic-gate * the object that the descriptor referred to is no longer in existence, we 115*7c478bd9Sstevel@tonic-gate * just null out the pointer in the descriptor. In this way the code that 116*7c478bd9Sstevel@tonic-gate * uses the descriptors knows that the object referred to by the descriptor 117*7c478bd9Sstevel@tonic-gate * no longer exists. 118*7c478bd9Sstevel@tonic-gate * 119*7c478bd9Sstevel@tonic-gate * We keep a reference count in the descriptors. This is incremented when 120*7c478bd9Sstevel@tonic-gate * we hand out a pointer to the descriptor and decremented when the application 121*7c478bd9Sstevel@tonic-gate * frees the descriptor it has. When the reference count goes to 0 we garbage 122*7c478bd9Sstevel@tonic-gate * collect the descriptors. In this way we only have to update active 123*7c478bd9Sstevel@tonic-gate * descriptors when we refresh the cache after an event. 124*7c478bd9Sstevel@tonic-gate * 125*7c478bd9Sstevel@tonic-gate * An example of the flow when we create descriptors: 126*7c478bd9Sstevel@tonic-gate * dm_get_descriptors libdiskmgt.c 127*7c478bd9Sstevel@tonic-gate * drive_get_descriptors drive.c 128*7c478bd9Sstevel@tonic-gate * cache_get_descriptors cache.c 129*7c478bd9Sstevel@tonic-gate * make_descriptors cache.c 130*7c478bd9Sstevel@tonic-gate * drive_make_descriptors drive.c 131*7c478bd9Sstevel@tonic-gate * cache_load_desc cache.c 132*7c478bd9Sstevel@tonic-gate * {update refcnts on descriptors & return them} 133*7c478bd9Sstevel@tonic-gate * 134*7c478bd9Sstevel@tonic-gate * The idea behind cache_get_descriptors and cache_load_desc is that we 135*7c478bd9Sstevel@tonic-gate * seperate the act of making the descriptor within the cache (which requires 136*7c478bd9Sstevel@tonic-gate * us to call back out to one of the object functions - drive_make_descriptors) 137*7c478bd9Sstevel@tonic-gate * from the act of handing out the descriptor (which requires us to increment 138*7c478bd9Sstevel@tonic-gate * the refcnt). In this way we keep all of the refcnt handling centralized 139*7c478bd9Sstevel@tonic-gate * in one function instead of forcing each object to ensure it replicates 140*7c478bd9Sstevel@tonic-gate * the refcnt handling correctly. 141*7c478bd9Sstevel@tonic-gate * 142*7c478bd9Sstevel@tonic-gate * Descriptors use two different kinds of indrection to refer to their 143*7c478bd9Sstevel@tonic-gate * corresponding object. For objects we cache (controllers, paths & drives) 144*7c478bd9Sstevel@tonic-gate * the descriptor keeps a pointer to that object. For objects that we 145*7c478bd9Sstevel@tonic-gate * dynamically build, the descriptor uses a combination of a pointer to the 146*7c478bd9Sstevel@tonic-gate * base object (usually the drive) along with a name (e.g. the media name or 147*7c478bd9Sstevel@tonic-gate * the alias). For objects that are based on media (e.g. a slice) we actually 148*7c478bd9Sstevel@tonic-gate * have to maintain a pointer (to the disk) and two names (e.g. the slice name 149*7c478bd9Sstevel@tonic-gate * and the media name which is the secondary name). 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate void 153*7c478bd9Sstevel@tonic-gate cache_free_alias(alias_t *aliasp) 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate slice_t *dp; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate free(aliasp->alias); 158*7c478bd9Sstevel@tonic-gate free(aliasp->kstat_name); 159*7c478bd9Sstevel@tonic-gate free(aliasp->wwn); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* free devpaths */ 162*7c478bd9Sstevel@tonic-gate dp = aliasp->devpaths; 163*7c478bd9Sstevel@tonic-gate while (dp != NULL) { 164*7c478bd9Sstevel@tonic-gate slice_t *nextp; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate nextp = dp->next; 167*7c478bd9Sstevel@tonic-gate free(dp->devpath); 168*7c478bd9Sstevel@tonic-gate free(dp); 169*7c478bd9Sstevel@tonic-gate dp = nextp; 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* free orig_paths */ 173*7c478bd9Sstevel@tonic-gate dp = aliasp->orig_paths; 174*7c478bd9Sstevel@tonic-gate while (dp != NULL) { 175*7c478bd9Sstevel@tonic-gate slice_t *nextp; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate nextp = dp->next; 178*7c478bd9Sstevel@tonic-gate free(dp->devpath); 179*7c478bd9Sstevel@tonic-gate free(dp); 180*7c478bd9Sstevel@tonic-gate dp = nextp; 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate free(aliasp); 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate void 187*7c478bd9Sstevel@tonic-gate cache_free_bus(bus_t *bp) 188*7c478bd9Sstevel@tonic-gate { 189*7c478bd9Sstevel@tonic-gate free(bp->name); 190*7c478bd9Sstevel@tonic-gate free(bp->btype); 191*7c478bd9Sstevel@tonic-gate free(bp->kstat_name); 192*7c478bd9Sstevel@tonic-gate free(bp->pname); 193*7c478bd9Sstevel@tonic-gate free(bp->controllers); 194*7c478bd9Sstevel@tonic-gate free(bp); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate void 198*7c478bd9Sstevel@tonic-gate cache_free_controller(controller_t *cp) 199*7c478bd9Sstevel@tonic-gate { 200*7c478bd9Sstevel@tonic-gate free(cp->name); 201*7c478bd9Sstevel@tonic-gate free(cp->kstat_name); 202*7c478bd9Sstevel@tonic-gate free(cp->disks); 203*7c478bd9Sstevel@tonic-gate if (cp->paths != NULL) { 204*7c478bd9Sstevel@tonic-gate int i; 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate for (i = 0; cp->paths[i]; i++) { 207*7c478bd9Sstevel@tonic-gate /* free the path since it can't exist w/o the controller */ 208*7c478bd9Sstevel@tonic-gate cache_free_path(cp->paths[i]); 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate free(cp->paths); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate free(cp); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate void 217*7c478bd9Sstevel@tonic-gate cache_free_descriptor(descriptor_t *desc) 218*7c478bd9Sstevel@tonic-gate { 219*7c478bd9Sstevel@tonic-gate if (!cache_is_valid_desc(desc)) { 220*7c478bd9Sstevel@tonic-gate return; 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate desc->refcnt--; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate if (desc->refcnt <= 0) { 226*7c478bd9Sstevel@tonic-gate free(desc->name); 227*7c478bd9Sstevel@tonic-gate free(desc->secondary_name); 228*7c478bd9Sstevel@tonic-gate if (desc->prev == NULL) { 229*7c478bd9Sstevel@tonic-gate /* this is the first descriptor, update head ptr */ 230*7c478bd9Sstevel@tonic-gate desc_listp = desc->next; 231*7c478bd9Sstevel@tonic-gate } else { 232*7c478bd9Sstevel@tonic-gate desc->prev->next = desc->next; 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate if (desc->next != NULL) { 235*7c478bd9Sstevel@tonic-gate desc->next->prev = desc->prev; 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate free(desc); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate void 242*7c478bd9Sstevel@tonic-gate cache_free_descriptors(descriptor_t **desc_list) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate int i; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate for (i = 0; desc_list[i]; i++) { 247*7c478bd9Sstevel@tonic-gate cache_free_descriptor(desc_list[i]); 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate free(desc_list); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate void 254*7c478bd9Sstevel@tonic-gate cache_free_disk(disk_t *dp) 255*7c478bd9Sstevel@tonic-gate { 256*7c478bd9Sstevel@tonic-gate alias_t *ap; 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate free(dp->device_id); 259*7c478bd9Sstevel@tonic-gate if (dp->devid != NULL) { 260*7c478bd9Sstevel@tonic-gate devid_free(dp->devid); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate free(dp->kernel_name); 263*7c478bd9Sstevel@tonic-gate free(dp->product_id); 264*7c478bd9Sstevel@tonic-gate free(dp->vendor_id); 265*7c478bd9Sstevel@tonic-gate free(dp->controllers); 266*7c478bd9Sstevel@tonic-gate /* the path objects are freed when we free the controller */ 267*7c478bd9Sstevel@tonic-gate free(dp->paths); 268*7c478bd9Sstevel@tonic-gate ap = dp->aliases; 269*7c478bd9Sstevel@tonic-gate while (ap != NULL) { 270*7c478bd9Sstevel@tonic-gate alias_t *nextp; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate nextp = ap->next; 273*7c478bd9Sstevel@tonic-gate cache_free_alias(ap); 274*7c478bd9Sstevel@tonic-gate ap = nextp; 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate free(dp); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate void 281*7c478bd9Sstevel@tonic-gate cache_free_path(path_t *pp) 282*7c478bd9Sstevel@tonic-gate { 283*7c478bd9Sstevel@tonic-gate int i; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate free(pp->name); 286*7c478bd9Sstevel@tonic-gate free(pp->disks); 287*7c478bd9Sstevel@tonic-gate free(pp->states); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate for (i = 0; pp->wwns[i]; i++) { 290*7c478bd9Sstevel@tonic-gate free(pp->wwns[i]); 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate free(pp->wwns); 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate free(pp); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate bus_t * 298*7c478bd9Sstevel@tonic-gate cache_get_buslist() 299*7c478bd9Sstevel@tonic-gate { 300*7c478bd9Sstevel@tonic-gate if (initialize() != 0) { 301*7c478bd9Sstevel@tonic-gate return (NULL); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate return (bus_listp); 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate controller_t * 308*7c478bd9Sstevel@tonic-gate cache_get_controllerlist() 309*7c478bd9Sstevel@tonic-gate { 310*7c478bd9Sstevel@tonic-gate if (initialize() != 0) { 311*7c478bd9Sstevel@tonic-gate return (NULL); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate return (controller_listp); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate /* 318*7c478bd9Sstevel@tonic-gate * This routine will either get the existing descriptor from the descriptor 319*7c478bd9Sstevel@tonic-gate * cache or make make a new descriptor and put it in the descriptor cache and 320*7c478bd9Sstevel@tonic-gate * return a pointer to that descriptor. We increment the refcnt when we hand 321*7c478bd9Sstevel@tonic-gate * out the descriptor. 322*7c478bd9Sstevel@tonic-gate */ 323*7c478bd9Sstevel@tonic-gate descriptor_t * 324*7c478bd9Sstevel@tonic-gate cache_get_desc(int type, void *gp, char *name, char *secondary_name, int *errp) 325*7c478bd9Sstevel@tonic-gate { 326*7c478bd9Sstevel@tonic-gate descriptor_t *dp; 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate *errp = 0; 329*7c478bd9Sstevel@tonic-gate if ((dp = have_desc(type, gp, name, secondary_name)) == NULL) { 330*7c478bd9Sstevel@tonic-gate /* make a new desc */ 331*7c478bd9Sstevel@tonic-gate if ((dp = new_descriptor(type, gp, name, secondary_name)) == NULL) { 332*7c478bd9Sstevel@tonic-gate *errp = ENOMEM; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate if (dp != NULL) { 337*7c478bd9Sstevel@tonic-gate dp->refcnt++; 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate return (dp); 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate descriptor_t ** 344*7c478bd9Sstevel@tonic-gate cache_get_descriptors(int type, int *errp) 345*7c478bd9Sstevel@tonic-gate { 346*7c478bd9Sstevel@tonic-gate descriptor_t **descs; 347*7c478bd9Sstevel@tonic-gate descriptor_t *descp; 348*7c478bd9Sstevel@tonic-gate int cnt = 0; 349*7c478bd9Sstevel@tonic-gate int pos; 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate if ((*errp = make_descriptors(type)) != 0) { 352*7c478bd9Sstevel@tonic-gate return (NULL); 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate /* count the number of active descriptors in the descriptor cache */ 356*7c478bd9Sstevel@tonic-gate descp = desc_listp; 357*7c478bd9Sstevel@tonic-gate while (descp != NULL) { 358*7c478bd9Sstevel@tonic-gate if (descp->type == type && descp->p.generic != NULL) { 359*7c478bd9Sstevel@tonic-gate cnt++; 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate descp = descp->next; 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate descs = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *)); 365*7c478bd9Sstevel@tonic-gate if (descs == NULL) { 366*7c478bd9Sstevel@tonic-gate *errp = ENOMEM; 367*7c478bd9Sstevel@tonic-gate return (NULL); 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate pos = 0; 371*7c478bd9Sstevel@tonic-gate descp = desc_listp; 372*7c478bd9Sstevel@tonic-gate while (descp != NULL) { 373*7c478bd9Sstevel@tonic-gate if (descp->type == type && descp->p.generic != NULL) { 374*7c478bd9Sstevel@tonic-gate /* update refcnts before handing out the descriptors */ 375*7c478bd9Sstevel@tonic-gate descp->refcnt++; 376*7c478bd9Sstevel@tonic-gate descs[pos++] = descp; 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate descp = descp->next; 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate descs[pos] = NULL; 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate *errp = 0; 383*7c478bd9Sstevel@tonic-gate return (descs); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate disk_t * 387*7c478bd9Sstevel@tonic-gate cache_get_disklist() 388*7c478bd9Sstevel@tonic-gate { 389*7c478bd9Sstevel@tonic-gate if (initialize() != 0) { 390*7c478bd9Sstevel@tonic-gate return (NULL); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate return (disk_listp); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate int 397*7c478bd9Sstevel@tonic-gate cache_is_valid_desc(descriptor_t *d) 398*7c478bd9Sstevel@tonic-gate { 399*7c478bd9Sstevel@tonic-gate descriptor_t *descp; 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate for (descp = desc_listp; descp != NULL; descp = descp->next) { 402*7c478bd9Sstevel@tonic-gate if (descp == d) { 403*7c478bd9Sstevel@tonic-gate return (1); 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate return (0); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate /* 411*7c478bd9Sstevel@tonic-gate * This function is called by the *_make_descriptors function 412*7c478bd9Sstevel@tonic-gate * (e.g. drive_make_descriptors) within each of the objects. This function 413*7c478bd9Sstevel@tonic-gate * makes sure that the descriptor is built in the descriptor cache but 414*7c478bd9Sstevel@tonic-gate * it does not hand out the descriptors, so the refcnt is never incremented. 415*7c478bd9Sstevel@tonic-gate */ 416*7c478bd9Sstevel@tonic-gate void 417*7c478bd9Sstevel@tonic-gate cache_load_desc(int type, void *gp, char *name, char *secondary_name, int *errp) 418*7c478bd9Sstevel@tonic-gate { 419*7c478bd9Sstevel@tonic-gate *errp = 0; 420*7c478bd9Sstevel@tonic-gate if (have_desc(type, gp, name, secondary_name) == NULL) { 421*7c478bd9Sstevel@tonic-gate /* make a new desc */ 422*7c478bd9Sstevel@tonic-gate if (new_descriptor(type, gp, name, secondary_name) == NULL) { 423*7c478bd9Sstevel@tonic-gate *errp = ENOMEM; 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate void 429*7c478bd9Sstevel@tonic-gate cache_rlock() 430*7c478bd9Sstevel@tonic-gate { 431*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&cache_lock); 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate void 435*7c478bd9Sstevel@tonic-gate cache_unlock() 436*7c478bd9Sstevel@tonic-gate { 437*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&cache_lock); 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate /* 441*7c478bd9Sstevel@tonic-gate * This function is called when we get a devtree event. Type is either add 442*7c478bd9Sstevel@tonic-gate * or delete of a drive. 443*7c478bd9Sstevel@tonic-gate * 444*7c478bd9Sstevel@tonic-gate * For delete, we need to clean up the 2nd level structures and clean up 445*7c478bd9Sstevel@tonic-gate * the pointers between the them. We also clear the descriptor ptr. 446*7c478bd9Sstevel@tonic-gate */ 447*7c478bd9Sstevel@tonic-gate void 448*7c478bd9Sstevel@tonic-gate cache_update(dm_event_type_t ev_type, char *devname) 449*7c478bd9Sstevel@tonic-gate { 450*7c478bd9Sstevel@tonic-gate char *orig_name; 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate cache_wlock(); 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate /* update the cache */ 455*7c478bd9Sstevel@tonic-gate switch (ev_type) { 456*7c478bd9Sstevel@tonic-gate case DM_EV_DISK_ADD: 457*7c478bd9Sstevel@tonic-gate rewalk_tree(); 458*7c478bd9Sstevel@tonic-gate events_new_event(devname, DM_DRIVE, DM_EV_TADD); 459*7c478bd9Sstevel@tonic-gate break; 460*7c478bd9Sstevel@tonic-gate case DM_EV_DISK_DELETE: 461*7c478bd9Sstevel@tonic-gate orig_name = devname; 462*7c478bd9Sstevel@tonic-gate devname = basename(devname); 463*7c478bd9Sstevel@tonic-gate del_drive_by_name(devname); 464*7c478bd9Sstevel@tonic-gate events_new_event(orig_name, DM_DRIVE, DM_EV_TREMOVE); 465*7c478bd9Sstevel@tonic-gate break; 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate cache_unlock(); 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate void 472*7c478bd9Sstevel@tonic-gate cache_wlock() 473*7c478bd9Sstevel@tonic-gate { 474*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&cache_lock); 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate /* 478*7c478bd9Sstevel@tonic-gate * Clear any descriptors that point at the specified cached object. 479*7c478bd9Sstevel@tonic-gate * We must go through the whole list since there can be multiple descriptors 480*7c478bd9Sstevel@tonic-gate * referencing the same object (i.e. drive/media/slice descriptors all point 481*7c478bd9Sstevel@tonic-gate * to the same drive object). The list is usually small (0 size) so this 482*7c478bd9Sstevel@tonic-gate * is not a big deal. 483*7c478bd9Sstevel@tonic-gate */ 484*7c478bd9Sstevel@tonic-gate static void 485*7c478bd9Sstevel@tonic-gate clear_descriptors(void *gp) 486*7c478bd9Sstevel@tonic-gate { 487*7c478bd9Sstevel@tonic-gate descriptor_t *descp; 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate for (descp = desc_listp; descp != NULL; descp = descp->next) { 490*7c478bd9Sstevel@tonic-gate if (descp->p.generic == gp) { 491*7c478bd9Sstevel@tonic-gate /* clear descriptor */ 492*7c478bd9Sstevel@tonic-gate descp->p.generic = NULL; 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate /* remove the ptr from the controller to the specified disk */ 498*7c478bd9Sstevel@tonic-gate static void 499*7c478bd9Sstevel@tonic-gate clr_ctrl_disk_ptr(controller_t *cp, disk_t *dp) 500*7c478bd9Sstevel@tonic-gate { 501*7c478bd9Sstevel@tonic-gate int i; 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate for (i = 0; cp->disks[i]; i++) { 504*7c478bd9Sstevel@tonic-gate if (dp == cp->disks[i]) { 505*7c478bd9Sstevel@tonic-gate int j; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate for (j = i; cp->disks[j]; j++) { 508*7c478bd9Sstevel@tonic-gate cp->disks[j] = cp->disks[j + 1]; 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate return; 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate /* remove the ptr from the path to the specified disk */ 516*7c478bd9Sstevel@tonic-gate static void 517*7c478bd9Sstevel@tonic-gate clr_path_disk_ptr(path_t *pp, disk_t *dp) 518*7c478bd9Sstevel@tonic-gate { 519*7c478bd9Sstevel@tonic-gate int i; 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate for (i = 0; pp->disks[i]; i++) { 522*7c478bd9Sstevel@tonic-gate if (dp == pp->disks[i]) { 523*7c478bd9Sstevel@tonic-gate int j; 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate for (j = i; pp->disks[j]; j++) { 526*7c478bd9Sstevel@tonic-gate pp->disks[j] = pp->disks[j + 1]; 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate return; 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate static void 534*7c478bd9Sstevel@tonic-gate del_drive(disk_t *dp) 535*7c478bd9Sstevel@tonic-gate { 536*7c478bd9Sstevel@tonic-gate int i; 537*7c478bd9Sstevel@tonic-gate disk_t *listp; 538*7c478bd9Sstevel@tonic-gate disk_t *prev = NULL; 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate clear_descriptors(dp); 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate /* clear any ptrs from controllers to this drive */ 543*7c478bd9Sstevel@tonic-gate if (dp->controllers != NULL) { 544*7c478bd9Sstevel@tonic-gate for (i = 0; dp->controllers[i]; i++) { 545*7c478bd9Sstevel@tonic-gate clr_ctrl_disk_ptr(dp->controllers[i], dp); 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate /* clear any ptrs from paths to this drive */ 550*7c478bd9Sstevel@tonic-gate if (dp->paths != NULL) { 551*7c478bd9Sstevel@tonic-gate for (i = 0; dp->paths[i]; i++) { 552*7c478bd9Sstevel@tonic-gate clr_path_disk_ptr(dp->paths[i], dp); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate /* clear drive from disk list */ 557*7c478bd9Sstevel@tonic-gate for (listp = disk_listp; listp != NULL; listp = listp->next) { 558*7c478bd9Sstevel@tonic-gate if (dp == listp) { 559*7c478bd9Sstevel@tonic-gate if (prev == NULL) { 560*7c478bd9Sstevel@tonic-gate disk_listp = dp->next; 561*7c478bd9Sstevel@tonic-gate } else { 562*7c478bd9Sstevel@tonic-gate prev->next = dp->next; 563*7c478bd9Sstevel@tonic-gate } 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate break; 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate if (prev == NULL) { 569*7c478bd9Sstevel@tonic-gate prev = disk_listp; 570*7c478bd9Sstevel@tonic-gate } else { 571*7c478bd9Sstevel@tonic-gate prev = prev->next; 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate cache_free_disk(dp); 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate /* 579*7c478bd9Sstevel@tonic-gate * Delete cached drive info when we get a devtree drive delete event. 580*7c478bd9Sstevel@tonic-gate */ 581*7c478bd9Sstevel@tonic-gate static void 582*7c478bd9Sstevel@tonic-gate del_drive_by_name(char *name) 583*7c478bd9Sstevel@tonic-gate { 584*7c478bd9Sstevel@tonic-gate disk_t *listp; 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate for (listp = disk_listp; listp != NULL; listp = listp->next) { 587*7c478bd9Sstevel@tonic-gate alias_t *ap; 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate for (ap = listp->aliases; ap; ap = ap->next) { 590*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(name, ap->alias)) { 591*7c478bd9Sstevel@tonic-gate del_drive(listp); 592*7c478bd9Sstevel@tonic-gate return; 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate static descriptor_t * 599*7c478bd9Sstevel@tonic-gate have_desc(int type, void *gp, char *name, char *secondary_name) 600*7c478bd9Sstevel@tonic-gate { 601*7c478bd9Sstevel@tonic-gate descriptor_t *descp; 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate if (name != NULL && name[0] == 0) { 604*7c478bd9Sstevel@tonic-gate name = NULL; 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate if (secondary_name != NULL && secondary_name[0] == 0) { 608*7c478bd9Sstevel@tonic-gate secondary_name = NULL; 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate descp = desc_listp; 612*7c478bd9Sstevel@tonic-gate while (descp != NULL) { 613*7c478bd9Sstevel@tonic-gate if (descp->type == type && descp->p.generic == gp && 614*7c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(descp->name, name)) { 615*7c478bd9Sstevel@tonic-gate if (type == DM_SLICE || type == DM_PARTITION || 616*7c478bd9Sstevel@tonic-gate type == DM_PATH) { 617*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(descp->secondary_name, 618*7c478bd9Sstevel@tonic-gate secondary_name)) { 619*7c478bd9Sstevel@tonic-gate return (descp); 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate } else { 622*7c478bd9Sstevel@tonic-gate return (descp); 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate } 625*7c478bd9Sstevel@tonic-gate descp = descp->next; 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate return (NULL); 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate static int 632*7c478bd9Sstevel@tonic-gate initialize() 633*7c478bd9Sstevel@tonic-gate { 634*7c478bd9Sstevel@tonic-gate struct search_args args; 635*7c478bd9Sstevel@tonic-gate int status; 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate if (cache_loaded) { 638*7c478bd9Sstevel@tonic-gate return (0); 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate libdiskmgt_init_debug(); 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate findevs(&args); 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate if (args.dev_walk_status != 0) { 646*7c478bd9Sstevel@tonic-gate return (args.dev_walk_status); 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate disk_listp = args.disk_listp; 650*7c478bd9Sstevel@tonic-gate controller_listp = args.controller_listp; 651*7c478bd9Sstevel@tonic-gate bus_listp = args.bus_listp; 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate cache_loaded = 1; 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate if ((status = events_start_event_watcher()) != 0) { 656*7c478bd9Sstevel@tonic-gate return (status); 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate return (0); 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate static int 663*7c478bd9Sstevel@tonic-gate make_descriptors(int type) 664*7c478bd9Sstevel@tonic-gate { 665*7c478bd9Sstevel@tonic-gate int error; 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate if ((error = initialize()) != 0) { 668*7c478bd9Sstevel@tonic-gate return (error); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate switch (type) { 672*7c478bd9Sstevel@tonic-gate case DM_DRIVE: 673*7c478bd9Sstevel@tonic-gate error = drive_make_descriptors(); 674*7c478bd9Sstevel@tonic-gate break; 675*7c478bd9Sstevel@tonic-gate case DM_BUS: 676*7c478bd9Sstevel@tonic-gate error = bus_make_descriptors(); 677*7c478bd9Sstevel@tonic-gate break; 678*7c478bd9Sstevel@tonic-gate case DM_CONTROLLER: 679*7c478bd9Sstevel@tonic-gate error = controller_make_descriptors(); 680*7c478bd9Sstevel@tonic-gate break; 681*7c478bd9Sstevel@tonic-gate case DM_PATH: 682*7c478bd9Sstevel@tonic-gate error = path_make_descriptors(); 683*7c478bd9Sstevel@tonic-gate break; 684*7c478bd9Sstevel@tonic-gate case DM_ALIAS: 685*7c478bd9Sstevel@tonic-gate error = alias_make_descriptors(); 686*7c478bd9Sstevel@tonic-gate break; 687*7c478bd9Sstevel@tonic-gate case DM_MEDIA: 688*7c478bd9Sstevel@tonic-gate error = media_make_descriptors(); 689*7c478bd9Sstevel@tonic-gate break; 690*7c478bd9Sstevel@tonic-gate case DM_PARTITION: 691*7c478bd9Sstevel@tonic-gate error = partition_make_descriptors(); 692*7c478bd9Sstevel@tonic-gate break; 693*7c478bd9Sstevel@tonic-gate case DM_SLICE: 694*7c478bd9Sstevel@tonic-gate error = slice_make_descriptors(); 695*7c478bd9Sstevel@tonic-gate break; 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate return (error); 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate static int 702*7c478bd9Sstevel@tonic-gate match_alias(alias_t *ap, alias_t *listp) 703*7c478bd9Sstevel@tonic-gate { 704*7c478bd9Sstevel@tonic-gate if (ap->alias == NULL) { 705*7c478bd9Sstevel@tonic-gate return (0); 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate while (listp != NULL) { 709*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(ap->alias, listp->alias)) { 710*7c478bd9Sstevel@tonic-gate return (1); 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate listp = listp->next; 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate return (0); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate static int 719*7c478bd9Sstevel@tonic-gate match_aliases(disk_t *d1p, disk_t *d2p) 720*7c478bd9Sstevel@tonic-gate { 721*7c478bd9Sstevel@tonic-gate alias_t *ap; 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate if (d1p->aliases == NULL || d2p->aliases == NULL) { 724*7c478bd9Sstevel@tonic-gate return (0); 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate ap = d1p->aliases; 728*7c478bd9Sstevel@tonic-gate while (ap != NULL) { 729*7c478bd9Sstevel@tonic-gate if (match_alias(ap, d2p->aliases)) { 730*7c478bd9Sstevel@tonic-gate return (1); 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate ap = ap->next; 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate return (0); 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate static int 739*7c478bd9Sstevel@tonic-gate match_disk(disk_t *oldp, disk_t *newp) 740*7c478bd9Sstevel@tonic-gate { 741*7c478bd9Sstevel@tonic-gate if (oldp->devid != NULL) { 742*7c478bd9Sstevel@tonic-gate if (newp->devid != NULL && 743*7c478bd9Sstevel@tonic-gate devid_compare(oldp->devid, newp->devid) == 0) { 744*7c478bd9Sstevel@tonic-gate return (1); 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate } else { 748*7c478bd9Sstevel@tonic-gate /* oldp device id is null */ 749*7c478bd9Sstevel@tonic-gate if (newp->devid == NULL) { 750*7c478bd9Sstevel@tonic-gate /* both disks have no device id, check aliases */ 751*7c478bd9Sstevel@tonic-gate if (match_aliases(oldp, newp)) { 752*7c478bd9Sstevel@tonic-gate return (1); 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate } 755*7c478bd9Sstevel@tonic-gate } 756*7c478bd9Sstevel@tonic-gate 757*7c478bd9Sstevel@tonic-gate return (0); 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate static descriptor_t * 761*7c478bd9Sstevel@tonic-gate new_descriptor(dm_desc_type_t type, void *op, char *name, char *secondary_name) 762*7c478bd9Sstevel@tonic-gate { 763*7c478bd9Sstevel@tonic-gate descriptor_t *d; 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate if (name != NULL && name[0] == 0) { 766*7c478bd9Sstevel@tonic-gate name = NULL; 767*7c478bd9Sstevel@tonic-gate } 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate if (secondary_name != NULL && secondary_name[0] == 0) { 770*7c478bd9Sstevel@tonic-gate secondary_name = NULL; 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate d = (descriptor_t *)malloc(sizeof (descriptor_t)); 774*7c478bd9Sstevel@tonic-gate if (d == NULL) { 775*7c478bd9Sstevel@tonic-gate return (NULL); 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate d->type = type; 778*7c478bd9Sstevel@tonic-gate switch (type) { 779*7c478bd9Sstevel@tonic-gate case DM_CONTROLLER: 780*7c478bd9Sstevel@tonic-gate d->p.controller = op; 781*7c478bd9Sstevel@tonic-gate break; 782*7c478bd9Sstevel@tonic-gate case DM_BUS: 783*7c478bd9Sstevel@tonic-gate d->p.bus = op; 784*7c478bd9Sstevel@tonic-gate break; 785*7c478bd9Sstevel@tonic-gate default: 786*7c478bd9Sstevel@tonic-gate d->p.disk = op; 787*7c478bd9Sstevel@tonic-gate break; 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate if (name != NULL) { 790*7c478bd9Sstevel@tonic-gate d->name = strdup(name); 791*7c478bd9Sstevel@tonic-gate if (d->name == NULL) { 792*7c478bd9Sstevel@tonic-gate free(d); 793*7c478bd9Sstevel@tonic-gate return (NULL); 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate } else { 796*7c478bd9Sstevel@tonic-gate d->name = NULL; 797*7c478bd9Sstevel@tonic-gate } 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate if (type == DM_SLICE || type == DM_PARTITION) { 800*7c478bd9Sstevel@tonic-gate if (secondary_name != NULL) { 801*7c478bd9Sstevel@tonic-gate d->secondary_name = strdup(secondary_name); 802*7c478bd9Sstevel@tonic-gate if (d->secondary_name == NULL) { 803*7c478bd9Sstevel@tonic-gate free(d->name); 804*7c478bd9Sstevel@tonic-gate free(d); 805*7c478bd9Sstevel@tonic-gate return (NULL); 806*7c478bd9Sstevel@tonic-gate } 807*7c478bd9Sstevel@tonic-gate } else { 808*7c478bd9Sstevel@tonic-gate d->secondary_name = NULL; 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate } else { 811*7c478bd9Sstevel@tonic-gate d->secondary_name = NULL; 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate d->refcnt = 0; 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate /* add this descriptor to the head of the list */ 817*7c478bd9Sstevel@tonic-gate if (desc_listp != NULL) { 818*7c478bd9Sstevel@tonic-gate desc_listp->prev = d; 819*7c478bd9Sstevel@tonic-gate } 820*7c478bd9Sstevel@tonic-gate d->prev = NULL; 821*7c478bd9Sstevel@tonic-gate d->next = desc_listp; 822*7c478bd9Sstevel@tonic-gate desc_listp = d; 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate return (d); 825*7c478bd9Sstevel@tonic-gate } 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate static void 828*7c478bd9Sstevel@tonic-gate rewalk_tree() 829*7c478bd9Sstevel@tonic-gate { 830*7c478bd9Sstevel@tonic-gate struct search_args args; 831*7c478bd9Sstevel@tonic-gate disk_t *free_disklistp; 832*7c478bd9Sstevel@tonic-gate controller_t *free_controllerlistp; 833*7c478bd9Sstevel@tonic-gate bus_t *free_buslistp; 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate findevs(&args); 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate if (args.dev_walk_status == 0) { 838*7c478bd9Sstevel@tonic-gate descriptor_t *descp; 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate /* walk the existing descriptors and update the ptrs */ 841*7c478bd9Sstevel@tonic-gate descp = desc_listp; 842*7c478bd9Sstevel@tonic-gate while (descp != NULL) { 843*7c478bd9Sstevel@tonic-gate update_desc(descp, args.disk_listp, args.controller_listp, 844*7c478bd9Sstevel@tonic-gate args.bus_listp); 845*7c478bd9Sstevel@tonic-gate descp = descp->next; 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate /* update the cached object ptrs */ 849*7c478bd9Sstevel@tonic-gate free_disklistp = disk_listp; 850*7c478bd9Sstevel@tonic-gate free_controllerlistp = controller_listp; 851*7c478bd9Sstevel@tonic-gate free_buslistp = bus_listp; 852*7c478bd9Sstevel@tonic-gate disk_listp = args.disk_listp; 853*7c478bd9Sstevel@tonic-gate controller_listp = args.controller_listp; 854*7c478bd9Sstevel@tonic-gate bus_listp = args.bus_listp; 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate } else { 857*7c478bd9Sstevel@tonic-gate free_disklistp = args.disk_listp; 858*7c478bd9Sstevel@tonic-gate free_controllerlistp = args.controller_listp; 859*7c478bd9Sstevel@tonic-gate free_buslistp = args.bus_listp; 860*7c478bd9Sstevel@tonic-gate } 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate /* 863*7c478bd9Sstevel@tonic-gate * Free the memory from either the old cached objects or the failed 864*7c478bd9Sstevel@tonic-gate * update objects. 865*7c478bd9Sstevel@tonic-gate */ 866*7c478bd9Sstevel@tonic-gate while (free_disklistp != NULL) { 867*7c478bd9Sstevel@tonic-gate disk_t *nextp; 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate nextp = free_disklistp->next; 870*7c478bd9Sstevel@tonic-gate cache_free_disk(free_disklistp); 871*7c478bd9Sstevel@tonic-gate free_disklistp = nextp; 872*7c478bd9Sstevel@tonic-gate } 873*7c478bd9Sstevel@tonic-gate while (free_controllerlistp != NULL) { 874*7c478bd9Sstevel@tonic-gate controller_t *nextp; 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate nextp = free_controllerlistp->next; 877*7c478bd9Sstevel@tonic-gate cache_free_controller(free_controllerlistp); 878*7c478bd9Sstevel@tonic-gate free_controllerlistp = nextp; 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate while (free_buslistp != NULL) { 881*7c478bd9Sstevel@tonic-gate bus_t *nextp; 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate nextp = free_buslistp->next; 884*7c478bd9Sstevel@tonic-gate cache_free_bus(free_buslistp); 885*7c478bd9Sstevel@tonic-gate free_buslistp = nextp; 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate } 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate /* 890*7c478bd9Sstevel@tonic-gate * Walk the new set of cached objects and update the descriptor ptr to point 891*7c478bd9Sstevel@tonic-gate * to the correct new object. If there is no object any more, set the desc 892*7c478bd9Sstevel@tonic-gate * ptr to null. 893*7c478bd9Sstevel@tonic-gate */ 894*7c478bd9Sstevel@tonic-gate static void 895*7c478bd9Sstevel@tonic-gate update_desc(descriptor_t *descp, disk_t *newdisksp, controller_t *newctrlp, 896*7c478bd9Sstevel@tonic-gate bus_t *newbusp) 897*7c478bd9Sstevel@tonic-gate { 898*7c478bd9Sstevel@tonic-gate /* if the descriptor is already dead, we're done */ 899*7c478bd9Sstevel@tonic-gate if (descp->p.generic == NULL) { 900*7c478bd9Sstevel@tonic-gate return; 901*7c478bd9Sstevel@tonic-gate } 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate /* 904*7c478bd9Sstevel@tonic-gate * All descriptors use a disk ptr except for controller descriptors 905*7c478bd9Sstevel@tonic-gate * and path descriptors. 906*7c478bd9Sstevel@tonic-gate */ 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate switch (descp->type) { 909*7c478bd9Sstevel@tonic-gate case DM_BUS: 910*7c478bd9Sstevel@tonic-gate update_desc_busp(descp, newbusp); 911*7c478bd9Sstevel@tonic-gate break; 912*7c478bd9Sstevel@tonic-gate case DM_CONTROLLER: 913*7c478bd9Sstevel@tonic-gate update_desc_ctrlp(descp, newctrlp); 914*7c478bd9Sstevel@tonic-gate break; 915*7c478bd9Sstevel@tonic-gate case DM_PATH: 916*7c478bd9Sstevel@tonic-gate update_desc_pathp(descp, newctrlp); 917*7c478bd9Sstevel@tonic-gate break; 918*7c478bd9Sstevel@tonic-gate default: 919*7c478bd9Sstevel@tonic-gate update_desc_diskp(descp, newdisksp); 920*7c478bd9Sstevel@tonic-gate break; 921*7c478bd9Sstevel@tonic-gate } 922*7c478bd9Sstevel@tonic-gate } 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate static void 925*7c478bd9Sstevel@tonic-gate update_desc_busp(descriptor_t *descp, bus_t *busp) 926*7c478bd9Sstevel@tonic-gate { 927*7c478bd9Sstevel@tonic-gate /* walk the new objects and find the correct bus */ 928*7c478bd9Sstevel@tonic-gate for (; busp; busp = busp->next) { 929*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(descp->p.bus->name, busp->name)) { 930*7c478bd9Sstevel@tonic-gate descp->p.bus = busp; 931*7c478bd9Sstevel@tonic-gate return; 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate /* we did not find the controller any more, clear the ptr in the desc */ 936*7c478bd9Sstevel@tonic-gate descp->p.bus = NULL; 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate static void 940*7c478bd9Sstevel@tonic-gate update_desc_ctrlp(descriptor_t *descp, controller_t *newctrlp) 941*7c478bd9Sstevel@tonic-gate { 942*7c478bd9Sstevel@tonic-gate /* walk the new objects and find the correct controller */ 943*7c478bd9Sstevel@tonic-gate for (; newctrlp; newctrlp = newctrlp->next) { 944*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(descp->p.controller->name, newctrlp->name)) { 945*7c478bd9Sstevel@tonic-gate descp->p.controller = newctrlp; 946*7c478bd9Sstevel@tonic-gate return; 947*7c478bd9Sstevel@tonic-gate } 948*7c478bd9Sstevel@tonic-gate } 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate /* we did not find the controller any more, clear the ptr in the desc */ 951*7c478bd9Sstevel@tonic-gate descp->p.controller = NULL; 952*7c478bd9Sstevel@tonic-gate } 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate static void 955*7c478bd9Sstevel@tonic-gate update_desc_diskp(descriptor_t *descp, disk_t *newdisksp) 956*7c478bd9Sstevel@tonic-gate { 957*7c478bd9Sstevel@tonic-gate /* walk the new objects and find the correct disk */ 958*7c478bd9Sstevel@tonic-gate for (; newdisksp; newdisksp = newdisksp->next) { 959*7c478bd9Sstevel@tonic-gate if (match_disk(descp->p.disk, newdisksp)) { 960*7c478bd9Sstevel@tonic-gate descp->p.disk = newdisksp; 961*7c478bd9Sstevel@tonic-gate return; 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate } 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate /* we did not find the disk any more, clear the ptr in the descriptor */ 966*7c478bd9Sstevel@tonic-gate descp->p.disk = NULL; 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate static void 970*7c478bd9Sstevel@tonic-gate update_desc_pathp(descriptor_t *descp, controller_t *newctrlp) 971*7c478bd9Sstevel@tonic-gate { 972*7c478bd9Sstevel@tonic-gate /* walk the new objects and find the correct path */ 973*7c478bd9Sstevel@tonic-gate for (; newctrlp; newctrlp = newctrlp->next) { 974*7c478bd9Sstevel@tonic-gate path_t **pp; 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate pp = newctrlp->paths; 977*7c478bd9Sstevel@tonic-gate if (pp != NULL) { 978*7c478bd9Sstevel@tonic-gate int i; 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate for (i = 0; pp[i]; i++) { 981*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(descp->p.path->name, pp[i]->name)) { 982*7c478bd9Sstevel@tonic-gate descp->p.path = pp[i]; 983*7c478bd9Sstevel@tonic-gate return; 984*7c478bd9Sstevel@tonic-gate } 985*7c478bd9Sstevel@tonic-gate } 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate } 988*7c478bd9Sstevel@tonic-gate 989*7c478bd9Sstevel@tonic-gate /* we did not find the path any more, clear the ptr in the desc */ 990*7c478bd9Sstevel@tonic-gate descp->p.path = NULL; 991*7c478bd9Sstevel@tonic-gate } 992