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 #include <fcntl.h>
28 #include <libdevinfo.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <sys/dkio.h>
32 #include <sys/sunddi.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35 
36 #include "libdiskmgt.h"
37 #include "disks_private.h"
38 
39 static int		get_status(disk_t *diskp, int fd, nvlist_t *attrs);
40 
41 descriptor_t **
alias_get_assoc_descriptors(descriptor_t * desc,dm_desc_type_t type,int * errp)42 alias_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type,
43     int *errp)
44 {
45 	switch (type) {
46 	case DM_DRIVE:
47 	    return (drive_get_assocs(desc, errp));
48 	}
49 
50 	*errp = EINVAL;
51 	return (NULL);
52 }
53 
54 nvlist_t *
alias_get_attributes(descriptor_t * dp,int * errp)55 alias_get_attributes(descriptor_t *dp, int *errp)
56 {
57 	alias_t		*ap;
58 	nvlist_t	*attrs = NULL;
59 
60 	/* Find the alias for this descriptor */
61 
62 	*errp = ENODEV;
63 	for (ap = dp->p.disk->aliases; ap != NULL; ap = ap->next) {
64 	    if (libdiskmgt_str_eq(dp->name, ap->alias)) {
65 		/* we found the alias for this descriptor */
66 
67 		if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
68 		    *errp = ENOMEM;
69 		    return (NULL);
70 		}
71 
72 		if (ap->target >= 0) {
73 		    if (nvlist_add_uint32(attrs, DM_LUN, ap->lun) != 0) {
74 			nvlist_free(attrs);
75 			*errp = ENOMEM;
76 			return (NULL);
77 		    }
78 
79 		    if (nvlist_add_uint32(attrs, DM_TARGET, ap->target) != 0) {
80 			nvlist_free(attrs);
81 			*errp = ENOMEM;
82 			return (NULL);
83 		    }
84 		}
85 
86 		if (ap->wwn != NULL) {
87 		    if (nvlist_add_string(attrs, DM_WWN, ap->wwn) != 0) {
88 			nvlist_free(attrs);
89 			*errp = ENOMEM;
90 			return (NULL);
91 		    }
92 		}
93 
94 		if (ap->devpaths != NULL) {
95 		    /* get the status for this alias */
96 		    int		fd;
97 
98 		    fd = open(ap->devpaths->devpath, O_RDONLY|O_NDELAY);
99 
100 		    if ((*errp = get_status(dp->p.disk, fd, attrs)) != 0) {
101 			nvlist_free(attrs);
102 			attrs = NULL;
103 		    }
104 
105 		    if (fd >= 0) {
106 			(void) close(fd);
107 		    }
108 		}
109 
110 		*errp = 0;
111 		break;
112 	    }
113 	}
114 
115 	return (attrs);
116 }
117 
118 descriptor_t *
alias_get_descriptor_by_name(char * name,int * errp)119 alias_get_descriptor_by_name(char *name, int *errp)
120 {
121 	descriptor_t	**aliases;
122 	int		i;
123 	descriptor_t	*alias = NULL;
124 
125 	aliases = cache_get_descriptors(DM_ALIAS, errp);
126 	if (*errp != 0) {
127 	    return (NULL);
128 	}
129 
130 	for (i = 0; aliases[i]; i++) {
131 	    if (libdiskmgt_str_eq(name, aliases[i]->name)) {
132 		alias = aliases[i];
133 	    } else {
134 		/* clean up the unused descriptors */
135 		cache_free_descriptor(aliases[i]);
136 	    }
137 	}
138 	free(aliases);
139 
140 	if (alias == NULL) {
141 	    *errp = ENODEV;
142 	}
143 
144 	return (alias);
145 }
146 
147 /* ARGSUSED */
148 descriptor_t **
alias_get_descriptors(int filter[],int * errp)149 alias_get_descriptors(int filter[], int *errp)
150 {
151 	return (cache_get_descriptors(DM_ALIAS, errp));
152 }
153 
154 char *
alias_get_name(descriptor_t * desc)155 alias_get_name(descriptor_t *desc)
156 {
157 	return (desc->name);
158 }
159 
160 /* ARGSUSED */
161 nvlist_t *
alias_get_stats(descriptor_t * dp,int stat_type,int * errp)162 alias_get_stats(descriptor_t *dp, int stat_type, int *errp)
163 {
164 	/* There are no stat types defined for aliases */
165 	*errp = EINVAL;
166 	return (NULL);
167 }
168 
169 int
alias_make_descriptors()170 alias_make_descriptors()
171 {
172 	int		error;
173 	disk_t		*dp;
174 
175 	dp = cache_get_disklist();
176 	while (dp != NULL) {
177 	    alias_t *ap;
178 
179 	    ap = dp->aliases;
180 	    while (ap != NULL) {
181 		if (ap->alias != NULL) {
182 		    cache_load_desc(DM_ALIAS, dp, ap->alias, NULL, &error);
183 		    if (error != 0) {
184 			return (error);
185 		    }
186 		}
187 		ap = ap->next;
188 	    }
189 	    dp = dp->next;
190 	}
191 
192 	return (0);
193 }
194 
195 static int
get_status(disk_t * diskp,int fd,nvlist_t * attrs)196 get_status(disk_t *diskp, int fd, nvlist_t *attrs)
197 {
198 	struct dk_minfo	minfo;
199 
200 	/* Make sure media is inserted and spun up. */
201 	if (fd >= 0 && media_read_info(fd, &minfo)) {
202 
203 	    if (nvlist_add_uint32(attrs, DM_STATUS, DM_DISK_UP) != 0) {
204 		return (ENOMEM);
205 	    }
206 
207 	} else {
208 	    /* Not ready, so either no media or dead. */
209 
210 	    if (diskp->removable) {
211 		/* This is a removable drive with no media. */
212 		if (nvlist_add_uint32(attrs, DM_STATUS, DM_DISK_UP) != 0) {
213 		    return (ENOMEM);
214 		}
215 	    } else {
216 		/* not removable, so must be dead */
217 		if (nvlist_add_uint32(attrs, DM_STATUS, DM_DISK_DOWN) != 0) {
218 		    return (ENOMEM);
219 		}
220 	    }
221 	}
222 
223 	return (0);
224 }
225