Example #1
0
int
topo_fmri_serial(topo_hdl_t *thp, nvlist_t *nvl, char **serial, int *err)
{
	nvlist_t *prop = NULL;
	char *sp;

	/*
	 * If there is a serial id in the resource fmri, then use that.
	 * Otherwise fall back to looking for a serial id property in the
	 * protocol group.
	 */
	if (nvlist_lookup_string(nvl, FM_FMRI_HC_SERIAL_ID, &sp) == 0) {
		if ((*serial = topo_hdl_strdup(thp, sp)) == NULL)
			return (set_error(thp, ETOPO_PROP_NOMEM, err,
			    "topo_fmri_serial", prop));
		else
			return (0);
	}

	if (fmri_prop(thp, nvl, TOPO_PGROUP_PROTOCOL, FM_FMRI_HC_SERIAL_ID,
	    NULL, &prop, err) < 0)
		return (set_error(thp, *err, err, "topo_fmri_serial", NULL));

	if (nvlist_lookup_string(prop, TOPO_PROP_VAL_VAL, &sp) != 0)
		return (set_error(thp, ETOPO_PROP_NVL, err, "topo_fmri_serial",
		    prop));

	if ((*serial = topo_hdl_strdup(thp, sp)) == NULL)
		return (set_error(thp, ETOPO_PROP_NOMEM, err,
		    "topo_fmri_serial", prop));

	nvlist_free(prop);

	return (0);
}
Example #2
0
/*
 * Fetch the Facility Node properties (name, type) from the FMRI
 * for this node, or return -1 if we can't.
 */
static int
get_facility_props(topo_hdl_t *hdl, tnode_t *node, char **facname,
    char **factype)
{
	int e, ret = -1;
	nvlist_t *fmri = NULL, *fnvl;
	char *nn = NULL, *tt = NULL;

	if (topo_node_resource(node, &fmri, &e) != 0)
		goto out;

	if (nvlist_lookup_nvlist(fmri, FM_FMRI_FACILITY, &fnvl) != 0)
		goto out;

	if (nvlist_lookup_string(fnvl, FM_FMRI_FACILITY_NAME, &nn) != 0)
		goto out;

	if (nvlist_lookup_string(fnvl, FM_FMRI_FACILITY_TYPE, &tt) != 0)
		goto out;

	*facname = topo_hdl_strdup(hdl, nn);
	*factype = topo_hdl_strdup(hdl, tt);
	ret = 0;

out:
	nvlist_free(fmri);
	return (ret);
}
Example #3
0
int
topo_fmri_nvl2str(topo_hdl_t *thp, nvlist_t *fmri, char **fmristr, int *err)
{
	char *scheme, *str;
	nvlist_t *out = NULL;
	tnode_t *rnode;

	if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
		return (set_error(thp, ETOPO_FMRI_MALFORM, err,
		    TOPO_METH_NVL2STR, out));

	if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
		return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
		    TOPO_METH_NVL2STR, out));

	if (topo_method_invoke(rnode, TOPO_METH_NVL2STR,
	    TOPO_METH_NVL2STR_VERSION, fmri, &out, err) != 0)
		return (set_error(thp, *err, err, TOPO_METH_NVL2STR, out));

	if (out == NULL || nvlist_lookup_string(out, "fmri-string", &str) != 0)
		return (set_error(thp, ETOPO_METHOD_INVAL, err,
		    TOPO_METH_NVL2STR, out));

	if ((*fmristr = topo_hdl_strdup(thp, str)) == NULL)
		return (set_error(thp, ETOPO_NOMEM, err,
		    TOPO_METH_NVL2STR, out));

	nvlist_free(out);

	return (0);
}
Example #4
0
int
prop_method_register(tnode_t *node, const char *pgname, const char *pname,
    topo_type_t ptype, const char *mname, topo_version_t version,
    const nvlist_t *args, int *err)
{
	topo_hdl_t *thp = node->tn_hdl;
	topo_propmethod_t *pm = NULL;
	topo_propval_t *pv = NULL;

	if ((pm = topo_hdl_zalloc(thp, sizeof (topo_propmethod_t))) == NULL)
		return (register_methoderror(node, pm, err, 1,
		    ETOPO_PROP_NOMEM));

	if ((pm->tpm_name = topo_hdl_strdup(thp, mname)) == NULL)
		return (register_methoderror(node, pm, err, 1,
		    ETOPO_PROP_NOMEM));

	pm->tpm_version = version;

	if (topo_hdl_nvdup(thp, (nvlist_t *)args, &pm->tpm_args) != 0)
		return (register_methoderror(node, pm, err, 1,
		    ETOPO_PROP_NOMEM));

	/*
	 * It's possible the property may already exist.  However we still want
	 * to allow the method to be registered.  This is to handle the case
	 * where we specify a prop method in an xml map to override the value
	 * that was set by the enumerator.
	 *
	 * By default, propmethod-backed properties are not MUTABLE.  This is
	 * done to simplify the programming model for modules that implement
	 * property methods as most propmethods tend to only support get
	 * operations.  Enumerator modules can override this by calling
	 * topo_prop_setmutable().  Propmethods that are registered via XML can
	 * be set as mutable via the optional "mutable" attribute, which will
	 * result in the xml parser calling topo_prop_setflags() after
	 * registering the propmethod.
	 */
	if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL)
		if ((pv = prop_create(node, pgname, pname, ptype,
		    TOPO_PROP_IMMUTABLE, err)) == NULL) {
			/* node unlocked */
			return (register_methoderror(node, pm, err, 0, *err));
		}

	if (pv->tp_method != NULL)
		return (register_methoderror(node, pm, err, 1,
		    ETOPO_METHOD_DEFD));

	if (pv->tp_val != NULL) {
		nvlist_free(pv->tp_val);
		pv->tp_val = NULL;
	}
	pv->tp_method = pm;

	topo_node_unlock(node);

	return (0);
}
Example #5
0
static topo_propval_t *
prop_create(tnode_t *node, const char *pgname, const char *pname,
    topo_type_t type, int flag, int *err)
{
	topo_hdl_t *thp = node->tn_hdl;
	topo_pgroup_t *pg;
	topo_propval_t *pv;
	topo_proplist_t *pvl;

	/*
	 * Replace existing prop value with new one
	 */
	if ((pg = pgroup_get(node, pgname)) == NULL) {
		topo_node_unlock(node);
		*err = ETOPO_PROP_NOENT;
		return (NULL);
	}

	if ((pv = propval_get(pg, pname)) != NULL) {
		if (pv->tp_type != type)
			return (set_seterror(node, NULL, err, ETOPO_PROP_TYPE));
		else if (! (pv->tp_flag & TOPO_PROP_MUTABLE))
			return (set_seterror(node, NULL, err, ETOPO_PROP_DEFD));

		nvlist_free(pv->tp_val);
		pv->tp_val = NULL;
	} else {
		if ((pvl = topo_hdl_zalloc(thp, sizeof (topo_proplist_t)))
		    == NULL)
			return (set_seterror(node, NULL, err, ETOPO_NOMEM));

		if ((pv = topo_hdl_zalloc(thp, sizeof (topo_propval_t)))
		    == NULL)
			return (set_seterror(node, pvl, err, ETOPO_NOMEM));

		pv->tp_hdl = thp;
		pvl->tp_pval = pv;

		if ((pv->tp_name = topo_hdl_strdup(thp, pname))
		    == NULL)
			return (set_seterror(node, pvl, err, ETOPO_NOMEM));
		pv->tp_flag = flag;
		pv->tp_type = type;
		topo_prop_hold(pv);
		topo_list_append(&pg->tpg_pvals, pvl);
	}

	return (pv);
}
Example #6
0
int
topo_pgroup_create(tnode_t *node, const topo_pgroup_info_t *pinfo, int *err)
{
	topo_pgroup_t *pg;
	topo_ipgroup_info_t *pip;
	topo_hdl_t *thp = node->tn_hdl;

	*err = 0;

	topo_node_lock(node);
	/*
	 * Check for an existing pgroup
	 */
	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
	    pg = topo_list_next(pg)) {
		if (strcmp(pg->tpg_info->tpi_name, pinfo->tpi_name) == 0) {
			*err = ETOPO_PROP_DEFD;
			topo_node_unlock(node);
			return (-1);
		}
	}

	if ((pg = topo_hdl_zalloc(thp, sizeof (topo_pgroup_t))) == NULL) {
		*err = ETOPO_NOMEM;
		topo_node_unlock(node);
		return (-1);
	}

	if ((pip = topo_hdl_zalloc(thp, sizeof (topo_ipgroup_info_t)))
	    == NULL)
		return (pgroup_seterr(node, pg, pip, err));

	if ((pip->tpi_name = topo_hdl_strdup(thp, pinfo->tpi_name))
	    == NULL)
		return (pgroup_seterr(node, pg, pip, err));

	pip->tpi_namestab = pinfo->tpi_namestab;
	pip->tpi_datastab = pinfo->tpi_datastab;
	pip->tpi_version = pinfo->tpi_version;

	pg->tpg_info = pip;

	topo_list_append(&node->tn_pgroups, pg);
	topo_node_unlock(node);

	return (0);
}
Example #7
0
int
topo_fmri_label(topo_hdl_t *thp, nvlist_t *nvl, char **label, int *err)
{
	nvlist_t *prop = NULL;
	char *lp;

	if (fmri_prop(thp, nvl, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL,
	    NULL, &prop, err) < 0)
		return (set_error(thp, *err, err, "topo_fmri_label", NULL));

	if (nvlist_lookup_string(prop, TOPO_PROP_VAL_VAL, &lp) != 0)
		return (set_error(thp, ETOPO_PROP_NVL, err, "topo_fmri_label",
		    prop));

	if ((*label = topo_hdl_strdup(thp, lp)) == NULL)
		return (set_error(thp, ETOPO_PROP_NOMEM, err, "topo_fmri_label",
		    prop));

	nvlist_free(prop);

	return (0);
}
Example #8
0
topo_pgroup_info_t *
topo_pgroup_info(tnode_t *node, const char *pgname, int *err)
{
	topo_hdl_t *thp = node->tn_hdl;
	topo_pgroup_t *pg;
	topo_ipgroup_info_t *pip;
	topo_pgroup_info_t *info;

	topo_node_lock(node);
	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
	    pg = topo_list_next(pg)) {
		if (strcmp(pgname, pg->tpg_info->tpi_name) == 0) {
			if ((info = topo_hdl_alloc(thp,
			    sizeof (topo_pgroup_info_t))) == NULL)
				return (NULL);

			pip = pg->tpg_info;
			if ((info->tpi_name =
			    topo_hdl_strdup(thp, pip->tpi_name)) == NULL) {
				*err = ETOPO_PROP_NOMEM;
				topo_hdl_free(thp, info,
				    sizeof (topo_pgroup_info_t));
				topo_node_unlock(node);
				return (NULL);
			}
			info->tpi_namestab = pip->tpi_namestab;
			info->tpi_datastab = pip->tpi_datastab;
			info->tpi_version = pip->tpi_version;
			topo_node_unlock(node);
			return (info);
		}
	}

	*err = ETOPO_PROP_NOENT;
	topo_node_unlock(node);
	return (NULL);
}
Example #9
0
static int
prop_getval(tnode_t *node, const char *pgname, const char *pname, void *val,
    topo_type_t type, uint_t *nelems, int *err)
{
	int i, j, ret = 0;
	topo_hdl_t *thp = node->tn_hdl;
	topo_propval_t *pv;

	topo_node_lock(node);
	if ((pv = prop_get(node, pgname, pname, NULL, err))
	    == NULL)
		return (get_properror(node, err, *err));

	if (pv->tp_type != type)
		return (get_properror(node, err, ETOPO_PROP_TYPE));

	switch (type) {
		case TOPO_TYPE_INT32:
			ret = nvlist_lookup_int32(pv->tp_val, TOPO_PROP_VAL_VAL,
			    (int32_t *)val);
			break;
		case TOPO_TYPE_UINT32:
			ret = nvlist_lookup_uint32(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (uint32_t *)val);
			break;
		case TOPO_TYPE_INT64:
			ret = nvlist_lookup_int64(pv->tp_val, TOPO_PROP_VAL_VAL,
			    (int64_t *)val);
			break;
		case TOPO_TYPE_UINT64:
			ret = nvlist_lookup_uint64(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (uint64_t *)val);
			break;
		case TOPO_TYPE_DOUBLE:
			ret = nvlist_lookup_double(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (double *)val);
			break;
		case TOPO_TYPE_STRING: {
			char *str;

			ret = nvlist_lookup_string(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &str);
			if (ret == 0) {
				char *s2;
				if ((s2 = topo_hdl_strdup(thp, str)) == NULL)
					ret = -1;
				else
					*(char **)val = s2;
			}
			break;
		}
		case TOPO_TYPE_FMRI: {
			nvlist_t *nvl;

			ret = nvlist_lookup_nvlist(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &nvl);
			if (ret == 0)
				ret = topo_hdl_nvdup(thp, nvl,
				    (nvlist_t **)val);
			break;
		}
		case TOPO_TYPE_INT32_ARRAY: {
			int32_t *a1, *a2;

			if ((ret = nvlist_lookup_int32_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (int32_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(int32_t **)val = a1;
			break;
		}
		case TOPO_TYPE_UINT32_ARRAY: {
			uint32_t *a1, *a2;

			if ((ret = nvlist_lookup_uint32_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (uint32_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(uint32_t **)val = a1;
			break;
		}
		case TOPO_TYPE_INT64_ARRAY: {
			int64_t *a1, *a2;

			if ((ret = nvlist_lookup_int64_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (int64_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(int64_t **)val = a1;
			break;
		}
		case TOPO_TYPE_UINT64_ARRAY: {
			uint64_t *a1, *a2;

			if ((ret = nvlist_lookup_uint64_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (uint64_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(uint64_t **)val = a1;
			break;
		}
		case TOPO_TYPE_STRING_ARRAY: {
			char **a1, **a2;

			if ((ret = nvlist_lookup_string_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (char *) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i) {
				if ((a1[i] = topo_hdl_strdup(thp, a2[i]))
				    == NULL) {
					for (j = 0; j < i; ++j)
						topo_hdl_free(thp, a1[j],
						    sizeof (char *));
					topo_hdl_free(thp, a1,
					    sizeof (char *) * *nelems);
					break;
				}
			}
			*(char ***)val = a1;
			break;
		}
		case TOPO_TYPE_FMRI_ARRAY: {
			nvlist_t **a1, **a2;

			if ((ret = nvlist_lookup_nvlist_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (nvlist_t *) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i) {
				if (topo_hdl_nvdup(thp, a2[i], &a1[i]) < 0) {
					for (j = 0; j < i; ++j)
						nvlist_free(a1[j]);
					topo_hdl_free(thp, a1,
					    sizeof (nvlist_t *) * *nelems);
					break;
				}
			}
			*(nvlist_t ***)val = a1;
			break;
		}
		default:
			ret = ETOPO_PROP_NOENT;
	}

	if (ret != 0)
		if (ret == ENOENT)
			return (get_properror(node, err, ETOPO_PROP_NOENT));
		else if (ret < ETOPO_UNKNOWN)
			return (get_properror(node, err, ETOPO_PROP_NVL));
		else
			return (get_properror(node, err, ret));

	topo_node_unlock(node);
	return (0);
}
Example #10
0
static char *
topo_snap_create(topo_hdl_t *thp, int *errp, boolean_t need_force)
{
	uuid_t uuid;
	char *ustr = NULL;

	topo_hdl_lock(thp);
	if (thp->th_uuid != NULL) {
		*errp = ETOPO_HDL_UUID;
		topo_hdl_unlock(thp);
		return (NULL);
	}

	if ((thp->th_uuid = topo_hdl_zalloc(thp, TOPO_UUID_SIZE)) == NULL) {
		*errp = ETOPO_NOMEM;
		topo_dprintf(thp, TOPO_DBG_ERR, "unable to allocate uuid: %s\n",
		    topo_strerror(*errp));
		topo_hdl_unlock(thp);
		return (NULL);
	}

	uuid_generate(uuid);
	uuid_unparse(uuid, thp->th_uuid);
	if ((ustr = topo_hdl_strdup(thp, thp->th_uuid)) == NULL) {
		*errp = ETOPO_NOMEM;
		topo_hdl_unlock(thp);
		return (NULL);
	}

	if (need_force) {
		topo_dprintf(thp, TOPO_DBG_FORCE,
		    "taking a DINFOFORCE snapshot\n");
		thp->th_di = di_init("/", DINFOFORCE |
		    DINFOSUBTREE | DINFOMINOR | DINFOPROP | DINFOPATH);
	} else {
		thp->th_di = di_init("/", DINFOCACHE);
	}
	thp->th_pi = di_prom_init();

	if (topo_tree_enum_all(thp) < 0) {
		topo_dprintf(thp, TOPO_DBG_ERR, "enumeration failure: %s\n",
		    topo_hdl_errmsg(thp));
		if (topo_hdl_errno(thp) == ETOPO_ENUM_FATAL) {
			*errp = thp->th_errno;

			if (thp->th_di != DI_NODE_NIL) {
				di_fini(thp->th_di);
				thp->th_di = DI_NODE_NIL;
			}
			if (thp->th_pi != DI_PROM_HANDLE_NIL) {
				di_prom_fini(thp->th_pi);
				thp->th_pi = DI_PROM_HANDLE_NIL;
			}

			topo_hdl_strfree(thp, ustr);
			topo_hdl_unlock(thp);
			return (NULL);
		}
	}

	if (thp->th_ipmi != NULL &&
	    ipmi_sdr_changed(thp->th_ipmi) &&
	    ipmi_sdr_refresh(thp->th_ipmi) != 0) {
		topo_dprintf(thp, TOPO_DBG_ERR,
		    "failed to refresh IPMI sdr repository: %s\n",
		    ipmi_errmsg(thp->th_ipmi));
	}

	topo_hdl_unlock(thp);

	return (ustr);
}
Example #11
0
topo_hdl_t *
topo_open(int version, const char *rootdir, int *errp)
{
	topo_hdl_t *thp = NULL;
	topo_alloc_t *tap;

	char platform[MAXNAMELEN];
	char isa[MAXNAMELEN];
	struct utsname uts;
	struct stat st;

	smbios_hdl_t *shp;
	smbios_system_t s1;
	smbios_info_t s2;
	id_t id;

	char *dbflags, *dbout;

	if (version != TOPO_VERSION)
		return (set_open_errno(thp, errp, ETOPO_HDL_ABIVER));

	if (rootdir != NULL && stat(rootdir, &st) < 0)
		return (set_open_errno(thp, errp, ETOPO_HDL_INVAL));

	if ((thp = topo_zalloc(sizeof (topo_hdl_t), 0)) == NULL)
		return (set_open_errno(thp, errp, ETOPO_NOMEM));

	(void) pthread_mutex_init(&thp->th_lock, NULL);

	if ((tap = topo_zalloc(sizeof (topo_alloc_t), 0)) == NULL)
		return (set_open_errno(thp, errp, ETOPO_NOMEM));

	/*
	 * Install default allocators
	 */
	tap->ta_flags = 0;
	tap->ta_alloc = topo_alloc;
	tap->ta_zalloc = topo_zalloc;
	tap->ta_free = topo_free;
	tap->ta_nvops.nv_ao_alloc = topo_nv_alloc;
	tap->ta_nvops.nv_ao_free = topo_nv_free;
	(void) nv_alloc_init(&tap->ta_nva, &tap->ta_nvops);
	thp->th_alloc = tap;

	if ((thp->th_modhash = topo_modhash_create(thp)) == NULL)
		return (set_open_errno(thp, errp, ETOPO_NOMEM));

	/*
	 * Set-up system information and search paths for modules
	 * and topology map files
	 */
	if (rootdir == NULL) {
		rootdir = topo_hdl_strdup(thp, "/");
		thp->th_rootdir = (char *)rootdir;
	} else {
		int len;
		char *rpath;

		len = strlen(rootdir);
		if (len >= PATH_MAX)
			return (set_open_errno(thp, errp, EINVAL));

		if (rootdir[len - 1] != '/') {
			rpath = alloca(len + 2);
			(void) snprintf(rpath, len + 2, "%s/", rootdir);
		} else {
			rpath = (char *)rootdir;
		}
		thp->th_rootdir = topo_hdl_strdup(thp, rpath);
	}

	platform[0] = '\0';
	isa[0] = '\0';
	(void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
	(void) sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
	(void) uname(&uts);
	thp->th_platform = topo_hdl_strdup(thp, platform);
	thp->th_isa = topo_hdl_strdup(thp, isa);
	thp->th_machine = topo_hdl_strdup(thp, uts.machine);
	if ((shp = smbios_open(NULL, SMB_VERSION, 0, NULL)) != NULL) {
		if ((id = smbios_info_system(shp, &s1)) != SMB_ERR &&
		    smbios_info_common(shp, id, &s2) != SMB_ERR) {

			if (strcmp(s2.smbi_product, SMB_DEFAULT1) != 0 &&
			    strcmp(s2.smbi_product, SMB_DEFAULT2) != 0) {
				thp->th_product = topo_cleanup_auth_str(thp,
				    (char *)s2.smbi_product);
			}
		}
		smbios_close(shp);
	} else {
		thp->th_product = topo_hdl_strdup(thp, thp->th_platform);
	}

	if (thp->th_rootdir == NULL || thp->th_platform == NULL ||
	    thp->th_machine == NULL)
		return (set_open_errno(thp, errp, ETOPO_NOMEM));

	dbflags	 = getenv("TOPO_DEBUG");
	dbout = getenv("TOPO_DEBUG_OUT");
	if (dbflags != NULL)
		topo_debug_set(thp, dbflags, dbout);

	if (topo_builtin_create(thp, thp->th_rootdir) != 0) {
		topo_dprintf(thp, TOPO_DBG_ERR,
		    "failed to load builtin modules: %s\n",
		    topo_hdl_errmsg(thp));
		return (set_open_errno(thp, errp, topo_hdl_errno(thp)));
	}

	return (thp);
}