iiboot.c revision 570de38f63910201fdd77246630b7aa8f9dc5661
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <locale.h>
#include <langinfo.h>
#include <libintl.h>
#include <stdarg.h>
#include <ctype.h>
#define MAX_PROCESSES 64
int parseopts(int, char **, int *);
int read_resume_cfg();
int read_suspend_cfg();
void iiboot_usage(void);
extern char *basename(char *);
dsw_config_t *resume_list = 0;
dsw_ioctl_t *suspend_list = 0;
int n_structs;
char *program;
char *cfg_cluster_tag = NULL;
volatile int fork_cnt;
volatile int fork_rc;
static void
{
if (status) {
} else {
}
}
}
static void
{
exit(1);
}
static void
{
}
/* ARGSUSED */
static void
{
int wait_loc = 0;
;
/*EMPTY*/
} else {
}
if (fork_cnt > 0)
--fork_cnt;
}
int
#ifdef lint
#else
#endif
{
int pairs;
int flag = 0;
int i, j;
int rc;
int ioctl_fd;
void *ioarg;
dsw_list_t args = {0};
int max_processes = MAX_PROCESSES;
(void) textdomain("ii");
gettext("Failed to open Point-in-Time Copy control "
"device"));
}
return (1);
if (flag == DSWIOC_RESUME)
pairs = read_resume_cfg();
else
pairs = -1;
if (pairs == 0) {
#ifdef DEBUG
gettext("Config contains no Point-in-Time Copy sets"));
#endif
return (0);
}
}
return (0);
"iiboot resume cluster %s failed", cfg_cluster_tag);
return (-1);
}
return (0);
/*
* If we are running in a Sun Cluster, this is a resume
* operation, get a list of all shadow volumes, where the
* shadow volumes match the shadows of the sets being resumed
*/
if (rc == -1) {
"iiboot get LIST failed, errno %d", errno);
gettext("Failed to get LIST of Point-in-Time "
"sets"));
return (-1);
}
gettext("Failed to allocate memory"));
}
}
/* Remove all elements that are not in the resume list */
for (i = 0; i < pairs; i++) {
resume_list[i].shadow_vol) == 0) {
lp++;
break;
}
}
}
if (i != pairs)
continue;
}
}
for (i = 0; i < pairs; i++) {
ustatus = spcs_s_ucreate();
if (flag == DSWIOC_RESUME) {
} else {
}
perror("fork");
/* back off on the max processes and try again */
if (fork_cnt > 0) {
(void) pause();
}
}
if (pid > 0) { /* this is parent process */
++fork_cnt;
while (fork_cnt > MAX_PROCESSES) {
(void) pause();
}
continue;
}
if (rc == SPCS_S_ERROR) {
if (flag == DSWIOC_RESUME)
"iiboot resume %s failed",
else
"iiboot suspend %s failed",
ii_iop->shadow_vol);
}
/* Resuming child */
if (flag == DSWIOC_RESUME)
exit(0);
}
/*
* Allow all processes to finish up before exiting
* Set rc for success
*/
while (fork_cnt > 0) {
(void) pause();
}
(void) alarm(0);
/* Disable duplicate shadows that were part of the implicit join */
int setno;
if (pid == -1) {
return (errno);
} else if (pid > 0) {
return (0); /* Parent, OK exit */
}
setno = 0;
while (++setno) {
/*
* Open the configuration database
*/
return (-1);
}
/* Sooner or later, this lock will be free */
(void) sleep(2);
break;
}
/* For imported shadows, master must be special tag */
/*
* For this record to be processed, the shadow volume
* name must match and the cluster tag must be blank
*/
continue;
}
/* Derrive local cluster tag */
else
"Failed to device group for shadow %s"),
lp->shadow_vol);
/* disable master volume if not imported */
"ii") < 0)
"SV disable of master failed"));
/*
* Delete the Imported Shadow set
*/
"Failed to delete Imported shadow %s"),
lp->shadow_vol);
}
/*
* SV disable shadow volume
*/
"SV disable of shadow failed"));
/*
* Commit the delete
*/
(void) cfg_commit(cfg);
/*
* Open the configuration database
*/
return (-1);
}
/* Sooner or later, this lock will be free */
(void) sleep(2);
/* Set cluster tag for Shadow volume */
/*
* Commit the delete
*/
(void) cfg_commit(cfg);
}
}
}
return (fork_rc);
}
static int
set_is_offline(char *cflags)
{
unsigned int flags;
int conv;
return (0);
/* convert flags to an int */
}
/*
* read_resume_cfg()
*
* DESCRIPTION: Read the relevant config info via libcfg
*
* Outputs:
* int i Number of Point-in-Time Copy sets
*
* Side Effects: The 0 to i-1 entries in the resume_list are filled.
*
*/
int
{
int i;
int valid_sets;
dsw_config_t *p;
static int offset = sizeof (NSKERN_II_BMP_OPTION);
errno);
}
errno);
}
/* Determine number of set, if zero return 0 */
return (0);
if (resume_list == NULL) {
errno);
}
valid_sets = 0;
p = resume_list;
for (i = 0; i < n_structs; i++) {
if (ctag)
break;
/* If cluster tags don't match, skip record */
continue;
}
continue;
}
if (ctag)
++p;
++valid_sets;
}
while (i < n_structs)
if (entry)
return (valid_sets);
}
/*
* read_suspend_cfg()
*
* DESCRIPTION: Read the relevant config info via libcfg
*
* Outputs:
* int i Number of Point-in-Time Copy sets
*
* Side Effects: The 0 to i-1 entries in the suspend_list are filled.
*
*/
int
{
int rc;
int i;
char buf[CFG_MAX_BUF];
char key[CFG_MAX_KEY];
int setnumber;
dsw_ioctl_t *p;
if (cfg_cluster_tag == NULL) {
return (1);
}
errno);
}
errno);
}
/*CSTYLED*/
for (i = 0; ; i++) {
setnumber = i + 1;
if (rc < 0)
break;
n_structs += 2;
sizeof (*suspend_list) * n_structs);
if (suspend_list == NULL) {
"iiboot suspend realloc failed, errno %d",
errno);
}
}
p = suspend_list + i;
}
return (i);
}
int
int argc;
char **argv;
int *flag;
{
int errflag = 0;
int Cflag = 0;
char c;
char inval = 0;
switch (c) {
case 'C':
if (Cflag) {
gettext("-C specified multiple times"));
iiboot_usage();
return (-1);
}
Cflag++;
break;
case 'h':
iiboot_usage();
exit(0);
/* NOTREACHED */
case 'r':
if (*flag)
inval = 1;
*flag = DSWIOC_RESUME;
break;
case 's':
if (*flag)
inval = 1;
*flag = DSWIOC_SUSPEND;
break;
case '?':
errflag++;
}
}
if (inval) {
errflag = 1;
}
iiboot_usage();
return (-1);
}
return (0);
}
void
{
program);
}