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 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 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 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 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 * 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 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