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>
41 #include <sys/unistat/spcs_s.h>
42 #include <sys/unistat/spcs_s_u.h>
43 #include <sys/unistat/spcs_errors.h>
45 #include <sys/nsctl/sv.h>
46 #include <sys/nsctl/sv_impl.h>
48 #include <sys/nsctl/cfg.h>
51 static int sv_max_devices
;
58 static const caddr_t sv_rpath
= SV_DEVICE
;
64 static void resume_dev(int, sv_name_t
*);
65 static void suspend_dev(int, const caddr_t
);
66 static int read_libcfg(sv_name_t svn
[]);
67 static void resume_sv();
68 static void suspend_sv();
69 static void prepare_unload_sv();
73 * support for the special cluster tag "local" to be used with -C in a
74 * cluster for local volumes.
77 #define SV_LOCAL_TAG "local"
79 static caddr_t program
;
80 static caddr_t cfg_cluster_tag
;
86 (void) fprintf(stderr
, gettext("usage:\n"));
88 (void) fprintf(stderr
, gettext(
89 "\t%s -h help\n"), program
);
91 (void) fprintf(stderr
, gettext(
92 "\t%s [-C tag] -r resume all sv devices\n"), program
);
94 (void) fprintf(stderr
, gettext(
95 "\t%s [-C tag] -s suspend all sv devices\n"), program
);
97 (void) fprintf(stderr
, gettext(
98 "\t%s -u prepare for sv unload\n"), program
);
103 message(caddr_t prefix
, spcs_s_info_t
*status
, caddr_t string
, va_list ap
)
105 (void) fprintf(stderr
, "%s: %s: ", program
, prefix
);
106 (void) vfprintf(stderr
, string
, ap
);
107 (void) fprintf(stderr
, "\n");
110 spcs_s_report(*status
, stderr
);
111 spcs_s_ufree(status
);
117 error(spcs_s_info_t
*status
, caddr_t string
, ...)
120 va_start(ap
, string
);
122 message(gettext("error"), status
, string
, ap
);
130 warn(spcs_s_info_t
*status
, caddr_t string
, ...)
133 va_start(ap
, string
);
135 message(gettext("warning"), status
, string
, ap
);
148 if (sv_max_devices
> 0)
151 fd
= open(sv_rpath
, O_RDONLY
);
153 error(NULL
, gettext("unable to open %s: %s"),
154 sv_rpath
, strerror(errno
));
156 bzero(&svl
, sizeof (svl
));
157 bzero(&svn
[0], sizeof (svn
));
159 svl
.svl_names
= &svn
[0];
160 svl
.svl_error
= spcs_s_ucreate();
162 if (ioctl(fd
, SVIOC_LIST
, &svl
) < 0)
163 error(&svl
.svl_error
, gettext("unable to get max devs"));
165 spcs_s_ufree(&svl
.svl_error
);
166 sv_max_devices
= svl
.svl_maxdevs
;
173 sv_alloc_svnames(void)
175 sv_name_t
*svn
= NULL
;
179 svn
= calloc(sv_max_devices
, sizeof (*svn
));
181 error(NULL
, "unable to allocate %ld bytes of memory",
182 sv_max_devices
* sizeof (*svn
));
189 main(int argc
, char *argv
[])
193 int Cflag
, resume
, suspend
, unload
;
196 (void) setlocale(LC_ALL
, "");
197 (void) textdomain("svboot");
199 program
= strdup(basename(argv
[0]));
201 Cflag
= unload
= resume
= suspend
= 0;
203 while ((opt
= getopt(argc
, argv
, "C:hrsu")) != EOF
) {
209 gettext("-C specified multiple times"));
216 cfg_cluster_tag
= optarg
;
235 case '?': /* FALLTHRU */
249 if ((resume
+ suspend
+ unload
) > 1) {
250 warn(NULL
, gettext("-r , -s and -u are mutually exclusive"));
255 if (!resume
&& !suspend
&& !unload
) {
256 warn(NULL
, gettext("option required"));
261 if (optind
!= argc
) {
268 * Check for the special (local) cluster tag
271 if (cfg_cluster_tag
!= NULL
&&
272 strcmp(cfg_cluster_tag
, SV_LOCAL_TAG
) == 0)
273 cfg_cluster_tag
= "-";
298 svn
= sv_alloc_svnames();
300 index
= read_libcfg(svn
);
302 fd
= open(sv_rpath
, O_RDONLY
);
304 warn(NULL
, gettext("unable to open %s: %s"),
305 svn
->svn_path
, strerror(errno
));
309 for (cnt
= 0; cnt
< index
; cnt
++) {
312 * Check for more data.
314 if (svn
[cnt
].svn_path
[0] == '\0') {
316 * This was set when reading sv.conf. After the last
317 * line svn_path was set to \0, so we are finished.
318 * We shouldn't get here, but put this in just in
323 resume_dev(fd
, &svn
[cnt
]);
330 resume_dev(int fd
, sv_name_t
*svn
)
335 bzero(&svc
, sizeof (svc
));
337 if (stat(svn
->svn_path
, &stb
) != 0) {
338 warn(NULL
, gettext("unable to access %s: %s"),
339 svn
->svn_path
, strerror(errno
));
343 svc
.svc_major
= major(stb
.st_rdev
);
344 svc
.svc_minor
= minor(stb
.st_rdev
);
345 (void) strncpy(svc
.svc_path
, svn
->svn_path
, sizeof (svc
.svc_path
));
347 svc
.svc_flag
= svn
->svn_mode
;
348 svc
.svc_error
= spcs_s_ucreate();
350 if (ioctl(fd
, SVIOC_ENABLE
, &svc
) < 0) {
351 spcs_log("sv", &svc
.svc_error
,
352 gettext("%s: unable to resume %s"),
353 program
, svn
->svn_path
);
355 warn(&svc
.svc_error
, gettext("unable to resume %s"),
360 spcs_log("sv", NULL
, gettext("%s: resume %s"),
361 program
, svn
->svn_path
);
363 spcs_s_ufree(&svc
.svc_error
);
368 * This routine parses the config file and
369 * stores the data in the svn array. The return value is the number
370 * of entries read from conf_file. If an error occurs the error()
371 * routine is called (which exits the program).
374 read_libcfg(sv_name_t svn
[])
376 char rdev
[CFG_MAX_BUF
];
377 char key
[CFG_MAX_KEY
];
381 int index
= 0; /* Current location in svn array */
382 sv_name_t
*cur_svn
; /* Pointer to svn[index] */
385 if ((cfg
= cfg_open("")) == NULL
) {
386 error(NULL
, gettext("Error opening config: %s"),
390 cfg_resource(cfg
, cfg_cluster_tag
);
391 if (!cfg_lock(cfg
, CFG_RDLOCK
)) {
392 error(NULL
, gettext("Error locking config: %s"),
396 for (i
= 0; /*CSTYLED*/; i
++) {
399 bzero(rdev
, CFG_MAX_BUF
);
400 (void) snprintf(key
, sizeof (key
), "sv.set%d.vol", setnumber
);
401 if (cfg_get_cstring(cfg
, key
, rdev
, sizeof (rdev
)) < 0)
404 /* Check to see if the raw device is present */
405 if (stat(rdev
, &stb
) != 0) {
406 warn(NULL
, gettext("unable to access %s: %s"),
407 rdev
, strerror(errno
));
411 if (!S_ISCHR(stb
.st_mode
)) {
412 warn(NULL
, gettext("%s is not a character device"),
417 cur_svn
= &svn
[index
]; /* For easier reading below */
419 if (strlen(rdev
) >= sizeof (cur_svn
->svn_path
)) {
421 "raw device name (%s) longer than %d characters"),
423 (sizeof (cur_svn
->svn_path
) - 1));
427 (void) strcpy(cur_svn
->svn_path
, rdev
);
428 cur_svn
->svn_mode
= (NSC_DEVICE
| NSC_CACHE
);
435 /* Set the last path to NULL */
436 svn
[index
].svn_path
[0] = '\0';
443 suspend_dev(int fd
, const caddr_t path
)
448 if (stat(path
, &stb
) < 0) {
449 svc
.svc_major
= (major_t
)-1;
450 svc
.svc_minor
= (minor_t
)-1;
452 svc
.svc_major
= major(stb
.st_rdev
);
453 svc
.svc_minor
= minor(stb
.st_rdev
);
456 (void) strcpy(svc
.svc_path
, path
);
457 svc
.svc_error
= spcs_s_ucreate();
459 if (ioctl(fd
, SVIOC_DISABLE
, &svc
) < 0) {
460 if (errno
!= SV_EDISABLED
) {
461 spcs_log("sv", &svc
.svc_error
,
462 gettext("%s: unable to suspend %s"),
466 gettext("unable to suspend %s"), path
);
471 spcs_log("sv", NULL
, gettext("%s: suspend %s"), program
, path
);
473 spcs_s_ufree(&svc
.svc_error
);
480 sv_name_t
*svn
, *svn_system
; /* Devices in system */
481 sv_list_t svl_system
;
485 svn_system
= sv_alloc_svnames();
487 svl_system
.svl_count
= read_libcfg(svn_system
);
489 if ((fd
= open(sv_rpath
, O_RDONLY
)) < 0) {
490 warn(NULL
, gettext("unable to open %s: %s"),
491 sv_rpath
, strerror(errno
));
495 for (i
= 0; i
< svl_system
.svl_count
; i
++) {
496 if (*svn_system
[i
].svn_path
== '\0')
499 svn
= &svn_system
[i
];
500 suspend_dev(fd
, svn
->svn_path
);
508 * Check kernel's sv_ndevices and thread sets,
509 * if empty then change kernel state to allow unload,
510 * and sleep SV_WAIT_UNLAOD (10 seconds).
512 * Only called in pkgrm time.
515 prepare_unload_sv(void)
520 if ((fd
= open(sv_rpath
, O_RDONLY
)) < 0) {
521 warn(NULL
, gettext("unable to open %s: %s"),
522 sv_rpath
, strerror(errno
));
526 if (ioctl(fd
, SVIOC_UNLOAD
, &rc
) < 0)
527 error(NULL
, gettext("unable to unload"));
530 error(NULL
, gettext("still has active devices or threads"));