4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <libdevinfo.h>
35 #include <sys/sunddi.h>
36 #include <sys/types.h>
40 #include "libdiskmgt.h"
41 #include "disks_private.h"
42 #include "partition.h"
48 * Set DM_LIBDISKMGT_DEBUG in the environment. Two levels of debugging:
49 * 1 - errors, warnings and minimal tracing information
50 * 2 - verbose information
51 * All output prints on stderr.
55 /* Lock protecting the cached data */
56 static rwlock_t cache_lock
= DEFAULTRWLOCK
;
57 static disk_t
*disk_listp
= NULL
;
58 static controller_t
*controller_listp
= NULL
;
59 static bus_t
*bus_listp
= NULL
;
60 static int cache_loaded
= 0;
62 descriptor_t
*desc_listp
= NULL
;
64 static void clear_descriptors(void *gp
);
65 static void clr_ctrl_disk_ptr(controller_t
*cp
, disk_t
*dp
);
66 static void clr_path_disk_ptr(path_t
*pp
, disk_t
*dp
);
67 static void del_drive(disk_t
*dp
);
68 static void del_drive_by_name(char *name
);
69 static descriptor_t
*have_desc(int type
, void *gp
, char *name
, char *mname
);
70 static int initialize();
71 static int make_descriptors(int type
);
72 static int match_disk(disk_t
*oldp
, disk_t
*newp
);
73 static int match_aliases(disk_t
*d1p
, disk_t
*d2p
);
74 static int match_alias(alias_t
*ap
, alias_t
*listp
);
75 static descriptor_t
*new_descriptor(dm_desc_type_t type
, void *op
,
76 char *name
, char *mname
);
77 static void rewalk_tree();
78 static void update_desc(descriptor_t
*descp
, disk_t
*newdisksp
,
79 controller_t
*newctrlp
, bus_t
*newbusp
);
80 static void update_desc_busp(descriptor_t
*descp
, bus_t
*busp
);
81 static void update_desc_ctrlp(descriptor_t
*descp
,
82 controller_t
*newstrlp
);
83 static void update_desc_diskp(descriptor_t
*descp
,
85 static void update_desc_pathp(descriptor_t
*descp
,
86 controller_t
*newctrlp
);
89 * We only cache some of the data that we can obtain. For much of the data
90 * (e.g. slices & disks getting repartitioned) there are no events which would
91 * enable us to cache. As more events are added we can cache more information.
93 * Currently we cache the information we get from the dev tree walk. This is
94 * basically the information about the drives, aliases, devpaths, controllers
95 * and paths. We do not cache any information related to media, partitions
98 * A fundamental part of the API design is that the application can hold on
99 * to a set of descriptors for an indeterminate amount of time. Even if the
100 * application does not hold descriptors there is a window of time between the
101 * call that gets the descriptor and the use of the descriptor to get more
102 * information. Because of this, the cache design must work even if the object
103 * that the descriptor refers to no longer exists.
105 * Given this requirement, the code implements a two level cache. The
106 * descriptors that the application gets are really pointers into the first
107 * level of the cache. This first level contains the actual descriptors.
108 * These descriptors in turn refer to the objects we build from the dev tree
109 * walk which represent the drives and controllers. This is the second level
112 * When we update the second level of the cache (the drives and controllers)
113 * we go through the first level (the descriptors) and update the pointers
114 * in those descriptors to refer to the new objects in the second level. If
115 * the object that the descriptor referred to is no longer in existence, we
116 * just null out the pointer in the descriptor. In this way the code that
117 * uses the descriptors knows that the object referred to by the descriptor
120 * We keep a reference count in the descriptors. This is incremented when
121 * we hand out a pointer to the descriptor and decremented when the application
122 * frees the descriptor it has. When the reference count goes to 0 we garbage
123 * collect the descriptors. In this way we only have to update active
124 * descriptors when we refresh the cache after an event.
126 * An example of the flow when we create descriptors:
127 * dm_get_descriptors libdiskmgt.c
128 * drive_get_descriptors drive.c
129 * cache_get_descriptors cache.c
130 * make_descriptors cache.c
131 * drive_make_descriptors drive.c
132 * cache_load_desc cache.c
133 * {update refcnts on descriptors & return them}
135 * The idea behind cache_get_descriptors and cache_load_desc is that we
136 * seperate the act of making the descriptor within the cache (which requires
137 * us to call back out to one of the object functions - drive_make_descriptors)
138 * from the act of handing out the descriptor (which requires us to increment
139 * the refcnt). In this way we keep all of the refcnt handling centralized
140 * in one function instead of forcing each object to ensure it replicates
141 * the refcnt handling correctly.
143 * Descriptors use two different kinds of indrection to refer to their
144 * corresponding object. For objects we cache (controllers, paths & drives)
145 * the descriptor keeps a pointer to that object. For objects that we
146 * dynamically build, the descriptor uses a combination of a pointer to the
147 * base object (usually the drive) along with a name (e.g. the media name or
148 * the alias). For objects that are based on media (e.g. a slice) we actually
149 * have to maintain a pointer (to the disk) and two names (e.g. the slice name
150 * and the media name which is the secondary name).
154 cache_free_alias(alias_t
*aliasp
)
159 free(aliasp
->kstat_name
);
163 dp
= aliasp
->devpaths
;
173 /* free orig_paths */
174 dp
= aliasp
->orig_paths
;
188 cache_free_bus(bus_t
*bp
)
192 free(bp
->kstat_name
);
194 free(bp
->controllers
);
199 cache_free_controller(controller_t
*cp
)
202 free(cp
->kstat_name
);
204 if (cp
->paths
!= NULL
) {
207 for (i
= 0; cp
->paths
[i
]; i
++) {
208 /* free the path since it can't exist w/o the ctrlr */
209 cache_free_path(cp
->paths
[i
]);
218 cache_free_descriptor(descriptor_t
*desc
)
220 if (!cache_is_valid_desc(desc
)) {
226 if (desc
->refcnt
<= 0) {
228 free(desc
->secondary_name
);
229 if (desc
->prev
== NULL
) {
230 /* this is the first descriptor, update head ptr */
231 desc_listp
= desc
->next
;
233 desc
->prev
->next
= desc
->next
;
235 if (desc
->next
!= NULL
) {
236 desc
->next
->prev
= desc
->prev
;
243 cache_free_descriptors(descriptor_t
**desc_list
)
247 for (i
= 0; desc_list
[i
]; i
++) {
248 cache_free_descriptor(desc_list
[i
]);
255 cache_free_disk(disk_t
*dp
)
260 if (dp
->devid
!= NULL
) {
261 devid_free(dp
->devid
);
263 free(dp
->kernel_name
);
264 free(dp
->product_id
);
266 free(dp
->controllers
);
267 /* the path objects are freed when we free the controller */
274 cache_free_alias(ap
);
282 cache_free_path(path_t
*pp
)
291 for (i
= 0; pp
->wwns
[i
]; i
++) {
303 if (initialize() != 0) {
311 cache_get_controllerlist()
313 if (initialize() != 0) {
317 return (controller_listp
);
321 * This routine will either get the existing descriptor from the descriptor
322 * cache or make make a new descriptor and put it in the descriptor cache and
323 * return a pointer to that descriptor. We increment the refcnt when we hand
324 * out the descriptor.
327 cache_get_desc(int type
, void *gp
, char *name
, char *secondary_name
, int *errp
)
332 if ((dp
= have_desc(type
, gp
, name
, secondary_name
)) == NULL
) {
333 /* make a new desc */
334 if ((dp
= new_descriptor(type
, gp
, name
, secondary_name
))
348 cache_get_descriptors(int type
, int *errp
)
350 descriptor_t
**descs
;
355 if ((*errp
= make_descriptors(type
)) != 0) {
359 /* count the number of active descriptors in the descriptor cache */
361 while (descp
!= NULL
) {
362 if (descp
->type
== type
&& descp
->p
.generic
!= NULL
) {
368 descs
= (descriptor_t
**)calloc(cnt
+ 1, sizeof (descriptor_t
*));
376 while (descp
!= NULL
) {
377 if (descp
->type
== type
&& descp
->p
.generic
!= NULL
) {
378 /* update refcnts before handing out the descriptors */
380 descs
[pos
++] = descp
;
393 if (initialize() != 0) {
401 cache_is_valid_desc(descriptor_t
*d
)
405 for (descp
= desc_listp
; descp
!= NULL
; descp
= descp
->next
) {
415 * This function is called by the *_make_descriptors function
416 * (e.g. drive_make_descriptors) within each of the objects. This function
417 * makes sure that the descriptor is built in the descriptor cache but
418 * it does not hand out the descriptors, so the refcnt is never incremented.
421 cache_load_desc(int type
, void *gp
, char *name
, char *secondary_name
, int *errp
)
424 if (have_desc(type
, gp
, name
, secondary_name
) == NULL
) {
425 /* make a new desc */
426 if (new_descriptor(type
, gp
, name
, secondary_name
) == NULL
) {
435 (void) rw_rdlock(&cache_lock
);
441 (void) rw_unlock(&cache_lock
);
445 * This function is called when we get a devtree event. Type is either add
446 * or delete of a drive.
448 * For delete, we need to clean up the 2nd level structures and clean up
449 * the pointers between the them. We also clear the descriptor ptr.
452 cache_update(dm_event_type_t ev_type
, char *devname
)
458 /* update the cache */
462 events_new_event(devname
, DM_DRIVE
, DM_EV_TADD
);
464 case DM_EV_DISK_DELETE
:
466 devname
= basename(devname
);
467 del_drive_by_name(devname
);
468 events_new_event(orig_name
, DM_DRIVE
, DM_EV_TREMOVE
);
478 (void) rw_wrlock(&cache_lock
);
482 * Clear any descriptors that point at the specified cached object.
483 * We must go through the whole list since there can be multiple descriptors
484 * referencing the same object (i.e. drive/media/slice descriptors all point
485 * to the same drive object). The list is usually small (0 size) so this
489 clear_descriptors(void *gp
)
493 for (descp
= desc_listp
; descp
!= NULL
; descp
= descp
->next
) {
494 if (descp
->p
.generic
== gp
) {
495 /* clear descriptor */
496 descp
->p
.generic
= NULL
;
501 /* remove the ptr from the controller to the specified disk */
503 clr_ctrl_disk_ptr(controller_t
*cp
, disk_t
*dp
)
507 for (i
= 0; cp
->disks
[i
]; i
++) {
508 if (dp
== cp
->disks
[i
]) {
511 for (j
= i
; cp
->disks
[j
]; j
++) {
512 cp
->disks
[j
] = cp
->disks
[j
+ 1];
519 /* remove the ptr from the path to the specified disk */
521 clr_path_disk_ptr(path_t
*pp
, disk_t
*dp
)
525 for (i
= 0; pp
->disks
[i
]; i
++) {
526 if (dp
== pp
->disks
[i
]) {
529 for (j
= i
; pp
->disks
[j
]; j
++) {
530 pp
->disks
[j
] = pp
->disks
[j
+ 1];
538 del_drive(disk_t
*dp
)
544 clear_descriptors(dp
);
546 /* clear any ptrs from controllers to this drive */
547 if (dp
->controllers
!= NULL
) {
548 for (i
= 0; dp
->controllers
[i
]; i
++) {
549 clr_ctrl_disk_ptr(dp
->controllers
[i
], dp
);
553 /* clear any ptrs from paths to this drive */
554 if (dp
->paths
!= NULL
) {
555 for (i
= 0; dp
->paths
[i
]; i
++) {
556 clr_path_disk_ptr(dp
->paths
[i
], dp
);
560 /* clear drive from disk list */
561 for (listp
= disk_listp
; listp
!= NULL
; listp
= listp
->next
) {
564 disk_listp
= dp
->next
;
566 prev
->next
= dp
->next
;
583 * Delete cached drive info when we get a devtree drive delete event.
586 del_drive_by_name(char *name
)
590 for (listp
= disk_listp
; listp
!= NULL
; listp
= listp
->next
) {
593 for (ap
= listp
->aliases
; ap
; ap
= ap
->next
) {
594 if (libdiskmgt_str_eq(name
, ap
->alias
)) {
602 static descriptor_t
*
603 have_desc(int type
, void *gp
, char *name
, char *secondary_name
)
607 if (name
!= NULL
&& name
[0] == 0) {
611 if (secondary_name
!= NULL
&& secondary_name
[0] == 0) {
612 secondary_name
= NULL
;
616 while (descp
!= NULL
) {
617 if (descp
->type
== type
&& descp
->p
.generic
== gp
&&
618 libdiskmgt_str_eq(descp
->name
, name
)) {
619 if (type
== DM_SLICE
|| type
== DM_PARTITION
||
621 if (libdiskmgt_str_eq(descp
->secondary_name
,
638 struct search_args args
;
644 libdiskmgt_init_debug();
648 if (args
.dev_walk_status
!= 0) {
649 return (args
.dev_walk_status
);
652 disk_listp
= args
.disk_listp
;
653 controller_listp
= args
.controller_listp
;
654 bus_listp
= args
.bus_listp
;
659 * Only start the event thread if we are not doing an install
661 if (getenv("_LIBDISKMGT_INSTALL") == NULL
) {
662 if (events_start_event_watcher() != 0) {
664 * Log a message about the failure to start
665 * sysevents and continue on.
667 syslog(LOG_WARNING
, dgettext(TEXT_DOMAIN
,
668 "libdiskmgt: sysevent thread for cache "
669 "events failed to start\n"));
676 make_descriptors(int type
)
680 if ((error
= initialize()) != 0) {
686 error
= drive_make_descriptors();
689 error
= bus_make_descriptors();
692 error
= controller_make_descriptors();
695 error
= path_make_descriptors();
698 error
= alias_make_descriptors();
701 error
= media_make_descriptors();
704 error
= partition_make_descriptors();
707 error
= slice_make_descriptors();
715 match_alias(alias_t
*ap
, alias_t
*listp
)
717 if (ap
->alias
== NULL
) {
721 while (listp
!= NULL
) {
722 if (libdiskmgt_str_eq(ap
->alias
, listp
->alias
)) {
732 match_aliases(disk_t
*d1p
, disk_t
*d2p
)
736 if (d1p
->aliases
== NULL
|| d2p
->aliases
== NULL
) {
742 if (match_alias(ap
, d2p
->aliases
)) {
752 match_disk(disk_t
*oldp
, disk_t
*newp
)
754 if (oldp
->devid
!= NULL
) {
755 if (newp
->devid
!= NULL
&&
756 devid_compare(oldp
->devid
, newp
->devid
) == 0) {
761 /* oldp device id is null */
762 if (newp
->devid
== NULL
) {
763 /* both disks have no device id, check aliases */
764 if (match_aliases(oldp
, newp
)) {
773 static descriptor_t
*
774 new_descriptor(dm_desc_type_t type
, void *op
, char *name
, char *secondary_name
)
778 if (name
!= NULL
&& name
[0] == 0) {
782 if (secondary_name
!= NULL
&& secondary_name
[0] == 0) {
783 secondary_name
= NULL
;
786 d
= (descriptor_t
*)malloc(sizeof (descriptor_t
));
793 d
->p
.controller
= op
;
803 d
->name
= strdup(name
);
804 if (d
->name
== NULL
) {
812 if (type
== DM_SLICE
|| type
== DM_PARTITION
) {
813 if (secondary_name
!= NULL
) {
814 d
->secondary_name
= strdup(secondary_name
);
815 if (d
->secondary_name
== NULL
) {
821 d
->secondary_name
= NULL
;
824 d
->secondary_name
= NULL
;
829 /* add this descriptor to the head of the list */
830 if (desc_listp
!= NULL
) {
831 desc_listp
->prev
= d
;
834 d
->next
= desc_listp
;
843 struct search_args args
;
844 disk_t
*free_disklistp
;
845 controller_t
*free_controllerlistp
;
846 bus_t
*free_buslistp
;
850 if (args
.dev_walk_status
== 0) {
853 /* walk the existing descriptors and update the ptrs */
855 while (descp
!= NULL
) {
856 update_desc(descp
, args
.disk_listp
,
857 args
.controller_listp
, args
.bus_listp
);
861 /* update the cached object ptrs */
862 free_disklistp
= disk_listp
;
863 free_controllerlistp
= controller_listp
;
864 free_buslistp
= bus_listp
;
865 disk_listp
= args
.disk_listp
;
866 controller_listp
= args
.controller_listp
;
867 bus_listp
= args
.bus_listp
;
870 free_disklistp
= args
.disk_listp
;
871 free_controllerlistp
= args
.controller_listp
;
872 free_buslistp
= args
.bus_listp
;
876 * Free the memory from either the old cached objects or the failed
879 while (free_disklistp
!= NULL
) {
882 nextp
= free_disklistp
->next
;
883 cache_free_disk(free_disklistp
);
884 free_disklistp
= nextp
;
886 while (free_controllerlistp
!= NULL
) {
889 nextp
= free_controllerlistp
->next
;
890 cache_free_controller(free_controllerlistp
);
891 free_controllerlistp
= nextp
;
893 while (free_buslistp
!= NULL
) {
896 nextp
= free_buslistp
->next
;
897 cache_free_bus(free_buslistp
);
898 free_buslistp
= nextp
;
903 * Walk the new set of cached objects and update the descriptor ptr to point
904 * to the correct new object. If there is no object any more, set the desc
908 update_desc(descriptor_t
*descp
, disk_t
*newdisksp
, controller_t
*newctrlp
,
911 /* if the descriptor is already dead, we're done */
912 if (descp
->p
.generic
== NULL
) {
917 * All descriptors use a disk ptr except for controller descriptors
918 * and path descriptors.
921 switch (descp
->type
) {
923 update_desc_busp(descp
, newbusp
);
926 update_desc_ctrlp(descp
, newctrlp
);
929 update_desc_pathp(descp
, newctrlp
);
932 update_desc_diskp(descp
, newdisksp
);
938 update_desc_busp(descriptor_t
*descp
, bus_t
*busp
)
940 /* walk the new objects and find the correct bus */
941 for (; busp
; busp
= busp
->next
) {
942 if (libdiskmgt_str_eq(descp
->p
.bus
->name
, busp
->name
)) {
948 /* we did not find the controller any more, clear the ptr in the desc */
953 update_desc_ctrlp(descriptor_t
*descp
, controller_t
*newctrlp
)
955 /* walk the new objects and find the correct controller */
956 for (; newctrlp
; newctrlp
= newctrlp
->next
) {
957 if (libdiskmgt_str_eq(descp
->p
.controller
->name
,
959 descp
->p
.controller
= newctrlp
;
964 /* we did not find the controller any more, clear the ptr in the desc */
965 descp
->p
.controller
= NULL
;
969 update_desc_diskp(descriptor_t
*descp
, disk_t
*newdisksp
)
971 /* walk the new objects and find the correct disk */
972 for (; newdisksp
; newdisksp
= newdisksp
->next
) {
973 if (match_disk(descp
->p
.disk
, newdisksp
)) {
974 descp
->p
.disk
= newdisksp
;
979 /* we did not find the disk any more, clear the ptr in the descriptor */
980 descp
->p
.disk
= NULL
;
984 update_desc_pathp(descriptor_t
*descp
, controller_t
*newctrlp
)
986 /* walk the new objects and find the correct path */
987 for (; newctrlp
; newctrlp
= newctrlp
->next
) {
990 pp
= newctrlp
->paths
;
994 for (i
= 0; pp
[i
]; i
++) {
995 if (libdiskmgt_str_eq(descp
->p
.path
->name
,
997 descp
->p
.path
= pp
[i
];
1004 /* we did not find the path any more, clear the ptr in the desc */
1005 descp
->p
.path
= NULL
;