275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock/*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * CDDL HEADER START
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * The contents of this file are subject to the terms of the
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Common Development and Distribution License (the "License").
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * You may not use this file except in compliance with the License.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * or http://www.opensolaris.org/os/licensing.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * See the License for the specific language governing permissions
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * and limitations under the License.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * When distributing Covered Code, include this CDDL HEADER in each
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * If applicable, add the following below this CDDL HEADER, with the
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * fields enclosed by brackets "[]" replaced with your own identifying
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * information: Portions Copyright [yyyy] [name of copyright owner]
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * CDDL HEADER END
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock/*
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
a8be79fa54c16403e012b2993a3edbe079777feeAlexander Stetsenko/*
a8be79fa54c16403e012b2993a3edbe079777feeAlexander Stetsenko * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
a8be79fa54c16403e012b2993a3edbe079777feeAlexander Stetsenko */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock#include <scsi/libses.h>
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock#include "ses_impl.h"
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockstatic boolean_t ses_plugin_dlclose;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock/*ARGSUSED*/
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockvoid *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_ctlpage_lookup(ses_plugin_t *sp, ses_snap_t *snap, int pagenum,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock size_t len, ses_node_t *np, boolean_t unique)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_target_t *tp = snap->ss_target;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_snap_page_t *pp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_pagedesc_t *dp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((pp = ses_snap_ctl_page(snap, pagenum, len, unique)) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (NULL);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((dp = ses_get_pagedesc(tp, pagenum, SES_PAGE_CTL)) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (NULL);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
a8be79fa54c16403e012b2993a3edbe079777feeAlexander Stetsenko if (np != NULL && dp->spd_ctl_fill != NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (dp->spd_ctl_fill(sp, pp->ssp_page,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pp->ssp_len, np));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock } else {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (pp->ssp_page);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockint
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_fill_node(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_target_t *tp = np->sn_snapshot->ss_target;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_t *sp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (sp = tp->st_plugin_first; sp != NULL; sp = sp->sp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (sp->sp_node_parse == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock continue;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (sp->sp_node_parse(sp, np) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockint
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_ctl(ses_node_t *np, const char *op, nvlist_t *arg)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_target_t *tp = np->sn_snapshot->ss_target;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_t *sp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock nvlist_t *nvl;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock nvpair_t *nvp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock int ret;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (nvlist_dup(arg, &nvl, 0) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (ses_set_errno(ESES_NOMEM));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock /*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Technically we could get away with a per-snapshot lock while we fill
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * the control page contents, but this doesn't take much time and we
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * want actual control operations to be protected per-target, so we just
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * take the target lock.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) pthread_mutex_lock(&tp->st_lock);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock /*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * We walk the list of plugins backwards, so that a product-specific
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * plugin can rewrite the nvlist to control operations in terms of the
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * standard mechanisms, if desired.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (sp = tp->st_plugin_first; sp != NULL; sp = sp->sp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (sp->sp_node_ctl == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock continue;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (sp->sp_node_ctl(sp, np, op, nvl) != 0) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock nvlist_free(nvl);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) pthread_mutex_unlock(&tp->st_lock);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((nvp = nvlist_next_nvpair(nvl, NULL)) != NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) ses_error(ESES_NOTSUP, "property '%s' invalid for "
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "this node", nvpair_name(nvp));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock nvlist_free(nvl);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) pthread_mutex_unlock(&tp->st_lock);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock nvlist_free(nvl);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ret = ses_snap_do_ctl(np->sn_snapshot);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) pthread_mutex_unlock(&tp->st_lock);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (ret);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock/*ARGSUSED*/
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockvoid *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_page_lookup(ses_plugin_t *sp, ses_snap_t *snap, int pagenum,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_node_t *np, size_t *lenp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_snap_page_t *pp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_target_t *tp = sp->sp_target;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_pagedesc_t *dp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((dp = ses_get_pagedesc(tp, pagenum, SES_PAGE_DIAG)) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (NULL);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((pp = ses_snap_find_page(snap, pagenum, B_FALSE)) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (NULL);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
a8be79fa54c16403e012b2993a3edbe079777feeAlexander Stetsenko if (np != NULL && dp->spd_index != NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (dp->spd_index(sp, np, pp->ssp_page, pp->ssp_len,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock lenp));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock } else {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *lenp = pp->ssp_len;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (pp->ssp_page);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_pagedesc_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_get_pagedesc(ses_target_t *tp, int pagenum, ses_pagetype_t type)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_t *sp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_pagedesc_t *dp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (sp = tp->st_plugin_first; sp != NULL; sp = sp->sp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (sp->sp_pages == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock continue;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (dp = &sp->sp_pages[0]; dp->spd_pagenum != -1;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock dp++) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((type == SES_PAGE_CTL && dp->spd_ctl_len == NULL) ||
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (type == SES_PAGE_DIAG && dp->spd_ctl_len != NULL))
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock continue;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (dp->spd_pagenum == pagenum)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (dp);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) ses_error(ESES_BAD_PAGE, "failed to find page 0x%x", pagenum);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (NULL);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockint
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_register(ses_plugin_t *sp, int version, ses_plugin_config_t *scp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (version != LIBSES_PLUGIN_VERSION)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (ses_set_errno(ESES_VERSION));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_pages = scp->spc_pages;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_node_parse = scp->spc_node_parse;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_node_ctl = scp->spc_node_ctl;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockvoid
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_setspecific(ses_plugin_t *sp, void *data)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_data = data;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockvoid *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_getspecific(ses_plugin_t *sp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (sp->sp_data);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockstatic void
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_cleanstr(char *s)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock while (*s != '\0') {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (*s == ' ' || *s == '/')
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *s = '-';
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock s++;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockstatic void
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_destroy(ses_plugin_t *sp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (sp->sp_initialized && sp->sp_fini != NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_fini(sp);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
c5904d138f3bdf0762dbf452a43d5a5c387ea6a8eschrock if (ses_plugin_dlclose)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) dlclose(sp->sp_object);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_free(sp);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockstatic int
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_loadone(ses_target_t *tp, const char *path, uint32_t pass)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_t *sp, **loc;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock void *obj;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock int (*ses_priority)(void);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((obj = dlopen(path, RTLD_PARENT | RTLD_LOCAL | RTLD_LAZY)) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((sp = ses_zalloc(sizeof (ses_plugin_t))) == NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) dlclose(obj);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_object = obj;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_init = (int (*)())dlsym(obj, "_ses_init");
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_fini = (void (*)())dlsym(obj, "_ses_fini");
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_target = tp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (sp->sp_init == NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_destroy(sp);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock /*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Framework modules can establish an explicit prioritying by declaring
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * the '_ses_priority' symbol, which returns an integer used to create
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * an explicit ordering between plugins.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((ses_priority = (int (*)())dlsym(obj, "_ses_priority")) != NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_priority = ses_priority();
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_priority |= (uint64_t)pass << 32;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (loc = &tp->st_plugin_first; *loc != NULL; loc = &(*loc)->sp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((*loc)->sp_priority > sp->sp_priority)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock break;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (*loc != NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (*loc)->sp_prev = sp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock else
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock tp->st_plugin_last = sp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_next = *loc;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *loc = sp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (sp->sp_init(sp) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->sp_initialized = B_TRUE;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockstatic int
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_load_dir(ses_target_t *tp, const char *pluginroot)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock char path[PATH_MAX];
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock DIR *dirp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock struct dirent64 *dp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock char *vendor, *product, *revision;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock char isa[257];
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) snprintf(path, sizeof (path), "%s/%s",
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pluginroot, LIBSES_PLUGIN_FRAMEWORK);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock#if defined(_LP64)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (sysinfo(SI_ARCHITECTURE_64, isa, sizeof (isa)) < 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock isa[0] = '\0';
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock#else
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock isa[0] = '\0';
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock#endif
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((dirp = opendir(path)) != NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock while ((dp = readdir64(dirp)) != NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (strcmp(dp->d_name, ".") == 0 ||
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock strcmp(dp->d_name, "..") == 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock continue;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) snprintf(path, sizeof (path), "%s/%s/%s/%s",
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pluginroot, LIBSES_PLUGIN_FRAMEWORK,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock isa, dp->d_name);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (ses_plugin_loadone(tp, path, 0) != 0) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) closedir(dirp);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) closedir(dirp);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock /*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Create a local copy of the vendor/product/revision, strip out any
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * questionable characters, and then attempt to load each plugin.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
23a1ccea6aac035f084a7a4cdc968687d1b02dafRoger A. Faulkner vendor = strdupa(libscsi_vendor(tp->st_target));
23a1ccea6aac035f084a7a4cdc968687d1b02dafRoger A. Faulkner product = strdupa(libscsi_product(tp->st_target));
23a1ccea6aac035f084a7a4cdc968687d1b02dafRoger A. Faulkner revision = strdupa(libscsi_revision(tp->st_target));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_cleanstr(vendor);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_cleanstr(product);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_cleanstr(revision);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) snprintf(path, sizeof (path), "%s/%s/%s/%s%s", pluginroot,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock LIBSES_PLUGIN_VENDOR, isa, vendor,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock LIBSES_PLUGIN_EXT);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (ses_plugin_loadone(tp, path, 1) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) snprintf(path, sizeof (path), "%s/%s/%s/%s-%s%s", pluginroot,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock LIBSES_PLUGIN_VENDOR, isa, vendor, product,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock LIBSES_PLUGIN_EXT);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (ses_plugin_loadone(tp, path, 2) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) snprintf(path, sizeof (path), "%s/%s/%s/%s-%s-%s%s", pluginroot,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock LIBSES_PLUGIN_VENDOR, isa, vendor, product,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock revision, LIBSES_PLUGIN_EXT);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (ses_plugin_loadone(tp, path, 3) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockint
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_load(ses_target_t *tp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock char pluginroot[PATH_MAX];
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock const char *pluginpath, *p, *q;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((pluginpath = getenv("SES_PLUGINPATH")) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pluginpath = LIBSES_DEFAULT_PLUGINDIR;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_dlclose = (getenv("SES_NODLCLOSE") == NULL);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim for (p = pluginpath; p != NULL; p = q) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if ((q = strchr(p, ':')) != NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ptrdiff_t len = q - p;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) strncpy(pluginroot, p, len);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pluginroot[len] = '\0';
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock while (*q == ':')
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ++q;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (*q == '\0')
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock q = NULL;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (len == 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock continue;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock } else {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) strcpy(pluginroot, p);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (pluginroot[0] != '/')
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock continue;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (ses_plugin_load_dir(tp, pluginroot) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (tp->st_plugin_first == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (ses_error(ESES_PLUGIN, "no plugins found"));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockvoid
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_plugin_unload(ses_target_t *tp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_t *sp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock while ((sp = tp->st_plugin_first) != NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock tp->st_plugin_first = sp->sp_next;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_plugin_destroy(sp);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}