10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*8276SJiri.Cervenka@Sun.COM * Common Development and Distribution License (the "License").
6*8276SJiri.Cervenka@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*8276SJiri.Cervenka@Sun.COM
220Sstevel@tonic-gate /*
23*8276SJiri.Cervenka@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate * Attempt to dynamically link in the Veritas libvxvmsc.so so that we can
290Sstevel@tonic-gate * see if there are any Veritas volumes on any of the slices.
300Sstevel@tonic-gate */
310Sstevel@tonic-gate
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <strings.h>
350Sstevel@tonic-gate #include <sys/param.h>
360Sstevel@tonic-gate #include <sys/errno.h>
370Sstevel@tonic-gate #include <thread.h>
380Sstevel@tonic-gate #include <synch.h>
390Sstevel@tonic-gate #include <dlfcn.h>
400Sstevel@tonic-gate #include <link.h>
410Sstevel@tonic-gate #include <ctype.h>
420Sstevel@tonic-gate
430Sstevel@tonic-gate #include "libdiskmgt.h"
440Sstevel@tonic-gate #include "disks_private.h"
450Sstevel@tonic-gate
46*8276SJiri.Cervenka@Sun.COM #define VXVM_LIB_NAME "libvxvmsc.so"
47*8276SJiri.Cervenka@Sun.COM
480Sstevel@tonic-gate #define VXVM_NAME_SIZE 1
490Sstevel@tonic-gate #define VXVM_PATH_SIZE 2
500Sstevel@tonic-gate
510Sstevel@tonic-gate typedef char *vm_name_t;
520Sstevel@tonic-gate typedef char *vm_path_t;
530Sstevel@tonic-gate
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate * Pointers to libvxvmsc.so functions that we dynamically resolve.
560Sstevel@tonic-gate */
570Sstevel@tonic-gate static int (*vxdl_libvxvm_get_version)(int version);
580Sstevel@tonic-gate static int (*vxdl_libvxvm_get_conf)(int param);
590Sstevel@tonic-gate static int (*vxdl_libvxvm_get_dgs)(int len, vm_name_t namep[]);
600Sstevel@tonic-gate static int (*vxdl_libvxvm_get_disks)(vm_name_t dgname, int len,
610Sstevel@tonic-gate vm_path_t pathp[]);
620Sstevel@tonic-gate
630Sstevel@tonic-gate #define MAX_DISK_GROUPS 128
640Sstevel@tonic-gate #define MAX_DISKS_DG 1024
650Sstevel@tonic-gate
660Sstevel@tonic-gate struct vxvm_list {
670Sstevel@tonic-gate struct vxvm_list *next;
680Sstevel@tonic-gate char *slice;
690Sstevel@tonic-gate };
700Sstevel@tonic-gate
710Sstevel@tonic-gate static struct vxvm_list *vxvm_listp = NULL;
720Sstevel@tonic-gate static time_t timestamp = 0;
730Sstevel@tonic-gate static mutex_t vxvm_lock = DEFAULTMUTEX;
740Sstevel@tonic-gate
750Sstevel@tonic-gate static int add_use_record(char *devname);
760Sstevel@tonic-gate static void free_vxvm();
770Sstevel@tonic-gate static void *init_vxvm();
780Sstevel@tonic-gate static int is_ctds(char *name);
790Sstevel@tonic-gate static int load_vxvm();
800Sstevel@tonic-gate
810Sstevel@tonic-gate int
inuse_vxvm(char * slice,nvlist_t * attrs,int * errp)820Sstevel@tonic-gate inuse_vxvm(char *slice, nvlist_t *attrs, int *errp)
830Sstevel@tonic-gate {
840Sstevel@tonic-gate int found = 0;
850Sstevel@tonic-gate time_t curr_time;
860Sstevel@tonic-gate char *sp = NULL;
870Sstevel@tonic-gate
880Sstevel@tonic-gate *errp = 0;
890Sstevel@tonic-gate if (slice == NULL) {
90*8276SJiri.Cervenka@Sun.COM return (found);
910Sstevel@tonic-gate }
920Sstevel@tonic-gate
930Sstevel@tonic-gate /*
940Sstevel@tonic-gate * Since vxvm "encapsulates" the disk we need to match on any
950Sstevel@tonic-gate * slice passed in. Strip the slice component from the devname.
960Sstevel@tonic-gate */
970Sstevel@tonic-gate if (is_ctds(slice)) {
98*8276SJiri.Cervenka@Sun.COM if ((sp = strrchr(slice, '/')) == NULL)
99*8276SJiri.Cervenka@Sun.COM sp = slice;
1000Sstevel@tonic-gate
101*8276SJiri.Cervenka@Sun.COM while (*sp && *sp != 's')
102*8276SJiri.Cervenka@Sun.COM sp++;
1030Sstevel@tonic-gate
104*8276SJiri.Cervenka@Sun.COM if (*sp)
105*8276SJiri.Cervenka@Sun.COM *sp = 0;
106*8276SJiri.Cervenka@Sun.COM else
107*8276SJiri.Cervenka@Sun.COM sp = NULL;
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate (void) mutex_lock(&vxvm_lock);
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate curr_time = time(NULL);
1130Sstevel@tonic-gate if (timestamp < curr_time && (curr_time - timestamp) > 60) {
114*8276SJiri.Cervenka@Sun.COM free_vxvm(); /* free old entries */
115*8276SJiri.Cervenka@Sun.COM *errp = load_vxvm(); /* load the cache */
1160Sstevel@tonic-gate
117*8276SJiri.Cervenka@Sun.COM timestamp = curr_time;
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate if (*errp == 0) {
121*8276SJiri.Cervenka@Sun.COM struct vxvm_list *listp;
1220Sstevel@tonic-gate
123*8276SJiri.Cervenka@Sun.COM listp = vxvm_listp;
124*8276SJiri.Cervenka@Sun.COM while (listp != NULL) {
125*8276SJiri.Cervenka@Sun.COM if (strcmp(slice, listp->slice) == 0) {
126*8276SJiri.Cervenka@Sun.COM libdiskmgt_add_str(attrs, DM_USED_BY,
127*8276SJiri.Cervenka@Sun.COM DM_USE_VXVM, errp);
128*8276SJiri.Cervenka@Sun.COM libdiskmgt_add_str(attrs, DM_USED_NAME,
129*8276SJiri.Cervenka@Sun.COM "", errp);
130*8276SJiri.Cervenka@Sun.COM found = 1;
131*8276SJiri.Cervenka@Sun.COM break;
132*8276SJiri.Cervenka@Sun.COM }
133*8276SJiri.Cervenka@Sun.COM listp = listp->next;
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate (void) mutex_unlock(&vxvm_lock);
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate /* restore slice name to orignal value */
1400Sstevel@tonic-gate if (sp != NULL)
141*8276SJiri.Cervenka@Sun.COM *sp = 's';
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate return (found);
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate static int
add_use_record(char * devname)1470Sstevel@tonic-gate add_use_record(char *devname)
1480Sstevel@tonic-gate {
1490Sstevel@tonic-gate struct vxvm_list *sp;
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate sp = (struct vxvm_list *)malloc(sizeof (struct vxvm_list));
1520Sstevel@tonic-gate if (sp == NULL) {
153*8276SJiri.Cervenka@Sun.COM return (ENOMEM);
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate if ((sp->slice = strdup(devname)) == NULL) {
157*8276SJiri.Cervenka@Sun.COM free(sp);
158*8276SJiri.Cervenka@Sun.COM return (ENOMEM);
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate sp->next = vxvm_listp;
1620Sstevel@tonic-gate vxvm_listp = sp;
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate /*
1650Sstevel@tonic-gate * Since vxvm "encapsulates" the disk we need to match on any
1660Sstevel@tonic-gate * slice passed in. Strip the slice component from the devname.
1670Sstevel@tonic-gate */
1680Sstevel@tonic-gate if (is_ctds(sp->slice)) {
169*8276SJiri.Cervenka@Sun.COM char *dp;
1700Sstevel@tonic-gate
171*8276SJiri.Cervenka@Sun.COM if ((dp = strrchr(sp->slice, '/')) == NULL)
172*8276SJiri.Cervenka@Sun.COM dp = sp->slice;
1730Sstevel@tonic-gate
174*8276SJiri.Cervenka@Sun.COM while (*dp && *dp != 's')
175*8276SJiri.Cervenka@Sun.COM dp++;
176*8276SJiri.Cervenka@Sun.COM *dp = 0;
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate return (0);
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate /*
1830Sstevel@tonic-gate * If the input name is in c[t]ds format then return 1, otherwise return 0.
1840Sstevel@tonic-gate */
1850Sstevel@tonic-gate static int
is_ctds(char * name)1860Sstevel@tonic-gate is_ctds(char *name)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate char *p;
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate if ((p = strrchr(name, '/')) == NULL)
191*8276SJiri.Cervenka@Sun.COM p = name;
1920Sstevel@tonic-gate else
193*8276SJiri.Cervenka@Sun.COM p++;
1940Sstevel@tonic-gate
1950Sstevel@tonic-gate if (*p++ != 'c') {
196*8276SJiri.Cervenka@Sun.COM return (0);
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate /* skip controller digits */
1990Sstevel@tonic-gate while (isdigit(*p)) {
200*8276SJiri.Cervenka@Sun.COM p++;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate /* handle optional target */
2040Sstevel@tonic-gate if (*p == 't') {
2050Sstevel@tonic-gate p++;
206*8276SJiri.Cervenka@Sun.COM /* skip over target */
207*8276SJiri.Cervenka@Sun.COM while (isdigit(*p) || isupper(*p)) {
208*8276SJiri.Cervenka@Sun.COM p++;
209*8276SJiri.Cervenka@Sun.COM }
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate if (*p++ != 'd') {
213*8276SJiri.Cervenka@Sun.COM return (0);
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate while (isdigit(*p)) {
216*8276SJiri.Cervenka@Sun.COM p++;
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate if (*p++ != 's') {
220*8276SJiri.Cervenka@Sun.COM return (0);
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate /* check the slice number */
2240Sstevel@tonic-gate while (isdigit(*p)) {
225*8276SJiri.Cervenka@Sun.COM p++;
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate if (*p != 0) {
229*8276SJiri.Cervenka@Sun.COM return (0);
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate return (1);
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate /*
2360Sstevel@tonic-gate * Free the list of vxvm entries.
2370Sstevel@tonic-gate */
2380Sstevel@tonic-gate static void
free_vxvm()2390Sstevel@tonic-gate free_vxvm()
2400Sstevel@tonic-gate {
2410Sstevel@tonic-gate struct vxvm_list *listp = vxvm_listp;
2420Sstevel@tonic-gate struct vxvm_list *nextp;
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate while (listp != NULL) {
245*8276SJiri.Cervenka@Sun.COM nextp = listp->next;
246*8276SJiri.Cervenka@Sun.COM free((void *)listp->slice);
247*8276SJiri.Cervenka@Sun.COM free((void *)listp);
248*8276SJiri.Cervenka@Sun.COM listp = nextp;
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate vxvm_listp = NULL;
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate /*
2550Sstevel@tonic-gate * Try to dynamically link the vxvm functions we need.
2560Sstevel@tonic-gate */
2570Sstevel@tonic-gate static void *
init_vxvm()2580Sstevel@tonic-gate init_vxvm()
2590Sstevel@tonic-gate {
2600Sstevel@tonic-gate void *lh;
2610Sstevel@tonic-gate
262*8276SJiri.Cervenka@Sun.COM if ((lh = dlopen(VXVM_LIB_NAME, RTLD_NOW)) == NULL) {
263*8276SJiri.Cervenka@Sun.COM return (NULL);
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate if ((vxdl_libvxvm_get_version = (int (*)(int))dlsym(lh,
2670Sstevel@tonic-gate "libvxvm_get_version")) == NULL) {
268*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
269*8276SJiri.Cervenka@Sun.COM return (NULL);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate if ((vxdl_libvxvm_get_conf = (int (*)(int))dlsym(lh,
2730Sstevel@tonic-gate "libvxvm_get_conf")) == NULL) {
274*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
275*8276SJiri.Cervenka@Sun.COM return (NULL);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate if ((vxdl_libvxvm_get_dgs = (int (*)(int, vm_name_t []))dlsym(lh,
2790Sstevel@tonic-gate "libvxvm_get_dgs")) == NULL) {
280*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
281*8276SJiri.Cervenka@Sun.COM return (NULL);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate if ((vxdl_libvxvm_get_disks = (int (*)(vm_name_t, int, vm_path_t []))
2850Sstevel@tonic-gate dlsym(lh, "libvxvm_get_disks")) == NULL) {
286*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
287*8276SJiri.Cervenka@Sun.COM return (NULL);
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate return (lh);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate static int
load_vxvm()2940Sstevel@tonic-gate load_vxvm()
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate void *lh;
2970Sstevel@tonic-gate int vers;
2980Sstevel@tonic-gate int nsize;
2990Sstevel@tonic-gate int psize;
3000Sstevel@tonic-gate int n_disk_groups;
3010Sstevel@tonic-gate vm_name_t *namep;
3020Sstevel@tonic-gate char *pnp;
3030Sstevel@tonic-gate vm_path_t *pathp;
3040Sstevel@tonic-gate int i;
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate if ((lh = init_vxvm()) == NULL) {
307*8276SJiri.Cervenka@Sun.COM /* No library. */
308*8276SJiri.Cervenka@Sun.COM return (0);
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate vers = (vxdl_libvxvm_get_version)(1 << 8);
3120Sstevel@tonic-gate if (vers == -1) {
313*8276SJiri.Cervenka@Sun.COM /* unsupported version */
314*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
315*8276SJiri.Cervenka@Sun.COM return (0);
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate nsize = (vxdl_libvxvm_get_conf)(VXVM_NAME_SIZE);
3190Sstevel@tonic-gate psize = (vxdl_libvxvm_get_conf)(VXVM_PATH_SIZE);
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate if (nsize == -1 || psize == -1) {
322*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
323*8276SJiri.Cervenka@Sun.COM return (0);
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate namep = (vm_name_t *)calloc(MAX_DISK_GROUPS, nsize);
3270Sstevel@tonic-gate if (namep == NULL) {
328*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
329*8276SJiri.Cervenka@Sun.COM return (ENOMEM);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate pathp = (vm_path_t *)calloc(MAX_DISKS_DG, psize);
3330Sstevel@tonic-gate if (pathp == NULL) {
334*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
335*8276SJiri.Cervenka@Sun.COM free(namep);
336*8276SJiri.Cervenka@Sun.COM return (ENOMEM);
3370Sstevel@tonic-gate }
3380Sstevel@tonic-gate
3390Sstevel@tonic-gate n_disk_groups = (vxdl_libvxvm_get_dgs)(MAX_DISK_GROUPS, namep);
3400Sstevel@tonic-gate if (n_disk_groups < 0) {
341*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
342*8276SJiri.Cervenka@Sun.COM free(namep);
343*8276SJiri.Cervenka@Sun.COM free(pathp);
344*8276SJiri.Cervenka@Sun.COM return (0);
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate pnp = (char *)namep;
3480Sstevel@tonic-gate for (i = 0; i < n_disk_groups; i++) {
349*8276SJiri.Cervenka@Sun.COM int n_disks;
3500Sstevel@tonic-gate
351*8276SJiri.Cervenka@Sun.COM n_disks = (vxdl_libvxvm_get_disks)(pnp, MAX_DISKS_DG, pathp);
3520Sstevel@tonic-gate
353*8276SJiri.Cervenka@Sun.COM if (n_disks >= 0) {
354*8276SJiri.Cervenka@Sun.COM int j;
355*8276SJiri.Cervenka@Sun.COM char *ppp;
3560Sstevel@tonic-gate
357*8276SJiri.Cervenka@Sun.COM ppp = (char *)pathp;
358*8276SJiri.Cervenka@Sun.COM for (j = 0; j < n_disks; j++) {
3590Sstevel@tonic-gate
360*8276SJiri.Cervenka@Sun.COM if (strncmp(ppp, "/dev/vx/", 8) == 0) {
361*8276SJiri.Cervenka@Sun.COM char *pslash;
362*8276SJiri.Cervenka@Sun.COM char nm[MAXPATHLEN];
3630Sstevel@tonic-gate
364*8276SJiri.Cervenka@Sun.COM pslash = strrchr(ppp, '/');
365*8276SJiri.Cervenka@Sun.COM pslash++;
3660Sstevel@tonic-gate
367*8276SJiri.Cervenka@Sun.COM (void) snprintf(nm, sizeof (nm),
368*8276SJiri.Cervenka@Sun.COM "/dev/dsk/%s", pslash);
369*8276SJiri.Cervenka@Sun.COM if (add_use_record(nm)) {
370*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
371*8276SJiri.Cervenka@Sun.COM free(pathp);
372*8276SJiri.Cervenka@Sun.COM free(namep);
373*8276SJiri.Cervenka@Sun.COM return (ENOMEM);
374*8276SJiri.Cervenka@Sun.COM }
375*8276SJiri.Cervenka@Sun.COM } else {
376*8276SJiri.Cervenka@Sun.COM if (add_use_record(ppp)) {
377*8276SJiri.Cervenka@Sun.COM (void) dlclose(lh);
378*8276SJiri.Cervenka@Sun.COM free(pathp);
379*8276SJiri.Cervenka@Sun.COM free(namep);
380*8276SJiri.Cervenka@Sun.COM return (ENOMEM);
381*8276SJiri.Cervenka@Sun.COM }
382*8276SJiri.Cervenka@Sun.COM }
383*8276SJiri.Cervenka@Sun.COM
384*8276SJiri.Cervenka@Sun.COM ppp += psize;
3850Sstevel@tonic-gate }
386*8276SJiri.Cervenka@Sun.COM }
3870Sstevel@tonic-gate
388*8276SJiri.Cervenka@Sun.COM pnp += nsize;
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate (void) dlclose(lh);
3920Sstevel@tonic-gate free(pathp);
3930Sstevel@tonic-gate free(namep);
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate return (0);
3960Sstevel@tonic-gate }
397