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.
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.
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]
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28 #include <sys/fcntl.h>
29 #include <sys/types.h>
34 #include <sys/lvm/mdio.h>
38 #include <libdevinfo.h>
39 #include "meta_set_prv.h"
42 * Just in case we're not in a build environment, make sure that
43 * TEXT_DOMAIN gets set to something.
45 #if !defined(TEXT_DOMAIN)
46 #define TEXT_DOMAIN "SYS_TEST"
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 */
56 typedef struct path_list
{
63 * A table of the supported path types - this should ideally be generated
64 * by reading the /etc/lvm/devpath file
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
},
74 static int num
= sizeof (plist
)/sizeof (path_list_t
);
76 static mddevopts_t dev_options
= 0;
78 /* indicate whether to print an error message or not */
79 static int firsttime
= 1;
82 #define NAME_MATCH 0x2
88 * Debug function: to turn on devadm function debugging include DEVADM
89 * in the MD_DEBUG enviroment variable: MD_DEBUG=...,DEVADM...
93 mda_debug(char *format
, ...)
96 static int debug_set
= 0;
100 if (((p
= getenv("MD_DEBUG")) != NULL
) &&
101 (strstr(p
, "DEVADM") != NULL
))
104 debug_set
= DEBUGOFF
;
106 if (debug_set
== DEBUGON
) {
107 va_start(ap
, format
);
108 (void) vfprintf(stderr
, format
, ap
);
113 /* print error messages to the terminal or syslog */
116 mda_print(char *message
, ...)
120 va_start(ap
, message
);
121 if (dev_options
& DEV_LOG
) {
123 * The program is a daemon in the sense that it
124 * is a system utility.
126 (void) vsyslog((LOG_ERR
| LOG_DAEMON
), message
, ap
);
128 (void) vfprintf(stderr
, message
, ap
);
134 * Utility to find the correct options to use for the devid search
135 * based upon the path of the device.
138 * -1 Error, the path passed in is not in the table
139 * >= 0 The element number for the options within the table
142 mda_findpath(char *path
)
146 for (i
= 0; i
< num
; i
++) {
147 if (strncmp(plist
[i
].search_path
, path
,
148 strlen(plist
[i
].search_path
)) == 0)
155 * Utility to get the path of a device
158 mda_getpath(char *devname
)
164 if ((ptr
= strrchr(devname
, '/')) == NULL
) {
165 mda_debug("Invalid format: %s\n", devname
);
169 len
= strlen(devname
) - strlen(ptr
);
170 pathname
= Malloc(len
+ 1);
171 (void) strncpy(pathname
, devname
, len
);
172 pathname
[len
] = '\0';
177 * meta_update_devtree -- Update the /dev/md namespace for metadevices.
179 * Only update the specific link if a valid minor(not NODEV) is given.
180 * Otherwise, update the entire /dev/md .
184 meta_update_devtree(minor_t mnum
)
187 di_devlink_handle_t hdl
;
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.
194 * Use the enhanced di_devlink_init interface if the mnum
199 * NOTE: This will take a _long_ time for large numbers
202 hdl
= di_devlink_init("md", DI_MAKE_LINK
);
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
);
212 (void) di_devlink_fini(&hdl
);
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
);
220 (void) di_devlink_fini(&hdl
);
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.
233 * METADEVADM_ERR ioctl failed and ep is updated with the error
234 * METADEVADM_SUCCESS success
237 update_locator_namespace(
248 (void) memset(&nm
, '\0', sizeof (nm
));
249 nm
.mde
= mdnullerror
;
252 nm
.devname
= (uintptr_t)devname
;
253 nm
.devname_len
= strlen(devname
);
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
);
261 return (METADEVADM_SUCCESS
);
265 * meta_update_namespace -- Contains the ioctl call that will update the
266 * device name and pathname in the namespace area.
269 * METADEVADM_ERR ioctl failed and ep is updated with the error
270 * METADEVADM_SUCCESS success
273 meta_update_namespace(
285 (void) memset(&nm
, '\0', sizeof (nm
));
286 nm
.mde
= mdnullerror
;
289 nm
.devname
= (uintptr_t)devname
;
290 nm
.devname_len
= strlen(devname
);
291 nm
.mnum
= meta_getminor(dev
);
292 nm
.major
= meta_getmajor(dev
);
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
);
300 return (METADEVADM_SUCCESS
);
304 * stripS - Strip s<digits> off the end of the ctds name if it exists
311 /* gobble number and 's' */
312 p
= name
+ strlen(name
) - 1;
313 for (; (p
> name
); --p
) {
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
332 * string that has the disk name in it ie. c0t0d0
343 if ((strncmp(name
, "/dev/dsk/", strlen("/dev/dsk/")) == 0) &&
344 (strchr((p
= name
+ strlen("/dev/dsk/")), '/') == NULL
)) {
345 diskname
= Strdup(p
);
350 if ((strncmp(name
, "/dev/rdsk/", strlen("/dev/rdsk/")) == 0) &&
351 (strchr((p
= name
+ strlen("/dev/rdsk/")), '/') == NULL
)) {
352 diskname
= Strdup(p
);
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
);
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
);
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
);
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
);
385 diskname
= Strdup(name
);
391 * has_devid -- return the device ID for a given key
395 * devid devid found that corresponds to the given key.
398 has_devid(set_t setno
, side_t sideno
, mdkey_t key
, md_error_t
*ep
)
400 return (meta_getdidbykey(setno
, sideno
, key
, ep
));
404 * Go through the existing list of replicas and check to see
405 * if their disk has moved, if so update the replica list
417 md_replicalist_t
*rlp
= NULL
;
418 md_replicalist_t
*rl
;
421 devid_nmlist_t
*disklist
= NULL
;
422 dev_t small_dev
= (dev_t
)NODEV
;
424 set_t setno
= sp
->setno
;
431 sideno
= getmyside(sp
, ep
);
432 if (sideno
== MD_SIDEWILD
) {
433 mda_debug("Failed to find the side number\n");
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
);
442 for (rl
= rlp
; (rl
!= NULL
); rl
= rl
->rl_next
) {
443 md_replica_t
*r
= rl
->rl_repp
;
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",
452 search_path
= plist
[search_number
].search_path
;
455 if (r
->r_devid
== NULL
)
458 ret
= meta_deviceid_to_nmlist(search_path
, r
->r_devid
,
459 r
->r_minor_name
, &disklist
);
461 mda_debug("replica update: search_path %s\n", search_path
);
465 * Failed to find the disk, nothing can be done.
466 * The replica will be marked as bad later.
468 mda_debug("replica update: failed to find disk %s\n",
472 mda_debug("replica update: current %s (%p)\n",
473 r
->r_namep
->bname
, (void *) small_dev
);
476 * Check to see if the returned disk matches the stored one
478 for (i
= 0; disklist
[i
].dev
!= NODEV
; i
++) {
481 mda_debug("replica update: devid list: %s (%p)\n",
482 disklist
[i
].devname
, (void *) disklist
[i
].dev
);
484 if (disklist
[i
].dev
== small_dev
) {
485 match_type
|= DEV_MATCH
;
488 if (strncmp(r
->r_namep
->bname
, disklist
[i
].devname
,
489 strlen(r
->r_namep
->bname
)) == 0) {
490 match_type
|= NAME_MATCH
;
494 * break out if some sort of match is found because
495 * we already match on the devid.
501 mda_debug("fix_replicanames: match: %x i: %d\n", match_type
, i
);
503 if (match_type
== (DEV_MATCH
|NAME_MATCH
)) {
505 mda_debug("replica update: no change %s\n",
506 disklist
[i
].devname
);
507 devid_free_nmlist(disklist
);
511 /* No match found - use the first entry in disklist */
512 if (disklist
[i
].dev
== NODEV
)
515 mda_debug("replica update: reloading %s %p\n",
517 (void *)(uintptr_t)meta_expldev(disklist
[i
].dev
));
520 mda_print(dgettext(TEXT_DOMAIN
,
521 "Disk movement detected\n"));
522 mda_print(dgettext(TEXT_DOMAIN
,
523 "Updating device names in Solaris Volume "
528 if (dev_options
& DEV_VERBOSE
) {
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"));
538 mda_print(dgettext(TEXT_DOMAIN
,
539 "%s changed to %s from device relocation "
541 (char *)r
->r_namep
->cname
, disklist
[i
].devname
,
545 if (!(dev_options
& DEV_NOACTION
)) {
546 mda_debug("Updating locator name\n");
547 ctds_name
= strrchr(disklist
[i
].devname
, '/');
549 if ((path_name
= mda_getpath(disklist
[i
].devname
))
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
);
567 devid_free_nmlist(disklist
);
569 metafreereplicalist(rlp
);
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
579 * If the set is a multi-node diskset that means there are no devid's
583 * METADEVADM_ERR error
584 * METADEVADM_SUCCESS success
585 * METADEVADM_DEVIDINVALID success, but invalid devids detected
601 char *search_path
= NULL
;
603 devid_nmlist_t
*disklist
= NULL
;
604 char *minor_name
= NULL
;
605 char *devidstr
= NULL
;
608 dev_t small_dev
= (dev_t
)NODEV
;
611 mdsetname_t
*sp
= *spp
;
616 * Check for multi-node diskset and return if it is one.
618 if (!metaislocalset(sp
)) {
619 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
)
620 return (METADEVADM_ERR
);
622 if (MD_MNSET_DESC(sd
))
623 return (METADEVADM_SUCCESS
);
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
633 (void) memset(&nm
, '\0', sizeof (nm
));
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
);
645 nm
.mde
= mdnullerror
;
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
);
654 if (nm
.key
== MD_KEYWILD
) {
655 /* no more entries */
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.
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",
671 mda_debug("pathname_reload: examining %s\n",
672 (char *)(uintptr_t)nm
.devname
);
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 */
683 if ((minor_name
= meta_getdidminorbykey(setno
, sideno
,
684 nm
.key
, ep
)) == NULL
) {
686 * In theory this is impossible because if the
687 * devidp is non-null then the minor_name has
688 * already been looked up.
690 mda_debug("No minor name for %s\n",
691 (char *)(uintptr_t)nm
.devname
);
696 * If there is a devid then we have a real device that
699 devidstr
= devid_str_encode(devidp
, minor_name
);
700 if (devidstr
== NULL
) {
701 mda_debug("Failed to encode the devid\n");
705 mda_debug("devid: %s\n", devidstr
);
708 * Find the search path that should be used. This is an
709 * optimization to try and prevent a search for the complete
712 search_number
= mda_findpath((char *)(uintptr_t)nm
.devname
);
713 if (search_number
== -1) {
714 search_path
= "/dev";
716 search_path
= plist
[search_number
].search_path
;
719 /* now look for the disk name using the devid */
720 ret
= meta_deviceid_to_nmlist(search_path
, devidp
,
721 minor_name
, &disklist
);
726 * Failed to find the disk
728 devid_str_free(devidstr
);
732 small_dev
= meta_cmpldev(dev
);
733 mda_debug("Old device lookup: %s (%p)\n",
734 (char *)(uintptr_t)nm
.devname
, (void *)small_dev
);
737 * Check to see if the returned disk matches the stored one
739 for (i
= 0; disklist
[i
].dev
!= NODEV
; i
++) {
741 mda_debug("From devid lookup: %s (%p)\n",
742 (char *)disklist
[i
].devname
,
743 (void *)disklist
[i
].dev
);
745 if (disklist
[i
].dev
== small_dev
) {
746 match_type
|= DEV_MATCH
;
749 if (strncmp((char *)(uintptr_t)nm
.devname
,
751 strlen((char *)(uintptr_t)nm
.devname
)) == 0) {
752 mda_debug("Name match: %s and %s (%d)\n",
754 (char *)(uintptr_t)nm
.devname
,
755 strlen((char *)(uintptr_t)nm
.devname
));
756 match_type
|= NAME_MATCH
;
759 if (match_type
== (DEV_MATCH
|NAME_MATCH
))
763 if (match_type
== (DEV_MATCH
|NAME_MATCH
)) {
765 devid_str_free(devidstr
);
766 mda_debug("All matched %s\n", disklist
[i
].devname
);
767 devid_free_nmlist(disklist
);
771 /* No match found - use the first entry in disklist */
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"));
782 if (dev_options
& DEV_VERBOSE
) {
783 mda_print(dgettext(TEXT_DOMAIN
,
784 "%s changed to %s from device relocation "
786 (char *)(uintptr_t)nm
.devname
, disklist
[i
].devname
,
789 devid_str_free(devidstr
);
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
);
798 if ((tmp
= strrchr(path
, '/')) == NULL
) {
799 mda_debug("Failed to parse %s\n", path
);
800 devid_free_nmlist(disklist
);
804 tmp
+= sizeof (char);
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
);
814 ctds_name
+= sizeof (char);
816 mda_debug("Reloading disk %s %s %p\n",
818 (void *)(uintptr_t)meta_expldev(disklist
[i
].dev
));
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
,
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
);
834 devid_free_nmlist(disklist
);
838 if (fix_replicanames(*spp
, ep
) == -1)
839 mda_debug("Failed to update replicas\n");
842 * check for invalid device id's
844 (void) memset(&ds
, '\0', sizeof (ds
));
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
);
856 * we have some invalid device id's so we need to
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
);
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) {
868 (void) mdstealerror(ep
, &ds
.mde
);
869 return (METADEVADM_ERR
);
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
);
884 return (METADEVADM_DEVIDINVALID
);
886 return (METADEVADM_SUCCESS
);
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.
897 * METADEVADM_ERR error
898 * METADEVADM_SUCCESS success
901 replica_update_devid(
902 md_replicalist_t
*rlp
,
910 md_replicalist_t
*rl
;
914 if (cdevidpp
== NULL
)
915 return (METADEVADM_ERR
);
917 ret
= devid_str_decode(dnp
->devid
, &devidp
, NULL
);
919 /* failed to encode the devid */
920 mda_debug("Failed to decode %s into a valid devid\n",
922 return (METADEVADM_ERR
);
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
;
930 if (strncmp(rnp
->cname
, dnp
->cname
, strlen(dnp
->cname
)) == 0) {
932 /* found the replica, now grab the devid */
933 if (*cdevidpp
== NULL
) {
934 *cdevidpp
= devid_str_encode(r
->r_devid
, NULL
);
937 if (*cdevidpp
== NULL
) {
939 return (METADEVADM_ERR
);
942 mda_debug("Updating replica %s, set %d, old devid %s\n",
943 rnp
->cname
, setno
, *cdevidpp
);
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
);
952 (void) memset(&db_c
, '\0', sizeof (db_c
));
954 db_c
.c_setno
= setno
;
955 db_c
.c_devt
= rnp
->dev
;
957 if (!(dev_options
& DEV_NOACTION
)) {
959 mda_debug("Updating replica\n");
962 * call into kernel to update lb
963 * namespace device id
966 if (metaioctl(MD_DB_SETDID
, &db_c
,
967 &db_c
.c_mde
, NULL
) != 0) {
969 (void) mdstealerror(ep
, &db_c
.c_mde
);
970 return (METADEVADM_ERR
);
977 return (METADEVADM_SUCCESS
);
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
986 * METADEVADM_ERR error
987 * METADEVADM_SUCCESS success
997 md_drive_desc
*dd
, *ddp
;
1002 char *old_cdevidp
= NULL
;
1003 md_replicalist_t
*rlp
= NULL
;
1004 int rval
= METADEVADM_ERR
;
1005 mdname_t
*np
= NULL
;
1007 char *pathname
= NULL
;
1008 char *diskname
= NULL
;
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
);
1020 if ((dnp
= metadrivename(spp
, ctd
, ep
)) == NULL
) {
1021 mda_debug("Failed to create a dnp for %s\n", ctd
);
1022 return (METADEVADM_ERR
);
1024 if (dnp
->devid
== NULL
) {
1026 * Disk does not have a devid! So cannot update the
1027 * devid within the replica.
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
);
1035 return (METADEVADM_ERR
);
1038 mda_debug("Devid update to: %s\n", dnp
->devid
);
1041 * Check if we own the set, if we do then do some processing
1044 if (meta_check_ownership(*spp
, ep
) == 0) {
1046 /* get the replicas */
1047 if (metareplicalist(*spp
, MD_BASICNAME_OK
| PRINT_FAST
, &rlp
,
1049 return (METADEVADM_ERR
);
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
);
1058 metafreereplicalist(rlp
);
1062 * If this is not the LOCAL set then need to update the LOCAL
1063 * replica with the new disk record.
1066 if (setno
!= MD_LOCAL_SET
) {
1067 mda_debug("Non-local set: %d side %d\n", setno
, side
);
1070 * Need to find the disk record within the set and then
1074 metaget_drivedesc(*spp
, MD_FULLNAME_ONLY
, ep
)) == NULL
) {
1077 /* no disks in the set - no point continuing */
1078 mda_debug("No disks in diskset\n");
1079 rval
= METADEVADM_SUCCESS
;
1083 for (ddp
= dd
; ddp
!= NULL
; ddp
= ddp
->dd_next
) {
1084 if (strncmp(ddp
->dd_dnp
->cname
, dnp
->cname
,
1085 strlen(dnp
->cname
)) == 0)
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
);
1100 * Now figure out the correct slice, for a diskset the slice
1101 * we care about is always the 'replica' slice.
1103 if (meta_replicaslice(dnp
, &rep_slice
, ep
) != 0) {
1104 mda_debug("Unable to find replica slice for %s\n",
1109 mda_debug("slice no: %d disk %s\n", rep_slice
, dnp
->cname
);
1111 if ((np
= metaslicename(dnp
, rep_slice
, ep
)) == NULL
) {
1112 mda_debug("Unable to build namespace\n");
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
);
1120 if (!(dev_options
& DEV_NOACTION
)) {
1122 mda_debug("Updating record: key %d name %s\n",
1123 ddp
->dd_dnp
->side_names_key
, np
->cname
);
1125 pathname
= mda_getpath(np
->bname
);
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) {
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.
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
);
1151 if ((dev_options
& DEV_LOCAL_SET
) && (setno
!= MD_LOCAL_SET
)) {
1153 * Only want to update the local set so do not continue.
1155 rval
= METADEVADM_SUCCESS
;
1160 * Iterate through all of the metadevices looking for the
1161 * passed in ctd. If found then update the devid
1163 (void) memset(&nm
, '\0', sizeof (nm
));
1164 nm
.key
= MD_KEYWILD
;
1167 nm
.mde
= mdnullerror
;
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
;
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
);
1184 mda_print(dgettext(TEXT_DOMAIN
,
1185 "%s not found in local set. "
1186 "Check your syntax\n"), ctd
);
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
;
1198 diskname
= getdiskname((char *)(uintptr_t)nm
.devname
);
1200 mda_debug("Checking %s with %s\n", diskname
, dnp
->cname
);
1201 if (strcmp(diskname
, dnp
->cname
) != 0)
1204 mda_debug("Updating device %s in namespace\n",
1205 (char *)(uintptr_t)nm
.devname
);
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
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
);
1221 continue; /* no devid. go on to next */
1223 if (old_cdevidp
== NULL
) {
1224 old_cdevidp
= devid_str_encode(devidp
, NULL
);
1229 * has devid so update namespace, note the key has been set
1230 * by the prior MD_IOCNXTKEY_NM ioctl.
1232 nm
.mde
= mdnullerror
;
1235 if (!(dev_options
& DEV_NOACTION
)) {
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.
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
);
1256 (void) mdstealerror(ep
, &nm
.mde
);
1258 rval
= METADEVADM_ERR
;
1262 if (old_cdevidp
== NULL
) {
1263 rval
= METADEVADM_ERR
;
1269 mda_print(dgettext(TEXT_DOMAIN
,
1270 "Updating Solaris Volume Manager device relocation "
1271 "information for %s\n"), ctd
);
1273 mda_print(dgettext(TEXT_DOMAIN
,
1274 "Old device reloc information:\n\t%s\n"), old_cdevidp
);
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 "
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
);
1288 ddi_devid_t devid1
= NULL
;
1291 rc
= devid_get(fd
, &devid1
);
1292 if (close(fd
) < 0) {
1293 mda_print(dgettext(TEXT_DOMAIN
,
1294 "Close of %s failed\n"), fp
);
1297 mda_print(dgettext(TEXT_DOMAIN
,
1298 "Unable to obtain device "
1299 "Reloc info for %s\n"), fp
);
1301 cdevidp
= devid_str_encode(devid1
, NULL
);
1302 if (cdevidp
== NULL
) {
1303 mda_print(dgettext(TEXT_DOMAIN
,
1305 "device Reloc info for %s\n"), fp
);
1307 mda_print(dgettext(TEXT_DOMAIN
,
1309 "information:\n\t%s\n"), cdevidp
);
1310 devid_str_free(cdevidp
);
1318 rval
= METADEVADM_SUCCESS
;
1326 devid_str_free(old_cdevidp
);
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.
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.
1357 dev_t small_dev
= (dev_t
)NODEV
;
1360 char *minor_name
= NULL
;
1362 devid_nmlist_t
*disklist
= NULL
;
1366 int search_number
= -1;
1367 char *search_type
= NULL
;
1368 char *search_path
= NULL
;
1370 mddrivename_t
*newdnp
;
1372 mdsetname_t
*sp
= *spp
;
1376 * setno should always be 0 but we're going to
1377 * check for multi-node diskset and return if it is one.
1379 if (!metaislocalset(sp
)) {
1380 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
)
1381 return (METADEVADM_ERR
);
1383 if (MD_MNSET_DESC(sd
))
1384 return (METADEVADM_SUCCESS
);
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
);
1399 * Find the correct side name for the disk. There is a sidename
1400 * for each host associated with the diskset.
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 */
1407 if (snp
->sideno
+ SKEW
== sideno
)
1410 if (snp
->sideno
== sideno
)
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
1423 mda_debug("Unable to find the side information for disk %s",
1425 (void) mddserror(ep
, MDE_DS_HOSTNOSIDE
, (*spp
)->setno
, mynode(),
1427 return (METADEVADM_ERR
);
1430 * Find the type of device we are to be searching on
1432 search_number
= mda_findpath(snp
->cname
);
1433 if (search_number
== -1) {
1434 search_path
= "/dev";
1435 search_type
= DEVID_MINOR_NAME_ALL
;
1437 search_path
= plist
[search_number
].search_path
;
1438 search_type
= plist
[search_number
].search_type
;
1441 mda_debug("Search path :%s searth_type: %x\n",
1442 search_path
, (int)search_type
);
1443 (void) memset(&nm
, '\0', sizeof (nm
));
1445 nm
.mde
= mdnullerror
;
1450 * Get the devname from the name space.
1452 if ((nm
.devname
= (uintptr_t)meta_getnmentbykey(setno
, sideno
,
1453 dnp
->side_names_key
, &drvnmp
, &mnum
, &dev
, ep
)) == NULL
) {
1454 return (METADEVADM_ERR
);
1457 ret
= devid_str_decode(dnp
->devid
, &devidp
, &minor_name
);
1458 devid_str_free(minor_name
);
1462 * Failed to encode the devid.
1465 return (METADEVADM_ERR
);
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.
1474 ret
= meta_deviceid_to_nmlist(search_path
, devidp
,
1475 search_type
, &disklist
);
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
);
1485 devid_free_nmlist(disklist
);
1486 return (METADEVADM_SUCCESS
);
1489 small_dev
= meta_cmpldev(dev
);
1490 mda_debug("Old device lookup: %s (%p)\n",
1491 (char *)(uintptr_t)nm
.devname
, (void *)small_dev
);
1493 * Check to see if the returned disk matches the stored one
1495 for (i
= 0; disklist
[i
].dev
!= NODEV
; i
++) {
1497 mda_debug("From devid lookup: %s (%p)\n",
1498 disklist
[i
].devname
, (void *)disklist
[i
].dev
);
1500 if (disklist
[i
].dev
== small_dev
) {
1501 match_type
|= DEV_MATCH
;
1504 if (strncmp((char *)(uintptr_t)nm
.devname
, disklist
[i
].devname
,
1505 strlen((char *)(uintptr_t)nm
.devname
)) == 0) {
1506 match_type
|= NAME_MATCH
;
1509 if (match_type
!= 0)
1514 mda_debug("meta_upd_ctdnames: match: %x i: %d\n", match_type
, i
);
1516 if (match_type
== (DEV_MATCH
|NAME_MATCH
)) {
1518 devid_free_nmlist(disklist
);
1519 return (METADEVADM_SUCCESS
);
1522 /* No match found - use the first entry in disklist */
1523 if (disklist
[i
].dev
== NODEV
)
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
);
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
);
1539 * If here, then the name in the disklist is the one we
1540 * want in any case so use it.
1542 mda_debug("devname: %s\n", disklist
[i
].devname
);
1544 * Need to remove the slice as metadrivename() expects a diskname
1546 stripS(disklist
[i
].devname
);
1548 * Build an mddrivename_t to use
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
);
1556 * Need to find the correct slice used for the replica
1558 if (meta_replicaslice(newdnp
, &rep_slice
, ep
) != 0) {
1559 return (METADEVADM_DSKNAME_ERR
);
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
);
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
);
1570 if (newname
!= NULL
)
1571 *newname
= Strdup(np
->bname
);
1573 if (!(dev_options
& DEV_NOACTION
)) {
1575 mda_debug("update namespace\n");
1577 /* get the block path */
1578 pathname
= mda_getpath(np
->bname
);
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 */
1584 devid_free_nmlist(disklist
);
1585 return (METADEVADM_ERR
);
1588 /* finished with the list so return the memory */
1590 devid_free_nmlist(disklist
);
1591 ret
= METADEVADM_DISKMOVE
;
1598 mddevopts_t options
,
1603 set_t setno
= sp
->setno
;
1605 char *pathname
= NULL
;
1606 mdsetname_t
*local_sp
= NULL
;
1607 md_drive_desc
*d
= NULL
;
1608 char *newname
= NULL
;
1613 /* if MN diskset just return */
1614 if (!metaislocalset(sp
)) {
1615 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
1616 return (METADEVADM_ERR
);
1618 if (MD_MNSET_DESC(sd
))
1619 return (METADEVADM_SUCCESS
);
1622 dev_options
|= options
;
1623 mda_debug("dev_options: %x\n", dev_options
);
1624 if (dev_options
& DEV_RELOAD
) {
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.
1630 if (setno
!= MD_LOCAL_SET
) {
1631 if ((dd
= metaget_drivedesc(sp
, MD_BASICNAME_OK
|
1632 PRINT_FAST
, ep
)) == NULL
) {
1635 return (METADEVADM_ERR
);
1637 local_sp
= metasetname(MD_LOCAL_NAME
, ep
);
1638 sideno
= getmyside(sp
, ep
) + SKEW
;
1639 for (d
= dd
; d
!= NULL
; d
= d
->dd_next
) {
1641 * Actually do the check of the disks.
1643 ret
= meta_upd_ctdnames(&local_sp
, 0, sideno
,
1644 d
->dd_dnp
, &newname
, ep
);
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
);
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
);