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 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <ctype.h>
28 #include <sys/fcntl.h>
29 #include <sys/types.h>
30 #include <devid.h>
31 #include <ftw.h>
32 #include <string.h>
33 #include <mdiox.h>
34 #include <sys/lvm/mdio.h>
35 #include <meta.h>
36 #include <syslog.h>
37 #include <sdssc.h>
38 #include <libdevinfo.h>
39 #include "meta_set_prv.h"
40
41 /*
42 * Just in case we're not in a build environment, make sure that
43 * TEXT_DOMAIN gets set to something.
44 */
45 #if !defined(TEXT_DOMAIN)
46 #define TEXT_DOMAIN "SYS_TEST"
47 #endif
48
49 #define RAW_PATH 0x001 /* rdsk */
50 #define BLOCK_PATH 0x002 /* dsk */
51 #define DSK_TYPE 0x004 /* normal /dev/[r]dsk */
52 #define TEST_TYPE 0x008 /* test driver path */
53 #define DID_TYPE 0x010 /* cluster did path */
54 #define AP_TYPE 0x020 /* should be obsolete */
55
56 typedef struct path_list {
57 char *search_path;
58 char *search_type;
59 int path_type;
60 } path_list_t;
61
62 /*
63 * A table of the supported path types - this should ideally be generated
64 * by reading the /etc/lvm/devpath file
65 */
66 static path_list_t plist[] = {
67 {"/dev/rdsk", DEVID_MINOR_NAME_ALL_CHR, RAW_PATH|DSK_TYPE},
68 {"/dev/dsk", DEVID_MINOR_NAME_ALL_BLK, BLOCK_PATH|DSK_TYPE},
69 {"/dev/did/rdsk", DEVID_MINOR_NAME_ALL_CHR, RAW_PATH|DID_TYPE},
70 {"/dev/did/dsk", DEVID_MINOR_NAME_ALL_BLK, BLOCK_PATH|DID_TYPE},
71 {"/dev/td/dsk", DEVID_MINOR_NAME_ALL_BLK, BLOCK_PATH|TEST_TYPE},
72 {"/dev/td/rdsk", DEVID_MINOR_NAME_ALL_CHR, RAW_PATH|TEST_TYPE},
73 };
74 static int num = sizeof (plist)/sizeof (path_list_t);
75
76 static mddevopts_t dev_options = 0;
77
78 /* indicate whether to print an error message or not */
79 static int firsttime = 1;
80
81 #define DEV_MATCH 0x1
82 #define NAME_MATCH 0x2
83
84 #define DEBUGON 1
85 #define DEBUGOFF 2
86
87 /*
88 * Debug function: to turn on devadm function debugging include DEVADM
89 * in the MD_DEBUG enviroment variable: MD_DEBUG=...,DEVADM...
90 */
91 /*PRINTFLIKE1*/
92 static void
mda_debug(char * format,...)93 mda_debug(char *format, ...)
94 {
95 char *p;
96 static int debug_set = 0;
97 va_list ap;
98
99 if (debug_set == 0) {
100 if (((p = getenv("MD_DEBUG")) != NULL) &&
101 (strstr(p, "DEVADM") != NULL))
102 debug_set = DEBUGON;
103 else
104 debug_set = DEBUGOFF;
105 }
106 if (debug_set == DEBUGON) {
107 va_start(ap, format);
108 (void) vfprintf(stderr, format, ap);
109 va_end(ap);
110 }
111 }
112
113 /* print error messages to the terminal or syslog */
114 /*PRINTFLIKE1*/
115 static void
mda_print(char * message,...)116 mda_print(char *message, ...)
117 {
118 va_list ap;
119
120 va_start(ap, message);
121 if (dev_options & DEV_LOG) {
122 /*
123 * The program is a daemon in the sense that it
124 * is a system utility.
125 */
126 (void) vsyslog((LOG_ERR | LOG_DAEMON), message, ap);
127 } else {
128 (void) vfprintf(stderr, message, ap);
129 }
130 va_end(ap);
131 }
132
133 /*
134 * Utility to find the correct options to use for the devid search
135 * based upon the path of the device.
136 *
137 * RETURN:
138 * -1 Error, the path passed in is not in the table
139 * >= 0 The element number for the options within the table
140 */
141 static int
mda_findpath(char * path)142 mda_findpath(char *path)
143 {
144 int i = 0;
145
146 for (i = 0; i < num; i++) {
147 if (strncmp(plist[i].search_path, path,
148 strlen(plist[i].search_path)) == 0)
149 return (i);
150 }
151 return (-1);
152 }
153
154 /*
155 * Utility to get the path of a device
156 */
157 static char *
mda_getpath(char * devname)158 mda_getpath(char *devname)
159 {
160 char *ptr;
161 char *pathname;
162 size_t len;
163
164 if ((ptr = strrchr(devname, '/')) == NULL) {
165 mda_debug("Invalid format: %s\n", devname);
166 return (NULL);
167 }
168 ptr++;
169 len = strlen(devname) - strlen(ptr);
170 pathname = Malloc(len + 1);
171 (void) strncpy(pathname, devname, len);
172 pathname[len] = '\0';
173 return (pathname);
174 }
175
176 /*
177 * meta_update_devtree -- Update the /dev/md namespace for metadevices.
178 *
179 * Only update the specific link if a valid minor(not NODEV) is given.
180 * Otherwise, update the entire /dev/md .
181 */
182
183 int
meta_update_devtree(minor_t mnum)184 meta_update_devtree(minor_t mnum)
185 {
186 char nodename[40];
187 di_devlink_handle_t hdl;
188
189 /*
190 * di_devlink_init() returns once the /dev links have been
191 * updated(created or removed). If di_devlink_init returns
192 * a NULL, the link operation failed.
193 *
194 * Use the enhanced di_devlink_init interface if the mnum
195 * is available.
196 */
197 if (mnum == NODEV) {
198 /*
199 * NOTE: This will take a _long_ time for large numbers
200 * of metadevices.
201 */
202 hdl = di_devlink_init("md", DI_MAKE_LINK);
203 } else {
204 /* Call di_devlink_init twice, for block and raw devices */
205 (void) sprintf(nodename, "/pseudo/md@0:%lu,%lu,raw",
206 MD_MIN2SET(mnum), MD_MIN2UNIT(mnum));
207 hdl = di_devlink_init(nodename, DI_MAKE_LINK);
208
209 if (hdl == NULL)
210 return (-1);
211 else
212 (void) di_devlink_fini(&hdl);
213
214 (void) sprintf(nodename, "/pseudo/md@0:%lu,%lu,blk",
215 MD_MIN2SET(mnum), MD_MIN2UNIT(mnum));
216 hdl = di_devlink_init(nodename, DI_MAKE_LINK);
217 }
218
219 if (hdl != NULL) {
220 (void) di_devlink_fini(&hdl);
221 return (0);
222 }
223
224 return (-1);
225 }
226
227 /*
228 * update_locator_namespace -- Contains the ioctl call that will update
229 * the ctds and pathname (ie. /dev/dsk etc) within the
230 * locator block namespace.
231 *
232 * RETURN
233 * METADEVADM_ERR ioctl failed and ep is updated with the error
234 * METADEVADM_SUCCESS success
235 */
236 static int
update_locator_namespace(set_t setno,side_t sideno,char * devname,md_dev64_t dev,char * pname,md_error_t * ep)237 update_locator_namespace(
238 set_t setno,
239 side_t sideno,
240 char *devname,
241 md_dev64_t dev,
242 char *pname,
243 md_error_t *ep
244 )
245 {
246 mdnm_params_t nm;
247
248 (void) memset(&nm, '\0', sizeof (nm));
249 nm.mde = mdnullerror;
250 nm.setno = setno;
251 nm.side = sideno;
252 nm.devname = (uintptr_t)devname;
253 nm.devname_len = strlen(devname);
254 nm.devt = dev;
255 nm.pathname = (uintptr_t)pname;
256 nm.pathname_len = strlen(pname);
257 if (metaioctl(MD_IOCUPD_LOCNM, &nm, &nm.mde, NULL) != 0) {
258 (void) mdstealerror(ep, &nm.mde);
259 return (METADEVADM_ERR);
260 }
261 return (METADEVADM_SUCCESS);
262 }
263
264 /*
265 * meta_update_namespace -- Contains the ioctl call that will update the
266 * device name and pathname in the namespace area.
267 *
268 * RETURN
269 * METADEVADM_ERR ioctl failed and ep is updated with the error
270 * METADEVADM_SUCCESS success
271 */
272 int
meta_update_namespace(set_t setno,side_t sideno,char * devname,md_dev64_t dev,mdkey_t key,char * pname,md_error_t * ep)273 meta_update_namespace(
274 set_t setno,
275 side_t sideno,
276 char *devname,
277 md_dev64_t dev,
278 mdkey_t key,
279 char *pname,
280 md_error_t *ep
281 )
282 {
283 mdnm_params_t nm;
284
285 (void) memset(&nm, '\0', sizeof (nm));
286 nm.mde = mdnullerror;
287 nm.setno = setno;
288 nm.side = sideno;
289 nm.devname = (uintptr_t)devname;
290 nm.devname_len = strlen(devname);
291 nm.mnum = meta_getminor(dev);
292 nm.major = meta_getmajor(dev);
293 nm.key = key;
294 nm.pathname = (uintptr_t)pname;
295 nm.pathname_len = strlen(pname);
296 if (metaioctl(MD_IOCUPD_NM, &nm, &nm.mde, NULL) != 0) {
297 (void) mdstealerror(ep, &nm.mde);
298 return (METADEVADM_ERR);
299 }
300 return (METADEVADM_SUCCESS);
301 }
302
303 /*
304 * stripS - Strip s<digits> off the end of the ctds name if it exists
305 */
306 static void
stripS(char * name)307 stripS(char *name)
308 {
309 char *p;
310
311 /* gobble number and 's' */
312 p = name + strlen(name) - 1;
313 for (; (p > name); --p) {
314 if (!isdigit(*p))
315 break;
316 }
317
318 if (*p == 's') {
319 *p = '\0';
320 }
321 }
322
323 /*
324 * getdiskname -- to be used when scanning the input from the -u arg.
325 * This routine will strip off input that is anything but cxtxdx.
326 * ie. it will call stripS to get rid of slice info. Will also
327 * strip off /dev/dsk, /dev/rdsk, /dev/ap/dsk, /dev/ap/rdsk,
328 * /dev/did/dsk, or /dev/did/rdsk. The caller will need to free
329 * the return value.
330 *
331 * RETURN
332 * string that has the disk name in it ie. c0t0d0
333 */
334 static char *
getdiskname(char * name)335 getdiskname(
336 char *name
337 )
338 {
339 char *p;
340 char *diskname;
341
342 /* regular device */
343 if ((strncmp(name, "/dev/dsk/", strlen("/dev/dsk/")) == 0) &&
344 (strchr((p = name + strlen("/dev/dsk/")), '/') == NULL)) {
345 diskname = Strdup(p);
346 stripS(diskname);
347 return (diskname);
348 }
349
350 if ((strncmp(name, "/dev/rdsk/", strlen("/dev/rdsk/")) == 0) &&
351 (strchr((p = name + strlen("/dev/rdsk/")), '/') == NULL)) {
352 diskname = Strdup(p);
353 stripS(diskname);
354 return (diskname);
355 }
356
357 if ((strncmp(name, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) &&
358 (strchr((p = name + strlen("/dev/ap/dsk/")), '/') == NULL)) {
359 diskname = Strdup(p);
360 stripS(diskname);
361 return (diskname);
362 }
363
364 if ((strncmp(name, "/dev/ap/rdsk/", strlen("/dev/ap/rdsk/")) == 0) &&
365 (strchr((p = name + strlen("/dev/ap/rdsk/")), '/') == NULL)) {
366 diskname = Strdup(p);
367 stripS(diskname);
368 return (diskname);
369 }
370
371 if ((strncmp(name, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) &&
372 (strchr((p = name + strlen("/dev/did/dsk/")), '/') == NULL)) {
373 diskname = Strdup(p);
374 stripS(diskname);
375 return (diskname);
376 }
377
378 if ((strncmp(name, "/dev/did/rdsk/", strlen("/dev/did/rdsk/")) == 0) &&
379 (strchr((p = name + strlen("/dev/did/rdsk/")), '/') == NULL)) {
380 diskname = Strdup(p);
381 stripS(diskname);
382 return (diskname);
383 }
384
385 diskname = Strdup(name);
386 stripS(diskname);
387 return (diskname);
388 }
389
390 /*
391 * has_devid -- return the device ID for a given key
392 *
393 * RETURN
394 * NULL error
395 * devid devid found that corresponds to the given key.
396 */
397 static ddi_devid_t
has_devid(set_t setno,side_t sideno,mdkey_t key,md_error_t * ep)398 has_devid(set_t setno, side_t sideno, mdkey_t key, md_error_t *ep)
399 {
400 return (meta_getdidbykey(setno, sideno, key, ep));
401 }
402
403 /*
404 * Go through the existing list of replicas and check to see
405 * if their disk has moved, if so update the replica list
406 *
407 * RETURN
408 * -1 error
409 * 0 success
410 */
411 static int
fix_replicanames(mdsetname_t * sp,md_error_t * ep)412 fix_replicanames(
413 mdsetname_t *sp,
414 md_error_t *ep
415 )
416 {
417 md_replicalist_t *rlp = NULL;
418 md_replicalist_t *rl;
419 int ret = -1;
420 int match_type = 0;
421 devid_nmlist_t *disklist = NULL;
422 dev_t small_dev = (dev_t)NODEV;
423 side_t sideno;
424 set_t setno = sp->setno;
425 char *search_path;
426 int search_number;
427 char *ctds_name;
428 char *path_name;
429 int i;
430
431 sideno = getmyside(sp, ep);
432 if (sideno == MD_SIDEWILD) {
433 mda_debug("Failed to find the side number\n");
434 return (-1);
435 }
436
437 if (metareplicalist(sp, MD_BASICNAME_OK | PRINT_FAST, &rlp, ep) < 0) {
438 mda_debug("Unable to get a list of replicas\n");
439 return (METADEVADM_ERR);
440 }
441
442 for (rl = rlp; (rl != NULL); rl = rl->rl_next) {
443 md_replica_t *r = rl->rl_repp;
444
445 small_dev = meta_cmpldev(r->r_namep->dev);
446 search_number = mda_findpath(r->r_namep->bname);
447 if (search_number == -1) {
448 mda_debug("replica update: invalid path: %s",
449 r->r_namep->bname);
450 continue;
451 } else {
452 search_path = plist[search_number].search_path;
453 }
454
455 if (r->r_devid == NULL)
456 continue;
457
458 ret = meta_deviceid_to_nmlist(search_path, r->r_devid,
459 r->r_minor_name, &disklist);
460
461 mda_debug("replica update: search_path %s\n", search_path);
462
463 if (ret != 0) {
464 /*
465 * Failed to find the disk, nothing can be done.
466 * The replica will be marked as bad later.
467 */
468 mda_debug("replica update: failed to find disk %s\n",
469 r->r_namep->cname);
470 continue;
471 }
472 mda_debug("replica update: current %s (%p)\n",
473 r->r_namep->bname, (void *) small_dev);
474
475 /*
476 * Check to see if the returned disk matches the stored one
477 */
478 for (i = 0; disklist[i].dev != NODEV; i++) {
479 match_type = 0;
480
481 mda_debug("replica update: devid list: %s (%p)\n",
482 disklist[i].devname, (void *) disklist[i].dev);
483
484 if (disklist[i].dev == small_dev) {
485 match_type |= DEV_MATCH;
486 }
487
488 if (strncmp(r->r_namep->bname, disklist[i].devname,
489 strlen(r->r_namep->bname)) == 0) {
490 match_type |= NAME_MATCH;
491 }
492
493 /*
494 * break out if some sort of match is found because
495 * we already match on the devid.
496 */
497 if (match_type != 0)
498 break;
499 }
500
501 mda_debug("fix_replicanames: match: %x i: %d\n", match_type, i);
502
503 if (match_type == (DEV_MATCH|NAME_MATCH)) {
504 /* no change */
505 mda_debug("replica update: no change %s\n",
506 disklist[i].devname);
507 devid_free_nmlist(disklist);
508 continue;
509 }
510
511 /* No match found - use the first entry in disklist */
512 if (disklist[i].dev == NODEV)
513 i = 0;
514
515 mda_debug("replica update: reloading %s %p\n",
516 disklist[i].devname,
517 (void *)(uintptr_t)meta_expldev(disklist[i].dev));
518
519 if (firsttime) {
520 mda_print(dgettext(TEXT_DOMAIN,
521 "Disk movement detected\n"));
522 mda_print(dgettext(TEXT_DOMAIN,
523 "Updating device names in Solaris Volume "
524 "Manager\n"));
525 firsttime = 0;
526 }
527
528 if (dev_options & DEV_VERBOSE) {
529 char *devidstr;
530
531 devidstr =
532 devid_str_encode(r->r_devid, r->r_minor_name);
533 if (devidstr == NULL) {
534 mda_print(dgettext(TEXT_DOMAIN,
535 "Failed to encode the devid\n"));
536 continue;
537 }
538 mda_print(dgettext(TEXT_DOMAIN,
539 "%s changed to %s from device relocation "
540 "information %s\n"),
541 (char *)r->r_namep->cname, disklist[i].devname,
542 devidstr);
543 }
544
545 if (!(dev_options & DEV_NOACTION)) {
546 mda_debug("Updating locator name\n");
547 ctds_name = strrchr(disklist[i].devname, '/');
548 ctds_name++;
549 if ((path_name = mda_getpath(disklist[i].devname))
550 == NULL) {
551 continue;
552 }
553 if (update_locator_namespace(setno, sideno,
554 ctds_name, meta_expldev(disklist[i].dev),
555 path_name, ep) != 0) {
556 mda_debug("replica update: ioctl failed\n");
557 if (dev_options & DEV_VERBOSE) {
558 mda_print(dgettext(TEXT_DOMAIN,
559 "Failed to update locator "
560 "namespace on change from %s "
561 "to %s\n"), ctds_name,
562 disklist[i].devname);
563 }
564 }
565 }
566 Free(path_name);
567 devid_free_nmlist(disklist);
568 }
569 metafreereplicalist(rlp);
570 return (0);
571 }
572
573 /*
574 * pathname_reload - main function for the -r option. Will reload the
575 * pathname in both the main namespace and the locator namespace.
576 * Also, checks both areas for invalid device ID's and prints them
577 * out.
578 *
579 * If the set is a multi-node diskset that means there are no devid's
580 * so just return.
581 *
582 * RETURN
583 * METADEVADM_ERR error
584 * METADEVADM_SUCCESS success
585 * METADEVADM_DEVIDINVALID success, but invalid devids detected
586 */
587 int
pathname_reload(mdsetname_t ** spp,set_t setno,md_error_t * ep)588 pathname_reload(
589 mdsetname_t **spp,
590 set_t setno,
591 md_error_t *ep)
592 {
593 char *drvnmp;
594 minor_t mnum = 0;
595 md_dev64_t dev = 0;
596 mdnm_params_t nm;
597 char *ctds_name;
598 ddi_devid_t devidp;
599 md_i_didstat_t ds;
600 side_t sideno;
601 char *search_path = NULL;
602 int search_number;
603 devid_nmlist_t *disklist = NULL;
604 char *minor_name = NULL;
605 char *devidstr = NULL;
606 char *path = NULL;
607 int ret;
608 dev_t small_dev = (dev_t)NODEV;
609 int match_type;
610 char *tmp = NULL;
611 mdsetname_t *sp = *spp;
612 md_set_desc *sd;
613 int i;
614
615 /*
616 * Check for multi-node diskset and return if it is one.
617 */
618 if (!metaislocalset(sp)) {
619 if ((sd = metaget_setdesc(sp, ep)) == NULL)
620 return (METADEVADM_ERR);
621
622 if (MD_MNSET_DESC(sd))
623 return (METADEVADM_SUCCESS);
624 }
625
626 /*
627 * Get the entry of the namespace via the key. To do this
628 * call MD_IOCNXTKEY until no more.
629 * For each entry in the namespace we want to check
630 * for devid and update
631 */
632
633 (void) memset(&nm, '\0', sizeof (nm));
634 nm.key = MD_KEYWILD;
635
636 sideno = getmyside(*spp, ep);
637 if (sideno == MD_SIDEWILD) {
638 /* failed to find this node in the set */
639 mda_debug("Failed to find the side number\n");
640 return (METADEVADM_ERR);
641 }
642
643 /* LINTED */
644 while (1) {
645 nm.mde = mdnullerror;
646 nm.setno = setno;
647 nm.side = sideno;
648 /* look at each key in the namespace */
649 if (metaioctl(MD_IOCNXTKEY_NM, &nm, &nm.mde, NULL) != 0) {
650 (void) mdstealerror(ep, &nm.mde);
651 return (METADEVADM_ERR);
652 }
653
654 if (nm.key == MD_KEYWILD) {
655 /* no more entries */
656 break;
657 }
658
659 /*
660 * get the nm entry using the key. Then check to see if
661 * there's a devid associated with this entry
662 * If not, go onto next key.
663 */
664 if ((nm.devname = (uintptr_t)meta_getnmentbykey(setno, sideno,
665 nm.key, &drvnmp, &mnum, &dev, ep)) == NULL) {
666 mda_debug("pathname_reload: no name for key: %d\n",
667 nm.key);
668 continue;
669 }
670
671 mda_debug("pathname_reload: examining %s\n",
672 (char *)(uintptr_t)nm.devname);
673
674 if ((devidp = has_devid(setno, sideno, nm.key, ep)) == NULL) {
675 /* metadevices do not have devid's in them */
676 mda_debug("pathname_reload: no devid for %s\n",
677 (char *)(uintptr_t)nm.devname);
678 /* Clear error if no devid and go to next nm entry */
679 mdclrerror(ep);
680 continue;
681 }
682
683 if ((minor_name = meta_getdidminorbykey(setno, sideno,
684 nm.key, ep)) == NULL) {
685 /*
686 * In theory this is impossible because if the
687 * devidp is non-null then the minor_name has
688 * already been looked up.
689 */
690 mda_debug("No minor name for %s\n",
691 (char *)(uintptr_t)nm.devname);
692 free(devidp);
693 continue;
694 }
695 /*
696 * If there is a devid then we have a real device that
697 * could have moved.
698 */
699 devidstr = devid_str_encode(devidp, minor_name);
700 if (devidstr == NULL) {
701 mda_debug("Failed to encode the devid\n");
702 free(devidp);
703 continue;
704 }
705 mda_debug("devid: %s\n", devidstr);
706
707 /*
708 * Find the search path that should be used. This is an
709 * optimization to try and prevent a search for the complete
710 * /dev namespace.
711 */
712 search_number = mda_findpath((char *)(uintptr_t)nm.devname);
713 if (search_number == -1) {
714 search_path = "/dev";
715 } else {
716 search_path = plist[search_number].search_path;
717 }
718
719 /* now look for the disk name using the devid */
720 ret = meta_deviceid_to_nmlist(search_path, devidp,
721 minor_name, &disklist);
722 free(devidp);
723
724 if (ret != 0) {
725 /*
726 * Failed to find the disk
727 */
728 devid_str_free(devidstr);
729 continue;
730 }
731
732 small_dev = meta_cmpldev(dev);
733 mda_debug("Old device lookup: %s (%p)\n",
734 (char *)(uintptr_t)nm.devname, (void *)small_dev);
735
736 /*
737 * Check to see if the returned disk matches the stored one
738 */
739 for (i = 0; disklist[i].dev != NODEV; i++) {
740 match_type = 0;
741 mda_debug("From devid lookup: %s (%p)\n",
742 (char *)disklist[i].devname,
743 (void *)disklist[i].dev);
744
745 if (disklist[i].dev == small_dev) {
746 match_type |= DEV_MATCH;
747 }
748
749 if (strncmp((char *)(uintptr_t)nm.devname,
750 disklist[i].devname,
751 strlen((char *)(uintptr_t)nm.devname)) == 0) {
752 mda_debug("Name match: %s and %s (%d)\n",
753 disklist[i].devname,
754 (char *)(uintptr_t)nm.devname,
755 strlen((char *)(uintptr_t)nm.devname));
756 match_type |= NAME_MATCH;
757 }
758
759 if (match_type == (DEV_MATCH|NAME_MATCH))
760 break;
761 }
762
763 if (match_type == (DEV_MATCH|NAME_MATCH)) {
764 /* no change */
765 devid_str_free(devidstr);
766 mda_debug("All matched %s\n", disklist[i].devname);
767 devid_free_nmlist(disklist);
768 continue;
769 }
770
771 /* No match found - use the first entry in disklist */
772 i = 0;
773
774 if (firsttime) {
775 mda_print(dgettext(TEXT_DOMAIN,
776 "Disk movement detected\n"));
777 mda_print(dgettext(TEXT_DOMAIN,
778 "Updating device names in "
779 "Solaris Volume Manager\n"));
780 firsttime = 0;
781 }
782 if (dev_options & DEV_VERBOSE) {
783 mda_print(dgettext(TEXT_DOMAIN,
784 "%s changed to %s from device relocation "
785 "information %s\n"),
786 (char *)(uintptr_t)nm.devname, disklist[i].devname,
787 devidstr);
788 }
789 devid_str_free(devidstr);
790
791 /* need to build up the path of the disk */
792 if ((path = Strdup(disklist[i].devname)) == NULL) {
793 mda_debug("Failed to duplicate path: %s\n",
794 disklist[i].devname);
795 devid_free_nmlist(disklist);
796 continue;
797 }
798 if ((tmp = strrchr(path, '/')) == NULL) {
799 mda_debug("Failed to parse %s\n", path);
800 devid_free_nmlist(disklist);
801 Free(path);
802 continue;
803 }
804 tmp += sizeof (char);
805 *tmp = '\0';
806
807 if ((ctds_name = strrchr(disklist[i].devname, '/')) == NULL) {
808 mda_debug("Failed to parse ctds name: %s\n",
809 disklist[i].devname);
810 devid_free_nmlist(disklist);
811 Free(path);
812 continue;
813 }
814 ctds_name += sizeof (char);
815
816 mda_debug("Reloading disk %s %s %p\n",
817 ctds_name, path,
818 (void *)(uintptr_t)meta_expldev(disklist[i].dev));
819
820 if (!(dev_options & DEV_NOACTION)) {
821 /* Something has changed so update the namespace */
822 if (meta_update_namespace(setno, sideno, ctds_name,
823 meta_expldev(disklist[i].dev), nm.key, path,
824 ep) != 0) {
825 mda_debug("Failed to update namespace\n");
826 if (dev_options & DEV_VERBOSE) {
827 mda_print(dgettext(TEXT_DOMAIN,
828 "Failed to update namespace on "
829 "change from %s to %s\n"),
830 ctds_name, disklist[i].devname);
831 }
832 }
833 }
834 devid_free_nmlist(disklist);
835 Free(path);
836 }
837
838 if (fix_replicanames(*spp, ep) == -1)
839 mda_debug("Failed to update replicas\n");
840
841 /*
842 * check for invalid device id's
843 */
844 (void) memset(&ds, '\0', sizeof (ds));
845 ds.setno = setno;
846 ds.side = sideno;
847 ds.mode = MD_FIND_INVDID;
848 /* get count of number of invalid device id's */
849 if (metaioctl(MD_IOCDID_STAT, &ds, &ds.mde, NULL) != 0) {
850 (void) mdstealerror(ep, &ds.mde);
851 return (METADEVADM_ERR);
852 }
853 if (ds.cnt != 0) {
854 char *ctdptr, *ctdp;
855 /*
856 * we have some invalid device id's so we need to
857 * print them out
858 */
859 ds.mode = MD_GET_INVDID;
860 /* malloc buffer for kernel to place devid list into */
861 if ((ctdptr = (char *)Malloc((ds.cnt * ds.maxsz) + 1)) == 0) {
862 return (METADEVADM_ERR);
863 }
864 ds.ctdp = (uintptr_t)ctdptr;
865 /* get actual list of invalid device id's */
866 if (metaioctl(MD_IOCDID_STAT, &ds, &ds.mde, NULL) != 0) {
867 Free(ctdptr);
868 (void) mdstealerror(ep, &ds.mde);
869 return (METADEVADM_ERR);
870 }
871
872 /* print out the invalid devid's */
873 mda_print(dgettext(TEXT_DOMAIN,
874 "Invalid device relocation information "
875 "detected in Solaris Volume Manager\n"));
876 mda_print(dgettext(TEXT_DOMAIN,
877 "Please check the status of the following disk(s):\n"));
878 ctdp = (char *)(uintptr_t)ds.ctdp;
879 while (*ctdp != NULL) {
880 mda_print("\t%s\n", ctdp);
881 ctdp += ds.maxsz;
882 }
883 Free(ctdptr);
884 return (METADEVADM_DEVIDINVALID);
885 }
886 return (METADEVADM_SUCCESS);
887 }
888
889 /*
890 * replica_update_devid - cycle through the replica list, rlp, and
891 * update the device ids on all of the replicas that are on the
892 * device specified by lp. A side effect is to update the value of
893 * cdevidpp to contain the character representation of the device
894 * id before updating if it is not already set.
895 *
896 * RETURN
897 * METADEVADM_ERR error
898 * METADEVADM_SUCCESS success
899 */
900 static int
replica_update_devid(md_replicalist_t * rlp,mddrivename_t * dnp,set_t setno,char ** cdevidpp,md_error_t * ep)901 replica_update_devid(
902 md_replicalist_t *rlp,
903 mddrivename_t *dnp,
904 set_t setno,
905 char **cdevidpp,
906 md_error_t *ep
907 )
908 {
909 mddb_config_t db_c;
910 md_replicalist_t *rl;
911 ddi_devid_t devidp;
912 int ret;
913
914 if (cdevidpp == NULL)
915 return (METADEVADM_ERR);
916
917 ret = devid_str_decode(dnp->devid, &devidp, NULL);
918 if (ret != 0) {
919 /* failed to encode the devid */
920 mda_debug("Failed to decode %s into a valid devid\n",
921 dnp->devid);
922 return (METADEVADM_ERR);
923 }
924
925 /* search replica list for give ctd name */
926 for (rl = rlp; (rl != NULL); rl = rl->rl_next) {
927 md_replica_t *r = rl->rl_repp;
928 mdname_t *rnp = r->r_namep;
929
930 if (strncmp(rnp->cname, dnp->cname, strlen(dnp->cname)) == 0) {
931
932 /* found the replica, now grab the devid */
933 if (*cdevidpp == NULL) {
934 *cdevidpp = devid_str_encode(r->r_devid, NULL);
935 }
936
937 if (*cdevidpp == NULL) {
938 devid_free(devidp);
939 return (METADEVADM_ERR);
940 }
941
942 mda_debug("Updating replica %s, set %d, old devid %s\n",
943 rnp->cname, setno, *cdevidpp);
944
945 if (dev_options & DEV_VERBOSE) {
946 mda_print(dgettext(TEXT_DOMAIN,
947 "Updating replica %s of set number %d from "
948 "device id %s to device id %s\n"),
949 rnp->cname, setno, *cdevidpp, dnp->devid);
950 }
951
952 (void) memset(&db_c, '\0', sizeof (db_c));
953
954 db_c.c_setno = setno;
955 db_c.c_devt = rnp->dev;
956
957 if (!(dev_options & DEV_NOACTION)) {
958
959 mda_debug("Updating replica\n");
960
961 /*
962 * call into kernel to update lb
963 * namespace device id
964 * of given devt
965 */
966 if (metaioctl(MD_DB_SETDID, &db_c,
967 &db_c.c_mde, NULL) != 0) {
968 devid_free(devidp);
969 (void) mdstealerror(ep, &db_c.c_mde);
970 return (METADEVADM_ERR);
971 }
972 }
973
974 }
975 }
976 devid_free(devidp);
977 return (METADEVADM_SUCCESS);
978 }
979
980 /*
981 * devid_update -- main routine for the -u option. Will update both the
982 * namespace and the locator block with the correct devid for the
983 * disk specified.
984 *
985 * RETURN
986 * METADEVADM_ERR error
987 * METADEVADM_SUCCESS success
988 */
989 static int
devid_update(mdsetname_t ** spp,set_t setno,char * ctd,md_error_t * ep)990 devid_update(
991 mdsetname_t **spp,
992 set_t setno,
993 char *ctd,
994 md_error_t *ep
995 )
996 {
997 md_drive_desc *dd, *ddp;
998 mddrivename_t *dnp;
999 mdnm_params_t nm;
1000 ddi_devid_t devidp;
1001 side_t side;
1002 char *old_cdevidp = NULL;
1003 md_replicalist_t *rlp = NULL;
1004 int rval = METADEVADM_ERR;
1005 mdname_t *np = NULL;
1006 uint_t rep_slice;
1007 char *pathname = NULL;
1008 char *diskname = NULL;
1009 int fd = -1;
1010 int len;
1011 char *fp;
1012
1013 side = getmyside(*spp, ep);
1014 if (side == MD_SIDEWILD) {
1015 /* failed to find this node in the set */
1016 mda_debug("Failed to find the side number\n");
1017 return (METADEVADM_ERR);
1018 }
1019
1020 if ((dnp = metadrivename(spp, ctd, ep)) == NULL) {
1021 mda_debug("Failed to create a dnp for %s\n", ctd);
1022 return (METADEVADM_ERR);
1023 }
1024 if (dnp->devid == NULL) {
1025 /*
1026 * Disk does not have a devid! So cannot update the
1027 * devid within the replica.
1028 */
1029 mda_debug("%s does not have a devid\n", dnp->cname);
1030 if (dev_options & DEV_VERBOSE) {
1031 mda_print(dgettext(TEXT_DOMAIN,
1032 "%s does not have a device id. Cannot update "
1033 "device id if none exists\n"), ctd);
1034 }
1035 return (METADEVADM_ERR);
1036 }
1037
1038 mda_debug("Devid update to: %s\n", dnp->devid);
1039
1040 /*
1041 * Check if we own the set, if we do then do some processing
1042 * on the replicas.
1043 */
1044 if (meta_check_ownership(*spp, ep) == 0) {
1045
1046 /* get the replicas */
1047 if (metareplicalist(*spp, MD_BASICNAME_OK | PRINT_FAST, &rlp,
1048 ep) < 0)
1049 return (METADEVADM_ERR);
1050
1051 /* update the devids in the replicas if necessary */
1052 if (replica_update_devid(rlp, dnp, setno, &old_cdevidp,
1053 ep) != METADEVADM_SUCCESS) {
1054 metafreereplicalist(rlp);
1055 return (METADEVADM_ERR);
1056 }
1057
1058 metafreereplicalist(rlp);
1059 }
1060
1061 /*
1062 * If this is not the LOCAL set then need to update the LOCAL
1063 * replica with the new disk record.
1064 */
1065
1066 if (setno != MD_LOCAL_SET) {
1067 mda_debug("Non-local set: %d side %d\n", setno, side);
1068
1069 /*
1070 * Need to find the disk record within the set and then
1071 * update it.
1072 */
1073 if ((dd =
1074 metaget_drivedesc(*spp, MD_FULLNAME_ONLY, ep)) == NULL) {
1075 if (! mdisok(ep))
1076 goto out;
1077 /* no disks in the set - no point continuing */
1078 mda_debug("No disks in diskset\n");
1079 rval = METADEVADM_SUCCESS;
1080 goto out;
1081 }
1082
1083 for (ddp = dd; ddp != NULL; ddp = ddp->dd_next) {
1084 if (strncmp(ddp->dd_dnp->cname, dnp->cname,
1085 strlen(dnp->cname)) == 0)
1086 break;
1087 }
1088
1089 if (ddp == NULL) {
1090 /* failed to finddisk in the set */
1091 mda_print(dgettext(TEXT_DOMAIN,
1092 "%s not found in set %s. Check your syntax\n"),
1093 ctd, (*spp)->setname);
1094 (void) mddserror(ep, MDE_DS_DRIVENOTINSET, setno, NULL,
1095 ctd, (*spp)->setname);
1096 goto out;
1097 }
1098
1099 /*
1100 * Now figure out the correct slice, for a diskset the slice
1101 * we care about is always the 'replica' slice.
1102 */
1103 if (meta_replicaslice(dnp, &rep_slice, ep) != 0) {
1104 mda_debug("Unable to find replica slice for %s\n",
1105 dnp->cname);
1106 goto out;
1107 }
1108
1109 mda_debug("slice no: %d disk %s\n", rep_slice, dnp->cname);
1110
1111 if ((np = metaslicename(dnp, rep_slice, ep)) == NULL) {
1112 mda_debug("Unable to build namespace\n");
1113 goto out;
1114 }
1115
1116 mda_debug("check: ctdname: %s\n", np->cname);
1117 mda_debug("check: ctdname: %s\n", np->rname);
1118 mda_debug("check: ctdname: %s\n", np->bname);
1119
1120 if (!(dev_options & DEV_NOACTION)) {
1121
1122 mda_debug("Updating record: key %d name %s\n",
1123 ddp->dd_dnp->side_names_key, np->cname);
1124
1125 pathname = mda_getpath(np->bname);
1126
1127 if (meta_update_namespace(MD_LOCAL_SET, side + SKEW,
1128 np->cname, np->dev, ddp->dd_dnp->side_names_key,
1129 pathname, ep) != 0) {
1130 goto out;
1131 }
1132
1133 /*
1134 * Now update the devid entry as well, this works
1135 * correctly because the prior call to
1136 * meta_update_namespace() above puts the correct dev_t
1137 * in the namespace which will then be resolved
1138 * to the new devid by the ioctl now called.
1139 */
1140 nm.mde = mdnullerror;
1141 nm.setno = MD_LOCAL_SET;
1142 nm.side = side + SKEW;
1143 nm.key = ddp->dd_dnp->side_names_key;
1144 if (metaioctl(MD_SETNMDID, &nm, &nm.mde, NULL) != 0) {
1145 (void) mdstealerror(ep, &nm.mde);
1146 goto out;
1147 }
1148 }
1149 }
1150
1151 if ((dev_options & DEV_LOCAL_SET) && (setno != MD_LOCAL_SET)) {
1152 /*
1153 * Only want to update the local set so do not continue.
1154 */
1155 rval = METADEVADM_SUCCESS;
1156 goto out;
1157 }
1158
1159 /*
1160 * Iterate through all of the metadevices looking for the
1161 * passed in ctd. If found then update the devid
1162 */
1163 (void) memset(&nm, '\0', sizeof (nm));
1164 nm.key = MD_KEYWILD;
1165 /* LINTED */
1166 while (1) {
1167 nm.mde = mdnullerror;
1168 nm.setno = setno;
1169 nm.side = side;
1170
1171 /* search each namespace entry */
1172 if (metaioctl(MD_IOCNXTKEY_NM, &nm, &nm.mde, NULL) != 0) {
1173 (void) mdstealerror(ep, &nm.mde);
1174 rval = METADEVADM_ERR;
1175 goto out;
1176 }
1177 if (nm.key == MD_KEYWILD) {
1178 if (setno != MD_LOCAL_SET) {
1179 mda_print(dgettext(TEXT_DOMAIN,
1180 "%s not found in set %s. Check your "
1181 "syntax\n"), ctd, (*spp)->setname);
1182 goto out;
1183 } else {
1184 mda_print(dgettext(TEXT_DOMAIN,
1185 "%s not found in local set. "
1186 "Check your syntax\n"), ctd);
1187 goto out;
1188 }
1189 }
1190
1191 nm.devname = (uintptr_t)meta_getnmentbykey(setno, side, nm.key,
1192 NULL, NULL, NULL, ep);
1193 if (nm.devname == NULL) {
1194 rval = METADEVADM_ERR;
1195 goto out;
1196 }
1197
1198 diskname = getdiskname((char *)(uintptr_t)nm.devname);
1199
1200 mda_debug("Checking %s with %s\n", diskname, dnp->cname);
1201 if (strcmp(diskname, dnp->cname) != 0)
1202 continue;
1203
1204 mda_debug("Updating device %s in namespace\n",
1205 (char *)(uintptr_t)nm.devname);
1206
1207 /*
1208 * found disk, does it have a devid within the namespace ?
1209 * It might not because it does not support devid's or was
1210 * put into the namespace when there was no devid support
1211 */
1212 if ((devidp = has_devid(setno, side, nm.key, ep)) == NULL) {
1213 mda_debug("%s has no devid in the namespace",
1214 (char *)(uintptr_t)nm.devname);
1215 if (dev_options & DEV_VERBOSE) {
1216 mda_print(dgettext(TEXT_DOMAIN,
1217 "SVM has no device id for "
1218 "%s, cannot update.\n"),
1219 (char *)(uintptr_t)nm.devname);
1220 }
1221 continue; /* no devid. go on to next */
1222 }
1223 if (old_cdevidp == NULL) {
1224 old_cdevidp = devid_str_encode(devidp, NULL);
1225 }
1226 free(devidp);
1227
1228 /*
1229 * has devid so update namespace, note the key has been set
1230 * by the prior MD_IOCNXTKEY_NM ioctl.
1231 */
1232 nm.mde = mdnullerror;
1233 nm.setno = setno;
1234 nm.side = side;
1235 if (!(dev_options & DEV_NOACTION)) {
1236 /*
1237 * The call below may fail if the -u option is being
1238 * used to update a disk that has been replaced.
1239 * The -u option to metadevadm should not be used
1240 * for this purpose because we trust the dev_t of
1241 * the device in the replica and if we have replaced
1242 * the device and it is a fibre one then the dev_t
1243 * will have changed. This means we end up looking for
1244 * the devid of a non-existant disk and we subsequently
1245 * fail with NODEVID.
1246 */
1247 if (metaioctl(MD_SETNMDID, &nm,
1248 &nm.mde, NULL) != 0) {
1249 if (dev_options & DEV_VERBOSE) {
1250 mda_print(dgettext(TEXT_DOMAIN,
1251 "SVM failed to update the device "
1252 "id for %s probably due to both "
1253 "devt and device id changing.\n"),
1254 (char *)(uintptr_t)nm.devname);
1255 }
1256 (void) mdstealerror(ep, &nm.mde);
1257 mde_perror(ep, "");
1258 rval = METADEVADM_ERR;
1259 goto out;
1260 }
1261 }
1262 if (old_cdevidp == NULL) {
1263 rval = METADEVADM_ERR;
1264 goto out;
1265 }
1266 break;
1267 } /* end while */
1268
1269 mda_print(dgettext(TEXT_DOMAIN,
1270 "Updating Solaris Volume Manager device relocation "
1271 "information for %s\n"), ctd);
1272
1273 mda_print(dgettext(TEXT_DOMAIN,
1274 "Old device reloc information:\n\t%s\n"), old_cdevidp);
1275
1276 len = strlen(dnp->rname) + strlen("s0");
1277 if ((fp = (char *)Malloc(len + 1)) == NULL) {
1278 mda_print(dgettext(TEXT_DOMAIN,
1279 "insufficient memory, device Reloc info not "
1280 "available\n"));
1281 } else {
1282 (void) snprintf(fp, len + 1, "%ss0", dnp->rname);
1283 if ((fd = open(fp, O_RDONLY|O_NDELAY)) < 0) {
1284 mda_print(dgettext(TEXT_DOMAIN,
1285 "Open of %s failed\n"), fp);
1286 } else {
1287 int rc = -1;
1288 ddi_devid_t devid1 = NULL;
1289 char *cdevidp;
1290
1291 rc = devid_get(fd, &devid1);
1292 if (close(fd) < 0) {
1293 mda_print(dgettext(TEXT_DOMAIN,
1294 "Close of %s failed\n"), fp);
1295 }
1296 if (rc != 0) {
1297 mda_print(dgettext(TEXT_DOMAIN,
1298 "Unable to obtain device "
1299 "Reloc info for %s\n"), fp);
1300 } else {
1301 cdevidp = devid_str_encode(devid1, NULL);
1302 if (cdevidp == NULL) {
1303 mda_print(dgettext(TEXT_DOMAIN,
1304 "Unable to print "
1305 "device Reloc info for %s\n"), fp);
1306 } else {
1307 mda_print(dgettext(TEXT_DOMAIN,
1308 "New device reloc "
1309 "information:\n\t%s\n"), cdevidp);
1310 devid_str_free(cdevidp);
1311 }
1312 devid_free(devid1);
1313 }
1314 }
1315 Free(fp);
1316 }
1317
1318 rval = METADEVADM_SUCCESS;
1319
1320 out:
1321 if (diskname)
1322 Free(diskname);
1323 if (pathname)
1324 Free(pathname);
1325 if (old_cdevidp) {
1326 devid_str_free(old_cdevidp);
1327 }
1328 return (rval);
1329
1330 }
1331
1332 /*
1333 * Check the ctd name of the disk to see if the disk has moved. If it
1334 * has moved then the newname is returned in 'newname', it is up to
1335 * the caller to free the memory associated with it.
1336 *
1337 * RETURN
1338 * METADEVADM_ERR error
1339 * METADEVADM_SUCCESS success
1340 * METADEVADM_DISKMOVE success, and the disk has moved
1341 * METADEVADM_DSKNAME_ERR error creating the disk name structures.
1342 */
1343 int
meta_upd_ctdnames(mdsetname_t ** spp,set_t setno,side_t sideno,mddrivename_t * dnp,char ** newname,md_error_t * ep)1344 meta_upd_ctdnames(
1345 mdsetname_t **spp,
1346 set_t setno,
1347 side_t sideno,
1348 mddrivename_t *dnp,
1349 char **newname,
1350 md_error_t *ep
1351 )
1352 {
1353 char *drvnmp;
1354 int i;
1355 minor_t mnum = 0;
1356 md_dev64_t dev = 0;
1357 dev_t small_dev = (dev_t)NODEV;
1358 mdnm_params_t nm;
1359 char *pathname;
1360 char *minor_name = NULL;
1361 ddi_devid_t devidp;
1362 devid_nmlist_t *disklist = NULL;
1363 int ret = 0;
1364 mdsidenames_t *snp;
1365 int match_type;
1366 int search_number = -1;
1367 char *search_type = NULL;
1368 char *search_path = NULL;
1369 uint_t rep_slice;
1370 mddrivename_t *newdnp;
1371 mdname_t *np;
1372 mdsetname_t *sp = *spp;
1373 md_set_desc *sd;
1374
1375 /*
1376 * setno should always be 0 but we're going to
1377 * check for multi-node diskset and return if it is one.
1378 */
1379 if (!metaislocalset(sp)) {
1380 if ((sd = metaget_setdesc(sp, ep)) == NULL)
1381 return (METADEVADM_ERR);
1382
1383 if (MD_MNSET_DESC(sd))
1384 return (METADEVADM_SUCCESS);
1385 }
1386
1387 if (dnp->devid == NULL) {
1388 /* no devid, nothing can be done */
1389 mda_debug("meta_upd_ctdnames: %s has no devid\n", dnp->cname);
1390 if (dev_options & DEV_VERBOSE) {
1391 mda_print(dgettext(TEXT_DOMAIN,
1392 "%s has no devid, cannot detect "
1393 "disk movement for this disk.\n"), dnp->cname);
1394 }
1395 return (ret);
1396 }
1397
1398 /*
1399 * Find the correct side name for the disk. There is a sidename
1400 * for each host associated with the diskset.
1401 */
1402 for (snp = dnp->side_names; snp != NULL; snp = snp->next) {
1403 mda_debug("meta_upd_ctdnames: %s %d args: setno %d sideno %d\n",
1404 snp->cname, snp->sideno, setno, sideno);
1405 /* only use SKEW for the local replica */
1406 if (setno == 0) {
1407 if (snp->sideno + SKEW == sideno)
1408 break;
1409 } else {
1410 if (snp->sideno == sideno)
1411 break;
1412 }
1413 }
1414
1415 if (snp == NULL) {
1416 /*
1417 * Failed to find the side name, this should not
1418 * be possible. However if it does happen this is an
1419 * indication of an inconsistant replica - something
1420 * might have gone wrong during an add or a delete of
1421 * a host.
1422 */
1423 mda_debug("Unable to find the side information for disk %s",
1424 dnp->cname);
1425 (void) mddserror(ep, MDE_DS_HOSTNOSIDE, (*spp)->setno, mynode(),
1426 NULL, dnp->cname);
1427 return (METADEVADM_ERR);
1428 }
1429 /*
1430 * Find the type of device we are to be searching on
1431 */
1432 search_number = mda_findpath(snp->cname);
1433 if (search_number == -1) {
1434 search_path = "/dev";
1435 search_type = DEVID_MINOR_NAME_ALL;
1436 } else {
1437 search_path = plist[search_number].search_path;
1438 search_type = plist[search_number].search_type;
1439 }
1440
1441 mda_debug("Search path :%s searth_type: %x\n",
1442 search_path, (int)search_type);
1443 (void) memset(&nm, '\0', sizeof (nm));
1444
1445 nm.mde = mdnullerror;
1446 nm.setno = setno;
1447 nm.side = sideno;
1448
1449 /*
1450 * Get the devname from the name space.
1451 */
1452 if ((nm.devname = (uintptr_t)meta_getnmentbykey(setno, sideno,
1453 dnp->side_names_key, &drvnmp, &mnum, &dev, ep)) == NULL) {
1454 return (METADEVADM_ERR);
1455 }
1456
1457 ret = devid_str_decode(dnp->devid, &devidp, &minor_name);
1458 devid_str_free(minor_name);
1459
1460 if (ret != 0) {
1461 /*
1462 * Failed to encode the devid.
1463 */
1464 devid_free(devidp);
1465 return (METADEVADM_ERR);
1466 }
1467
1468 /*
1469 * Use the stored devid to find the existing device node and check
1470 * to see if the disk has moved. Use the raw devices as the name
1471 * of the disk is stored as the raw device, if this is not done
1472 * then the disk will not be found.
1473 */
1474 ret = meta_deviceid_to_nmlist(search_path, devidp,
1475 search_type, &disklist);
1476
1477 if (ret != 0) {
1478 if (dev_options & DEV_VERBOSE) {
1479 mda_print(dgettext(TEXT_DOMAIN,
1480 "Device ID %s last associated with "
1481 "disk %s no longer found in system\n"),
1482 dnp->devid, dnp->cname);
1483 }
1484 devid_free(devidp);
1485 devid_free_nmlist(disklist);
1486 return (METADEVADM_SUCCESS);
1487 }
1488
1489 small_dev = meta_cmpldev(dev);
1490 mda_debug("Old device lookup: %s (%p)\n",
1491 (char *)(uintptr_t)nm.devname, (void *)small_dev);
1492 /*
1493 * Check to see if the returned disk matches the stored one
1494 */
1495 for (i = 0; disklist[i].dev != NODEV; i++) {
1496 match_type = 0;
1497 mda_debug("From devid lookup: %s (%p)\n",
1498 disklist[i].devname, (void *)disklist[i].dev);
1499
1500 if (disklist[i].dev == small_dev) {
1501 match_type |= DEV_MATCH;
1502 }
1503
1504 if (strncmp((char *)(uintptr_t)nm.devname, disklist[i].devname,
1505 strlen((char *)(uintptr_t)nm.devname)) == 0) {
1506 match_type |= NAME_MATCH;
1507 }
1508
1509 if (match_type != 0)
1510 break;
1511 }
1512 devid_free(devidp);
1513
1514 mda_debug("meta_upd_ctdnames: match: %x i: %d\n", match_type, i);
1515
1516 if (match_type == (DEV_MATCH|NAME_MATCH)) {
1517 /* no change */
1518 devid_free_nmlist(disklist);
1519 return (METADEVADM_SUCCESS);
1520 }
1521
1522 /* No match found - use the first entry in disklist */
1523 if (disklist[i].dev == NODEV)
1524 i = 0;
1525
1526 if (!(match_type & DEV_MATCH)) {
1527 /* did not match on the dev, so dev_t has changed */
1528 mda_debug("Did not match on dev: %p %p\n",
1529 (void *) small_dev, (void *) disklist[i].dev);
1530 dev = meta_expldev(disklist[i].dev);
1531 }
1532
1533 if (!(match_type & NAME_MATCH)) {
1534 mda_debug("Did not match on name: %s (%p)\n",
1535 (char *)(uintptr_t)nm.devname, (void *) disklist[i].dev);
1536 }
1537
1538 /*
1539 * If here, then the name in the disklist is the one we
1540 * want in any case so use it.
1541 */
1542 mda_debug("devname: %s\n", disklist[i].devname);
1543 /*
1544 * Need to remove the slice as metadrivename() expects a diskname
1545 */
1546 stripS(disklist[i].devname);
1547 /*
1548 * Build an mddrivename_t to use
1549 */
1550 if ((newdnp = metadrivename(spp, disklist[i].devname, ep)) == NULL) {
1551 mda_debug("Unable to make a dnp out of %s\n",
1552 disklist[i].devname);
1553 return (METADEVADM_DSKNAME_ERR);
1554 }
1555 /*
1556 * Need to find the correct slice used for the replica
1557 */
1558 if (meta_replicaslice(newdnp, &rep_slice, ep) != 0) {
1559 return (METADEVADM_DSKNAME_ERR);
1560 }
1561
1562 if ((np = metaslicename(newdnp, rep_slice, ep)) == NULL) {
1563 mda_debug("Failed to build an np for %s\n", dnp->rname);
1564 return (METADEVADM_DSKNAME_ERR);
1565 }
1566 mda_debug("check: cname: %s\n", np->cname);
1567 mda_debug("check: rname: %s\n", np->rname);
1568 mda_debug("check: bname: %s\n", np->bname);
1569
1570 if (newname != NULL)
1571 *newname = Strdup(np->bname);
1572
1573 if (!(dev_options & DEV_NOACTION)) {
1574
1575 mda_debug("update namespace\n");
1576
1577 /* get the block path */
1578 pathname = mda_getpath(np->bname);
1579
1580 if (meta_update_namespace(setno, sideno, np->cname,
1581 dev, dnp->side_names_key, pathname, ep) != 0) {
1582 /* finished with the list so return the memory */
1583 Free(pathname);
1584 devid_free_nmlist(disklist);
1585 return (METADEVADM_ERR);
1586 }
1587 }
1588 /* finished with the list so return the memory */
1589 Free(pathname);
1590 devid_free_nmlist(disklist);
1591 ret = METADEVADM_DISKMOVE;
1592 return (ret);
1593 }
1594
1595 int
meta_fixdevid(mdsetname_t * sp,mddevopts_t options,char * diskname,md_error_t * ep)1596 meta_fixdevid(
1597 mdsetname_t *sp,
1598 mddevopts_t options,
1599 char *diskname,
1600 md_error_t *ep
1601 )
1602 {
1603 set_t setno = sp->setno;
1604 int ret = 0;
1605 char *pathname = NULL;
1606 mdsetname_t *local_sp = NULL;
1607 md_drive_desc *d = NULL;
1608 char *newname = NULL;
1609 md_drive_desc *dd;
1610 side_t sideno;
1611 md_set_desc *sd;
1612
1613 /* if MN diskset just return */
1614 if (!metaislocalset(sp)) {
1615 if ((sd = metaget_setdesc(sp, ep)) == NULL) {
1616 return (METADEVADM_ERR);
1617 }
1618 if (MD_MNSET_DESC(sd))
1619 return (METADEVADM_SUCCESS);
1620 }
1621
1622 dev_options |= options;
1623 mda_debug("dev_options: %x\n", dev_options);
1624 if (dev_options & DEV_RELOAD) {
1625 /*
1626 * If it's not the local set we need to check the local
1627 * namespace to see if disks have moved as it contains
1628 * entries for the disks in the set.
1629 */
1630 if (setno != MD_LOCAL_SET) {
1631 if ((dd = metaget_drivedesc(sp, MD_BASICNAME_OK |
1632 PRINT_FAST, ep)) == NULL) {
1633 mde_perror(ep, "");
1634 mdclrerror(ep);
1635 return (METADEVADM_ERR);
1636 }
1637 local_sp = metasetname(MD_LOCAL_NAME, ep);
1638 sideno = getmyside(sp, ep) + SKEW;
1639 for (d = dd; d != NULL; d = d->dd_next) {
1640 /*
1641 * Actually do the check of the disks.
1642 */
1643 ret = meta_upd_ctdnames(&local_sp, 0, sideno,
1644 d->dd_dnp, &newname, ep);
1645
1646 if ((ret == METADEVADM_ERR) ||
1647 (ret == METADEVADM_DSKNAME_ERR)) {
1648 /* check failed in unknown manner */
1649 mda_debug("meta_upd_ctdnames failed\n");
1650 return (METADEVADM_ERR);
1651 }
1652 }
1653 }
1654
1655 /* do a reload of the devid namespace */
1656 ret = pathname_reload(&sp, setno, ep);
1657 } else if (dev_options & DEV_UPDATE) {
1658 pathname = getdiskname(diskname);
1659 ret = devid_update(&sp, setno, pathname, ep);
1660 free(pathname);
1661 }
1662 return (ret);
1663 }
1664