diff options
author | jc156560 <none@none> | 2007-01-21 16:17:27 -0800 |
---|---|---|
committer | jc156560 <none@none> | 2007-01-21 16:17:27 -0800 |
commit | 711890bc9379ceea66272dc8d4981812224ea86e (patch) | |
tree | b1e518a5474da8ddcbedad3919bf88a2f8f4f567 /usr/src/lib | |
parent | c7a40cc4a9ca339dad64780ebf91c8ca8a28715a (diff) | |
download | illumos-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/Makefile | 4 | ||||
-rw-r--r-- | usr/src/lib/libraidcfg/Makefile | 61 | ||||
-rw-r--r-- | usr/src/lib/libraidcfg/Makefile.com | 51 | ||||
-rw-r--r-- | usr/src/lib/libraidcfg/amd64/Makefile | 32 | ||||
-rw-r--r-- | usr/src/lib/libraidcfg/common/llib-lraidcfg | 122 | ||||
-rw-r--r-- | usr/src/lib/libraidcfg/common/mapfile-vers | 49 | ||||
-rw-r--r-- | usr/src/lib/libraidcfg/common/raidcfg.c | 4672 | ||||
-rw-r--r-- | usr/src/lib/libraidcfg/i386/Makefile | 31 | ||||
-rw-r--r-- | usr/src/lib/libraidcfg/sparc/Makefile | 31 | ||||
-rw-r--r-- | usr/src/lib/libraidcfg/sparcv9/Makefile | 32 | ||||
-rw-r--r-- | usr/src/lib/libsecdb/exec_attr.txt | 1 | ||||
-rw-r--r-- | usr/src/lib/raidcfg_plugins/Makefile | 52 |
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: |