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