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 2005 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 * namespace utilities 31 */ 32 33 #include <meta.h> 34 35 typedef struct deviceinfo { 36 char *bname; /* block name of the device */ 37 char *dname; /* driver for the device */ 38 minor_t mnum; /* minor number for the device */ 39 } deviceinfo_t; 40 41 static deviceinfo_t devlist[MD_MNMAXSIDES]; 42 43 /* 44 * Ask the driver for the device name, driver name, and minor number; 45 * which has been stored in the metadevice state database 46 * (on behalf of the utilities). 47 * (by key) 48 */ 49 char * 50 meta_getnmentbykey( 51 set_t setno, 52 side_t sideno, 53 mdkey_t key, 54 char **drvnm, 55 minor_t *mnum, 56 md_dev64_t *dev, 57 md_error_t *ep 58 ) 59 { 60 struct mdnm_params nm; 61 static char device_name[MAXPATHLEN]; 62 63 (void) memset(&nm, '\0', sizeof (nm)); 64 nm.setno = setno; 65 nm.side = sideno; 66 nm.key = key; 67 nm.devname = (uint64_t)device_name; 68 69 if (metaioctl(MD_IOCGET_NM, &nm, &nm.mde, NULL) != 0) { 70 (void) mdstealerror(ep, &nm.mde); 71 return (NULL); 72 } 73 74 if (drvnm != NULL) 75 *drvnm = Strdup(nm.drvnm); 76 77 if (mnum != NULL) 78 *mnum = nm.mnum; 79 80 if (dev != NULL) 81 *dev = meta_expldev(makedevice(nm.major, nm.mnum)); 82 83 return (Strdup(device_name)); 84 } 85 86 /* 87 * Ask the driver for the minor name which has been stored in the 88 * metadevice state database. 89 * (by key) 90 */ 91 char * 92 meta_getdidminorbykey( 93 set_t setno, 94 side_t sideno, 95 mdkey_t key, 96 md_error_t *ep 97 ) 98 { 99 struct mdnm_params nm; 100 static char minorname[MAXPATHLEN]; 101 102 (void) memset(&nm, '\0', sizeof (nm)); 103 nm.setno = setno; 104 nm.side = sideno; 105 nm.key = key; 106 nm.minorname = (uint64_t)minorname; 107 108 if (metaioctl(MD_IOCGET_DIDMIN, &nm, &nm.mde, NULL) != 0) { 109 (void) mdstealerror(ep, &nm.mde); 110 return (NULL); 111 } 112 113 return (Strdup(minorname)); 114 } 115 116 /* 117 * Ask the driver for the device id string which has been stored in the 118 * metadevice state database (on behalf of the utilities). 119 * (by key) 120 */ 121 ddi_devid_t 122 meta_getdidbykey( 123 set_t setno, 124 side_t sideno, 125 mdkey_t key, 126 md_error_t *ep 127 ) 128 { 129 struct mdnm_params nm; 130 131 (void) memset(&nm, '\0', sizeof (nm)); 132 nm.setno = setno; 133 nm.side = sideno; 134 nm.key = key; 135 136 /* 137 * First ask the driver for the size of the device id string. This is 138 * signaled by passing the driver a devid_size of zero. 139 */ 140 nm.devid_size = 0; 141 if (metaioctl(MD_IOCGET_DID, &nm, &nm.mde, NULL) != 0) { 142 (void) mdstealerror(ep, &nm.mde); 143 return (NULL); 144 } 145 146 /* 147 * If the devid_size is still zero then something is wrong. 148 */ 149 if (nm.devid_size == 0) { 150 (void) mdstealerror(ep, &nm.mde); 151 return (NULL); 152 } 153 154 /* 155 * Now go get the actual device id string. Caller is responsible for 156 * free'ing device id memory buffer. 157 */ 158 if ((nm.devid = (uintptr_t)malloc(nm.devid_size)) == NULL) { 159 return (NULL); 160 } 161 if (metaioctl(MD_IOCGET_DID, &nm, &nm.mde, NULL) != 0) { 162 (void) mdstealerror(ep, &nm.mde); 163 (void) free((void *)(uintptr_t)nm.devid); 164 return (NULL); 165 } 166 167 return ((void *)(uintptr_t)nm.devid); 168 } 169 170 /* 171 * set the devid. 172 */ 173 int 174 meta_setdid( 175 set_t setno, 176 side_t sideno, 177 mdkey_t key, 178 md_error_t *ep 179 ) 180 { 181 struct mdnm_params nm; 182 int i; 183 184 (void) memset(&nm, '\0', sizeof (nm)); 185 nm.setno = setno; 186 nm.side = sideno; 187 nm.key = key; 188 189 if (metaioctl(MD_IOCSET_DID, &nm, &nm.mde, NULL) != 0) { 190 (void) mdstealerror(ep, &nm.mde); 191 return (-1); 192 } 193 194 if (setno == MD_LOCAL_SET) { 195 /* 196 * If this is the local set then we are adding in the devids 197 * for the disks in the diskset and so this means adding 198 * a reference count for each side. Need to do this after 199 * the initial add so that the correct devid is picked up. 200 * The key is the key of the drive record and as such this 201 * means the minor number of the device which is used to 202 * get the devid. If the wrong side is used then it would 203 * be possible to get the wrong devid in the namespace, hence 204 * the requirement to process the local side first of all. 205 */ 206 for (i = 0 + SKEW; i < MD_MAXSIDES; i++) { 207 /* 208 * We can just call the ioctl again because it will 209 * fail with ENOENT if the side does not exist, and 210 * more importantly does not increment the usage count 211 * on the devid. 212 */ 213 nm.side = (side_t)i; 214 if (nm.side == sideno) 215 continue; 216 if (metaioctl(MD_IOCSET_DID, &nm, &nm.mde, NULL) != 0) { 217 if (mdissyserror(&nm.mde, ENODEV)) { 218 mdclrerror(&nm.mde); 219 } else { 220 (void) mdstealerror(ep, &nm.mde); 221 return (-1); 222 } 223 } 224 } 225 } 226 return (0); 227 } 228 /* 229 * Ask the driver for the name, which has been stored in the 230 * metadevice state database (on behalf of the utilities). 231 * (by key) 232 */ 233 char * 234 meta_getnmbykey( 235 set_t setno, 236 side_t sideno, 237 mdkey_t key, 238 md_error_t *ep 239 ) 240 { 241 return (meta_getnmentbykey(setno, sideno, key, NULL, NULL, NULL, ep)); 242 } 243 244 /* 245 * Ask the driver for the device name, driver name, minor number, and key; 246 * which has been stored in the metadevice state database 247 * (on behalf of the utilities). 248 * (by md_dev64_t) 249 */ 250 char * 251 meta_getnmentbydev( 252 set_t setno, 253 side_t sideno, 254 md_dev64_t dev, 255 char **drvnm, 256 minor_t *mnum, 257 mdkey_t *key, 258 md_error_t *ep 259 ) 260 { 261 struct mdnm_params nm; 262 static char device_name[MAXPATHLEN]; 263 264 /* must have a dev */ 265 assert(dev != NODEV64); 266 267 (void) memset(&nm, '\0', sizeof (nm)); 268 nm.setno = setno; 269 nm.side = sideno; 270 nm.key = MD_KEYWILD; 271 nm.major = meta_getmajor(dev); 272 nm.mnum = meta_getminor(dev); 273 nm.devname = (uint64_t)device_name; 274 275 if (metaioctl(MD_IOCGET_NM, &nm, &nm.mde, NULL) != 0) { 276 (void) mdstealerror(ep, &nm.mde); 277 return (NULL); 278 } 279 280 if (drvnm != NULL) 281 *drvnm = Strdup(nm.drvnm); 282 if (mnum != NULL) 283 *mnum = nm.mnum; 284 285 if (key != NULL) 286 *key = nm.retkey; 287 288 return (Strdup(device_name)); 289 } 290 291 int 292 add_name( 293 mdsetname_t *sp, 294 side_t sideno, 295 mdkey_t key, 296 char *dname, 297 minor_t mnum, 298 char *bname, 299 md_error_t *ep 300 ) 301 { 302 struct mdnm_params nm; 303 304 (void) memset(&nm, '\0', sizeof (nm)); 305 nm.setno = sp->setno; 306 nm.side = sideno; 307 nm.key = key; 308 nm.mnum = mnum; 309 (void) strncpy(nm.drvnm, dname, sizeof (nm.drvnm)); 310 nm.devname_len = strlen(bname) + 1; 311 nm.devname = (uintptr_t)bname; 312 313 if (metaioctl(MD_IOCSET_NM, &nm, &nm.mde, bname) < 0) 314 return (mdstealerror(ep, &nm.mde)); 315 316 return (nm.key); 317 } 318 319 /* 320 * Remove the device name which corresponds to the given device number. 321 */ 322 int 323 del_name( 324 mdsetname_t *sp, 325 side_t sideno, 326 mdkey_t key, 327 md_error_t *ep 328 ) 329 { 330 struct mdnm_params nm; 331 332 (void) memset(&nm, '\0', sizeof (nm)); 333 nm.setno = sp->setno; 334 nm.side = sideno; 335 nm.key = key; 336 337 if (metaioctl(MD_IOCREM_NM, &nm, &nm.mde, NULL) != 0) 338 return (mdstealerror(ep, &nm.mde)); 339 340 return (0); 341 } 342 343 static void 344 empty_devicelist() 345 { 346 side_t sideno; 347 348 for (sideno = 0; sideno < MD_MNMAXSIDES; sideno++) { 349 if (devlist[sideno].bname != (char *)NULL) { 350 Free(devlist[sideno].bname); 351 Free(devlist[sideno].dname); 352 devlist[sideno].mnum = NODEV; 353 } 354 } 355 } 356 357 static void 358 add_to_devicelist( 359 side_t sideno, 360 char *bname, 361 char *dname, 362 minor_t mnum 363 ) 364 { 365 devlist[sideno].bname = Strdup(bname); 366 devlist[sideno].dname = Strdup(dname); 367 368 devlist[sideno].mnum = mnum; 369 } 370 371 /* 372 * Build a list of the names on the systems, if this fails the caller 373 * will tidy up the entries in the devlist. 374 */ 375 static int 376 build_sidenamelist( 377 mdsetname_t *sp, 378 mdname_t *np, 379 md_error_t *ep 380 ) 381 { 382 side_t sideno = MD_SIDEWILD; 383 minor_t mnum = NODEV; 384 char *bname = NULL; 385 char *dname = NULL; 386 int err; 387 388 /*CONSTCOND*/ 389 while (1) { 390 391 if ((err = meta_getnextside_devinfo(sp, np->bname, &sideno, 392 &bname, &dname, &mnum, ep)) == -1) 393 return (-1); 394 395 if (err == 0) 396 break; 397 398 /* the sideno gives us the index into the array */ 399 add_to_devicelist(sideno, bname, dname, mnum); 400 } 401 return (0); 402 } 403 404 /* 405 * add name key 406 * the meta_create* functions should be the only ones using this. The 407 * adding of a name to the namespace must be done in a particular order 408 * to devid support for the disksets. The order is: add the 'local' side 409 * first of all, so the devid lookup in the kernel will use the correct 410 * device information and then add in the other sides. 411 */ 412 int 413 add_key_name( 414 mdsetname_t *sp, 415 mdname_t *np, 416 mdnamelist_t **nlpp, 417 md_error_t *ep 418 ) 419 { 420 int err; 421 side_t sideno = MD_SIDEWILD; 422 side_t thisside; 423 mdkey_t key = MD_KEYWILD; 424 md_set_desc *sd; 425 int maxsides; 426 427 /* should have a set */ 428 assert(sp != NULL); 429 430 if (! metaislocalset(sp)) { 431 if ((sd = metaget_setdesc(sp, ep)) == NULL) { 432 return (-1); 433 } 434 } 435 436 if (build_sidenamelist(sp, np, ep) == -1) { 437 empty_devicelist(); 438 return (-1); 439 } 440 441 /* 442 * When a disk is added into the namespace the local information for 443 * that disk is added in first of all. For the local set this is not 444 * a concern and for the host that owns the diskset it is not a concern 445 * but when a disk is added in the remote namespace we *must* use the 446 * local information for that disk first of all. This is because when 447 * in the kernel (md_setdevname) the passed in dev_t is used to find 448 * the devid of the disk. This means we have to cater for the following: 449 * 450 * - a disk on the remote host having the dev_t that has been passed 451 * into the kernel and this disk is not actually the disk that is 452 * being added into the diskset. 453 * - the dev_t does not exist on this node 454 * 455 * So putting in the local information first of all makes sure that the 456 * dev_t passed into the kernel is correct with respect to that node 457 * and then any further additions for that name match on the key 458 * passed back. 459 */ 460 thisside = getmyside(sp, ep); 461 462 if (devlist[thisside].dname == NULL || 463 strlen(devlist[thisside].dname) == 0) { 464 /* 465 * Did not find the disk information for the disk. This can 466 * be because of an inconsistancy in the namespace: that is the 467 * devid we have in the namespace does not exist on the 468 * system and thus when looking up the disk information 469 * using this devid we fail to find anything. 470 */ 471 (void) mdcomperror(ep, MDE_SP_COMP_OPEN_ERR, 0, np->dev, 472 np->cname); 473 empty_devicelist(); 474 return (-1); 475 } 476 477 if ((err = add_name(sp, thisside, key, devlist[thisside].dname, 478 devlist[thisside].mnum, devlist[thisside].bname, ep)) == -1) { 479 empty_devicelist(); 480 return (-1); 481 } 482 483 /* We now have a 'key' so add in the other sides */ 484 key = (mdkey_t)err; 485 486 if (metaislocalset(sp)) 487 goto done; 488 489 if (MD_MNSET_DESC(sd)) 490 maxsides = MD_MNMAXSIDES; 491 else 492 maxsides = MD_MAXSIDES; 493 494 for (sideno = 0; sideno < maxsides; sideno++) { 495 /* ignore thisside, as it has been added above */ 496 if (sideno == thisside) 497 continue; 498 499 if (devlist[sideno].dname != NULL) { 500 err = add_name(sp, sideno, key, devlist[sideno].dname, 501 devlist[sideno].mnum, devlist[sideno].bname, ep); 502 if (err == -1) { 503 empty_devicelist(); 504 return (-1); 505 } 506 } 507 } 508 509 done: 510 empty_devicelist(); 511 /* save key, return success */ 512 np->key = key; 513 if (nlpp != NULL) 514 (void) metanamelist_append(nlpp, np); 515 return (0); 516 } 517 518 /* 519 * delete name key 520 * the meta_create* functions should be the only ones using this. The 521 * removal of the names must be done in a particular order: remove the 522 * non-local entries first of all and then finally the local entry. 523 */ 524 int 525 del_key_name( 526 mdsetname_t *sp, 527 mdname_t *np, 528 md_error_t *ep 529 ) 530 { 531 side_t sideno = MD_SIDEWILD; 532 int err; 533 int retval = 0; 534 side_t thisside; 535 536 /* should have a set */ 537 assert(sp != NULL); 538 539 /* should have a key */ 540 assert((np->key != MD_KEYWILD) && (np->key != MD_KEYBAD)); 541 542 thisside = getmyside(sp, ep); 543 544 /* remove the remote sides first of all */ 545 for (;;) { 546 if ((err = meta_getnextside_devinfo(sp, np->bname, &sideno, 547 NULL, NULL, NULL, ep)) == -1) 548 return (-1); 549 550 if (err == 0) 551 break; 552 553 /* ignore thisside */ 554 if (thisside == sideno) { 555 continue; 556 } 557 if ((err = del_name(sp, sideno, np->key, ep)) == -1) 558 retval = -1; 559 } 560 561 /* now remove this side */ 562 if (retval == 0) 563 if ((err = del_name(sp, thisside, np->key, ep)) == -1) 564 retval = -1; 565 566 np->key = MD_KEYBAD; 567 return (retval); 568 } 569 570 /* 571 * delete namelist keys 572 * the meta_create* functions should be the only ones using this 573 */ 574 int 575 del_key_names( 576 mdsetname_t *sp, 577 mdnamelist_t *nlp, 578 md_error_t *ep 579 ) 580 { 581 mdnamelist_t *p; 582 md_error_t status = mdnullerror; 583 int rval = 0; 584 585 /* if ignoring errors */ 586 if (ep == NULL) 587 ep = &status; 588 589 /* delete names */ 590 for (p = nlp; (p != NULL); p = p->next) { 591 mdname_t *np = p->namep; 592 593 if (del_key_name(sp, np, ep) != 0) 594 rval = -1; 595 } 596 597 /* cleanup, return success */ 598 if (ep == &status) 599 mdclrerror(&status); 600 return (rval); 601 } 602