raidcfg.c revision e7dcc4f88a44295346fce0b9eb3d10eb1c442c0f
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <fcntl.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 <config_admin.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
#if defined(__sparcv9)
#define SUPP_PLUGIN_DIR "/usr/lib/raidcfg/sparcv9"
#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;
/* in the linked data structures (objects) */
} raid_list_t;
typedef struct {
void *prev;
void *next;
typedef struct {
/*
* Object type structure containing function pointers;
*/
typedef struct {
char **);
raid_obj_id_t *, char **);
/*
* Common object data structure
*/
typedef struct {
void *data; /* Pointer to attribute structure */
} raid_obj_t;
/*
* Definition about handle
*/
typedef struct {
#pragma init(raidcfg_init)
#pragma fini(raidcfg_fini)
/*
* Function prototypes
*/
raid_obj_id_t *, arraypart_attr_t *);
static int raid_handle_init();
static void raid_handle_fini();
static void raid_handle_delete(raid_obj_handle_t);
static void raid_handle_delete_controller_comp(uint32_t);
static int obj_rescan(raid_obj_tab_t *);
uint32_t);
uint32_t, void *, char **);
raid_obj_id_t *, char **);
static int raid_obj_create_system_obj(raid_obj_tab_t *);
static void *raid_obj_attr_new(raid_obj_type_id_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_obj_tab_destroy(raid_obj_tab_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 *);
/* Global object table */
/* Plug-in modules maintenance data structures */
/* Handle table definition */
static struct {
int handle_num;
int used;
int unused;
} raid_handle_sys = {0, 0, 0, NULL};
/*
* RAID object method table definition
*/
obj_hsp_unbind}, /* hsp 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:
break;
case STD_IOCTL:
"Request standard IOCTL service.\n");
break;
case ERR_DRIVER_NOT_FOUND:
"Controller device can not be found.\n");
break;
case ERR_DRIVER_OPEN:
break;
case ERR_DRIVER_LOCK:
break;
case ERR_DRIVER_CLOSED:
break;
case ERR_DRIVER_ACROSS:
"Operation across multiple controllers.\n");
break;
case ERR_ARRAY_LEVEL:
"Operation not support with volume of this level.\n");
break;
case ERR_ARRAY_SIZE:
"Capacity of array out of range.\n");
break;
case ERR_ARRAY_STRIPE_SIZE:
break;
case ERR_ARRAY_CACHE_POLICY:
"Illegal cache-write policy.\n");
break;
case ERR_ARRAY_IN_USE:
break;
case ERR_ARRAY_TASK:
break;
case ERR_ARRAY_CONFIG:
"Configuration over device node failed.\n");
break;
case ERR_ARRAY_DISKNUM:
break;
case ERR_ARRAY_LAYOUT:
break;
case ERR_ARRAY_AMOUNT:
break;
case ERR_DISK_STATE:
"Incorrect disk status for current operation.\n");
break;
case ERR_DISK_SPACE:
break;
case ERR_DISK_SEG_AMOUNT:
break;
case ERR_DISK_NOT_EMPTY:
break;
case ERR_DISK_TASK:
break;
case ERR_TASK_STATE:
"Incorrect task state for current operation.\n");
break;
case ERR_OP_ILLEGAL:
break;
case ERR_OP_NO_IMPL:
"Operation is not implemented.\n");
break;
case ERR_OP_FAILED:
break;
case ERR_DEVICE_NOENT:
break;
case ERR_DEVICE_TYPE:
break;
case ERR_DEVICE_DUP:
break;
case ERR_DEVICE_OVERFLOW:
break;
case ERR_DEVICE_UNCLEAN:
break;
case ERR_DEVICE_INVALID:
break;
case ERR_NOMEM:
"Can not allocate more memory space.\n");
break;
case ERR_PRIV:
break;
default:
}
(void) mutex_unlock(&raidcfg_mp);
return (ret_val);
}
int
{
int ret_val;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (obj_id);
}
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret_val);
}
int
{
int ret_val;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (obj_id);
}
break;
}
(void) mutex_unlock(&raidcfg_mp);
return (obj_id);
}
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret_val);
}
int
{
int ret_val;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (obj_id);
}
break;
}
(void) mutex_unlock(&raidcfg_mp);
return (obj_id);
}
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret_val);
}
int
{
int ret;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
(void) mutex_unlock(&raidcfg_mp);
return (SUCCESS);
}
int
{
int ret;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
(void) mutex_unlock(&raidcfg_mp);
return (SUCCESS);
}
int
raidcfg_get_type(int handle)
{
int ret_val;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret_val);
}
int
{
void *data;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_INVALID);
}
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(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:
{
(void **)(&ctlr_attr));
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
src->associated_id);
(void **)(&array_attr));
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
}
}
(void) mutex_unlock(&raidcfg_mp);
return (SUCCESS);
case OBJ_TYPE_DISK:
size = sizeof (disk_attr_t);
break;
case OBJ_TYPE_ARRAY_PART:
{
(void **)(&ctlr_attr));
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
(void) mutex_unlock(&raidcfg_mp);
return (SUCCESS);
}
(void **)(&disk_attr));
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
}
(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) mutex_unlock(&raidcfg_mp);
return (ret);
}
int
{
int ret_val;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (obj_id);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret_val);
}
int
{
int ret_val;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (obj_id);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret_val);
}
int
raidcfg_list_next(int handle)
{
int ret_val;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (obj_id);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret_val);
}
int
char **plugin_err_str)
{
int ret;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ERR_OP_NO_IMPL);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
int
{
int ret;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ERR_OP_NO_IMPL);
}
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
int
char **plugin_err_str)
{
int i, ret;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
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_handles + i));
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_TYPE);
}
}
/* Create an empty array object */
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (obj_id);
}
(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 */
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (array_handle);
}
int
{
int ret;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_TYPE);
}
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);
}
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
int
char **plugin_err_str)
{
int ret, i;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_OP_ILLEGAL);
}
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 (array_obj_id < OBJ_NONE) {
(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);
}
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_TYPE);
}
} else
hsp_relations[i].disk_handle);
if (disk_obj_id < OBJ_NONE) {
(void) mutex_unlock(&raidcfg_mp);
return (disk_obj_id);
}
if (disk_obj_id == OBJ_NONE) {
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_TYPE);
}
}
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
int
char **plugin_err_str)
{
int ret, i;
(void) mutex_lock(&raidcfg_mp);
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ERR_OP_ILLEGAL);
}
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 (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_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_TYPE);
}
} else
hsp_relations[i].disk_handle);
if (disk_obj_id < OBJ_NONE) {
(void) mutex_unlock(&raidcfg_mp);
return (disk_obj_id);
}
if (disk_obj_id == OBJ_NONE) {
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_NOENT);
}
(void) mutex_unlock(&raidcfg_mp);
return (ERR_DEVICE_TYPE);
}
}
(void) obj_rescan(&raid_tab_sys);
(void) mutex_unlock(&raidcfg_mp);
return (ret);
}
/*
* RaidCfg lib routines
*/
void
raidcfg_init(void)
{
(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);
(void) mutex_destroy(&raidcfg_mp);
}
/*
* Support routines
*/
static int
{
int i, j;
i = *((int *)p1);
j = *((int *)p2);
return (i - j);
}
static uint64_t
{
/* 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 **)(&disk_attr));
arraypart_attrs[i].offset = 0;
continue;
}
(&diskseg_attr));
arraypart_attrs[i].offset = 0;
OBJ_NONE) {
(void **)(&diskseg_attr));
arraypart_attrs[i].size) {
}
}
}
}
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;
}
++disk_num;
}
switch (raid_level) {
case RAID_LEVEL_0:
break;
case RAID_LEVEL_1:
break;
case RAID_LEVEL_1E:
break;
case RAID_LEVEL_5:
break;
case RAID_LEVEL_10:
break;
case RAID_LEVEL_50:
break;
default:
return (ERR_ARRAY_LEVEL);
break;
}
return (capacity);
}
static int
{
char *ap_id;
int count = 0;
return (ERR_NOMEM);
if (type == 0) {
} else
do {
count++;
return (ERR_ARRAY_CONFIG);
}
return (SUCCESS);
}
/*
* Raid handle maintenance routines
*/
static int
{
int i;
void *ptr;
return (ERR_NOMEM);
/* Clean up the new allocated handles */
i < raid_handle_sys.handle_num; ++i) {
}
/* For the first time of allocation, set up the system object handle */
raid_handle_sys.used = 0;
}
return (SUCCESS);
}
static void
{
i = raid_handle_sys.used;
/* Close all opened controllers */
while (i != 0) {
}
/* Clean up handle space */
raid_handle_sys.unused = 0;
raid_handle_sys.used = 0;
}
static raid_obj_handle_t
{
int ret;
ret = raid_handle_init();
return (ret);
}
return (ret);
}
static void
{
int i = raid_handle_sys.used, j = 0;
if (handle == 0)
return;
while (i != 0 && i != handle) {
j = i;
}
if (i == handle) {
if (j != 0)
else
raid_handle_sys.unused = i;
}
}
static void
{
int i = raid_handle_sys.used, j;
while (i != 0) {
j = i;
controller_id) &&
}
}
static raid_obj_id_t
{
if (handle == OBJ_SYSTEM)
return (OBJ_SYSTEM);
switch (handle_attr->type) {
case OBJ_TYPE_SYSTEM:
return (OBJ_SYSTEM);
case OBJ_TYPE_CONTROLLER:
break;
case OBJ_TYPE_ARRAY:
break;
case OBJ_TYPE_HSP:
break;
case OBJ_TYPE_DISK:
break;
case OBJ_TYPE_ARRAY_PART:
break;
case OBJ_TYPE_DISK_SEG:
break;
case OBJ_TYPE_TASK:
break;
default:
return (ERR_DEVICE_INVALID);
}
return (obj_id);
return (ERR_DEVICE_NOENT);
return (obj_id);
}
static raid_obj_handle_t
{
if (obj_id == OBJ_SYSTEM)
return (OBJ_SYSTEM);
/* If the object mapped by a handle */
if (handle != 0)
return (handle);
/* Search for existing handles */
break;
if (handle != 0)
return (handle);
/* Allocate new handle for this object */
switch (type) {
case OBJ_TYPE_SYSTEM:
break;
case OBJ_TYPE_CONTROLLER:
break;
case OBJ_TYPE_ARRAY:
break;
case OBJ_TYPE_HSP:
break;
case OBJ_TYPE_DISK:
break;
case OBJ_TYPE_ARRAY_PART:
break;
case OBJ_TYPE_DISK_SEG:
break;
case OBJ_TYPE_TASK:
break;
default:
return (ERR_DEVICE_INVALID);
}
return (handle);
}
static raid_lib_t *
{
return (NULL);
if (handle == 0)
return (NULL);
}
static int
{
return (ERR_DEVICE_TYPE);
if (handle == 0)
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
static int
{
return (ERR_DEVICE_TYPE);
if (handle == 0)
return (ERR_DEVICE_NOENT);
}
static int
{
return (ERR_DEVICE_TYPE);
if (handle == 0)
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
/*
* Raid object maintenance routines
*/
static int
{
return (status);
if (status & OBJ_STATUS_SCANCOMP)
return (SUCCESS);
return (ERR_DEVICE_INVALID);
++obj_type_cnt) {
else
comp_num = 0;
return (comp_num);
if (comp_num == 0)
continue;
return (ERR_NOMEM);
for (i = 0; i < comp_num; ++i) {
return (ret);
}
(void) raid_obj_clear_status(raid_tab,
*(comp_list + i), OBJ_STATUS_CMD_CLEAN);
obj_id);
}
}
return (SUCCESS);
}
static int
{
int ret;
return (ERR_NOMEM);
return (ret);
}
return (SUCCESS);
}
static raid_obj_id_t
{
int ret;
return (ERR_DEVICE_TYPE);
return (status);
if (!(status & OBJ_STATUS_SCANCOMP)) {
return (ret);
}
return (id);
if (type < OBJ_TYPE_SYSTEM)
return (type);
return (id);
return (id);
if (type < OBJ_TYPE_SYSTEM)
return (type);
break;
};
return (id);
}
static raid_obj_id_t
{
if (obj_type < OBJ_TYPE_SYSTEM)
return (obj_type);
do {
return (id);
if (type < OBJ_TYPE_SYSTEM)
return (type);
return (id);
}
static int
{
void *attr;
return (status);
if (type < OBJ_TYPE_SYSTEM)
return (type);
if (!(status & OBJ_STATUS_OPENED)) {
else
}
return (ret);
return (ERR_DEVICE_INVALID);
return (SUCCESS);
}
static raid_obj_id_t
{
return (obj_id);
do {
return (ERR_DEVICE_INVALID);
break;
return (obj_id);
}
static raid_obj_id_t
{
return (obj_id);
return (obj_id);
}
static raid_obj_id_t
{
return (obj_id);
do {
return (ERR_DEVICE_INVALID);
break;
return (ret);
return (obj_id);
}
static raid_obj_id_t
{
return (obj_id);
return (obj_id);
do {
break;
return (obj_id);
return (obj_id);
}
static raid_obj_id_t
{
return (obj_id);
return (obj_id);
do {
return (ERR_DEVICE_INVALID);
break;
return (obj_id);
}
static raid_obj_id_t
{
return (obj_id);
return (obj_id);
do {
return (ERR_DEVICE_INVALID);
break;
OBJ_NONE);
return (obj_id);
}
static raid_obj_id_t
{
return (obj_id);
return (obj_id);
do {
return (ERR_DEVICE_INVALID);
break;
return (obj_id);
}
static raid_obj_id_t
{
return (obj_id);
return (obj_id);
do {
if (task_obj_id < OBJ_NONE)
return (task_obj_id);
if (task_obj_id == OBJ_NONE) {
continue;
}
return (ERR_DEVICE_INVALID);
return (task_obj_id);
}
if (task_obj_id < OBJ_NONE)
return (task_obj_id);
if (task_obj_id == OBJ_NONE)
continue;
return (ERR_DEVICE_INVALID);
return (task_obj_id);
return (obj_id);
return (obj_id);
do {
if (task_obj_id < OBJ_NONE)
return (task_obj_id);
if (task_obj_id == OBJ_NONE)
continue;
return (ERR_DEVICE_INVALID);
return (task_obj_id);
return (obj_id);
}
static raid_obj_id_t
{
return (ERR_DEVICE_INVALID);
}
return (id);
}
/*
* Raid object operation routines
*/
static int
{
int num = 0;
return (ERR_DEVICE_TYPE);
if (comp_type != OBJ_TYPE_CONTROLLER)
return (0);
return (ERR_DRIVER_NOT_FOUND);
char path[MAX_PATH_LEN];
continue;
continue;
++ num;
}
return (num);
}
static int
{
char path[MAX_PATH_LEN];
int i = 0;
return (ERR_DEVICE_TYPE);
return (ERR_OP_ILLEGAL);
if (comp_type != OBJ_TYPE_CONTROLLER)
return (0);
return (ERR_DRIVER_NOT_FOUND);
return (ERR_NOMEM);
}
continue;
continue;
tmplist[i] = controller_id;
++ i;
}
}
for (i = 0; i < num; i++) {
*(comp_list + i));
return (ERR_DEVICE_INVALID);
}
}
return (SUCCESS);
}
static int
{
return (ERR_DEVICE_TYPE);
return (0);
return (ERR_DRIVER_CLOSED);
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
return (0);
return (ERR_OP_ILLEGAL);
for (i = 0; i < comp_num; ++i)
return (ERR_DEVICE_TYPE);
return (ERR_DRIVER_CLOSED);
return (ERR_NOMEM);
return (ret);
}
for (i = 0; i < comp_num; ++ i) {
void *attr_buf;
return (ERR_DEVICE_INVALID);
}
switch (comp_type) {
case OBJ_TYPE_ARRAY:
break;
case OBJ_TYPE_DISK:
break;
default:
return (ERR_DEVICE_INVALID);
}
}
return (SUCCESS);
}
static int
{
return (ERR_DEVICE_TYPE);
return (SUCCESS);
return (ERR_DEVICE_INVALID);
/*
* For a controller, even it's not opened, we can still
* get the driver name
*/
if (fd == 0)
return (SUCCESS);
return (SUCCESS);
}
return (ret);
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
switch (sub_cmd) {
case ACT_CONTROLLER_OPEN:
/* Check if already opened */
if (fd > 0)
return (SUCCESS);
/* Check if plugin is already attached */
return (ERR_DRIVER_NOT_FOUND);
}
}
break;
case ACT_CONTROLLER_CLOSE:
if (fd <= 0)
return (SUCCESS);
return (SUCCESS);
}
}
break;
case ACT_CONTROLLER_FLASH_FW:
{
char *filebuf;
int image_fd;
return (ERR_OP_ILLEGAL);
/* Open firmware image file */
if (image_fd == -1)
return (ERR_OP_FAILED);
return (ERR_OP_FAILED);
}
return (ERR_NOMEM);
}
return (ERR_OP_FAILED);
}
if (fd <= 0) {
return (ERR_DRIVER_CLOSED);
}
return (ERR_DRIVER_CLOSED);
}
return (ERR_OP_NO_IMPL);
}
}
break;
default:
return (ERR_OP_ILLEGAL);
}
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
if (comp_type != OBJ_TYPE_ARRAY_PART &&
comp_type != OBJ_TYPE_ARRAY &&
return (0);
return (ERR_DEVICE_INVALID);
if (controller_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
}
return (ERR_DRIVER_CLOSED);
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
if (comp_type != OBJ_TYPE_ARRAY_PART &&
comp_type != OBJ_TYPE_ARRAY &&
return (0);
return (ERR_OP_ILLEGAL);
for (i = 0; i < comp_num; ++i)
return (ERR_DEVICE_TYPE);
return (ERR_DEVICE_INVALID);
if (controller_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
}
return (ERR_DRIVER_CLOSED);
return (ERR_NOMEM);
return (ret);
}
for (i = 0; i < comp_num; ++ i) {
void *attr_buf;
return (ERR_DEVICE_INVALID);
}
switch (comp_type) {
case OBJ_TYPE_ARRAY:
break;
case OBJ_TYPE_ARRAY_PART:
break;
case OBJ_TYPE_TASK:
break;
default:
return (ERR_DEVICE_INVALID);
}
}
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
return (SUCCESS);
return (ERR_DEVICE_INVALID);
if (controller_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
}
return (ERR_DRIVER_CLOSED);
return (ret);
return (ret);
}
static int
{
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);
}
if (controller_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
}
return (ERR_DRIVER_CLOSED);
return (ERR_OP_NO_IMPL);
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
if (comp_type != OBJ_TYPE_DISK_SEG &&
comp_type != OBJ_TYPE_HSP &&
return (0);
return (ERR_DEVICE_INVALID);
}
return (SUCCESS);
}
if (controller_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
}
return (ERR_DRIVER_CLOSED);
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
if (comp_type != OBJ_TYPE_DISK_SEG &&
comp_type != OBJ_TYPE_HSP &&
return (0);
return (ERR_OP_ILLEGAL);
for (i = 0; i < comp_num; ++i)
return (ERR_DEVICE_TYPE);
return (ERR_DEVICE_INVALID);
}
return (SUCCESS);
}
if (controller_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
}
return (ERR_DRIVER_CLOSED);
return (ERR_NOMEM);
return (ret);
}
for (i = 0; i < comp_num; ++ i) {
void *attr_buf;
return (ERR_DEVICE_INVALID);
}
switch (comp_type) {
case OBJ_TYPE_DISK_SEG:
break;
case OBJ_TYPE_HSP:
break;
case OBJ_TYPE_TASK:
break;
default:
return (ERR_DEVICE_INVALID);
}
}
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
return (SUCCESS);
return (ERR_DEVICE_INVALID);
if (controller_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
}
return (ERR_DRIVER_CLOSED);
return (ret);
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
return (SUCCESS);
return (ERR_DEVICE_INVALID);
else
return (SUCCESS);
}
static int
{
return (ERR_DEVICE_TYPE);
return (SUCCESS);
return (ERR_DEVICE_INVALID);
if (array_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
if (array_attr == NULL)
return (ERR_DEVICE_INVALID);
if (controller_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
}
return (ERR_DRIVER_CLOSED);
return (ret);
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
return (SUCCESS);
return (ERR_DEVICE_INVALID);
if (disk_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
if (controller_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
}
return (ERR_DRIVER_CLOSED);
return (ret);
return (ret);
}
static int
{
return (ERR_DEVICE_TYPE);
return (ERR_DEVICE_INVALID);
if (controller_obj_id < OBJ_NONE)
return (ERR_DEVICE_INVALID);
return (ERR_DEVICE_INVALID);
}
return (ERR_DRIVER_CLOSED);
return (ret);
}
static int
{
if (array_attr == NULL)
return (ERR_DEVICE_INVALID);
/* Check the disk layout expression */
if (disk_list[0] != OBJ_SEPARATOR_BEGIN ||
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)
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:
return (ERR_ARRAY_LAYOUT);
break;
case RAID_LEVEL_1:
return (ERR_ARRAY_LAYOUT);
break;
case RAID_LEVEL_1E:
case RAID_LEVEL_5:
return (ERR_ARRAY_LAYOUT);
break;
case RAID_LEVEL_10:
return (ERR_ARRAY_LAYOUT);
break;
case RAID_LEVEL_50:
return (ERR_ARRAY_LAYOUT);
break;
default:
return (ERR_ARRAY_LEVEL);
}
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 =
continue;
}
if (*(disk_list + i) == OBJ_SEPARATOR_END) {
arraypart_attrs[i].disk_id =
continue;
}
disk_cnt++;
/* Check if it's a disk */
return (ERR_DEVICE_TYPE);
/* Check if it's duplicated with other disks */
for (j = 0; j < i; ++j)
return (ERR_DEVICE_DUP);
}
/* Check disk status */
(void **)(&disk_attr));
return (ret);
return (ERR_DISK_STATE);
}
/* All disks must belong to the same controller */
return (obj_id);
if (controller_obj_id == OBJ_NONE) {
(void **)(&controller_attr));
} else if (obj_id != controller_obj_id) {
return (ERR_DRIVER_ACROSS);
}
/* Check if the disk contains too many segments */
j = 0;
++j;
}
if (j > controller_attr->max_seg_per_disk) {
return (ERR_DISK_SEG_AMOUNT);
}
/* Check if controller is a hostraid controller */
/*
* For hostraid, the first disk should
* be with of minimum capacity
*/
if (min_disk_capacity == 0) {
/* Can not specify capacity for hostraid */
if (array_attr->capacity != 0) {
return (ERR_OP_ILLEGAL);
}
return (ERR_DISK_SPACE);
}
/* Disk should not be used for hostraid */
return (obj_id);
return (ERR_DISK_NOT_EMPTY);
}
}
}
/* Check if array amount exceeds limit */
if (controller_attr->max_array_num <=
return (ERR_ARRAY_AMOUNT);
return (ERR_DRIVER_CLOSED);
/* Check if the controller can support the array RAID level */
switch (array_attr->raid_level) {
case RAID_LEVEL_0:
return (ERR_ARRAY_LEVEL);
}
break;
case RAID_LEVEL_1:
return (ERR_ARRAY_LEVEL);
}
break;
case RAID_LEVEL_1E:
return (ERR_ARRAY_LEVEL);
}
break;
case RAID_LEVEL_5:
return (ERR_ARRAY_LEVEL);
}
break;
case RAID_LEVEL_10:
return (ERR_ARRAY_LEVEL);
}
break;
case RAID_LEVEL_50:
return (ERR_ARRAY_LEVEL);
}
break;
default:
return (ERR_ARRAY_LEVEL);
}
/* Check if plug in can calculate the maximum size */
if (ret == ERR_OP_NO_IMPL) {
/* Calculate the maximum capacity */
/*
* If controller is capable to allocate space,
* set offset and size attributes to OBJ_ATTR_NONE
* and let the controller to determine these value
*/
for (i = 0; i < num_of_comp; ++i) {
arraypart_attrs[i].offset =
arraypart_attrs[i].size =
}
/* There's no enough space for specified capacity */
return (ERR_ARRAY_SIZE);
}
/* capacity == 0, allocate maximum space */
if (array_attr->capacity == 0)
return (ret);
/* Return the maximum size */
return (ERR_ARRAY_SIZE);
}
return (ERR_ARRAY_SIZE);
}
return (ret);
/* Add array object into device tree so that we can map the handle */
/* unconfig disk minor nodes if it's hostraid */
sizeof (uint32_t));
if (diskid_list == NULL) {
return (ERR_NOMEM);
}
sizeof (disk_tag_t));
return (ERR_NOMEM);
}
for (i = 0; i < num_of_comp; ++i) {
if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
} else if (*(disk_list + i) == OBJ_SEPARATOR_END) {
} else {
(void **)(&disk_attr));
return (ret);
}
}
}
for (i = 0; i < num_of_comp; ++i) {
continue;
}
continue;
return (ret);
}
}
} else {
/* for HW raid */
}
return (ret);
}
static int
char **plugin_err_str)
{
if (controller_obj_id <= OBJ_NONE)
return (controller_obj_id);
(void **)(&controller_attr));
return (ret);
}
return (ret);
return (ERR_DRIVER_CLOSED);
/* change minor nodes state for disks */
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.
*/
arraypart_obj_id)) {
if (arraypart_obj_id < OBJ_NONE)
return (arraypart_obj_id);
++i;
}
return (ERR_NOMEM);
/* Stor all member disk ids into disk_ids */
while (arraypart_obj_id > OBJ_NONE) {
(void **)(&arraypart_attr));
return (ret);
}
(void **)(&disk_attr));
return (ret);
}
continue;
}
++j;
}
} else {
return (ret);
}
if (disk_ids)
return (ret);
}
for (i = 0; i < j; ++i)
disk_ids[i], 0);
if (ret == ERR_ARRAY_CONFIG)
return (ret);
}
}
if (disk_ids)
return (ret);
}
static int
char **plugin_err_str)
{
if (hsp_relation == NULL)
return (ERR_NOMEM);
for (i = 0; i < num; ++i) {
(array_obj_id != OBJ_ATTR_NONE &&
OBJ_TYPE_ARRAY)) {
return (ERR_DEVICE_TYPE);
}
/* Get controller attributes */
if (controller_obj_id == OBJ_NONE)
disk_obj_id)) {
return (ERR_DRIVER_ACROSS);
}
(void **)(&controller_attr));
/* Get disk attributes */
(void **)(&disk_attr));
return (ERR_DISK_STATE);
}
/* If it's not a hsp disk, check if there's occupied space */
OBJ_NONE) {
(void **)(&diskseg_attr));
if (!(diskseg_attr->state &
return (ERR_DISK_NOT_EMPTY);
}
}
}
if (array_obj_id != OBJ_ATTR_NONE) {
/* If local hsp is supported */
return (ERR_OP_ILLEGAL);
}
return (ERR_DEVICE_TYPE);
}
/* Get array attributes */
(void **)(&array_attr));
/* RAID 0 array can not use hsp */
return (ERR_ARRAY_LEVEL);
}
/* If It's belong to another controller */
array_obj_id)) {
return (ERR_DRIVER_ACROSS);
}
/* Get an array part attributes */
else
(void **)(&arraypart_attr));
/* Check if disk space is enough for array */
return (ERR_DISK_SPACE);
}
if ((arraypart_attr->size +
arraypart_attr->offset) >
return (ERR_DISK_SPACE);
}
/* if global hsp is supported */
return (ERR_OP_ILLEGAL);
}
/*
* If the array is already associated with the
* local hsp, or it's a global hsp, ignore it
*/
(array_obj_id != OBJ_ATTR_NONE)) ||
(array_obj_id == OBJ_ATTR_NONE))) {
return (ERR_OP_ILLEGAL);
}
}
}
if (array_obj_id != OBJ_ATTR_NONE)
else
++ j;
}
if (j == 0)
return (SUCCESS);
return (ERR_DRIVER_CLOSED);
return (ERR_OP_NO_IMPL);
}
j, hsp_relation, plugin_err_str);
return (ret);
}
static int
char **plugin_err_str)
{
if (hsp_relation == NULL)
return (ERR_NOMEM);
for (i = 0; i < num; ++i) {
return (ERR_DEVICE_TYPE);
}
/* Get controller attributes */
if (controller_obj_id == OBJ_NONE)
disk_obj_id)) {
return (ERR_DRIVER_ACROSS);
}
(void **)(&controller_attr));
/* Get disk attributes */
(void **)(&disk_attr));
return (ERR_DISK_STATE);
}
/* If it's not a hsp disk */
return (ERR_DISK_STATE);
}
if (array_obj_id != OBJ_ATTR_NONE) {
return (ERR_DEVICE_TYPE);
}
/* Get array attributes */
(void **)(&array_attr));
/* If It's belong to another controller */
array_obj_id)) {
return (ERR_DRIVER_ACROSS);
}
/* If want to remove an array from a global hsp */
return (ERR_OP_ILLEGAL);
}
do {
(void **)(&hsp_attr));
if (hsp_attr->associated_id ==
array_attr->array_id ||
break;
/* if global hsp is supported */
return (ERR_OP_ILLEGAL);
}
/*
* If array is associated with a local hsp, or remove a
* global hsp disk
*/
(array_obj_id == OBJ_ATTR_NONE)) {
if (array_obj_id != OBJ_ATTR_NONE)
else
hsp_relation[j].array_id =
++ j;
} else {
return (ERR_OP_ILLEGAL);
}
}
return (ERR_DRIVER_CLOSED);
return (ERR_OP_NO_IMPL);
}
j, hsp_relation, plugin_err_str);
return (ret);
}
/*
* Object maintennance routines
*/
static int
{
int ret;
return (ERR_NOMEM);
if (ret == ERR_DEVICE_DUP) {
return (ERR_DEVICE_UNCLEAN);
}
return (SUCCESS);
}
static raid_obj_id_t
{
++ raid_tab->obj_id_cnt;
if (raid_tab->obj_id_cnt <= 0)
return (ERR_DEVICE_OVERFLOW);
return (raid_tab->obj_id_cnt);
}
static void *
{
switch (obj_type) {
case OBJ_TYPE_CONTROLLER:
break;
case OBJ_TYPE_ARRAY:
break;
case OBJ_TYPE_DISK:
break;
case OBJ_TYPE_HSP:
break;
case OBJ_TYPE_ARRAY_PART:
break;
case OBJ_TYPE_DISK_SEG:
break;
case OBJ_TYPE_TASK:
break;
default:
break;
}
return (obj_attr);
}
static raid_obj_id_t
{
int ret;
void *data_ptr;
return (ERR_NOMEM);
return (ERR_DEVICE_OVERFLOW);
if (ret == ERR_DEVICE_DUP) {
return (ERR_DEVICE_DUP);
}
return (ERR_NOMEM);
}
}
static int
{
return (SUCCESS);
}
return (ERR_DEVICE_NOENT);
}
static int
{
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
static raid_obj_type_id_t
{
return (ERR_DEVICE_NOENT);
return (ERR_DEVICE_INVALID);
return (obj->obj_type_id);
}
static int
{
return (ERR_DEVICE_NOENT);
return (ERR_DEVICE_TYPE);
return (SUCCESS);
}
static raid_obj_status_t
{
return (ERR_DEVICE_NOENT);
}
static int
{
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
static int
{
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
static raid_obj_id_t
{
return (ERR_DEVICE_NOENT);
}
static int
{
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
static raid_obj_id_t
{
return (ERR_DEVICE_NOENT);
}
static int
{
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
static raid_obj_id_t
{
return (ERR_DEVICE_NOENT);
}
static int
{
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
static void *
{
return (NULL);
}
static int
void *data)
{
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
static raid_obj_handle_t
{
return (ERR_DEVICE_NOENT);
}
static int
{
return (ERR_DEVICE_NOENT);
return (SUCCESS);
}
/*
* Object list maintennance routines
*/
static void
{
}
static void *
{
}
static void *
{
}
static void
{
}
}
static void
{
}
}
}
static void *
{
return (obj);
}
static void *
{
break;
return (obj);
}
static int
{
unsigned i;
if (hash_slots == 0)
return (ERR_OP_ILLEGAL);
return (ERR_NOMEM);
for (i = 0; i < hash_slots; i++)
return (SUCCESS);
}
static void
{
unsigned i;
struct raid_obj_t *obj;
}
tab->obj_id_cnt = 0;
}
static int
{
return (ERR_DEVICE_DUP);
return (SUCCESS);
}
static void *
{
return (obj);
}
static void *
{
return (obj);
}
static void
{
}
/*
* Plug-in maintennance routines
*/
static int
{
return (ERR_DRIVER_NOT_FOUND);
if (buf1[0] != '/')
else
buf[0] = 0;
return (ERR_DRIVER_NOT_FOUND);
else
*colon = 0;
return (ERR_DRIVER_NOT_FOUND);
return (SUCCESS);
}
static char *
{
char buf[MAX_PATH_LEN];
int ret;
return (NULL);
*tmp = 0;
return (NULL);
if (di_node == DI_NODE_NIL)
return (NULL);
return (name);
}
static void
{
while (raid_lib) {
}
}
static raid_lib_t *
raid_plugin_load(char *driver_name)
{
char buf[MAX_PATH_LEN] = {0};
void *sym;
return (NULL);
return (NULL);
}
else {
return (NULL);
}
}
NULL) {
return (NULL);
} else
NULL) {
return (NULL);
} else
return (NULL);
} else
return (NULL);
} else
return (NULL);
} else
raid_obj_type_id_t, void*))sym;
return (NULL);
} else
arraypart_attr_t *, char **))sym;
return (NULL);
} else
return (supplib);
}
static raid_lib_t *
{
char *driver_name;
/* Check if it's mapped to handle structure */
(void **)(&controller_attr));
/* Check if the plugin module is already loaded */
if (driver_name == NULL)
return (NULL);
return (raid_lib);
}
/* Loading the plugin module */
return (raid_lib);
}