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