xref: /illumos-gate/usr/src/lib/libdiskmgt/common/inuse_vxvm.c (revision 628e3cbed6489fa1db545d8524a06cd6535af456)
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 /*
30  * Attempt to dynamically link in the Veritas libvxvmsc.so so that we can
31  * see if there are any Veritas volumes on any of the slices.
32  */
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <strings.h>
37 #include <sys/param.h>
38 #include <sys/errno.h>
39 #include <thread.h>
40 #include <synch.h>
41 #include <dlfcn.h>
42 #include <link.h>
43 #include <ctype.h>
44 
45 #include "libdiskmgt.h"
46 #include "disks_private.h"
47 
48 #define	VXVM_NAME_SIZE	1
49 #define	VXVM_PATH_SIZE	2
50 
51 typedef char	*vm_name_t;
52 typedef char	*vm_path_t;
53 
54 /*
55  * Pointers to libvxvmsc.so functions that we dynamically resolve.
56  */
57 static int (*vxdl_libvxvm_get_version)(int version);
58 static int (*vxdl_libvxvm_get_conf)(int param);
59 static int (*vxdl_libvxvm_get_dgs)(int len, vm_name_t namep[]);
60 static int (*vxdl_libvxvm_get_disks)(vm_name_t dgname, int len,
61 		vm_path_t pathp[]);
62 
63 #define	MAX_DISK_GROUPS 128
64 #define	MAX_DISKS_DG 1024
65 
66 struct vxvm_list {
67 	struct vxvm_list	*next;
68 	char			*slice;
69 };
70 
71 static struct vxvm_list	*vxvm_listp = NULL;
72 static time_t		timestamp = 0;
73 static mutex_t		vxvm_lock = DEFAULTMUTEX;
74 
75 static int	add_use_record(char *devname);
76 static void	free_vxvm();
77 static void	*init_vxvm();
78 static int	is_ctds(char *name);
79 static int	load_vxvm();
80 
81 int
82 inuse_vxvm(char *slice, nvlist_t *attrs, int *errp)
83 {
84 	int		found = 0;
85 	time_t		curr_time;
86 	char		*sp = NULL;
87 
88 	*errp = 0;
89 	if (slice == NULL) {
90 	    return (found);
91 	}
92 
93 	/*
94 	 * Since vxvm "encapsulates" the disk we need to match on any
95 	 * slice passed in.  Strip the slice component from the devname.
96 	 */
97 	if (is_ctds(slice)) {
98 	    if ((sp = strrchr(slice, '/')) == NULL)
99 		sp = slice;
100 
101 	    while (*sp && *sp != 's')
102 		sp++;
103 
104 	    if (*sp)
105 		*sp = 0;
106 	    else
107 		sp = NULL;
108 	}
109 
110 	(void) mutex_lock(&vxvm_lock);
111 
112 	curr_time = time(NULL);
113 	if (timestamp < curr_time && (curr_time - timestamp) > 60) {
114 	    free_vxvm();		/* free old entries */
115 	    *errp = load_vxvm();	/* load the cache */
116 
117 	    timestamp = curr_time;
118 	}
119 
120 	if (*errp == 0) {
121 	    struct vxvm_list	*listp;
122 
123 	    listp = vxvm_listp;
124 	    while (listp != NULL) {
125 		if (strcmp(slice, listp->slice) == 0) {
126 		    libdiskmgt_add_str(attrs, DM_USED_BY, DM_USE_VXVM, errp);
127 		    libdiskmgt_add_str(attrs, DM_USED_NAME, "", errp);
128 		    found = 1;
129 		    break;
130 		}
131 		listp = listp->next;
132 	    }
133 	}
134 
135 	(void) mutex_unlock(&vxvm_lock);
136 
137 	/* restore slice name to orignal value */
138 	if (sp != NULL)
139 	    *sp = 's';
140 
141 	return (found);
142 }
143 
144 static int
145 add_use_record(char *devname)
146 {
147 	struct vxvm_list *sp;
148 
149 	sp = (struct vxvm_list *)malloc(sizeof (struct vxvm_list));
150 	if (sp == NULL) {
151 	    return (ENOMEM);
152 	}
153 
154 	if ((sp->slice = strdup(devname)) == NULL) {
155 	    free(sp);
156 	    return (ENOMEM);
157 	}
158 
159 	sp->next = vxvm_listp;
160 	vxvm_listp = sp;
161 
162 	/*
163 	 * Since vxvm "encapsulates" the disk we need to match on any
164 	 * slice passed in.  Strip the slice component from the devname.
165 	 */
166 	if (is_ctds(sp->slice)) {
167 	    char	*dp;
168 
169 	    if ((dp = strrchr(sp->slice, '/')) == NULL)
170 		dp = sp->slice;
171 
172 	    while (*dp && *dp != 's')
173 		dp++;
174 	    *dp = 0;
175 	}
176 
177 	return (0);
178 }
179 
180 /*
181  * If the input name is in c[t]ds format then return 1, otherwise return 0.
182  */
183 static int
184 is_ctds(char *name)
185 {
186 	char	*p;
187 
188 	if ((p = strrchr(name, '/')) == NULL)
189 	    p = name;
190 	else
191 	    p++;
192 
193 	if (*p++ != 'c') {
194 	    return (0);
195 	}
196 	/* skip controller digits */
197 	while (isdigit(*p)) {
198 	    p++;
199 	}
200 
201 	/* handle optional target */
202 	if (*p == 't') {
203 	    p++;
204 	    /* skip over target */
205 	    while (isdigit(*p) || isupper(*p)) {
206 		p++;
207 	    }
208 	}
209 
210 	if (*p++ != 'd') {
211 	    return (0);
212 	}
213 	while (isdigit(*p)) {
214 	    p++;
215 	}
216 
217 	if (*p++ != 's') {
218 	    return (0);
219 	}
220 
221 	/* check the slice number */
222 	while (isdigit(*p)) {
223 	    p++;
224 	}
225 
226 	if (*p != 0) {
227 	    return (0);
228 	}
229 
230 	return (1);
231 }
232 
233 /*
234  * Free the list of vxvm entries.
235  */
236 static void
237 free_vxvm()
238 {
239 	struct vxvm_list	*listp = vxvm_listp;
240 	struct vxvm_list	*nextp;
241 
242 	while (listp != NULL) {
243 	    nextp = listp->next;
244 	    free((void *)listp->slice);
245 	    free((void *)listp);
246 	    listp = nextp;
247 	}
248 
249 	vxvm_listp = NULL;
250 }
251 
252 /*
253  * Try to dynamically link the vxvm functions we need.
254  */
255 static void *
256 init_vxvm()
257 {
258 	void	*lh;
259 
260 	if ((lh = dlopen("libvxvmsc.so", RTLD_NOW)) == NULL) {
261 	    return (lh);
262 	}
263 
264 	if ((vxdl_libvxvm_get_version = (int (*)(int))dlsym(lh,
265 	    "libvxvm_get_version")) == NULL) {
266 	    (void) dlclose(lh);
267 	    return (NULL);
268 	}
269 
270 	if ((vxdl_libvxvm_get_conf = (int (*)(int))dlsym(lh,
271 	    "libvxvm_get_conf")) == NULL) {
272 	    (void) dlclose(lh);
273 	    return (NULL);
274 	}
275 
276 	if ((vxdl_libvxvm_get_dgs = (int (*)(int, vm_name_t []))dlsym(lh,
277 	    "libvxvm_get_dgs")) == NULL) {
278 	    (void) dlclose(lh);
279 	    return (NULL);
280 	}
281 
282 	if ((vxdl_libvxvm_get_disks = (int (*)(vm_name_t, int, vm_path_t []))
283 	    dlsym(lh, "libvxvm_get_disks")) == NULL) {
284 	    (void) dlclose(lh);
285 	    return (NULL);
286 	}
287 
288 	return (lh);
289 }
290 
291 static int
292 load_vxvm()
293 {
294 	void		*lh;
295 	int		vers;
296 	int		nsize;
297 	int		psize;
298 	int		n_disk_groups;
299 	vm_name_t	*namep;
300 	char		*pnp;
301 	vm_path_t	*pathp;
302 	int		i;
303 
304 	if ((lh = init_vxvm()) == NULL) {
305 	    /* No library. */
306 	    return (0);
307 	}
308 
309 	vers = (vxdl_libvxvm_get_version)(1 << 8);
310 	if (vers == -1) {
311 	    /* unsupported version */
312 	    (void) dlclose(lh);
313 	    return (0);
314 	}
315 
316 	nsize = (vxdl_libvxvm_get_conf)(VXVM_NAME_SIZE);
317 	psize = (vxdl_libvxvm_get_conf)(VXVM_PATH_SIZE);
318 
319 	if (nsize == -1 || psize == -1) {
320 	    (void) dlclose(lh);
321 	    return (0);
322 	}
323 
324 	namep = (vm_name_t *)calloc(MAX_DISK_GROUPS, nsize);
325 	if (namep == NULL) {
326 	    (void) dlclose(lh);
327 	    return (ENOMEM);
328 	}
329 
330 	pathp = (vm_path_t *)calloc(MAX_DISKS_DG, psize);
331 	if (pathp == NULL) {
332 	    (void) dlclose(lh);
333 	    free(namep);
334 	    return (ENOMEM);
335 	}
336 
337 	n_disk_groups = (vxdl_libvxvm_get_dgs)(MAX_DISK_GROUPS, namep);
338 	if (n_disk_groups < 0) {
339 	    (void) dlclose(lh);
340 	    free(namep);
341 	    free(pathp);
342 	    return (0);
343 	}
344 
345 	pnp = (char *)namep;
346 	for (i = 0; i < n_disk_groups; i++) {
347 	    int n_disks;
348 
349 	    n_disks = (vxdl_libvxvm_get_disks)(pnp, MAX_DISKS_DG, pathp);
350 
351 	    if (n_disks >= 0) {
352 		int	j;
353 		char	*ppp;
354 
355 		ppp = (char *)pathp;
356 		for (j = 0; j < n_disks; j++) {
357 
358 		    if (strncmp(ppp, "/dev/vx/", 8) == 0) {
359 			char	*pslash;
360 			char	nm[MAXPATHLEN];
361 
362 			pslash = strrchr(ppp, '/');
363 			pslash++;
364 
365 			(void) snprintf(nm, sizeof (nm), "/dev/dsk/%s", pslash);
366 			if (add_use_record(nm)) {
367 			    (void) dlclose(lh);
368 			    free(pathp);
369 			    free(namep);
370 			    return (ENOMEM);
371 			}
372 		    } else {
373 			if (add_use_record(ppp)) {
374 			    (void) dlclose(lh);
375 			    free(pathp);
376 			    free(namep);
377 			    return (ENOMEM);
378 			}
379 		    }
380 
381 		    ppp += psize;
382 		}
383 	    }
384 
385 	    pnp += nsize;
386 	}
387 
388 	(void) dlclose(lh);
389 	free(pathp);
390 	free(namep);
391 
392 	return (0);
393 }
394