dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libdiskmgt / common / path.c
blobd9b2fafaa0a86b77a2f8db07feb71c9883329ade
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <fcntl.h>
29 #include <libdevinfo.h>
30 #include <stdlib.h>
31 #include <sys/sunddi.h>
32 #include <sys/types.h>
34 #include "libdiskmgt.h"
35 #include "disks_private.h"
37 static int add_path_state(descriptor_t *dp, nvlist_t *attrs);
38 static int add_wwn(descriptor_t *dp, nvlist_t *attrs);
39 static descriptor_t **get_assoc_drives(descriptor_t *desc, int *errp);
40 static descriptor_t **get_assoc_controllers(descriptor_t *desc, int *errp);
41 static char *path_state_name(di_path_state_t st);
43 descriptor_t **
44 path_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type, int *errp)
46 switch (type) {
47 case DM_DRIVE:
48 return (get_assoc_drives(desc, errp));
49 case DM_CONTROLLER:
50 return (get_assoc_controllers(desc, errp));
53 *errp = EINVAL;
54 return (NULL);
57 nvlist_t *
58 path_get_attributes(descriptor_t *dp, int *errp)
60 path_t *pp;
61 nvlist_t *attrs = NULL;
63 pp = dp->p.path;
65 if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
66 *errp = ENOMEM;
67 return (NULL);
70 if (nvlist_add_string(attrs, DM_CTYPE, pp->ctype) != 0) {
71 nvlist_free(attrs);
72 *errp = ENOMEM;
73 return (NULL);
77 * We add the path state and wwn attributes only for descriptors that
78 * we got via their association to a specific drive (since these
79 * attributes are drive specific).
81 if (dp->name != NULL) {
82 if (add_path_state(dp, attrs) != 0) {
83 nvlist_free(attrs);
84 *errp = ENOMEM;
85 return (NULL);
87 if (add_wwn(dp, attrs) != 0) {
88 nvlist_free(attrs);
89 *errp = ENOMEM;
90 return (NULL);
94 *errp = 0;
95 return (attrs);
98 descriptor_t *
99 path_get_descriptor_by_name(char *name, int *errp)
101 descriptor_t **paths;
102 int i;
103 descriptor_t *path = NULL;
105 paths = cache_get_descriptors(DM_PATH, errp);
106 if (*errp != 0) {
107 return (NULL);
110 for (i = 0; paths[i]; i++) {
111 if (libdiskmgt_str_eq(name, paths[i]->p.path->name)) {
112 path = paths[i];
113 } else {
114 /* clean up the unused descriptors */
115 cache_free_descriptor(paths[i]);
118 free(paths);
120 if (path == NULL) {
121 *errp = ENODEV;
124 return (path);
127 /* ARGSUSED */
128 descriptor_t **
129 path_get_descriptors(int filter[], int *errp)
131 return (cache_get_descriptors(DM_PATH, errp));
134 char *
135 path_get_name(descriptor_t *desc)
137 return (desc->p.path->name);
140 /* ARGSUSED */
141 nvlist_t *
142 path_get_stats(descriptor_t *dp, int stat_type, int *errp)
144 /* There are no stat types defined for paths */
145 *errp = EINVAL;
146 return (NULL);
150 path_make_descriptors()
152 int error;
153 controller_t *cp;
155 cp = cache_get_controllerlist();
156 while (cp != NULL) {
157 if (cp->paths != NULL) {
158 int i;
160 for (i = 0; cp->paths[i]; i++) {
161 cache_load_desc(DM_PATH, cp->paths[i], NULL, NULL, &error);
162 if (error != 0) {
163 return (error);
167 cp = cp->next;
170 return (0);
174 * This is called when we have a name in the descriptor name field. That
175 * only will be the case when the descriptor was created by getting the
176 * association from a drive to the path. Since we filled in the name with
177 * the drive device id in that case, we can use the device id to look up the
178 * drive-path state.
180 static int
181 add_path_state(descriptor_t *dp, nvlist_t *attrs)
183 ddi_devid_t devid;
184 path_t *pp;
185 int i;
186 int status = 0;
188 if (devid_str_decode(dp->name, &devid, NULL) != 0) {
189 return (0);
192 /* find the index of the correct drive assoc. */
193 pp = dp->p.path;
194 for (i = 0; pp->disks[i] && pp->states[i] != -1; i++) {
195 if (pp->disks[i]->devid != NULL &&
196 devid_compare(pp->disks[i]->devid, devid) == 0) {
198 /* add the corresponding state */
199 if (nvlist_add_string(attrs, DM_PATH_STATE,
200 path_state_name(pp->states[i])) != 0) {
201 status = ENOMEM;
203 break;
206 devid_free(devid);
208 return (status);
212 * This is called when we have a name in the descriptor name field. That
213 * only will be the case when the descriptor was created by getting the
214 * association from a drive to the path. Since we filled in the name with
215 * the drive device id in that case, we can use the device id to look up the
216 * drive wwn.
218 static int
219 add_wwn(descriptor_t *dp, nvlist_t *attrs)
221 ddi_devid_t devid;
222 path_t *pp;
223 int i;
224 int status = 0;
226 if (devid_str_decode(dp->name, &devid, NULL) != 0) {
227 return (0);
230 /* find the index of the correct drive assoc. */
231 pp = dp->p.path;
232 for (i = 0; pp->disks[i] && pp->states[i] != -1; i++) {
233 if (pp->disks[i]->devid != NULL &&
234 devid_compare(pp->disks[i]->devid, devid) == 0) {
236 /* add the corresponding state */
237 if (nvlist_add_string(attrs, DM_WWN, pp->wwns[i]) != 0) {
238 status = ENOMEM;
240 break;
243 devid_free(devid);
245 return (status);
248 static descriptor_t **
249 get_assoc_controllers(descriptor_t *desc, int *errp)
251 path_t *pp;
252 descriptor_t **controllers;
253 int i;
255 pp = desc->p.path;
257 /* a path can have just one controller */
259 controllers = (descriptor_t **)calloc(2, sizeof (descriptor_t *));
260 if (controllers == NULL) {
261 *errp = ENOMEM;
262 return (NULL);
265 i = 0;
266 if (pp->controller != NULL) {
267 controllers[i++] = cache_get_desc(DM_CONTROLLER,
268 pp->controller, NULL, NULL, errp);
269 if (*errp != 0) {
270 cache_free_descriptors(controllers);
271 return (NULL);
275 controllers[i] = NULL;
277 *errp = 0;
278 return (controllers);
281 static descriptor_t **
282 get_assoc_drives(descriptor_t *desc, int *errp)
284 path_t *pp;
285 descriptor_t **drives;
286 int cnt;
287 int i;
289 pp = desc->p.path;
291 /* Count how many we have. */
292 for (cnt = 0; pp->disks[cnt]; cnt++);
294 /* make the snapshot */
295 drives = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
296 if (drives == NULL) {
297 *errp = ENOMEM;
298 return (NULL);
301 for (i = 0; pp->disks[i]; i++) {
302 drives[i] = cache_get_desc(DM_DRIVE, pp->disks[i], NULL, NULL,
303 errp);
304 if (*errp != 0) {
305 cache_free_descriptors(drives);
306 return (NULL);
309 drives[i] = NULL;
311 *errp = 0;
312 return (drives);
315 static char *
316 path_state_name(di_path_state_t st)
318 switch (st) {
319 case DI_PATH_STATE_ONLINE:
320 return ("online");
321 case DI_PATH_STATE_STANDBY:
322 return ("standby");
323 case DI_PATH_STATE_OFFLINE:
324 return ("offline");
325 case DI_PATH_STATE_FAULT:
326 return ("faulted");
328 return ("unknown");