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