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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
28 #include <sys/mkdev.h>
29 #include <sys/param.h>
43 #include <sys/unistat/spcs_s.h>
44 #include <sys/unistat/spcs_s_u.h>
45 #include <sys/unistat/spcs_errors.h>
47 #include <sys/nsctl/sv.h>
48 #include <sys/nsctl/sv_impl.h>
50 #include <sys/nsctl/cfg.h>
51 #include <sys/nsctl/nsc_hash.h>
53 #include "../sv/svadm.h"
56 static int sv_max_devices
;
60 * support for the special cluster tag "local" to be used with -C in a
61 * cluster for local volumes.
64 #define SV_LOCAL_TAG "local"
66 static int sv_islocal
;
72 static CFGFILE
*cfg
; /* libcfg file pointer */
73 static int cfg_changed
; /* set to 1 if we need to commit changes */
75 static char *cfg_cluster_tag
; /* local cluster tag */
77 static char *implicit_tag
; /* implicit cluster tag */
81 * Print width for print_sv() output.
84 #define STATWIDTH (SV_MAXPATH / 2)
90 static const caddr_t sv_rpath
= SV_DEVICE
;
96 static int read_config_file(const caddr_t
, sv_name_t
[]);
97 static int enable_dev(sv_name_t
*);
98 static int disable_dev(const caddr_t
);
99 static void error(spcs_s_info_t
*, caddr_t
, ...);
100 static void create_cfg_hash();
101 static int find_in_hash(char *path
);
102 static void destroy_hashtable();
103 static void remove_from_cfgfile(char *path
, int setnumber
);
105 static caddr_t program
;
108 sv_cfg_open(CFGLOCK mode
)
113 cfg
= cfg_open(NULL
);
115 error(NULL
, gettext("unable to access the configuration"));
119 if (cfg_cluster_tag
&& *cfg_cluster_tag
) {
120 cfg_resource(cfg
, cfg_cluster_tag
);
122 cfg_resource(cfg
, NULL
);
124 if (!cfg_lock(cfg
, mode
)) {
125 error(NULL
, gettext("unable to lock the configuration"));
138 (void) cfg_commit(cfg
);
151 (void) fprintf(stderr
, gettext("usage:\n"));
153 (void) fprintf(stderr
, gettext(
154 "\t%s -h help\n"), program
);
156 (void) fprintf(stderr
, gettext(
157 "\t%s [-C tag] display status\n"),
160 (void) fprintf(stderr
, gettext(
161 "\t%s [-C tag] -i display "
162 "extended status\n"), program
);
164 (void) fprintf(stderr
, gettext(
165 "\t%s [-C tag] -v display "
166 "version number\n"), program
);
168 (void) fprintf(stderr
, gettext(
169 "\t%s [-C tag] -e { -f file | volume } enable\n"), program
);
171 (void) fprintf(stderr
, gettext(
172 "\t%s [-C tag] -d { -f file | volume } disable\n"), program
);
174 (void) fprintf(stderr
, gettext(
175 "\t%s [-C tag] -r { -f file | volume } reconfigure\n"), program
);
181 message(caddr_t prefix
, spcs_s_info_t
*status
, caddr_t string
, va_list ap
)
183 (void) fprintf(stderr
, "%s: %s: ", program
, prefix
);
184 (void) vfprintf(stderr
, string
, ap
);
185 (void) fprintf(stderr
, "\n");
188 spcs_s_report(*status
, stderr
);
189 spcs_s_ufree(status
);
195 error(spcs_s_info_t
*status
, caddr_t string
, ...)
198 va_start(ap
, string
);
200 message(gettext("error"), status
, string
, ap
);
210 warn(spcs_s_info_t
*status
, caddr_t string
, ...)
213 va_start(ap
, string
);
215 message(gettext("warning"), status
, string
, ap
);
228 if (sv_max_devices
> 0)
231 fd
= open(sv_rpath
, O_RDONLY
);
233 error(NULL
, gettext("unable to open %s: %s"),
234 sv_rpath
, strerror(errno
));
236 bzero(&svl
, sizeof (svl
));
237 bzero(&svn
[0], sizeof (svn
));
239 svl
.svl_names
= &svn
[0];
240 svl
.svl_error
= spcs_s_ucreate();
242 if (ioctl(fd
, SVIOC_LIST
, &svl
) < 0) {
244 error(&svl
.svl_error
, gettext("unable to get max devs"));
247 spcs_s_ufree(&svl
.svl_error
);
248 sv_max_devices
= svl
.svl_maxdevs
;
255 sv_alloc_svnames(void)
257 sv_name_t
*svn
= NULL
;
261 svn
= calloc(sv_max_devices
, sizeof (*svn
));
263 error(NULL
, "unable to allocate %ld bytes of memory",
264 sv_max_devices
* sizeof (*svn
));
272 sv_check_dgislocal(char *dgname
)
278 * check where this disk service is mastered
281 rc
= cfg_dgname_islocal(dgname
, &othernode
);
283 error(NULL
, gettext("unable to find "
284 "disk service, %s: %s"), dgname
, strerror(errno
));
288 error(NULL
, gettext("disk service, %s, is "
289 "active on node \"%s\"\nPlease re-issue "
290 "the command on that node"), dgname
, othernode
);
296 * Carry out cluster based checks for a specified volume, or just
300 sv_check_cluster(char *path
)
302 char dgname
[CFG_MAX_BUF
];
303 static int sv_iscluster
= -1; /* set to 1 if running in a cluster */
306 * Find out if we are running in a cluster
308 if (sv_iscluster
== -1) {
309 if ((sv_iscluster
= cfg_iscluster()) < 0) {
310 error(NULL
, gettext("unable to ascertain environment"));
314 if (!sv_iscluster
&& cfg_cluster_tag
!= NULL
) {
315 error(NULL
, gettext("-C is not valid when not in a cluster"));
318 if (!sv_iscluster
|| sv_islocal
|| path
== NULL
) {
324 * Cluster-only checks on pathname
326 if (cfg_dgname(path
, dgname
, sizeof (dgname
)) == NULL
) {
327 error(NULL
, gettext("unable to determine "
328 "disk group name for %s"), path
);
332 if (cfg_cluster_tag
!= NULL
) {
334 * Do dgislocal check now in case path did not contain
337 * E.g. adding a /dev/did/ device to a disk service.
340 sv_check_dgislocal(cfg_cluster_tag
);
343 if (strcmp(dgname
, "") == 0)
344 return; /* NULL dgname is valid */
346 if (cfg_cluster_tag
== NULL
) {
348 * Implicitly set the cluster tag to dgname
351 sv_check_dgislocal(dgname
);
358 implicit_tag
= strdup(dgname
);
359 if (implicit_tag
== NULL
) {
361 gettext("unable to allocate memory "
366 * Check dgname and cluster tag from -C are the same.
369 if (strcmp(dgname
, cfg_cluster_tag
) != 0) {
371 gettext("-C (%s) does not match disk group "
372 "name (%s) for %s"), cfg_cluster_tag
,
377 * sv_check_dgislocal(cfg_cluster_tag) was called above.
389 bzero(&svv
, sizeof (svv
));
390 svv
.svv_error
= spcs_s_ucreate();
392 fd
= open(sv_rpath
, O_RDONLY
);
394 warn(NULL
, gettext("unable to open %s: %s"),
395 sv_rpath
, strerror(errno
));
399 if (ioctl(fd
, SVIOC_VERSION
, &svv
) != 0) {
400 error(&svv
.svv_error
,
401 gettext("unable to read the version number"));
405 spcs_s_ufree(&svv
.svv_error
);
407 (void) printf(gettext("Storage Volume version %d.%d.%d.%d\n"),
408 svv
.svv_major_rev
, svv
.svv_minor_rev
,
409 svv
.svv_micro_rev
, svv
.svv_baseline_rev
);
411 if (svv
.svv_micro_rev
) {
412 (void) printf(gettext("Storage Volume version %d.%d.%d\n"),
413 svv
.svv_major_rev
, svv
.svv_minor_rev
, svv
.svv_micro_rev
);
415 (void) printf(gettext("Storage Volume version %d.%d\n"),
416 svv
.svv_major_rev
, svv
.svv_minor_rev
);
424 main(int argc
, char *argv
[])
428 char *conf_file
= NULL
;
429 int enable
, disable
, compare
, print
, version
;
430 int opt
, Cflag
, fflag
, iflag
;
433 (void) setlocale(LC_ALL
, "");
434 (void) textdomain("svadm");
436 program
= strdup(basename(argv
[0]));
438 Cflag
= fflag
= iflag
= 0;
439 compare
= enable
= disable
= version
= 0;
443 while ((opt
= getopt(argc
, argv
, "C:def:hirv")) != EOF
) {
449 gettext("-C specified multiple times"));
456 cfg_cluster_tag
= optarg
;
479 /* Compare running system with sv.cf */
505 if ((enable
+ disable
+ compare
) > 1) {
506 warn(NULL
, gettext("-d, -e and -r are mutually exclusive"));
511 if (fflag
&& (print
|| version
)) {
512 warn(NULL
, gettext("-f is only valid with -d, -e or -r"));
517 if (fflag
&& optind
!= argc
) {
522 if (print
|| version
) {
523 /* check for no more args */
525 if (optind
!= argc
) {
530 /* check for inline args */
532 if (!fflag
&& (argc
- optind
) != 1) {
538 if (!print
&& iflag
) {
545 * Check for the special cluster tag and convert into the
546 * internal representation.
549 if (cfg_cluster_tag
!= NULL
&&
550 strcmp(cfg_cluster_tag
, SV_LOCAL_TAG
) == 0) {
551 cfg_cluster_tag
= "-";
560 if (optind
!= argc
) {
561 /* deal with inline volume argument */
565 rc
= enable_one_sv(argv
[optind
]);
567 rc
= disable_one_sv(argv
[optind
]);
568 else /* if (compare) */
569 compare_one_sv(argv
[optind
]);
579 rc
= enable_sv(conf_file
);
581 rc
= disable_sv(conf_file
);
583 compare_sv(conf_file
);
586 else /* if (version) */
597 /* LINT - not static as fwcadm uses it */
599 enable_sv(char *conf_file
)
606 svn
= sv_alloc_svnames();
608 index
= read_config_file(conf_file
, svn
);
612 for (cnt
= 0; cnt
< index
; cnt
++) {
615 * Check for more data.
617 if (svn
[cnt
].svn_path
[0] == '\0') {
619 * This was set when reading sv.conf. After the last
620 * line svn_path was set to \0, so we are finished.
621 * We shouldn't get here, but put this in just in
626 rc
= enable_dev(&svn
[cnt
]);
637 /* LINT - not static as fwcadm uses it */
639 enable_one_sv(caddr_t path
)
646 bzero(&svn
, sizeof (svn
));
647 (void) strncpy(svn
.svn_path
, path
, sizeof (svn
.svn_path
));
648 svn
.svn_mode
= (NSC_DEVICE
| NSC_CACHE
);
650 /* force NULL termination */
651 svn
.svn_path
[sizeof (svn
.svn_path
) - 1] = '\0';
653 rc
= enable_dev(&svn
);
661 enable_dev(sv_name_t
*svn
)
663 char buf
[CFG_MAX_BUF
];
672 sv_check_cluster(svn
->svn_path
);
673 sv_cfg_open(CFG_WRLOCK
);
675 bzero(&svc
, sizeof (svc
));
677 if (stat(svn
->svn_path
, &stb
) != 0) {
678 warn(NULL
, gettext("unable to access %s: %s"),
679 svn
->svn_path
, strerror(errno
));
683 if (!S_ISCHR(stb
.st_mode
)) {
684 warn(NULL
, gettext("%s is not a character device - ignored"),
689 svc
.svc_major
= major(stb
.st_rdev
);
690 svc
.svc_minor
= minor(stb
.st_rdev
);
691 (void) strncpy(svc
.svc_path
, svn
->svn_path
, sizeof (svc
.svc_path
));
693 fd
= open(sv_rpath
, O_RDONLY
);
695 warn(NULL
, gettext("unable to open %s: %s"),
696 svn
->svn_path
, strerror(errno
));
700 svc
.svc_flag
= svn
->svn_mode
;
701 svc
.svc_error
= spcs_s_ucreate();
703 /* first, check for duplicates */
704 rc
= cfg_get_canonical_name(cfg
, svn
->svn_path
, &altname
);
706 spcs_log("sv", NULL
, gettext("Unable to parse config file"));
707 warn(NULL
, gettext("Unable to parse config file"));
712 error(NULL
, gettext("'%s' has already been configured as "
713 "'%s'. Re-enter command with the latter name."),
714 svn
->svn_path
, altname
);
717 /* secondly, try to insert it into the dsvol config */
718 if (implicit_tag
&& *implicit_tag
) {
719 lcltag
= implicit_tag
;
720 } else if (cfg_cluster_tag
&& *cfg_cluster_tag
) {
721 lcltag
= cfg_cluster_tag
;
725 rc
= cfg_add_user(cfg
, svn
->svn_path
, lcltag
, "sv");
726 if (CFG_USER_ERR
== rc
) {
728 gettext("%s: unable to put %s into dsvol cfg"),
729 program
, svn
->svn_path
);
730 warn(NULL
, gettext("unable to put %s into dsvol cfg"),
737 if (CFG_USER_OK
== rc
) {
743 if (ioctl(fd
, SVIOC_ENABLE
, &svc
) < 0) {
744 if ((CFG_USER_REPEAT
== rc
) && (SV_EENABLED
== errno
)) {
745 /* it's ok -- we were just double-checking */
750 spcs_log("sv", &svc
.svc_error
,
751 gettext("%s: unable to enable %s"),
752 program
, svn
->svn_path
);
754 warn(&svc
.svc_error
, gettext("unable to enable %s"),
757 /* remove it from dsvol, if we're the ones who put it in */
758 if (CFG_USER_FIRST
== rc
) {
759 (void) cfg_rem_user(cfg
, svn
->svn_path
, lcltag
, "sv");
765 spcs_log("sv", NULL
, gettext("%s: enabled %s"),
766 program
, svn
->svn_path
);
768 if (implicit_tag
!= NULL
) {
770 if (cfg_cluster_tag
!= NULL
) {
772 gettext("enable_dev: -C %s AND implicit_tag %s!"),
773 cfg_cluster_tag
, implicit_tag
);
777 (void) snprintf(buf
, sizeof (buf
), "%s - %s",
778 svc
.svc_path
, implicit_tag
);
780 (void) strcpy(buf
, svc
.svc_path
);
784 if (cfg_put_cstring(cfg
, "sv", buf
, sizeof (buf
)) < 0) {
786 gettext("unable to add %s to configuration storage: %s"),
787 svc
.svc_path
, cfg_error(&sev
));
792 spcs_s_ufree(&svc
.svc_error
);
800 * This routine parses the config file passed in via conf_file and
801 * stores the data in the svn array. The return value is the number
802 * of entries read from conf_file. If an error occurs the error()
803 * routine is called (which exits the program).
806 read_config_file(const caddr_t conf_file
, sv_name_t svn
[])
808 char line
[1024], rdev
[1024], junk
[1024];
812 int index
= 0; /* Current location in svn array */
813 sv_name_t
*cur_svn
; /* Pointer to svn[index] */
816 if (access(conf_file
, R_OK
) != 0 ||
817 stat(conf_file
, &stb
) != 0 ||
818 !S_ISREG(stb
.st_mode
)) {
819 error(NULL
, gettext("cannot read config file %s"), conf_file
);
822 if ((fp
= fopen(conf_file
, "r")) == NULL
) {
823 error(NULL
, gettext("unable to open config file %s: %s"),
824 conf_file
, strerror(errno
));
829 while (fgets(line
, sizeof (line
), fp
) != NULL
) {
837 if (line
[i
-1] == '\n')
839 else if (i
== (sizeof (line
) - 1)) {
841 "line %d: line too long -- should be less than %d characters"),
842 lineno
, (sizeof (line
) - 1));
843 warn(NULL
, gettext("line %d: ignored"), lineno
);
847 * check for comment line.
852 cnt
= sscanf(line
, "%s %s", rdev
, junk
);
854 if (cnt
!= 1 && cnt
!= 2) {
856 warn(NULL
, gettext("line %d: invalid format"),
858 warn(NULL
, gettext("line %d: ignored"), lineno
);
863 rdev
[sizeof (rdev
) - 1] = '\0';
865 cur_svn
= &svn
[index
]; /* For easier reading below */
867 if (strlen(rdev
) >= sizeof (cur_svn
->svn_path
)) {
869 "line %d: raw device name (%s) longer than %d characters"),
871 (sizeof (cur_svn
->svn_path
) - 1));
872 warn(NULL
, gettext("line %d: ignored"), lineno
);
876 (void) strcpy(cur_svn
->svn_path
, rdev
);
877 cur_svn
->svn_mode
= (NSC_DEVICE
| NSC_CACHE
);
882 /* Set the last path to NULL */
883 svn
[index
].svn_path
[0] = '\0';
892 * Disable the device from the kernel configuration.
896 * non-zero on failure.
898 * Failures are reported to the user.
901 disable_dev(const caddr_t path
)
907 sv_check_cluster(path
);
909 if (stat(path
, &stb
) < 0) {
910 svc
.svc_major
= (major_t
)-1;
911 svc
.svc_minor
= (minor_t
)-1;
913 svc
.svc_major
= major(stb
.st_rdev
);
914 svc
.svc_minor
= minor(stb
.st_rdev
);
917 if ((fd
= open(sv_rpath
, O_RDONLY
)) < 0) {
918 warn(NULL
, gettext("unable to open %s: %s"),
919 sv_rpath
, strerror(errno
));
923 (void) strcpy(svc
.svc_path
, path
);
924 svc
.svc_error
= spcs_s_ucreate();
927 * Issue the ioctl to attempt to disable this device. Note that all
928 * the libdscfg details are handled elsewhere.
930 if (ioctl(fd
, SVIOC_DISABLE
, &svc
) < 0) {
931 if (errno
!= SV_EDISABLED
) {
932 spcs_log("sv", &svc
.svc_error
,
933 gettext("%s: unable to disable %s"),
937 gettext("unable to disable %s"), path
);
943 spcs_log("sv", NULL
, gettext("%s: disabled %s"), program
, path
);
945 spcs_s_ufree(&svc
.svc_error
);
953 print_cluster_tag(const int setnumber
)
955 char buf
[CFG_MAX_BUF
];
956 char key
[CFG_MAX_KEY
];
958 bzero(buf
, sizeof (buf
));
959 (void) snprintf(key
, sizeof (key
), "sv.set%d.cnode", setnumber
);
961 (void) cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
));
964 if (strcmp(buf
, "-") == 0) {
965 (void) printf(" [%s]", gettext("local to node"));
967 (void) printf(" [%s: %s]", gettext("cluster"), buf
);
973 /* LINT - not static as fwcadm uses it */
975 print_sv(int verbose
)
977 sv_name_t
*svn
, *svn_system
; /* Devices in system */
978 sv_list_t svl_system
;
982 sv_check_cluster(NULL
);
983 sv_cfg_open(CFG_RDLOCK
);
985 svn_system
= sv_alloc_svnames();
987 if ((fd
= open(sv_rpath
, O_RDONLY
)) < 0) {
988 (void) printf(gettext("unable to open %s: %s"),
989 sv_rpath
, strerror(errno
));
993 /* Grab the system list from the driver */
994 svl_system
.svl_count
= sv_max_devices
;
995 svl_system
.svl_names
= &svn_system
[0];
996 svl_system
.svl_error
= spcs_s_ucreate();
998 if (ioctl(fd
, SVIOC_LIST
, &svl_system
) < 0) {
999 error(&svl_system
.svl_error
, gettext("unable to get list"));
1002 spcs_s_ufree(&svl_system
.svl_error
);
1006 * We build a hashmap out of the entries from the config file to make
1007 * searching faster. We end up taking a performance hit when the # of
1008 * volumes is small, but for larger configurations it's a
1012 /* build the hashtable */
1013 cfg_rewind(cfg
, CFG_SEC_CONF
);
1017 * For each volume found from the kernel, print out
1018 * info about it from the kernel.
1020 for (i
= 0; i
< svl_system
.svl_count
; i
++) {
1021 if (*svn_system
[i
].svn_path
== '\0') {
1025 svn
= &svn_system
[i
];
1026 if (svn
->svn_mode
== 0) {
1028 (void) printf(gettext("%s [kernel guard]\n"),
1033 /* get sv entry from the hashtable */
1034 if ((setnumber
= find_in_hash(svn
->svn_path
)) != -1) {
1035 (void) printf("%-*s", STATWIDTH
, svn
->svn_path
);
1038 print_cluster_tag(setnumber
);
1041 (void) printf("\n");
1045 * We didn't find the entry in the hashtable. Let
1046 * the user know that the persistent storage is
1047 * inconsistent with the kernel configuration.
1049 if (cfg_cluster_tag
== NULL
)
1051 "%s is configured, but not in the "
1052 "config storage"), svn
->svn_path
);
1056 /* free up the hashtable */
1057 destroy_hashtable();
1063 /* LINT - not static as fwcadm uses it */
1065 disable_sv(char *conf_file
)
1067 sv_name_t
*svn
, *svn_system
; /* Devices in system */
1068 sv_list_t svl_system
;
1069 int fd
, i
, setnumber
;
1072 svn_system
= sv_alloc_svnames();
1076 if (conf_file
== NULL
) {
1077 if ((fd
= open(sv_rpath
, O_RDONLY
)) < 0) {
1078 (void) printf(gettext("unable to open %s: %s"),
1079 sv_rpath
, strerror(errno
));
1083 /* Grab the system list from the driver */
1084 svl_system
.svl_count
= sv_max_devices
;
1085 svl_system
.svl_names
= &svn_system
[0];
1086 svl_system
.svl_error
= spcs_s_ucreate();
1088 if (ioctl(fd
, SVIOC_LIST
, &svl_system
) < 0) {
1089 error(&(svl_system
.svl_error
),
1090 gettext("unable to get list"));
1093 spcs_s_ufree(&(svl_system
.svl_error
));
1096 svl_system
.svl_count
= read_config_file(conf_file
, svn_system
);
1100 for (i
= 0; i
< svl_system
.svl_count
; i
++) {
1101 if (*svn_system
[i
].svn_path
== '\0')
1104 svn
= &svn_system
[i
];
1106 sv_check_cluster(svn
->svn_path
);
1107 sv_cfg_open(CFG_WRLOCK
);
1110 if ((setnumber
= find_in_hash(svn
->svn_path
)) != -1) {
1111 if ((rc
= disable_dev(svn
->svn_path
)) != -1) {
1112 remove_from_cfgfile(svn
->svn_path
, setnumber
);
1113 } else if (errno
== SV_ENODEV
) {
1114 remove_from_cfgfile(svn
->svn_path
, setnumber
);
1117 /* warn the user that we didn't find it in cfg file */
1119 "%s was not found in the config storage"),
1121 /* try to disable anyway */
1122 (void) disable_dev(svn
->svn_path
);
1127 destroy_hashtable();
1137 /* LINT - not static as fwcadm uses it */
1139 disable_one_sv(char *path
)
1145 sv_check_cluster(path
);
1146 sv_cfg_open(CFG_WRLOCK
);
1149 if ((setnumber
= find_in_hash(path
)) != -1) {
1150 /* remove from kernel */
1151 if ((rc
= disable_dev(path
)) == 0) {
1152 /* remove the cfgline */
1153 remove_from_cfgfile(path
, setnumber
);
1154 } else if (errno
== SV_ENODEV
) {
1155 remove_from_cfgfile(path
, setnumber
);
1158 /* warn the user that we didn't find it in cfg file */
1160 gettext("%s was not found in the config storage"), path
);
1161 /* still attempt to remove */
1162 (void) disable_dev(path
);
1165 destroy_hashtable();
1173 compare_tag(char *path
)
1175 char buf
[CFG_MAX_BUF
], vol
[CFG_MAX_BUF
], cnode
[CFG_MAX_BUF
];
1176 char key
[CFG_MAX_KEY
];
1177 int found
, setnumber
, i
;
1180 sv_check_cluster(path
);
1181 cfg_resource(cfg
, (char *)NULL
); /* reset */
1182 cfg_rewind(cfg
, CFG_SEC_CONF
);
1185 if (cfg_cluster_tag
!= NULL
&& implicit_tag
!= NULL
) {
1186 error(NULL
, gettext("compare_tag: -C %s AND implicit_tag %s!"),
1187 cfg_cluster_tag
, implicit_tag
);
1191 if (cfg_cluster_tag
!= NULL
)
1192 tag
= cfg_cluster_tag
;
1193 else if (implicit_tag
!= NULL
)
1199 for (i
= 0; i
< sv_max_devices
; i
++) {
1201 (void) snprintf(key
, sizeof (key
), "sv.set%d", setnumber
);
1202 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0) {
1206 if (sscanf(buf
, "%s - %s", vol
, cnode
) != 2) {
1210 if (strcmp(path
, vol
) == 0) {
1217 warn(NULL
, gettext("unable to find %s in the configuration"),
1222 /* have name match, compare cnode to new tag */
1224 if (strcmp(tag
, cnode
) == 0) {
1225 /* cluster tags match */
1229 /* need to change the cluster tag */
1231 (void) snprintf(key
, sizeof (key
), "sv.set%d.cnode", setnumber
);
1232 if (cfg_put_cstring(cfg
, key
, tag
, strlen(tag
)) < 0) {
1234 gettext("unable to change cluster tag for %s"), path
);
1240 /* change "-" tags to "" for display purposes */
1242 if (strcmp(tag
, "-") == 0)
1245 if (strcmp(cnode
, "-") == 0)
1246 (void) strcpy(cnode
, "");
1249 gettext("%s: changed cluster tag for %s from \"%s\" to \"%s\"\n"),
1250 program
, path
, cnode
, tag
);
1252 spcs_log("sv", NULL
,
1253 gettext("%s: changed cluster tag for %s from \"%s\" to \"%s\""),
1254 program
, path
, cnode
, tag
);
1258 /* LINT - not static as fwcadm uses it */
1260 compare_sv(char *conf_file
)
1262 sv_name_t
*svn_config
; /* Devices in config file */
1263 sv_name_t
*svn_system
; /* Devices in system */
1264 sv_name_t
*enable
; /* Devices that need enabled */
1265 sv_list_t svl_system
;
1268 int setnumber
, i
, j
;
1269 int index
= 0; /* Index in enable[] */
1273 svn_config
= sv_alloc_svnames();
1274 svn_system
= sv_alloc_svnames();
1275 enable
= sv_alloc_svnames();
1277 bzero(svn_system
, sizeof (svn_system
));
1278 bzero(&svl_system
, sizeof (svl_system
));
1279 bzero(enable
, sizeof (enable
));
1282 * Read the configuration file
1283 * The return value is the number of entries
1285 config_cnt
= read_config_file(conf_file
, svn_config
);
1287 if ((fd0
= open(sv_rpath
, O_RDONLY
)) < 0)
1288 error(NULL
, gettext("unable to open %s: %s"),
1289 sv_rpath
, strerror(errno
));
1291 /* Grab the system list from the driver */
1292 svl_system
.svl_count
= sv_max_devices
;
1293 svl_system
.svl_names
= &svn_system
[0];
1294 svl_system
.svl_error
= spcs_s_ucreate();
1296 if (ioctl(fd0
, SVIOC_LIST
, &svl_system
) < 0) {
1297 error(&svl_system
.svl_error
, gettext("unable to get list"));
1300 spcs_s_ufree(&svl_system
.svl_error
);
1304 * Count the number of devices in the system.
1305 * The last entry in the array has '\0' for a path name.
1307 for (j
= 0; j
< sv_max_devices
; j
++) {
1308 if (svn_system
[j
].svn_path
[0] != '\0') {
1315 * Compare the configuration array with the system array.
1316 * Mark any differences and disable conflicting devices.
1318 for (i
= 0; i
< config_cnt
; i
++) {
1320 for (j
= 0; j
< sys_cnt
; j
++) {
1321 if (svn_system
[j
].svn_path
[0] == '\0' ||
1322 svn_system
[j
].svn_mode
== 0)
1325 /* Check to see if path matches */
1326 if (strcmp(svn_system
[j
].svn_path
,
1327 svn_config
[i
].svn_path
) == 0) {
1329 svn_system
[j
].svn_path
[0] = '\0';
1336 /* Minor number not in system = > enable device */
1337 enable
[index
].svn_mode
= svn_config
[i
].svn_mode
;
1338 (void) strcpy(enable
[index
].svn_path
,
1339 svn_config
[i
].svn_path
);
1344 /* Disable any devices that weren't in the config file */
1345 for (j
= 0; j
< sys_cnt
; j
++) {
1346 sv_check_cluster(NULL
);
1347 sv_cfg_open(CFG_WRLOCK
);
1349 if (svn_system
[j
].svn_path
[0] != '\0' &&
1350 svn_system
[j
].svn_mode
!= 0) {
1351 (void) printf(gettext("%s: disabling sv: %s\n"),
1352 program
, svn_system
[j
].svn_path
);
1353 if (disable_dev(svn_system
[j
].svn_path
) == 0) {
1355 find_in_hash(svn_system
[j
].svn_path
);
1356 if (setnumber
!= -1) {
1357 /* the volume was found in cfg store */
1358 remove_from_cfgfile(
1359 svn_system
[j
].svn_path
, setnumber
);
1364 destroy_hashtable();
1369 * Config file doesn't match system => enable the devices
1373 (void) printf(gettext("%s: enabling new sv: %s\n"),
1374 program
, enable
[index
].svn_path
);
1375 (void) enable_dev(&enable
[index
]);
1379 * Search for entries where the cluster tag has changed.
1381 sv_check_cluster(NULL
);
1382 sv_cfg_open(CFG_WRLOCK
);
1384 for (i
= 0; i
< sv_max_devices
; i
++) {
1385 if (svn_config
[i
].svn_path
[0] == '\0')
1388 compare_tag(svn_config
[i
].svn_path
);
1396 * We assume that the volume is already enabled and we can only
1397 * be changing the cluster tag. Anything else is an error.
1399 /* LINT - not static as fwcadm uses it */
1401 compare_one_sv(char *path
)
1404 sv_check_cluster(NULL
);
1405 sv_cfg_open(CFG_WRLOCK
);
1413 * Read all sets from the libdscfg configuration file, and store everything in
1416 * We assume that the config file has been opened & rewound for us. We store
1417 * the volume name as the key, and the setnumber where we found it as the data.
1419 * The caller can pass in a pointer to the maximum number of volumes, or
1420 * a pointer to NULL, specifying we want 'all' the volumes. The table is
1421 * searched using find_in_hash.
1426 char key
[CFG_MAX_KEY
], buf
[CFG_MAX_BUF
];
1427 char vol
[CFG_MAX_BUF
], cnode
[CFG_MAX_BUF
];
1431 if (hcreate((size_t)sv_max_devices
) == 0)
1432 error(NULL
, gettext("unable to create hash table"));
1434 for (setnumber
= 1; /* CSTYLED */; setnumber
++) {
1435 (void) snprintf(key
, sizeof (key
), "sv.set%d", setnumber
);
1436 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0)
1439 if (sscanf(buf
, "%s - %s", vol
, cnode
) != 2) {
1443 item
.key
= strdup(vol
);
1444 item
.data
= (void *)setnumber
;
1445 if (hsearch(item
, ENTER
) == NULL
) {
1447 gettext("unable to add entry to hash table"));
1453 * Function to search the hash for a specific volume. If it is found,
1454 * we return the set number. If it isn't found, we return -1
1457 find_in_hash(char *path
)
1459 ENTRY
*found_entry
, item
;
1464 if ((found_entry
= hsearch(item
, FIND
)) != NULL
) {
1465 retval
= (int)found_entry
->data
;
1472 * Just a wrapper to destory the hashtable. At some point in the future we
1473 * might want to do something more.... For instance, verify that the cfg
1474 * database and the kernel configuration match (?) Just an idea.
1483 * This function will remove a particular set from the config file.
1485 * We make a whole host of assumptions:
1486 * o the hashfile is up to date;
1487 * o The config file has been opened with a WRLOCK for us.
1490 remove_from_cfgfile(char *path
, int setnumber
)
1492 char key
[CFG_MAX_KEY
];
1496 /* attempt to remove the volume from config storage */
1497 (void) snprintf(key
, sizeof (key
), "sv.set%d", setnumber
);
1498 if (cfg_put_cstring(cfg
, key
, NULL
, 0) < 0) {
1499 warn(NULL
, gettext("unable to remove %s from "
1500 "config storage: %s"), path
, cfg_error(&sev
));
1502 if (implicit_tag
&& *implicit_tag
) {
1503 lcltag
= implicit_tag
;
1504 } else if (cfg_cluster_tag
&& *cfg_cluster_tag
) {
1505 lcltag
= cfg_cluster_tag
;
1509 if (cfg_rem_user(cfg
, path
, lcltag
, "sv") != CFG_USER_LAST
) {
1510 warn(NULL
, gettext("unable to remove %s from dsvol"),