summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorjc156560 <none@none>2007-01-21 16:17:27 -0800
committerjc156560 <none@none>2007-01-21 16:17:27 -0800
commit711890bc9379ceea66272dc8d4981812224ea86e (patch)
treeb1e518a5474da8ddcbedad3919bf88a2f8f4f567 /usr/src
parentc7a40cc4a9ca339dad64780ebf91c8ca8a28715a (diff)
downloadillumos-joyent-711890bc9379ceea66272dc8d4981812224ea86e.tar.gz
PSARC 2005/204 RaidCfg project
PSARC 2006/663 RaidCfg mpt adjustment 6508590 raidctl utility should use the pass_thru interface for mpt support
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/Makefile.lint2
-rw-r--r--usr/src/cmd/raidctl/Makefile11
-rw-r--r--usr/src/cmd/raidctl/raidctl.c3982
-rw-r--r--usr/src/head/Makefile4
-rw-r--r--usr/src/head/raidcfg.h103
-rw-r--r--usr/src/head/raidcfg_spi.h353
-rw-r--r--usr/src/lib/Makefile4
-rw-r--r--usr/src/lib/libraidcfg/Makefile61
-rw-r--r--usr/src/lib/libraidcfg/Makefile.com51
-rw-r--r--usr/src/lib/libraidcfg/amd64/Makefile32
-rw-r--r--usr/src/lib/libraidcfg/common/llib-lraidcfg122
-rw-r--r--usr/src/lib/libraidcfg/common/mapfile-vers49
-rw-r--r--usr/src/lib/libraidcfg/common/raidcfg.c4672
-rw-r--r--usr/src/lib/libraidcfg/i386/Makefile31
-rw-r--r--usr/src/lib/libraidcfg/sparc/Makefile31
-rw-r--r--usr/src/lib/libraidcfg/sparcv9/Makefile32
-rw-r--r--usr/src/lib/libsecdb/exec_attr.txt1
-rw-r--r--usr/src/lib/raidcfg_plugins/Makefile52
-rw-r--r--usr/src/pkgdefs/SUNWcsl/prototype_com5
-rw-r--r--usr/src/pkgdefs/SUNWcsl/prototype_i3865
-rw-r--r--usr/src/pkgdefs/SUNWcsl/prototype_sparc5
-rw-r--r--usr/src/pkgdefs/etc/exception_list_i38610
-rw-r--r--usr/src/pkgdefs/etc/exception_list_sparc10
23 files changed, 8153 insertions, 1475 deletions
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint
index 50773f685d..6d14d280e7 100644
--- a/usr/src/Makefile.lint
+++ b/usr/src/Makefile.lint
@@ -356,6 +356,7 @@ COMMON_SUBDIRS = \
lib/libpool \
lib/libproc \
lib/libpthread \
+ lib/libraidcfg \
lib/librcm \
lib/librestart \
lib/librt \
@@ -392,6 +393,7 @@ COMMON_SUBDIRS = \
lib/passwdutil \
lib/pkcs11 \
lib/print \
+ lib/raidcfg_plugins \
lib/fm \
lib/udapl \
lib/watchmalloc \
diff --git a/usr/src/cmd/raidctl/Makefile b/usr/src/cmd/raidctl/Makefile
index 1ff5118c4f..3dbd866b23 100644
--- a/usr/src/cmd/raidctl/Makefile
+++ b/usr/src/cmd/raidctl/Makefile
@@ -2,9 +2,8 @@
# 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.
+# 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
# or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,7 @@
#
# CDDL HEADER END
#
-#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -32,9 +30,8 @@ PROG= raidctl
include $(SRC)/cmd/Makefile.cmd
-LDLIBS += -lcfgadm
+LDLIBS += -lraidcfg
CFLAGS += $(CCVERBOSE)
-CPPFLAGS += -I$(SRC)/uts/common
.KEEP_STATE:
diff --git a/usr/src/cmd/raidctl/raidctl.c b/usr/src/cmd/raidctl/raidctl.c
index 15b657c3c5..fcec737124 100644
--- a/usr/src/cmd/raidctl/raidctl.c
+++ b/usr/src/cmd/raidctl/raidctl.c
@@ -17,1877 +17,2933 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
- */
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ *
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * raidctl.c is the entry file of RAID configuration utility.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <fcntl.h>
#include <langinfo.h>
-#include <libintl.h>
-#include <limits.h>
+#include <regex.h>
#include <locale.h>
-#include <stdarg.h>
+#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
-#include <sys/ddi.h>
-#include <sys/mpt/mpi.h>
-#include <sys/mpt/mpi_ioc.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/pci.h>
#include <unistd.h>
-#include <sys/mnttab.h>
-#include <sys/dkio.h>
-#include <config_admin.h>
-#include <sys/param.h>
-#include <sys/raidioctl.h>
-
-/*
- * list of controllers to list
- * setup like this:
- * [ctrl_num] [status]
- *
- * where status is:
- * RAID Found,
- * No RAID Found
- * RAID not supported on this controller
- * Invalid Controller
- */
-
-typedef enum {
- RAID_FOUND = 0x0,
- RAID_NOT_FOUND,
- RAID_NOT_SUPPORTED,
- RAID_INVALID_CTRL,
- RAID_DONT_USE
-} raidctl_errno_t;
-
-/* For no-mixup indexing of info_ctrl */
-#define INFO_CTRL 0
-#define INFO_STATUS 1
-
-static int **info_ctrl = NULL;
-/* Length of conrollers list */
-static int ctrl_nums = 0;
+#include <errno.h>
+#include <libgen.h>
+#include <raidcfg.h>
-#define DEVDIR "/dev/rdsk"
+#define TRUE 1
+#define FALSE 0
-#define DO_HW_RAID_NOP -1
-#define DO_HW_RAID_INFO 0
-#define DO_HW_RAID_CREATE 1
-#define DO_HW_RAID_DELETE 2
-#define DO_HW_RAID_FLASH 3
+#ifndef TEXT_DOMAIN
+#define TEXT_DOMAIN "SYS_TEST"
+#endif
-/* values to use for raid level in raidctl */
-#define RAID_STRIPE 0
-#define RAID_MIRROR 1
+/*
+ * Return value of command
+ */
+#define SUCCESS 0
+#define INVALID_ARG 1
+#define FAILURE 2
/*
- * Error return codes
+ * Initial value of variables
*/
-#define SUCCESS 0
-#define INVALID_ARG 1
-#define FAILURE 2
+#define INIT_HANDLE_VALUE -3
+#define MAX64BIT 0xffffffffffffffffull
+#define MAX32BIT 0xfffffffful
/*
- * FW Update Stuff
+ * Flag of set or unset HSP
*/
+#define HSP_SET 1
+#define HSP_UNSET 0
-/* signature and initial offset for PCI expansion rom images */
-#define PCIROM_SIG 0xaa55 /* offset 0h, length 2 bytes */
-#define PCIR_OFF 0x18 /* Pointer to PCI Data Structure */
-
-/* offsets in PCI data structure header */
-#define PCIR_DEVID 0x6 /* PCI device id */
-#define PCIR_CODETYPE 0x14 /* type of code (intel/fcode) */
-#define PCIR_INDICATOR 0x15 /* "last image" indicator */
-
-/* flags for image types */
-#define BIOS_IMAGE 0x1
-#define FCODE_IMAGE 0x2
-#define UNKNOWN_IMAGE 0x3
-#define LAST_IMAGE 0x80
-#define NOT_LAST_IMAGE 0
-#define PCI_IMAGE_UNIT_SIZE 512
-
-/* ID's and offsets for MPT Firmware images */
-#define FW_ROM_ID 0x5aea /* bytes 4 & 5 of file */
-#define FW_ROM_OFFSET_CHIP_TYPE 0x22 /* (U16) */
-#define FW_ROM_OFFSET_VERSION 0x24 /* (U16) */
-#define FW_ROM_OFFSET_VERSION_NAME 0x44 /* (32 U8) */
-
-/* ID's for supported chips */
-#define LSI_1030 0x30
-#define LSI_1064 0x50
-#define LSI_1068 0x54
-#define LSI_1064E 0x56
-#define LSI_1068E 0x58
-
-/* Key to search for when looking for fcode version */
-#define FCODE_VERS_KEY1 0x12
-#define FCODE_VERS_KEY2 0x7
-#define BIOS_STR "LSI SCSI Host Adapter BIOS Driver: "
-
-/* get a word from a buffer (works with non-word aligned offsets) */
-#define gw(x) (((x)[0]) + (((x)[1]) << 8))
-
-/* Number of disks currently supported, per RAID volume */
-#define N_DISKS 8
-
-/* Maximum number of RAID volumes currently supported per HBA */
-#define N_RAIDVOLS 2
+/*
+ * Operate codes of command
+ */
+#define DO_HW_RAID_NOP -1
+#define DO_HW_RAID_HELP 0
+#define DO_HW_RAID_CREATEO 1
+#define DO_HW_RAID_CREATEN 2
+#define DO_HW_RAID_DELETE 3
+#define DO_HW_RAID_LIST 4
+#define DO_HW_RAID_FLASH 5
+#define DO_HW_RAID_HSP 6
+#define DO_HW_RAID_SET_ATTR 7
+#define DO_HW_RAID_SNAPSHOT 8
+
+#define LOWER_H (1 << 0)
+#define LOWER_C (1 << 1)
+#define LOWER_D (1 << 2)
+#define LOWER_L (1 << 3)
+#define LOWER_R (1 << 4)
+#define LOWER_Z (1 << 5)
+#define LOWER_G (1 << 6)
+#define LOWER_A (1 << 7)
+#define LOWER_S (1 << 8)
+#define LOWER_P (1 << 9)
+#define LOWER_F (1 << 10)
+#define UPPER_S (1 << 11)
+#define UPPER_C (1 << 12)
+#define UPPER_F (1 << 13)
+
+/* Add a ARRAY state (temporary) */
+#define ARRAY_STATE_SYNC 100
/*
* Function and strings to properly localize our prompt.
- * So for example in german it would ask (ja/nein) or (yes/no) in
+ * So for example in German it would ask (ja/nein) or (yes/no) in
* english.
*/
+#ifndef SCHAR_MAX
+#define SCHAR_MAX 10
+#endif
+
+#define RAIDCTL_LOCKF "/var/run/lockf_raidctl"
+
+/* Locale setting */
static int yes(void);
-static char yeschr[SCHAR_MAX + 2];
-static char nochr[SCHAR_MAX +2];
+static int rpmatch(char *s);
+static char *yesstr = NULL;
+static char *nostr = NULL;
+static char *yesexpr = NULL;
+
+static char *default_yesexpr = "^[yY]";
+static char *default_yesstr = "yes";
+static char *default_nostr = "no";
+
+static regex_t re;
+
+#define SET_DEFAULT_STRS \
+ regfree(&re); \
+ free(yesexpr); \
+ free(yesstr); \
+ free(nostr); \
+ yesexpr = default_yesexpr; \
+ yesstr = default_yesstr; \
+ nostr = default_nostr;
+
+#define FREE_STRS \
+ if (yesexpr != default_yesexpr) \
+ free(yesexpr); \
+ if (yesstr != default_yesstr) \
+ free(yesstr); \
+ if (nostr != default_nostr) \
+ free(nostr);
+
+/* program name */
+static char *prog_namep;
-typedef struct raidlist {
- raid_config_t raid_config[N_RAIDVOLS];
- int controller;
- char devctl[MAXPATHLEN];
- struct raidlist *next;
-} raidlist_t;
-static raidlist_t *raids;
+/*
+ * Functions declaration
+ */
+static void helpinfo(char *prog_namep);
+static int do_create_cidl(char *raid_levelp, char *capacityp, char *disk_argp,
+ char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind);
+static int do_create_ctd(char *raid_levelp, char **disks_argpp,
+ uint32_t disks_num, uint32_t argindex, uint32_t f_flag);
+static int do_list(char *disk_argp, char **argv, uint32_t optind,
+ uint8_t is_snapshot);
+static int do_delete(uint32_t f_flag, char **argv, uint32_t optind);
+static int do_flash(uint8_t f_flag, char *filep, char **ctls_argpp,
+ uint32_t index, uint32_t ctl_num);
+static int do_set_hsp(char *a_argp, char *disk_argp, char **argv,
+ uint32_t optind);
+static int do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv,
+ uint32_t optind);
+static int snapshot_raidsystem(uint8_t recursive, uint8_t indent,
+ uint8_t is_snapshot);
+static int snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive,
+ uint8_t indent, uint8_t is_snapshot);
+static int snapshot_array(raid_obj_handle_t array_handle,
+ uint8_t indent, uint8_t is_sub, uint8_t is_snapshot);
+static int snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle,
+ uint8_t indent, uint8_t is_snapshot);
+static int print_ctl_table(raid_obj_handle_t ctl_handle);
+static int print_array_table(raid_obj_handle_t ctl_handle,
+ raid_obj_handle_t array_handle);
+static int print_disk_table(raid_obj_handle_t ctl_handle,
+ raid_obj_handle_t disk_handle);
+static int print_ctl_attr(raidcfg_controller_t *attrp);
+static int print_array_attr(raidcfg_array_t *attrp);
+static int print_arraypart_attr(raidcfg_arraypart_t *attrp);
+static int print_disk_attr(raid_obj_handle_t ctl_handle,
+ raid_obj_handle_t disk_handle, raidcfg_disk_t *attrp);
+static void print_indent(uint8_t indent);
+static int get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp,
+ int *comps_nump, raid_obj_handle_t **handlespp);
+static int get_disk_handle_ctd(int disks_num, char **disks_argpp,
+ uint32_t *ctl_tagp, raid_obj_handle_t *disks_handlep);
+static int get_ctl_tag(char *argp, uint32_t *ctl_tagp);
+static int get_array_tag(char *argp, uint32_t *ctl_tagp,
+ array_tag_t *array_tagp);
+static int get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp,
+ uint32_t *controller_id);
+static int get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp);
+static int calc_size(char *sizep, uint64_t *valp);
+static int is_fully_numeric(char *strp);
+static int size_to_string(uint64_t size, char *string, int len);
+static int enter_raidctl_lock(int *fd);
+static void exit_raidctl_lock(int fd);
/*
- * usage: raidctl
- * usage: raidctl [-f] -c primary secondary
- * usage: raidctl [-f] -c -r 1 primary secondary
- * usage: raidctl [-f] -c -r 0 disk1 disk2 [disk3] ...
- * usage: raidctl [-f] -d volume
- * usage: raidctl [-f] -F image_file controller
- * usage: raidctl -l [controller...]
- * example:
- * raidctl -c c1t1d0 c1t2d0
- * raidctl -c -r 0 c1t1d0 c1t2d0 c1t3d0 c1t4d0
- * raidctl -d c1t1d0
- * raidctl -F image 1
+ * Entry function of raidctl command
*/
-static void
-usage(char *prog_name)
+int
+main(int argc, char **argv)
{
- (void) fprintf(stderr, gettext("usage: %s\n"), prog_name);
+ /* operation index */
+ int8_t findex = DO_HW_RAID_NOP;
+
+ /* argument pointers */
+ char *r_argp = NULL;
+ char *z_argp = NULL;
+ char *g_argp = NULL;
+ char *a_argp = NULL;
+ char *s_argp = NULL;
+ char *p_argp = NULL;
+ char *F_argp = NULL;
+ char *C_argp = NULL;
- (void) fprintf(stderr, gettext("usage: %s [-f] -c primary secondary\n"),
- prog_name);
+ /*
+ * operation flags.
+ */
+ uint8_t r_flag = FALSE;
+ uint8_t f_flag = FALSE;
+ uint8_t action = FALSE;
+ uint64_t options = 0;
- (void) fprintf(stderr, gettext("usage: %s [-f] -c -r 1 primary "
- "secondary\n"), prog_name);
+ /* index and temporary variables */
+ int ret;
+ int status;
+ char c = '\0';
- (void) fprintf(stderr, gettext("usage: %s [-f] -c -r 0 disk1 disk2 "
- "[disk3] ...\n"), prog_name);
+ /* fd for the filelock */
+ int fd;
- (void) fprintf(stderr, gettext("usage: %s [-f] -d volume\n"),
- prog_name);
+ if (enter_raidctl_lock(&fd) != SUCCESS) {
+ return (FAILURE);
+ }
- (void) fprintf(stderr,
- gettext("usage: %s [-f] -F image_file controller \n"),
- prog_name);
+ (void) setlocale(LC_ALL, "");
+ (void) textdomain(TEXT_DOMAIN);
- (void) fprintf(stderr, gettext("usage: %s -l [controller...]\n"),
- prog_name);
+ /* parse command line, and get program name */
+ if ((prog_namep = strrchr(argv[0], '/')) == NULL) {
+ prog_namep = argv[0];
+ } else {
+ prog_namep++;
+ }
- (void) fprintf(stderr, gettext("example:\n"));
- (void) fprintf(stderr, "%s -c c1t1d0 c1t2d0\n", prog_name);
- (void) fprintf(stderr, "%s -c -r 0 c1t1d0 c1t2d0 "
- "c1t3d0 c1t4d0\n", prog_name);
- (void) fprintf(stderr, "%s -d c1t1d0\n", prog_name);
- (void) fprintf(stderr, "%s -F image 1\n", prog_name);
+ /* close error option messages from getopt */
+ opterr = 0;
- exit(1);
-}
+ /* get yes expression according to current locale */
+ yesexpr = strdup(nl_langinfo(YESEXPR));
+ yesstr = strdup(nl_langinfo(YESSTR));
+ nostr = strdup(nl_langinfo(NOSTR));
+ if (yesexpr == NULL || yesstr == NULL || nostr == NULL) {
+ return (FAILURE);
+ }
-/* Make errno message more "user friendly" */
-static void
-raidctl_error(char *str)
-{
- switch (errno) {
- case EINVAL:
- (void) fprintf(stderr, gettext("Error: "
- "invalid argument would be returned\n"));
+ /*
+ * If the was no expression or if there is a compile error
+ * use default yes expression.
+ */
+ status = regcomp(&re, yesexpr, REG_EXTENDED | REG_NOSUB);
+ if ((*yesexpr == (char)NULL) ||
+ (*yesstr == (char)NULL) ||
+ (*nostr == (char)NULL) ||
+ (status != 0)) {
+ SET_DEFAULT_STRS;
+ if (regcomp(&re, default_yesexpr,
+ REG_EXTENDED | REG_NOSUB) != 0) {
+ return (FALSE);
+ }
+ }
+
+ while ((c = getopt(argc, argv,
+ "?hC:cdlF:r:z:g:a:s:p:fS")) != EOF) {
+ switch (c) {
+ case 'h':
+ case '?':
+ if (action == FALSE) {
+ findex = DO_HW_RAID_HELP;
+ action = TRUE;
+ options |= LOWER_H;
+ } else {
+ findex = DO_HW_RAID_NOP;
+ }
+ break;
+ case 'C':
+ if (action == FALSE) {
+ findex = DO_HW_RAID_CREATEN;
+ C_argp = optarg;
+ action = TRUE;
+ options |= UPPER_C;
+ } else {
+ findex = DO_HW_RAID_NOP;
+ }
+ break;
+ case 'c':
+ if (action == FALSE) {
+ findex = DO_HW_RAID_CREATEO;
+ action = TRUE;
+ options |= LOWER_C;
+ } else {
+ findex = DO_HW_RAID_NOP;
+ }
+ break;
+ case 'd':
+ if (action == FALSE) {
+ findex = DO_HW_RAID_DELETE;
+ action = TRUE;
+ options |= LOWER_D;
+ } else {
+ findex = DO_HW_RAID_NOP;
+ }
+ break;
+ case 'l':
+ if (action == FALSE) {
+ findex = DO_HW_RAID_LIST;
+ action = TRUE;
+ options |= LOWER_L;
+ } else {
+ findex = DO_HW_RAID_NOP;
+ }
+ break;
+ case 'F':
+ if (action == FALSE) {
+ findex = DO_HW_RAID_FLASH;
+ F_argp = optarg;
+ action = TRUE;
+ options |= UPPER_F;
+ } else {
+ findex = DO_HW_RAID_NOP;
+ }
+ break;
+ case 'a':
+ if (action == FALSE) {
+ findex = DO_HW_RAID_HSP;
+ a_argp = optarg;
+ action = TRUE;
+ options |= LOWER_A;
+ } else {
+ findex = DO_HW_RAID_NOP;
+ }
+ break;
+ case 'p':
+ if (action == FALSE) {
+ findex = DO_HW_RAID_SET_ATTR;
+ p_argp = optarg;
+ action = TRUE;
+ options |= LOWER_P;
+ } else {
+ findex = DO_HW_RAID_NOP;
+ }
+ break;
+ case 'r':
+ r_argp = optarg;
+ r_flag = TRUE;
+ options |= LOWER_R;
+ break;
+ case 'z':
+ z_argp = optarg;
+ options |= LOWER_Z;
+ break;
+ case 'g':
+ g_argp = optarg;
+ options |= LOWER_G;
+ break;
+ case 's':
+ s_argp = optarg;
+ options |= LOWER_S;
+ break;
+ case 'f':
+ f_flag = TRUE;
+ options |= LOWER_F;
+ break;
+ case 'S':
+ if (action == FALSE) {
+ findex = DO_HW_RAID_SNAPSHOT;
+ action = TRUE;
+ options |= UPPER_S;
+ } else {
+ findex = DO_HW_RAID_NOP;
+ }
+ break;
+ default:
+ (void) fprintf(stderr,
+ gettext("Invalid argument(s).\n"));
+ exit_raidctl_lock(fd);
+ FREE_STRS;
+ regfree(&re);
+ return (INVALID_ARG);
+ }
+ }
+
+ /* parse options */
+ switch (findex) {
+ case DO_HW_RAID_HELP:
+ if ((options & ~(LOWER_H)) != 0) {
+ ret = INVALID_ARG;
+ } else {
+ helpinfo(prog_namep);
+ ret = SUCCESS;
+ }
break;
- case EIO:
- case EFAULT:
- (void) fprintf(stderr,
- gettext("Error: Device inaccessible.\n"));
+ case DO_HW_RAID_CREATEO:
+ if ((options & ~(LOWER_F | LOWER_C | LOWER_R)) != 0) {
+ ret = INVALID_ARG;
+ } else {
+ if (r_flag != FALSE && f_flag == FALSE) {
+ ret = do_create_ctd(r_argp, argv, argc - 4,
+ optind, f_flag);
+ } else if (r_flag == FALSE && f_flag == FALSE) {
+ ret = do_create_ctd(NULL, argv, argc - 2,
+ optind, f_flag);
+ } else if (r_flag != FALSE && f_flag != FALSE) {
+ ret = do_create_ctd(r_argp, argv, argc - 5,
+ optind, f_flag);
+ } else {
+ ret = do_create_ctd(NULL, argv, argc - 3,
+ optind, f_flag);
+ }
+ }
+ break;
+ case DO_HW_RAID_CREATEN:
+ if ((options & ~(LOWER_F | UPPER_C | LOWER_R | LOWER_Z |
+ LOWER_S)) != 0) {
+ ret = INVALID_ARG;
+ } else {
+ ret = do_create_cidl(r_argp, z_argp, C_argp, s_argp,
+ f_flag, argv, optind);
+ }
+ break;
+ case DO_HW_RAID_DELETE:
+ if ((options & ~(LOWER_F | LOWER_D)) != 0) {
+ ret = INVALID_ARG;
+ } else {
+ ret = do_delete(f_flag, argv, optind);
+ }
+ break;
+ case DO_HW_RAID_LIST:
+ if ((options & ~(LOWER_L | LOWER_G)) != 0) {
+ ret = INVALID_ARG;
+ } else {
+ ret = do_list(g_argp, argv, optind, FALSE);
+ }
+ break;
+ case DO_HW_RAID_SNAPSHOT:
+ if ((options & ~(UPPER_S | LOWER_G)) != 0) {
+ ret = INVALID_ARG;
+ } else {
+ ret = do_list(g_argp, argv, optind, TRUE);
+ }
+ break;
+ case DO_HW_RAID_FLASH:
+ if ((options & ~(LOWER_F | UPPER_F)) != 0) {
+ ret = INVALID_ARG;
+ } else {
+ if (f_flag == FALSE) {
+ ret = do_flash(f_flag, F_argp, argv, optind,
+ argc - 3);
+ } else {
+ ret = do_flash(f_flag, F_argp, argv, optind,
+ argc - 4);
+ }
+ }
+ break;
+ case DO_HW_RAID_HSP:
+ if ((options & ~(LOWER_A | LOWER_G)) != 0) {
+ ret = INVALID_ARG;
+ } else {
+ ret = do_set_hsp(a_argp, g_argp, argv, optind);
+ }
break;
- case ENOTTY:
- (void) fprintf(stderr, gettext("Error: "
- "Device does not support requested action.\n"));
+ case DO_HW_RAID_SET_ATTR:
+ if ((options & ~(LOWER_F | LOWER_P)) != 0) {
+ ret = INVALID_ARG;
+ } else {
+ ret = do_set_array_attr(f_flag, p_argp, argv, optind);
+ }
+ break;
+ case DO_HW_RAID_NOP:
+ if (argc == 1) {
+ ret = do_list(g_argp, argv, optind, FALSE);
+ } else {
+ ret = INVALID_ARG;
+ }
break;
default:
- perror(str);
+ ret = INVALID_ARG;
+ break;
}
-}
-static int
-get_link_path(const char *thing, char *buf)
-{
- if (readlink(thing, buf, MAXPATHLEN) < 0)
- return (1);
- return (0);
+ if (ret == INVALID_ARG) {
+ (void) fprintf(stderr,
+ gettext("Invalid argument(s).\n"));
+ }
+ exit_raidctl_lock(fd);
+
+ FREE_STRS;
+ regfree(&re);
+ return (ret);
}
-static int
-get_ctrl_devctl(char *ctrl, char *b)
+/*
+ * helpinfo(prog_namep)
+ * This function prints help informations for usrs.
+ */
+static void
+helpinfo(char *prog_namep)
{
- char devctl_buf[MAXPATHLEN];
- char *colon;
+ char quote = '"';
- (void) strlcpy(devctl_buf, ctrl, MAXPATHLEN);
+ (void) printf(gettext("%s [-f] -C %c<disks>%c [-r <raid_level>] "
+ "[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep,
+ quote, quote);
- colon = strrchr(devctl_buf, ':');
- if (colon == NULL)
- return (1);
-
- *colon = 0;
- (void) snprintf(devctl_buf, MAXPATHLEN, "%s:devctl", devctl_buf);
- (void) strlcpy(b, devctl_buf, MAXPATHLEN);
- return (0);
-}
-
-static int
-get_devctl(char *disk, char *b)
-{
- char buf1[MAXPATHLEN] = {0};
- char devctl_buf[MAXPATHLEN];
- char *slash;
- char devname[32];
+ (void) printf(gettext("%s [-f] -d <volume>\n"), prog_namep);
- if (get_link_path(disk, buf1))
- return (1);
+ (void) printf(gettext("%s [-f] -F <filename> <controller1> "
+ "[<controller2> ...]\n"), prog_namep);
- (void) strlcpy(devctl_buf, buf1, MAXPATHLEN);
+ (void) printf(gettext("%s [-f] -p %c<param>=<value>%c <volume>\n"),
+ prog_namep, quote, quote);
- slash = strrchr(devctl_buf, '/');
- if (slash == NULL)
- return (1);
+ (void) printf(gettext("%s [-f] -c [-r <raid_level>] <disk1> <disk2> "
+ "[<disk3> ...]\n"), prog_namep);
- *slash = 0;
- slash = strrchr(devctl_buf, '/');
- (void) strlcpy(devname, slash, 32);
- *slash = 0;
+ (void) printf(gettext("%s [-l]\n"), prog_namep);
- (void) snprintf(devctl_buf, MAXPATHLEN, "%s%s:devctl",
- devctl_buf, devname);
+ (void) printf(gettext("%s -l -g <disk> <controller>\n"), prog_namep);
- (void) strlcpy(b, devctl_buf, MAXPATHLEN);
+ (void) printf(gettext("%s -l <volume>\n"), prog_namep);
- return (0);
-}
+ (void) printf(gettext("%s -l <controller1> [<controller2> ...]\n"),
+ prog_namep);
-raidlist_t *
-already_there(int controller)
-{
- raidlist_t *curr = raids;
+ (void) printf(gettext("%s -a {set | unset} -g <disk> "
+ "{<volume> | <controller>}\n"), prog_namep);
- while (curr != NULL) {
- if (curr->controller == controller)
- return (curr);
+ (void) printf(gettext("%s -S [<volume> | <controller>]\n"), prog_namep);
- curr = curr->next;
- }
+ (void) printf(gettext("%s -S -g <disk> <controller>\n"), prog_namep);
- return (NULL);
+ (void) printf(gettext("%s -h\n"), prog_namep);
}
/*
- * Display those controllers where RAID volumes were not found
+ * do_create_cidl(raid_levelp, capacityp, disks_argp, stripe_sizep,
+ * f_flag, argv, optind)
+ * This function creates a new RAID volume with specified arguments,
+ * and returns result as SUCCESS, INVALID_ARG or FAILURE.
+ * The "c.id.l" is used to express single physical disk. 'c' expresses
+ * bus number, 'id' expresses target number, and 'l' expresses lun.
+ * The physical disks represented by c.id.l may be invisible to OS, which
+ * means physical disks attached to controllers are not accessible by
+ * OS directly. The disks should be organized as a logical volume, and
+ * the logical volume is exported to OS as a single unit. Some hardware
+ * RAID controllers also support physical disks accessed by OS directly,
+ * for example LSI1068. In this case, it's both OK to express physical
+ * disk by c.id.l format or canonical ctd format.
*/
-static void
-print_no_raids()
+static int
+do_create_cidl(char *raid_levelp, char *capacityp, char *disks_argp,
+ char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind)
{
- int i, space = 0;
-
- if (info_ctrl == NULL)
- return;
-
- for (i = 0; i < ctrl_nums; i++) {
- /* Status of '0' means RAID exists at that controller */
- if (info_ctrl[i][INFO_STATUS] == RAID_FOUND ||
- info_ctrl[i][INFO_STATUS] == RAID_DONT_USE)
- continue;
+ uint32_t ctl_tag = MAX32BIT;
+ raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
+ uint32_t raid_level = RAID_LEVEL_1;
+ uint64_t capacity = 0;
+ uint64_t stripe_size = (uint64_t)OBJ_ATTR_NONE;
+ raid_obj_handle_t *disk_handlesp = NULL;
+ raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
+ raidcfg_controller_t ctl_attr;
+ int comps_num = 0;
+ int ret = 0;
+
+ raidcfg_array_t array_attr;
+
+ if (argv[optind] == NULL || argv[optind + 1] != NULL) {
+ return (INVALID_ARG);
+ }
- if (!space && raids != NULL) {
- (void) printf("\n");
- space = 1;
- }
+ if (disks_argp == NULL) {
+ return (INVALID_ARG);
+ }
- /* switch statement used to enable gettext()'ing of text */
- switch (info_ctrl[i][INFO_STATUS]) {
- case RAID_INVALID_CTRL:
- (void) printf(gettext("Invalid controller '%d'\n"),
- info_ctrl[i][INFO_CTRL]);
- break;
- case RAID_NOT_SUPPORTED:
- (void) printf(gettext("No RAID supported "
- "on controller '%d'\n"),
- info_ctrl[i][INFO_CTRL]);
+ /* Check controller tag */
+ if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
+ return (INVALID_ARG);
+ }
- break;
- default:
- (void) printf(gettext("No RAID volumes found on "
- "controller '%d'\n"), info_ctrl[i][INFO_CTRL]);
- }
+ ctl_handle = raidcfg_get_controller(ctl_tag);
+ if (ctl_handle <= 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
+ return (FAILURE);
}
-}
-static void
-add_raid_to_raidlist(char *ctrl_name, int controller)
-{
- raidlist_t *curr;
- char buf[MAXPATHLEN] = {0};
- char buf1[MAXPATHLEN] = {0};
- int nvols;
- int fd;
- int i;
- int n;
+ if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
+ }
- if (readlink(ctrl_name, buf, sizeof (buf)) < 0)
- return;
+ /* Get raid level */
+ if (raid_levelp != NULL) {
+ if (*raid_levelp == '1' &&
+ (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) {
+ raid_level = RAID_LEVEL_1E;
+ } else {
+ if (is_fully_numeric(raid_levelp) == FALSE) {
+ return (INVALID_ARG);
+ }
- if (get_ctrl_devctl(buf, buf1))
- return;
+ switch (atoi(raid_levelp)) {
+ case 0:
+ raid_level = RAID_LEVEL_0;
+ break;
+ case 1:
+ raid_level = RAID_LEVEL_1;
+ break;
+ case 5:
+ raid_level = RAID_LEVEL_5;
+ break;
+ case 10:
+ raid_level = RAID_LEVEL_10;
+ break;
+ case 50:
+ raid_level = RAID_LEVEL_50;
+ break;
+ default:
+ return (INVALID_ARG);
+ }
+ }
+ }
/*
- * If "-l" was specified, then only look at those controllers
- * listed as part of the command line input.
+ * The rang check of capacity and stripe size is performed in library,
+ * and it relates to hardware feature.
*/
- if (info_ctrl != NULL) {
- for (i = 0; i < ctrl_nums; i++) {
- if (info_ctrl[i][INFO_STATUS] == RAID_DONT_USE)
- continue;
- if (controller == info_ctrl[i][INFO_CTRL])
- break;
+
+ /* Capacity in bytes. Capacity 0 means max available space. */
+ if (capacityp != NULL) {
+ if (*capacityp == '-' ||
+ calc_size(capacityp, &capacity) != SUCCESS) {
+ return (INVALID_ARG);
}
- /* return if we didn't find a controller */
- if (i == ctrl_nums)
- return;
}
- fd = open(buf1, O_RDONLY);
- if (fd == -1) {
- if (info_ctrl != NULL)
- info_ctrl[i][INFO_STATUS] = RAID_INVALID_CTRL;
- return;
+ /* Stripe size in bytes */
+ if (stripe_sizep != NULL) {
+ if (calc_size(stripe_sizep, &stripe_size) != SUCCESS ||
+ *stripe_sizep == '-') {
+ return (INVALID_ARG);
+ }
}
- /*
- * query the HBA driver for volume capacity
- */
- if (ioctl(fd, RAID_NUMVOLUMES, &nvols) < 0) {
- if (info_ctrl != NULL)
- info_ctrl[i][INFO_STATUS] = RAID_NOT_SUPPORTED;
- (void) close(fd);
- return;
+ /* Open controller before accessing its object */
+ if ((ret = raidcfg_open_controller(ctl_handle, NULL)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
}
- /*
- * now iterate through nvols configurations
- */
- for (n = 0; n < nvols; n++) {
- raid_config_t config;
-
- /* use unitid to retrieve this volume */
- config.unitid = n;
- if (ioctl(fd, RAID_GETCONFIG, &config) < 0) {
- if (info_ctrl != NULL)
- info_ctrl[i][INFO_STATUS] = RAID_NOT_SUPPORTED;
- (void) close(fd);
- return;
- }
-
- /* if ndisks is 0, this volume is not configured */
- if (config.ndisks == 0)
- continue;
-
- /* otherwise, we have a raid volume */
- if (info_ctrl != NULL)
- info_ctrl[i][INFO_STATUS] = RAID_FOUND;
-
- /*
- * if raids has not been initialized, then do so.
- * otherwise, see if this controller is in raids.
- * if it is not, add it. then, add this volume to
- * the raidlist
- */
- if (raids == NULL) {
- raids = (raidlist_t *)malloc(sizeof (raidlist_t));
- curr = raids;
- } else {
- if ((curr = already_there(controller)) != NULL)
- goto already_there;
+ /* Get disks' handles */
+ if ((ret = get_disk_handle_cidl(ctl_tag, disks_argp, &comps_num,
+ &disk_handlesp)) != SUCCESS) {
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (ret);
+ }
- curr = raids;
+ if (f_flag == FALSE) {
+ (void) fprintf(stdout, gettext("Creating RAID volume "
+ "will destroy all data on spare space of member disks, "
+ "proceed (%s/%s)? "), yesstr, nostr);
+ if (!yes()) {
+ (void) fprintf(stdout, gettext("RAID volume "
+ "not created.\n\n"));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ free(disk_handlesp);
+ return (SUCCESS);
+ }
+ }
- /* add this controller to raids */
- while (curr->next != NULL)
- curr = curr->next;
+ /* Create array */
+ array_handle = raidcfg_create_array(comps_num,
+ disk_handlesp, raid_level, capacity, stripe_size, NULL);
- curr->next = (raidlist_t *)malloc(sizeof (raidlist_t));
- curr = curr->next;
- }
+ if (array_handle <= 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
+ free(disk_handlesp);
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
+ }
-already_there:
- /*
- * curr is now pointing to this controller. since we are
- * adding controllers one at a time from do_search(), set
- * curr->next to NULL so that we know where the end of our
- * currently added controllers lies.
- */
- curr->next = NULL;
- curr->controller = controller;
- (void) strlcpy(curr->devctl, buf1, sizeof (curr->devctl));
- (void) fflush(stdout);
- (void) memcpy(&curr->raid_config[n], &config,
- (sizeof (raid_config_t)));
+ /* Get attribute of the new created array */
+ if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ free(disk_handlesp);
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
}
- if (info_ctrl != NULL && info_ctrl[i][INFO_STATUS] != RAID_FOUND)
- info_ctrl[i][INFO_STATUS] = RAID_NOT_FOUND;
-}
+ (void) fprintf(stdout, gettext("Volume c%ut%llud%llu is created "
+ "successfully!\n"), ctl_tag, array_attr.tag.idl.target_id,
+ array_attr.tag.idl.lun);
-static void
-print_header()
-{
- (void) printf(gettext("RAID\tVolume\tRAID\t\tRAID\t\tDisk"));
- (void) printf("\n");
- (void) printf(gettext("Volume\tType\tStatus\t\tDisk\t\tStatus"));
- (void) printf("\n");
- (void) printf("------------------------------------------------------");
- (void) printf("\n");
-}
+ /* Print attribute of array */
+ (void) print_array_table(ctl_handle, array_handle);
-static void
-print_raidconfig(int c, raid_config_t config)
-{
- int i;
- char voltype[8];
-
- /* print RAID volume target ID and volume type */
- if (config.raid_level == RAID_STRIPE) {
- (void) snprintf(voltype, sizeof (voltype), "IS");
- } else if (config.raid_level == RAID_MIRROR) {
- (void) snprintf(voltype, sizeof (voltype), "IM");
- }
-
- (void) printf("c%dt%dd0\t%s\t", c, config.targetid, voltype);
-
- /* Get RAID Info */
- if (config.flags & RAID_FLAG_RESYNCING &&
- config.state == RAID_STATE_DEGRADED) {
- (void) printf(gettext("RESYNCING\t"));
- } else if (config.state == RAID_STATE_DEGRADED) {
- (void) printf(gettext("DEGRADED\t"));
- } else if (config.state == RAID_STATE_OPTIMAL) {
- (void) printf(gettext("OK\t\t"));
- } else if (config.state == RAID_STATE_FAILED) {
- (void) printf(gettext("FAILED\t\t"));
- } else {
- (void) printf(gettext("ERROR\t\t"));
- }
+ /* Close controller */
+ (void) raidcfg_close_controller(ctl_handle, NULL);
- /* Get RAID Disks */
- if (config.disk[0] != 0xff)
- (void) printf("c%dt%dd0\t\t", c, config.disk[0]);
- else
- (void) printf("-\t\t");
+ free(disk_handlesp);
+ return (SUCCESS);
+}
- /* Get RAID Disk's Status */
- if (config.diskstatus[0] & RAID_DISKSTATUS_FAILED) {
- (void) printf(gettext("FAILED\n"));
- } else if (config.diskstatus[0] & RAID_DISKSTATUS_MISSING) {
- (void) printf(gettext("MISSING\n"));
- } else {
- (void) printf(gettext("OK\n"));
+/*
+ * do_create_ctd(raid_levelp, disks_argpp, disks_num, argindex, f_flag)
+ * This function creates array with specified arguments, and return result
+ * as SUCCESS, FAILURE, or INVALID_ARG. It only supports LSI MPT controller
+ * to be compatible with old raidctl. The capacity and stripe size can't
+ * be specified for LSI MPT controller, and they use zero and default value.
+ * The "ctd" is the canonical expression of physical disks which are
+ * accessible by OS.
+ */
+static int
+do_create_ctd(char *raid_levelp, char **disks_argpp, uint32_t disks_num,
+ uint32_t argindex, uint32_t f_flag)
+{
+ uint32_t ctl_tag = MAX32BIT;
+ raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
+ uint32_t raid_level = RAID_LEVEL_1;
+ uint64_t capacity = 0;
+ uint32_t stripe_size = (uint32_t)OBJ_ATTR_NONE;
+ raid_obj_handle_t *disk_handlesp = NULL;
+ raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
+ raidcfg_controller_t ctl_attr;
+ int ret;
+
+ raidcfg_array_t array_attr;
+ int i, j;
+
+ /* Check disks parameter */
+ if (disks_argpp == NULL || disks_num < 2) {
+ return (INVALID_ARG);
}
- for (i = 1; i < config.ndisks; i++) {
- if (config.disk[i] != 0xff)
- (void) printf("\t\t\t\tc%dt%dd0\t\t", c,
- config.disk[i]);
- else
- (void) printf("\t\t\t\t-\t\t");
-
- if (config.diskstatus[i] & RAID_DISKSTATUS_FAILED) {
- (void) printf(gettext("FAILED\n"));
- } else if (config.diskstatus[i] & RAID_DISKSTATUS_MISSING) {
- (void) printf(gettext("MISSING\n"));
- } else {
- (void) printf(gettext("OK\n"));
+ for (i = 0, j = argindex; i < disks_num; i++, j++) {
+ if (disks_argpp[j] == NULL) {
+ return (INVALID_ARG);
}
}
-}
-static void
-print_disklist()
-{
- raidlist_t *curr = raids;
- int i;
+ /*
+ * We need check if the raid_level string is fully numeric. If user
+ * input string with unsupported letters, such as "s10", atoi() will
+ * return zero because it is an illegal string, but it doesn't mean
+ * RAID_LEVEL_0.
+ */
+ if (raid_levelp != NULL) {
+ if (*raid_levelp == '1' &&
+ (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) {
+ raid_level = RAID_LEVEL_1E;
+ } else {
+ if (is_fully_numeric(raid_levelp) == FALSE) {
+ return (INVALID_ARG);
+ }
- while (curr != NULL) {
- for (i = 0; i < N_RAIDVOLS; i++) {
- if (curr->raid_config[i].ndisks != 0) {
- print_raidconfig(curr->controller,
- curr->raid_config[i]);
+ switch (atoi(raid_levelp)) {
+ case 0:
+ raid_level = RAID_LEVEL_0;
+ break;
+ case 1:
+ raid_level = RAID_LEVEL_1;
+ break;
+ case 5:
+ raid_level = RAID_LEVEL_5;
+ break;
+ default:
+ return (INVALID_ARG);
}
}
- curr = curr->next;
}
-}
-static void
-free_disklist()
-{
- raidlist_t *curr = raids;
+ /* Get disks tag and controller tag */
+ disk_handlesp = (raid_obj_handle_t *)calloc(disks_num + 2,
+ sizeof (raid_obj_handle_t));
+ if (disk_handlesp == NULL) {
+ return (FAILURE);
+ }
- while (curr != NULL) {
- raidlist_t *temp;
- temp = curr;
- curr = curr->next;
- free(temp);
+ disk_handlesp[0] = OBJ_SEPARATOR_BEGIN;
+ disk_handlesp[disks_num + 1] = OBJ_SEPARATOR_END;
+
+ if ((ret = get_disk_handle_ctd(disks_num, &disks_argpp[argindex],
+ &ctl_tag, &disk_handlesp[1])) != SUCCESS) {
+ free(disk_handlesp);
+ return (ret);
}
-}
-static void
-do_search()
-{
- DIR *dir;
- struct dirent *dp;
- char buf[MAXPATHLEN];
- int c;
- int i, j;
+ /* LIB API should check whether all disks here belong to one ctl. */
+ /* get_disk_handle_ctd has opened controller. */
+ ctl_handle = raidcfg_get_controller(ctl_tag);
- /*
- * In case repeated numbers were found, assign the repititions as
- * RAID_DONT_USE
- */
- for (i = 0; i < ctrl_nums; i++) {
- int first_one = 1;
- for (j = 0; j < ctrl_nums; j++) {
- if (info_ctrl[i][INFO_CTRL] ==
- info_ctrl[j][INFO_CTRL]) {
- if (info_ctrl[j][INFO_STATUS] == RAID_DONT_USE)
- continue;
- if (first_one) {
- first_one = 0;
- } else {
- info_ctrl[j][INFO_STATUS] =
- RAID_DONT_USE;
- }
- }
- }
+ if (ctl_handle <= 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ free(disk_handlesp);
+ return (FAILURE);
}
- if ((dir = opendir("/dev/cfg")) == NULL) {
+ /* Check if the controller is host raid type */
+ if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ free(disk_handlesp);
+ return (FAILURE);
+ }
+
+ if ((ctl_attr.capability & RAID_CAP_DISK_TRANS) == 0) {
+ /* -c only support host raid controller, return failure here */
(void) fprintf(stderr,
- gettext("Cannot open /dev/cfg: %s\n"), strerror(errno));
- return;
+ gettext("Option -c only supports host raid controller.\n"));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ free(disk_handlesp);
+ return (FAILURE);
}
+
+ if (f_flag == FALSE) {
+ (void) fprintf(stdout, gettext("Creating RAID volume "
+ "will destroy all data on spare space of member disks, "
+ "proceed (%s/%s)? "), yesstr, nostr);
+ if (!yes()) {
+ (void) fprintf(stdout, gettext("RAID volume "
+ "not created.\n\n"));
+ free(disk_handlesp);
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (SUCCESS);
+ }
+ }
+
/*
- * iterate over the controllers and add any
- * controllers with RAID volumes to the raids
- * list, one at a time
+ * For old raidctl, capacity is 0, which means to creates
+ * max possible capacity of array.
*/
- while ((dp = readdir(dir)) != NULL) {
- if (strcmp(dp->d_name, ".") == 0 ||
- strcmp(dp->d_name, "..") == 0)
- continue;
- if (sscanf(dp->d_name, "c%d", &c) != 1)
- continue;
- (void) snprintf(buf, sizeof (buf), "/dev/cfg/%s", dp->d_name);
- add_raid_to_raidlist(buf, c);
- }
- (void) closedir(dir);
-}
-
-/*
- * do_info() will do the following:
- * - create a list of disks' devctls
- * - try to talk to each of the devctls found
- * - if raid configuration is found, display it.
- */
-static void
-do_info()
-{
- int i;
- (void) chdir(DEVDIR);
- do_search();
+ array_handle = raidcfg_create_array(disks_num + 2,
+ disk_handlesp, raid_level, capacity, stripe_size, NULL);
- if (raids == NULL) {
- if (info_ctrl != NULL) {
- print_no_raids();
- for (i = 0; i < ctrl_nums; i++)
- free(info_ctrl[i]);
- free(info_ctrl);
- } else {
- (void) printf(gettext("No RAID volumes found\n"));
- }
- return;
+ if (array_handle <= 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
+ free(disk_handlesp);
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
}
- print_header();
- print_disklist();
- print_no_raids();
- free_disklist();
- if (info_ctrl) {
- for (i = 0; i < ctrl_nums; i++)
- free(info_ctrl[i]);
- free(info_ctrl);
+ /* Get attribute of array */
+ if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ free(disk_handlesp);
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
}
+
+ /* Close controller */
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+
+ /* Print feedback for user */
+ (void) fprintf(stdout,
+ gettext("Volume c%ut%llud%llu is created successfully!\n"),
+ ctl_tag, array_attr.tag.idl.target_id,
+ array_attr.tag.idl.lun);
+ free(disk_handlesp);
+ return (SUCCESS);
}
+/*
+ * do_list(disk_arg, argv, optind, is_snapshot)
+ * This function lists RAID's system configuration. It supports various RAID
+ * controller. The return value can be SUCCESS, FAILURE, or INVALID_ARG.
+ */
static int
-disk_in_raid(int c, int t)
+do_list(char *disk_argp, char **argv, uint32_t optind, uint8_t is_snapshot)
{
- raidlist_t *curr;
- raid_config_t raid;
- int i, j, n;
-
- do_search();
- curr = raids;
-
- while (curr != NULL) {
- if (curr->controller == c) {
- for (i = 0; i < N_RAIDVOLS; i++) {
- raid = curr->raid_config[i];
- if ((n = raid.ndisks) != 0) {
- for (j = 0; j < n; j++) {
- if (raid.disk[j] == t) {
- return (1);
- }
+ uint32_t ctl_tag = MAX32BIT;
+ raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
+ raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
+ raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
+ disk_tag_t disk_tag;
+ array_tag_t array_tag;
+
+ int ret;
+
+ /* print RAID system */
+ if (disk_argp == NULL) {
+ if (argv[optind] == NULL) {
+ ret = snapshot_raidsystem(TRUE, 0, is_snapshot);
+ return (ret);
+ } else {
+ if (is_fully_numeric(argv[optind]) == TRUE) {
+ while (argv[optind] != NULL) {
+ if (get_ctl_tag(argv[optind], &ctl_tag)
+ != SUCCESS) {
+ ret = INVALID_ARG;
+ optind++;
+ continue;
+ }
+ ctl_handle =
+ raidcfg_get_controller(ctl_tag);
+ if (ctl_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ctl_handle));
+ ret = FAILURE;
+ optind++;
+ continue;
}
+ ret =
+ raidcfg_open_controller(ctl_handle,
+ NULL);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ret));
+ ret = FAILURE;
+ optind++;
+ continue;
+ }
+ if (is_snapshot == FALSE) {
+ ret =
+ print_ctl_table(ctl_handle);
+ } else {
+ ret =
+ snapshot_ctl(ctl_handle,
+ FALSE, 0, is_snapshot);
+ }
+ (void) raidcfg_close_controller(
+ ctl_handle, NULL);
+ optind++;
+ }
+ } else {
+ if (get_array_tag(argv[optind],
+ &ctl_tag, &array_tag) != SUCCESS) {
+ return (INVALID_ARG);
+ }
+ ctl_handle = raidcfg_get_controller(ctl_tag);
+ if (ctl_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ctl_handle));
+ return (FAILURE);
+ }
+
+ ret = raidcfg_open_controller(ctl_handle, NULL);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ret));
+ return (FAILURE);
+ }
+
+ array_handle = raidcfg_get_array(ctl_handle,
+ array_tag.idl.target_id, array_tag.idl.lun);
+ if (array_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(array_handle));
+ (void) raidcfg_close_controller(
+ ctl_handle, NULL);
+ return (FAILURE);
}
+ if (is_snapshot == FALSE) {
+ ret = print_array_table(ctl_handle,
+ array_handle);
+ } else {
+ ret = snapshot_array(array_handle, 0,
+ FALSE, is_snapshot);
+ }
+ (void) raidcfg_close_controller(
+ ctl_handle, NULL);
}
}
- curr = curr->next;
+ } else {
+ if (argv[optind + 1] != NULL) {
+ return (INVALID_ARG);
+ }
+
+ if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
+ return (INVALID_ARG);
+ }
+
+ ctl_handle = raidcfg_get_controller(ctl_tag);
+ if (ctl_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ctl_handle));
+ return (FAILURE);
+ }
+
+ if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
+ return (INVALID_ARG);
+ }
+
+ ret = raidcfg_open_controller(ctl_handle, NULL);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ret));
+ return (FAILURE);
+ }
+
+ disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
+ if (disk_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(disk_handle));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
+ }
+
+ if (is_snapshot == FALSE) {
+ ret = print_disk_table(ctl_handle, disk_handle);
+ } else {
+ ret = snapshot_disk(ctl_tag, disk_handle, 0,
+ is_snapshot);
+ }
+ (void) raidcfg_close_controller(ctl_handle, NULL);
}
- return (0);
+ return (ret);
}
+/*
+ * do_delete(f_flag, argv, optind)
+ * This function deletes a specified array, and return result as SUCCESS,
+ * FAILURE or INVALID_ARG.
+ */
static int
-disk_there(int c, int t)
+do_delete(uint32_t f_flag, char **argv, uint32_t optind)
{
- char disk[100];
- int fd;
+ uint32_t ctl_tag;
+ char *array_argp;
+ array_tag_t array_tag;
+ raid_obj_handle_t ctl_handle;
+ raid_obj_handle_t array_handle;
+ int ret;
+
+ array_argp = argv[optind];
+ if (array_argp == NULL || argv[optind + 1] != NULL) {
+ return (INVALID_ARG);
+ }
- (void) snprintf(disk, sizeof (disk), "c%dt%dd0s2", c, t);
+ if (get_array_tag(array_argp, &ctl_tag, &array_tag) != SUCCESS) {
+ return (INVALID_ARG);
+ }
- fd = open(disk, O_RDWR | O_NDELAY);
- if (fd == -1) {
- return (-1);
+ ctl_handle = raidcfg_get_controller(ctl_tag);
+ if (ctl_handle <= 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
+ return (INVALID_ARG);
}
- (void) close(fd);
- return (0);
-}
+ ret = raidcfg_open_controller(ctl_handle, NULL);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
+ }
-static int
-get_controller(char *dev)
-{
- raidlist_t *curr;
- int c;
- do_search();
- curr = raids;
- while (curr != NULL) {
- if (strcmp(curr->devctl, dev) == 0) {
- c = curr->controller;
- break;
+ array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id,
+ array_tag.idl.lun);
+ if (array_handle <= 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
+ }
+
+ if (f_flag == FALSE) {
+ (void) fprintf(stdout, gettext("Deleting RAID volume "
+ "%s will destroy all data it contains, "
+ "proceed (%s/%s)? "), array_argp, yesstr, nostr);
+ if (!yes()) {
+ (void) fprintf(stdout, gettext("RAID Volume "
+ "%s not deleted.\n\n"), array_argp);
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (SUCCESS);
}
- curr = curr->next;
}
- free_disklist();
- return (c);
-}
-static int
-disk_mounted(char *d)
-{
- struct mnttab mt;
- FILE *f = fopen("/etc/mnttab", "r");
+ if ((ret = raidcfg_delete_array(array_handle, NULL)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
+ }
- while (getmntent(f, &mt) != EOF)
- if (strstr(mt.mnt_special, d) != NULL)
- return (1);
+ (void) fprintf(stdout, gettext("Volume %s is deleted successfully!\n"),
+ array_argp);
+ (void) raidcfg_close_controller(ctl_handle, NULL);
- return (0);
+ return (SUCCESS);
}
+/*
+ * do_flash(f_flag, filep, ctls_argpp, index, ctl_num)
+ * This function downloads and updates firmware for specified controller, and
+ * return result as SUCCESS, FAILURE or INVALID_ARG.
+ */
static int
-disk_big_enough(char **d, diskaddr_t *cap, int *errcond)
+do_flash(uint8_t f_flag, char *filep, char **ctls_argpp,
+ uint32_t index, uint32_t ctl_num)
{
- struct dk_minfo minfo;
- char disk[N_DISKS][MAXPATHLEN];
- uint_t disk_lbsize[N_DISKS];
- diskaddr_t disk_capacity[N_DISKS];
- int i, fd;
-
- for (i = 0; i < N_DISKS; i++) {
- if (d[i] == NULL)
- break;
+ uint32_t ctl_tag = MAX32BIT;
+ char *ctl_argp = NULL;
+ raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
+ int ret;
+ int i, j;
+
+ if (ctl_num == 0)
+ return (INVALID_ARG);
+
+ for (i = 0, j = index; i < ctl_num; i++, j++) {
+ ctl_argp = ctls_argpp[j];
+ if (get_ctl_tag(ctl_argp, &ctl_tag) != SUCCESS) {
+ return (INVALID_ARG);
+ }
+
+ /* Ask user to confirm operation. */
+ if (f_flag == FALSE) {
+ (void) fprintf(stdout, gettext("Update flash image on "
+ "controller %d (%s/%s)? "), ctl_tag, yesstr, nostr);
+ if (!yes()) {
+ (void) fprintf(stdout,
+ gettext("Controller %d not "
+ "flashed.\n\n"), ctl_tag);
+ return (SUCCESS);
+ }
+ }
- (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]);
- fd = open(disk[i], O_RDWR | O_NDELAY);
- if (fd == -1)
+ if ((ctl_handle = raidcfg_get_controller(ctl_tag)) < 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ctl_handle));
return (FAILURE);
- if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == -1) {
- (void) close(fd);
+ }
+
+ ret = raidcfg_open_controller(ctl_handle, NULL);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
return (FAILURE);
}
- disk_lbsize[i] = minfo.dki_lbsize;
- disk_capacity[i] = minfo.dki_capacity;
+ (void) fprintf(stdout, gettext("Start updating controller "
+ "c%u firmware....\n"), ctl_tag);
- /* lbsize must be the same on all disks */
- if (disk_lbsize[0] != disk_lbsize[i]) {
- *errcond = 2;
- return (INVALID_ARG);
+ if ((ret = raidcfg_update_fw(ctl_handle, filep, NULL)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
}
- /* ensure drive capacity is greater than or equal to first */
- if (disk_capacity[0] > disk_capacity[i]) {
- *errcond = 1;
- return (INVALID_ARG);
- }
- (void) close(fd);
+ (void) fprintf(stdout, gettext("Update controller "
+ "c%u firmware successfully.\n"), ctl_tag);
+
+ (void) raidcfg_close_controller(ctl_handle, NULL);
}
- /*
- * setting capacity as the dk_minfo.dki_capacity of d[0]
- * this is the number of dki_lbsize blocks on disk
- */
- *cap = disk_capacity[0];
return (SUCCESS);
}
+/*
+ * do_set_hsp(a_argp, disk_argp, argv, optind)
+ * This function set or unset HSP relationship between disk and controller/
+ * array, and return result as SUCCESS, FAILURE or INVALID_ARG.
+ */
static int
-do_config_change_state(cfga_cmd_t cmd, int d, int c)
+do_set_hsp(char *a_argp, char *disk_argp, char **argv, uint32_t optind)
{
- cfga_err_t cfga_err;
- char *ap_id;
- int rv = SUCCESS;
- int count = 0;
+ uint32_t flag = MAX32BIT;
+ uint32_t ctl_tag = MAX32BIT;
+ array_tag_t array_tag;
+ raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
+ raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
+ raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
+ raidcfg_controller_t ctl_attr;
+ disk_tag_t disk_tag;
+
+ int ret;
+ int hsp_type;
+ raidcfg_hsp_relation_t hsp_relation;
+
+ (void) memset(&hsp_relation, 0, sizeof (raidcfg_hsp_relation_t));
+
+ if (a_argp == NULL) {
+ return (INVALID_ARG);
+ }
- ap_id = (char *)malloc(100);
- if (ap_id == NULL)
- return (FAILURE);
+ if (strcmp(a_argp, "set") == 0) {
+ flag = HSP_SET;
+ } else if (strcmp(a_argp, "unset") == 0) {
+ flag = HSP_UNSET;
+ } else {
+ return (INVALID_ARG);
+ }
- (void) snprintf(ap_id, 100, "c%d::dsk/c%dt%dd0", c, c, d);
+ if (disk_argp == NULL) {
+ return (INVALID_ARG);
+ }
- /*
- * If the config_change_state() funcation fails, we want to
- * retry. If the retry fails, then we return failure to fail.
- *
- * If we fail:
- *
- * If we were called from create, then we fail the raid
- * creation.
- *
- * If we were called from delete, then the disk will not
- * be re-configured by raidctl.
- */
- do {
- cfga_err = config_change_state(cmd, 1, &ap_id, NULL,
- NULL, NULL, NULL, 0);
- count++;
- } while (cfga_err != CFGA_OK && count < 2);
+ if (argv[optind] == NULL || argv[optind + 1] != NULL) {
+ return (INVALID_ARG);
+ } else if (is_fully_numeric(argv[optind]) == TRUE) {
+ /* Global HSP */
+ hsp_type = 0;
+ if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
+ return (INVALID_ARG);
+ }
- if (cfga_err != CFGA_OK)
- rv = FAILURE;
+ if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
+ return (INVALID_ARG);
+ }
- free(ap_id);
- return (rv);
-}
+ ctl_handle = raidcfg_get_controller(ctl_tag);
+ if (ctl_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ctl_handle));
+ return (FAILURE);
+ }
-static int
-do_create(char **d, int rlevel, int force)
-{
- raid_config_t config;
- raid_config_t newvol;
- char disk[N_DISKS][MAXPATHLEN] = {0};
- int map[N_DISKS];
- char channel1[MAXPATHLEN];
- char channel2[MAXPATHLEN];
- diskaddr_t capacity;
- int fd, fd2, size, errcond;
- int c[N_DISKS];
- int t[N_DISKS];
- char *tmp;
- int loc, i, devid, n, ndisks = 0;
-
- (void) chdir(DEVDIR);
-
- /* initialize target map */
- for (i = 0; i < N_DISKS; i++)
- map[i] = -1;
-
- for (i = 0; i < N_DISKS; i++) {
- if (d[i] == NULL)
- break;
+ ret = raidcfg_open_controller(ctl_handle, NULL);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
+ }
- if ((sscanf(d[i], "c%dt%dd0", &c[i], &t[i])) != 2 ||
- t[i] < 0) {
- (void) fprintf(stderr,
- gettext("Invalid disk format.\n"));
+ disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
+ if (disk_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(disk_handle));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
+ }
+ } else {
+ /* Local HSP */
+ hsp_type = 1;
+ if (get_array_tag(argv[optind], &ctl_tag, &array_tag) !=
+ SUCCESS) {
return (INVALID_ARG);
}
- /* ensure that all disks are on the same controller, */
- if (c[i] != c[0]) {
- (void) fprintf(stderr, gettext("Disks must be "
- "on the same controller.\n"));
- return (INVALID_ARG);
+ /* Open controller */
+ ctl_handle = raidcfg_get_controller(ctl_tag);
+ if (ctl_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ctl_handle));
+ return (FAILURE);
+ }
+
+ ret = raidcfg_open_controller(ctl_handle, NULL);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
+ }
+
+ /* Get controller's attribute */
+ if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
}
- /* that all disks are online, */
- if (disk_there(c[0], t[i])) {
- (void) printf(gettext("Disk 'c%dt%dd0' is not "
- "present.\n"), c[0], t[i]);
- (void) printf(gettext("Cannot create RAID volume.\n"));
+ if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
+ (void) raidcfg_close_controller(ctl_handle, NULL);
return (INVALID_ARG);
}
- /* that there are no duplicate disks, */
- loc = t[i];
- if (map[loc] == -1) {
- map[loc] = t[i];
+ /* Get disk handle */
+ disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
+ if (disk_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(disk_handle));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
+ }
+
+ /* Get array handle */
+ array_handle = raidcfg_get_array(ctl_handle,
+ array_tag.idl.target_id, array_tag.idl.lun);
+ if (array_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(array_handle));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
+ }
+ }
+
+ hsp_relation.disk_handle = disk_handle;
+ if (hsp_type) {
+ /* Set or unset local HSP */
+ hsp_relation.array_handle = array_handle;
+ } else {
+ /* Set or unset global HSP */
+ hsp_relation.array_handle = OBJ_ATTR_NONE;
+ }
+
+ /* Perform operation of set or unset */
+ if (flag == HSP_SET) {
+ if ((ret = raidcfg_set_hsp(1, &hsp_relation, NULL)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
+ }
+
+ if (hsp_type) {
+ (void) printf(gettext("Set local HSP between disk %s "
+ "and RAID volume %s successfully.\n"),
+ disk_argp, argv[optind]);
} else {
- (void) fprintf(stderr,
- gettext("Disks must be different.\n"));
- return (INVALID_ARG);
+ (void) printf(gettext("Set global HSP between disk %s "
+ "and controller %s successfully.\n"),
+ disk_argp, argv[optind]);
+ }
+ } else {
+ if ((ret = raidcfg_unset_hsp(1, &hsp_relation, NULL)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
}
- /* that no disk is already in use by another volume, */
- if (disk_in_raid(c[0], t[i])) {
- (void) fprintf(stderr, gettext("Disk %s is already in "
- "a RAID volume.\n"), d[i]);
+ if (hsp_type) {
+ (void) printf(gettext("Unset local HSP between "
+ "disk %s and RAID volume %s successfully.\n"),
+ disk_argp, argv[optind]);
+ } else {
+ (void) printf(gettext("Unset global HSP between "
+ "disk %s and controller %s successfully.\n"),
+ disk_argp, argv[optind]);
+ }
+ }
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (SUCCESS);
+}
+
+/*
+ * do_set_array_attr(f_flag, p_argp, argv, optind)
+ * This function changes array's attribute when array is running.
+ * The changeable attribute is up to controller's feature.
+ * The return value can be SUCCESS, FAILURE or INVALID_ARG.
+ */
+static int
+do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, uint32_t optind)
+{
+ uint32_t ctl_tag = MAX32BIT;
+ array_tag_t array_tag;
+ uint32_t type = MAX32BIT;
+ uint32_t value = MAX32BIT;
+ raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
+ raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
+
+ char *param, *op = "=";
+
+ int ret;
+
+ if (argv[optind] == NULL || argv[optind + 1] != NULL) {
+ return (INVALID_ARG);
+ }
+
+ if (p_argp != NULL) {
+ param = strtok(p_argp, op);
+ if (strcmp(param, "wp") == 0) {
+ type = SET_CACHE_WR_PLY;
+ } else {
return (INVALID_ARG);
}
- /* that no target's id is lower than the raidtarg, */
- if (t[0] > t[i]) {
- (void) fprintf(stderr, gettext("First target ID must "
- "be less than other member target IDs.\n"));
+ param = strtok(NULL, op);
+ if (strcmp(param, "on") == 0) {
+ value = CACHE_WR_ON;
+ } else if (strcmp(param, "off") == 0) {
+ value = CACHE_WR_OFF;
+ } else {
return (INVALID_ARG);
}
- (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]);
- ndisks++;
+ } else {
+ return (INVALID_ARG);
}
- /* confirm minimum number of disks */
- if (ndisks < 2) {
- (void) fprintf(stderr, gettext("At least two disks are required"
- " for RAID creation.\n"));
+ if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != SUCCESS) {
return (INVALID_ARG);
}
- /* validate the drive capacities */
- switch (disk_big_enough(d, &capacity, &errcond)) {
- case FAILURE:
+ ctl_handle = raidcfg_get_controller(ctl_tag);
+ if (ctl_handle <= 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
return (FAILURE);
- case INVALID_ARG:
- switch (errcond) {
- case 1:
- (void) fprintf(stderr, gettext("Cannot create RAID volume when "
- "primary disk is larger than secondary disk.\n"));
- break;
- case 2:
- (void) fprintf(stderr, gettext("Cannot create RAID volume when "
- "disk block sizes differ.\n"));
- }
- return (INVALID_ARG);
}
- /*
- * capacity is now set to the number of blocks on a disk, which is
- * the total capacity of a mirror. the capacity of a stripe is the
- * cumulative amount of blocks on all disks
- */
- if (rlevel == RAID_STRIPE)
- capacity *= ndisks;
-
- if (get_devctl(disk[0], channel1))
+ ret = raidcfg_open_controller(ctl_handle, NULL);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
return (FAILURE);
+ }
- fd = open(channel1, O_RDONLY);
- if (fd == -1) {
- perror(channel1);
+ array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id,
+ array_tag.idl.lun);
+ if (array_handle <= 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
return (FAILURE);
}
- /*
- * query the HBA driver for volume capacity
- */
- if (ioctl(fd, RAID_NUMVOLUMES, &n) < 0) {
- raidctl_error("RAID_NUMVOLUMES");
- goto fail;
+ /* Ask user to confirm operation. */
+ if (f_flag == FALSE) {
+ (void) fprintf(stdout, gettext("Update attribute of "
+ "array %s (%s/%s)? "), argv[optind], yesstr, nostr);
+ if (!yes()) {
+ (void) fprintf(stdout,
+ gettext("Array %s not "
+ "changed.\n\n"), argv[optind]);
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (SUCCESS);
+ }
}
- /*
- * current support for both LSI1030 and LSI1064/1068 HBAs
- */
- if (ioctl(fd, RAID_GETDEVID, &devid) < 0) {
- raidctl_error("RAID_GETDEVID");
- goto fail;
- }
-
- if ((devid == LSI_1064) || (devid == LSI_1064E) ||
- (devid == LSI_1068) || (devid == LSI_1068E)) {
- /*
- * no secondary channel, just check to make
- * sure we can fit a new volume
- */
- for (i = 0; i < n; i++) {
- config.unitid = i;
- if (ioctl(fd, RAID_GETCONFIG, &config) < 0) {
- raidctl_error("RAID_GETCONFIG");
- goto fail;
- }
+ if ((ret = raidcfg_set_attr(array_handle, type, &value, NULL)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
+ }
- if (config.ndisks == 0)
- break;
- }
+ (void) printf(gettext("Set attribute of RAID volume %s "
+ "successfully.\n"), argv[optind]);
+ (void) raidcfg_close_controller(ctl_handle, NULL);
- if (i == n) {
- (void) printf(gettext("HBA supports a maximum of %d "
- "RAID Volumes, HBA is full\n"), n);
- goto fail;
- }
-
- /*
- * we have the capacity to add a volume, now confirm the
- * creation. the 1064/1068 uses a much larger metadata region
- * than the 1030 (64MB, as opposed to 16KB). this larger
- * reservation is enough to alter the disk label. therefore,
- * once the volume is created, it must be relabeled.
- * first, confirm that no file systems are mounted, as
- * we will be pulling the disk out from under them
- */
- for (i = 0; i < ndisks; i++) {
- if (disk_mounted(d[i])) {
- (void) fprintf(stderr, gettext("Cannot create "
- "RAID volume, disk \"%s\" is mounted "
- ".\n"), d[i]);
- return (INVALID_ARG);
- }
- }
+ return (SUCCESS);
+}
- /*
- * will not support data migration or disk relabeling with
- * this utility, and so next we must confirm the creation as
- * all data on member disks will be lost.
- */
- if (!force) {
- (void) fprintf(stderr, gettext("Creating RAID volume "
- "c%dt%dd0 will destroy all data on member disks, "
- "proceed (%s/%s)? "), c[0], t[0], yeschr, nochr);
- if (!yes()) {
- (void) fprintf(stderr, gettext("RAID volume "
- "c%dt%dd0 not created.\n\n"), c[0], t[0]);
- (void) close(fd);
- return (SUCCESS);
+/*
+ * snapshot_raidsystem(recursive, indent, is_snapshot)
+ * This function prints the snapshot of whole RAID's system configuration,
+ * and return result as SUCCESS or FAILURE.
+ */
+static int
+snapshot_raidsystem(uint8_t recursive, uint8_t indent, uint8_t is_snapshot)
+{
+ raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
+ int ret;
+
+ ctl_handle = raidcfg_list_head(OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
+ while (ctl_handle > 0) {
+ ret = raidcfg_open_controller(ctl_handle, NULL);
+ if (ret == 0) {
+ if (snapshot_ctl(ctl_handle, recursive, indent,
+ is_snapshot) == FAILURE) {
+ (void) raidcfg_close_controller(ctl_handle,
+ NULL);
}
}
-
- /*
- * we are ready to move onto the creation
- */
- goto no_secondary_channel;
+ ctl_handle = raidcfg_list_next(ctl_handle);
}
+ return (SUCCESS);
+}
- /*
- * LSI1030, support for single IM volume
- */
- if (rlevel != RAID_MIRROR) {
- (void) printf(gettext("HBA only supports RAID "
- "level 1 (mirrored) volumes\n"));
- goto fail;
- }
- /*
- * look up the volume configuration
- */
- config.unitid = n;
- if (ioctl(fd, RAID_GETCONFIG, &config) < 0) {
- raidctl_error("RAID_GETCONFIG");
- goto fail;
+/*
+ * snapshot_ctl(ctl_handle, recursive, indent, is_snapshot)
+ * This function prints snapshot of specified controller's configuration,
+ * and return result as SUCCESS or FAILURE.
+ */
+static int
+snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, uint8_t indent,
+ uint8_t is_snapshot)
+{
+ raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
+ raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
+ raidcfg_controller_t ctl_attr;
+ uint32_t ctl_tag;
+ char ctlbuf[256];
+ int ret;
+
+ if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
}
- if (config.ndisks != 0) {
- (void) printf(gettext("RAID Volume already exists "
- "on this controller 'c%dt%dd0'\n"),
- c[0], config.targetid);
- goto fail;
+ ctl_tag = ctl_attr.controller_id;
+ if (is_snapshot == FALSE) {
+ print_indent(indent);
+ (void) fprintf(stdout, gettext("Controller: %u\n"), ctl_tag);
+ } else {
+ (void) snprintf(ctlbuf, sizeof (ctlbuf), "%u \"%s\"",
+ ctl_tag, ctl_attr.controller_type);
+ (void) fprintf(stdout, "%s", ctlbuf);
+
+ (void) fprintf(stdout, "\n");
}
- /*
- * Make sure there isn't a raid created on this controller's
- * other channel, if it has multiple channels
- */
- (void) strlcpy(channel2, channel1, sizeof (channel2));
- tmp = strrchr(channel2, ':');
- tmp[0] = 0;
- size = strlen(channel2);
+ if (recursive == TRUE) {
+ array_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_ARRAY);
+ while (array_handle > 0) {
+ if (snapshot_array(array_handle,
+ indent + 1, FALSE, is_snapshot) == FAILURE) {
+ return (FAILURE);
+ }
- /*
- * Make sure that the secondary disk is not mounted
- */
- if (disk_mounted(disk[1])) {
- (void) fprintf(stderr, gettext("Cannot create RAID volume when "
- "secondary disk \"%s\" is mounted.\n"), disk[1]);
- return (INVALID_ARG);
- }
+ array_handle = raidcfg_list_next(array_handle);
+ }
- /*
- * Format the channel string for the other channel so we can
- * see if a raid exists on it. In this case if we are being
- * asked to create a raid on channel 2 (indicated by the 1,1
- * at the end of the string) we want to check channel 1),
- * otherwise we will check channel 2.
- */
- if (channel2[size - 2] == ',') {
- channel2[size - 1] = 0;
- channel2[size - 2] = 0;
- (void) snprintf(channel2, sizeof (channel2),
- "%s:devctl", channel2);
- } else {
- (void) snprintf(channel2, sizeof (channel2),
- "%s,1:devctl", channel2);
- }
+ disk_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_DISK);
+ while (disk_handle > 0) {
+ if (snapshot_disk(ctl_tag, disk_handle,
+ indent + 1, is_snapshot) == FAILURE) {
+ return (FAILURE);
+ }
- fd2 = open(channel2, O_RDONLY);
- if (fd2 == -1) {
- if (errno == ENOENT)
- goto no_secondary_channel;
- perror(channel2);
- goto fail;
+ disk_handle = raidcfg_list_next(disk_handle);
+ }
}
+ return (SUCCESS);
+}
- if (ioctl(fd2, RAID_GETCONFIG, &config) < 0) {
- goto fail;
+
+/*
+ * snapshot_array(array_handle, indent, is_sub, is_snapshot)
+ * This function prints snapshot of specified array's configuration,
+ * and return result as SUCCESS or FAILURE.
+ */
+static int
+snapshot_array(raid_obj_handle_t array_handle, uint8_t indent, uint8_t is_sub,
+ uint8_t is_snapshot)
+{
+ raid_obj_handle_t ctl_handle;
+ raid_obj_handle_t subarray_handle;
+ raid_obj_handle_t arraypart_handle;
+ raid_obj_handle_t task_handle;
+
+ raidcfg_controller_t ctl_attr;
+ raidcfg_array_t array_attr;
+ raidcfg_arraypart_t arraypart_attr;
+ raidcfg_task_t task_attr;
+
+ char arraybuf[256] = "\0";
+ char diskbuf[256] = "\0";
+ char tempbuf[256] = "\0";
+ int disknum = 0;
+
+ uint32_t ctl_tag;
+ int ret;
+
+ ctl_handle = raidcfg_get_container(array_handle);
+ ret = raidcfg_get_attr(ctl_handle, &ctl_attr);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
}
+ ctl_tag = ctl_attr.controller_id;
- if (config.ndisks != 0) {
- int cx;
- cx = get_controller(channel2);
- (void) printf(gettext("RAID Volume already exists "
- "on this controller 'c%dt%dd0'\n"), cx,
- config.targetid);
- goto fail;
+ /* Print array attribute */
+ if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
}
-no_secondary_channel:
+ if (is_snapshot == FALSE) {
+ print_indent(indent);
+ if (is_sub == FALSE) {
+ (void) fprintf(stdout, gettext("Volume:"
+ "c%ut%llud%llu\n"),
+ ctl_tag, array_attr.tag.idl.target_id,
+ array_attr.tag.idl.lun);
+ } else {
+ (void) fprintf(stdout, gettext("Sub-Volume\n"));
+ }
+ } else {
+ (void) snprintf(arraybuf, sizeof (arraybuf), "c%ut%llud%llu ",
+ ctl_tag, array_attr.tag.idl.target_id,
+ array_attr.tag.idl.lun);
+
+ /* Check if array is in sync state */
+ task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK);
+ if (task_handle > 0) {
+ (void) raidcfg_get_attr(task_handle, &task_attr);
+ if (task_attr.task_func == TASK_FUNC_BUILD) {
+ array_attr.state = ARRAY_STATE_SYNC;
+ }
+ } else {
+ subarray_handle = raidcfg_list_head(array_handle,
+ OBJ_TYPE_ARRAY);
+ while (subarray_handle > 0) {
+ task_handle = raidcfg_list_head(subarray_handle,
+ OBJ_TYPE_TASK);
+ if (task_handle > 0) {
+ (void) raidcfg_get_attr(task_handle,
+ &task_attr);
+ if (task_attr.task_func ==
+ TASK_FUNC_BUILD) {
+ array_attr.state =
+ ARRAY_STATE_SYNC;
+ }
+ break;
+ }
+ subarray_handle =
+ raidcfg_list_next(subarray_handle);
+ }
+ }
- /* all checks complete, fill in the config */
- newvol.targetid = t[0];
- newvol.disk[0] = t[0];
- newvol.raid_level = rlevel;
- newvol.ndisks = ndisks;
- newvol.raid_capacity = capacity;
+ /* Print sub array */
+ subarray_handle = raidcfg_list_head(array_handle,
+ OBJ_TYPE_ARRAY);
+ while (subarray_handle > 0) {
+ /* print subarraypart */
+ arraypart_handle = raidcfg_list_head(subarray_handle,
+ OBJ_TYPE_ARRAY_PART);
+ while (arraypart_handle > 0) {
+ if ((ret = raidcfg_get_attr(arraypart_handle,
+ &arraypart_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ret));
+ return (FAILURE);
+ }
- /* populate config.disk, and unconfigure all disks, except targetid */
- for (i = 1; i < ndisks; i++) {
- if (do_config_change_state(CFGA_CMD_UNCONFIGURE,
- t[i], c[0])) {
- perror("config_change_state");
- goto fail;
+ if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
+ (void) snprintf(tempbuf,
+ sizeof (tempbuf),
+ gettext("N/A"));
+ } else {
+ (void) snprintf(tempbuf,
+ sizeof (tempbuf),
+ "%llu.%llu.%llu",
+ arraypart_attr.tag.cidl.bus,
+ arraypart_attr.tag.cidl.target_id,
+ arraypart_attr.tag.cidl.lun);
+ }
+ (void) strcat(diskbuf, tempbuf);
+ (void) strcat(diskbuf, " ");
+ disknum++;
+ arraypart_handle =
+ raidcfg_list_next(arraypart_handle);
+ }
+ subarray_handle = raidcfg_list_next(subarray_handle);
}
- newvol.disk[i] = t[i];
- }
- if (ioctl(fd, RAID_CREATE, &newvol)) {
- /* reconfigure all disks, except targetid */
- for (i = 1; i < ndisks; i++) {
- (void) do_config_change_state(CFGA_CMD_CONFIGURE,
- newvol.disk[i], c[0]);
+ /* Print arraypart */
+ arraypart_handle = raidcfg_list_head(array_handle,
+ OBJ_TYPE_ARRAY_PART);
+ while (arraypart_handle > 0) {
+ if ((ret = raidcfg_get_attr(arraypart_handle,
+ &arraypart_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ret));
+ return (FAILURE);
+ }
+
+ if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
+ (void) snprintf(tempbuf, sizeof (tempbuf),
+ gettext("N/A"));
+ } else {
+ (void) snprintf(tempbuf, sizeof (tempbuf),
+ "%llu.%llu.%llu",
+ arraypart_attr.tag.cidl.bus,
+ arraypart_attr.tag.cidl.target_id,
+ arraypart_attr.tag.cidl.lun);
+ }
+ (void) strcat(diskbuf, tempbuf);
+ (void) strcat(diskbuf, " ");
+ disknum++;
+ arraypart_handle = raidcfg_list_next(arraypart_handle);
}
- raidctl_error("RAID_CREATE");
- goto fail;
+ (void) snprintf(tempbuf, sizeof (tempbuf), "%u ", disknum);
+ (void) strcat(arraybuf, tempbuf);
+ (void) strcat(arraybuf, diskbuf);
+
+ switch (array_attr.raid_level) {
+ case RAID_LEVEL_0:
+ (void) sprintf(tempbuf, "0");
+ break;
+ case RAID_LEVEL_1:
+ (void) sprintf(tempbuf, "1");
+ break;
+ case RAID_LEVEL_1E:
+ (void) sprintf(tempbuf, "1E");
+ break;
+ case RAID_LEVEL_5:
+ (void) sprintf(tempbuf, "5");
+ break;
+ case RAID_LEVEL_10:
+ (void) sprintf(tempbuf, "10");
+ break;
+ case RAID_LEVEL_50:
+ (void) sprintf(tempbuf, "50");
+ break;
+ default:
+ (void) snprintf(tempbuf, sizeof (tempbuf),
+ gettext("N/A"));
+ break;
+ }
+ (void) strcat(arraybuf, tempbuf);
+ (void) fprintf(stdout, "%s ", arraybuf);
+
+ switch (array_attr.state) {
+ case ARRAY_STATE_OPTIMAL:
+ (void) fprintf(stdout, gettext("OPTIMAL"));
+ break;
+ case ARRAY_STATE_DEGRADED:
+ (void) fprintf(stdout, gettext("DEGRADED"));
+ break;
+ case ARRAY_STATE_FAILED:
+ (void) fprintf(stdout, gettext("FAILED"));
+ break;
+ case ARRAY_STATE_SYNC:
+ (void) fprintf(stdout, gettext("SYNC"));
+ break;
+ default:
+ (void) fprintf(stdout, gettext("N/A"));
+ break;
+ }
+ (void) fprintf(stdout, "\n");
}
- (void) printf(gettext("Volume 'c%dt%dd0' created\n"), c[0], t[0]);
- (void) close(fd);
- (void) close(fd2);
return (SUCCESS);
-
-fail:
- (void) close(fd);
- (void) close(fd2);
- return (FAILURE);
}
+/*
+ * snapshot_disk(ctl_tag, disk_handle, indent, is_snapshot)
+ * This function prints snapshot of specified disk's configuration, and return
+ * result as SUCCESS or FAILURE.
+ */
static int
-do_delete(char *d, int force)
+snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, uint8_t indent,
+ uint8_t is_snapshot)
{
- raid_config_t config;
- char disk1[MAXPATHLEN];
- char buf[MAXPATHLEN];
- int fd;
- int target;
- int ctrl;
- int i, j;
- int wrong_targ = 0;
- int nvols;
- uint8_t t;
-
- (void) chdir(DEVDIR);
-
- if ((sscanf(d, "c%dt%dd0", &ctrl, &target)) != 2) {
- (void) fprintf(stderr, gettext("Invalid disk format.\n"));
- return (INVALID_ARG);
+ raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
+ raid_obj_handle_t hsp_handle;
+
+ raidcfg_controller_t ctl_attr;
+ raidcfg_disk_t disk_attr;
+ char diskbuf[256] = "";
+ char tempbuf[256] = "";
+
+ int ret;
+
+ ctl_handle = raidcfg_get_controller(ctl_tag);
+ ret = raidcfg_get_attr(ctl_handle, &ctl_attr);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
}
- t = (uint8_t)target;
- (void) snprintf(disk1, sizeof (disk1), DEVDIR"/%ss2", d);
+ /* Print attribute of disk */
+ if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
+ }
+
+ if (is_snapshot == FALSE) {
+ print_indent(indent);
- if (get_devctl(disk1, buf) != 0) {
- (void) fprintf(stderr, gettext("Not a volume '%s'\n"), d);
+ hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
+
+ if (disk_attr.tag.cidl.bus == MAX64BIT) {
+ (void) fprintf(stdout, gettext("Disk: N/A"));
+ } else {
+ (void) fprintf(stdout, gettext("Disk: %llu.%llu.%llu"),
+ disk_attr.tag.cidl.bus,
+ disk_attr.tag.cidl.target_id,
+ disk_attr.tag.cidl.lun);
+ }
+ if (hsp_handle > 0) {
+ (void) fprintf(stdout, "(HSP)");
+ }
+ (void) fprintf(stdout, "\n");
+ } else {
+ if (disk_attr.tag.cidl.bus == MAX64BIT) {
+ (void) fprintf(stdout, gettext("N/A"));
+ } else {
+ (void) snprintf(diskbuf, sizeof (diskbuf),
+ "%llu.%llu.%llu ",
+ disk_attr.tag.cidl.bus,
+ disk_attr.tag.cidl.target_id,
+ disk_attr.tag.cidl.lun);
+ }
+ hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
+ if (hsp_handle > 0) {
+ (void) snprintf(tempbuf, sizeof (tempbuf),
+ gettext("HSP"));
+ } else if (disk_attr.state == DISK_STATE_GOOD) {
+ (void) snprintf(tempbuf, sizeof (tempbuf),
+ gettext("GOOD"));
+ } else if (disk_attr.state == DISK_STATE_FAILED) {
+ (void) snprintf(tempbuf, sizeof (tempbuf),
+ gettext("FAILED"));
+ } else {
+ (void) snprintf(tempbuf, sizeof (tempbuf),
+ gettext("N/A"));
+ }
+
+ (void) strcat(diskbuf, tempbuf);
+ (void) fprintf(stdout, "%s\n", diskbuf);
+ }
+
+ return (SUCCESS);
+}
+
+static int
+print_ctl_table(raid_obj_handle_t ctl_handle)
+{
+ raidcfg_controller_t ctl_attr;
+ char controller[8];
+ int ret;
+
+ if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
return (FAILURE);
}
- fd = open(buf, O_RDONLY);
- if (fd == -1) {
- perror(buf);
+ (void) fprintf(stdout, gettext("Controller\tType\t\tVersion"));
+ (void) fprintf(stdout, "\n");
+ (void) fprintf(stdout, "--------------------------------");
+ (void) fprintf(stdout, "--------------------------------");
+ (void) fprintf(stdout, "\n");
+
+ (void) snprintf(controller, sizeof (controller), "%u",
+ ctl_attr.controller_id);
+ (void) printf("c%s\t\t", controller);
+
+ (void) print_ctl_attr(&ctl_attr);
+ (void) fprintf(stdout, "\n");
+
+ return (SUCCESS);
+}
+
+static int
+print_array_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t array_handle)
+{
+ raidcfg_controller_t ctl_attr;
+ raidcfg_array_t array_attr;
+ raidcfg_array_t subarray_attr;
+ raidcfg_arraypart_t arraypart_attr;
+ raidcfg_task_t task_attr;
+
+ raid_obj_handle_t subarray_handle;
+ raid_obj_handle_t arraypart_handle;
+ raid_obj_handle_t task_handle;
+
+ char array[8];
+ char arraypart[8];
+ int ret;
+ int i;
+
+ /* Controller attribute */
+ if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
return (FAILURE);
}
- if (ioctl(fd, RAID_NUMVOLUMES, &nvols)) {
- raidctl_error("RAID_NUMVOLUMES");
- goto fail;
+ /* Array attribute */
+ if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
}
- for (i = 0; i < nvols; i++) {
- config.unitid = i;
- if (ioctl(fd, RAID_GETCONFIG, &config)) {
- raidctl_error("RAID_GETCONFIG");
- goto fail;
+ /* print header */
+ (void) fprintf(stdout, gettext("Volume\t\t\tSize\tStripe\tStatus\t"
+ " Cache\tRAID"));
+ (void) fprintf(stdout, "\n");
+ (void) fprintf(stdout, gettext("\tSub\t\t\tSize\t\t\tLevel"));
+ (void) fprintf(stdout, "\n");
+ (void) fprintf(stdout, gettext("\t\tDisk\t\t\t\t\t"));
+ (void) fprintf(stdout, "\n");
+ (void) fprintf(stdout, "--------------------------------");
+ (void) fprintf(stdout, "--------------------------------");
+ (void) fprintf(stdout, "\n");
+
+ /* print array */
+ (void) snprintf(array, sizeof (array), "c%ut%llud%llu",
+ ctl_attr.controller_id, array_attr.tag.idl.target_id,
+ array_attr.tag.idl.lun);
+ (void) fprintf(stdout, "%s\t\t\t", array);
+
+ /* check if array is in sync state */
+ task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK);
+ if (task_handle > 0) {
+ (void) raidcfg_get_attr(task_handle, &task_attr);
+ if (task_attr.task_func == TASK_FUNC_BUILD) {
+ array_attr.state = ARRAY_STATE_SYNC;
}
- if (config.ndisks != 0) {
- /* there is a RAID volume in this slot */
- if (config.targetid != t) {
- wrong_targ++;
- continue;
+ } else {
+ subarray_handle = raidcfg_list_head(array_handle,
+ OBJ_TYPE_ARRAY);
+ while (subarray_handle > 0) {
+ task_handle = raidcfg_list_head(subarray_handle,
+ OBJ_TYPE_TASK);
+ if (task_handle > 0) {
+ (void) raidcfg_get_attr(task_handle,
+ &task_attr);
+ if (task_attr.task_func == TASK_FUNC_BUILD) {
+ array_attr.state = ARRAY_STATE_SYNC;
+ }
+ break;
}
- /* and it's our target */
- break;
+ subarray_handle = raidcfg_list_next(subarray_handle);
}
}
- if (i == nvols) {
- /* we found no RAID volumes */
- (void) fprintf(stderr, gettext("No RAID volumes exist on "
- "controller '%d'\n"), ctrl);
- goto fail;
- }
+ (void) print_array_attr(&array_attr);
+ (void) fprintf(stdout, "\n");
- if (wrong_targ == nvols) {
- /* we found RAID volumes, but none matched */
- (void) fprintf(stderr,
- gettext("RAID volume 'c%dt%dd0' does not exist\n"),
- ctrl, t);
- goto fail;
- }
+ /* Print sub array */
+ i = 0; /* Count sub array number */
+ subarray_handle = raidcfg_list_head(array_handle, OBJ_TYPE_ARRAY);
+ while (subarray_handle > 0) {
+ if ((ret = raidcfg_get_attr(subarray_handle,
+ &subarray_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
+ }
- /* if this volume is a stripe, all data will be lost */
- if (config.raid_level == RAID_STRIPE) {
- if (disk_mounted(d)) {
- (void) fprintf(stderr, gettext("Cannot delete "
- "RAID0 volume, \"%s\" is mounted.\n"), d);
- return (INVALID_ARG);
+ /* Use sub0/sub1 here, not cxtxd0 for subarray */
+ (void) snprintf(array, sizeof (array), "sub%u", i++);
+ (void) fprintf(stdout, "\t%s\t\t", array);
+
+ /* Check if array is in sync */
+ task_handle = raidcfg_list_head(subarray_handle, OBJ_TYPE_TASK);
+ if (task_handle > 0) {
+ (void) raidcfg_get_attr(task_handle, &task_attr);
+ if (task_attr.task_func == TASK_FUNC_BUILD) {
+ subarray_attr.state = ARRAY_STATE_SYNC;
+ }
}
- if (!force) {
- (void) fprintf(stderr, gettext("Deleting volume "
- "c%dt%dd0 will destroy all data it contains, "
- "proceed (%s/%s)? "), ctrl, t, yeschr, nochr);
- if (!yes()) {
- (void) fprintf(stderr, gettext("RAID volume "
- "c%dt%dd0 not deleted.\n\n"), ctrl, t);
- (void) close(fd);
- return (SUCCESS);
+
+ (void) print_array_attr(&subarray_attr);
+ (void) fprintf(stdout, "\n");
+
+ /* Print subarraypart */
+ arraypart_handle = raidcfg_list_head(subarray_handle,
+ OBJ_TYPE_ARRAY_PART);
+ while (arraypart_handle > 0) {
+ if ((ret = raidcfg_get_attr(arraypart_handle,
+ &arraypart_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ret));
+ return (FAILURE);
}
+
+ if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
+ (void) snprintf(arraypart, sizeof (arraypart),
+ gettext("N/A"));
+ } else {
+ (void) snprintf(arraypart, sizeof (arraypart),
+ "%llu.%llu.%llu",
+ arraypart_attr.tag.cidl.bus,
+ arraypart_attr.tag.cidl.target_id,
+ arraypart_attr.tag.cidl.lun);
+ }
+
+ (void) fprintf(stdout, "\t\t%s\t", arraypart);
+ (void) print_arraypart_attr(&arraypart_attr);
+ (void) fprintf(stdout, "\n");
+ arraypart_handle = raidcfg_list_next(arraypart_handle);
}
+ subarray_handle = raidcfg_list_next(subarray_handle);
}
- /* if this volume is a mirror, prompt user to verify the operation */
- else if (config.raid_level == RAID_MIRROR && !force) {
- (void) fprintf(stderr, gettext("Are you sure you want to "
- "delete RAID-1 Volume c%dt%dd0(%s/%s)? "),
- ctrl, t, yeschr, nochr);
- if (!yes()) {
- (void) fprintf(stderr, gettext("RAID volume "
- "c%dt%dd0 not deleted.\n\n"), ctrl, t);
- (void) close(fd);
- return (SUCCESS);
+
+ /* Print arraypart */
+ arraypart_handle = raidcfg_list_head(array_handle,
+ OBJ_TYPE_ARRAY_PART);
+ while (arraypart_handle > 0) {
+ if ((ret = raidcfg_get_attr(arraypart_handle,
+ &arraypart_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
}
+
+ if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
+ (void) snprintf(arraypart, sizeof (arraypart),
+ gettext("N/A"));
+ } else {
+ (void) snprintf(arraypart, sizeof (arraypart),
+ "%llu.%llu.%llu",
+ arraypart_attr.tag.cidl.bus,
+ arraypart_attr.tag.cidl.target_id,
+ arraypart_attr.tag.cidl.lun);
+ }
+
+ (void) fprintf(stdout, "\t\t%s\t", arraypart);
+ (void) print_arraypart_attr(&arraypart_attr);
+ (void) fprintf(stdout, "\n");
+ arraypart_handle = raidcfg_list_next(arraypart_handle);
}
- if (ioctl(fd, RAID_DELETE, &t)) {
- perror("RAID_DELETE");
- goto fail;
+ return (SUCCESS);
+}
+
+static int
+print_disk_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle)
+{
+ raidcfg_controller_t ctl_attr;
+ raidcfg_disk_t disk_attr;
+ char disk[8];
+ int ret;
+
+ if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
}
- /* reconfigure all disks, except targetid */
- for (j = 1; j < config.ndisks; j++) {
- (void) do_config_change_state(CFGA_CMD_CONFIGURE,
- config.disk[j], ctrl);
+ if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
}
- (void) fprintf(stderr, gettext("Volume 'c%dt%dd0' deleted.\n"),
- ctrl, target);
- (void) close(fd);
+ /* Print header */
+ (void) fprintf(stdout, gettext("Disk\tVendor\tProduct\t\tCapacity\t"
+ "Status\tHSP"));
+ (void) fprintf(stdout, "\n");
+ (void) fprintf(stdout, "--------------------------------");
+ (void) fprintf(stdout, "--------------------------------");
+ (void) fprintf(stdout, "\n");
+
+
+ (void) snprintf(disk, sizeof (disk), "%llu.%llu.%llu",
+ disk_attr.tag.cidl.bus,
+ disk_attr.tag.cidl.target_id,
+ disk_attr.tag.cidl.lun);
+
+ (void) fprintf(stdout, "%s\t", disk);
+
+ (void) print_disk_attr(ctl_handle, disk_handle, &disk_attr);
+ (void) fprintf(stdout, "\n");
+
return (SUCCESS);
+}
-fail:
- (void) close(fd);
- return (FAILURE);
+/*
+ * print_ctl_attr(attrp)
+ * This function prints attribute of specified controller, and return
+ * result as SUCCESS or FAILURE.
+ */
+static int
+print_ctl_attr(raidcfg_controller_t *attrp)
+{
+ char type[CONTROLLER_TYPE_LEN];
+ char version[CONTROLLER_FW_LEN];
+
+ if (attrp == NULL) {
+ return (FAILURE);
+ }
+
+ (void) snprintf(type, sizeof (type), "%s", attrp->controller_type);
+ (void) fprintf(stdout, "%-16s", type);
+
+ (void) snprintf(version, sizeof (version), "%s", attrp->fw_version);
+ (void) fprintf(stdout, "%s", version);
+
+ return (SUCCESS);
}
-static void
-getimagetype(uint8_t *rombuf, int *imagetype)
+/*
+ * print_array_attr(attrp)
+ * This function prints attribute of specified array, and return
+ * result as SUCCESS or FAILURE.
+ */
+static int
+print_array_attr(raidcfg_array_t *attrp)
{
- uint8_t type = rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE];
- if (type == 0) {
- *imagetype = BIOS_IMAGE;
- return;
+ char capacity[8];
+ char stripe_size[8];
+ char raid_level[8];
+
+ if (attrp == NULL) {
+ return (FAILURE);
+ }
+
+ if (attrp->capacity != MAX64BIT) {
+ if (size_to_string(attrp->capacity, capacity, 8) != SUCCESS) {
+ return (FAILURE);
+ }
+ (void) printf("%s\t", capacity);
+ } else {
+ (void) printf(gettext("N/A\t"));
}
- if (type == 1) {
- *imagetype = FCODE_IMAGE;
- return;
+
+ if (attrp->stripe_size != MAX32BIT) {
+ (void) snprintf(stripe_size, sizeof (stripe_size), "%uK",
+ attrp->stripe_size / 1024);
+ (void) printf("%s\t", stripe_size);
+ } else {
+ (void) printf(gettext("N/A\t"));
}
+
+ switch (attrp->state) {
+ case ARRAY_STATE_OPTIMAL:
+ (void) printf("%-8s", gettext("OPTIMAL"));
+ break;
+ case ARRAY_STATE_DEGRADED:
+ (void) printf("%-8s", gettext("DEGRADED"));
+ break;
+ case ARRAY_STATE_FAILED:
+ (void) printf("%-8s", gettext("FAILED"));
+ break;
+ case ARRAY_STATE_SYNC:
+ (void) printf("%-8s", gettext("SYNC"));
+ break;
+ default:
+ (void) printf("%-8s", gettext("N/A"));
+ break;
+ }
+ (void) printf(" ");
+
+ if (attrp->write_policy == CACHE_WR_OFF) {
+ (void) printf(gettext("OFF"));
+ } else if (attrp->write_policy == CACHE_WR_ON) {
+ (void) printf(gettext("ON"));
+ } else {
+ (void) printf(gettext("N/A"));
+ }
+ (void) printf("\t");
+
+ switch (attrp->raid_level) {
+ case RAID_LEVEL_0:
+ (void) sprintf(raid_level, "RAID0");
+ break;
+ case RAID_LEVEL_1:
+ (void) sprintf(raid_level, "RAID1");
+ break;
+ case RAID_LEVEL_1E:
+ (void) sprintf(raid_level, "RAID1E");
+ break;
+ case RAID_LEVEL_5:
+ (void) sprintf(raid_level, "RAID5");
+ break;
+ case RAID_LEVEL_10:
+ (void) sprintf(raid_level, "RAID10");
+ break;
+ case RAID_LEVEL_50:
+ (void) sprintf(raid_level, "RAID50");
+ break;
+ default:
+ (void) snprintf(raid_level, sizeof (raid_level),
+ gettext("N/A"));
+ break;
+ }
+ (void) printf("%s", raid_level);
+
+ return (SUCCESS);
}
+/*
+ * print_arraypart_attr(attrp)
+ * This function print attribute of specified arraypart, and return
+ * result as SUCCESS or FAILURE.
+ */
static int
-getfcodever(uint8_t *rombuf, uint32_t nbytes, char **fcodeversion)
+print_arraypart_attr(raidcfg_arraypart_t *attrp)
{
- int x, y, size;
- int found_1 = 0, found_2 = 0;
- int image_length = 0;
- int no_of_images = 0;
- uint8_t *rombuf_1 = NULL;
- uint16_t image_units = 0;
+ char size[8];
- /*
- * Single Image - Open firmware image
- */
- if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] == 1) {
- rombuf_1 = rombuf + gw(rombuf + PCIR_OFF) + PCI_PDS_INDICATOR;
- no_of_images = 1;
- goto process_image;
+ if (attrp == NULL) {
+ return (FAILURE);
}
- /*
- * Combined Image - First Image - x86/PC-AT Bios image
- */
- if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] != 0) {
- (void) fprintf(stderr, gettext("This is neither open image"
- " nor Bios/Fcode combined image\n"));
- return (1);
+ if (attrp->size != MAX64BIT) {
+ if (size_to_string(attrp->size, size, 8) != SUCCESS) {
+ return (FAILURE);
+ }
+ (void) printf("%s\t", size);
+ } else {
+ (void) printf(gettext("N/A\t"));
}
- /*
- * Seek to 2nd Image
- */
- rombuf_1 = rombuf + gw(rombuf + PCI_ROM_PCI_DATA_STRUCT_PTR);
- image_units = gw(rombuf_1 + PCI_PDS_IMAGE_LENGTH);
- image_length = image_units * PCI_IMAGE_UNIT_SIZE;
- rombuf_1 += image_length;
+ (void) printf("\t");
- /*
- * Combined Image - Second Image - Open Firmware image
- */
- if (rombuf_1[PCI_PDS_CODE_TYPE] != 1) {
- (void) fprintf(stderr, gettext("This is neither open image"
- " nor Bios/Fcode combined image\n"));
- return (1);
+ if (attrp->state == DISK_STATE_GOOD) {
+ (void) printf(gettext("GOOD"));
+ } else if (attrp->state == DISK_STATE_FAILED) {
+ (void) printf(gettext("FAILED"));
+ } else {
+ (void) printf(gettext("N/A"));
}
- rombuf_1 += PCI_PDS_INDICATOR;
- no_of_images = 2;
+ (void) printf("\t");
-process_image:
- /*
- * This should be the last image
- */
- if (*rombuf_1 != LAST_IMAGE) {
- (void) fprintf(stderr, gettext("This is not a valid "
- "Bios/Fcode image file\n"));
- return (1);
+ return (SUCCESS);
+}
+
+/*
+ * print_disk_attr(ctl_handle, disk_handle, attrp)
+ * This function prints attribute of specified disk, and return
+ * result as SUCCESS or FAILURE.
+ */
+static int
+print_disk_attr(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle,
+ raidcfg_disk_t *attrp)
+{
+ char vendor[DISK_VENDER_LEN];
+ char product[DISK_PRODUCT_LEN];
+ char capacity[16];
+ char hsp[16];
+
+ raid_obj_handle_t hsp_handle;
+ raidcfg_hsp_t hsp_attr;
+ raidcfg_controller_t ctl_attr;
+ int ret;
+ char is_indent;
+
+ if (attrp == NULL) {
+ return (FAILURE);
}
- /*
- * Scan through the bios/fcode file to get the fcode version
- * 0x12 and 0x7 indicate the start of the fcode version string
- */
- for (x = 0; x < (nbytes - 8); x++) {
- if ((rombuf[x] == FCODE_VERS_KEY1) &&
- (rombuf[x+1] == FCODE_VERS_KEY2) &&
- (rombuf[x+2] == 'v') && (rombuf[x+3] == 'e') &&
- (rombuf[x+4] == 'r') && (rombuf[x+5] == 's') &&
- (rombuf[x+6] == 'i') && (rombuf[x+7] == 'o') &&
- (rombuf[x+8] == 'n')) {
- found_1 = 1;
- break;
+ (void) snprintf(vendor, sizeof (vendor), "%s", attrp->vendorid);
+ (void) printf("%s\t", vendor);
+
+ (void) snprintf(product, sizeof (product), "%s", attrp->productid);
+ (void) printf("%s\t", product);
+
+ if (attrp->capacity != MAX64BIT) {
+ if (size_to_string(attrp->capacity, capacity, 16) != SUCCESS) {
+ return (FAILURE);
}
+ (void) printf("%s\t\t", capacity);
+ } else {
+ (void) printf(gettext("N/A"));
}
- /*
- * Store the version string if we have found the beginning of it
- */
- if (found_1) {
- while (x > 0) {
- if (rombuf[--x] == FCODE_VERS_KEY1) {
- if (rombuf[x-1] != FCODE_VERS_KEY1) {
- x++;
- }
- break;
+ if (attrp->state == DISK_STATE_GOOD) {
+ (void) printf(gettext("GOOD"));
+ } else if (attrp->state == DISK_STATE_FAILED) {
+ (void) printf(gettext("FAILED"));
+ } else {
+ (void) printf(gettext("N/A"));
+ }
+ (void) printf("\t");
+
+ /* Controller attribute */
+ if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
+ return (FAILURE);
+ }
+
+ hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
+ if (hsp_handle == 0) {
+ (void) printf(gettext("N/A\n"));
+ } else {
+ is_indent = FALSE;
+ while (hsp_handle > 0) {
+ if ((ret = raidcfg_get_attr(hsp_handle,
+ &hsp_attr)) < 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ret));
+ return (FAILURE);
}
- }
- if (x > 0) {
- *fcodeversion = (char *)malloc(rombuf[x] + 1);
- for (y = 0; y < rombuf[x]; y++) {
- (*fcodeversion)[y] = rombuf[x+y+1];
+
+ if (is_indent == TRUE) {
+ (void) printf("\t\t\t\t\t\t\t");
+ } else {
+ is_indent = TRUE;
}
- (*fcodeversion)[y] = '\0';
- } else {
- found_1 = 0;
- }
- }
- /*
- * Scan through the bios/fcode file to get the Bios version
- * "@(#)" string indicates the start of the Bios version string
- * Append this version string, after already existing fcode version.
- */
- if (no_of_images == 2) {
- for (x = 0; x < (nbytes - 4); x++) {
- if ((rombuf[x] == '@') && (rombuf[x+1] == '(') &&
- (rombuf[x+2] == '#') && (rombuf[x+3] == ')')) {
- found_2 = 1;
- break;
+ if (hsp_attr.type == HSP_TYPE_LOCAL) {
+ (void) snprintf(hsp, sizeof (hsp),
+ "c%ut%llud%llu",
+ ctl_attr.controller_id,
+ hsp_attr.tag.idl.target_id,
+ hsp_attr.tag.idl.lun);
+ (void) printf("%s\n", hsp);
+ } else if (hsp_attr.type == HSP_TYPE_GLOBAL) {
+ (void) printf(gettext("Global\n"));
+ } else {
+ return (FAILURE);
}
- }
- if (found_2) {
- x += 4;
- (*fcodeversion)[y] = '\n';
- size = y + strlen((char *)(rombuf + x)) +
- strlen(BIOS_STR) + 2;
- *fcodeversion = (char *)realloc((*fcodeversion), size);
- y++;
- (*fcodeversion)[y] = '\0';
- (void) strlcat(*fcodeversion, BIOS_STR, size);
- (void) strlcat(*fcodeversion, (char *)(rombuf + x),
- size);
+ hsp_handle = raidcfg_list_next(hsp_handle);
}
}
-
- return ((found_1 || found_2) ? 0 : 1);
+ return (SUCCESS);
}
+
+/*
+ * print_indent(indent)
+ * This function prints specified number of tab characters. It's used to
+ * format layout.
+ */
static void
-getfwver(uint8_t *rombuf, char *fwversion)
+print_indent(uint8_t indent)
{
- (void) snprintf(fwversion, 8, "%d.%.2d.%.2d.%.2d",
- rombuf[FW_ROM_OFFSET_VERSION + 3],
- rombuf[FW_ROM_OFFSET_VERSION + 2],
- rombuf[FW_ROM_OFFSET_VERSION + 1],
- rombuf[FW_ROM_OFFSET_VERSION + 0]);
+ uint32_t i;
+ for (i = 0; i < indent; i++) {
+ (void) fprintf(stdout, "\t");
+ }
}
+/*
+ * get_disk_handle_cidl(ctl_tag, disks_argp, comps_num, handlespp)
+ * This function parses the string of disk argument, and gets the disks tag
+ * and separators from the string. Then it translates the tag to handle, and
+ * stores handles and separators to new buffer pointed by parameter handlespp.
+ * The format of disk_arg must be C:ID:L, for example, it is 0.1.0. The first
+ * "0" is channel number, and the second "1" is target number, and the third
+ * "0" is LUN number. The disk tags are separated by comma and parenthesis.
+ * Function returns SUCCESS or FAILURE.
+ */
static int
-getbioscodever(uint8_t *rombuf, uint32_t nbytes, char **biosversion)
+get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, int *comps_nump,
+ raid_obj_handle_t **handlespp)
{
- int x, size;
- int found = 0;
+ int len = 0;
+ int i = 0, j = 0;
+ char *p, *t;
+ char *delimit = " ";
+ char *disks_str;
+ disk_tag_t disk_tag;
+
+ if (disks_argp == NULL || comps_nump == NULL) {
+ return (FAILURE);
+ }
- for (x = 0; x < (nbytes - 4); x++) {
- if ((rombuf[x] == '@') && (rombuf[x+1] == '(') &&
- (rombuf[x+2] == '#') && (rombuf[x+3] == ')')) {
- found = 1;
- break;
- }
+ p = disks_argp;
+ len = strlen(disks_argp);
+
+ if ((disks_str = (char *)malloc(3 * len + 4)) == NULL) {
+ return (FAILURE);
+ }
+
+ /* Insert whitespace between disk tags, '(' , and ')' */
+ disks_str[j ++] = '(';
+ disks_str[j ++] = ' ';
+
+ while (p[i] != '\0') {
+ if (p[i] == ')' || p[i] == '(') {
+ disks_str[j ++] = ' ';
+ disks_str[j ++] = p[i];
+ disks_str[j ++] = ' ';
+ } else
+ disks_str[j ++] = p[i];
+ i ++;
+ }
+ disks_str[j ++] = ' ';
+ disks_str[j ++] = ')';
+ disks_str[j] = '\0';
+
+ len = strlen(disks_str) + 1;
+
+ if ((t = (char *)malloc(len)) == NULL) {
+ return (FAILURE);
}
+ (void) memcpy(t, disks_str, len);
+ p = strtok(t, delimit);
+ while (p != NULL) {
+ (*comps_nump)++;
+ p = strtok(NULL, delimit);
+ }
+ free(t);
- if (found) {
- x += 4;
- size = strlen((char *)(rombuf + x)) + strlen(BIOS_STR) + 1;
- *biosversion = (char *)realloc((*biosversion), size);
- bcopy((char *)(rombuf + x), *biosversion, size - 1);
- (*biosversion)[size - 1] = '\0';
+ *handlespp = calloc(*comps_nump, sizeof (raid_obj_handle_t));
+ if (*handlespp == NULL) {
+ return (FAILURE);
}
- return (found);
+ for (i = 0; i < *comps_nump; i++)
+ (*handlespp)[i] = INIT_HANDLE_VALUE;
+
+ i = 0;
+ p = strtok(disks_str, delimit);
+ while (p != NULL) {
+ if (*p == '(') {
+ (*handlespp)[i] = OBJ_SEPARATOR_BEGIN;
+ } else if (*p == ')') {
+ (*handlespp)[i] = OBJ_SEPARATOR_END;
+ } else {
+ if (get_disk_tag_cidl(p, &disk_tag) != SUCCESS) {
+ free(*handlespp);
+ free(disks_str);
+ return (INVALID_ARG);
+ }
+ (*handlespp)[i] =
+ raidcfg_get_disk(raidcfg_get_controller(ctl_tag),
+ disk_tag);
+ if ((*handlespp)[i] <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr((*handlespp)[i]));
+ free(*handlespp);
+ free(disks_str);
+ return (FAILURE);
+ }
+ }
+ p = strtok(NULL, delimit);
+ i++;
+ }
+ free(disks_str);
+ return (SUCCESS);
}
+/*
+ * get_disk_handle_ctd(disks_num, disks_argpp, ctl_tagp, disks_handlep)
+ * This function parses string of single disk with "ctd" format, for example,
+ * c0t0d0, and translates it to controller tag and disk tag.
+ * Then it calls lib api and get disk handle. The controller tag and disk
+ * handle are both returned by out parameters.
+ * The return value is SUCCESS or FAILURE.
+ */
static int
-checkfile(uint8_t *rombuf, uint32_t nbytes, uint32_t chksum, int *imagetype)
+get_disk_handle_ctd(int disks_num, char **disks_argpp, uint32_t *ctl_tagp,
+ raid_obj_handle_t *disks_handlep)
{
- char *imageversion = NULL;
- char *biosversion = NULL;
- char *fwversion;
+ raid_obj_handle_t ctl_handle;
+ disk_tag_t disk_tag;
+ uint32_t ctl_id;
+ int i;
+ int ret;
- fwversion = (char *)malloc(8);
+ if (disks_handlep == NULL) {
+ return (FAILURE);
+ }
- if (gw(&rombuf[0]) == PCIROM_SIG) {
+ for (i = 0; i < disks_num; i++) {
+ if (get_disk_tag_ctd(disks_argpp[i], &disk_tag, &ctl_id) !=
+ SUCCESS) {
+ return (INVALID_ARG);
+ }
- *imagetype = UNKNOWN_IMAGE;
- getimagetype(rombuf, imagetype);
+ *ctl_tagp = ctl_id;
- if (*imagetype == FCODE_IMAGE) {
- if (getfcodever(rombuf, nbytes, &imageversion) == 0 &&
- imageversion != NULL) {
- (void) printf(gettext("Image file contains "
- "fcode version \t%s\n"), imageversion);
- free(imageversion);
+ if (i == 0) {
+ ctl_handle = raidcfg_get_controller(*ctl_tagp);
+ if (ctl_handle <= 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ctl_handle));
+ return (FAILURE);
}
- } else if (*imagetype == BIOS_IMAGE) {
- if (getbioscodever(rombuf, nbytes, &biosversion) == 1 &&
- biosversion != NULL) {
- (void) printf(gettext("Image file contains "
- "BIOS version \t%s\n"), biosversion);
- free(biosversion);
+ ret = raidcfg_open_controller(ctl_handle, NULL);
+ if (ret < 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(ret));
+ return (FAILURE);
}
- } else {
- /* When imagetype equals to UNKNOWN_IMAGE */
- return (-1);
}
- } else if (gw(&rombuf[3]) == FW_ROM_ID) {
- if (chksum != 0) {
- (void) fprintf(stderr,
- gettext("The ROM checksum appears bad "
- "(%d)\n"), chksum);
- return (-1);
- }
- getfwver(rombuf, fwversion);
-
- if ((gw(&rombuf[FW_ROM_OFFSET_CHIP_TYPE]) &
- MPI_FW_HEADER_PID_PROD_MASK) ==
- MPI_FW_HEADER_PID_PROD_IM_SCSI) {
- (void) printf(gettext("ROM image contains "
- "MPT firmware version %s "
- "(w/Integrated Mirroring)\n"),
- fwversion);
- } else {
- (void) printf(gettext("ROM image contains "
- "MPT firmware ""version %s\n"),
- fwversion);
- }
- free(fwversion);
- } else {
-
-#ifdef DEBUG
- (void) fprintf(stderr, "Not valid FCODE image %x\n", gw(&rombuf[0]));
-#else
- (void) fprintf(stderr, gettext("Not valid FCODE image\n"));
-#endif
- return (-1);
+ if ((disks_handlep[i] =
+ raidcfg_get_disk(ctl_handle, disk_tag)) < 0) {
+ (void) fprintf(stderr, "%s\n",
+ raidcfg_errstr(disks_handlep[i]));
+ (void) raidcfg_close_controller(ctl_handle, NULL);
+ return (FAILURE);
+ }
}
- return (0);
+
+ return (SUCCESS);
}
+/*
+ * get_ctl_tag(argp)
+ * This function translates controller string to tag. The return value is
+ * SUCCESS if the string has legal format and is parsed successfully,
+ * or FAILURE if it fails.
+ */
static int
-updateflash(uint8_t *rombuf, uint32_t nbytes, char *devctl)
+get_ctl_tag(char *argp, uint32_t *ctl_tagp)
{
- int fd = 0;
- update_flash_t flashdata;
-
- fd = open(devctl, O_RDONLY);
- if (fd == -1) {
- perror(devctl);
- return (-1);
- }
- (void) memset(&flashdata, 0, sizeof (flashdata));
- flashdata.ptrbuffer = (caddr_t)rombuf;
- flashdata.size = nbytes;
- if ((rombuf[0] == 0x55) && (rombuf[1] == 0xaa)) {
- flashdata.type = FW_TYPE_FCODE;
- } else {
- flashdata.type = FW_TYPE_UCODE;
- }
-
- if (ioctl(fd, RAID_UPDATEFW, &flashdata)) {
- raidctl_error("RAID_UPDATEFW");
- (void) close(fd);
- return (-1);
+ if (argp == NULL || is_fully_numeric(argp) == FALSE ||
+ ctl_tagp == NULL) {
+ return (FAILURE);
}
-
- (void) close(fd);
- return (0);
+ *ctl_tagp = (atoi(argp));
+ return (SUCCESS);
}
+/*
+ * get_array_tag(argp, ctl_tagp, array_tagp)
+ * This function parses array string to get array tag and controller tag.
+ * The return value is SUCCESS if the string has legal format, or
+ * FAILURE if it fails.
+ */
static int
-readfile(char *filespec, uint8_t **rombuf, uint32_t *nbytes, uint32_t *chksum)
+get_array_tag(char *argp, uint32_t *ctl_tagp, array_tag_t *array_tagp)
{
- struct stat statbuf;
- uint32_t count;
- uint32_t checksum = 0;
- int fd, i;
- uint8_t *filebuf;
+ char *t = NULL;
+ char *cp = NULL;
+ char *tp = NULL;
+ char *dp = NULL;
+
+ uint32_t value_c = MAX32BIT;
+ uint32_t value_t = MAX32BIT;
+ uint32_t value_d = MAX32BIT;
+ int len = 0;
- if ((fd = open((const char *)filespec, O_RDONLY | O_NDELAY)) == -1) {
- perror(filespec);
- return (-1);
+ if (argp == NULL || (len = strlen(argp)) == 0 ||
+ array_tagp == NULL) {
+ return (FAILURE);
}
- if (fstat(fd, &statbuf) != 0) {
- perror("fstat");
- (void) fprintf(stderr,
- gettext("Error getting stats on file\n"));
- (void) close(fd);
- return (-1);
+ t = (char *)malloc(len + 1);
+ if (t == NULL) {
+ return (FAILURE);
}
-#ifdef DEBUG
- (void) printf("Filesize = %ld\n", statbuf.st_size);
-#endif
+ (void) memcpy(t, argp, len + 1);
- filebuf = (uint8_t *)realloc(*rombuf, statbuf.st_size + *nbytes);
+ /* Now remmber to release t memory if exception occurs */
+ if (((dp = strchr(t, 'd')) == NULL) ||
+ ((tp = strchr(t, 't')) == NULL) ||
+ ((cp = strchr(t, 'c')) == NULL)) {
+ free(t);
+ return (FAILURE);
+ }
+ cp = t;
- count = read(fd, filebuf + *nbytes, statbuf.st_size);
- (void) close(fd);
- if (count != statbuf.st_size) {
- perror("size check");
- (void) fprintf(stderr, gettext("File is corrupt\n"));
- return (-1);
+ *dp = '\0';
+ dp++;
+ *tp = '\0';
+ tp++;
+ cp++;
+
+ if (is_fully_numeric(dp) == FALSE ||
+ is_fully_numeric(tp) == FALSE ||
+ is_fully_numeric(cp) == FALSE) {
+ free(t);
+ return (FAILURE);
}
- for (i = 0; i < *nbytes; i++)
- checksum += filebuf[i] << (8 * (i & 3));
+ value_c = atoi(cp);
+ value_t = atoi(tp);
+ value_d = atoi(dp);
+
+ array_tagp->idl.target_id = value_t;
+ array_tagp->idl.lun = value_d;
- *rombuf = filebuf;
- *nbytes = *nbytes + count;
- *chksum = checksum;
+ if (ctl_tagp != NULL) {
+ *ctl_tagp = value_c;
+ }
- return (0);
+ free(t);
+ return (SUCCESS);
}
+/*
+ * get_disk_tag_ctd(argp, disk_tagp)
+ * This function parses disk string of ctd format, and translates it to
+ * disk tag and controller tag. The tags is returned by out parameters.
+ * The return value is SUCCESS if the string has legal format, or FAILURE
+ * if it fails.
+ */
static int
-yes(void)
+get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, uint32_t *ctl_tag)
{
- int i, b;
- char ans[SCHAR_MAX + 1];
+ char *t = NULL;
+ char *cp = NULL;
+ char *tp = NULL;
+ char *dp = NULL;
- for (i = 0; ; i++) {
- b = getchar();
- if (b == '\n' || b == '\0' || b == EOF) {
- ans[i] = 0;
- break;
- }
- if (i < SCHAR_MAX)
- ans[i] = b;
+ uint32_t value_c = MAX32BIT;
+ uint32_t value_t = MAX32BIT;
+ uint32_t value_d = MAX32BIT;
+
+ int len = 0;
+
+ if (argp == NULL || (len = strlen(argp)) == 0 ||
+ disk_tagp == NULL) {
+ return (FAILURE);
}
- if (i >= SCHAR_MAX) {
- i = SCHAR_MAX;
- ans[SCHAR_MAX] = 0;
+
+ t = (char *)malloc(len + 1);
+ if (t == NULL) {
+ return (FAILURE);
+ }
+
+ (void) memcpy(t, argp, len + 1);
+
+ /* Now remmber to release t memory if exception occurs */
+ if (((dp = strchr(t, 'd')) == NULL) ||
+ ((tp = strchr(t, 't')) == NULL) ||
+ ((cp = strchr(t, 'c')) == NULL)) {
+ free(t);
+ return (FAILURE);
}
- if ((i != 0) && ((strncmp(yeschr, ans, i)) == 0))
- return (1);
+ cp = t;
+
+ *dp = '\0';
+ dp++;
+ *tp = '\0';
+ tp++;
+ cp++;
- return (0);
+ if (is_fully_numeric(dp) == FALSE ||
+ is_fully_numeric(tp) == FALSE ||
+ is_fully_numeric(cp) == FALSE) {
+ free(t);
+ return (FAILURE);
+ }
+
+ value_c = atoi(cp);
+ value_t = atoi(tp);
+ value_d = atoi(dp);
+
+ disk_tagp->cidl.bus = 0;
+ disk_tagp->cidl.target_id = value_t;
+ disk_tagp->cidl.lun = value_d;
+ *ctl_tag = value_c;
+
+ free(t);
+ return (SUCCESS);
}
+/*
+ * get_disk_tag_cidl(argp, disk_tagp)
+ * This function parses disk string of cidl format and translates it to tag.
+ * The return value is disk tag if the string has legal format, or FAILURE
+ * if it fails.
+ */
static int
-do_flash(int c, char *fpath, int force)
+get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp)
{
- char devctl[MAXPATHLEN] = {0};
- char buf[MAXPATHLEN] = {0};
- int rv = 0;
- int imagetype;
- uint32_t nbytes = 0;
- uint32_t chksum;
- uint8_t *rombuf = NULL;
- char cwd[MAXPATHLEN];
+ int len = 0;
+ char *p = NULL;
+ char *t = NULL;
+ char *dot1p = NULL;
+ char *dot2p = NULL;
- /*
- * Read fw file
- */
- rv = readfile(fpath, &rombuf, &nbytes, &chksum);
- if (rv != 0) {
+ if (argp == NULL || (len = strlen(argp)) == 0) {
return (FAILURE);
}
- (void) getcwd(cwd, sizeof (cwd));
+ if (disk_tagp == NULL) {
+ return (FAILURE);
+ }
- (void) chdir(DEVDIR);
+ t = (char *)malloc(len + 1);
+ if (t == NULL) {
+ return (FAILURE);
+ }
- /* Get link from "/dev/cfg" */
- (void) snprintf(buf, sizeof (buf), "/dev/cfg/c%d", c);
- if (get_link_path(buf, devctl) != 0) {
- (void) fprintf(stderr,
- gettext("Invalid controller '%d'\n"), c);
- return (INVALID_ARG);
+ (void) memcpy(t, argp, len + 1);
+ p = t;
+
+ dot2p = strrchr(p, '.');
+ if (dot2p == NULL) {
+ free(t);
+ return (FAILURE);
}
+ *dot2p = '\0';
+ dot2p++;
- /* Check File */
- rv = checkfile(rombuf, nbytes, chksum, &imagetype);
- if (rv != 0) {
+ dot1p = strrchr(p, '.');
+ if (dot1p == NULL) {
+ free(t);
return (FAILURE);
}
+ *dot1p = '\0';
+ dot1p++;
- /* Confirm */
- if (!force) {
- (void) fprintf(stderr, gettext("Update flash image on "
- "controller %d (%s/%s)? "), c, yeschr, nochr);
- if (!yes()) {
- (void) fprintf(stderr, gettext("Controller %d not "
- "flashed.\n\n"), c);
- return (SUCCESS);
- }
+ /* Assert only 2 dots in this string */
+ if (strrchr(p, '.') != NULL) {
+ free(t);
+ return (FAILURE);
}
- /* Do Flash */
- if (updateflash(rombuf, nbytes, devctl)) {
- (void) fprintf(stderr, gettext("Flash not updated on "
- "Controller %d.\n\n"), c);
- return (INVALID_ARG);
+ while (*p == ' ')
+ p++;
+
+ if (is_fully_numeric(p) == FALSE ||
+ is_fully_numeric(dot1p) == FALSE ||
+ is_fully_numeric(dot2p) == FALSE) {
+ free(t);
+ return (FAILURE);
}
- (void) printf(gettext("Flash updated successfully.\n\n"));
+
+ disk_tagp->cidl.bus = atoi(p);
+ disk_tagp->cidl.target_id = atoi(dot1p);
+ disk_tagp->cidl.lun = atoi(dot2p);
+
+ free(t);
return (SUCCESS);
}
+/*
+ * calc_size(sizep, valp)
+ * This function calculates the value represented by string sizep.
+ * The string sizep can be decomposed into three parts: an initial,
+ * possibly empty, sequence of white-space characters; a subject digital
+ * sequence interpreted as an integer with unit k/K/m/M/g/G/t/T; and a
+ * final string of one or more unrecognized characters or white-sapce
+ * characters, including the terminating null. If unrecognized character
+ * exists or overflow happens, the conversion must fail and return
+ * INVALID_ARG. If the conversion is performed successfully, result will
+ * be saved into valp and function returns SUCCESS. It returns FAILURE
+ * when memory allocation fails.
+ */
static int
-fully_numeric(char *str)
+calc_size(char *sizep, uint64_t *valp)
{
- int size = strlen(str);
- int i;
+ int len;
+ uint64_t size;
+ uint64_t unit;
+ char *t = NULL;
+ char *tailp = NULL;
- for (i = 0; i < size; i++) {
- if (i == 0 && str[i] == '-' && size != 1)
- continue;
- if (!isdigit(str[i]))
- return (0);
+ if (sizep == NULL || valp == NULL) {
+ return (INVALID_ARG);
}
- return (1);
-}
-/*
- * Useful parsing macros
- */
-#define must_be(s, c) if (*s++ != c) return (0)
-#define skip_digits(s) while (isdigit(*s)) s++
+ len = strlen(sizep);
+ if (len == 0) {
+ return (INVALID_ARG);
+ }
+
+ t = (char *)malloc(len + 1);
+ if (t == NULL) {
+ return (FAILURE);
+ }
+
+ (void) memcpy(t, sizep, len + 1);
+
+ switch (*(t + len - 1)) {
+ case 'k':
+ case 'K':
+ unit = 1024ull;
+ errno = 0;
+ size = strtoll(t, &tailp, 0);
+ break;
+ case 'm':
+ case 'M':
+ unit = 1024ull * 1024ull;
+ errno = 0;
+ size = strtoll(t, &tailp, 0);
+ break;
+ case 'g':
+ case 'G':
+ unit = 1024ull * 1024ull * 1024ull;
+ errno = 0;
+ size = strtoll(t, &tailp, 0);
+ break;
+ case 't':
+ case 'T':
+ unit = 1024ull * 1024ull * 1024ull * 1024ull;
+ errno = 0;
+ size = strtoll(t, &tailp, 0);
+ break;
+ default:
+ /* The unit must be kilobyte at least. */
+ free(t);
+ return (INVALID_ARG);
+ }
+
+ *(t + len - 1) = '\0';
+ if (is_fully_numeric(t) != TRUE) {
+ free(t);
+ return (INVALID_ARG);
+ }
+
+ errno = 0;
+ size = strtoll(t, &tailp, 0);
+
+ /* Check overflow condition */
+ if (errno == ERANGE || (size > (MAX64BIT / unit))) {
+ free(t);
+ return (INVALID_ARG);
+ }
+
+ *valp = size * unit;
+ free(t);
+ return (SUCCESS);
+}
/*
- * Return true if a name is in the internal canonical form
+ * is_fully_numeric(str)
+ * This function checks if the string are legal numeric string. The beginning
+ * or ending characters can be white spaces.
+ * Return value is TRUE if the string are legal numeric string, or FALSE
+ * otherwise.
*/
static int
-canonical_name(char *name)
+is_fully_numeric(char *strp)
{
- must_be(name, 'c');
- skip_digits(name);
- if (*name == 't') {
- name++;
- skip_digits(name);
- }
- must_be(name, 'd');
- skip_digits(name);
- return (*name == 0);
-}
+ uint32_t len;
+ uint32_t i;
-int
-main(int argc, char **argv)
-{
- int rv = SUCCESS;
- int i, c;
- int findex = DO_HW_RAID_INFO;
- int controller;
- char *disks[N_DISKS] = {0};
- char *darg;
- char *farg;
- char *rarg;
- char *progname;
-
- int l_flag = 0;
- int c_flag = 0;
- int d_flag = 0;
- int f_flag = 0;
- int F_flag = 0;
- int r_flag = 0;
- int no_flags = 1;
- int r = RAID_MIRROR; /* default raid level is 1 */
- char *current_dir;
+ if (strp == NULL) {
+ return (FALSE);
+ }
- (void) setlocale(LC_ALL, "");
- (void) textdomain(TEXT_DOMAIN);
+ len = strlen(strp);
+ if (len == 0) {
+ return (FALSE);
+ }
- if (geteuid() != 0) {
- (void) fprintf(stderr, gettext("Must be root.\n"));
- exit(1);
+ /* Skip whitespace characters */
+ for (i = 0; i < len; i++) {
+ if (strp[i] != ' ') {
+ break;
+ }
}
- if ((progname = strrchr(argv[0], '/')) == NULL)
- progname = argv[0];
- else
- progname++;
+ /* if strp points all space characters */
+ if (i == len) {
+ return (FALSE);
+ }
- raids = NULL;
+ /* Check the digitals in string */
+ for (; i < len; i++) {
+ if (!isdigit(strp[i])) {
+ break;
+ }
+ }
- (void) strncpy(yeschr, nl_langinfo(YESSTR), SCHAR_MAX + 1);
- (void) strncpy(nochr, nl_langinfo(NOSTR), SCHAR_MAX + 1);
+ /* Check the ending string */
+ for (; i < len; i++) {
+ if (strp[i] != ' ') {
+ return (FALSE);
+ }
+ }
- while ((c = getopt(argc, argv, "cr:lfd:F:")) != EOF) {
- switch (c) {
- case 'c':
- if (argc < 4)
- usage(progname);
- findex = DO_HW_RAID_CREATE;
- c_flag = 1;
- no_flags = 0;
- break;
- case 'r':
- rarg = optarg;
- r = atoi(rarg);
- if ((r != RAID_STRIPE) && (r != RAID_MIRROR))
- usage(progname);
- r_flag = 1;
- break;
- case 'd':
- darg = optarg;
- d_flag = 1;
- findex = DO_HW_RAID_DELETE;
- no_flags = 0;
- break;
- case 'l':
- findex = DO_HW_RAID_INFO;
- l_flag = 1;
- no_flags = 0;
- break;
- case 'F':
- findex = DO_HW_RAID_FLASH;
- farg = optarg;
- F_flag = 1;
- no_flags = 0;
- break;
- case 'f':
- f_flag = 1;
- no_flags = 0;
+ return (TRUE);
+}
+
+static int
+yes(void)
+{
+ int i, b;
+ char ans[SCHAR_MAX + 1];
+
+ for (i = 0; ; i++) {
+ b = getchar();
+ if (b == '\n' || b == '\0' || b == EOF) {
+ ans[i] = 0;
break;
- case '?':
- default:
- usage(progname);
+ }
+ if (i < SCHAR_MAX) {
+ ans[i] = b;
}
}
+ if (i >= SCHAR_MAX) {
+ i = SCHAR_MAX;
+ ans[SCHAR_MAX] = 0;
+ }
- if (no_flags && argc > 1)
- usage(progname);
+ return (rpmatch(ans));
+}
- /* compatibility rules */
- if (c_flag && d_flag)
- usage(progname);
- if (l_flag && (d_flag || c_flag || f_flag || F_flag || r_flag))
- usage(progname);
- if (F_flag && (d_flag || c_flag || l_flag || r_flag))
- usage(progname);
+/*
+ * Function: int rpmatch(char *)
+ *
+ * Description:
+ *
+ * Internationalized get yes / no answer.
+ *
+ * Inputs:
+ * s -> Pointer to answer to compare against.
+ *
+ * Returns:
+ * TRUE -> Answer was affirmative
+ * FALSE -> Answer was negative
+ */
- switch (findex) {
- case DO_HW_RAID_INFO:
- if (l_flag) {
- /*
- * "raidctl" makes argc == 1
- * "-l" makes argc == 2
- */
- ctrl_nums = argc - 2;
- if (ctrl_nums != 0) {
- info_ctrl = (int **)
- malloc(ctrl_nums * sizeof (int));
- if (info_ctrl == NULL)
- return (FAILURE);
- }
- for (i = 0; i < ctrl_nums; i++) {
- char *tmp = argv[i + 2];
+static int
+rpmatch(char *s)
+{
+ int status;
- info_ctrl[i] = (int *)malloc(2 * sizeof (int));
- if (info_ctrl[i] == NULL) {
- free(info_ctrl);
- return (FAILURE);
- }
- if (fully_numeric(tmp)) {
- (void) sscanf(tmp, "%d",
- &info_ctrl[i][INFO_CTRL]);
- info_ctrl[i][INFO_STATUS] =
- RAID_INVALID_CTRL;
- } else {
- (void) fprintf(stderr,
- gettext("Invalid controller '%s'\n"),
- tmp);
- info_ctrl[i][INFO_STATUS] =
- RAID_DONT_USE;
- }
- }
- } else if (argc > 1) {
- usage(progname);
- }
+ /* match yesexpr */
+ status = regexec(&re, s, (size_t)0, NULL, 0);
+ if (status != 0) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
- do_info();
- break;
- case DO_HW_RAID_CREATE:
- for (i = 0; i < N_DISKS; i++) {
- int p = 2 + (r_flag * 2) + f_flag + i;
+static int
+size_to_string(uint64_t size, char *string, int len)
+{
+ int i = 0;
+ uint32_t remainder;
+ char unit[][2] = {" ", "K", "M", "G", "T"};
- if (p == argc)
- break;
+ if (string == NULL) {
+ return (FAILURE);
+ }
+ while (size > 1023) {
+ remainder = size % 1024;
+ size /= 1024;
+ i++;
+ }
- disks[i] = argv[p];
+ if (i > 4) {
+ return (FAILURE);
+ }
- if (!canonical_name(disks[i]))
- usage(progname);
+ remainder /= 103;
+ if (remainder == 0) {
+ (void) snprintf(string, len, "%llu", size);
+ } else {
+ (void) snprintf(string, len, "%llu.%1u", size,
+ remainder);
+ }
- /* no more than 2 disks for raid level 1 */
- if ((r == RAID_MIRROR) && (i > 1))
- usage(progname);
- }
+ /* make sure there is one byte for unit */
+ if ((strlen(string) + 1) >= len) {
+ return (FAILURE);
+ }
+ (void) strcat(string, unit[i]);
- rv = do_create(disks, r, f_flag);
- break;
- case DO_HW_RAID_DELETE:
- if (!canonical_name(darg))
- usage(progname);
+ return (SUCCESS);
+}
- rv = do_delete(darg, f_flag);
- break;
- case DO_HW_RAID_FLASH:
- ctrl_nums = argc - f_flag - 3;
- if (ctrl_nums == 0)
- usage(progname);
-
- current_dir = getcwd(NULL, MAXPATHLEN);
-
- for (i = 0; i < ctrl_nums; i++) {
- char *tmp = argv[i + 3 + f_flag];
- (void) chdir(current_dir);
- if (fully_numeric(tmp)) {
- (void) sscanf(tmp, "%d", &controller);
- rv = do_flash(controller, farg, f_flag);
- if (rv == FAILURE)
- break;
- } else {
- (void) fprintf(stderr,
- gettext("Invalid controller '%s'\n"),
- tmp);
- }
+/*
+ * Only one raidctl is running at one time.
+ */
+static int
+enter_raidctl_lock(int *fd)
+{
+ int fd0 = -1;
+ struct flock lock;
+
+ fd0 = open(RAIDCTL_LOCKF, O_CREAT|O_WRONLY, 0600);
+ if (fd0 < 0) {
+ (void) fprintf(stderr, gettext("raidctl:failed to open lockfile"
+ " '"RAIDCTL_LOCKF"': %s\n"), strerror(errno));
+ return (FAILURE);
+ }
+
+ *fd = fd0;
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+
+ if ((fcntl(fd0, F_SETLK, &lock) == -1) &&
+ (errno == EAGAIN || errno == EDEADLK)) {
+ if (fcntl(fd0, F_GETLK, &lock) == -1) {
+ (void) fprintf(stderr,
+ gettext("raidctl:enter_filelock error\n"));
+ return (FAILURE);
}
- free(current_dir);
- break;
- default:
- usage(progname);
+ (void) fprintf(stderr, gettext("raidctl:"
+ "enter_filelock:filelock is owned "
+ "by 'process %d'\n"), lock.l_pid);
+ return (FAILURE);
}
- return (rv);
+
+ return (SUCCESS);
+}
+
+static void
+exit_raidctl_lock(int fd)
+{
+ struct flock lock;
+
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ if (fcntl(fd, F_SETLK, &lock) == -1) {
+ (void) fprintf(stderr, gettext("raidctl: failed to"
+ " exit_filelock: %s\n"),
+ strerror(errno));
+ }
+ (void) close(fd);
}
diff --git a/usr/src/head/Makefile b/usr/src/head/Makefile
index f4cc4e82e0..1a92230e86 100644
--- a/usr/src/head/Makefile
+++ b/usr/src/head/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -135,6 +135,8 @@ HDRS= $($(MACH)_HDRS) $(ATTRDB_HDRS) \
pthread.h \
pw.h \
pwd.h \
+ raidcfg.h \
+ raidcfg_spi.h \
rctl.h \
re_comp.h \
regex.h \
diff --git a/usr/src/head/raidcfg.h b/usr/src/head/raidcfg.h
new file mode 100644
index 0000000000..995397b015
--- /dev/null
+++ b/usr/src/head/raidcfg.h
@@ -0,0 +1,103 @@
+/*
+ * 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
+ * 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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _RAIDCFG_H
+#define _RAIDCFG_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <raidcfg_spi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Reserved Raid object IDs;
+ * ID 0 is reserved for root object;
+ * ID 0 also stands for NONE OBJECT.
+ */
+#define OBJ_SYSTEM 0
+#define OBJ_NONE 0
+
+typedef int raid_obj_handle_t;
+
+/*
+ * API data structure definition
+ */
+typedef struct {
+ int array_handle;
+ int disk_handle;
+} raidcfg_hsp_relation_t;
+
+typedef controller_attr_t raidcfg_controller_t;
+typedef array_attr_t raidcfg_array_t;
+typedef disk_attr_t raidcfg_disk_t;
+
+typedef struct {
+ uint32_t associated_id;
+ uint32_t type;
+ array_tag_t tag;
+} raidcfg_hsp_t;
+
+typedef struct {
+ uint32_t disk_id;
+ uint32_t state;
+ uint64_t offset;
+ uint64_t size;
+ disk_tag_t tag;
+} raidcfg_arraypart_t;
+
+typedef diskseg_attr_t raidcfg_diskseg_t;
+typedef task_attr_t raidcfg_task_t;
+
+/*
+ * raidcfg common library APIs
+ */
+const char *raidcfg_errstr(int);
+int raidcfg_get_controller(uint32_t);
+int raidcfg_get_array(int, uint64_t, uint64_t);
+int raidcfg_get_disk(int, disk_tag_t);
+int raidcfg_open_controller(int, char **);
+int raidcfg_close_controller(int, char **);
+int raidcfg_get_type(int);
+int raidcfg_get_attr(int, void *);
+int raidcfg_get_container(int);
+int raidcfg_list_head(int, raid_obj_type_id_t);
+int raidcfg_list_next(int);
+int raidcfg_set_attr(int, uint32_t, void *, char **);
+int raidcfg_set_hsp(int, raidcfg_hsp_relation_t *, char **);
+int raidcfg_unset_hsp(int, raidcfg_hsp_relation_t *, char **);
+int raidcfg_create_array(int, int *, uint32_t, uint64_t, uint32_t, char **);
+int raidcfg_delete_array(int, char **);
+int raidcfg_update_fw(int, char *, char **);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RAIDCFG_H */
diff --git a/usr/src/head/raidcfg_spi.h b/usr/src/head/raidcfg_spi.h
new file mode 100644
index 0000000000..62c23fb42a
--- /dev/null
+++ b/usr/src/head/raidcfg_spi.h
@@ -0,0 +1,353 @@
+/*
+ * 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
+ * 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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_RAIDCFG_SPI_H
+#define _SYS_RAIDCFG_SPI_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Controller capabilities
+ */
+#define RAID_CAP_RAID0 1
+#define RAID_CAP_RAID1 1 << 1
+#define RAID_CAP_RAID1E 1 << 2
+#define RAID_CAP_RAID5 1 << 3
+#define RAID_CAP_RAID10 1 << 4
+#define RAID_CAP_RAID50 1 << 5
+#define RAID_CAP_G_HSP 1 << 6
+#define RAID_CAP_L_HSP 1 << 7
+#define RAID_CAP_DISK_TRANS 1 << 8
+#define RAID_CAP_FULL_DISK_ONLY 1 << 9
+#define RAID_CAP_SMART_ALLOC 1 << 10
+#define RAID_CAP_ARRAY_ALIGN 1 << 11
+
+/*
+ * General constants
+ */
+#define OBJ_SEPARATOR_BEGIN -1
+#define OBJ_SEPARATOR_END -2
+
+#define OBJ_ATTR_NONE -1
+
+/*
+ * Array RAID level definition
+ */
+#define RAID_LEVEL_0 1
+#define RAID_LEVEL_1 2
+#define RAID_LEVEL_1E 3
+#define RAID_LEVEL_5 4
+#define RAID_LEVEL_10 5
+#define RAID_LEVEL_50 6
+
+/*
+ * Array cache write policy
+ */
+#define CACHE_WR_OFF 0
+#define CACHE_WR_ON 1
+
+/*
+ * Array cache read policy
+ */
+#define CACHE_RD_OFF 0
+#define CACHE_RD_ON 1
+
+/*
+ * Array status
+ */
+#define ARRAY_STATE_OPTIMAL 0
+#define ARRAY_STATE_DEGRADED 1
+#define ARRAY_STATE_FAILED 2
+
+/*
+ * Disk state
+ */
+#define DISK_STATE_GOOD 0
+#define DISK_STATE_FAILED 1
+
+/*
+ * Array part state
+ */
+#define ARRAYPART_STATE_GOOD 0
+#define ARRAYPART_STATE_MISSED 1
+
+/*
+ * Disk segment state
+ */
+#define DISKSEG_STATE_GOOD 1
+#define DISKSEG_STATE_RESERVED 1 << 1
+#define DISKSEG_STATE_DEAD 1 << 2
+#define DISKSEG_STATE_NORMAL 1 << 3
+
+/*
+ * Controller connection type
+ */
+#define TYPE_UNKNOWN 0
+#define TYPE_SCSI 1
+#define TYPE_SAS 2
+
+#define RAID_TASK_SUSPEND 0
+#define RAID_TASK_RESUME 1
+#define RAID_TASK_TERMINATE 2
+
+#define HSP_TYPE_GLOBAL 0
+#define HSP_TYPE_LOCAL 1
+
+/*
+ * Sub-command of set attribute
+ */
+#define SET_CACHE_WR_PLY 0
+#define SET_CACHE_RD_PLY 1
+
+/*
+ * Sub-commands for act method of object
+ */
+#define ACT_CONTROLLER_OPEN 0
+#define ACT_CONTROLLER_CLOSE 1
+#define ACT_CONTROLLER_FLASH_FW 2
+
+/*
+ * Some definitions
+ */
+#define CONTROLLER_FW_LEN 32
+#define CONTROLLER_TYPE_LEN 32
+
+#define DISK_VENDER_LEN 8
+#define DISK_PRODUCT_LEN 16
+#define DISK_REV_LEN 4
+
+#define DISK_ID(c, id, l) ((c) << 7 | (l) << 4 | (id))
+#define BUS(disk_id) ((disk_id) >> 7)
+#define TARGET(disk_id) ((disk_id) & 0xf)
+#define LUN(disk_id) (((disk_id) >> 4) & 0x7)
+
+#define ARRAY_ID(id, l) ((l) << 16 | (id))
+#define ARRAY_TARGET(array_id) ((array_id) & 0xffff)
+#define ARRAY_LUN(array_id) ((array_id) >> 16)
+
+#define RDCFG_PLUGIN_V1 0x10000
+#define CFGDIR "/dev/cfg"
+#define MAX_PATH_LEN 255
+
+/*
+ * Mininum array part size: 256M
+ */
+#define ARRAYPART_MIN_SIZE (uint64_t)(1 << 28)
+
+/*
+ * Return code
+ */
+#define SUCCESS 0
+#define STD_IOCTL -1
+#define ERR_DRIVER_NOT_FOUND -2
+#define ERR_DRIVER_OPEN -3
+#define ERR_DRIVER_LOCK -4
+#define ERR_DRIVER_CLOSED -5
+#define ERR_DRIVER_ACROSS -6
+#define ERR_ARRAY_LEVEL -7
+#define ERR_ARRAY_SIZE -8
+#define ERR_ARRAY_STRIPE_SIZE -9
+#define ERR_ARRAY_CACHE_POLICY -10
+#define ERR_ARRAY_IN_USE -11
+#define ERR_ARRAY_TASK -12
+#define ERR_ARRAY_CONFIG -13
+#define ERR_ARRAY_DISKNUM -14
+#define ERR_ARRAY_LAYOUT -15
+#define ERR_ARRAY_AMOUNT -16
+#define ERR_DISK_STATE -17
+#define ERR_DISK_SPACE -18
+#define ERR_DISK_SEG_AMOUNT -19
+#define ERR_DISK_NOT_EMPTY -20
+#define ERR_DISK_TASK -21
+#define ERR_TASK_STATE -22
+#define ERR_OP_ILLEGAL -23
+#define ERR_OP_NO_IMPL -24
+#define ERR_OP_FAILED -25
+#define ERR_DEVICE_NOENT -26
+#define ERR_DEVICE_TYPE -27
+#define ERR_DEVICE_DUP -28
+#define ERR_DEVICE_OVERFLOW -29
+#define ERR_DEVICE_UNCLEAN -30
+#define ERR_DEVICE_INVALID -31
+#define ERR_NOMEM -32
+#define ERR_PRIV -33
+#define ERR_PLUGIN -34
+
+/*
+ * Raid object types
+ */
+typedef enum {
+ OBJ_TYPE_SYSTEM,
+ OBJ_TYPE_CONTROLLER,
+ OBJ_TYPE_ARRAY,
+ OBJ_TYPE_DISK,
+ OBJ_TYPE_HSP,
+ OBJ_TYPE_ARRAY_PART,
+ OBJ_TYPE_DISK_SEG,
+ OBJ_TYPE_TASK,
+ OBJ_TYPE_ALL
+} raid_obj_type_id_t;
+
+/*
+ * Task functions
+ */
+typedef enum {
+ TASK_FUNC_UNKNOWN,
+ TASK_FUNC_INIT,
+ TASK_FUNC_BUILD,
+ TASK_FUNC_VERIFY
+} raidtask_func_t;
+
+/*
+ * Task state
+ */
+typedef enum {
+ TASK_STATE_UNKNOWN,
+ TASK_STATE_TERMINATED,
+ TASK_STATE_FAILED,
+ TASK_STATE_DONE,
+ TASK_STATE_RUNNING,
+ TASK_STATE_SUSPENDED
+} raidtask_state_t;
+
+/*
+ * Attributes of all RAID objects
+ */
+typedef union {
+ uint64_t reserved[3];
+ struct {
+ uint64_t target_id;
+ uint64_t lun;
+ } idl;
+} array_tag_t;
+
+typedef union {
+ struct {
+ uint64_t bus;
+ uint64_t target_id;
+ uint64_t lun;
+ } cidl;
+} disk_tag_t;
+
+typedef struct {
+ uint32_t controller_id;
+ uint32_t max_array_num;
+ uint32_t max_seg_per_disk;
+ uint32_t connection_type;
+ uint64_t capability;
+ char fw_version[CONTROLLER_FW_LEN];
+ char controller_type[CONTROLLER_TYPE_LEN];
+} controller_attr_t;
+
+typedef struct {
+ uint32_t array_id;
+ uint32_t state;
+ array_tag_t tag;
+ uint64_t capacity;
+ uint32_t raid_level;
+ uint32_t stripe_size;
+ uint32_t write_policy;
+ uint32_t read_policy;
+} array_attr_t;
+
+typedef struct {
+ uint32_t disk_id;
+ uint32_t state;
+ disk_tag_t tag;
+ uint64_t capacity;
+ char vendorid[DISK_VENDER_LEN];
+ char productid[DISK_PRODUCT_LEN];
+ char revision[DISK_REV_LEN];
+} disk_attr_t;
+
+typedef struct {
+ uint32_t associated_id;
+ uint32_t type;
+} hsp_attr_t;
+
+typedef struct {
+ uint32_t disk_id;
+ uint32_t state;
+ uint64_t offset;
+ uint64_t size;
+} arraypart_attr_t;
+
+typedef struct {
+ uint32_t seq_no;
+ uint32_t state;
+ uint64_t offset;
+ uint64_t size;
+} diskseg_attr_t;
+
+typedef struct {
+ uint32_t task_id;
+ uint32_t task_func;
+ uint32_t task_state;
+ uint32_t progress;
+} task_attr_t;
+
+typedef struct {
+ uint32_t array_id;
+ uint32_t disk_id;
+} hsp_relation_t;
+
+/*
+ * Structure used to register plug-in modules
+ */
+typedef struct raid_lib_type {
+ uint32_t version;
+ struct raid_lib_type *next;
+ void *lib_handle;
+ const char *name;
+
+ int (*open_controller)(uint32_t, char **);
+ int (*close_controller)(uint32_t, char **);
+ int (*compnum)(uint32_t, uint32_t, raid_obj_type_id_t,
+ raid_obj_type_id_t);
+ int (*complist)(uint32_t, uint32_t, raid_obj_type_id_t,
+ raid_obj_type_id_t, int, void *);
+ int (*get_attr)(uint32_t, uint32_t, uint32_t, raid_obj_type_id_t,
+ void *);
+ int (*set_attr)(uint32_t, uint32_t, uint32_t, uint32_t *, char **);
+ int (*array_create)(uint32_t, array_attr_t *, int,
+ arraypart_attr_t *, char **);
+ int (*array_delete)(uint32_t, uint32_t, char **);
+ int (*hsp_bind)(uint32_t, uint32_t, hsp_relation_t *, char **);
+ int (*hsp_unbind)(uint32_t, uint32_t, hsp_relation_t *, char **);
+ int (*flash_fw)(uint32_t, char *, uint32_t, char **);
+} raid_lib_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_RAIDCFG_SPI_H */
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index c541fcb01c..dd0c8d7801 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -199,10 +199,12 @@ SUBDIRS += \
gss_mechs/mech_dummy \
gss_mechs/mech_dh \
rpcsec_gss \
+ libraidcfg .WAIT \
librcm .WAIT \
libcfgadm .WAIT \
libpicl .WAIT \
libpicltree .WAIT \
+ raidcfg_plugins \
cfgadm_plugins \
libmail \
lvm \
diff --git a/usr/src/lib/libraidcfg/Makefile b/usr/src/lib/libraidcfg/Makefile
new file mode 100644
index 0000000000..2505f2f5c5
--- /dev/null
+++ b/usr/src/lib/libraidcfg/Makefile
@@ -0,0 +1,61 @@
+#
+# 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
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libraidcfg/Makefile
+#
+
+include $(SRC)/lib/Makefile.lib
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+POFILE = libraidcfg.po
+MSGSRCS :sh = echo */*.c
+MSGFILES = $(MSGSRCS:%.c=%.i)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+_msg: $(MSGDOMAINPOFILE)
+
+$(POFILE): $(MSGFILES)
+ $(BUILDPO.msgfiles)
+
+FRC:
+
+include $(SRC)/Makefile.msg.targ
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/lib/libraidcfg/Makefile.com b/usr/src/lib/libraidcfg/Makefile.com
new file mode 100644
index 0000000000..e523a79552
--- /dev/null
+++ b/usr/src/lib/libraidcfg/Makefile.com
@@ -0,0 +1,51 @@
+#
+# 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
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libraidcfg/Makefile.com
+#
+
+LIBRARY = libraidcfg.a
+VERS = .1
+OBJECTS = raidcfg.o
+
+include ../../Makefile.lib
+
+LIBS = $(DYNLIB) $(LINTLIB)
+LDLIBS += -lcfgadm -ldevinfo -lc
+
+SRCDIR = ../common
+$(LINTLIB):= SRCS = $(LINTSRC:%=$(SRCDIR)/%)
+
+CFLAGS += $(CCVERBOSE)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/libraidcfg/amd64/Makefile b/usr/src/lib/libraidcfg/amd64/Makefile
new file mode 100644
index 0000000000..22ff31377a
--- /dev/null
+++ b/usr/src/lib/libraidcfg/amd64/Makefile
@@ -0,0 +1,32 @@
+#
+# 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
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libraidcfg/common/llib-lraidcfg b/usr/src/lib/libraidcfg/common/llib-lraidcfg
new file mode 100644
index 0000000000..7992f52add
--- /dev/null
+++ b/usr/src/lib/libraidcfg/common/llib-lraidcfg
@@ -0,0 +1,122 @@
+/*
+ * 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
+ * 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
+ */
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <raidcfg.h>
+
+const char *
+raidcfg_errstr(
+ int err_code);
+
+int
+raidcfg_get_controller(
+ uint32_t controller_id);
+
+int
+raidcfg_get_array(
+ int controller_handle,
+ uint64_t target_id,
+ uint64_t lun);
+
+int
+raidcfg_get_disk(
+ int controller_handle,
+ disk_tag_t tag);
+
+int
+raidcfg_open_controller(
+ int handle,
+ char **plugin_err_str);
+
+int
+raidcfg_close_controller(
+ int handle,
+ char **plugin_err_str);
+
+int
+raidcfg_get_type(
+ int handle);
+
+int
+raidcfg_get_attr(
+ int handle,
+ void *attr);
+
+int
+raidcfg_get_container(
+ int handle);
+
+int
+raidcfg_list_head(
+ int handle,
+ raid_obj_type_id_t type);
+
+int
+raidcfg_list_next(
+ int handle);
+
+int
+raidcfg_set_attr(
+ int handle,
+ uint32_t set_cmd,
+ void *value,
+ char **plugin_err_str);
+
+int
+raidcfg_update_fw(
+ int handle,
+ char *file,
+ char **plugin_err_str);
+
+int
+raidcfg_create_array(
+ int num_of_comps,
+ int *disk_handles,
+ uint32_t raid_level,
+ uint64_t size,
+ uint32_t stripe_size,
+ char **plugin_err_str);
+
+int
+raidcfg_delete_array(
+ int array_handle,
+ char **plugin_err_str);
+
+int
+raidcfg_set_hsp(
+ int num,
+ raidcfg_hsp_relation_t *hsp_relations,
+ char **plugin_err_str);
+
+int
+raidcfg_unset_hsp(
+ int num,
+ raidcfg_hsp_relation_t *hsp_relations,
+ char **plugin_err_str);
+
diff --git a/usr/src/lib/libraidcfg/common/mapfile-vers b/usr/src/lib/libraidcfg/common/mapfile-vers
new file mode 100644
index 0000000000..e08383e4a3
--- /dev/null
+++ b/usr/src/lib/libraidcfg/common/mapfile-vers
@@ -0,0 +1,49 @@
+#
+# 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
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+SUNWprivate {
+ global:
+ raidcfg_errstr;
+ raidcfg_get_controller;
+ raidcfg_get_array;
+ raidcfg_get_disk;
+ raidcfg_open_controller;
+ raidcfg_close_controller;
+ raidcfg_get_type;
+ raidcfg_get_attr;
+ raidcfg_get_container;
+ raidcfg_list_head;
+ raidcfg_list_next;
+ raidcfg_set_attr;
+ raidcfg_create_array;
+ raidcfg_delete_array;
+ raidcfg_set_hsp;
+ raidcfg_unset_hsp;
+ raidcfg_update_fw;
+ local:
+ *;
+};
diff --git a/usr/src/lib/libraidcfg/common/raidcfg.c b/usr/src/lib/libraidcfg/common/raidcfg.c
new file mode 100644
index 0000000000..085853585f
--- /dev/null
+++ b/usr/src/lib/libraidcfg/common/raidcfg.c
@@ -0,0 +1,4672 @@
+/*
+ * 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
+ * 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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <link.h>
+#include <strings.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mnttab.h>
+#include <config_admin.h>
+#include <sys/param.h>
+#include <libintl.h>
+#include <libdevinfo.h>
+#include <raidcfg.h>
+#include <thread.h>
+#include <synch.h>
+
+#ifndef TEXT_DOMAIN
+#define TEXT_DOMAIN "SYS_TEST"
+#endif
+
+#define HASH_SLOTS 16
+#define HANDLER_SLOTS 256
+
+/*
+ * Raid object status;
+ */
+#define OBJ_STATUS_CMD_CLEAN -1
+#define OBJ_STATUS_OPENED 1
+#define OBJ_STATUS_SCANCOMP 1 << 1
+
+#if defined(__sparcv9)
+#define SUPP_PLUGIN_DIR "/usr/lib/raidcfg/sparcv9"
+#elif defined(__amd64)
+#define SUPP_PLUGIN_DIR "/usr/lib/raidcfg/amd64"
+#else
+#define SUPP_PLUGIN_DIR "/usr/lib/raidcfg"
+#endif
+
+/*
+ * Basic types
+ */
+typedef int raid_obj_id_t;
+typedef int raid_obj_status_t;
+
+/*
+ * Data structures used for object maintennance
+ */
+typedef struct {
+ void *head;
+ void *tail;
+ size_t offset; /* offset of double-linked element (raid_list_el_t) */
+ /* in the linked data structures (objects) */
+} raid_list_t;
+
+typedef struct {
+ void *prev;
+ void *next;
+} raid_list_el_t;
+
+typedef struct {
+ raid_obj_id_t obj_id_cnt; /* id 0 is reserved */
+ size_t slots; /* How many lists linked by *table */
+ raid_list_t *table;
+} raid_obj_tab_t;
+
+/*
+ * Object type structure containing function pointers;
+ */
+typedef struct {
+ int (*compnum)(raid_obj_tab_t *, raid_obj_id_t, raid_obj_type_id_t);
+ int (*complist)(raid_obj_tab_t *, raid_obj_id_t, int, raid_obj_id_t *,
+ raid_obj_type_id_t);
+ int (*get_attr)(raid_obj_tab_t *, raid_obj_id_t);
+ int (*set_attr)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, uint32_t *,
+ char **);
+ int (*act)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, void *, char **);
+ int (*create_obj)(raid_obj_tab_t *, raid_obj_id_t, int,
+ raid_obj_id_t *, char **);
+ int (*delete_obj)(raid_obj_tab_t *, raid_obj_id_t, char **);
+ int (*bind_obj)(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
+ int (*unbind_obj)(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
+} raid_obj_op_t;
+
+/*
+ * Common object data structure
+ */
+typedef struct {
+ raid_list_el_t el; /* double-links */
+
+ raid_obj_type_id_t obj_type_id;
+ raid_obj_id_t obj_id;
+ raid_obj_status_t status;
+
+ raid_obj_id_t container;
+ raid_obj_id_t sibling;
+ raid_obj_id_t component;
+
+ void *data; /* Pointer to attribute structure */
+ raid_obj_handle_t handle;
+} raid_obj_t;
+
+/*
+ * Definition about handle
+ */
+typedef struct {
+ uint32_t next;
+ uint32_t type;
+ uint32_t controller_id;
+ uint32_t array_id;
+ uint32_t disk_id;
+ uint64_t seq_id;
+ uint32_t task_id;
+ uint32_t fd; /* Only for controller */
+ raid_lib_t *raid_lib; /* Only for controller */
+} handle_attr_t;
+
+#define LIST_OBJ_TO_EL(list, obj) \
+ ((void *)((char *)(obj) + (list)->offset))
+#define OBJ_TAB_SLOT(tab, id) \
+ ((tab)->table + ((id)%(tab)->slots))
+
+#pragma init(raidcfg_init)
+#pragma fini(raidcfg_fini)
+
+/*
+ * Function prototypes
+ */
+static int intcompare(const void *p1, const void *p2);
+static uint64_t raid_space_noalign(raid_obj_tab_t *, uint32_t, int,
+ raid_obj_id_t *, arraypart_attr_t *);
+static int raid_dev_config(cfga_cmd_t, uint32_t, uint32_t, uint8_t);
+static int raid_dev_unmounted(uint32_t, uint32_t);
+static int raid_handle_init();
+static void raid_handle_fini();
+static raid_obj_handle_t raid_handle_new(raid_obj_type_id_t);
+static void raid_handle_delete(raid_obj_handle_t);
+static void raid_handle_delete_controller_comp(uint32_t);
+static raid_obj_id_t raid_handle_to_obj(raid_obj_tab_t *,
+ raid_obj_handle_t);
+static raid_obj_handle_t raid_obj_to_handle(raid_obj_tab_t *,
+ raid_obj_id_t);
+static raid_lib_t *raid_obj_get_lib(raid_obj_tab_t *, raid_obj_id_t);
+static int raid_obj_set_lib(raid_obj_tab_t *, raid_obj_id_t, raid_lib_t *);
+static int raid_obj_get_fd(raid_obj_tab_t *, raid_obj_id_t);
+static int raid_obj_set_fd(raid_obj_tab_t *, raid_obj_id_t, int);
+static int obj_scan_comp(raid_obj_tab_t *, raid_obj_id_t);
+static int obj_rescan(raid_obj_tab_t *);
+static raid_obj_id_t obj_get_comp(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_type_id_t);
+static raid_obj_id_t obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
+static int obj_get_attr(raid_obj_tab_t *, raid_obj_id_t, void **);
+static raid_obj_id_t obj_locate_controller(raid_obj_tab_t *, uint32_t);
+static raid_obj_id_t obj_locate_array(raid_obj_tab_t *, uint32_t, uint32_t);
+static raid_obj_id_t obj_locate_array_recur(raid_obj_tab_t *, raid_obj_id_t,
+ uint32_t);
+static raid_obj_id_t obj_locate_hsp(raid_obj_tab_t *, uint32_t,
+ uint32_t, uint32_t);
+static raid_obj_id_t obj_locate_disk(raid_obj_tab_t *, uint32_t, uint32_t);
+static raid_obj_id_t obj_locate_arraypart(raid_obj_tab_t *, uint32_t,
+ uint32_t, uint32_t);
+static raid_obj_id_t obj_locate_diskseg(raid_obj_tab_t *, uint32_t,
+ uint32_t, uint32_t);
+static raid_obj_id_t obj_locate_task(raid_obj_tab_t *, uint32_t, uint32_t);
+static raid_obj_id_t obj_get_controller(raid_obj_tab_t *, raid_obj_id_t);
+
+static int obj_sys_compnum(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_type_id_t);
+static int obj_sys_complist(raid_obj_tab_t *, raid_obj_id_t, int,
+ raid_obj_id_t *, raid_obj_type_id_t);
+static int obj_controller_compnum(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_type_id_t);
+static int obj_controller_complist(raid_obj_tab_t *, raid_obj_id_t, int,
+ raid_obj_id_t *, raid_obj_type_id_t);
+static int obj_controller_get_attr(raid_obj_tab_t *, raid_obj_id_t);
+static int obj_controller_act(raid_obj_tab_t *, raid_obj_id_t,
+ uint32_t, void *, char **);
+static int obj_array_compnum(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_type_id_t);
+static int obj_array_complist(raid_obj_tab_t *, raid_obj_id_t, int,
+ raid_obj_id_t *, raid_obj_type_id_t);
+static int obj_array_get_attr(raid_obj_tab_t *, raid_obj_id_t);
+static int obj_array_set_attr(raid_obj_tab_t *, raid_obj_id_t,
+ uint32_t, uint32_t *, char **);
+static int obj_disk_compnum(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_type_id_t);
+static int obj_disk_complist(raid_obj_tab_t *, raid_obj_id_t, int,
+ raid_obj_id_t *, raid_obj_type_id_t);
+static int obj_disk_get_attr(raid_obj_tab_t *, raid_obj_id_t);
+static int obj_hsp_get_attr(raid_obj_tab_t *, raid_obj_id_t);
+static int obj_arraypart_get_attr(raid_obj_tab_t *, raid_obj_id_t);
+static int obj_diskseg_get_attr(raid_obj_tab_t *, raid_obj_id_t);
+static int obj_task_get_attr(raid_obj_tab_t *, raid_obj_id_t);
+static int obj_array_create(raid_obj_tab_t *, raid_obj_id_t, int,
+ raid_obj_id_t *, char **);
+static int obj_array_delete(raid_obj_tab_t *, raid_obj_id_t, char **);
+static int obj_hsp_bind(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
+static int obj_hsp_unbind(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
+
+static int raid_obj_create_system_obj(raid_obj_tab_t *);
+static raid_obj_id_t raid_obj_id_new(raid_obj_tab_t *);
+static void *raid_obj_attr_new(raid_obj_type_id_t);
+static raid_obj_id_t raid_obj_create(raid_obj_tab_t *, raid_obj_type_id_t);
+static int raid_obj_delete(raid_obj_tab_t *, raid_obj_id_t);
+static int raid_obj_add_org(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
+static raid_obj_type_id_t raid_obj_get_type(raid_obj_tab_t *, raid_obj_id_t);
+static int raid_obj_set_type(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_type_id_t);
+static raid_obj_status_t raid_obj_get_status(raid_obj_tab_t *, raid_obj_id_t);
+static int raid_obj_set_status(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_status_t);
+static int raid_obj_clear_status(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_status_t);
+static raid_obj_id_t raid_obj_get_container(raid_obj_tab_t *, raid_obj_id_t);
+static int raid_obj_set_container(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_id_t);
+static raid_obj_id_t raid_obj_get_comp(raid_obj_tab_t *, raid_obj_id_t);
+static int raid_obj_set_comp(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
+static raid_obj_id_t raid_obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
+static int raid_obj_set_sibling(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_id_t);
+static void *raid_obj_get_data_ptr(raid_obj_tab_t *, raid_obj_id_t);
+static int raid_obj_set_data_ptr(raid_obj_tab_t *, raid_obj_id_t, void *);
+static raid_obj_handle_t raid_obj_get_handle(raid_obj_tab_t *,
+ raid_obj_id_t);
+static int raid_obj_set_handle(raid_obj_tab_t *, raid_obj_id_t,
+ raid_obj_handle_t);
+
+static void raid_list_create(raid_list_t *, size_t);
+static void *raid_list_head(raid_list_t *);
+static void *raid_list_next(raid_list_t *, void *);
+static void raid_list_insert_tail(raid_list_t *, void *);
+static void raid_list_remove(raid_list_t *, void *);
+static void *raid_list_remove_head(raid_list_t *);
+static void *raid_list_find(raid_list_t *, raid_obj_id_t);
+static int raid_obj_tab_create(raid_obj_tab_t *, size_t);
+static void raid_obj_tab_destroy(raid_obj_tab_t *);
+static int raid_obj_tab_insert(raid_obj_tab_t *, raid_obj_id_t, void *);
+static void *raid_obj_tab_remove(raid_obj_tab_t *, raid_obj_id_t);
+static void *raid_obj_tab_find(raid_obj_tab_t *, raid_obj_id_t);
+static void raid_list_destroy(raid_list_t *);
+
+static int controller_id_to_path(uint32_t, char *);
+static char *controller_id_to_driver_name(uint32_t);
+static void raid_plugin_init();
+static raid_lib_t *raid_plugin_load(char *);
+static raid_lib_t *raid_find_lib(raid_obj_tab_t *, raid_obj_id_t);
+
+/* Global object table */
+static raid_obj_tab_t raid_tab_sys = {0, 0, NULL};
+
+/* Plug-in modules maintenance data structures */
+static raid_lib_t *raid_lib_sys = NULL;
+
+/* Handle table definition */
+static struct {
+ int handle_num;
+ int used;
+ int unused;
+ handle_attr_t *handles;
+} raid_handle_sys = {0, 0, 0, NULL};
+
+/*
+ * RAID object method table definition
+ */
+static raid_obj_op_t raid_obj_op_sys[OBJ_TYPE_ALL] = {
+ {obj_sys_compnum, obj_sys_complist, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL}, /* system object methods */
+ {obj_controller_compnum, obj_controller_complist,
+ obj_controller_get_attr, NULL, obj_controller_act,
+ NULL, NULL, NULL, NULL}, /* controller object methods */
+ {obj_array_compnum, obj_array_complist, obj_array_get_attr,
+ obj_array_set_attr, NULL, obj_array_create,
+ obj_array_delete, NULL, NULL}, /* array object methods */
+ {obj_disk_compnum, obj_disk_complist, obj_disk_get_attr, NULL,
+ NULL, NULL, NULL, NULL, NULL}, /* disk object methods */
+ {NULL, NULL, obj_hsp_get_attr, NULL, NULL, NULL, NULL, obj_hsp_bind,
+ obj_hsp_unbind}, /* hsp object methods */
+ {NULL, NULL, obj_arraypart_get_attr, NULL, NULL, NULL, NULL,
+ NULL, NULL}, /* array part object methods */
+ {NULL, NULL, obj_diskseg_get_attr, NULL, NULL, NULL, NULL, NULL, NULL},
+ {NULL, NULL, obj_task_get_attr, NULL, NULL, NULL, NULL,
+ NULL, NULL} /* disk seg object methods */
+};
+
+/*
+ * Mutex for multithread safe
+ */
+static mutex_t raidcfg_mp;
+
+/*
+ * RaidCfg library APIs
+ */
+const char *
+raidcfg_errstr(int err_code)
+{
+ char *ret_val;
+
+ (void) mutex_lock(&raidcfg_mp);
+ switch (err_code) {
+ case SUCCESS:
+ ret_val = dgettext(TEXT_DOMAIN, "Operation succeeded.\n");
+ break;
+ case STD_IOCTL:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Request standard IOCTL service.\n");
+ break;
+ case ERR_DRIVER_NOT_FOUND:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Controller device can not be found.\n");
+ break;
+ case ERR_DRIVER_OPEN:
+ ret_val = dgettext(TEXT_DOMAIN, "Can not open controller.\n");
+ break;
+ case ERR_DRIVER_LOCK:
+ ret_val = dgettext(TEXT_DOMAIN, "Controller is locked.\n");
+ break;
+ case ERR_DRIVER_CLOSED:
+ ret_val = dgettext(TEXT_DOMAIN, "Controller is not opened.\n");
+ break;
+ case ERR_DRIVER_ACROSS:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Operation across multiple controllers.\n");
+ break;
+ case ERR_ARRAY_LEVEL:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Operation not support with volume of this level.\n");
+ break;
+ case ERR_ARRAY_SIZE:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Capacity of array out of range.\n");
+ break;
+ case ERR_ARRAY_STRIPE_SIZE:
+ ret_val = dgettext(TEXT_DOMAIN, "Illegal stripe size.\n");
+ break;
+ case ERR_ARRAY_CACHE_POLICY:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Illegal cache-write policy.\n");
+ break;
+ case ERR_ARRAY_IN_USE:
+ ret_val = dgettext(TEXT_DOMAIN, "Array in use.\n");
+ break;
+ case ERR_ARRAY_TASK:
+ ret_val = dgettext(TEXT_DOMAIN, "Array has background task.\n");
+ break;
+ case ERR_ARRAY_CONFIG:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Configuration over device node failed.\n");
+ break;
+ case ERR_ARRAY_DISKNUM:
+ ret_val = dgettext(TEXT_DOMAIN, "Incorrect number of disks.\n");
+ break;
+ case ERR_ARRAY_LAYOUT:
+ ret_val = dgettext(TEXT_DOMAIN, "Illegal array layout.\n");
+ break;
+ case ERR_ARRAY_AMOUNT:
+ ret_val = dgettext(TEXT_DOMAIN, "Too many arrays.\n");
+ break;
+ case ERR_DISK_STATE:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Incorrect disk status for current operation.\n");
+ break;
+ case ERR_DISK_SPACE:
+ ret_val = dgettext(TEXT_DOMAIN, "No enough disk space.\n");
+ break;
+ case ERR_DISK_SEG_AMOUNT:
+ ret_val = dgettext(TEXT_DOMAIN, "Too many disk segments.\n");
+ break;
+ case ERR_DISK_NOT_EMPTY:
+ ret_val = dgettext(TEXT_DOMAIN, "Disk has occupied space.\n");
+ break;
+ case ERR_DISK_TASK:
+ ret_val = dgettext(TEXT_DOMAIN, "Disk has background task.\n");
+ break;
+ case ERR_TASK_STATE:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Incorrect task state for current operation.\n");
+ break;
+ case ERR_OP_ILLEGAL:
+ ret_val = dgettext(TEXT_DOMAIN, "Illegal operation.\n");
+ break;
+ case ERR_OP_NO_IMPL:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Operation is not implemented.\n");
+ break;
+ case ERR_OP_FAILED:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Operation in plugin failed.\n");
+ break;
+ case ERR_DEVICE_NOENT:
+ ret_val = dgettext(TEXT_DOMAIN, "Device not found.\n");
+ break;
+ case ERR_DEVICE_TYPE:
+ ret_val = dgettext(TEXT_DOMAIN, "Illegal type of device.\n");
+ break;
+ case ERR_DEVICE_DUP:
+ ret_val = dgettext(TEXT_DOMAIN, "Device record duplicated.\n");
+ break;
+ case ERR_DEVICE_OVERFLOW:
+ ret_val = dgettext(TEXT_DOMAIN, "Too many devices.\n");
+ break;
+ case ERR_DEVICE_UNCLEAN:
+ ret_val = dgettext(TEXT_DOMAIN, "Device pool is not clean.\n");
+ break;
+ case ERR_DEVICE_INVALID:
+ ret_val = dgettext(TEXT_DOMAIN, "Device record is invalid.\n");
+ break;
+ case ERR_NOMEM:
+ ret_val = dgettext(TEXT_DOMAIN,
+ "Can not allocate more memory space.\n");
+ break;
+ case ERR_PRIV:
+ ret_val = dgettext(TEXT_DOMAIN, "No privilege.\n");
+ break;
+ default:
+ ret_val = dgettext(TEXT_DOMAIN, "Undefined error.\n");
+ }
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (ret_val);
+}
+
+int
+raidcfg_get_controller(uint32_t controller_id)
+{
+ raid_obj_id_t obj_id;
+ int ret_val;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = obj_locate_controller(&raid_tab_sys, controller_id);
+ if (obj_id < OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (obj_id);
+ }
+
+ if (obj_id == OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+ ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (ret_val);
+}
+
+int
+raidcfg_get_array(int controller_handle, uint64_t target_id, uint64_t lun)
+{
+ raid_obj_id_t obj_id;
+ raidcfg_array_t *attr;
+ int ret_val;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
+ if (obj_id < OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (obj_id);
+ }
+
+ obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_ARRAY);
+
+ while (obj_id > OBJ_NONE) {
+ (void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
+ if (attr->tag.idl.target_id == target_id &&
+ attr->tag.idl.lun == lun)
+ break;
+
+ obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
+ }
+
+ if (obj_id < OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (obj_id);
+ }
+ if (obj_id == OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+ ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (ret_val);
+}
+
+int
+raidcfg_get_disk(int controller_handle, disk_tag_t tag)
+{
+ raid_obj_id_t obj_id;
+ raidcfg_disk_t *attr;
+ int ret_val;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
+ if (obj_id < OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (obj_id);
+ }
+
+ obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_DISK);
+
+ while (obj_id > OBJ_NONE) {
+ (void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
+ if (attr->tag.cidl.bus == tag.cidl.bus &&
+ attr->tag.cidl.target_id == tag.cidl.target_id &&
+ attr->tag.cidl.lun == tag.cidl.lun)
+ break;
+
+ obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
+ }
+
+ if (obj_id < OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (obj_id);
+ }
+ if (obj_id == OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+ ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (ret_val);
+}
+
+int
+raidcfg_open_controller(int handle, char **plugin_err_str)
+{
+ raid_obj_id_t obj_id;
+ int ret;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
+ if (obj_id < OBJ_NONE) {
+ raid_handle_delete(handle);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+
+ ret = obj_controller_act(&raid_tab_sys, obj_id,
+ ACT_CONTROLLER_OPEN, NULL, plugin_err_str);
+ if (ret < SUCCESS) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+ }
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (SUCCESS);
+}
+
+int
+raidcfg_close_controller(int handle, char **plugin_err_str)
+{
+ raid_obj_id_t obj_id;
+ int ret;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
+ if (obj_id < OBJ_NONE) {
+ raid_handle_delete(handle);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+
+ ret = obj_controller_act(&raid_tab_sys, obj_id,
+ ACT_CONTROLLER_CLOSE, NULL, plugin_err_str);
+ if (ret < SUCCESS) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+ }
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (SUCCESS);
+}
+
+int
+raidcfg_get_type(int handle)
+{
+ raid_obj_id_t obj_id;
+ int ret_val;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
+ if (obj_id < OBJ_NONE) {
+ raid_handle_delete(handle);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+ ret_val = raid_obj_get_type(&raid_tab_sys, obj_id);
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (ret_val);
+}
+
+int
+raidcfg_get_attr(int handle, void *attr)
+{
+ raid_obj_id_t obj_id;
+ raid_obj_type_id_t type;
+ void *data;
+ int ret, size;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ if (attr == NULL) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_INVALID);
+ }
+
+ obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
+ if (obj_id < OBJ_NONE) {
+ raid_handle_delete(handle);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+
+ type = raid_obj_get_type(&raid_tab_sys, obj_id);
+ ret = obj_get_attr(&raid_tab_sys, obj_id, &data);
+ if (ret < SUCCESS) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+ }
+
+ switch (type) {
+ case OBJ_TYPE_CONTROLLER:
+ size = sizeof (controller_attr_t);
+ break;
+ case OBJ_TYPE_ARRAY:
+ size = sizeof (array_attr_t);
+ break;
+ case OBJ_TYPE_HSP:
+ {
+ raidcfg_hsp_t *dst = attr;
+ hsp_attr_t *src = data;
+ controller_attr_t *ctlr_attr;
+ array_attr_t *array_attr;
+
+ dst->associated_id = src->associated_id;
+ dst->type = src->type;
+
+ obj_id = obj_get_controller(&raid_tab_sys, obj_id);
+ ret = obj_get_attr(&raid_tab_sys, obj_id,
+ (void **)(&ctlr_attr));
+ if (ret < SUCCESS) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+ }
+
+ if (src->type == HSP_TYPE_LOCAL) {
+ obj_id = obj_locate_array(&raid_tab_sys,
+ ctlr_attr->controller_id,
+ src->associated_id);
+ ret = obj_get_attr(&raid_tab_sys, obj_id,
+ (void **)(&array_attr));
+ if (ret < SUCCESS) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+ }
+
+ dst->tag.idl.target_id =
+ array_attr->tag.idl.target_id;
+ dst->tag.idl.lun = array_attr->tag.idl.lun;
+ }
+ }
+ (void) mutex_unlock(&raidcfg_mp);
+ return (SUCCESS);
+ case OBJ_TYPE_DISK:
+ size = sizeof (disk_attr_t);
+ break;
+ case OBJ_TYPE_ARRAY_PART:
+ {
+ raidcfg_arraypart_t *dst = attr;
+ arraypart_attr_t *src = data;
+ controller_attr_t *ctlr_attr;
+ disk_attr_t *disk_attr;
+
+ dst->disk_id = src->disk_id;
+ dst->offset = src->offset;
+ dst->size = src->size;
+ dst->state = src->state;
+
+ obj_id = obj_get_controller(&raid_tab_sys, obj_id);
+ ret = obj_get_attr(&raid_tab_sys, obj_id,
+ (void **)(&ctlr_attr));
+ if (ret < SUCCESS) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+ }
+
+ obj_id = obj_locate_disk(&raid_tab_sys,
+ ctlr_attr->controller_id, src->disk_id);
+ if (obj_id <= OBJ_NONE) {
+ dst->tag.cidl.bus = (uint64_t)OBJ_ATTR_NONE;
+ dst->tag.cidl.target_id =
+ (uint64_t)OBJ_ATTR_NONE;
+ dst->tag.cidl.lun = (uint64_t)OBJ_ATTR_NONE;
+ (void) mutex_unlock(&raidcfg_mp);
+ return (SUCCESS);
+ }
+
+ ret = obj_get_attr(&raid_tab_sys, obj_id,
+ (void **)(&disk_attr));
+ if (ret < SUCCESS) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+ }
+
+ dst->tag.cidl.bus = disk_attr->tag.cidl.bus;
+ dst->tag.cidl.target_id = disk_attr->tag.cidl.target_id;
+ dst->tag.cidl.lun = disk_attr->tag.cidl.lun;
+ }
+ (void) mutex_unlock(&raidcfg_mp);
+ return (SUCCESS);
+ case OBJ_TYPE_DISK_SEG:
+ size = sizeof (diskseg_attr_t);
+ break;
+ case OBJ_TYPE_TASK:
+ size = sizeof (task_attr_t);
+ break;
+ default:
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_TYPE);
+ }
+
+ (void) memcpy(attr, data, size);
+
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+}
+
+int
+raidcfg_get_container(int handle)
+{
+ raid_obj_id_t obj_id;
+ int ret_val;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
+ if (obj_id < OBJ_NONE) {
+ raid_handle_delete(handle);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+
+ obj_id = raid_obj_get_container(&raid_tab_sys, obj_id);
+ if (obj_id < OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (obj_id);
+ }
+ ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (ret_val);
+}
+
+int
+raidcfg_list_head(int handle, raid_obj_type_id_t type)
+{
+ raid_obj_id_t obj_id;
+ int ret_val;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
+ if (obj_id < OBJ_NONE) {
+ raid_handle_delete(handle);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+
+ obj_id = obj_get_comp(&raid_tab_sys, obj_id, type);
+ if (obj_id < OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (obj_id);
+ }
+ ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (ret_val);
+}
+
+int
+raidcfg_list_next(int handle)
+{
+ raid_obj_id_t obj_id;
+ int ret_val;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
+ if (obj_id < OBJ_NONE) {
+ raid_handle_delete(handle);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+
+ obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
+ if (obj_id < OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (obj_id);
+ }
+ ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (ret_val);
+}
+
+int
+raidcfg_set_attr(int handle, uint32_t set_cmd, void *value,
+ char **plugin_err_str)
+{
+ raid_obj_id_t obj_id;
+ raid_obj_type_id_t type;
+ int ret;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
+ if (obj_id < OBJ_NONE) {
+ raid_handle_delete(handle);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+
+ type = raid_obj_get_type(&raid_tab_sys, obj_id);
+ if (raid_obj_op_sys[type].set_attr == NULL) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_OP_NO_IMPL);
+ }
+
+ ret = raid_obj_op_sys[type].set_attr(&raid_tab_sys,
+ obj_id, set_cmd, value, plugin_err_str);
+
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+}
+
+int
+raidcfg_update_fw(int handle, char *file, char **plugin_err_str)
+{
+ raid_obj_id_t obj_id;
+ int ret;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
+ if (obj_id < OBJ_NONE) {
+ raid_handle_delete(handle);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+
+ if (raid_obj_get_type(&raid_tab_sys, obj_id) != OBJ_TYPE_CONTROLLER) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_OP_NO_IMPL);
+ }
+
+ ret = raid_obj_op_sys[OBJ_TYPE_CONTROLLER].act(&raid_tab_sys,
+ obj_id, ACT_CONTROLLER_FLASH_FW, file, plugin_err_str);
+
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+}
+
+int
+raidcfg_create_array(int num_of_comps, int *disk_handles,
+ uint32_t raid_level, uint64_t size, uint32_t stripe_size,
+ char **plugin_err_str)
+{
+ raid_obj_id_t *disk_obj_ids, obj_id;
+ array_attr_t *array_attr;
+ raid_obj_handle_t array_handle;
+ int i, ret;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+
+ disk_obj_ids = calloc(num_of_comps, sizeof (raid_obj_id_t));
+ if (disk_obj_ids == NULL) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_NOMEM);
+ }
+
+ /* convert disk handles into disk object ids; */
+ for (i = 0; i < num_of_comps; ++i) {
+ if (*(disk_handles + i) == OBJ_SEPARATOR_BEGIN ||
+ *(disk_handles + i) == OBJ_SEPARATOR_END) {
+ *(disk_obj_ids + i) = *(disk_handles + i);
+ continue;
+ }
+
+ *(disk_obj_ids + i) = raid_handle_to_obj(&raid_tab_sys,
+ *(disk_handles + i));
+ if (raid_obj_get_type(&raid_tab_sys, *(disk_obj_ids + i)) !=
+ OBJ_TYPE_DISK) {
+ free(disk_obj_ids);
+ (void) obj_rescan(&raid_tab_sys);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_TYPE);
+ }
+ }
+
+ /* Create an empty array object */
+ obj_id = raid_obj_create(&raid_tab_sys, OBJ_TYPE_ARRAY);
+ if (obj_id < OBJ_NONE) {
+ free(disk_obj_ids);
+ (void) obj_rescan(&raid_tab_sys);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (obj_id);
+ }
+ (void) raid_obj_clear_status(&raid_tab_sys, obj_id,
+ OBJ_STATUS_CMD_CLEAN);
+
+ array_attr = raid_obj_get_data_ptr(&raid_tab_sys, obj_id);
+ array_attr->array_id = (uint32_t)OBJ_ATTR_NONE;
+ array_attr->raid_level = raid_level;
+ array_attr->capacity = size;
+ array_attr->stripe_size = stripe_size;
+ array_attr->write_policy = CACHE_WR_ON;
+ array_attr->read_policy = CACHE_RD_ON;
+
+ ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].create_obj(&raid_tab_sys, obj_id,
+ num_of_comps, disk_obj_ids, plugin_err_str);
+ free(disk_obj_ids);
+
+ if (ret < SUCCESS) {
+ (void) obj_rescan(&raid_tab_sys);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+ }
+
+ /* create_obj() method should put the array object in the device tree */
+ array_handle = raid_obj_to_handle(&raid_tab_sys, obj_id);
+
+ (void) obj_rescan(&raid_tab_sys);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (array_handle);
+}
+
+int
+raidcfg_delete_array(int array_handle, char **plugin_err_str)
+{
+ raid_obj_id_t array_obj_id;
+ int ret;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+
+ if (raidcfg_get_type(array_handle) != OBJ_TYPE_ARRAY) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_TYPE);
+ }
+
+ array_obj_id = raid_handle_to_obj(&raid_tab_sys, array_handle);
+ if (array_obj_id < OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (array_obj_id);
+ }
+ if (array_obj_id == OBJ_NONE) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_INVALID);
+ }
+
+ ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].delete_obj(&raid_tab_sys,
+ array_obj_id, plugin_err_str);
+ (void) obj_rescan(&raid_tab_sys);
+
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ret);
+}
+
+int
+raidcfg_set_hsp(int num, raidcfg_hsp_relation_t *hsp_relations,
+ char **plugin_err_str)
+{
+ raid_obj_id_t disk_obj_id, array_obj_id;
+ raid_obj_id_t *hsp_relation_objs;
+ int ret, i;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ if ((num == 0) || (hsp_relations == NULL)) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_OP_ILLEGAL);
+ }
+
+ hsp_relation_objs = malloc(2 * num * sizeof (raid_obj_id_t));
+ if (hsp_relation_objs == NULL) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_NOMEM);
+ }
+
+ (void) obj_rescan(&raid_tab_sys);
+
+ for (i = 0; i < num; ++ i) {
+ if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
+ array_obj_id = raid_handle_to_obj(&raid_tab_sys,
+ hsp_relations[i].array_handle);
+ if (array_obj_id < OBJ_NONE) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (array_obj_id);
+ }
+ if (array_obj_id == OBJ_NONE) {
+ (void) free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+ if (raidcfg_get_type(hsp_relations[i].array_handle) !=
+ OBJ_TYPE_ARRAY) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_TYPE);
+ }
+ } else
+ array_obj_id = OBJ_ATTR_NONE;
+
+ disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
+ hsp_relations[i].disk_handle);
+ if (disk_obj_id < OBJ_NONE) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (disk_obj_id);
+ }
+ if (disk_obj_id == OBJ_NONE) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+ if (raidcfg_get_type(hsp_relations[i].disk_handle) !=
+ OBJ_TYPE_DISK) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_TYPE);
+ }
+
+ hsp_relation_objs[2 * i] = array_obj_id;
+ hsp_relation_objs[2 * i + 1] = disk_obj_id;
+ }
+
+ ret = raid_obj_op_sys[OBJ_TYPE_HSP].bind_obj(&raid_tab_sys, num,
+ hsp_relation_objs, plugin_err_str);
+
+ (void) obj_rescan(&raid_tab_sys);
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (ret);
+}
+
+int
+raidcfg_unset_hsp(int num, raidcfg_hsp_relation_t *hsp_relations,
+ char **plugin_err_str)
+{
+ raid_obj_id_t disk_obj_id, array_obj_id;
+ raid_obj_id_t *hsp_relation_objs;
+ int ret, i;
+
+ (void) mutex_lock(&raidcfg_mp);
+ (void) obj_rescan(&raid_tab_sys);
+ if ((num == 0) || (hsp_relations == NULL)) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_OP_ILLEGAL);
+ }
+
+ hsp_relation_objs = malloc(2 * num * sizeof (raid_obj_id_t));
+ if (hsp_relation_objs == NULL) {
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_NOMEM);
+ }
+
+ (void) obj_rescan(&raid_tab_sys);
+
+ for (i = 0; i < num; ++ i) {
+ if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
+ array_obj_id = raid_handle_to_obj(&raid_tab_sys,
+ hsp_relations[i].array_handle);
+ if (array_obj_id < OBJ_NONE) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (array_obj_id);
+ }
+ if (array_obj_id == OBJ_NONE) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+ if (raidcfg_get_type(hsp_relations[i].array_handle) !=
+ OBJ_TYPE_ARRAY) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_TYPE);
+ }
+ } else
+ array_obj_id = OBJ_ATTR_NONE;
+
+ disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
+ hsp_relations[i].disk_handle);
+ if (disk_obj_id < OBJ_NONE) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (disk_obj_id);
+ }
+ if (disk_obj_id == OBJ_NONE) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_NOENT);
+ }
+ if (raidcfg_get_type(hsp_relations[i].disk_handle) !=
+ OBJ_TYPE_DISK) {
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+ return (ERR_DEVICE_TYPE);
+ }
+
+ hsp_relation_objs[2 * i] = array_obj_id;
+ hsp_relation_objs[2 * i + 1] = disk_obj_id;
+ }
+
+ ret = raid_obj_op_sys[OBJ_TYPE_HSP].unbind_obj(&raid_tab_sys,
+ num, hsp_relation_objs, plugin_err_str);
+
+ (void) obj_rescan(&raid_tab_sys);
+ free(hsp_relation_objs);
+ (void) mutex_unlock(&raidcfg_mp);
+
+ return (ret);
+}
+
+/*
+ * RaidCfg lib routines
+ */
+void
+raidcfg_init(void)
+{
+ (void) mutex_init(&raidcfg_mp, NULL, NULL);
+ raid_plugin_init();
+ (void) raid_handle_init();
+ (void) obj_rescan(&raid_tab_sys);
+}
+
+void
+raidcfg_fini(void)
+{
+ /*
+ * Need to close all opened controllers before destroying object table
+ */
+ (void) obj_rescan(&raid_tab_sys);
+ raid_handle_fini();
+ raid_obj_tab_destroy(&raid_tab_sys);
+ raid_plugin_init();
+ (void) mutex_destroy(&raidcfg_mp);
+}
+
+/*
+ * Support routines
+ */
+static int
+intcompare(const void *p1, const void *p2)
+{
+ int i, j;
+ i = *((int *)p1);
+ j = *((int *)p2);
+ return (i - j);
+}
+
+static uint64_t
+raid_space_noalign(raid_obj_tab_t *raid_tab, uint32_t raid_level, int num,
+ raid_obj_id_t *disk_objs, arraypart_attr_t *arraypart_attrs)
+{
+ disk_attr_t *disk_attr;
+ diskseg_attr_t *diskseg_attr;
+ raid_obj_id_t obj_id;
+ uint64_t offset, capacity;
+ int i, disk_num, sub_array_num, disk_layer;
+
+ /* Find out the maximum available space for all disks */
+ for (i = 0; i < num; ++i) {
+ if ((disk_objs[i] == OBJ_SEPARATOR_BEGIN) ||
+ (disk_objs[i] == OBJ_SEPARATOR_END))
+ continue;
+
+ (void) obj_get_attr(raid_tab, disk_objs[i],
+ (void **)(&disk_attr));
+ obj_id = obj_get_comp(raid_tab, disk_objs[i],
+ OBJ_TYPE_DISK_SEG);
+ if (obj_id == OBJ_NONE) {
+ arraypart_attrs[i].offset = 0;
+ arraypart_attrs[i].size = disk_attr->capacity;
+ continue;
+ }
+
+ (void) obj_get_attr(raid_tab, obj_id, (void **)
+ (&diskseg_attr));
+ arraypart_attrs[i].offset = 0;
+ arraypart_attrs[i].size = diskseg_attr->offset;
+ offset = diskseg_attr->offset + diskseg_attr->size;
+
+ while ((obj_id = obj_get_sibling(raid_tab, obj_id)) !=
+ OBJ_NONE) {
+ (void) obj_get_attr(raid_tab, obj_id,
+ (void **)(&diskseg_attr));
+ if ((diskseg_attr->offset - offset) >
+ arraypart_attrs[i].size) {
+ arraypart_attrs[i].offset = offset;
+ arraypart_attrs[i].size = diskseg_attr->offset
+ - offset;
+ }
+
+ offset = diskseg_attr->offset + diskseg_attr->size;
+ }
+
+ if ((disk_attr->capacity - offset) > arraypart_attrs[i].size) {
+ arraypart_attrs[i].offset = offset;
+ arraypart_attrs[i].size = disk_attr->capacity
+ - offset;
+ }
+ }
+
+ capacity = OBJ_ATTR_NONE;
+ disk_num = 0;
+ disk_layer = 0;
+ sub_array_num = 0;
+ for (i = 0; i < num; ++i) {
+ if (disk_objs[i] == OBJ_SEPARATOR_BEGIN) {
+ ++ disk_layer;
+ continue;
+ }
+ if (disk_objs[i] == OBJ_SEPARATOR_END) {
+ -- disk_layer;
+ if (disk_layer != 0)
+ ++ sub_array_num;
+ continue;
+ }
+
+ if (capacity > arraypart_attrs[i].size)
+ capacity = arraypart_attrs[i].size;
+ ++disk_num;
+ }
+
+ switch (raid_level) {
+ case RAID_LEVEL_0:
+ capacity = capacity * disk_num;
+ break;
+ case RAID_LEVEL_1:
+ capacity = capacity * disk_num / 2;
+ break;
+ case RAID_LEVEL_1E:
+ capacity = capacity * disk_num / 2;
+ break;
+ case RAID_LEVEL_5:
+ capacity = capacity * (disk_num - 1);
+ break;
+ case RAID_LEVEL_10:
+ capacity = capacity * disk_num / 2;
+ break;
+ case RAID_LEVEL_50:
+ capacity = capacity * (disk_num - sub_array_num);
+ break;
+ default:
+ return (ERR_ARRAY_LEVEL);
+ break;
+ }
+
+ return (capacity);
+}
+
+static int
+raid_dev_config(cfga_cmd_t cmd, uint32_t controller_id, uint32_t target_id,
+ uint8_t type)
+{
+ cfga_err_t cfga_err;
+ char *ap_id;
+ int count = 0;
+
+ ap_id = (char *)malloc(MAX_PATH_LEN);
+ if (ap_id == NULL)
+ return (ERR_NOMEM);
+
+ if (type == 0) {
+ (void) snprintf(ap_id, MAX_PATH_LEN, "c%d::dsk/c%dt%dd0",
+ controller_id, controller_id, target_id);
+ } else
+ (void) snprintf(ap_id, MAX_PATH_LEN, "c%d", controller_id);
+
+ do {
+ cfga_err = config_change_state(cmd, 1, &ap_id, "disable_rcm",
+ NULL, NULL, NULL, 0);
+ count++;
+ } while (cfga_err != CFGA_OK && count < 2);
+
+ if (cfga_err != CFGA_OK) {
+ free(ap_id);
+ return (ERR_ARRAY_CONFIG);
+ }
+
+ free(ap_id);
+ return (SUCCESS);
+}
+
+static int
+raid_dev_unmounted(uint32_t controller_id, uint32_t target_id)
+{
+ struct mnttab mt;
+ FILE *f;
+ char path[MAX_PATH_LEN];
+
+ (void) snprintf(path, MAX_PATH_LEN, "c%dt%dd0",
+ controller_id, target_id);
+
+ f = fopen(MNTTAB, "r");
+
+ while (getmntent(f, &mt) != EOF)
+ if (strstr(mt.mnt_special, path) != NULL) {
+ (void) fclose(f);
+ return (ERR_ARRAY_IN_USE);
+ }
+
+ (void) fclose(f);
+ return (SUCCESS);
+}
+
+/*
+ * Raid handle maintenance routines
+ */
+static int
+raid_handle_init()
+{
+ int i;
+ void *ptr;
+
+ raid_handle_sys.handle_num += HANDLER_SLOTS;
+ ptr = realloc(raid_handle_sys.handles,
+ raid_handle_sys.handle_num * sizeof (handle_attr_t));
+ if (ptr == NULL)
+ return (ERR_NOMEM);
+ raid_handle_sys.handles = ptr;
+
+ /* Clean up the new allocated handles */
+ for (i = raid_handle_sys.handle_num - HANDLER_SLOTS;
+ i < raid_handle_sys.handle_num; ++i) {
+ raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
+ raid_handle_sys.handles[i].next = i + 1;
+ }
+
+ /* For the first time of allocation, set up the system object handle */
+ if (raid_handle_sys.handle_num == HANDLER_SLOTS) {
+ raid_handle_sys.handles[0].type = OBJ_TYPE_SYSTEM;
+ raid_handle_sys.handles[0].next = 0;
+ raid_handle_sys.unused = 1;
+ raid_handle_sys.used = 0;
+ }
+ return (SUCCESS);
+}
+
+static void
+raid_handle_fini()
+{
+ raid_obj_handle_t i;
+
+ i = raid_handle_sys.used;
+
+ /* Close all opened controllers */
+ while (i != 0) {
+ if ((raid_handle_sys.handles[i].type == OBJ_TYPE_CONTROLLER) &&
+ (raid_handle_sys.handles[i].fd != 0) &&
+ (raid_handle_sys.handles[i].raid_lib != NULL))
+ raid_handle_sys.handles[i].raid_lib->close_controller(
+ raid_handle_sys.handles[i].controller_id, NULL);
+ i = raid_handle_sys.handles[i].next;
+ }
+
+ /* Clean up handle space */
+ raid_handle_sys.handle_num = 0;
+ raid_handle_sys.unused = 0;
+ raid_handle_sys.used = 0;
+ free(raid_handle_sys.handles);
+ raid_handle_sys.handles = NULL;
+}
+
+static raid_obj_handle_t
+raid_handle_new(raid_obj_type_id_t type)
+{
+ int ret;
+
+ if (raid_handle_sys.unused == raid_handle_sys.handle_num - 1) {
+ ret = raid_handle_init();
+ if (ret < SUCCESS)
+ return (ret);
+ }
+
+ ret = raid_handle_sys.unused;
+ raid_handle_sys.unused = raid_handle_sys.handles[ret].next;
+
+ raid_handle_sys.handles[ret].next = raid_handle_sys.used;
+ raid_handle_sys.used = ret;
+ raid_handle_sys.handles[ret].type = type;
+
+ return (ret);
+}
+
+static void
+raid_handle_delete(raid_obj_handle_t handle)
+{
+ int i = raid_handle_sys.used, j = 0;
+
+ if (handle == 0)
+ return;
+
+ while (i != 0 && i != handle) {
+ j = i;
+ i = raid_handle_sys.handles[i].next;
+ }
+
+ if (i == handle) {
+ if (j != 0)
+ raid_handle_sys.handles[j].next =
+ raid_handle_sys.handles[i].next;
+ else
+ raid_handle_sys.used =
+ raid_handle_sys.handles[i].next;
+
+ raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
+ raid_handle_sys.handles[i].next =
+ raid_handle_sys.unused;
+ raid_handle_sys.unused = i;
+ }
+}
+
+static void
+raid_handle_delete_controller_comp(uint32_t controller_id)
+{
+ int i = raid_handle_sys.used, j;
+
+ while (i != 0) {
+ j = i;
+ i = raid_handle_sys.handles[i].next;
+ if ((raid_handle_sys.handles[j].controller_id == controller_id) &&
+ (raid_handle_sys.handles[j].type != OBJ_TYPE_CONTROLLER))
+ raid_handle_delete(j);
+ }
+}
+
+static raid_obj_id_t
+raid_handle_to_obj(raid_obj_tab_t *raid_tab, raid_obj_handle_t handle)
+{
+ handle_attr_t *handle_attr;
+ raid_obj_id_t obj_id;
+
+ if (handle == OBJ_SYSTEM)
+ return (OBJ_SYSTEM);
+
+ handle_attr = raid_handle_sys.handles + handle;
+
+ switch (handle_attr->type) {
+ case OBJ_TYPE_SYSTEM:
+ return (OBJ_SYSTEM);
+ case OBJ_TYPE_CONTROLLER:
+ obj_id = obj_locate_controller(raid_tab,
+ handle_attr->controller_id);
+ break;
+ case OBJ_TYPE_ARRAY:
+ obj_id = obj_locate_array(raid_tab,
+ handle_attr->controller_id, handle_attr->array_id);
+ break;
+ case OBJ_TYPE_HSP:
+ obj_id = obj_locate_hsp(raid_tab,
+ handle_attr->controller_id, handle_attr->disk_id,
+ handle_attr->array_id);
+ break;
+ case OBJ_TYPE_DISK:
+ obj_id = obj_locate_disk(raid_tab,
+ handle_attr->controller_id, handle_attr->disk_id);
+ break;
+ case OBJ_TYPE_ARRAY_PART:
+ obj_id = obj_locate_arraypart(raid_tab,
+ handle_attr->controller_id, handle_attr->array_id,
+ handle_attr->disk_id);
+ break;
+ case OBJ_TYPE_DISK_SEG:
+ obj_id = obj_locate_diskseg(raid_tab,
+ handle_attr->controller_id,
+ handle_attr->disk_id, handle_attr->seq_id);
+ break;
+ case OBJ_TYPE_TASK:
+ obj_id = obj_locate_task(raid_tab,
+ handle_attr->controller_id, handle_attr->task_id);
+ break;
+ default:
+ return (ERR_DEVICE_INVALID);
+ }
+
+ if (obj_id < OBJ_NONE)
+ return (obj_id);
+ if (obj_id == OBJ_NONE)
+ return (ERR_DEVICE_NOENT);
+
+ (void) raid_obj_set_handle(raid_tab, obj_id, handle);
+ return (obj_id);
+}
+
+static raid_obj_handle_t
+raid_obj_to_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_id_t obj_id_backup = obj_id;
+ raid_obj_type_id_t type;
+ raid_obj_handle_t handle;
+ controller_attr_t *controller_attr;
+ array_attr_t *array_attr;
+ hsp_attr_t *hsp_attr;
+ disk_attr_t *disk_attr;
+ arraypart_attr_t *arraypart_attr;
+ diskseg_attr_t *diskseg_attr;
+ task_attr_t *task_attr;
+
+ if (obj_id == OBJ_SYSTEM)
+ return (OBJ_SYSTEM);
+
+ /* If the object mapped by a handle */
+ handle = raid_obj_get_handle(raid_tab, obj_id);
+ if (handle != 0)
+ return (handle);
+
+ /* Search for existing handles */
+ for (handle = raid_handle_sys.used; handle != 0;
+ handle = raid_handle_sys.handles[handle].next)
+ if (raid_handle_to_obj(raid_tab, handle) == obj_id)
+ break;
+
+ if (handle != 0)
+ return (handle);
+
+ /* Allocate new handle for this object */
+ type = raid_obj_get_type(raid_tab, obj_id);
+ handle = raid_handle_new(type);
+ (void) raid_obj_set_handle(raid_tab, obj_id, handle);
+ raid_handle_sys.handles[handle].type = type;
+
+ switch (type) {
+ case OBJ_TYPE_SYSTEM:
+ break;
+ case OBJ_TYPE_CONTROLLER:
+ controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].controller_id =
+ controller_attr->controller_id;
+ break;
+ case OBJ_TYPE_ARRAY:
+ array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].array_id = array_attr->array_id;
+ obj_id = obj_get_controller(raid_tab, obj_id);
+ controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].controller_id =
+ controller_attr->controller_id;
+ break;
+ case OBJ_TYPE_HSP:
+ hsp_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].array_id =
+ hsp_attr->associated_id;
+ obj_id = raid_obj_get_container(raid_tab, obj_id);
+ disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
+ obj_id = obj_get_controller(raid_tab, obj_id);
+ controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].controller_id =
+ controller_attr->controller_id;
+ break;
+ case OBJ_TYPE_DISK:
+ disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
+ obj_id = obj_get_controller(raid_tab, obj_id);
+ controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].controller_id =
+ controller_attr->controller_id;
+ break;
+ case OBJ_TYPE_ARRAY_PART:
+ arraypart_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].disk_id =
+ arraypart_attr->disk_id;
+ obj_id = raid_obj_get_container(raid_tab, obj_id);
+ array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].array_id =
+ array_attr->array_id;
+ obj_id = obj_get_controller(raid_tab, obj_id);
+ controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].controller_id =
+ controller_attr->controller_id;
+ break;
+ case OBJ_TYPE_DISK_SEG:
+ diskseg_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].seq_id = diskseg_attr->seq_no;
+ obj_id = raid_obj_get_container(raid_tab, obj_id);
+ disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].disk_id =
+ disk_attr->disk_id;
+ obj_id = obj_get_controller(raid_tab, obj_id);
+ controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].controller_id =
+ controller_attr->controller_id;
+ break;
+ case OBJ_TYPE_TASK:
+ task_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].task_id = task_attr->task_id;
+ obj_id = obj_get_controller(raid_tab, obj_id);
+ controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ raid_handle_sys.handles[handle].controller_id =
+ controller_attr->controller_id;
+ break;
+ default:
+ return (ERR_DEVICE_INVALID);
+ }
+
+ (void) raid_obj_set_handle(raid_tab, obj_id_backup, handle);
+ return (handle);
+}
+
+static raid_lib_t *
+raid_obj_get_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_handle_t handle;
+ controller_attr_t *attr;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
+ return (NULL);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ handle = raid_handle_sys.used;
+ while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
+ raid_handle_sys.handles[handle].controller_id !=
+ attr->controller_id)
+ handle = raid_handle_sys.handles[handle].next;
+
+ if (handle == 0)
+ return (NULL);
+
+ return (raid_handle_sys.handles[handle].raid_lib);
+}
+
+static int
+raid_obj_set_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_lib_t *raid_lib)
+{
+ raid_obj_handle_t handle;
+ controller_attr_t *attr;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
+ return (ERR_DEVICE_TYPE);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ handle = raid_handle_sys.used;
+ while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
+ raid_handle_sys.handles[handle].controller_id !=
+ attr->controller_id)
+ handle = raid_handle_sys.handles[handle].next;
+
+ if (handle == 0)
+ return (ERR_DEVICE_NOENT);
+
+ raid_handle_sys.handles[handle].raid_lib = raid_lib;
+ return (SUCCESS);
+}
+
+static int
+raid_obj_get_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_handle_t handle;
+ controller_attr_t *attr;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
+ return (ERR_DEVICE_TYPE);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ handle = raid_handle_sys.used;
+ while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
+ raid_handle_sys.handles[handle].controller_id !=
+ attr->controller_id)
+ handle = raid_handle_sys.handles[handle].next;
+
+ if (handle == 0)
+ return (ERR_DEVICE_NOENT);
+
+ return (raid_handle_sys.handles[handle].fd);
+}
+
+static int
+raid_obj_set_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, int fd)
+{
+ raid_obj_handle_t handle;
+ controller_attr_t *attr;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
+ return (ERR_DEVICE_TYPE);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ handle = raid_handle_sys.used;
+ while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
+ raid_handle_sys.handles[handle].controller_id !=
+ attr->controller_id)
+ handle = raid_handle_sys.handles[handle].next;
+
+ if (handle == 0)
+ return (ERR_DEVICE_NOENT);
+
+ raid_handle_sys.handles[handle].fd = fd;
+ return (SUCCESS);
+}
+
+/*
+ * Raid object maintenance routines
+ */
+static int
+obj_scan_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_status_t status;
+ raid_obj_type_id_t type;
+ int ret, i, obj_type_cnt, comp_num;
+ raid_obj_id_t *comp_list;
+
+ status = raid_obj_get_status(raid_tab, obj_id);
+ if (status < SUCCESS)
+ return (status);
+
+ if (status & OBJ_STATUS_SCANCOMP)
+ return (SUCCESS);
+
+ type = raid_obj_get_type(raid_tab, obj_id);
+ if (type < OBJ_TYPE_SYSTEM || type > OBJ_TYPE_ALL)
+ return (ERR_DEVICE_INVALID);
+
+ for (obj_type_cnt = OBJ_SYSTEM; obj_type_cnt < OBJ_TYPE_ALL;
+ ++obj_type_cnt) {
+ if (raid_obj_op_sys[type].compnum != NULL)
+ comp_num = raid_obj_op_sys[type].compnum(
+ raid_tab, obj_id, obj_type_cnt);
+ else
+ comp_num = 0;
+
+ if (comp_num < SUCCESS)
+ return (comp_num);
+ if (comp_num == 0)
+ continue;
+
+ comp_list = calloc(comp_num, sizeof (raid_obj_id_t));
+ if (comp_list == NULL)
+ return (ERR_NOMEM);
+
+ for (i = 0; i < comp_num; ++i) {
+ *(comp_list + i) = raid_obj_create(raid_tab,
+ obj_type_cnt);
+ if (*(comp_list + i) < SUCCESS) {
+ ret = *(comp_list + i);
+ free(comp_list);
+ return (ret);
+ }
+
+ (void) raid_obj_clear_status(raid_tab,
+ *(comp_list + i), OBJ_STATUS_CMD_CLEAN);
+ (void) raid_obj_add_org(raid_tab, *(comp_list + i),
+ obj_id);
+ }
+
+ if (raid_obj_op_sys[type].complist != NULL)
+ raid_obj_op_sys[type].complist(raid_tab,
+ obj_id, comp_num, comp_list, obj_type_cnt);
+ free(comp_list);
+ }
+
+ (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_SCANCOMP);
+ return (SUCCESS);
+}
+
+static int
+obj_rescan(raid_obj_tab_t *raid_tab)
+{
+ int ret;
+
+ raid_obj_tab_destroy(raid_tab);
+
+ if (raid_obj_tab_create(raid_tab, HASH_SLOTS) != SUCCESS)
+ return (ERR_NOMEM);
+
+ if ((ret = raid_obj_create_system_obj(raid_tab)) != SUCCESS) {
+ raid_obj_tab_destroy(raid_tab);
+ return (ret);
+ }
+
+ return (SUCCESS);
+}
+
+static raid_obj_id_t
+obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_type_id_t obj_type)
+{
+ raid_obj_id_t id;
+ raid_obj_type_id_t type;
+ raid_obj_status_t status;
+ int ret;
+
+ if ((obj_type < OBJ_TYPE_SYSTEM) || (obj_type > OBJ_TYPE_ALL))
+ return (ERR_DEVICE_TYPE);
+
+ status = raid_obj_get_status(raid_tab, obj_id);
+ if (status < SUCCESS)
+ return (status);
+
+ if (!(status & OBJ_STATUS_SCANCOMP)) {
+ ret = obj_scan_comp(raid_tab, obj_id);
+ if (ret < SUCCESS)
+ return (ret);
+ }
+
+ id = raid_obj_get_comp(raid_tab, obj_id);
+ if (id <= OBJ_NONE)
+ return (id);
+
+ type = raid_obj_get_type(raid_tab, id);
+ if (type < OBJ_TYPE_SYSTEM)
+ return (type);
+
+ if (type == obj_type)
+ return (id);
+
+ while (id > OBJ_NONE) {
+ id = raid_obj_get_sibling(raid_tab, id);
+ if (id <= OBJ_NONE)
+ return (id);
+
+ type = raid_obj_get_type(raid_tab, id);
+ if (type < OBJ_TYPE_SYSTEM)
+ return (type);
+
+ if (type == obj_type)
+ break;
+ };
+
+ return (id);
+}
+
+static raid_obj_id_t
+obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_id_t id;
+ raid_obj_type_id_t type, obj_type;
+
+ id = obj_id;
+ obj_type = raid_obj_get_type(raid_tab, id);
+ if (obj_type < OBJ_TYPE_SYSTEM)
+ return (obj_type);
+
+ do {
+ id = raid_obj_get_sibling(raid_tab, id);
+ if (id < OBJ_NONE)
+ return (id);
+
+ type = raid_obj_get_type(raid_tab, id);
+ if (type < OBJ_TYPE_SYSTEM)
+ return (type);
+ } while ((type != obj_type) && (id != OBJ_NONE));
+
+ return (id);
+}
+
+static int
+obj_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, void **data)
+{
+ raid_obj_type_id_t type;
+ raid_obj_status_t status;
+ void *attr;
+ int ret = SUCCESS;
+
+ status = raid_obj_get_status(raid_tab, obj_id);
+ if (status < SUCCESS)
+ return (status);
+
+ type = raid_obj_get_type(raid_tab, obj_id);
+ if (type < OBJ_TYPE_SYSTEM)
+ return (type);
+
+ if (!(status & OBJ_STATUS_OPENED)) {
+ if (raid_obj_op_sys[type].get_attr == NULL)
+ (void) raid_obj_set_status(raid_tab, obj_id,
+ OBJ_STATUS_OPENED);
+ else
+ ret = raid_obj_op_sys[type].get_attr(raid_tab, obj_id);
+ }
+ if (ret < SUCCESS)
+ return (ret);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL && type != OBJ_TYPE_SYSTEM)
+ return (ERR_DEVICE_INVALID);
+
+ *data = attr;
+ return (SUCCESS);
+}
+
+static raid_obj_id_t
+obj_locate_controller(raid_obj_tab_t *raid_tab, uint32_t controller_id)
+{
+ raid_obj_id_t obj_id;
+ controller_attr_t *attr;
+
+ obj_id = obj_get_comp(raid_tab, OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ do {
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ if (attr->controller_id == controller_id)
+ break;
+ } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) != OBJ_NONE);
+
+ return (obj_id);
+}
+
+static raid_obj_id_t
+obj_locate_array(raid_obj_tab_t *raid_tab, uint32_t controller_id,
+ uint32_t array_id)
+{
+ raid_obj_id_t obj_id;
+
+ obj_id = obj_locate_controller(raid_tab, controller_id);
+ if (obj_id < OBJ_NONE)
+ return (obj_id);
+
+ obj_id = obj_locate_array_recur(raid_tab, obj_id, array_id);
+
+ return (obj_id);
+}
+
+static raid_obj_id_t
+obj_locate_array_recur(raid_obj_tab_t *raid_tab,
+ raid_obj_id_t container_obj_id, uint32_t array_id)
+{
+ raid_obj_id_t obj_id, ret;
+ array_attr_t *attr;
+
+ obj_id = obj_get_comp(raid_tab, container_obj_id, OBJ_TYPE_ARRAY);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ do {
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ if (attr->array_id == array_id)
+ break;
+
+ ret = obj_locate_array_recur(raid_tab, obj_id, array_id);
+ if (ret != OBJ_NONE)
+ return (ret);
+
+ } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
+
+ return (obj_id);
+}
+
+static raid_obj_id_t
+obj_locate_hsp(raid_obj_tab_t *raid_tab, uint32_t controller_id,
+ uint32_t disk_id, uint32_t array_id)
+{
+ raid_obj_id_t obj_id;
+ hsp_attr_t *hsp_attr;
+
+ obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_HSP);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ do {
+ (void) obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
+ if (hsp_attr->associated_id == array_id)
+ break;
+
+ obj_id = obj_get_sibling(raid_tab, obj_id);
+ if (obj_id < OBJ_NONE)
+ return (obj_id);
+ } while (obj_id > OBJ_NONE);
+
+ return (obj_id);
+}
+
+static raid_obj_id_t
+obj_locate_disk(raid_obj_tab_t *raid_tab, uint32_t controller_id,
+ uint32_t disk_id)
+{
+ raid_obj_id_t obj_id;
+ disk_attr_t *attr;
+
+ obj_id = obj_locate_controller(raid_tab, controller_id);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ do {
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ if (attr->disk_id == disk_id)
+ break;
+ } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
+
+ return (obj_id);
+}
+
+static raid_obj_id_t
+obj_locate_arraypart(raid_obj_tab_t *raid_tab, uint32_t controller_id,
+ uint32_t array_id, uint32_t disk_id)
+{
+ raid_obj_id_t obj_id;
+
+ arraypart_attr_t *attr;
+
+ obj_id = obj_locate_array(raid_tab, controller_id, array_id);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY_PART);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ do {
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ if (attr->disk_id == disk_id)
+ break;
+ } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) >
+ OBJ_NONE);
+
+ return (obj_id);
+}
+
+static raid_obj_id_t
+obj_locate_diskseg(raid_obj_tab_t *raid_tab, uint32_t controller_id,
+ uint32_t disk_id, uint32_t seq_no)
+{
+ raid_obj_id_t obj_id;
+ diskseg_attr_t *attr;
+
+ obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK_SEG);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ do {
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ if (attr->seq_no == seq_no)
+ break;
+ } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
+
+ return (obj_id);
+}
+
+static raid_obj_id_t
+obj_locate_task(raid_obj_tab_t *raid_tab, uint32_t controller_id,
+ uint32_t task_id)
+{
+ raid_obj_id_t obj_id, obj_id2, task_obj_id;
+ task_attr_t *attr;
+
+ obj_id = obj_locate_controller(raid_tab, controller_id);
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+
+ obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
+ if (obj_id < OBJ_NONE)
+ return (obj_id);
+
+ do {
+ obj_id2 = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
+ while (obj_id2 != OBJ_NONE) {
+ task_obj_id = obj_get_comp(raid_tab, obj_id2,
+ OBJ_TYPE_TASK);
+
+ if (task_obj_id < OBJ_NONE)
+ return (task_obj_id);
+
+ if (task_obj_id == OBJ_NONE) {
+ obj_id2 = obj_get_sibling(raid_tab, obj_id2);
+ continue;
+ }
+
+ attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ if (attr->task_id == task_id)
+ return (task_obj_id);
+
+ obj_id2 = obj_get_sibling(raid_tab, obj_id2);
+ }
+
+ task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
+ if (task_obj_id < OBJ_NONE)
+ return (task_obj_id);
+
+ if (task_obj_id == OBJ_NONE)
+ continue;
+
+ attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ if (attr->task_id == task_id)
+ return (task_obj_id);
+ } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
+
+ if (obj_id < OBJ_NONE)
+ return (obj_id);
+
+ obj_id = obj_locate_controller(raid_tab, controller_id);
+ obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
+ if (obj_id < OBJ_NONE)
+ return (obj_id);
+
+ do {
+ task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
+ if (task_obj_id < OBJ_NONE)
+ return (task_obj_id);
+
+ if (task_obj_id == OBJ_NONE)
+ continue;
+
+ attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ if (attr->task_id == task_id)
+ return (task_obj_id);
+ } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
+
+ return (obj_id);
+
+}
+
+static raid_obj_id_t
+obj_get_controller(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_id_t id = obj_id;
+
+ while (raid_obj_get_type(raid_tab, id) != OBJ_TYPE_CONTROLLER) {
+ id = raid_obj_get_container(raid_tab, id);
+ if ((id == OBJ_SYSTEM) || (id < OBJ_NONE))
+ return (ERR_DEVICE_INVALID);
+ }
+
+ return (id);
+}
+
+/*
+ * Raid object operation routines
+ */
+static int
+obj_sys_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_type_id_t comp_type)
+{
+ DIR *dir;
+ struct dirent *dp;
+ int num = 0;
+
+ if ((raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM))
+ return (ERR_DEVICE_TYPE);
+
+ if (comp_type != OBJ_TYPE_CONTROLLER)
+ return (0);
+
+ if ((dir = opendir(CFGDIR)) == NULL)
+ return (ERR_DRIVER_NOT_FOUND);
+
+ while ((dp = readdir(dir)) != NULL) {
+ uint32_t controller_id;
+ char path[MAX_PATH_LEN];
+
+ if (strcmp(dp->d_name, ".") == 0 ||
+ strcmp(dp->d_name, "..") == 0)
+ continue;
+
+ if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
+ continue;
+
+ if (controller_id_to_path(controller_id, path) == SUCCESS)
+ ++ num;
+ }
+
+ (void) closedir(dir);
+ return (num);
+}
+
+static int
+obj_sys_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ int num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
+{
+ DIR *dir;
+ struct dirent *dp;
+ controller_attr_t *attr;
+ uint32_t controller_id;
+ uint32_t *tmplist;
+ char path[MAX_PATH_LEN];
+ int i = 0;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM)
+ return (ERR_DEVICE_TYPE);
+ if ((num <= 0) || (comp_list == NULL))
+ return (ERR_OP_ILLEGAL);
+
+ if (comp_type != OBJ_TYPE_CONTROLLER)
+ return (0);
+
+ if ((dir = opendir(CFGDIR)) == NULL)
+ return (ERR_DRIVER_NOT_FOUND);
+ tmplist = calloc(num, sizeof (uint32_t));
+ if (tmplist == NULL) {
+ return (ERR_NOMEM);
+ }
+ while ((dp = readdir(dir)) != NULL) {
+ if (strcmp(dp->d_name, ".") == 0 ||
+ strcmp(dp->d_name, "..") == 0)
+ continue;
+
+ if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
+ continue;
+
+ if (controller_id_to_path(controller_id, path) == SUCCESS) {
+ tmplist[i] = controller_id;
+ ++ i;
+ }
+ }
+ qsort((void *)tmplist, num, sizeof (uint32_t), intcompare);
+ for (i = 0; i < num; i++) {
+ attr = raid_obj_get_data_ptr(raid_tab,
+ *(comp_list + i));
+
+ if (attr == NULL) {
+ free(tmplist);
+ return (ERR_DEVICE_INVALID);
+ }
+
+ attr->controller_id = tmplist[i];
+ }
+ free(tmplist);
+ (void) closedir(dir);
+ return (SUCCESS);
+}
+
+static int
+obj_controller_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_type_id_t comp_type)
+{
+ raid_lib_t *raid_lib;
+ int ret = SUCCESS, fd;
+ controller_attr_t *ctl_attrp;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
+ return (ERR_DEVICE_TYPE);
+
+ if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
+ return (0);
+
+ raid_lib = raid_obj_get_lib(raid_tab, obj_id);
+ fd = raid_obj_get_fd(raid_tab, obj_id);
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if ((raid_lib == NULL) || (ctl_attrp == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ret = raid_lib->compnum(ctl_attrp->controller_id, 0,
+ OBJ_TYPE_CONTROLLER, comp_type);
+
+ return (ret);
+}
+
+static int
+obj_controller_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
+{
+ raid_lib_t *raid_lib;
+ controller_attr_t *ctl_attrp;
+ int ret, i, fd;
+ uint32_t *ids;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
+ return (ERR_DEVICE_TYPE);
+
+ if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
+ return (0);
+
+ if ((comp_num <= 0) || (comp_list == NULL))
+ return (ERR_OP_ILLEGAL);
+
+ for (i = 0; i < comp_num; ++i)
+ if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
+ comp_type)
+ return (ERR_DEVICE_TYPE);
+
+ raid_lib = raid_obj_get_lib(raid_tab, obj_id);
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
+ fd = raid_obj_get_fd(raid_tab, obj_id);
+ if ((raid_lib == NULL) || (ctl_attrp == NULL)|| (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ids = malloc(comp_num * sizeof (uint32_t));
+ if (ids == NULL)
+ return (ERR_NOMEM);
+
+ ret = raid_lib->complist(ctl_attrp->controller_id, 0,
+ OBJ_TYPE_CONTROLLER, comp_type, comp_num, ids);
+ if (ret < SUCCESS) {
+ free(ids);
+ return (ret);
+ }
+ qsort((void *)ids, comp_num, sizeof (uint32_t), intcompare);
+ for (i = 0; i < comp_num; ++ i) {
+ array_attr_t *array_attr;
+ disk_attr_t *disk_attr;
+ void *attr_buf;
+
+ attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
+ if (attr_buf == NULL) {
+ free(ids);
+ return (ERR_DEVICE_INVALID);
+ }
+
+ switch (comp_type) {
+ case OBJ_TYPE_ARRAY:
+ array_attr = attr_buf;
+ array_attr->array_id = *(ids + i);
+ break;
+ case OBJ_TYPE_DISK:
+ disk_attr = attr_buf;
+ disk_attr->disk_id = *(ids + i);
+ break;
+ default:
+ free(ids);
+ return (ERR_DEVICE_INVALID);
+ }
+ }
+
+ free(ids);
+ return (SUCCESS);
+}
+
+static int
+obj_controller_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ controller_attr_t *attr;
+ raid_lib_t *raid_lib;
+ int ret = SUCCESS, fd;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
+ return (ERR_DEVICE_TYPE);
+
+ if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
+ return (SUCCESS);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ raid_lib = raid_obj_get_lib(raid_tab, obj_id);
+ fd = raid_obj_get_fd(raid_tab, obj_id);
+
+ /*
+ * For a controller, even it's not opened, we can still
+ * get the driver name
+ */
+
+ if (fd == 0)
+ return (SUCCESS);
+
+ if (raid_lib == NULL) {
+ return (SUCCESS);
+ }
+
+ ret = raid_lib->get_attr(attr->controller_id, OBJ_ATTR_NONE,
+ OBJ_ATTR_NONE, OBJ_TYPE_CONTROLLER, attr);
+ if (ret < SUCCESS)
+ return (ret);
+
+ (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
+
+ return (ret);
+}
+
+static int
+obj_controller_act(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ uint32_t sub_cmd, void *prop_list, char **plugin_err_str)
+{
+ controller_attr_t *attr;
+ raid_lib_t *raid_lib;
+ int ret, fd;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
+ return (ERR_DEVICE_TYPE);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+
+ raid_lib = raid_obj_get_lib(raid_tab, obj_id);
+ fd = raid_obj_get_fd(raid_tab, obj_id);
+
+ switch (sub_cmd) {
+ case ACT_CONTROLLER_OPEN:
+ /* Check if already opened */
+
+ if (fd > 0)
+ return (SUCCESS);
+
+ /* Check if plugin is already attached */
+ if (raid_lib == NULL) {
+ raid_lib = raid_find_lib(raid_tab, obj_id);
+ if (raid_lib == NULL)
+ return (ERR_DRIVER_NOT_FOUND);
+ }
+
+ ret = raid_lib->open_controller(attr->controller_id,
+ plugin_err_str);
+ if (ret == SUCCESS) {
+ (void) raid_obj_set_lib(raid_tab, obj_id, raid_lib);
+ (void) raid_obj_set_fd(raid_tab, obj_id, 1);
+ }
+ break;
+ case ACT_CONTROLLER_CLOSE:
+
+ if (fd <= 0)
+ return (SUCCESS);
+
+ if (raid_lib == NULL) {
+ return (SUCCESS);
+ }
+ ret = raid_lib->close_controller(attr->controller_id,
+ plugin_err_str);
+ if (ret == SUCCESS) {
+ (void) raid_obj_set_fd(raid_tab, obj_id, 0);
+ (void) raid_obj_set_lib(raid_tab, obj_id, NULL);
+ raid_handle_delete_controller_comp(attr->controller_id);
+ }
+ break;
+ case ACT_CONTROLLER_FLASH_FW:
+ {
+ char *filebuf;
+ int image_fd;
+ uint32_t size;
+ struct stat statbuf;
+
+ if (prop_list == NULL)
+ return (ERR_OP_ILLEGAL);
+
+ /* Open firmware image file */
+ image_fd = open((const char *)prop_list,
+ O_RDONLY | O_NDELAY);
+ if (image_fd == -1)
+ return (ERR_OP_FAILED);
+
+ if (fstat(image_fd, &statbuf) != 0) {
+ (void) close(image_fd);
+ return (ERR_OP_FAILED);
+ }
+
+ filebuf = malloc(statbuf.st_size);
+ if (filebuf == NULL) {
+ (void) close(image_fd);
+ return (ERR_NOMEM);
+ }
+
+ size = read(image_fd, filebuf, statbuf.st_size);
+ if (size != statbuf.st_size) {
+ (void) close(image_fd);
+ free(filebuf);
+ return (ERR_OP_FAILED);
+ }
+
+ if (fd <= 0) {
+ (void) close(image_fd);
+ free(filebuf);
+ return (ERR_DRIVER_CLOSED);
+ }
+
+ if (raid_lib == NULL) {
+ (void) close(image_fd);
+ free(filebuf);
+ return (ERR_DRIVER_CLOSED);
+ }
+ if (raid_lib->flash_fw == NULL) {
+ (void) close(image_fd);
+ free(filebuf);
+ return (ERR_OP_NO_IMPL);
+ }
+
+ ret = raid_lib->flash_fw(attr->controller_id,
+ filebuf, size, plugin_err_str);
+ }
+ break;
+ default:
+ return (ERR_OP_ILLEGAL);
+ }
+
+ return (ret);
+}
+
+static int
+obj_array_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_type_id_t comp_type)
+{
+ array_attr_t *attr;
+ controller_attr_t *ctl_attrp;
+ raid_obj_id_t controller_obj_id;
+ raid_lib_t *raid_lib;
+ int ret = SUCCESS, fd;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
+ return (ERR_DEVICE_TYPE);
+
+ if (comp_type != OBJ_TYPE_ARRAY_PART &&
+ comp_type != OBJ_TYPE_ARRAY &&
+ comp_type != OBJ_TYPE_TASK)
+ return (0);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ controller_obj_id = obj_get_controller(raid_tab, obj_id);
+ if (controller_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
+ if (ctl_attrp == NULL) {
+ return (ERR_DEVICE_INVALID);
+ }
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ret = raid_lib->compnum(ctl_attrp->controller_id, attr->array_id,
+ OBJ_TYPE_ARRAY, comp_type);
+
+ return (ret);
+}
+
+static int
+obj_array_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
+{
+ array_attr_t *attr;
+ controller_attr_t *ctl_attrp;
+ raid_obj_id_t controller_obj_id;
+ raid_lib_t *raid_lib;
+ int ret, i, fd;
+ uint32_t *ids;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
+ return (ERR_DEVICE_TYPE);
+
+ if (comp_type != OBJ_TYPE_ARRAY_PART &&
+ comp_type != OBJ_TYPE_ARRAY &&
+ comp_type != OBJ_TYPE_TASK)
+ return (0);
+
+ if (comp_num <= 0 || comp_list == NULL)
+ return (ERR_OP_ILLEGAL);
+
+ for (i = 0; i < comp_num; ++i)
+ if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
+ comp_type)
+ return (ERR_DEVICE_TYPE);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ controller_obj_id = obj_get_controller(raid_tab, obj_id);
+ if (controller_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
+ if (ctl_attrp == NULL) {
+ return (ERR_DEVICE_INVALID);
+ }
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ids = malloc(comp_num * sizeof (uint32_t));
+ if (ids == NULL)
+ return (ERR_NOMEM);
+
+ ret = raid_lib->complist(ctl_attrp->controller_id,
+ attr->array_id, OBJ_TYPE_ARRAY, comp_type, comp_num, ids);
+
+ if (ret < SUCCESS) {
+ free(ids);
+ return (ret);
+ }
+
+ for (i = 0; i < comp_num; ++ i) {
+ array_attr_t *array_attr;
+ arraypart_attr_t *arraypart_attr;
+ task_attr_t *task_attr;
+ void *attr_buf;
+
+ attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
+ if (attr_buf == NULL) {
+ free(ids);
+ return (ERR_DEVICE_INVALID);
+ }
+
+ switch (comp_type) {
+ case OBJ_TYPE_ARRAY:
+ array_attr = attr_buf;
+ array_attr->array_id = *(ids + i);
+ break;
+ case OBJ_TYPE_ARRAY_PART:
+ arraypart_attr = attr_buf;
+ arraypart_attr->disk_id = *(ids + i);
+ break;
+ case OBJ_TYPE_TASK:
+ task_attr = attr_buf;
+ task_attr->task_id = *(ids + i);
+ break;
+ default:
+ free(ids);
+ return (ERR_DEVICE_INVALID);
+ }
+ }
+
+
+ free(ids);
+ return (ret);
+}
+
+static int
+obj_array_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ array_attr_t *attr;
+ controller_attr_t *ctl_attrp;
+ raid_lib_t *raid_lib;
+ int ret = SUCCESS, fd;
+ raid_obj_id_t controller_obj_id;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
+ return (ERR_DEVICE_TYPE);
+
+ if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
+ return (SUCCESS);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ controller_obj_id = obj_get_controller(raid_tab, obj_id);
+ if (controller_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
+ if (ctl_attrp == NULL) {
+ return (ERR_DEVICE_INVALID);
+ }
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ret = raid_lib->get_attr(ctl_attrp->controller_id,
+ attr->array_id, 0, OBJ_TYPE_ARRAY, attr);
+
+ if (ret < SUCCESS)
+ return (ret);
+
+ (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
+
+ return (ret);
+}
+
+static int
+obj_array_set_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ uint32_t sub_cmd, uint32_t *value, char **plugin_err_str)
+{
+ array_attr_t *attr;
+ controller_attr_t *ctl_attrp;
+ raid_lib_t *raid_lib;
+ int ret = SUCCESS, fd;
+ raid_obj_id_t controller_obj_id;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
+ return (ERR_DEVICE_TYPE);
+
+ switch (sub_cmd) {
+ case SET_CACHE_WR_PLY:
+ if (*value != CACHE_WR_OFF &&
+ *value != CACHE_WR_ON)
+ return (ERR_OP_ILLEGAL);
+ break;
+ case SET_CACHE_RD_PLY:
+ if (*value != CACHE_RD_OFF &&
+ *value != CACHE_RD_ON)
+ return (ERR_OP_ILLEGAL);
+ break;
+ default:
+ return (ERR_OP_ILLEGAL);
+ }
+
+ (void) obj_get_attr(raid_tab, obj_id, (void **)(&attr));
+
+ controller_obj_id = obj_get_controller(raid_tab, obj_id);
+ if (controller_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
+ if (ctl_attrp == NULL) {
+ return (ERR_DEVICE_INVALID);
+ }
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ if (raid_lib->set_attr == NULL)
+ return (ERR_OP_NO_IMPL);
+
+ ret = raid_lib->set_attr(ctl_attrp->controller_id,
+ attr->array_id, sub_cmd, value, plugin_err_str);
+
+ return (ret);
+}
+
+static int
+obj_disk_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_type_id_t comp_type)
+{
+ disk_attr_t *attr;
+ controller_attr_t *ctl_attrp;
+ raid_obj_id_t controller_obj_id;
+ raid_lib_t *raid_lib;
+ int ret = SUCCESS, fd;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
+ return (ERR_DEVICE_TYPE);
+
+ if (comp_type != OBJ_TYPE_DISK_SEG &&
+ comp_type != OBJ_TYPE_HSP &&
+ comp_type != OBJ_TYPE_TASK)
+ return (0);
+ ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
+ if ((ret != SUCCESS) || (attr == NULL)) {
+ return (ERR_DEVICE_INVALID);
+ }
+ if (attr->state == DISK_STATE_FAILED) {
+ return (SUCCESS);
+ }
+
+ controller_obj_id = obj_get_controller(raid_tab, obj_id);
+ if (controller_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
+ if (ctl_attrp == NULL) {
+ return (ERR_DEVICE_INVALID);
+ }
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ret = raid_lib->compnum(ctl_attrp->controller_id,
+ attr->disk_id, OBJ_TYPE_DISK, comp_type);
+
+ return (ret);
+}
+
+static int
+obj_disk_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
+{
+ disk_attr_t *attr;
+ controller_attr_t *ctl_attrp;
+ raid_obj_id_t controller_obj_id;
+ raid_lib_t *raid_lib;
+ int ret, i, fd;
+ uint32_t *ids;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
+ return (ERR_DEVICE_TYPE);
+
+ if (comp_type != OBJ_TYPE_DISK_SEG &&
+ comp_type != OBJ_TYPE_HSP &&
+ comp_type != OBJ_TYPE_TASK)
+ return (0);
+
+ if (comp_num <= 0 || comp_list == NULL)
+ return (ERR_OP_ILLEGAL);
+
+ for (i = 0; i < comp_num; ++i)
+ if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
+ comp_type)
+ return (ERR_DEVICE_TYPE);
+ ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
+ if ((ret != SUCCESS) || (attr == NULL)) {
+ return (ERR_DEVICE_INVALID);
+ }
+ if (attr->state == DISK_STATE_FAILED) {
+ return (SUCCESS);
+ }
+
+ controller_obj_id = obj_get_controller(raid_tab, obj_id);
+ if (controller_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
+ if (ctl_attrp == NULL) {
+ return (ERR_DEVICE_INVALID);
+ }
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ids = malloc(comp_num * sizeof (uint32_t));
+ if (ids == NULL)
+ return (ERR_NOMEM);
+
+ ret = raid_lib->complist(ctl_attrp->controller_id,
+ attr->disk_id, OBJ_TYPE_DISK, comp_type, comp_num, ids);
+
+ if (ret < SUCCESS) {
+ free(ids);
+ return (ret);
+ }
+
+ for (i = 0; i < comp_num; ++ i) {
+ diskseg_attr_t *diskseg_attr;
+ hsp_attr_t *hsp_attr;
+ task_attr_t *task_attr;
+ void *attr_buf;
+
+ attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
+ if (attr_buf == NULL) {
+ free(ids);
+ return (ERR_DEVICE_INVALID);
+ }
+
+ switch (comp_type) {
+ case OBJ_TYPE_DISK_SEG:
+ diskseg_attr = attr_buf;
+ diskseg_attr->seq_no = *(ids + i);
+ break;
+ case OBJ_TYPE_HSP:
+ hsp_attr = attr_buf;
+ hsp_attr->associated_id = *(ids + i);
+ break;
+ case OBJ_TYPE_TASK:
+ task_attr = attr_buf;
+ task_attr->task_id = *(ids + i);
+ break;
+ default:
+ free(ids);
+ return (ERR_DEVICE_INVALID);
+ }
+ }
+
+
+ free(ids);
+ return (ret);
+}
+
+static int
+obj_disk_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ disk_attr_t *attr;
+ controller_attr_t *ctl_attrp;
+ raid_lib_t *raid_lib;
+ int ret = SUCCESS, fd;
+ raid_obj_id_t controller_obj_id;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
+ return (ERR_DEVICE_TYPE);
+
+ if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
+ return (SUCCESS);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ controller_obj_id = obj_get_controller(raid_tab, obj_id);
+ if (controller_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
+ if (ctl_attrp == NULL) {
+ return (ERR_DEVICE_INVALID);
+ }
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ret = raid_lib->get_attr(ctl_attrp->controller_id,
+ attr->disk_id, 0, OBJ_TYPE_DISK, attr);
+
+ if (ret < SUCCESS)
+ return (ret);
+
+ (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
+
+ return (ret);
+}
+
+static int
+obj_hsp_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ hsp_attr_t *attr;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_HSP)
+ return (ERR_DEVICE_TYPE);
+
+ if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
+ return (SUCCESS);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ if (attr->associated_id == (uint32_t)OBJ_ATTR_NONE)
+ attr->type = HSP_TYPE_GLOBAL;
+ else
+ attr->type = HSP_TYPE_LOCAL;
+
+ return (SUCCESS);
+}
+
+static int
+obj_arraypart_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ arraypart_attr_t *attr;
+ array_attr_t *array_attr;
+ controller_attr_t *ctl_attrp;
+ raid_lib_t *raid_lib;
+ int ret = SUCCESS, fd;
+ raid_obj_id_t controller_obj_id, array_obj_id;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY_PART)
+ return (ERR_DEVICE_TYPE);
+
+ if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
+ return (SUCCESS);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ array_obj_id = raid_obj_get_container(raid_tab, obj_id);
+ if (array_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
+ if (array_attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ controller_obj_id = obj_get_controller(raid_tab, obj_id);
+ if (controller_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
+ if (ctl_attrp == NULL) {
+ return (ERR_DEVICE_INVALID);
+ }
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ret = raid_lib->get_attr(ctl_attrp->controller_id,
+ array_attr->array_id, attr->disk_id,
+ OBJ_TYPE_ARRAY_PART, attr);
+
+ if (ret < SUCCESS)
+ return (ret);
+
+ (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
+
+ return (ret);
+}
+
+static int
+obj_diskseg_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ diskseg_attr_t *attr;
+ disk_attr_t *disk_attr;
+ controller_attr_t *ctl_attrp;
+ raid_lib_t *raid_lib;
+ int ret = SUCCESS, fd;
+ raid_obj_id_t controller_obj_id, disk_obj_id;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK_SEG)
+ return (ERR_DEVICE_TYPE);
+
+ if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
+ return (SUCCESS);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
+ if (disk_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
+ if (disk_attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ controller_obj_id = obj_get_controller(raid_tab, obj_id);
+ if (controller_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
+ if (ctl_attrp == NULL) {
+ return (ERR_DEVICE_INVALID);
+ }
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ret = raid_lib->get_attr(ctl_attrp->controller_id,
+ disk_attr->disk_id, attr->seq_no, OBJ_TYPE_DISK_SEG, attr);
+
+ if (ret < SUCCESS)
+ return (ret);
+
+ (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
+
+ return (ret);
+}
+
+static int
+obj_task_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ task_attr_t *attr;
+ controller_attr_t *ctl_attrp;
+ raid_lib_t *raid_lib;
+ int ret = SUCCESS, fd;
+ raid_obj_id_t controller_obj_id;
+
+ if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_TASK)
+ return (ERR_DEVICE_TYPE);
+
+ attr = raid_obj_get_data_ptr(raid_tab, obj_id);
+ if (attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ controller_obj_id = obj_get_controller(raid_tab, obj_id);
+ if (controller_obj_id < OBJ_NONE)
+ return (ERR_DEVICE_INVALID);
+
+ ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
+ if (ctl_attrp == NULL) {
+ return (ERR_DEVICE_INVALID);
+ }
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ ret = raid_lib->get_attr(ctl_attrp->controller_id,
+ attr->task_id, OBJ_ATTR_NONE, OBJ_TYPE_TASK, attr);
+
+ return (ret);
+}
+
+static int
+obj_array_create(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
+ int num_of_comp, raid_obj_id_t *disk_list, char **plugin_err_str)
+{
+ controller_attr_t *controller_attr;
+ array_attr_t *array_attr, array_attr2;
+ disk_attr_t *disk_attr;
+ arraypart_attr_t *arraypart_attrs;
+ raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
+ raid_lib_t *raid_lib;
+ int i, j, ret, fd;
+ int disk_cnt = 0, disk_set_num = 0, set_num = 0, layer_cnt = 0;
+ uint64_t min_disk_capacity = 0;
+ uint32_t *diskid_list;
+
+ array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
+ if (array_attr == NULL)
+ return (ERR_DEVICE_INVALID);
+
+ /* Check the disk layout expression */
+ if (disk_list[0] != OBJ_SEPARATOR_BEGIN ||
+ disk_list[num_of_comp - 1] != OBJ_SEPARATOR_END)
+ return (ERR_ARRAY_LAYOUT);
+ for (i = 0; i < num_of_comp; ++i) {
+ if (disk_list[i] == OBJ_SEPARATOR_BEGIN) {
+ if (disk_cnt != 0)
+ return (ERR_ARRAY_LAYOUT);
+ ++layer_cnt;
+ continue;
+ }
+ if (disk_list[i] == OBJ_SEPARATOR_END) {
+ if (disk_set_num == 0)
+ disk_set_num = disk_cnt;
+ else if (disk_set_num != disk_cnt && disk_cnt != 0)
+ return (ERR_ARRAY_LAYOUT);
+ disk_cnt = 0;
+ ++set_num;
+ --layer_cnt;
+ continue;
+ }
+ switch (array_attr->raid_level) {
+ case RAID_LEVEL_0:
+ case RAID_LEVEL_1:
+ case RAID_LEVEL_1E:
+ case RAID_LEVEL_5:
+ if (layer_cnt != 1)
+ return (ERR_ARRAY_LAYOUT);
+ break;
+ case RAID_LEVEL_10:
+ case RAID_LEVEL_50:
+ if (layer_cnt != 2)
+ return (ERR_ARRAY_LAYOUT);
+ break;
+ default:
+ return (ERR_ARRAY_LEVEL);
+ }
+ ++disk_cnt;
+ }
+
+ if (layer_cnt != 0)
+ return (ERR_ARRAY_LAYOUT);
+
+ switch (array_attr->raid_level) {
+ case RAID_LEVEL_0:
+ if (disk_set_num < 2 || set_num != 1)
+ return (ERR_ARRAY_LAYOUT);
+ break;
+ case RAID_LEVEL_1:
+ if (disk_set_num != 2 || set_num != 1)
+ return (ERR_ARRAY_LAYOUT);
+ break;
+ case RAID_LEVEL_1E:
+ case RAID_LEVEL_5:
+ if (disk_set_num < 3 || set_num != 1)
+ return (ERR_ARRAY_LAYOUT);
+ break;
+ case RAID_LEVEL_10:
+ if (disk_set_num != 2 || set_num < 2)
+ return (ERR_ARRAY_LAYOUT);
+ break;
+ case RAID_LEVEL_50:
+ if (disk_set_num < 3 || set_num < 2)
+ return (ERR_ARRAY_LAYOUT);
+ break;
+ default:
+ return (ERR_ARRAY_LEVEL);
+ }
+
+ arraypart_attrs = calloc(num_of_comp, sizeof (arraypart_attr_t));
+ if (arraypart_attrs == NULL)
+ return (ERR_NOMEM);
+
+ for (i = 0; i < num_of_comp; ++i) {
+ /* Keep seperators */
+ if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
+ arraypart_attrs[i].disk_id =
+ (uint32_t)OBJ_SEPARATOR_BEGIN;
+ continue;
+ }
+
+ if (*(disk_list + i) == OBJ_SEPARATOR_END) {
+ arraypart_attrs[i].disk_id =
+ (uint32_t)OBJ_SEPARATOR_END;
+ continue;
+ }
+
+ disk_cnt++;
+ /* Check if it's a disk */
+ if (raid_obj_get_type(raid_tab, *(disk_list + i)) !=
+ OBJ_TYPE_DISK)
+ return (ERR_DEVICE_TYPE);
+
+ /* Check if it's duplicated with other disks */
+ for (j = 0; j < i; ++j)
+ if (*(disk_list + j) == *(disk_list + i)) {
+ free(arraypart_attrs);
+ return (ERR_DEVICE_DUP);
+ }
+
+ /* Check disk status */
+ ret = obj_get_attr(raid_tab, *(disk_list + i),
+ (void **)(&disk_attr));
+ if (ret != SUCCESS)
+ return (ret);
+
+ if (disk_attr->state != DISK_STATE_GOOD) {
+ free(arraypart_attrs);
+ return (ERR_DISK_STATE);
+ }
+
+ /* All disks must belong to the same controller */
+ obj_id = obj_get_controller(raid_tab, *(disk_list + i));
+ if (obj_id <= OBJ_NONE)
+ return (obj_id);
+ if (controller_obj_id == OBJ_NONE) {
+ controller_obj_id = obj_id;
+ ret = obj_get_attr(raid_tab, controller_obj_id,
+ (void **)(&controller_attr));
+ } else if (obj_id != controller_obj_id) {
+ free(arraypart_attrs);
+ return (ERR_DRIVER_ACROSS);
+ }
+
+ /* Check if the disk contains too many segments */
+ obj_id = obj_get_comp(raid_tab, *(disk_list + i),
+ OBJ_TYPE_DISK_SEG);
+ j = 0;
+ while (obj_id > OBJ_NONE) {
+ ++j;
+ obj_id = obj_get_sibling(raid_tab, obj_id);
+ }
+ if (j > controller_attr->max_seg_per_disk) {
+ free(arraypart_attrs);
+ return (ERR_DISK_SEG_AMOUNT);
+ }
+
+ /* Each disk should be un-used */
+ if ((ret = raid_dev_unmounted(controller_attr->controller_id,
+ disk_attr->disk_id)) != SUCCESS) {
+ free(arraypart_attrs);
+ return (ret);
+ }
+
+ /* Check if controller is a hostraid controller */
+ if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
+ /*
+ * For hostraid, the first disk should
+ * be with of minimum capacity
+ */
+ if (min_disk_capacity == 0) {
+ min_disk_capacity = disk_attr->capacity;
+
+ /* Can not specify capacity for hostraid */
+ if (array_attr->capacity != 0) {
+ free(arraypart_attrs);
+ return (ERR_DISK_SPACE);
+ }
+ } else if (min_disk_capacity > disk_attr->capacity) {
+ free(arraypart_attrs);
+ return (ERR_DISK_SPACE);
+ }
+
+ /* Disk should not be used for hostraid */
+ obj_id = obj_get_comp(raid_tab, *(disk_list + i),
+ OBJ_TYPE_DISK_SEG);
+ if (obj_id < OBJ_NONE) {
+ free(arraypart_attrs);
+ return (obj_id);
+ } else if (obj_id > OBJ_NONE) {
+ free(arraypart_attrs);
+ return (ERR_DISK_NOT_EMPTY);
+ }
+ }
+
+ arraypart_attrs[i].disk_id = disk_attr->disk_id;
+ arraypart_attrs[i].offset = OBJ_ATTR_NONE;
+ arraypart_attrs[i].size = OBJ_ATTR_NONE;
+ }
+
+ /* Check if array amount exceeds limit */
+ if (controller_attr->max_array_num <=
+ obj_controller_compnum(raid_tab, controller_obj_id,
+ OBJ_TYPE_ARRAY))
+ return (ERR_ARRAY_AMOUNT);
+
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ /* Check if the controller can support the array RAID level */
+ switch (array_attr->raid_level) {
+ case RAID_LEVEL_0:
+ if (!(controller_attr->capability & RAID_CAP_RAID0)) {
+ free(arraypart_attrs);
+ return (ERR_ARRAY_LEVEL);
+ }
+ break;
+ case RAID_LEVEL_1:
+ if (!(controller_attr->capability & RAID_CAP_RAID1)) {
+ free(arraypart_attrs);
+ return (ERR_ARRAY_LEVEL);
+ }
+ break;
+ case RAID_LEVEL_1E:
+ if (!(controller_attr->capability & RAID_CAP_RAID1E)) {
+ free(arraypart_attrs);
+ return (ERR_ARRAY_LEVEL);
+ }
+ break;
+ case RAID_LEVEL_5:
+ if (!(controller_attr->capability & RAID_CAP_RAID5)) {
+ free(arraypart_attrs);
+ return (ERR_ARRAY_LEVEL);
+ }
+ break;
+ case RAID_LEVEL_10:
+ if (!(controller_attr->capability & RAID_CAP_RAID10)) {
+ free(arraypart_attrs);
+ return (ERR_ARRAY_LEVEL);
+ }
+ break;
+ case RAID_LEVEL_50:
+ if (!(controller_attr->capability & RAID_CAP_RAID50)) {
+ free(arraypart_attrs);
+ return (ERR_ARRAY_LEVEL);
+ }
+ break;
+ default:
+ free(arraypart_attrs);
+ return (ERR_ARRAY_LEVEL);
+ }
+
+ /* Check if plug in can calculate the maximum size */
+ (void) memcpy(&array_attr2, array_attr, sizeof (array_attr_t));
+ array_attr2.capacity = OBJ_ATTR_NONE;
+ ret = raid_lib->array_create(controller_attr->controller_id,
+ &array_attr2, num_of_comp, arraypart_attrs, plugin_err_str);
+
+ /* If plugin/driver will not calculate space */
+ if (ret == ERR_OP_NO_IMPL) {
+ /* Calculate the maximum capacity */
+ array_attr2.capacity = raid_space_noalign(raid_tab,
+ array_attr2.raid_level, num_of_comp, disk_list,
+ arraypart_attrs);
+
+ /*
+ * If controller is capable to allocate space,
+ * set offset and size attributes to OBJ_ATTR_NONE
+ * and let the controller to determine these value
+ */
+ if (controller_attr->capability & RAID_CAP_SMART_ALLOC)
+ for (i = 0; i < num_of_comp; ++i) {
+ arraypart_attrs[i].offset =
+ OBJ_ATTR_NONE;
+ arraypart_attrs[i].size =
+ OBJ_ATTR_NONE;
+ }
+
+ /* There's no enough space for specified capacity */
+ if (array_attr->capacity > array_attr2.capacity) {
+ free(arraypart_attrs);
+ return (ERR_ARRAY_SIZE);
+ }
+
+ /* capacity == 0, allocate maximum space */
+ if (array_attr->capacity == 0)
+ array_attr->capacity = array_attr2.capacity;
+ } else if (ret < SUCCESS) {
+ free(arraypart_attrs);
+ return (ret);
+ } else if (array_attr2.capacity < array_attr->capacity) {
+ /* Return the maximum size */
+ array_attr->capacity = array_attr2.capacity;
+ free(arraypart_attrs);
+ return (ERR_ARRAY_SIZE);
+ }
+
+ if (array_attr->capacity < ARRAYPART_MIN_SIZE * disk_cnt) {
+ free(arraypart_attrs);
+ return (ERR_ARRAY_SIZE);
+ }
+
+
+ ret = raid_lib->array_create(controller_attr->controller_id,
+ array_attr, num_of_comp, arraypart_attrs, plugin_err_str);
+ free(arraypart_attrs);
+
+ if (ret != SUCCESS)
+ return (ret);
+
+ /* Add array object into device tree so that we can map the handle */
+ (void) raid_obj_add_org(raid_tab, array_obj_id, controller_obj_id);
+
+ /* unconfig disk minor nodes if it's hostraid */
+ if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
+ diskid_list = (uint32_t *)calloc(num_of_comp,
+ sizeof (uint32_t));
+ if (diskid_list == NULL) {
+ return (ERR_NOMEM);
+ }
+
+ for (i = 0; i < num_of_comp; ++i) {
+ if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
+ diskid_list[i] = (uint32_t)OBJ_SEPARATOR_BEGIN;
+ } else if (*(disk_list + i) == OBJ_SEPARATOR_END) {
+ diskid_list[i] = (uint32_t)OBJ_SEPARATOR_END;
+ } else {
+ ret = obj_get_attr(raid_tab, *(disk_list + i),
+ (void **)(&disk_attr));
+ if (ret != SUCCESS) {
+ free(diskid_list);
+ return (ret);
+ }
+ diskid_list[i] = disk_attr->disk_id;
+ }
+ }
+
+ for (i = 0; i < num_of_comp; ++i) {
+ if (diskid_list[i] == (uint32_t)OBJ_SEPARATOR_BEGIN ||
+ diskid_list[i] == (uint32_t)OBJ_SEPARATOR_END) {
+ continue;
+ }
+
+ if (TARGET(diskid_list[i]) ==
+ ARRAY_TARGET(array_attr->array_id) &&
+ LUN(diskid_list[i]) ==
+ ARRAY_LUN(array_attr->array_id))
+ continue;
+
+ ret = raid_dev_config(CFGA_CMD_UNCONFIGURE,
+ controller_attr->controller_id, diskid_list[i], 0);
+ if (ret != SUCCESS) {
+ free(diskid_list);
+ return (ret);
+ }
+ }
+ free(diskid_list);
+ } else {
+ /* for HW raid */
+ ret = raid_dev_config(CFGA_CMD_CONFIGURE,
+ controller_attr->controller_id, array_attr->array_id, 1);
+ }
+
+ return (ret);
+}
+
+static int
+obj_array_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
+ char **plugin_err_str)
+{
+ raid_obj_id_t controller_obj_id;
+ controller_attr_t *controller_attr;
+ array_attr_t *array_attr;
+ arraypart_attr_t *arraypart_attr;
+ raid_obj_id_t arraypart_obj_id;
+ raid_lib_t *raid_lib;
+ int i = 0, j = 0, ret, fd;
+ uint32_t *disk_ids = NULL;
+
+ controller_obj_id = obj_get_controller(raid_tab, array_obj_id);
+ if (controller_obj_id <= OBJ_NONE)
+ return (controller_obj_id);
+
+ ret = obj_get_attr(raid_tab, controller_obj_id,
+ (void **)(&controller_attr));
+ if (ret < SUCCESS) {
+ return (ret);
+ }
+ ret = obj_get_attr(raid_tab, array_obj_id, (void **)(&array_attr));
+ if (ret < SUCCESS)
+ return (ret);
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ if ((ret = raid_dev_unmounted(controller_attr->controller_id,
+ array_attr->array_id)) != SUCCESS)
+ return (ret);
+
+ /* change minor nodes state for disks */
+ if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
+ arraypart_obj_id = obj_get_comp(raid_tab, array_obj_id,
+ OBJ_TYPE_ARRAY_PART);
+ if (arraypart_obj_id < OBJ_NONE) {
+ return (arraypart_obj_id);
+ }
+
+ /*
+ * Check how many disks in volume and malloc space for
+ * disk_ids; note that the number should be the disk
+ * number minors 1 since the primary disk should not
+ * be counted in.
+ */
+ while (arraypart_obj_id = obj_get_sibling(raid_tab,
+ arraypart_obj_id)) {
+ if (arraypart_obj_id < OBJ_NONE)
+ return (arraypart_obj_id);
+ ++i;
+ }
+ disk_ids = calloc(i, sizeof (uint32_t));
+ if (disk_ids == NULL)
+ return (ERR_NOMEM);
+
+ /* Stor all member disk ids into disk_ids */
+ arraypart_obj_id = obj_get_comp(raid_tab, array_obj_id,
+ OBJ_TYPE_ARRAY_PART);
+
+ while (arraypart_obj_id > OBJ_NONE) {
+ ret = obj_get_attr(raid_tab, arraypart_obj_id,
+ (void **)(&arraypart_attr));
+ if (ret != SUCCESS) {
+ return (ret);
+ }
+ if (TARGET(arraypart_attr->disk_id) ==
+ ARRAY_TARGET(array_attr->array_id) &&
+ LUN(arraypart_attr->disk_id) ==
+ ARRAY_LUN(array_attr->array_id)) {
+ arraypart_obj_id = obj_get_sibling(raid_tab,
+ arraypart_obj_id);
+ continue;
+ }
+
+ disk_ids[j] = arraypart_attr->disk_id;
+ ++j;
+ arraypart_obj_id = obj_get_sibling(raid_tab,
+ arraypart_obj_id);
+ }
+ } else {
+ ret = raid_dev_config(CFGA_CMD_UNCONFIGURE,
+ controller_attr->controller_id, array_attr->array_id, 1);
+ if (ret != SUCCESS)
+ return (ret);
+ }
+
+ ret = raid_lib->array_delete(controller_attr->controller_id,
+ array_attr->array_id, plugin_err_str);
+ if (ret < SUCCESS) {
+ if (disk_ids)
+ free(disk_ids);
+ return (ret);
+ }
+
+ if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
+ for (i = 0; i < j; ++i)
+ ret = raid_dev_config(CFGA_CMD_CONFIGURE,
+ controller_attr->controller_id,
+ disk_ids[i], 0);
+ if (ret < SUCCESS) {
+ free(disk_ids);
+ return (ret);
+ }
+ }
+
+ if (disk_ids)
+ free(disk_ids);
+ return (ret);
+}
+
+static int
+obj_hsp_bind(raid_obj_tab_t *raid_tab, int num, raid_obj_id_t *obj_ids,
+ char **plugin_err_str)
+{
+ raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
+ raid_obj_id_t array_obj_id, disk_obj_id;
+ hsp_relation_t *hsp_relation;
+ controller_attr_t *controller_attr;
+ array_attr_t *array_attr;
+ arraypart_attr_t *arraypart_attr;
+ disk_attr_t *disk_attr;
+ diskseg_attr_t *diskseg_attr;
+ hsp_attr_t *hsp_attr;
+ raid_lib_t *raid_lib;
+ int ret, fd, i, j = 0;
+
+ hsp_relation = malloc(sizeof (hsp_relation_t) * num);
+ if (hsp_relation == NULL)
+ return (ERR_NOMEM);
+
+ for (i = 0; i < num; ++i) {
+ array_obj_id = *(obj_ids + i * 2);
+ disk_obj_id = *(obj_ids + i * 2 + 1);
+
+ if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK ||
+ (array_obj_id != OBJ_ATTR_NONE &&
+ raid_obj_get_type(raid_tab, array_obj_id) !=
+ OBJ_TYPE_ARRAY)) {
+ free(hsp_relation);
+ return (ERR_DEVICE_TYPE);
+ }
+
+ /* Get controller attributes */
+ if (controller_obj_id == OBJ_NONE)
+ controller_obj_id = obj_get_controller(raid_tab,
+ disk_obj_id);
+ else if (controller_obj_id != obj_get_controller(raid_tab,
+ disk_obj_id)) {
+ free(hsp_relation);
+ return (ERR_DRIVER_ACROSS);
+ }
+
+ ret = obj_get_attr(raid_tab, controller_obj_id,
+ (void **)(&controller_attr));
+
+ /* Get disk attributes */
+ ret = obj_get_attr(raid_tab, disk_obj_id,
+ (void **)(&disk_attr));
+ if (disk_attr->state == DISK_STATE_FAILED) {
+ free(hsp_relation);
+ return (ERR_DISK_STATE);
+ }
+
+ /* If it's not a hsp disk, check if there's occupied space */
+ if (obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP) ==
+ OBJ_NONE) {
+ obj_id = obj_get_comp(raid_tab, disk_obj_id,
+ OBJ_TYPE_DISK_SEG);
+ while (obj_id != OBJ_NONE) {
+ ret = obj_get_attr(raid_tab, obj_id,
+ (void **)(&diskseg_attr));
+ if (!(diskseg_attr->state &
+ DISKSEG_STATE_RESERVED)) {
+ free(hsp_relation);
+ return (ERR_DISK_NOT_EMPTY);
+ }
+ obj_id = obj_get_sibling(raid_tab, obj_id);
+ }
+ }
+
+ if (array_obj_id != OBJ_ATTR_NONE) {
+ /* If local hsp is supported */
+ if (!(controller_attr->capability & RAID_CAP_L_HSP)) {
+ free(hsp_relation);
+ return (ERR_OP_ILLEGAL);
+ }
+
+ if (raid_obj_get_type(raid_tab, array_obj_id) !=
+ OBJ_TYPE_ARRAY) {
+ free(hsp_relation);
+ return (ERR_DEVICE_TYPE);
+ }
+
+ /* Get array attributes */
+ ret = obj_get_attr(raid_tab, array_obj_id,
+ (void **)(&array_attr));
+ /* RAID 0 array can not use hsp */
+ if (array_attr->raid_level == RAID_LEVEL_0) {
+ free(hsp_relation);
+ return (ERR_ARRAY_LEVEL);
+ }
+
+ /* If It's belong to another controller */
+ if (controller_obj_id != obj_get_controller(raid_tab,
+ array_obj_id)) {
+ free(hsp_relation);
+ return (ERR_DRIVER_ACROSS);
+ }
+
+ /* Get an array part attributes */
+ if ((array_attr->raid_level == RAID_LEVEL_10) ||
+ (array_attr->raid_level == RAID_LEVEL_50))
+ obj_id = obj_get_comp(raid_tab, array_obj_id,
+ OBJ_TYPE_ARRAY);
+ else
+ obj_id = array_obj_id;
+ obj_id = obj_get_comp(raid_tab, obj_id,
+ OBJ_TYPE_ARRAY_PART);
+ ret = obj_get_attr(raid_tab, obj_id,
+ (void **)(&arraypart_attr));
+
+ /* Check if disk space is enough for array */
+ if (arraypart_attr->size > disk_attr->capacity) {
+ free(hsp_relation);
+ return (ERR_DISK_SPACE);
+ }
+ if (controller_attr->capability & RAID_CAP_ARRAY_ALIGN)
+ if ((arraypart_attr->size +
+ arraypart_attr->offset) >
+ disk_attr->capacity) {
+ free(hsp_relation);
+ return (ERR_DISK_SPACE);
+ }
+ } else if (!(controller_attr->capability & RAID_CAP_G_HSP)) {
+ /* if global hsp is supported */
+ free(hsp_relation);
+ return (ERR_OP_ILLEGAL);
+ }
+
+ /*
+ * If the array is already associated with the
+ * local hsp, or it's a global hsp, ignore it
+ */
+ obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
+ if (obj_id > OBJ_NONE) {
+ if (obj_get_attr(raid_tab, obj_id,
+ (void **)&hsp_attr) >= SUCCESS) {
+ if (((hsp_attr->type == HSP_TYPE_GLOBAL) &&
+ (array_obj_id != OBJ_ATTR_NONE)) ||
+ ((hsp_attr->type == HSP_TYPE_LOCAL) &&
+ (array_obj_id == OBJ_ATTR_NONE))) {
+ free(hsp_relation);
+ return (ERR_OP_ILLEGAL);
+ }
+ }
+ }
+
+ if (array_obj_id != OBJ_ATTR_NONE)
+ hsp_relation[j].array_id = array_attr->array_id;
+ else
+ hsp_relation[j].array_id = (uint32_t)OBJ_ATTR_NONE;
+ hsp_relation[j].disk_id = disk_attr->disk_id;
+ ++ j;
+ }
+
+
+ if (j == 0)
+ return (SUCCESS);
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ if (raid_lib->hsp_bind == NULL) {
+ free(hsp_relation);
+ return (ERR_OP_NO_IMPL);
+ }
+
+ ret = raid_lib->hsp_bind(controller_attr->controller_id,
+ j, hsp_relation, plugin_err_str);
+
+ free(hsp_relation);
+ return (ret);
+}
+
+static int
+obj_hsp_unbind(raid_obj_tab_t *raid_tab, int num, raid_obj_id_t *obj_ids,
+ char **plugin_err_str)
+{
+ raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
+ raid_obj_id_t array_obj_id, disk_obj_id;
+ hsp_relation_t *hsp_relation;
+ controller_attr_t *controller_attr;
+ array_attr_t *array_attr;
+ disk_attr_t *disk_attr;
+ hsp_attr_t *hsp_attr;
+ raid_lib_t *raid_lib;
+ int ret, fd, i, j = 0;
+
+ hsp_relation = malloc(sizeof (hsp_relation_t) * num);
+ if (hsp_relation == NULL)
+ return (ERR_NOMEM);
+
+ for (i = 0; i < num; ++i) {
+ array_obj_id = *(obj_ids + i * 2);
+ disk_obj_id = *(obj_ids + i * 2 + 1);
+
+ if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK) {
+ free(hsp_relation);
+ return (ERR_DEVICE_TYPE);
+ }
+
+ /* Get controller attributes */
+ if (controller_obj_id == OBJ_NONE)
+ controller_obj_id = obj_get_controller(raid_tab,
+ disk_obj_id);
+ else if (controller_obj_id != obj_get_controller(raid_tab,
+ disk_obj_id)) {
+ free(hsp_relation);
+ return (ERR_DRIVER_ACROSS);
+ }
+
+ ret = obj_get_attr(raid_tab, controller_obj_id,
+ (void **)(&controller_attr));
+
+ /* Get disk attributes */
+ ret = obj_get_attr(raid_tab, disk_obj_id,
+ (void **)(&disk_attr));
+ if (disk_attr->state == DISK_STATE_FAILED) {
+ free(hsp_relation);
+ return (ERR_DISK_STATE);
+ }
+
+ /* If it's not a hsp disk */
+ obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
+ if (obj_id == OBJ_NONE) {
+ free(hsp_relation);
+ return (ERR_DISK_STATE);
+ }
+ ret = obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
+
+ if (array_obj_id != OBJ_ATTR_NONE) {
+ if (raid_obj_get_type(raid_tab, array_obj_id) !=
+ OBJ_TYPE_ARRAY) {
+ free(hsp_relation);
+ return (ERR_DEVICE_TYPE);
+ }
+
+ /* Get array attributes */
+ ret = obj_get_attr(raid_tab, array_obj_id,
+ (void **)(&array_attr));
+
+ /* If It's belong to another controller */
+ if (controller_obj_id != obj_get_controller(raid_tab,
+ array_obj_id)) {
+ free(hsp_relation);
+ return (ERR_DRIVER_ACROSS);
+ }
+
+ /* If want to remove an array from a global hsp */
+ if (hsp_attr->type == HSP_TYPE_GLOBAL) {
+ free(hsp_relation);
+ return (ERR_OP_ILLEGAL);
+ }
+
+ do {
+ (void) obj_get_attr(raid_tab, obj_id,
+ (void **)(&hsp_attr));
+
+ if (hsp_attr->associated_id ==
+ array_attr->array_id ||
+ hsp_attr->type == HSP_TYPE_GLOBAL)
+ break;
+
+ obj_id = obj_get_sibling(raid_tab, obj_id);
+ } while (obj_id > OBJ_NONE);
+ } else if (hsp_attr->type != HSP_TYPE_GLOBAL) {
+ /* if global hsp is supported */
+ free(hsp_relation);
+ return (ERR_OP_ILLEGAL);
+ }
+
+ /*
+ * If array is associated with a local hsp, or remove a
+ * global hsp disk
+ */
+ if ((obj_id && (array_obj_id != OBJ_ATTR_NONE)) ||
+ (array_obj_id == OBJ_ATTR_NONE)) {
+ if (array_obj_id != OBJ_ATTR_NONE)
+ hsp_relation[j].array_id = array_attr->array_id;
+ else
+ hsp_relation[j].array_id =
+ (uint32_t)OBJ_ATTR_NONE;
+ hsp_relation[j].disk_id = disk_attr->disk_id;
+ ++ j;
+ } else {
+ free(hsp_relation);
+ return (ERR_OP_ILLEGAL);
+ }
+ }
+
+
+ raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
+ fd = raid_obj_get_fd(raid_tab, controller_obj_id);
+ if ((raid_lib == NULL) || (fd == 0))
+ return (ERR_DRIVER_CLOSED);
+
+ if (raid_lib->hsp_unbind == NULL) {
+ free(hsp_relation);
+ return (ERR_OP_NO_IMPL);
+ }
+
+ ret = raid_lib->hsp_unbind(controller_attr->controller_id,
+ j, hsp_relation, plugin_err_str);
+
+ free(hsp_relation);
+ return (ret);
+}
+
+/*
+ * Object maintennance routines
+ */
+static int
+raid_obj_create_system_obj(raid_obj_tab_t *raid_tab)
+{
+ raid_obj_t *raid_obj;
+ int ret;
+
+ raid_obj = calloc(1, sizeof (raid_obj_t));
+ if (raid_obj == NULL)
+ return (ERR_NOMEM);
+
+ raid_obj->obj_id = OBJ_SYSTEM;
+ raid_obj->obj_type_id = OBJ_TYPE_SYSTEM;
+ raid_obj->data = NULL;
+
+ ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
+ if (ret == ERR_DEVICE_DUP) {
+ free(raid_obj);
+ return (ERR_DEVICE_UNCLEAN);
+ }
+
+ return (SUCCESS);
+}
+
+static raid_obj_id_t
+raid_obj_id_new(raid_obj_tab_t *raid_tab)
+{
+ ++ raid_tab->obj_id_cnt;
+ if (raid_tab->obj_id_cnt <= 0)
+ return (ERR_DEVICE_OVERFLOW);
+
+ return (raid_tab->obj_id_cnt);
+}
+
+static void *
+raid_obj_attr_new(raid_obj_type_id_t obj_type)
+{
+ void *obj_attr = NULL;
+
+ switch (obj_type) {
+ case OBJ_TYPE_CONTROLLER:
+ obj_attr = calloc(1, sizeof (controller_attr_t));
+ break;
+ case OBJ_TYPE_ARRAY:
+ obj_attr = calloc(1, sizeof (array_attr_t));
+ break;
+ case OBJ_TYPE_DISK:
+ obj_attr = calloc(1, sizeof (disk_attr_t));
+ break;
+ case OBJ_TYPE_HSP:
+ obj_attr = calloc(1, sizeof (hsp_attr_t));
+ break;
+ case OBJ_TYPE_ARRAY_PART:
+ obj_attr = calloc(1, sizeof (arraypart_attr_t));
+ break;
+ case OBJ_TYPE_DISK_SEG:
+ obj_attr = calloc(1, sizeof (diskseg_attr_t));
+ break;
+ case OBJ_TYPE_TASK:
+ obj_attr = calloc(1, sizeof (task_attr_t));
+ break;
+ default:
+ break;
+ }
+
+ return (obj_attr);
+}
+
+static raid_obj_id_t
+raid_obj_create(raid_obj_tab_t *raid_tab, raid_obj_type_id_t obj_type)
+{
+ raid_obj_t *raid_obj;
+ int ret;
+ void *data_ptr;
+
+ raid_obj = calloc(1, sizeof (raid_obj_t));
+ if (raid_obj == NULL)
+ return (ERR_NOMEM);
+
+ raid_obj->obj_id = raid_obj_id_new(raid_tab);
+ if (raid_obj->obj_id < OBJ_NONE)
+ return (ERR_DEVICE_OVERFLOW);
+
+ ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
+ if (ret == ERR_DEVICE_DUP) {
+ free(raid_obj);
+ return (ERR_DEVICE_DUP);
+ }
+
+ data_ptr = raid_obj_attr_new(obj_type);
+ if (data_ptr == NULL) {
+ (void) raid_obj_delete(raid_tab, raid_obj->obj_id);
+ return (ERR_NOMEM);
+ }
+
+ (void) raid_obj_set_data_ptr(raid_tab, raid_obj->obj_id, data_ptr);
+
+ (void) raid_obj_set_type(raid_tab, raid_obj->obj_id, obj_type);
+ return (raid_obj->obj_id);
+}
+
+static int
+raid_obj_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t raid_obj_id)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_remove(raid_tab, raid_obj_id);
+ if (obj != NULL) {
+ free(obj->data);
+ free(obj);
+ return (SUCCESS);
+ }
+
+ return (ERR_DEVICE_NOENT);
+}
+
+static int
+raid_obj_add_org(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_id_t container_id)
+{
+ raid_obj_id_t tmp, tmp1;
+
+ tmp = raid_obj_get_comp(raid_tab, container_id);
+ if (tmp < OBJ_NONE)
+ return (ERR_DEVICE_NOENT);
+
+ if (tmp == OBJ_NONE) {
+ (void) raid_obj_set_container(raid_tab, obj_id, container_id);
+ (void) raid_obj_set_comp(raid_tab, container_id, obj_id);
+ return (SUCCESS);
+ }
+
+ while ((tmp1 = raid_obj_get_sibling(raid_tab, tmp)) != OBJ_NONE)
+ tmp = tmp1;
+
+ if (raid_obj_set_sibling(raid_tab, tmp, obj_id) < SUCCESS)
+ return (ERR_DEVICE_NOENT);
+ (void) raid_obj_set_container(raid_tab, obj_id, container_id);
+
+ return (SUCCESS);
+}
+
+static raid_obj_type_id_t
+raid_obj_get_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ if ((obj->obj_type_id < OBJ_TYPE_SYSTEM) ||
+ (obj->obj_type_id >= OBJ_TYPE_ALL))
+ return (ERR_DEVICE_INVALID);
+
+ return (obj->obj_type_id);
+}
+
+static int
+raid_obj_set_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_type_id_t type)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ if ((type < OBJ_TYPE_SYSTEM) || (type >= OBJ_TYPE_ALL))
+ return (ERR_DEVICE_TYPE);
+
+ obj->obj_type_id = type;
+ return (SUCCESS);
+}
+
+static raid_obj_status_t
+raid_obj_get_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ return (obj->status);
+}
+
+static int
+raid_obj_set_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_status_t status)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ obj->status = obj->status | status;
+
+ return (SUCCESS);
+}
+
+static int
+raid_obj_clear_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_status_t status)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ obj->status = obj->status & ~status;
+
+ return (SUCCESS);
+}
+
+static raid_obj_id_t
+raid_obj_get_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ return (obj->container);
+}
+
+static int
+raid_obj_set_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_id_t container_id)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ obj->container = container_id;
+ return (SUCCESS);
+}
+
+static raid_obj_id_t
+raid_obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ return (obj->component);
+}
+
+static int
+raid_obj_set_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_id_t comp)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ obj->component = comp;
+ return (SUCCESS);
+}
+
+static raid_obj_id_t
+raid_obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ return (obj->sibling);
+}
+
+static int
+raid_obj_set_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_id_t sibling)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ obj->sibling = sibling;
+
+ return (SUCCESS);
+}
+
+static void *
+raid_obj_get_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (NULL);
+
+ return (obj->data);
+}
+
+static int
+raid_obj_set_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ void *data)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ obj->data = data;
+
+ return (SUCCESS);
+}
+
+static raid_obj_handle_t
+raid_obj_get_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ return (obj->handle);
+}
+
+static int
+raid_obj_set_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
+ raid_obj_handle_t handle)
+{
+ raid_obj_t *obj;
+
+ obj = raid_obj_tab_find(raid_tab, obj_id);
+ if (obj == NULL)
+ return (ERR_DEVICE_NOENT);
+
+ obj->handle = handle;
+ return (SUCCESS);
+}
+/*
+ * Object list maintennance routines
+ */
+static void
+raid_list_create(raid_list_t *list, size_t offset)
+{
+ list->head = NULL;
+ list->tail = NULL;
+ list->offset = offset;
+}
+
+static void *
+raid_list_head(raid_list_t *list)
+{
+ return (list->head);
+}
+
+static void *
+raid_list_next(raid_list_t *list, void *obj)
+{
+ raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj);
+
+ return (el->next);
+}
+
+static void
+raid_list_insert_tail(raid_list_t *list, void *obj)
+{
+ raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
+
+ el->prev = list->tail;
+ list->tail = obj;
+
+ el->next = NULL;
+
+ if (list->head == NULL)
+ list->head = obj;
+
+ if (el->prev != NULL) {
+ el1 = LIST_OBJ_TO_EL(list, el->prev);
+ el1->next = obj;
+ }
+}
+
+static void
+raid_list_remove(raid_list_t *list, void *obj)
+{
+ raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
+
+ if (list->head == obj)
+ list->head = el->next;
+
+ if (list->tail == obj)
+ list->tail = el->prev;
+
+ if (el->next != NULL) {
+ el1 = LIST_OBJ_TO_EL(list, el->next);
+ el1->prev = el->prev;
+ }
+
+ if (el->prev != NULL) {
+ el1 = LIST_OBJ_TO_EL(list, el->prev);
+ el1->next = el->next;
+ }
+
+ el->prev = el->next = NULL;
+}
+
+static void *
+raid_list_remove_head(raid_list_t *list)
+{
+ void *obj = list->head;
+
+ if (obj != NULL)
+ raid_list_remove(list, obj);
+
+ return (obj);
+}
+
+static void *
+raid_list_find(raid_list_t *list, raid_obj_id_t obj_id)
+{
+ raid_obj_t *obj;
+
+ for (obj = raid_list_head(list); obj != NULL;
+ obj = raid_list_next(list, obj))
+ if (obj->obj_id == obj_id)
+ break;
+
+ return (obj);
+}
+
+static int
+raid_obj_tab_create(raid_obj_tab_t *tab, size_t hash_slots)
+{
+ unsigned i;
+
+ if (hash_slots == 0)
+ return (ERR_OP_ILLEGAL);
+
+ tab->slots = hash_slots;
+
+ if ((tab->table = calloc(hash_slots, sizeof (raid_list_t))) == NULL)
+ return (ERR_NOMEM);
+
+ for (i = 0; i < hash_slots; i++)
+ raid_list_create(&tab->table[i], offsetof(raid_obj_t, el));
+
+ return (SUCCESS);
+}
+
+static void
+raid_obj_tab_destroy(raid_obj_tab_t *tab)
+{
+ unsigned i;
+
+ for (i = 0; i < tab->slots; i++) {
+ struct raid_obj_t *obj;
+
+ while ((obj = raid_list_remove_head(&tab->table[i])) != NULL)
+ free(obj);
+
+ raid_list_destroy(&tab->table[i]);
+ }
+
+ if (tab->table)
+ free(tab->table);
+
+ tab->table = NULL;
+ tab->slots = 0;
+ tab->obj_id_cnt = 0;
+}
+
+static int
+raid_obj_tab_insert(raid_obj_tab_t *tab, raid_obj_id_t id, void *obj)
+{
+ raid_list_t *list;
+
+ list = OBJ_TAB_SLOT(tab, id);
+
+ if (raid_list_find(list, id) != NULL)
+ return (ERR_DEVICE_DUP);
+
+ raid_list_insert_tail(list, obj);
+
+ return (SUCCESS);
+}
+
+static void *
+raid_obj_tab_remove(raid_obj_tab_t *tab, raid_obj_id_t id)
+{
+ raid_list_t *list;
+ raid_obj_t *obj;
+
+ list = OBJ_TAB_SLOT(tab, id);
+
+ if ((obj = raid_list_find(list, id)) != NULL)
+ raid_list_remove(list, obj);
+
+ return (obj);
+}
+
+static void *
+raid_obj_tab_find(raid_obj_tab_t *tab, raid_obj_id_t id)
+{
+ raid_list_t *list;
+ raid_obj_t *obj;
+
+ list = OBJ_TAB_SLOT(tab, id);
+ obj = raid_list_find(list, id);
+
+ return (obj);
+}
+
+static void
+raid_list_destroy(raid_list_t *list)
+{
+ list->head = NULL;
+ list->tail = NULL;
+ list->offset = 0;
+}
+
+/*
+ * Plug-in maintennance routines
+ */
+static int
+controller_id_to_path(uint32_t controller_id, char *path)
+{
+ char buf[MAX_PATH_LEN] = {0}, buf1[MAX_PATH_LEN] = {0}, *colon;
+
+ (void) snprintf(buf, MAX_PATH_LEN, "%s/c%d", CFGDIR, controller_id);
+ if (readlink(buf, buf1, sizeof (buf1)) < 0)
+ return (ERR_DRIVER_NOT_FOUND);
+
+ if (buf1[0] != '/')
+ (void) snprintf(buf, sizeof (buf), "%s/", CFGDIR);
+ else
+ buf[0] = 0;
+ (void) strlcat(buf, buf1, MAX_PATH_LEN);
+
+ colon = strrchr(buf, ':');
+ if (colon == NULL)
+ return (ERR_DRIVER_NOT_FOUND);
+ else
+ *colon = 0;
+
+ (void) snprintf(path, MAX_PATH_LEN, "%s:devctl", buf);
+
+ if (access(path, F_OK) < 0)
+ return (ERR_DRIVER_NOT_FOUND);
+
+ return (SUCCESS);
+}
+
+static char *
+controller_id_to_driver_name(uint32_t controller_id)
+{
+ char buf[MAX_PATH_LEN];
+ di_node_t di_node;
+ char *name, *tmp;
+ int ret;
+
+ ret = controller_id_to_path(controller_id, buf);
+ if (ret < SUCCESS)
+ return (NULL);
+
+ tmp = strrchr(buf, ':');
+ if (tmp != NULL)
+ *tmp = 0;
+
+ tmp = strstr(buf, "pci");
+ if (tmp == NULL)
+ return (NULL);
+
+ di_node = di_init(tmp, DINFOPROP);
+ if (di_node == DI_NODE_NIL)
+ return (NULL);
+
+ name = di_driver_name(di_node);
+
+ return (name);
+}
+
+static void
+raid_plugin_init()
+{
+ raid_lib_t *raid_lib = raid_lib_sys;
+
+ while (raid_lib) {
+ raid_lib_sys = raid_lib->next;
+ (void) dlclose(raid_lib->lib_handle);
+ free(raid_lib);
+ raid_lib = raid_lib_sys;
+ }
+}
+
+static raid_lib_t *
+raid_plugin_load(char *driver_name)
+{
+ char buf[MAX_PATH_LEN] = {0};
+ raid_lib_t *supplib;
+ void *sym;
+
+ supplib = calloc(1, sizeof (raid_lib_t));
+ if (supplib == NULL)
+ return (NULL);
+
+ (void) snprintf(buf, MAX_PATH_LEN, "%s/%s.so.1",
+ SUPP_PLUGIN_DIR, driver_name);
+
+ supplib->lib_handle = dlopen(buf, RTLD_LAZY);
+ if (supplib->lib_handle == NULL) {
+ free(supplib);
+ return (NULL);
+ }
+
+ supplib->name = driver_name;
+
+ if ((sym = dlsym(supplib->lib_handle, "rdcfg_version")) == NULL)
+ supplib->version = RDCFG_PLUGIN_V1;
+ else {
+ supplib->version = *((uint32_t *)sym);
+ if (supplib->version != RDCFG_PLUGIN_V1) {
+ (void) dlclose(supplib->lib_handle);
+ free(supplib);
+ return (NULL);
+ }
+ }
+
+ if ((sym = dlsym(supplib->lib_handle, "rdcfg_open_controller")) ==
+ NULL) {
+ (void) dlclose(supplib->lib_handle);
+ free(supplib);
+ return (NULL);
+ } else
+ supplib->open_controller = (int(*)(uint32_t, char **))sym;
+
+ if ((sym = dlsym(supplib->lib_handle, "rdcfg_close_controller")) ==
+ NULL) {
+ (void) dlclose(supplib->lib_handle);
+ free(supplib);
+ return (NULL);
+ } else
+ supplib->close_controller = (int (*)(uint32_t, char **))sym;
+
+ if ((sym = dlsym(supplib->lib_handle, "rdcfg_compnum")) == NULL) {
+ (void) dlclose(supplib->lib_handle);
+ free(supplib);
+ return (NULL);
+ } else
+ supplib->compnum = (int (*)(uint32_t, uint32_t,
+ raid_obj_type_id_t, raid_obj_type_id_t))sym;
+
+ if ((sym = dlsym(supplib->lib_handle, "rdcfg_complist")) == NULL) {
+ (void) dlclose(supplib->lib_handle);
+ free(supplib);
+ return (NULL);
+ } else
+ supplib->complist = (int (*)(uint32_t, uint32_t,
+ raid_obj_type_id_t, raid_obj_type_id_t, int, void *))sym;
+
+ if ((sym = dlsym(supplib->lib_handle, "rdcfg_get_attr")) == NULL) {
+ (void) dlclose(supplib->lib_handle);
+ free(supplib);
+ return (NULL);
+ } else
+ supplib->get_attr = (int (*)(uint32_t, uint32_t, uint32_t,
+ raid_obj_type_id_t, void*))sym;
+
+ if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_create")) == NULL) {
+ (void) dlclose(supplib->lib_handle);
+ free(supplib);
+ return (NULL);
+ } else
+ supplib->array_create = (int (*)(uint32_t, array_attr_t *, int,
+ arraypart_attr_t *, char **))sym;
+
+ if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_delete")) == NULL) {
+ (void) dlclose(supplib->lib_handle);
+ free(supplib);
+ return (NULL);
+ } else
+ supplib->array_delete =
+ (int (*)(uint32_t, uint32_t, char **))sym;
+
+ supplib->hsp_bind = (int (*)(uint32_t, uint32_t, hsp_relation_t *,
+ char **))dlsym(supplib->lib_handle, "rdcfg_hsp_bind");
+ supplib->hsp_unbind = (int (*)(uint32_t, uint32_t, hsp_relation_t *,
+ char **))dlsym(supplib->lib_handle, "rdcfg_hsp_unbind");
+ supplib->set_attr = (int (*)(uint32_t, uint32_t, uint32_t, uint32_t *,
+ char **))dlsym(supplib->lib_handle, "rdcfg_set_attr");
+ supplib->flash_fw = (int (*)(uint32_t, char *, uint32_t, char **))
+ dlsym(supplib->lib_handle, "rdcfg_flash_fw");
+
+ supplib->next = raid_lib_sys;
+ raid_lib_sys = supplib;
+ return (supplib);
+}
+
+static raid_lib_t *
+raid_find_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t controller_obj_id)
+{
+ controller_attr_t *controller_attr;
+ raid_lib_t *raid_lib;
+ char *driver_name;
+ raid_obj_handle_t handle;
+
+ /* Check if it's mapped to handle structure */
+ handle = raid_obj_to_handle(raid_tab, controller_obj_id);
+ if (raid_handle_sys.handles[handle].raid_lib != NULL)
+ return (raid_handle_sys.handles[handle].raid_lib);
+
+ (void) obj_get_attr(raid_tab, controller_obj_id,
+ (void **)(&controller_attr));
+
+ /* Check if the plugin module is already loaded */
+ driver_name = controller_id_to_driver_name(
+ controller_attr->controller_id);
+ if (driver_name == NULL)
+ return (NULL);
+
+ raid_lib = raid_lib_sys;
+ while (raid_lib != NULL) {
+ if (raid_lib->name != NULL &&
+ strcmp(driver_name, raid_lib->name) == 0)
+ return (raid_lib);
+
+ raid_lib = raid_lib->next;
+ }
+
+ /* Loading the plugin module */
+ raid_lib = raid_plugin_load(driver_name);
+
+ return (raid_lib);
+}
diff --git a/usr/src/lib/libraidcfg/i386/Makefile b/usr/src/lib/libraidcfg/i386/Makefile
new file mode 100644
index 0000000000..f8ddafac61
--- /dev/null
+++ b/usr/src/lib/libraidcfg/i386/Makefile
@@ -0,0 +1,31 @@
+#
+# 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
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libraidcfg/sparc/Makefile b/usr/src/lib/libraidcfg/sparc/Makefile
new file mode 100644
index 0000000000..f8ddafac61
--- /dev/null
+++ b/usr/src/lib/libraidcfg/sparc/Makefile
@@ -0,0 +1,31 @@
+#
+# 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
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libraidcfg/sparcv9/Makefile b/usr/src/lib/libraidcfg/sparcv9/Makefile
new file mode 100644
index 0000000000..22ff31377a
--- /dev/null
+++ b/usr/src/lib/libraidcfg/sparcv9/Makefile
@@ -0,0 +1,32 @@
+#
+# 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
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libsecdb/exec_attr.txt b/usr/src/lib/libsecdb/exec_attr.txt
index e568985fcb..1f410856a0 100644
--- a/usr/src/lib/libsecdb/exec_attr.txt
+++ b/usr/src/lib/libsecdb/exec_attr.txt
@@ -95,6 +95,7 @@ File System Management:suser:cmd:::/usr/sbin/mountall:uid=0
File System Management:solaris:cmd:::/usr/sbin/quotacheck:uid=0;gid=sys
File System Management:solaris:cmd:::/usr/sbin/quotaoff:uid=0;gid=sys
File System Management:solaris:cmd:::/usr/sbin/quotaon:uid=0;gid=sys
+File System Management:solaris:cmd:::/usr/sbin/raidctl:privs=sys_config,sys_devices;euid=0
File System Management:suser:cmd:::/usr/sbin/ramdiskadm:euid=0
File System Management:suser:cmd:::/usr/sbin/share:uid=0;gid=root
File System Management:suser:cmd:::/usr/sbin/sharemgr:uid=0;gid=root
diff --git a/usr/src/lib/raidcfg_plugins/Makefile b/usr/src/lib/raidcfg_plugins/Makefile
new file mode 100644
index 0000000000..ec46aed318
--- /dev/null
+++ b/usr/src/lib/raidcfg_plugins/Makefile
@@ -0,0 +1,52 @@
+#
+# 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
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/raidcfg_plugins/Makefile
+#
+
+include $(SRC)/Makefile.master
+
+CLOSED_PLUGIN = $(CLOSED)/lib/raidcfg_plugins/
+
+$(CLOSED_BUILD)COMMON_SUBDIRS += $(CLOSED_PLUGIN)/mpt
+
+SUBDIRS= $(COMMON_SUBDIRS) $($(MACH)_SUBDIRS)
+
+all:= TARGET= all
+install:= TARGET= install
+clean:= TARGET= clean
+clobber:= TARGET= clobber
+lint:= TARGET= lint
+_msg:= TARGET= _msg
+
+.KEEP_STATE:
+
+all clean clobber lint install _msg: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_com b/usr/src/pkgdefs/SUNWcsl/prototype_com
index 5e557a0004..4a8c324b85 100644
--- a/usr/src/pkgdefs/SUNWcsl/prototype_com
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_com
@@ -21,7 +21,7 @@
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -221,6 +221,7 @@ s none usr/lib/librt.so.1=../../lib/librt.so.1
s none usr/lib/librt.so=../../lib/librt.so.1
s none usr/lib/libposix4.so=../../lib/librt.so.1
s none usr/lib/libposix4.so.1=../../lib/librt.so.1
+f none usr/lib/libraidcfg.so.1 755 root bin
s none usr/lib/librtld.so.1=../../lib/librtld.so.1
s none usr/lib/librtld_db.so=../../lib/librtld_db.so.1
s none usr/lib/librtld_db.so.1=../../lib/librtld_db.so.1
@@ -289,6 +290,8 @@ s none usr/lib/nss_nis.so.1=../../lib/nss_nis.so.1
s none usr/lib/nss_nisplus.so.1=../../lib/nss_nisplus.so.1
s none usr/lib/nss_user.so.1=../../lib/nss_user.so.1
f none usr/lib/passwdutil.so.1 755 root bin
+d none usr/lib/raidcfg 755 root bin
+f none usr/lib/raidcfg/mpt.so.1 755 root bin
s none usr/lib/straddr.so=./straddr.so.2
f none usr/lib/straddr.so.2 755 root bin
d none usr/lib/security 755 root bin
diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_i386 b/usr/src/pkgdefs/SUNWcsl/prototype_i386
index 4c65a8fd58..3e59533bc2 100644
--- a/usr/src/pkgdefs/SUNWcsl/prototype_i386
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_i386
@@ -20,7 +20,7 @@
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -86,6 +86,8 @@ d none usr/lib/lwp/amd64 755 root bin
s none usr/lib/lwp/64=amd64
s none usr/lib/lwp/amd64/libthread.so.1=../../amd64/libthread.so.1
s none usr/lib/lwp/amd64/libthread_db.so.1=../../amd64/libthread_db.so.1
+d none usr/lib/raidcfg/amd64 755 root bin
+f none usr/lib/raidcfg/amd64/mpt.so.1 755 root bin
d none usr/lib/security/amd64 755 root bin
s none usr/lib/security/64=amd64
f none usr/lib/security/amd64/crypt_bsdmd5.so.1 755 root bin
@@ -196,6 +198,7 @@ f none usr/lib/amd64/libproject.so.1 755 root bin
s none usr/lib/amd64/libproject.so=libproject.so.1
f none usr/lib/amd64/libpkcs11.so.1 755 root bin
s none usr/lib/amd64/libpkcs11.so=libpkcs11.so.1
+f none usr/lib/amd64/libraidcfg.so.1 755 root bin
f none usr/lib/amd64/lib300.so.1 755 root bin
s none usr/lib/amd64/lib300.so=./lib300.so.1
f none usr/lib/amd64/lib300s.so.1 755 root bin
diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_sparc b/usr/src/pkgdefs/SUNWcsl/prototype_sparc
index 1bcdad558d..3b103442f9 100644
--- a/usr/src/pkgdefs/SUNWcsl/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_sparc
@@ -21,7 +21,7 @@
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -79,6 +79,8 @@ d none usr/lib/lwp/sparcv9 755 root bin
s none usr/lib/lwp/64=sparcv9
s none usr/lib/lwp/sparcv9/libthread.so.1=../../sparcv9/libthread.so.1
s none usr/lib/lwp/sparcv9/libthread_db.so.1=../../sparcv9/libthread_db.so.1
+d none usr/lib/raidcfg/sparcv9 755 root bin
+f none usr/lib/raidcfg/sparcv9/mpt.so.1 755 root bin
d none usr/lib/security/sparcv9 755 root bin
s none usr/lib/security/64=sparcv9
f none usr/lib/security/sparcv9/crypt_bsdmd5.so.1 755 root bin
@@ -189,6 +191,7 @@ f none usr/lib/sparcv9/libproject.so.1 755 root bin
s none usr/lib/sparcv9/libproject.so=libproject.so.1
f none usr/lib/sparcv9/libpkcs11.so.1 755 root bin
s none usr/lib/sparcv9/libpkcs11.so=libpkcs11.so.1
+f none usr/lib/sparcv9/libraidcfg.so.1 755 root bin
f none usr/lib/sparcv9/lib300.so.1 755 root bin
s none usr/lib/sparcv9/lib300.so=./lib300.so.1
f none usr/lib/sparcv9/lib300s.so.1 755 root bin
diff --git a/usr/src/pkgdefs/etc/exception_list_i386 b/usr/src/pkgdefs/etc/exception_list_i386
index c20e9716df..724028cff5 100644
--- a/usr/src/pkgdefs/etc/exception_list_i386
+++ b/usr/src/pkgdefs/etc/exception_list_i386
@@ -423,6 +423,16 @@ usr/lib/llib-ldisasm i386
usr/lib/llib-ldisasm.ln i386
usr/lib/amd64/llib-ldisasm.ln i386
#
+# Private interfaces for libraidcfg
+#
+usr/include/raidcfg.h i386
+usr/include/raidcfg_spi.h i386
+usr/lib/libraidcfg.so i386
+usr/lib/llib-lraidcfg i386
+usr/lib/llib-lraidcfg.ln i386
+usr/lib/amd64/libraidcfg.so i386
+usr/lib/amd64/llib-lraidcfg.ln i386
+#
# This file is used for private communication between mdb, drv/kmdb, and
# misc/kmdb. The interfaces described herein are not intended for customer
# use, and are thus excluded from packaging.
diff --git a/usr/src/pkgdefs/etc/exception_list_sparc b/usr/src/pkgdefs/etc/exception_list_sparc
index d8930e923a..a280a97752 100644
--- a/usr/src/pkgdefs/etc/exception_list_sparc
+++ b/usr/src/pkgdefs/etc/exception_list_sparc
@@ -427,6 +427,16 @@ usr/lib/llib-ldisasm sparc
usr/lib/llib-ldisasm.ln sparc
usr/lib/sparcv9/llib-ldisasm.ln sparc
#
+# Private interfaces for libraidcfg
+#
+usr/include/raidcfg.h sparc
+usr/include/raidcfg_spi.h sparc
+usr/lib/libraidcfg.so sparc
+usr/lib/llib-lraidcfg sparc
+usr/lib/llib-lraidcfg.ln sparc
+usr/lib/sparcv9/llib-lraidcfg.ln sparc
+usr/lib/sparcv9/libraidcfg.so sparc
+#
# This file is used for private communication between mdb, drv/kmdb, and
# misc/kmdb. The interfaces described herein are not intended for customer
# use, and are thus excluded from packaging.