summaryrefslogtreecommitdiff
path: root/usr/src/lib
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/lib
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/lib')
-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
12 files changed, 5137 insertions, 1 deletions
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: