summaryrefslogtreecommitdiff
path: root/usr/src/lib/lvm/libsvm/common
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/lvm/libsvm/common
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/lvm/libsvm/common')
-rw-r--r--usr/src/lib/lvm/libsvm/common/check_svm.c169
-rw-r--r--usr/src/lib/lvm/libsvm/common/debug.c76
-rw-r--r--usr/src/lib/lvm/libsvm/common/getdrvname.c90
-rw-r--r--usr/src/lib/lvm/libsvm/common/hdrs/libsvm.h70
-rw-r--r--usr/src/lib/lvm/libsvm/common/hdrs/svm.h95
-rw-r--r--usr/src/lib/lvm/libsvm/common/metaconf.c195
-rw-r--r--usr/src/lib/lvm/libsvm/common/metainterfaces.c490
-rw-r--r--usr/src/lib/lvm/libsvm/common/modops.c120
-rw-r--r--usr/src/lib/lvm/libsvm/common/start_svm.c284
-rw-r--r--usr/src/lib/lvm/libsvm/common/update_mdconf.c379
10 files changed, 1968 insertions, 0 deletions
diff --git a/usr/src/lib/lvm/libsvm/common/check_svm.c b/usr/src/lib/lvm/libsvm/common/check_svm.c
new file mode 100644
index 0000000000..5c92ac2788
--- /dev/null
+++ b/usr/src/lib/lvm/libsvm/common/check_svm.c
@@ -0,0 +1,169 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <meta.h>
+#include <sys/types.h>
+#include <sys/mkdev.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <svm.h>
+
+/*
+ * FUNCTION: valid_bootlist
+ *
+ * INPUT: file pointer, line buffer, line_length
+ *
+ * RETURN VALUES:
+ * 0 - SUCCESS
+ * -1 - FAIL
+ *
+ */
+
+int
+valid_bootlist(FILE *fp, int line_len)
+{
+ char *bp = NULL;
+ char *line;
+
+ /*
+ * errno may not be cleared by callee routines and we
+ * we want to catch fgets failures hence errno is reset.
+ */
+ errno = 0;
+ if ((line = malloc(line_len)) == NULL)
+ return (RET_ERROR);
+
+ while (fgets(line, line_len, fp) != NULL) {
+ bp = strstr(line, "mddb_bootlist");
+ if (bp != NULL) {
+ /* if not commented out then breakout */
+ if (*line != '*' && *line != '#') {
+ break;
+ }
+ }
+ }
+
+ free(line);
+ if (bp == NULL || errno != 0)
+ return (RET_ERROR);
+
+ return (RET_SUCCESS);
+}
+
+/*
+ * FUNCTION: svm_check
+ * Check the existance of DiskSuite or SVM
+ *
+ * INPUT: rootpath
+ *
+ * RETURN VALUES:
+ * 0 - SUCCESS
+ * -1 - FAIL
+ */
+
+int
+svm_check(char *path)
+{
+ FILE *fp;
+ char tmppath[PATH_MAX];
+ int rval;
+
+ (void) strcat(strcpy(tmppath, path), MD_CONF);
+
+ if ((fp = fopen(tmppath, "r")) == NULL) {
+ rval = errno;
+ goto free_exit;
+ }
+
+ rval = valid_bootlist(fp, MDDB_BOOTLIST_MAX_LEN);
+
+ debug_printf("svm_check(): valid bootlist in %s. status %d\n",
+ tmppath, rval);
+
+ if (rval == RET_SUCCESS) {
+ goto free_exit;
+ }
+ (void) fclose(fp);
+
+ /* not found in md.conf try etc/system */
+ (void) strcat(strcpy(tmppath, path), SYSTEM_FILE);
+
+ if ((fp = fopen(tmppath, "r")) == NULL) {
+ rval = errno;
+ goto free_exit;
+ }
+
+ rval = valid_bootlist(fp, MDDB_BOOTLIST_MAX_LEN);
+
+ debug_printf("svm_check(): valid bootlist in %s. status %d\n",
+ tmppath, rval);
+free_exit:
+ (void) fclose(fp);
+ if (rval > 0)
+ rval = RET_ERROR;
+ return (rval);
+}
+
+/*
+ * FUNCTION: svm_is_md
+ * Check if the the given device name has an md driver.
+ * INPUT: special device name (/dev/dsk/c0t0d0s0 or /dev/md/dsk/d10)
+ *
+ * RETURN:
+ * 1 - if it is a metadevice.
+ * 0 - if it is not a metadevice.
+ */
+
+int
+svm_is_md(char *device_name)
+{
+ char buf[30];
+ struct stat sbuf;
+ int rval = 0;
+
+ (void) memset(buf, 0, 30);
+
+ debug_printf("svm_is_md(): device %s\n", device_name);
+ if (stat(device_name, &sbuf) != 0)
+ return (RET_ERROR);
+
+ if (get_drv_name(major(sbuf.st_rdev), "/", buf) == RET_ERROR) {
+ debug_printf("svm_is_md(): device get_drv_name failed: %s\n",
+ device_name);
+ return (0);
+ }
+ if (strcmp(buf, MD_MODULE) == 0) {
+ debug_printf("svm_is_md(): device %s succeed\n", device_name);
+ rval = 1;
+ }
+ return (rval);
+}
diff --git a/usr/src/lib/lvm/libsvm/common/debug.c b/usr/src/lib/lvm/libsvm/common/debug.c
new file mode 100644
index 0000000000..38f7ae56cc
--- /dev/null
+++ b/usr/src/lib/lvm/libsvm/common/debug.c
@@ -0,0 +1,76 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+/* The following defines are for tracing output (from libsmpicommon) */
+
+#define LOG 0x1 /* write message to log file */
+#define SCR 0x2 /* write message to the screen */
+#define LOGSCR LOG|SCR /* write message to the log and screen */
+#define LEVEL0 0x0001 /* message level 0 */
+#define LEVEL1 0x0002 /* message level 1 */
+#define LEVEL2 0x0004 /* message level 2 */
+#define LEVEL3 0x0010 /* message level 3 */
+
+extern int get_trace_level(void);
+extern int write_status(unsigned char, unsigned int, char *, ...);
+
+const char libsvm_str[] = "LIB_SVM: ";
+const int libsvm_len = sizeof (libsvm_str);
+
+/*PRINTFLIKE1*/
+void
+debug_printf(char *fmt, ...)
+{
+ va_list ap;
+ char *cp;
+ char *buf;
+
+ if (get_trace_level() > 5) {
+ if ((buf = calloc(PATH_MAX, sizeof (char))) == NULL)
+ return;
+ (void) strcpy(buf, libsvm_str);
+ /*
+ * libsvm_len - 1 is because the length includes NULL
+ */
+
+ cp = buf + (libsvm_len - 1);
+ va_start(ap, fmt);
+ if (vsnprintf(cp, (PATH_MAX - (libsvm_len - 1)),
+ fmt, ap) >= 0) {
+ write_status(LOGSCR, LEVEL0, buf);
+ }
+ free(buf);
+ va_end(ap);
+ }
+}
diff --git a/usr/src/lib/lvm/libsvm/common/getdrvname.c b/usr/src/lib/lvm/libsvm/common/getdrvname.c
new file mode 100644
index 0000000000..9bef7fa115
--- /dev/null
+++ b/usr/src/lib/lvm/libsvm/common/getdrvname.c
@@ -0,0 +1,90 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <svm.h>
+
+/*
+ * Macros to produce a quoted string containing the value of a
+ * preprocessor macro. For example, if SIZE is defined to be 256,
+ * VAL2STR(SIZE) is "256". This is used to construct format
+ * strings for scanf-family functions below.
+ */
+#define QUOTE(x) #x
+#define VAL2STR(x) QUOTE(x)
+
+/*
+ * FUNCTION:
+ * Return the driver name for a major number
+ *
+ * INPUT: major number, mount point for name_to_major file, pointer
+ * to a valid buffer.
+ *
+ * RETURN VALUES:
+ * 0 - SUCCESS - buf contain the driver name.
+ * -1 - FAIL
+ *
+ */
+
+int
+get_drv_name(major_t major, char *mnt, char *buf)
+{
+ FILE *fp;
+ char drv[FILENAME_MAX + 1];
+ char entry[FILENAME_MAX + 1];
+ char line[MAX_N2M_ALIAS_LINE];
+ char fname[PATH_MAX];
+
+ int status = RET_NOERROR;
+ (void) snprintf(fname, sizeof (fname), "%s%s", mnt, NAME_TO_MAJOR);
+
+ if ((fp = fopen(fname, "r")) == NULL) {
+ return (RET_ERROR);
+ }
+
+ while ((fgets(line, sizeof (line), fp) != NULL) &&
+ status == RET_NOERROR) {
+ if (sscanf(line,
+ "%" VAL2STR(FILENAME_MAX) "s %" VAL2STR(FILENAME_MAX) "s",
+ drv, entry) != 2) {
+ status = RET_ERROR;
+ }
+ if (atoi(entry) == major)
+ break;
+
+ }
+
+ if (status == RET_NOERROR)
+ (void) strcpy(buf, drv);
+ (void) fclose(fp);
+ return (status);
+}
diff --git a/usr/src/lib/lvm/libsvm/common/hdrs/libsvm.h b/usr/src/lib/lvm/libsvm/common/hdrs/libsvm.h
new file mode 100644
index 0000000000..98c13a2684
--- /dev/null
+++ b/usr/src/lib/lvm/libsvm/common/hdrs/libsvm.h
@@ -0,0 +1,70 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBSVM_H
+#define _LIBSVM_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * The following declarations are for libsvm which provides
+ * Solaris Install with a set of interfaces required to upgrade
+ * mirrored roots. These are controlled by a Contract PSARC 2000/049
+ * and should not be changed without informing Install.
+ */
+
+typedef struct {
+ char *root_md; /* metaroot device name */
+ int count; /* number of components in the metadevice */
+ char *md_comps[1]; /* array of "ctds" component names */
+} svm_info_t;
+
+/* Convertion of MDDB flags */
+#define SVM_DONT_CONV 0x01 /* Don't convert MDDB to devid mode */
+#define SVM_CONV 0x02 /* Convert MDDB to devid mode */
+
+
+extern int svm_check(char *rootpath);
+extern int svm_start(char *rootpath, svm_info_t **svm_infopp,
+ int repl_state_flag);
+extern int svm_stop();
+extern void svm_free(svm_info_t *svm_infop);
+extern int svm_is_md(char *device_name);
+extern int svm_get_components(char *root_md_device, svm_info_t **svmpp);
+extern svm_info_t *svm_alloc();
+extern int get_mdcomponents(char *devname, svm_info_t **pp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBSVM_H */
diff --git a/usr/src/lib/lvm/libsvm/common/hdrs/svm.h b/usr/src/lib/lvm/libsvm/common/hdrs/svm.h
new file mode 100644
index 0000000000..cb5d60f30f
--- /dev/null
+++ b/usr/src/lib/lvm/libsvm/common/hdrs/svm.h
@@ -0,0 +1,95 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#ifndef _SVM_H
+#define _SVM_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define RET_SUCCESS 0
+#define RET_ERROR -1
+#define RET_NOERROR RET_SUCCESS
+
+
+#define PROP_KEEP_REPL_STATE "md_keep_repl_state"
+#define PROP_DEVID_DESTROY "md_devid_destroy"
+
+#define MD_CONF "/kernel/drv/md.conf"
+#define MD_CONF_ORIG "/tmp/md.conf.orig"
+#define SYSTEM_FILE "/etc/system"
+#define NAME_TO_MAJOR "/etc/name_to_major"
+#define VFSTAB "/etc/vfstab"
+
+#define MD_MODULE "md"
+#define ROOT_MNTPT "/"
+#define ROOT_METADEVICE "/dev/md/dsk/"
+
+
+typedef enum {
+ MD_STR_NOTFOUND, /* bootlist not found */
+ MD_STR_START, /* bootlist found, convertion started */
+ MD_STR_DONE /* bootlist converversion done */
+} convflag_t;
+
+/* The following defines have been taken from addrem.h */
+#define MAX_CMD_LINE 256
+#define MAX_N2M_ALIAS_LINE FILENAME_MAX + FILENAME_MAX + 1
+#define MAXLEN_NAM_TO_MAJ_ENT FILENAME_MAX + MAX_STR_MAJOR + 1
+#define OPT_LEN 128
+#define CADDR_HEX_STR 16
+#define UINT_STR 10
+#define MODLINE_ENT_MAX (4 * UINT_STR) + CADDR_HEX_STR + MODMAXNAMELEN
+#define MAX_STR_MAJOR UINT_STR
+#define STR_LONG 10
+#define PERM_STR 4
+#define MAX_PERM_ENTRY (2 * STR_LONG) + PERM_STR + (2 * FILENAME_MAX) + 1
+#define MAX_DBFILE_ENTRY MAX_PERM_ENTRY
+
+extern void create_diskset_links();
+extern int copyfile(char *from, char *to);
+extern int get_drv_name(major_t major, char *file_name, char *buf);
+extern int mod_unload(char *modname);
+extern int valid_bootlist(FILE *fp, int line_size);
+extern int convert_bootlist(char *systemfile, char *mdconf, char **tmpfilename);
+extern int write_xlate_to_mdconf(char *rootpath);
+extern int write_targ_nm_table(char *rootpath);
+extern int get_rootmetadevice(char *rootpath, char **devname);
+extern void set_upgrade_prop(char *prop_name, int val);
+extern int is_upgrade_prop(char *prop_name);
+extern int create_in_file_prop(char *prop_name, char *fname);
+extern void debug_printf(char *fmt, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SVM_H */
diff --git a/usr/src/lib/lvm/libsvm/common/metaconf.c b/usr/src/lib/lvm/libsvm/common/metaconf.c
new file mode 100644
index 0000000000..504f38ba73
--- /dev/null
+++ b/usr/src/lib/lvm/libsvm/common/metaconf.c
@@ -0,0 +1,195 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/mkdev.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <limits.h>
+#include <string.h>
+#include <libsvm.h>
+#include <svm.h>
+#include <errno.h>
+
+
+#define VERSION "1.0"
+#define DISK_DIR "/dev/rdsk"
+
+extern int _map_to_effective_dev();
+
+int
+is_blankline(char *buf)
+{
+ for (; *buf != 0; buf++) {
+ if (!isspace(*buf))
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * FUNCTION: write_targ_nm_table
+ * creates a tuple table of <driver name, major number > in md.conf
+ * INPUT: rootpath
+ *
+ * RETURN VALUES:
+ * RET_SUCCESS
+ * RET_ERROR
+ */
+
+int
+write_targ_nm_table(char *path)
+{
+ FILE *targfp = NULL;
+ FILE *mdfp = NULL;
+ char buf[PATH_MAX], *cp;
+ int retval = RET_SUCCESS;
+ int first_entry = 1;
+
+ if ((mdfp = fopen(MD_CONF, "a")) == NULL)
+ return (RET_ERROR);
+
+ (void) snprintf(buf, sizeof (buf), "%s%s", path, NAME_TO_MAJOR);
+
+ if ((targfp = fopen(buf, "r")) == NULL) {
+ (void) fclose(mdfp);
+ return (RET_ERROR);
+ }
+
+ while (fgets(buf, PATH_MAX, targfp) != NULL &&
+ (retval == RET_SUCCESS)) {
+ cp = strrchr(buf, '\n');
+ *cp = 0;
+ if (is_blankline(buf))
+ continue;
+ if (first_entry) {
+ if (fprintf(mdfp, "md_targ_nm_table=\"%s\"", buf) < 0)
+ retval = RET_ERROR;
+ first_entry = 0;
+ }
+ if (fprintf(mdfp, ",\"%s\"", buf) < 0)
+ retval = RET_ERROR;
+ }
+ if (!first_entry)
+ if (fprintf(mdfp, ";\n") < 0)
+ retval = RET_ERROR;
+ (void) fclose(mdfp);
+ (void) fclose(targfp);
+ return (retval);
+}
+
+/*
+ * FUNCTION: write_xlate_to_mdconf
+ * creates a tuple table of <miniroot devt, target devt> in md.conf
+ * INPUT: rootpath
+ *
+ * RETURN VALUES:
+ * RET_SUCCESS
+ * RET_ERROR
+ */
+
+int
+write_xlate_to_mdconf(char *path)
+{
+ FILE *fptr = NULL;
+ struct dirent *dp;
+ DIR *dirp;
+ struct stat statb_dev;
+ struct stat statb_edev;
+ char *devname;
+ char edevname[PATH_MAX];
+ char targname[PATH_MAX];
+ char diskdir[PATH_MAX];
+ int first_devid = 1;
+ int ret = RET_SUCCESS;
+
+ if ((fptr = fopen(MD_CONF, "a")) == NULL) {
+ return (RET_ERROR);
+ }
+
+
+ (void) snprintf(diskdir, sizeof (diskdir), "%s%s", path, DISK_DIR);
+ if ((dirp = opendir(diskdir)) == NULL) {
+ (void) fclose(fptr);
+ return (RET_ERROR);
+ }
+
+ /* special case to write the first tuple in the table */
+ while (((dp = readdir(dirp)) != (struct dirent *)0) &&
+ (ret != RET_ERROR)) {
+ if ((strcmp(dp->d_name, ".") == 0) ||
+ (strcmp(dp->d_name, "..") == 0))
+ continue;
+
+ if ((strlen(diskdir) + strlen(dp->d_name) + 2) > PATH_MAX) {
+ continue;
+ }
+
+ (void) snprintf(targname, sizeof (targname), "%s/%s",
+ diskdir, dp->d_name);
+
+ if (stat(targname, &statb_dev) != 0) {
+ continue;
+ }
+
+ if ((devname = strstr(targname, DISK_DIR)) == NULL) {
+ continue;
+ }
+
+ if (_map_to_effective_dev((char *)devname, (char *)&edevname)
+ != 0) {
+ continue;
+ }
+
+ if (stat(edevname, &statb_edev) != 0) {
+ continue;
+ }
+
+ if (first_devid) {
+ if (fprintf(fptr, "md_xlate_ver=\"%s\";\n"
+ "md_xlate=%lu,%lu", VERSION,
+ statb_edev.st_rdev, statb_dev.st_rdev) < 0)
+ ret = RET_ERROR;
+ first_devid = 0;
+ }
+ if (fprintf(fptr, ",%lu,%lu", statb_edev.st_rdev,
+ statb_dev.st_rdev) < 0)
+ ret = RET_ERROR;
+ } /* end while */
+
+ if (!first_devid)
+ if (fprintf(fptr, ";\n") < 0)
+ ret = RET_ERROR;
+ (void) fclose(fptr);
+ (void) closedir(dirp);
+ return (ret);
+}
diff --git a/usr/src/lib/lvm/libsvm/common/metainterfaces.c b/usr/src/lib/lvm/libsvm/common/metainterfaces.c
new file mode 100644
index 0000000000..20746d4b58
--- /dev/null
+++ b/usr/src/lib/lvm/libsvm/common/metainterfaces.c
@@ -0,0 +1,490 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/vfstab.h>
+#include <meta.h>
+#include <libsvm.h>
+#include <svm.h>
+#include <sdssc.h>
+
+
+extern int mod_unload(char *modname);
+static int inited = 0;
+
+/*
+ * FUNCTION: init_metalib
+ * initialize libmeta only once.
+ *
+ * RETURN VALUES:
+ * 0 - SUCCESS
+ * -1 - FAIL
+ */
+
+static int
+init_metalib()
+{
+ int largc = 1;
+ char *largv = "libsvm";
+ md_error_t status = mdnullerror;
+
+ if (!inited) {
+ if (md_init_nosig(largc, &largv, 0, 1, &status) != 0 ||
+ meta_check_root(&status) != 0) {
+ return (-1);
+ }
+ inited = 1;
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * FUNCTION: reset_metalib
+ *
+ * INPUT: ptr to md_error_t
+ */
+
+static void
+reset_metalib(md_error_t *ep)
+{
+ inited = 0;
+ (void) close_admin(ep);
+}
+
+/*
+ * FUNCTION: metahalt
+ * halt the metadb
+ *
+ */
+
+static void
+metahalt()
+{
+ mdsetname_t *sp;
+ md_error_t status = mdnullerror;
+
+ (void) init_metalib();
+ if ((sp = metasetname(MD_LOCAL_NAME, &status)) == NULL) {
+ return;
+ }
+ if (meta_lock(sp, TRUE, &status)) {
+ return;
+ }
+ if (metaioctl(MD_HALT, NULL, &status, NULL) != 0) {
+ debug_printf("metahalt(): errno %d\n",
+ status.info.md_error_info_t_u.sys_error.errnum);
+ }
+ (void) meta_unlock(sp, &status);
+ reset_metalib(&status);
+}
+
+/*
+ * FUNCTION: svm_stop
+ * Halt the SDS/SVM configuration and unload md module.
+ *
+ * RETURN VALUES:
+ * 0 - SUCCESS
+ * RET_ERROR
+ */
+
+#define MAX_TIMEOUT 1800
+int
+svm_stop()
+{
+ int rval = RET_SUCCESS;
+ int timeval = 0;
+ int sleep_int = 5;
+
+ metahalt();
+
+ if ((rval = mod_unload(MD_MODULE)) != 0) {
+ timeval += sleep_int;
+ (void) sleep(sleep_int);
+ while (timeval < MAX_TIMEOUT) {
+ if ((rval = mod_unload(MD_MODULE)) == 0) {
+ debug_printf("svm_stop(): mod_unload succeeded."
+ " Time %d\n", timeval);
+
+ break;
+ }
+
+ debug_printf("svm_stop(): mod_unload failed. Trying "
+ "in %d s (%d)\n", sleep_int, timeval);
+
+ timeval += sleep_int;
+ (void) sleep(sleep_int);
+ metahalt();
+ }
+
+ if (rval != 0) {
+ rval = RET_ERROR;
+ debug_printf("svm_stop(): mod_unload FAILED!\n");
+ }
+ }
+
+ return (rval);
+}
+
+/*
+ * FUNCTION: get_rootmetadevice
+ * parses the vfstab to return the metadevice
+ *
+ * INPUT:
+ * mount point
+ * mdname - pointer to string pointer that will contain the
+ * metadevice name. Caller must free the allocated space.
+ * RETURN VALUES:
+ * mdname - md root device name
+ * 0 - SUCCESS
+ * !0 - FAIL
+ * > 0 errno
+ * RET_ERROR
+ */
+
+int
+get_rootmetadevice(char *mntpath, char **mdname)
+{
+ struct vfstab v;
+ FILE *fp;
+ int rval = RET_SUCCESS;
+ char *cp;
+ char vfstab_name[PATH_MAX + 1];
+
+ if (mdname == NULL)
+ return (EINVAL);
+
+ *mdname = NULL;
+
+ if (snprintf(vfstab_name, PATH_MAX + 1, "%s%s", mntpath, VFSTAB) < 0)
+ return (ENOMEM);
+
+ debug_printf("get_rootmetadevice(): mntpath %s %s\n", mntpath,
+ vfstab_name);
+
+ if ((fp = fopen(vfstab_name, "r")) == NULL) {
+ rval = errno;
+ return (rval);
+ }
+
+ if ((rval = getvfsfile(fp, &v, ROOT_MNTPT)) != 0) {
+ goto out;
+ }
+
+
+ debug_printf("get_rootmetadevice(): vfs_special %s\n", v.vfs_special);
+ if (strstr(v.vfs_special, ROOT_METADEVICE) == NULL) {
+ /* md device not found */
+ rval = RET_ERROR;
+ goto out;
+ }
+
+ /* found a match fill it and return */
+ cp = v.vfs_special + strlen(ROOT_METADEVICE);
+
+ *mdname = (char *)malloc(strlen(cp) + 1);
+
+ if (*mdname == NULL) {
+ rval = ENOMEM;
+ goto out;
+ }
+ (void) strcpy(*mdname, cp);
+ debug_printf("get_rootmetadevice(): *mdname %s rval %d\n",
+ *mdname, rval);
+out:
+ (void) fclose(fp);
+ return (rval);
+}
+
+/*
+ * FUNCTION: create_diskset_links
+ * Create the diskset name symlinks in /dev/md from the diskset
+ * names found in the set records. These are normally created
+ * in rpc.metad when you create the set but those symlinks are
+ * sitting out on the real system disk and we're running off the
+ * devfs that got created when we booted off the install image.
+ */
+
+void
+create_diskset_links()
+{
+ int max_sets;
+ int i;
+ md_error_t error = mdnullerror;
+
+ /*
+ * Resolve the function pointers for libsds_sc so that we can
+ * snarf the set records.
+ */
+ (void) sdssc_bind_library();
+ (void) init_metalib();
+
+ if ((max_sets = get_max_sets(&error)) == 0) {
+ debug_printf("create_diskset_links(): get_max_sets failed\n");
+ mdclrerror(&error);
+ return;
+ }
+
+ for (i = 1; i < max_sets; i++) {
+ md_set_record *sr;
+ char setname[MAXPATHLEN];
+ char setnum[MAXPATHLEN];
+
+ if ((sr = metad_getsetbynum(i, &error)) == NULL) {
+ mdclrerror(&error);
+ continue;
+ }
+
+ (void) snprintf(setname, MAXPATHLEN, "/dev/md/%s",
+ sr->sr_setname);
+ (void) snprintf(setnum, MAXPATHLEN, "shared/%d", i);
+ /*
+ * Ignore failures to create the symlink. This could
+ * happen because suninstall is restartable so the
+ * symlink might have already been created.
+ */
+ (void) symlink(setnum, setname);
+ }
+}
+
+/*
+ * FUNCTION: svm_alloc
+ * Return a pointer to an opaque piece of zeroed memory.
+ *
+ * RETURN VALUES:
+ * Non null - SUCCESS
+ * NULL - FAIL
+ */
+
+svm_info_t *
+svm_alloc()
+{
+ return ((svm_info_t *)calloc(1, sizeof (svm_info_t)));
+}
+
+/*
+ * FUNCTION: svm_free
+ *
+ * INPUT: pointer to struct svm_info
+ */
+
+void
+svm_free(svm_info_t *svmp)
+{
+ int i;
+
+ if (svmp == NULL)
+ return;
+
+ for (i = 0; i < svmp->count; i++) {
+ free(svmp->md_comps[i]);
+ }
+ free(svmp->root_md);
+ free(svmp);
+}
+
+/*
+ * FUNCTION: get_mdcomponents
+ * Given "uname" metadevice, return the physical components
+ * of that metadevice.
+ *
+ * INPUT:
+ * uname - metadevice name
+ *
+ * RETURN VALUES:
+ * svmp - structure containing md name and components
+ * RET_SUCCESS
+ * RET_ERROR
+ *
+ */
+
+int
+get_mdcomponents(char *uname, svm_info_t **svmpp)
+{
+
+ svm_info_t *svmp;
+ md_error_t status, *ep;
+ mdname_t *namep;
+ mdnamelist_t *nlp = NULL;
+ mdnamelist_t *p;
+ mdsetname_t *sp = NULL;
+ char *strp = NULL;
+ int rval, cnt;
+
+ rval = RET_SUCCESS;
+ cnt = 0;
+ status = mdnullerror;
+ ep = &status;
+ svmp = *svmpp;
+
+ (void) init_metalib();
+
+ debug_printf("get_mdcomponents(): Enter unit name %s\n", uname);
+
+ if (((namep = metaname(&sp, uname, ep)) == NULL) ||
+ (metachkmeta(namep, ep) != 0)) {
+ debug_printf("get_mdcomponents(): "
+ "metaname or metachkmeta failed\n");
+ mdclrerror(ep);
+ return (RET_ERROR);
+ }
+
+ debug_printf("get_mdcomponents(): meta_getdevs %s\n", namep->cname);
+
+ if ((meta_getdevs(sp, namep, &nlp, ep)) < 0) {
+ debug_printf("get_mdcomponents(): "
+ "comp %s - meta_getdevs failed\n", uname);
+ metafreenamelist(nlp);
+ mdclrerror(ep);
+ return (RET_ERROR);
+ }
+
+ /* compute the number of devices */
+
+ for (p = nlp, cnt = 0; p != NULL; p = p->next, cnt++)
+ ;
+
+ /*
+ * Need to add n -1 components since slvmp already has space
+ * for one device.
+ */
+
+ svmp = (svm_info_t *)realloc(svmp, sizeof (svm_info_t) +
+ (sizeof (char *) * (cnt - 1)));
+
+ if (svmp == NULL) {
+ debug_printf("get_mdcomponents(): realloc of svmp failed\n");
+ metafreenamelist(nlp);
+ return (RET_ERROR);
+ }
+
+
+ for (p = nlp, cnt = 0; p != NULL; p = p->next, cnt++) {
+ mdname_t *devnp = p->namep;
+
+ if ((strp = strdup(devnp->cname)) == NULL) {
+ rval = RET_ERROR;
+ break;
+ }
+ svmp->md_comps[cnt] = strp;
+ }
+
+ /* count is set to the number of devices in the list */
+
+ svmp->count = cnt;
+ svmp->root_md = strdup(uname);
+ if (rval == RET_SUCCESS && svmp->root_md != NULL) {
+ debug_printf("get_mdcomponents(): root_md %s count %d \n",
+ svmp->root_md, svmp->count);
+ for (cnt = 0; cnt < svmp->count; cnt++)
+ debug_printf("get_mdcomponents(): %s\n",
+ svmp->md_comps[cnt]);
+ } else {
+ rval = RET_ERROR;
+ svm_free(svmp);
+ svmp = NULL;
+ debug_printf("get_mdcomponents(): malloc failed\n");
+
+ }
+
+
+ metafreenamelist(nlp);
+ *svmpp = svmp;
+ return (rval);
+}
+
+
+/*
+ * FUNCTION: svm_get_components
+ * return svm_infop with the components of a metadevice.
+ *
+ * INPUT:
+ * md_device - eg. /dev/md/dsk/d10, /dev/md/foo/dsk/d10, or
+ * /dev/md/shared/1/dsk/d10
+ *
+ * RETURN:
+ * 0 - SUCCESS
+ * !0 - FAIL
+ */
+
+int
+svm_get_components(char *md_device, svm_info_t **svmpp)
+{
+ int len;
+
+ /*
+ * If this is a named diskset with a shared name
+ * (e.g. /dev/md/shared/1/dsk/d10) call get_mdcomponents with
+ * the diskset and metadevice name (e.g. foo/d10).
+ * Otherwise this is a regular name (e.g. /dev/md/dsk/d10 or
+ * /dev/md/foo/dsk/d10 or d10 or foo/d10) all of which
+ * get_mdcomponents can handle directly.
+ */
+
+ len = strlen("/dev/md/shared/");
+ if (strncmp(md_device, "/dev/md/shared/", len) == 0) {
+ int numlen;
+ int setnum;
+ char *cp;
+ char *slashp;
+ char mdname[MAXPATHLEN];
+ mdsetname_t *sp;
+ md_error_t error = mdnullerror;
+
+ cp = md_device + len;
+
+ if ((slashp = strstr(cp, "/")) == NULL)
+ return (RET_ERROR);
+ numlen = slashp - cp;
+ if (numlen >= MAXPATHLEN - 1)
+ return (RET_ERROR);
+
+ (void) strlcpy(mdname, cp, numlen + 1);
+ /* setnum now contains the diskset number */
+ setnum = atoi(mdname);
+ if ((sp = metasetnosetname(setnum, &error)) == NULL ||
+ !mdisok(&error))
+ return (RET_ERROR);
+
+ cp = slashp + 1;
+ /* cp now pointing at dsk/... */
+ if ((slashp = strstr(cp, "/")) == NULL)
+ return (RET_ERROR);
+
+ (void) snprintf(mdname, MAXPATHLEN, "%s/%s", sp->setname,
+ slashp + 1);
+ /* mdname now contains diskset and metadevice name e.g. foo/d10 */
+
+ debug_printf("svm_get_components(): mdname %s\n", mdname);
+ return (get_mdcomponents(mdname, svmpp));
+
+ } else {
+ debug_printf("svm_get_components(): md_device %s\n", md_device);
+ return (get_mdcomponents(md_device, svmpp));
+ }
+}
diff --git a/usr/src/lib/lvm/libsvm/common/modops.c b/usr/src/lib/lvm/libsvm/common/modops.c
new file mode 100644
index 0000000000..78914a9069
--- /dev/null
+++ b/usr/src/lib/lvm/libsvm/common/modops.c
@@ -0,0 +1,120 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/errno.h>
+#include <sys/modctl.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <svm.h>
+
+/*
+ * FUNCTION: get modid
+ * Given a module name returns module id.
+ *
+ * INPUT: module name
+ *
+ * RETURN VALUES:
+ * > 0 SUCCESS
+ * -1 FAIL
+ */
+
+static int
+get_modid(char *modname)
+{
+ struct modinfo modinfo;
+ int id;
+ int rval = RET_ERROR;
+
+ id = -1; /* look for all modules */
+
+ modinfo.mi_id = modinfo.mi_nextid = id;
+ modinfo.mi_info = MI_INFO_ALL | MI_INFO_NOBASE;
+
+ do {
+ if (modctl(MODINFO, id, &modinfo) < 0)
+ break;
+
+ modinfo.mi_name[MODMAXNAMELEN - 1] = '\0';
+ /* if we find a match break out */
+ if (strcmp(modinfo.mi_name, modname) == 0) {
+ rval = modinfo.mi_id;
+ break;
+ }
+ /* LINTED */
+ } while (1);
+
+ return (rval);
+}
+
+/*
+ * FUNCTION: mod_unload
+ * unload a module.
+ *
+ * INPUT: module name
+ *
+ * RETURN VALUES:
+ * 0 - SUCCESS
+ * !0 - FAIL
+ * > 0 errno
+ * -1
+ * NOTE: If we fail to get the module id because the module is not
+ * currently loaded we still want to try to force a reload of the
+ * .conf file when it does load.
+ */
+int
+mod_unload(char *modname)
+{
+ int id;
+ major_t major;
+ int rval = RET_SUCCESS;
+
+ id = get_modid(modname);
+
+ if (id != -1) {
+ if (modctl(MODUNLOAD, id) < 0) {
+ rval = errno;
+ }
+ }
+
+ if ((modctl(MODGETMAJBIND, modname, strlen(modname) + 1,
+ &major)) != 0) {
+ return (errno);
+ }
+
+ if ((modctl(MODUNLOADDRVCONF, major) != 0) ||
+ (modctl(MODLOADDRVCONF, major) != 0)) {
+ return (errno);
+ }
+
+ return (rval);
+}
diff --git a/usr/src/lib/lvm/libsvm/common/start_svm.c b/usr/src/lib/lvm/libsvm/common/start_svm.c
new file mode 100644
index 0000000000..f423d4f418
--- /dev/null
+++ b/usr/src/lib/lvm/libsvm/common/start_svm.c
@@ -0,0 +1,284 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <ctype.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <limits.h>
+#include <meta.h>
+#include <svm.h>
+#include <libsvm.h>
+
+#define MODEBITS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
+#define ISREG(A) (((A).st_mode & S_IFMT) == S_IFREG)
+#define DEFAULT_ROOTDIR "/a"
+
+
+/*
+ * FUNCTION: svm_start
+ * starts SDS/SVM configuration. If root mirroring exists then the
+ * components of the root mirror are returned in svmpp.
+ *
+ * INPUT: mntpnt - root mount point
+ * svmpp - prealloced structure to return components
+ * repl_state_flag - SVM_CONV/SVM_DONT_CONV
+ *
+ * RETURN:
+ * 0 - SUCCESS
+ * !0 - ERROR
+ * if > 0 errno
+ */
+
+int
+svm_start(char *mntpnt, svm_info_t **svmpp, int repl_state_flag)
+{
+ char *rootdir, *tf;
+ char *mdevnamep = NULL;
+ char system_file[PATH_MAX];
+ char mdconf[PATH_MAX];
+ int rval = 0;
+
+ if (mntpnt == NULL)
+ rootdir = DEFAULT_ROOTDIR;
+ else
+ rootdir = mntpnt;
+
+ if ((rval = snprintf(system_file, PATH_MAX, "%s%s",
+ rootdir, SYSTEM_FILE)) < 0) {
+ return (RET_ERROR);
+ }
+
+ if ((rval = snprintf(mdconf, PATH_MAX, "%s%s",
+ rootdir, MD_CONF)) < 0) {
+ return (RET_ERROR);
+ }
+
+ debug_printf("svm_start(): repl_state_flag %s\n",
+ (repl_state_flag == SVM_DONT_CONV) ? "SVM_DONT_CONV":
+ "SVM_CONV");
+
+ if (copyfile(MD_CONF, MD_CONF_ORIG))
+ return (RET_ERROR);
+
+ switch (rval = convert_bootlist(system_file, mdconf, &tf)) {
+ case 0:
+ case -1: /* found in etc/system flag */
+ break;
+ default: /* convert bootlist failed */
+ debug_printf("svm_start(): convert_bootlist failed."
+ "rval %d\n", rval);
+ goto errout;
+ }
+
+ if (repl_state_flag == SVM_DONT_CONV) {
+ rval = create_in_file_prop(PROP_KEEP_REPL_STATE, tf);
+ if (rval != 0)
+ goto errout;
+ }
+
+ if (is_upgrade_prop(PROP_DEVID_DESTROY)) {
+ rval = create_in_file_prop(PROP_DEVID_DESTROY, tf);
+ /*
+ * For the idempotent behavior reset internal
+ * flag incase we have to return due to errors
+ */
+ set_upgrade_prop(PROP_DEVID_DESTROY, 0);
+ if (rval != 0)
+ goto errout;
+ }
+
+
+ /*
+ * Since svm_start is called only after svm_check,
+ * we can assume that there is a valid metadb. If the mddb_bootlist
+ * is not found in etc/system, then it must be in md.conf which
+ * we copied to temporary file pointed to by tf
+ */
+ if (copyfile(tf, MD_CONF)) {
+ debug_printf("svm_start(): copy of %s to %s failed\n", tf,
+ MD_CONF);
+ goto errout;
+ }
+
+ if ((rval = write_xlate_to_mdconf(rootdir)) != 0) {
+ debug_printf("svm_start(): write_xlate_to_mdconf(%s) failed\n",
+ rootdir);
+ goto errout;
+ }
+
+ if ((rval = write_targ_nm_table(rootdir)) != 0) {
+ goto errout;
+ }
+
+ /* run devfsadm to create the devices specified in md.conf */
+ if ((rval = system("/usr/sbin/devfsadm -r /tmp -p "
+ "/tmp/root/etc/path_to_inst -i md")) != 0) {
+ debug_printf("svm_start(): devfsadm -i md failed: %d\n", rval);
+ goto errout;
+ }
+
+ /*
+ * We have to unload md after the devfsadm run so that when metainit
+ * loads things it gets the right information from md.conf.
+ */
+ if (rval = svm_stop()) {
+ debug_printf("svm_start(): svm_stop failed.\n");
+ return (RET_ERROR);
+ }
+
+ if ((rval = system("/usr/sbin/metainit -r")) != 0) {
+ debug_printf("svm_start(): metainit -r failed: %d\n", rval);
+ goto errout;
+ }
+
+ create_diskset_links();
+
+ if ((rval = system("/usr/sbin/metasync -r")) != 0) {
+ debug_printf("svm_start(): metasync -r failed: %d\n", rval);
+ goto errout;
+ }
+
+ /*
+ * We ignore failures from metadevadm, since it can fail if
+ * miniroot dev_t's don't match target dev_ts. But it still
+ * will update md.conf with device Id information which is
+ * why we are calling it here.
+ */
+
+ (void) system("/usr/sbin/metadevadm -r");
+
+ /*
+ * check to see if we have a root metadevice and if so
+ * get its components.
+ */
+
+ if ((rval = get_rootmetadevice(rootdir, &mdevnamep)) == 0) {
+ if (rval = get_mdcomponents(mdevnamep, svmpp)) {
+ debug_printf("svm_start(): get_mdcomponents(%s,..)"
+ "failed %d\n", mdevnamep, rval);
+ goto errout;
+ }
+
+ } else {
+ rval = 0; /* not a mirrored root */
+ debug_printf("svm_start(): get_rootmetadevice(%s,..) "
+ "No root mirrors! ", rootdir);
+ }
+errout:
+ free(mdevnamep);
+ if (rval != 0) {
+ struct stat sbuf;
+ if (stat(MD_CONF_ORIG, &sbuf) == 0)
+ (void) copyfile(MD_CONF_ORIG, MD_CONF);
+ debug_printf("svm_start(): svm_start failed: %d\n", rval);
+ } else {
+ int i;
+
+ if ((*svmpp)->count > 0) {
+ debug_printf("svmpp: ");
+ debug_printf(" root_md: %s", (*svmpp)->root_md);
+ debug_printf(" count: %d", (*svmpp)->count);
+ for (i = 0; i < (*svmpp)->count; i++) {
+ debug_printf(" md_comps[%d]: %s", i,
+ (*svmpp)->md_comps[i]);
+ }
+ debug_printf(" \n");
+ } else {
+ if ((*svmpp)->count == 0)
+ debug_printf("svm_start(): no mirrored root\n");
+ }
+ debug_printf("svm_start(): svm_start succeeded.\n");
+ }
+ return (rval);
+}
+
+/*
+ * FUNCTION: copyfile
+ *
+ * INPUT: self descriptive
+ *
+ * RETURN:
+ * RET_SUCCESS
+ * RET_ERROR
+ */
+int
+copyfile(char *from, char *to)
+{
+ int fromfd, tofd;
+ char buf[1024];
+ ssize_t rbytes;
+ struct stat fromstat;
+
+ if ((fromfd = open(from, O_RDONLY | O_NDELAY)) < 0)
+ return (RET_ERROR);
+
+ if ((fstat(fromfd, &fromstat) < 0) || ! ISREG(fromstat)) {
+ (void) close(fromfd);
+ return (RET_ERROR);
+ }
+
+ if ((tofd = open(to, O_CREAT | O_WRONLY | O_TRUNC,
+ (fromstat.st_mode & MODEBITS))) < 0) {
+ (void) close(fromfd);
+ return (RET_ERROR);
+ }
+
+ /*
+ * in case the file exists then perm is forced by this chmod
+ */
+ (void) fchmod(tofd, fromstat.st_mode & MODEBITS);
+
+ for (;;) {
+ rbytes = read(fromfd, buf, sizeof (buf));
+ /*
+ * no need to check for negative values since the file
+ * has been successfully stat'ed
+ */
+ if (rbytes == 0)
+ break;
+ if (write(tofd, buf, rbytes) != rbytes) {
+ rbytes = -1;
+ break;
+ }
+ }
+
+ (void) close(fromfd);
+ (void) close(tofd);
+ if (rbytes < 0) {
+ (void) unlink(to);
+ return (RET_ERROR);
+ }
+ return (RET_SUCCESS);
+}
diff --git a/usr/src/lib/lvm/libsvm/common/update_mdconf.c b/usr/src/lib/lvm/libsvm/common/update_mdconf.c
new file mode 100644
index 0000000000..f757648911
--- /dev/null
+++ b/usr/src/lib/lvm/libsvm/common/update_mdconf.c
@@ -0,0 +1,379 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <devid.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <meta.h>
+#include <libsvm.h>
+#include <svm.h>
+
+/*
+ * magic strings in system
+ */
+#define BEGMDDBSTR "* Begin MDD database info (do not edit)\n"
+#define ENDMDDBSTR "* End MDD database info (do not edit)\n"
+#define NEW_BEGMDDBSTR "# Begin MDD database info (do not edit)\n"
+#define NEW_ENDMDDBSTR "# End MDD database info (do not edit)\n"
+
+#define MDDBBOOTLIST "mddb_bootlist"
+
+#define SYS_COMMENTCHAR '*'
+#define CONF_COMMENTCHAR '#'
+
+typedef struct {
+ char *prop_name;
+ int prop_val;
+} md_prop_t;
+
+typedef enum {
+ MDDB_SYS_FILE,
+ MDDB_MDCONF_FILE
+} ftype_t;
+
+static md_prop_t upgrade_props[] = {
+ { PROP_KEEP_REPL_STATE, 0 },
+ { PROP_DEVID_DESTROY, 0},
+ { NULL, 0}
+};
+
+/*
+ * The following functions manage upgrade properties
+ */
+
+void
+set_upgrade_prop(char *prop_name, int val)
+{
+ md_prop_t *upp;
+
+ upp = &upgrade_props[0];
+
+ for (; upp->prop_name != NULL; upp++) {
+ if (strcmp(upp->prop_name, prop_name) == 0) {
+ upp->prop_val = val;
+ return;
+ }
+ }
+}
+
+int
+is_upgrade_prop(char *prop_name)
+{
+ md_prop_t *upp;
+
+ upp = &upgrade_props[0];
+
+ for (; upp->prop_name != NULL; upp++) {
+ if (strcmp(upp->prop_name, prop_name) == 0) {
+ return (upp->prop_val == 1);
+ }
+ }
+ return (0);
+}
+
+int
+create_in_file_prop(char *prop_name, char *fname)
+{
+ FILE *fp;
+ md_prop_t *upp;
+ int rval = RET_ERROR;
+
+ if ((fp = fopen(fname, "a")) == NULL) {
+ return (errno);
+ }
+
+ upp = &upgrade_props[0];
+
+ for (; upp->prop_name != NULL; upp++) {
+ if (strcmp(upp->prop_name, prop_name) == 0) {
+ (void) fprintf(fp, "%s = 1;\n", upp->prop_name);
+ rval = RET_SUCCESS;
+ break;
+ }
+ }
+ (void) fclose(fp);
+ return (rval);
+}
+
+static int
+is_devid_added(char *str)
+{
+ int cnt = 0;
+ char *cp;
+
+ /* there are exactly 3 colons in the string for devid */
+ for (cnt = 0; cnt < 4; cnt++) {
+ if ((cp = strchr(str, ':')) == NULL)
+ break;
+ str = ++cp;
+ }
+ return (cnt == 3);
+}
+
+/*
+ * FUNCTION: parse_bootlist
+ * Parse the bootlist and add the extra field to mddb_boolist entry to
+ * conform to devid changes.
+ *
+ * Old format: <drivername>:<minor_number>:<offset>
+ * New format: <drivername>:<minor_number>:<offset>:<devid>
+ * Devid of id0 implies no device id.
+ *
+ * INPUT: *line - contains the mddb_bootlist
+ * *tfp - File pointer to the md.conf.tmp file.
+ *
+ * RETURN:
+ * 0 - Success
+ * > 0 - Failure. Errno returned
+ */
+
+static int
+parse_bootlist(char *line, FILE *tfp)
+{
+ char output[1024];
+ char *cp;
+ int retval = RET_SUCCESS;
+
+ (void) memset(output, 0, sizeof (output));
+
+ if (line[0] == SYS_COMMENTCHAR) {
+ output[0] = CONF_COMMENTCHAR;
+ }
+ /* move the line start of mddbbootlist */
+ cp = strstr(line, MDDBBOOTLIST);
+ if (cp != NULL)
+ line = cp;
+
+ /* grab the "mddb_boolist" word */
+ cp = strtok(line, "= ");
+ (void) strcat(output, cp);
+ (void) strcat(output, "=\042"); /* add back the EQUAL and QUOTE chars */
+
+ /*
+ * The line passed in is for example,
+ * mddb_bootlist1="sd:7:16:id1,sd@SIBM_DDRS34560SUN4.2G2N9688_____/h";
+ * At this point mddb_bootlist and "=" have been parsed out.
+ * The remaining string consists of driver name, colon separator and
+ * the device id(if it exists) within quotes.
+ * The deviceid string can contain upper and lower letters, digits
+ * and +-.=_~. Quotes, spaces and \n and \t are not
+ * allowed. They are converted to either _ or their ascii value.
+ * So using space,\n,;and quotes as a separator is safe.
+ */
+
+ while ((cp = strtok(NULL, " \n\042;")) != NULL) {
+ (void) strcat(output, cp);
+ if (!is_devid_added(cp)) {
+ /* append :id0 for devid */
+ (void) strcat(strcat(output, ":"),
+ devid_str_encode(NULL, NULL));
+
+ /* no devid => SDS->SLVM migration. Set the flag */
+ set_upgrade_prop(PROP_DEVID_DESTROY, 1);
+ }
+ (void) strcat(output, " "); /* leave space between entries */
+ }
+
+ /* remove the extra space at the end */
+ output[strlen(output) - 1] = 0;
+ (void) strcat(output, "\042;\n");
+ if (fprintf(tfp, "%s", output) < 0) {
+ retval = errno;
+ }
+ return (retval);
+}
+
+/*
+ * FUNCTION: snarf_n_modify_bootlist
+ * This function stuffs the mddb_bootlist from either etc/system
+ * or kernel/drv/md.conf of the target system into a temporary file tname.
+ * The boolist in the temporary file is in device ID format.
+ *
+ * INPUT: *fp - file pointer that contains the mddb_bootlist.
+ * *tname - file into which the modified bootlist will be written to.
+ * * buf - buffer handed by upper level routine for reading in contents.
+ * * bufsiz - size of the buffer.
+ * mddb_file - flag
+ *
+ * RETURN:
+ * 0 - Success
+ * > 0 - Failure. Errno returned.
+ */
+
+static int
+snarf_n_modify_bootlist(
+ FILE *fp, /* File pointer to snarf from */
+ char *tname, /* name of the temporary file */
+ char *buf, /* Buffer to read into */
+ int bufsz, /* buffer size */
+ ftype_t mddb_file /* flag to indicate if its /etc/system or md.conf */
+)
+{
+ FILE *tfp;
+ int rval = RET_SUCCESS;
+ char *fname = SYSTEM_FILE;
+ char *mddb_start = BEGMDDBSTR;
+ char *mddb_end = ENDMDDBSTR;
+ convflag_t cstatus = MD_STR_NOTFOUND;
+
+ if (mddb_file == MDDB_MDCONF_FILE) {
+ fname = MD_CONF;
+ mddb_start = NEW_BEGMDDBSTR;
+ mddb_end = NEW_ENDMDDBSTR;
+ }
+
+ if ((tfp = fopen(tname, "a")) == NULL)
+ return (errno);
+ debug_printf("Convert from %s\n", fname);
+
+ rewind(fp);
+ while (fgets(buf, bufsz, fp) != NULL) {
+ if (strcmp(buf, mddb_start) == 0) {
+ cstatus = MD_STR_START;
+ if (fprintf(tfp, "%s", NEW_BEGMDDBSTR) < 0) {
+ rval = errno;
+ break;
+ }
+ continue;
+ }
+ if (cstatus == MD_STR_START) {
+ if (strcmp(buf, mddb_end) == 0) {
+ cstatus = MD_STR_DONE;
+ if (fprintf(tfp, "%s", NEW_ENDMDDBSTR) < 0) {
+ rval = errno;
+ break;
+ }
+
+ if (mddb_file == MDDB_MDCONF_FILE)
+ continue;
+ else
+ break;
+ }
+
+ rval = parse_bootlist(buf, tfp);
+ if (rval == RET_SUCCESS)
+ continue;
+ else
+ break;
+ }
+ if (mddb_file == MDDB_MDCONF_FILE) {
+ if (fprintf(tfp, "%s\n", buf) < 0) {
+ rval = errno;
+ break;
+ }
+ }
+
+ } /* while (fgets */
+
+ if (cstatus == MD_STR_NOTFOUND || cstatus == MD_STR_START)
+ rval = RET_ERROR;
+ (void) fclose(tfp);
+ return (rval);
+}
+
+
+/*
+ * FUNCTION: convert_bootlist
+ * Get the bootlist from $ROOT/etc/system and add modified bootlist to
+ * md.conf.
+ * The function converts the mddb_boolist format from that in /etc/system
+ * to md.conf. Also new fields are added to handle the devid id format.
+ * A copy of md.conf is created and the new entries are added to it.
+ * The name of the new file is returned to the calling program.
+ *
+ * Input: system file name
+ * md.conf file name
+ * pointer to temp file name.
+ * RETURN:
+ * *tname - name of the file that has md.conf + new mddb_boolist entries
+ * 0 - success
+ * -1 - mddb_bootlist not found
+ * > 0 - errno
+ *
+ */
+
+int
+convert_bootlist(
+ char *sname, /* system file name */
+ char *mdconf, /* md.conf file name */
+ char **tname /* temp file name */
+)
+{
+ FILE *fp;
+ char cmd_buf[MDDB_BOOTLIST_MAX_LEN];
+ int retval = RET_SUCCESS;
+
+ /* check names */
+ assert(sname != NULL);
+ assert(tname != NULL);
+
+ /* get temp name */
+ *tname = tmpnam(NULL);
+
+ if ((fp = fopen(sname, "r")) == NULL) {
+ retval = errno;
+ goto out;
+ }
+ if (valid_bootlist(fp, MDDB_BOOTLIST_MAX_LEN) == RET_SUCCESS) {
+ if ((retval = copyfile(mdconf, *tname)) == RET_ERROR) {
+ debug_printf("convert_bootlist: copy %s %s failed\n",
+ mdconf, *tname);
+ goto out;
+ }
+ retval = snarf_n_modify_bootlist(fp, *tname, cmd_buf,
+ MDDB_BOOTLIST_MAX_LEN, MDDB_SYS_FILE);
+ } else {
+ (void) fclose(fp); /* close system file */
+ if ((fp = fopen(mdconf, "r")) == NULL) {
+ retval = errno;
+ goto out;
+ }
+ if (valid_bootlist(fp, MDDB_BOOTLIST_MAX_LEN) == RET_ERROR) {
+ retval = RET_ERROR;
+ goto out;
+ }
+ retval = snarf_n_modify_bootlist(fp, *tname, cmd_buf,
+ MDDB_BOOTLIST_MAX_LEN, MDDB_MDCONF_FILE);
+ }
+out:
+ debug_printf("convert_bootlist: retval %d\n", retval);
+ if (fp != NULL)
+ (void) fclose(fp);
+
+ if ((retval != RET_SUCCESS) && (*tname != NULL)) {
+ (void) unlink(*tname);
+ free(*tname);
+ }
+ return (retval);
+}