1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <fcntl.h>
30 #include <libdevinfo.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <sys/dkio.h>
34 #include <sys/sunddi.h>
35 #include <sys/types.h>
36 #include <unistd.h>
37 
38 #include "libdiskmgt.h"
39 #include "disks_private.h"
40 
41 static int		get_status(disk_t *diskp, int fd, nvlist_t *attrs);
42 
43 descriptor_t **
alias_get_assoc_descriptors(descriptor_t * desc,dm_desc_type_t type,int * errp)44 alias_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type,
45     int *errp)
46 {
47 	switch (type) {
48 	case DM_DRIVE:
49 	    return (drive_get_assocs(desc, errp));
50 	}
51 
52 	*errp = EINVAL;
53 	return (NULL);
54 }
55 
56 nvlist_t *
alias_get_attributes(descriptor_t * dp,int * errp)57 alias_get_attributes(descriptor_t *dp, int *errp)
58 {
59 	alias_t		*ap;
60 	nvlist_t	*attrs = NULL;
61 
62 	/* Find the alias for this descriptor */
63 
64 	*errp = ENODEV;
65 	for (ap = dp->p.disk->aliases; ap != NULL; ap = ap->next) {
66 	    if (libdiskmgt_str_eq(dp->name, ap->alias)) {
67 		/* we found the alias for this descriptor */
68 
69 		if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
70 		    *errp = ENOMEM;
71 		    return (NULL);
72 		}
73 
74 		if (ap->target >= 0) {
75 		    if (nvlist_add_uint32(attrs, DM_LUN, ap->lun) != 0) {
76 			nvlist_free(attrs);
77 			*errp = ENOMEM;
78 			return (NULL);
79 		    }
80 
81 		    if (nvlist_add_uint32(attrs, DM_TARGET, ap->target) != 0) {
82 			nvlist_free(attrs);
83 			*errp = ENOMEM;
84 			return (NULL);
85 		    }
86 		}
87 
88 		if (ap->wwn != NULL) {
89 		    if (nvlist_add_string(attrs, DM_WWN, ap->wwn) != 0) {
90 			nvlist_free(attrs);
91 			*errp = ENOMEM;
92 			return (NULL);
93 		    }
94 		}
95 
96 		if (ap->devpaths != NULL) {
97 		    /* get the status for this alias */
98 		    int		fd;
99 
100 		    fd = open(ap->devpaths->devpath, O_RDONLY|O_NDELAY);
101 
102 		    if ((*errp = get_status(dp->p.disk, fd, attrs)) != 0) {
103 			nvlist_free(attrs);
104 			attrs = NULL;
105 		    }
106 
107 		    if (fd >= 0) {
108 			(void) close(fd);
109 		    }
110 		}
111 
112 		*errp = 0;
113 		break;
114 	    }
115 	}
116 
117 	return (attrs);
118 }
119 
120 descriptor_t *
alias_get_descriptor_by_name(char * name,int * errp)121 alias_get_descriptor_by_name(char *name, int *errp)
122 {
123 	descriptor_t	**aliases;
124 	int		i;
125 	descriptor_t	*alias = NULL;
126 
127 	aliases = cache_get_descriptors(DM_ALIAS, errp);
128 	if (*errp != 0) {
129 	    return (NULL);
130 	}
131 
132 	for (i = 0; aliases[i]; i++) {
133 	    if (libdiskmgt_str_eq(name, aliases[i]->name)) {
134 		alias = aliases[i];
135 	    } else {
136 		/* clean up the unused descriptors */
137 		cache_free_descriptor(aliases[i]);
138 	    }
139 	}
140 	free(aliases);
141 
142 	if (alias == NULL) {
143 	    *errp = ENODEV;
144 	}
145 
146 	return (alias);
147 }
148 
149 /* ARGSUSED */
150 descriptor_t **
alias_get_descriptors(int filter[],int * errp)151 alias_get_descriptors(int filter[], int *errp)
152 {
153 	return (cache_get_descriptors(DM_ALIAS, errp));
154 }
155 
156 char *
alias_get_name(descriptor_t * desc)157 alias_get_name(descriptor_t *desc)
158 {
159 	return (desc->name);
160 }
161 
162 /* ARGSUSED */
163 nvlist_t *
alias_get_stats(descriptor_t * dp,int stat_type,int * errp)164 alias_get_stats(descriptor_t *dp, int stat_type, int *errp)
165 {
166 	/* There are no stat types defined for aliases */
167 	*errp = EINVAL;
168 	return (NULL);
169 }
170 
171 int
alias_make_descriptors()172 alias_make_descriptors()
173 {
174 	int		error;
175 	disk_t		*dp;
176 
177 	dp = cache_get_disklist();
178 	while (dp != NULL) {
179 	    alias_t *ap;
180 
181 	    ap = dp->aliases;
182 	    while (ap != NULL) {
183 		if (ap->alias != NULL) {
184 		    cache_load_desc(DM_ALIAS, dp, ap->alias, NULL, &error);
185 		    if (error != 0) {
186 			return (error);
187 		    }
188 		}
189 		ap = ap->next;
190 	    }
191 	    dp = dp->next;
192 	}
193 
194 	return (0);
195 }
196 
197 static int
get_status(disk_t * diskp,int fd,nvlist_t * attrs)198 get_status(disk_t *diskp, int fd, nvlist_t *attrs)
199 {
200 	struct dk_minfo	minfo;
201 
202 	/* Make sure media is inserted and spun up. */
203 	if (fd >= 0 && media_read_info(fd, &minfo)) {
204 
205 	    if (nvlist_add_uint32(attrs, DM_STATUS, DM_DISK_UP) != 0) {
206 		return (ENOMEM);
207 	    }
208 
209 	} else {
210 	    /* Not ready, so either no media or dead. */
211 
212 	    if (diskp->removable) {
213 		/* This is a removable drive with no media. */
214 		if (nvlist_add_uint32(attrs, DM_STATUS, DM_DISK_UP) != 0) {
215 		    return (ENOMEM);
216 		}
217 	    } else {
218 		/* not removable, so must be dead */
219 		if (nvlist_add_uint32(attrs, DM_STATUS, DM_DISK_DOWN) != 0) {
220 		    return (ENOMEM);
221 		}
222 	    }
223 	}
224 
225 	return (0);
226 }
227