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*b8a9e29cSrm160521 * Common Development and Distribution License (the "License").
6*b8a9e29cSrm160521 * 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*b8a9e29cSrm160521 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <fcntl.h>
297c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <stdlib.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
3382d71480Ssjelinek #include <libintl.h>
347c478bd9Sstevel@tonic-gate #include <synch.h>
357c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
367c478bd9Sstevel@tonic-gate #include <sys/types.h>
377c478bd9Sstevel@tonic-gate #include <libgen.h>
3882d71480Ssjelinek #include <syslog.h>
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate #include "libdiskmgt.h"
417c478bd9Sstevel@tonic-gate #include "disks_private.h"
427c478bd9Sstevel@tonic-gate #include "partition.h"
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate #define ALIASES 0
457c478bd9Sstevel@tonic-gate #define DEVPATHS 1
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate * Set DM_LIBDISKMGT_DEBUG in the environment. Two levels of debugging:
497c478bd9Sstevel@tonic-gate * 1 - errors, warnings and minimal tracing information
507c478bd9Sstevel@tonic-gate * 2 - verbose information
517c478bd9Sstevel@tonic-gate * All output prints on stderr.
527c478bd9Sstevel@tonic-gate */
537c478bd9Sstevel@tonic-gate int dm_debug = 0;
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate /* Lock protecting the cached data */
567c478bd9Sstevel@tonic-gate static rwlock_t cache_lock = DEFAULTRWLOCK;
577c478bd9Sstevel@tonic-gate static disk_t *disk_listp = NULL;
587c478bd9Sstevel@tonic-gate static controller_t *controller_listp = NULL;
597c478bd9Sstevel@tonic-gate static bus_t *bus_listp = NULL;
607c478bd9Sstevel@tonic-gate static int cache_loaded = 0;
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate descriptor_t *desc_listp = NULL;
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate static void clear_descriptors(void *gp);
657c478bd9Sstevel@tonic-gate static void clr_ctrl_disk_ptr(controller_t *cp, disk_t *dp);
667c478bd9Sstevel@tonic-gate static void clr_path_disk_ptr(path_t *pp, disk_t *dp);
677c478bd9Sstevel@tonic-gate static void del_drive(disk_t *dp);
687c478bd9Sstevel@tonic-gate static void del_drive_by_name(char *name);
697c478bd9Sstevel@tonic-gate static descriptor_t *have_desc(int type, void *gp, char *name, char *mname);
707c478bd9Sstevel@tonic-gate static int initialize();
717c478bd9Sstevel@tonic-gate static int make_descriptors(int type);
727c478bd9Sstevel@tonic-gate static int match_disk(disk_t *oldp, disk_t *newp);
737c478bd9Sstevel@tonic-gate static int match_aliases(disk_t *d1p, disk_t *d2p);
747c478bd9Sstevel@tonic-gate static int match_alias(alias_t *ap, alias_t *listp);
757c478bd9Sstevel@tonic-gate static descriptor_t *new_descriptor(dm_desc_type_t type, void *op,
767c478bd9Sstevel@tonic-gate char *name, char *mname);
777c478bd9Sstevel@tonic-gate static void rewalk_tree();
787c478bd9Sstevel@tonic-gate static void update_desc(descriptor_t *descp, disk_t *newdisksp,
797c478bd9Sstevel@tonic-gate controller_t *newctrlp, bus_t *newbusp);
807c478bd9Sstevel@tonic-gate static void update_desc_busp(descriptor_t *descp, bus_t *busp);
817c478bd9Sstevel@tonic-gate static void update_desc_ctrlp(descriptor_t *descp,
827c478bd9Sstevel@tonic-gate controller_t *newstrlp);
837c478bd9Sstevel@tonic-gate static void update_desc_diskp(descriptor_t *descp,
847c478bd9Sstevel@tonic-gate disk_t *newdisksp);
857c478bd9Sstevel@tonic-gate static void update_desc_pathp(descriptor_t *descp,
867c478bd9Sstevel@tonic-gate controller_t *newctrlp);
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate * We only cache some of the data that we can obtain. For much of the data
907c478bd9Sstevel@tonic-gate * (e.g. slices & disks getting repartitioned) there are no events which would
917c478bd9Sstevel@tonic-gate * enable us to cache. As more events are added we can cache more information.
927c478bd9Sstevel@tonic-gate *
937c478bd9Sstevel@tonic-gate * Currently we cache the information we get from the dev tree walk. This is
947c478bd9Sstevel@tonic-gate * basically the information about the drives, aliases, devpaths, controllers
957c478bd9Sstevel@tonic-gate * and paths. We do not cache any information related to media, partitions
967c478bd9Sstevel@tonic-gate * or slices.
977c478bd9Sstevel@tonic-gate *
987c478bd9Sstevel@tonic-gate * A fundamental part of the API design is that the application can hold on
997c478bd9Sstevel@tonic-gate * to a set of descriptors for an indeterminate amount of time. Even if the
1007c478bd9Sstevel@tonic-gate * application does not hold descriptors there is a window of time between the
1017c478bd9Sstevel@tonic-gate * call that gets the descriptor and the use of the descriptor to get more
1027c478bd9Sstevel@tonic-gate * information. Because of this, the cache design must work even if the object
1037c478bd9Sstevel@tonic-gate * that the descriptor refers to no longer exists.
1047c478bd9Sstevel@tonic-gate *
1057c478bd9Sstevel@tonic-gate * Given this requirement, the code implements a two level cache. The
1067c478bd9Sstevel@tonic-gate * descriptors that the application gets are really pointers into the first
1077c478bd9Sstevel@tonic-gate * level of the cache. This first level contains the actual descriptors.
1087c478bd9Sstevel@tonic-gate * These descriptors in turn refer to the objects we build from the dev tree
1097c478bd9Sstevel@tonic-gate * walk which represent the drives and controllers. This is the second level
1107c478bd9Sstevel@tonic-gate * in the cache.
1117c478bd9Sstevel@tonic-gate *
1127c478bd9Sstevel@tonic-gate * When we update the second level of the cache (the drives and controllers)
1137c478bd9Sstevel@tonic-gate * we go through the first level (the descriptors) and update the pointers
1147c478bd9Sstevel@tonic-gate * in those descriptors to refer to the new objects in the second level. If
1157c478bd9Sstevel@tonic-gate * the object that the descriptor referred to is no longer in existence, we
1167c478bd9Sstevel@tonic-gate * just null out the pointer in the descriptor. In this way the code that
1177c478bd9Sstevel@tonic-gate * uses the descriptors knows that the object referred to by the descriptor
1187c478bd9Sstevel@tonic-gate * no longer exists.
1197c478bd9Sstevel@tonic-gate *
1207c478bd9Sstevel@tonic-gate * We keep a reference count in the descriptors. This is incremented when
1217c478bd9Sstevel@tonic-gate * we hand out a pointer to the descriptor and decremented when the application
1227c478bd9Sstevel@tonic-gate * frees the descriptor it has. When the reference count goes to 0 we garbage
1237c478bd9Sstevel@tonic-gate * collect the descriptors. In this way we only have to update active
1247c478bd9Sstevel@tonic-gate * descriptors when we refresh the cache after an event.
1257c478bd9Sstevel@tonic-gate *
1267c478bd9Sstevel@tonic-gate * An example of the flow when we create descriptors:
1277c478bd9Sstevel@tonic-gate * dm_get_descriptors libdiskmgt.c
1287c478bd9Sstevel@tonic-gate * drive_get_descriptors drive.c
1297c478bd9Sstevel@tonic-gate * cache_get_descriptors cache.c
1307c478bd9Sstevel@tonic-gate * make_descriptors cache.c
1317c478bd9Sstevel@tonic-gate * drive_make_descriptors drive.c
1327c478bd9Sstevel@tonic-gate * cache_load_desc cache.c
1337c478bd9Sstevel@tonic-gate * {update refcnts on descriptors & return them}
1347c478bd9Sstevel@tonic-gate *
1357c478bd9Sstevel@tonic-gate * The idea behind cache_get_descriptors and cache_load_desc is that we
1367c478bd9Sstevel@tonic-gate * seperate the act of making the descriptor within the cache (which requires
1377c478bd9Sstevel@tonic-gate * us to call back out to one of the object functions - drive_make_descriptors)
1387c478bd9Sstevel@tonic-gate * from the act of handing out the descriptor (which requires us to increment
1397c478bd9Sstevel@tonic-gate * the refcnt). In this way we keep all of the refcnt handling centralized
1407c478bd9Sstevel@tonic-gate * in one function instead of forcing each object to ensure it replicates
1417c478bd9Sstevel@tonic-gate * the refcnt handling correctly.
1427c478bd9Sstevel@tonic-gate *
1437c478bd9Sstevel@tonic-gate * Descriptors use two different kinds of indrection to refer to their
1447c478bd9Sstevel@tonic-gate * corresponding object. For objects we cache (controllers, paths & drives)
1457c478bd9Sstevel@tonic-gate * the descriptor keeps a pointer to that object. For objects that we
1467c478bd9Sstevel@tonic-gate * dynamically build, the descriptor uses a combination of a pointer to the
1477c478bd9Sstevel@tonic-gate * base object (usually the drive) along with a name (e.g. the media name or
1487c478bd9Sstevel@tonic-gate * the alias). For objects that are based on media (e.g. a slice) we actually
1497c478bd9Sstevel@tonic-gate * have to maintain a pointer (to the disk) and two names (e.g. the slice name
1507c478bd9Sstevel@tonic-gate * and the media name which is the secondary name).
1517c478bd9Sstevel@tonic-gate */
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate void
cache_free_alias(alias_t * aliasp)1547c478bd9Sstevel@tonic-gate cache_free_alias(alias_t *aliasp)
1557c478bd9Sstevel@tonic-gate {
1567c478bd9Sstevel@tonic-gate slice_t *dp;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate free(aliasp->alias);
1597c478bd9Sstevel@tonic-gate free(aliasp->kstat_name);
1607c478bd9Sstevel@tonic-gate free(aliasp->wwn);
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate /* free devpaths */
1637c478bd9Sstevel@tonic-gate dp = aliasp->devpaths;
1647c478bd9Sstevel@tonic-gate while (dp != NULL) {
1657c478bd9Sstevel@tonic-gate slice_t *nextp;
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate nextp = dp->next;
1687c478bd9Sstevel@tonic-gate free(dp->devpath);
1697c478bd9Sstevel@tonic-gate free(dp);
1707c478bd9Sstevel@tonic-gate dp = nextp;
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate /* free orig_paths */
1747c478bd9Sstevel@tonic-gate dp = aliasp->orig_paths;
1757c478bd9Sstevel@tonic-gate while (dp != NULL) {
1767c478bd9Sstevel@tonic-gate slice_t *nextp;
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate nextp = dp->next;
1797c478bd9Sstevel@tonic-gate free(dp->devpath);
1807c478bd9Sstevel@tonic-gate free(dp);
1817c478bd9Sstevel@tonic-gate dp = nextp;
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate free(aliasp);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate void
cache_free_bus(bus_t * bp)1887c478bd9Sstevel@tonic-gate cache_free_bus(bus_t *bp)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate free(bp->name);
1917c478bd9Sstevel@tonic-gate free(bp->btype);
1927c478bd9Sstevel@tonic-gate free(bp->kstat_name);
1937c478bd9Sstevel@tonic-gate free(bp->pname);
1947c478bd9Sstevel@tonic-gate free(bp->controllers);
1957c478bd9Sstevel@tonic-gate free(bp);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate void
cache_free_controller(controller_t * cp)1997c478bd9Sstevel@tonic-gate cache_free_controller(controller_t *cp)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate free(cp->name);
2027c478bd9Sstevel@tonic-gate free(cp->kstat_name);
2037c478bd9Sstevel@tonic-gate free(cp->disks);
2047c478bd9Sstevel@tonic-gate if (cp->paths != NULL) {
2057c478bd9Sstevel@tonic-gate int i;
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate for (i = 0; cp->paths[i]; i++) {
208*b8a9e29cSrm160521 /* free the path since it can't exist w/o the ctrlr */
2097c478bd9Sstevel@tonic-gate cache_free_path(cp->paths[i]);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate free(cp->paths);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate free(cp);
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate void
cache_free_descriptor(descriptor_t * desc)2187c478bd9Sstevel@tonic-gate cache_free_descriptor(descriptor_t *desc)
2197c478bd9Sstevel@tonic-gate {
2207c478bd9Sstevel@tonic-gate if (!cache_is_valid_desc(desc)) {
2217c478bd9Sstevel@tonic-gate return;
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate desc->refcnt--;
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate if (desc->refcnt <= 0) {
2277c478bd9Sstevel@tonic-gate free(desc->name);
2287c478bd9Sstevel@tonic-gate free(desc->secondary_name);
2297c478bd9Sstevel@tonic-gate if (desc->prev == NULL) {
2307c478bd9Sstevel@tonic-gate /* this is the first descriptor, update head ptr */
2317c478bd9Sstevel@tonic-gate desc_listp = desc->next;
2327c478bd9Sstevel@tonic-gate } else {
2337c478bd9Sstevel@tonic-gate desc->prev->next = desc->next;
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate if (desc->next != NULL) {
2367c478bd9Sstevel@tonic-gate desc->next->prev = desc->prev;
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate free(desc);
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate void
cache_free_descriptors(descriptor_t ** desc_list)2437c478bd9Sstevel@tonic-gate cache_free_descriptors(descriptor_t **desc_list)
2447c478bd9Sstevel@tonic-gate {
2457c478bd9Sstevel@tonic-gate int i;
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate for (i = 0; desc_list[i]; i++) {
2487c478bd9Sstevel@tonic-gate cache_free_descriptor(desc_list[i]);
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate free(desc_list);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate void
cache_free_disk(disk_t * dp)2557c478bd9Sstevel@tonic-gate cache_free_disk(disk_t *dp)
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate alias_t *ap;
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate free(dp->device_id);
2607c478bd9Sstevel@tonic-gate if (dp->devid != NULL) {
2617c478bd9Sstevel@tonic-gate devid_free(dp->devid);
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate free(dp->kernel_name);
2647c478bd9Sstevel@tonic-gate free(dp->product_id);
2657c478bd9Sstevel@tonic-gate free(dp->vendor_id);
2667c478bd9Sstevel@tonic-gate free(dp->controllers);
2677c478bd9Sstevel@tonic-gate /* the path objects are freed when we free the controller */
2687c478bd9Sstevel@tonic-gate free(dp->paths);
2697c478bd9Sstevel@tonic-gate ap = dp->aliases;
2707c478bd9Sstevel@tonic-gate while (ap != NULL) {
2717c478bd9Sstevel@tonic-gate alias_t *nextp;
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate nextp = ap->next;
2747c478bd9Sstevel@tonic-gate cache_free_alias(ap);
2757c478bd9Sstevel@tonic-gate ap = nextp;
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate free(dp);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate void
cache_free_path(path_t * pp)2827c478bd9Sstevel@tonic-gate cache_free_path(path_t *pp)
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate free(pp->name);
2857c478bd9Sstevel@tonic-gate free(pp->disks);
2867c478bd9Sstevel@tonic-gate free(pp->states);
2877c478bd9Sstevel@tonic-gate
288*b8a9e29cSrm160521 if (pp->wwns) {
289*b8a9e29cSrm160521 int i;
290*b8a9e29cSrm160521
2917c478bd9Sstevel@tonic-gate for (i = 0; pp->wwns[i]; i++) {
2927c478bd9Sstevel@tonic-gate free(pp->wwns[i]);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate free(pp->wwns);
295*b8a9e29cSrm160521 }
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate free(pp);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate bus_t *
cache_get_buslist()3017c478bd9Sstevel@tonic-gate cache_get_buslist()
3027c478bd9Sstevel@tonic-gate {
3037c478bd9Sstevel@tonic-gate if (initialize() != 0) {
3047c478bd9Sstevel@tonic-gate return (NULL);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate return (bus_listp);
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate controller_t *
cache_get_controllerlist()3117c478bd9Sstevel@tonic-gate cache_get_controllerlist()
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate if (initialize() != 0) {
3147c478bd9Sstevel@tonic-gate return (NULL);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate return (controller_listp);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate /*
3217c478bd9Sstevel@tonic-gate * This routine will either get the existing descriptor from the descriptor
3227c478bd9Sstevel@tonic-gate * cache or make make a new descriptor and put it in the descriptor cache and
3237c478bd9Sstevel@tonic-gate * return a pointer to that descriptor. We increment the refcnt when we hand
3247c478bd9Sstevel@tonic-gate * out the descriptor.
3257c478bd9Sstevel@tonic-gate */
3267c478bd9Sstevel@tonic-gate descriptor_t *
cache_get_desc(int type,void * gp,char * name,char * secondary_name,int * errp)3277c478bd9Sstevel@tonic-gate cache_get_desc(int type, void *gp, char *name, char *secondary_name, int *errp)
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate descriptor_t *dp;
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate *errp = 0;
3327c478bd9Sstevel@tonic-gate if ((dp = have_desc(type, gp, name, secondary_name)) == NULL) {
3337c478bd9Sstevel@tonic-gate /* make a new desc */
334*b8a9e29cSrm160521 if ((dp = new_descriptor(type, gp, name, secondary_name))
335*b8a9e29cSrm160521 == NULL) {
3367c478bd9Sstevel@tonic-gate *errp = ENOMEM;
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate if (dp != NULL) {
3417c478bd9Sstevel@tonic-gate dp->refcnt++;
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate return (dp);
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate descriptor_t **
cache_get_descriptors(int type,int * errp)3487c478bd9Sstevel@tonic-gate cache_get_descriptors(int type, int *errp)
3497c478bd9Sstevel@tonic-gate {
3507c478bd9Sstevel@tonic-gate descriptor_t **descs;
3517c478bd9Sstevel@tonic-gate descriptor_t *descp;
3527c478bd9Sstevel@tonic-gate int cnt = 0;
3537c478bd9Sstevel@tonic-gate int pos;
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate if ((*errp = make_descriptors(type)) != 0) {
3567c478bd9Sstevel@tonic-gate return (NULL);
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate /* count the number of active descriptors in the descriptor cache */
3607c478bd9Sstevel@tonic-gate descp = desc_listp;
3617c478bd9Sstevel@tonic-gate while (descp != NULL) {
3627c478bd9Sstevel@tonic-gate if (descp->type == type && descp->p.generic != NULL) {
3637c478bd9Sstevel@tonic-gate cnt++;
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate descp = descp->next;
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate descs = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
3697c478bd9Sstevel@tonic-gate if (descs == NULL) {
3707c478bd9Sstevel@tonic-gate *errp = ENOMEM;
3717c478bd9Sstevel@tonic-gate return (NULL);
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate pos = 0;
3757c478bd9Sstevel@tonic-gate descp = desc_listp;
3767c478bd9Sstevel@tonic-gate while (descp != NULL) {
3777c478bd9Sstevel@tonic-gate if (descp->type == type && descp->p.generic != NULL) {
3787c478bd9Sstevel@tonic-gate /* update refcnts before handing out the descriptors */
3797c478bd9Sstevel@tonic-gate descp->refcnt++;
3807c478bd9Sstevel@tonic-gate descs[pos++] = descp;
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate descp = descp->next;
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate descs[pos] = NULL;
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate *errp = 0;
3877c478bd9Sstevel@tonic-gate return (descs);
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate disk_t *
cache_get_disklist()3917c478bd9Sstevel@tonic-gate cache_get_disklist()
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate if (initialize() != 0) {
3947c478bd9Sstevel@tonic-gate return (NULL);
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate return (disk_listp);
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate int
cache_is_valid_desc(descriptor_t * d)4017c478bd9Sstevel@tonic-gate cache_is_valid_desc(descriptor_t *d)
4027c478bd9Sstevel@tonic-gate {
4037c478bd9Sstevel@tonic-gate descriptor_t *descp;
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate for (descp = desc_listp; descp != NULL; descp = descp->next) {
4067c478bd9Sstevel@tonic-gate if (descp == d) {
4077c478bd9Sstevel@tonic-gate return (1);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate return (0);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate * This function is called by the *_make_descriptors function
4167c478bd9Sstevel@tonic-gate * (e.g. drive_make_descriptors) within each of the objects. This function
4177c478bd9Sstevel@tonic-gate * makes sure that the descriptor is built in the descriptor cache but
4187c478bd9Sstevel@tonic-gate * it does not hand out the descriptors, so the refcnt is never incremented.
4197c478bd9Sstevel@tonic-gate */
4207c478bd9Sstevel@tonic-gate void
cache_load_desc(int type,void * gp,char * name,char * secondary_name,int * errp)4217c478bd9Sstevel@tonic-gate cache_load_desc(int type, void *gp, char *name, char *secondary_name, int *errp)
4227c478bd9Sstevel@tonic-gate {
4237c478bd9Sstevel@tonic-gate *errp = 0;
4247c478bd9Sstevel@tonic-gate if (have_desc(type, gp, name, secondary_name) == NULL) {
4257c478bd9Sstevel@tonic-gate /* make a new desc */
4267c478bd9Sstevel@tonic-gate if (new_descriptor(type, gp, name, secondary_name) == NULL) {
4277c478bd9Sstevel@tonic-gate *errp = ENOMEM;
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate void
cache_rlock()4337c478bd9Sstevel@tonic-gate cache_rlock()
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate (void) rw_rdlock(&cache_lock);
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate void
cache_unlock()4397c478bd9Sstevel@tonic-gate cache_unlock()
4407c478bd9Sstevel@tonic-gate {
4417c478bd9Sstevel@tonic-gate (void) rw_unlock(&cache_lock);
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate /*
4457c478bd9Sstevel@tonic-gate * This function is called when we get a devtree event. Type is either add
4467c478bd9Sstevel@tonic-gate * or delete of a drive.
4477c478bd9Sstevel@tonic-gate *
4487c478bd9Sstevel@tonic-gate * For delete, we need to clean up the 2nd level structures and clean up
4497c478bd9Sstevel@tonic-gate * the pointers between the them. We also clear the descriptor ptr.
4507c478bd9Sstevel@tonic-gate */
4517c478bd9Sstevel@tonic-gate void
cache_update(dm_event_type_t ev_type,char * devname)4527c478bd9Sstevel@tonic-gate cache_update(dm_event_type_t ev_type, char *devname)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate char *orig_name;
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate cache_wlock();
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate /* update the cache */
4597c478bd9Sstevel@tonic-gate switch (ev_type) {
4607c478bd9Sstevel@tonic-gate case DM_EV_DISK_ADD:
4617c478bd9Sstevel@tonic-gate rewalk_tree();
4627c478bd9Sstevel@tonic-gate events_new_event(devname, DM_DRIVE, DM_EV_TADD);
4637c478bd9Sstevel@tonic-gate break;
4647c478bd9Sstevel@tonic-gate case DM_EV_DISK_DELETE:
4657c478bd9Sstevel@tonic-gate orig_name = devname;
4667c478bd9Sstevel@tonic-gate devname = basename(devname);
4677c478bd9Sstevel@tonic-gate del_drive_by_name(devname);
4687c478bd9Sstevel@tonic-gate events_new_event(orig_name, DM_DRIVE, DM_EV_TREMOVE);
4697c478bd9Sstevel@tonic-gate break;
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate cache_unlock();
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate void
cache_wlock()4767c478bd9Sstevel@tonic-gate cache_wlock()
4777c478bd9Sstevel@tonic-gate {
4787c478bd9Sstevel@tonic-gate (void) rw_wrlock(&cache_lock);
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate /*
4827c478bd9Sstevel@tonic-gate * Clear any descriptors that point at the specified cached object.
4837c478bd9Sstevel@tonic-gate * We must go through the whole list since there can be multiple descriptors
4847c478bd9Sstevel@tonic-gate * referencing the same object (i.e. drive/media/slice descriptors all point
4857c478bd9Sstevel@tonic-gate * to the same drive object). The list is usually small (0 size) so this
4867c478bd9Sstevel@tonic-gate * is not a big deal.
4877c478bd9Sstevel@tonic-gate */
4887c478bd9Sstevel@tonic-gate static void
clear_descriptors(void * gp)4897c478bd9Sstevel@tonic-gate clear_descriptors(void *gp)
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate descriptor_t *descp;
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate for (descp = desc_listp; descp != NULL; descp = descp->next) {
4947c478bd9Sstevel@tonic-gate if (descp->p.generic == gp) {
4957c478bd9Sstevel@tonic-gate /* clear descriptor */
4967c478bd9Sstevel@tonic-gate descp->p.generic = NULL;
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate /* remove the ptr from the controller to the specified disk */
5027c478bd9Sstevel@tonic-gate static void
clr_ctrl_disk_ptr(controller_t * cp,disk_t * dp)5037c478bd9Sstevel@tonic-gate clr_ctrl_disk_ptr(controller_t *cp, disk_t *dp)
5047c478bd9Sstevel@tonic-gate {
5057c478bd9Sstevel@tonic-gate int i;
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate for (i = 0; cp->disks[i]; i++) {
5087c478bd9Sstevel@tonic-gate if (dp == cp->disks[i]) {
5097c478bd9Sstevel@tonic-gate int j;
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate for (j = i; cp->disks[j]; j++) {
5127c478bd9Sstevel@tonic-gate cp->disks[j] = cp->disks[j + 1];
5137c478bd9Sstevel@tonic-gate }
5147c478bd9Sstevel@tonic-gate return;
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate /* remove the ptr from the path to the specified disk */
5207c478bd9Sstevel@tonic-gate static void
clr_path_disk_ptr(path_t * pp,disk_t * dp)5217c478bd9Sstevel@tonic-gate clr_path_disk_ptr(path_t *pp, disk_t *dp)
5227c478bd9Sstevel@tonic-gate {
5237c478bd9Sstevel@tonic-gate int i;
5247c478bd9Sstevel@tonic-gate
5257c478bd9Sstevel@tonic-gate for (i = 0; pp->disks[i]; i++) {
5267c478bd9Sstevel@tonic-gate if (dp == pp->disks[i]) {
5277c478bd9Sstevel@tonic-gate int j;
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate for (j = i; pp->disks[j]; j++) {
5307c478bd9Sstevel@tonic-gate pp->disks[j] = pp->disks[j + 1];
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate return;
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate }
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate static void
del_drive(disk_t * dp)5387c478bd9Sstevel@tonic-gate del_drive(disk_t *dp)
5397c478bd9Sstevel@tonic-gate {
5407c478bd9Sstevel@tonic-gate int i;
5417c478bd9Sstevel@tonic-gate disk_t *listp;
5427c478bd9Sstevel@tonic-gate disk_t *prev = NULL;
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate clear_descriptors(dp);
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate /* clear any ptrs from controllers to this drive */
5477c478bd9Sstevel@tonic-gate if (dp->controllers != NULL) {
5487c478bd9Sstevel@tonic-gate for (i = 0; dp->controllers[i]; i++) {
5497c478bd9Sstevel@tonic-gate clr_ctrl_disk_ptr(dp->controllers[i], dp);
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate /* clear any ptrs from paths to this drive */
5547c478bd9Sstevel@tonic-gate if (dp->paths != NULL) {
5557c478bd9Sstevel@tonic-gate for (i = 0; dp->paths[i]; i++) {
5567c478bd9Sstevel@tonic-gate clr_path_disk_ptr(dp->paths[i], dp);
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate
5607c478bd9Sstevel@tonic-gate /* clear drive from disk list */
5617c478bd9Sstevel@tonic-gate for (listp = disk_listp; listp != NULL; listp = listp->next) {
5627c478bd9Sstevel@tonic-gate if (dp == listp) {
5637c478bd9Sstevel@tonic-gate if (prev == NULL) {
5647c478bd9Sstevel@tonic-gate disk_listp = dp->next;
5657c478bd9Sstevel@tonic-gate } else {
5667c478bd9Sstevel@tonic-gate prev->next = dp->next;
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate break;
5707c478bd9Sstevel@tonic-gate }
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate if (prev == NULL) {
5737c478bd9Sstevel@tonic-gate prev = disk_listp;
5747c478bd9Sstevel@tonic-gate } else {
5757c478bd9Sstevel@tonic-gate prev = prev->next;
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate }
5787c478bd9Sstevel@tonic-gate
5797c478bd9Sstevel@tonic-gate cache_free_disk(dp);
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate /*
5837c478bd9Sstevel@tonic-gate * Delete cached drive info when we get a devtree drive delete event.
5847c478bd9Sstevel@tonic-gate */
5857c478bd9Sstevel@tonic-gate static void
del_drive_by_name(char * name)5867c478bd9Sstevel@tonic-gate del_drive_by_name(char *name)
5877c478bd9Sstevel@tonic-gate {
5887c478bd9Sstevel@tonic-gate disk_t *listp;
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate for (listp = disk_listp; listp != NULL; listp = listp->next) {
5917c478bd9Sstevel@tonic-gate alias_t *ap;
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate for (ap = listp->aliases; ap; ap = ap->next) {
5947c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(name, ap->alias)) {
5957c478bd9Sstevel@tonic-gate del_drive(listp);
5967c478bd9Sstevel@tonic-gate return;
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate }
6007c478bd9Sstevel@tonic-gate }
6017c478bd9Sstevel@tonic-gate
6027c478bd9Sstevel@tonic-gate static descriptor_t *
have_desc(int type,void * gp,char * name,char * secondary_name)6037c478bd9Sstevel@tonic-gate have_desc(int type, void *gp, char *name, char *secondary_name)
6047c478bd9Sstevel@tonic-gate {
6057c478bd9Sstevel@tonic-gate descriptor_t *descp;
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate if (name != NULL && name[0] == 0) {
6087c478bd9Sstevel@tonic-gate name = NULL;
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate if (secondary_name != NULL && secondary_name[0] == 0) {
6127c478bd9Sstevel@tonic-gate secondary_name = NULL;
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate descp = desc_listp;
6167c478bd9Sstevel@tonic-gate while (descp != NULL) {
6177c478bd9Sstevel@tonic-gate if (descp->type == type && descp->p.generic == gp &&
6187c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(descp->name, name)) {
6197c478bd9Sstevel@tonic-gate if (type == DM_SLICE || type == DM_PARTITION ||
6207c478bd9Sstevel@tonic-gate type == DM_PATH) {
6217c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(descp->secondary_name,
6227c478bd9Sstevel@tonic-gate secondary_name)) {
6237c478bd9Sstevel@tonic-gate return (descp);
6247c478bd9Sstevel@tonic-gate }
6257c478bd9Sstevel@tonic-gate } else {
6267c478bd9Sstevel@tonic-gate return (descp);
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate descp = descp->next;
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate return (NULL);
6337c478bd9Sstevel@tonic-gate }
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate static int
initialize()6367c478bd9Sstevel@tonic-gate initialize()
6377c478bd9Sstevel@tonic-gate {
6387c478bd9Sstevel@tonic-gate struct search_args args;
6397c478bd9Sstevel@tonic-gate
6407c478bd9Sstevel@tonic-gate if (cache_loaded) {
6417c478bd9Sstevel@tonic-gate return (0);
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate libdiskmgt_init_debug();
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate findevs(&args);
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate if (args.dev_walk_status != 0) {
6497c478bd9Sstevel@tonic-gate return (args.dev_walk_status);
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate
6527c478bd9Sstevel@tonic-gate disk_listp = args.disk_listp;
6537c478bd9Sstevel@tonic-gate controller_listp = args.controller_listp;
6547c478bd9Sstevel@tonic-gate bus_listp = args.bus_listp;
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate cache_loaded = 1;
6577c478bd9Sstevel@tonic-gate
6583e1bd7a2Ssjelinek /*
6593e1bd7a2Ssjelinek * Only start the event thread if we are not doing an install
6603e1bd7a2Ssjelinek */
6613e1bd7a2Ssjelinek if (getenv("_LIBDISKMGT_INSTALL") == NULL) {
66282d71480Ssjelinek if (events_start_event_watcher() != 0) {
66382d71480Ssjelinek /*
66482d71480Ssjelinek * Log a message about the failure to start
66582d71480Ssjelinek * sysevents and continue on.
66682d71480Ssjelinek */
66782d71480Ssjelinek syslog(LOG_WARNING, dgettext(TEXT_DOMAIN,
66882d71480Ssjelinek "libdiskmgt: sysevent thread for cache "
66982d71480Ssjelinek "events failed to start\n"));
6707c478bd9Sstevel@tonic-gate }
6713e1bd7a2Ssjelinek }
6727c478bd9Sstevel@tonic-gate return (0);
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate static int
make_descriptors(int type)6767c478bd9Sstevel@tonic-gate make_descriptors(int type)
6777c478bd9Sstevel@tonic-gate {
6787c478bd9Sstevel@tonic-gate int error;
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate if ((error = initialize()) != 0) {
6817c478bd9Sstevel@tonic-gate return (error);
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate switch (type) {
6857c478bd9Sstevel@tonic-gate case DM_DRIVE:
6867c478bd9Sstevel@tonic-gate error = drive_make_descriptors();
6877c478bd9Sstevel@tonic-gate break;
6887c478bd9Sstevel@tonic-gate case DM_BUS:
6897c478bd9Sstevel@tonic-gate error = bus_make_descriptors();
6907c478bd9Sstevel@tonic-gate break;
6917c478bd9Sstevel@tonic-gate case DM_CONTROLLER:
6927c478bd9Sstevel@tonic-gate error = controller_make_descriptors();
6937c478bd9Sstevel@tonic-gate break;
6947c478bd9Sstevel@tonic-gate case DM_PATH:
6957c478bd9Sstevel@tonic-gate error = path_make_descriptors();
6967c478bd9Sstevel@tonic-gate break;
6977c478bd9Sstevel@tonic-gate case DM_ALIAS:
6987c478bd9Sstevel@tonic-gate error = alias_make_descriptors();
6997c478bd9Sstevel@tonic-gate break;
7007c478bd9Sstevel@tonic-gate case DM_MEDIA:
7017c478bd9Sstevel@tonic-gate error = media_make_descriptors();
7027c478bd9Sstevel@tonic-gate break;
7037c478bd9Sstevel@tonic-gate case DM_PARTITION:
7047c478bd9Sstevel@tonic-gate error = partition_make_descriptors();
7057c478bd9Sstevel@tonic-gate break;
7067c478bd9Sstevel@tonic-gate case DM_SLICE:
7077c478bd9Sstevel@tonic-gate error = slice_make_descriptors();
7087c478bd9Sstevel@tonic-gate break;
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate return (error);
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate static int
match_alias(alias_t * ap,alias_t * listp)7157c478bd9Sstevel@tonic-gate match_alias(alias_t *ap, alias_t *listp)
7167c478bd9Sstevel@tonic-gate {
7177c478bd9Sstevel@tonic-gate if (ap->alias == NULL) {
7187c478bd9Sstevel@tonic-gate return (0);
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate while (listp != NULL) {
7227c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(ap->alias, listp->alias)) {
7237c478bd9Sstevel@tonic-gate return (1);
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate listp = listp->next;
7267c478bd9Sstevel@tonic-gate }
7277c478bd9Sstevel@tonic-gate
7287c478bd9Sstevel@tonic-gate return (0);
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate static int
match_aliases(disk_t * d1p,disk_t * d2p)7327c478bd9Sstevel@tonic-gate match_aliases(disk_t *d1p, disk_t *d2p)
7337c478bd9Sstevel@tonic-gate {
7347c478bd9Sstevel@tonic-gate alias_t *ap;
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate if (d1p->aliases == NULL || d2p->aliases == NULL) {
7377c478bd9Sstevel@tonic-gate return (0);
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate
7407c478bd9Sstevel@tonic-gate ap = d1p->aliases;
7417c478bd9Sstevel@tonic-gate while (ap != NULL) {
7427c478bd9Sstevel@tonic-gate if (match_alias(ap, d2p->aliases)) {
7437c478bd9Sstevel@tonic-gate return (1);
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate ap = ap->next;
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate return (0);
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate static int
match_disk(disk_t * oldp,disk_t * newp)7527c478bd9Sstevel@tonic-gate match_disk(disk_t *oldp, disk_t *newp)
7537c478bd9Sstevel@tonic-gate {
7547c478bd9Sstevel@tonic-gate if (oldp->devid != NULL) {
7557c478bd9Sstevel@tonic-gate if (newp->devid != NULL &&
7567c478bd9Sstevel@tonic-gate devid_compare(oldp->devid, newp->devid) == 0) {
7577c478bd9Sstevel@tonic-gate return (1);
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate } else {
7617c478bd9Sstevel@tonic-gate /* oldp device id is null */
7627c478bd9Sstevel@tonic-gate if (newp->devid == NULL) {
7637c478bd9Sstevel@tonic-gate /* both disks have no device id, check aliases */
7647c478bd9Sstevel@tonic-gate if (match_aliases(oldp, newp)) {
7657c478bd9Sstevel@tonic-gate return (1);
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gate return (0);
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate
7737c478bd9Sstevel@tonic-gate static descriptor_t *
new_descriptor(dm_desc_type_t type,void * op,char * name,char * secondary_name)7747c478bd9Sstevel@tonic-gate new_descriptor(dm_desc_type_t type, void *op, char *name, char *secondary_name)
7757c478bd9Sstevel@tonic-gate {
7767c478bd9Sstevel@tonic-gate descriptor_t *d;
7777c478bd9Sstevel@tonic-gate
7787c478bd9Sstevel@tonic-gate if (name != NULL && name[0] == 0) {
7797c478bd9Sstevel@tonic-gate name = NULL;
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate
7827c478bd9Sstevel@tonic-gate if (secondary_name != NULL && secondary_name[0] == 0) {
7837c478bd9Sstevel@tonic-gate secondary_name = NULL;
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate
7867c478bd9Sstevel@tonic-gate d = (descriptor_t *)malloc(sizeof (descriptor_t));
7877c478bd9Sstevel@tonic-gate if (d == NULL) {
7887c478bd9Sstevel@tonic-gate return (NULL);
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate d->type = type;
7917c478bd9Sstevel@tonic-gate switch (type) {
7927c478bd9Sstevel@tonic-gate case DM_CONTROLLER:
7937c478bd9Sstevel@tonic-gate d->p.controller = op;
7947c478bd9Sstevel@tonic-gate break;
7957c478bd9Sstevel@tonic-gate case DM_BUS:
7967c478bd9Sstevel@tonic-gate d->p.bus = op;
7977c478bd9Sstevel@tonic-gate break;
7987c478bd9Sstevel@tonic-gate default:
7997c478bd9Sstevel@tonic-gate d->p.disk = op;
8007c478bd9Sstevel@tonic-gate break;
8017c478bd9Sstevel@tonic-gate }
8027c478bd9Sstevel@tonic-gate if (name != NULL) {
8037c478bd9Sstevel@tonic-gate d->name = strdup(name);
8047c478bd9Sstevel@tonic-gate if (d->name == NULL) {
8057c478bd9Sstevel@tonic-gate free(d);
8067c478bd9Sstevel@tonic-gate return (NULL);
8077c478bd9Sstevel@tonic-gate }
8087c478bd9Sstevel@tonic-gate } else {
8097c478bd9Sstevel@tonic-gate d->name = NULL;
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate
8127c478bd9Sstevel@tonic-gate if (type == DM_SLICE || type == DM_PARTITION) {
8137c478bd9Sstevel@tonic-gate if (secondary_name != NULL) {
8147c478bd9Sstevel@tonic-gate d->secondary_name = strdup(secondary_name);
8157c478bd9Sstevel@tonic-gate if (d->secondary_name == NULL) {
8167c478bd9Sstevel@tonic-gate free(d->name);
8177c478bd9Sstevel@tonic-gate free(d);
8187c478bd9Sstevel@tonic-gate return (NULL);
8197c478bd9Sstevel@tonic-gate }
8207c478bd9Sstevel@tonic-gate } else {
8217c478bd9Sstevel@tonic-gate d->secondary_name = NULL;
8227c478bd9Sstevel@tonic-gate }
8237c478bd9Sstevel@tonic-gate } else {
8247c478bd9Sstevel@tonic-gate d->secondary_name = NULL;
8257c478bd9Sstevel@tonic-gate }
8267c478bd9Sstevel@tonic-gate
8277c478bd9Sstevel@tonic-gate d->refcnt = 0;
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate /* add this descriptor to the head of the list */
8307c478bd9Sstevel@tonic-gate if (desc_listp != NULL) {
8317c478bd9Sstevel@tonic-gate desc_listp->prev = d;
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate d->prev = NULL;
8347c478bd9Sstevel@tonic-gate d->next = desc_listp;
8357c478bd9Sstevel@tonic-gate desc_listp = d;
8367c478bd9Sstevel@tonic-gate
8377c478bd9Sstevel@tonic-gate return (d);
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate static void
rewalk_tree()8417c478bd9Sstevel@tonic-gate rewalk_tree()
8427c478bd9Sstevel@tonic-gate {
8437c478bd9Sstevel@tonic-gate struct search_args args;
8447c478bd9Sstevel@tonic-gate disk_t *free_disklistp;
8457c478bd9Sstevel@tonic-gate controller_t *free_controllerlistp;
8467c478bd9Sstevel@tonic-gate bus_t *free_buslistp;
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate findevs(&args);
8497c478bd9Sstevel@tonic-gate
8507c478bd9Sstevel@tonic-gate if (args.dev_walk_status == 0) {
8517c478bd9Sstevel@tonic-gate descriptor_t *descp;
8527c478bd9Sstevel@tonic-gate
8537c478bd9Sstevel@tonic-gate /* walk the existing descriptors and update the ptrs */
8547c478bd9Sstevel@tonic-gate descp = desc_listp;
8557c478bd9Sstevel@tonic-gate while (descp != NULL) {
856*b8a9e29cSrm160521 update_desc(descp, args.disk_listp,
857*b8a9e29cSrm160521 args.controller_listp, args.bus_listp);
8587c478bd9Sstevel@tonic-gate descp = descp->next;
8597c478bd9Sstevel@tonic-gate }
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate /* update the cached object ptrs */
8627c478bd9Sstevel@tonic-gate free_disklistp = disk_listp;
8637c478bd9Sstevel@tonic-gate free_controllerlistp = controller_listp;
8647c478bd9Sstevel@tonic-gate free_buslistp = bus_listp;
8657c478bd9Sstevel@tonic-gate disk_listp = args.disk_listp;
8667c478bd9Sstevel@tonic-gate controller_listp = args.controller_listp;
8677c478bd9Sstevel@tonic-gate bus_listp = args.bus_listp;
8687c478bd9Sstevel@tonic-gate
8697c478bd9Sstevel@tonic-gate } else {
8707c478bd9Sstevel@tonic-gate free_disklistp = args.disk_listp;
8717c478bd9Sstevel@tonic-gate free_controllerlistp = args.controller_listp;
8727c478bd9Sstevel@tonic-gate free_buslistp = args.bus_listp;
8737c478bd9Sstevel@tonic-gate }
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate /*
8767c478bd9Sstevel@tonic-gate * Free the memory from either the old cached objects or the failed
8777c478bd9Sstevel@tonic-gate * update objects.
8787c478bd9Sstevel@tonic-gate */
8797c478bd9Sstevel@tonic-gate while (free_disklistp != NULL) {
8807c478bd9Sstevel@tonic-gate disk_t *nextp;
8817c478bd9Sstevel@tonic-gate
8827c478bd9Sstevel@tonic-gate nextp = free_disklistp->next;
8837c478bd9Sstevel@tonic-gate cache_free_disk(free_disklistp);
8847c478bd9Sstevel@tonic-gate free_disklistp = nextp;
8857c478bd9Sstevel@tonic-gate }
8867c478bd9Sstevel@tonic-gate while (free_controllerlistp != NULL) {
8877c478bd9Sstevel@tonic-gate controller_t *nextp;
8887c478bd9Sstevel@tonic-gate
8897c478bd9Sstevel@tonic-gate nextp = free_controllerlistp->next;
8907c478bd9Sstevel@tonic-gate cache_free_controller(free_controllerlistp);
8917c478bd9Sstevel@tonic-gate free_controllerlistp = nextp;
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate while (free_buslistp != NULL) {
8947c478bd9Sstevel@tonic-gate bus_t *nextp;
8957c478bd9Sstevel@tonic-gate
8967c478bd9Sstevel@tonic-gate nextp = free_buslistp->next;
8977c478bd9Sstevel@tonic-gate cache_free_bus(free_buslistp);
8987c478bd9Sstevel@tonic-gate free_buslistp = nextp;
8997c478bd9Sstevel@tonic-gate }
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate
9027c478bd9Sstevel@tonic-gate /*
9037c478bd9Sstevel@tonic-gate * Walk the new set of cached objects and update the descriptor ptr to point
9047c478bd9Sstevel@tonic-gate * to the correct new object. If there is no object any more, set the desc
9057c478bd9Sstevel@tonic-gate * ptr to null.
9067c478bd9Sstevel@tonic-gate */
9077c478bd9Sstevel@tonic-gate static void
update_desc(descriptor_t * descp,disk_t * newdisksp,controller_t * newctrlp,bus_t * newbusp)9087c478bd9Sstevel@tonic-gate update_desc(descriptor_t *descp, disk_t *newdisksp, controller_t *newctrlp,
9097c478bd9Sstevel@tonic-gate bus_t *newbusp)
9107c478bd9Sstevel@tonic-gate {
9117c478bd9Sstevel@tonic-gate /* if the descriptor is already dead, we're done */
9127c478bd9Sstevel@tonic-gate if (descp->p.generic == NULL) {
9137c478bd9Sstevel@tonic-gate return;
9147c478bd9Sstevel@tonic-gate }
9157c478bd9Sstevel@tonic-gate
9167c478bd9Sstevel@tonic-gate /*
9177c478bd9Sstevel@tonic-gate * All descriptors use a disk ptr except for controller descriptors
9187c478bd9Sstevel@tonic-gate * and path descriptors.
9197c478bd9Sstevel@tonic-gate */
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate switch (descp->type) {
9227c478bd9Sstevel@tonic-gate case DM_BUS:
9237c478bd9Sstevel@tonic-gate update_desc_busp(descp, newbusp);
9247c478bd9Sstevel@tonic-gate break;
9257c478bd9Sstevel@tonic-gate case DM_CONTROLLER:
9267c478bd9Sstevel@tonic-gate update_desc_ctrlp(descp, newctrlp);
9277c478bd9Sstevel@tonic-gate break;
9287c478bd9Sstevel@tonic-gate case DM_PATH:
9297c478bd9Sstevel@tonic-gate update_desc_pathp(descp, newctrlp);
9307c478bd9Sstevel@tonic-gate break;
9317c478bd9Sstevel@tonic-gate default:
9327c478bd9Sstevel@tonic-gate update_desc_diskp(descp, newdisksp);
9337c478bd9Sstevel@tonic-gate break;
9347c478bd9Sstevel@tonic-gate }
9357c478bd9Sstevel@tonic-gate }
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate static void
update_desc_busp(descriptor_t * descp,bus_t * busp)9387c478bd9Sstevel@tonic-gate update_desc_busp(descriptor_t *descp, bus_t *busp)
9397c478bd9Sstevel@tonic-gate {
9407c478bd9Sstevel@tonic-gate /* walk the new objects and find the correct bus */
9417c478bd9Sstevel@tonic-gate for (; busp; busp = busp->next) {
9427c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(descp->p.bus->name, busp->name)) {
9437c478bd9Sstevel@tonic-gate descp->p.bus = busp;
9447c478bd9Sstevel@tonic-gate return;
9457c478bd9Sstevel@tonic-gate }
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate /* we did not find the controller any more, clear the ptr in the desc */
9497c478bd9Sstevel@tonic-gate descp->p.bus = NULL;
9507c478bd9Sstevel@tonic-gate }
9517c478bd9Sstevel@tonic-gate
9527c478bd9Sstevel@tonic-gate static void
update_desc_ctrlp(descriptor_t * descp,controller_t * newctrlp)9537c478bd9Sstevel@tonic-gate update_desc_ctrlp(descriptor_t *descp, controller_t *newctrlp)
9547c478bd9Sstevel@tonic-gate {
9557c478bd9Sstevel@tonic-gate /* walk the new objects and find the correct controller */
9567c478bd9Sstevel@tonic-gate for (; newctrlp; newctrlp = newctrlp->next) {
957*b8a9e29cSrm160521 if (libdiskmgt_str_eq(descp->p.controller->name,
958*b8a9e29cSrm160521 newctrlp->name)) {
9597c478bd9Sstevel@tonic-gate descp->p.controller = newctrlp;
9607c478bd9Sstevel@tonic-gate return;
9617c478bd9Sstevel@tonic-gate }
9627c478bd9Sstevel@tonic-gate }
9637c478bd9Sstevel@tonic-gate
9647c478bd9Sstevel@tonic-gate /* we did not find the controller any more, clear the ptr in the desc */
9657c478bd9Sstevel@tonic-gate descp->p.controller = NULL;
9667c478bd9Sstevel@tonic-gate }
9677c478bd9Sstevel@tonic-gate
9687c478bd9Sstevel@tonic-gate static void
update_desc_diskp(descriptor_t * descp,disk_t * newdisksp)9697c478bd9Sstevel@tonic-gate update_desc_diskp(descriptor_t *descp, disk_t *newdisksp)
9707c478bd9Sstevel@tonic-gate {
9717c478bd9Sstevel@tonic-gate /* walk the new objects and find the correct disk */
9727c478bd9Sstevel@tonic-gate for (; newdisksp; newdisksp = newdisksp->next) {
9737c478bd9Sstevel@tonic-gate if (match_disk(descp->p.disk, newdisksp)) {
9747c478bd9Sstevel@tonic-gate descp->p.disk = newdisksp;
9757c478bd9Sstevel@tonic-gate return;
9767c478bd9Sstevel@tonic-gate }
9777c478bd9Sstevel@tonic-gate }
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate /* we did not find the disk any more, clear the ptr in the descriptor */
9807c478bd9Sstevel@tonic-gate descp->p.disk = NULL;
9817c478bd9Sstevel@tonic-gate }
9827c478bd9Sstevel@tonic-gate
9837c478bd9Sstevel@tonic-gate static void
update_desc_pathp(descriptor_t * descp,controller_t * newctrlp)9847c478bd9Sstevel@tonic-gate update_desc_pathp(descriptor_t *descp, controller_t *newctrlp)
9857c478bd9Sstevel@tonic-gate {
9867c478bd9Sstevel@tonic-gate /* walk the new objects and find the correct path */
9877c478bd9Sstevel@tonic-gate for (; newctrlp; newctrlp = newctrlp->next) {
9887c478bd9Sstevel@tonic-gate path_t **pp;
9897c478bd9Sstevel@tonic-gate
9907c478bd9Sstevel@tonic-gate pp = newctrlp->paths;
9917c478bd9Sstevel@tonic-gate if (pp != NULL) {
9927c478bd9Sstevel@tonic-gate int i;
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate for (i = 0; pp[i]; i++) {
995*b8a9e29cSrm160521 if (libdiskmgt_str_eq(descp->p.path->name,
996*b8a9e29cSrm160521 pp[i]->name)) {
9977c478bd9Sstevel@tonic-gate descp->p.path = pp[i];
9987c478bd9Sstevel@tonic-gate return;
9997c478bd9Sstevel@tonic-gate }
10007c478bd9Sstevel@tonic-gate }
10017c478bd9Sstevel@tonic-gate }
10027c478bd9Sstevel@tonic-gate }
10037c478bd9Sstevel@tonic-gate
10047c478bd9Sstevel@tonic-gate /* we did not find the path any more, clear the ptr in the desc */
10057c478bd9Sstevel@tonic-gate descp->p.path = NULL;
10067c478bd9Sstevel@tonic-gate }
1007