2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A/*
2N/A * Creates and maintains a cache of slices used by SVM.
2N/A */
2N/A
2N/A#include <meta.h>
2N/A#include <stdlib.h>
2N/A#include <stdio.h>
2N/A#include <string.h>
2N/A#include <libintl.h>
2N/A#include <synch.h>
2N/A#include <thread.h>
2N/A#include <dlfcn.h>
2N/A#include <link.h>
2N/A#include <libsysevent.h>
2N/A#include <syslog.h>
2N/A#include <sys/types.h>
2N/A#include <sys/sysevent/eventdefs.h>
2N/A
2N/A#include "libdiskmgt.h"
2N/A#include "disks_private.h"
2N/A
2N/A/*
2N/A * The list of SVM slices in use.
2N/A */
2N/A
2N/Astruct svm_list {
2N/A struct svm_list *next;
2N/A char *slice;
2N/A char *name;
2N/A char *type;
2N/A};
2N/A
2N/Astatic struct svm_list *svm_listp = NULL;
2N/Astatic rwlock_t svm_lock = DEFAULTRWLOCK;
2N/Astatic int initialized = 0;
2N/Astatic mutex_t init_lock = DEFAULTMUTEX;
2N/A
2N/Astatic int add_use_record(char *devname, char *type, char *mname);
2N/Astatic int diskset_info(mdsetname_t *sp);
2N/Astatic int drive_in_diskset(char *dpath, char *setname);
2N/Astatic void event_handler();
2N/Astatic void free_names(mdnamelist_t *nlp);
2N/Astatic void free_svm(struct svm_list *listp);
2N/Astatic int init_svm();
2N/Astatic int load_svm();
2N/Astatic int new_entry(char *sname, char *type, char *mname,
2N/A mdsetname_t *sp);
2N/A
2N/A/*
2N/A * Pointers to libmeta functions that we dynamically resolve.
2N/A */
2N/Astatic set_t (*mdl_get_max_sets)(md_error_t *ep);
2N/Astatic void (*mdl_mdclrerror)(md_error_t *ep);
2N/Astatic md_error_t *mdl_mdnullerror;
2N/Astatic void (*mdl_metaflushnames)(int flush_sr_cache);
2N/Astatic void (*mdl_metaflushsetname)(mdsetname_t *sp);
2N/Astatic void (*mdl_metafreenamelist)(mdnamelist_t *nlp);
2N/Astatic void (*mdl_metafreereplicalist)(md_replicalist_t *rlp);
2N/Astatic md_drive_desc *(*mdl_metaget_drivedesc)(mdsetname_t *sp, int flags,
2N/A md_error_t *ep);
2N/Astatic mdname_t *(*mdl_metaname)(mdsetname_t **spp, char *uname,
2N/A meta_device_type_t uname_type, md_error_t *ep);
2N/Astatic int (*mdl_metareplicalist)(mdsetname_t *sp, int flags,
2N/A md_replicalist_t **rlpp, md_error_t *ep);
2N/Astatic mdsetname_t *(*mdl_metasetnosetname)(set_t setno, md_error_t *ep);
2N/Astatic int (*mdl_meta_get_hotspare_names)(mdsetname_t *sp,
2N/A mdnamelist_t **nlpp, int options, md_error_t *ep);
2N/Astatic md_raid_t *(*mdl_meta_get_raid)(mdsetname_t *sp, mdname_t *raidnp,
2N/A md_error_t *ep);
2N/Astatic int (*mdl_meta_get_raid_names)(mdsetname_t *sp,
2N/A mdnamelist_t **nlpp, int options, md_error_t *ep);
2N/Astatic md_sp_t *(*mdl_meta_get_sp)(mdsetname_t *sp, mdname_t *np,
2N/A md_error_t *ep);
2N/Astatic int (*mdl_meta_get_sp_names)(mdsetname_t *sp,
2N/A mdnamelist_t **nlpp, int options, md_error_t *ep);
2N/Astatic md_stripe_t *(*mdl_meta_get_stripe)(mdsetname_t *sp,
2N/A mdname_t *stripenp, md_error_t *ep);
2N/Astatic int (*mdl_meta_get_stripe_names)(mdsetname_t *sp,
2N/A mdnamelist_t **nlpp, int options, md_error_t *ep);
2N/Astatic int (*mdl_meta_get_trans_names)(mdsetname_t *sp,
2N/A mdnamelist_t **nlpp, int options, md_error_t *ep);
2N/Astatic void (*mdl_meta_invalidate_name)(mdname_t *np);
2N/Astatic void (*mdl_sdssc_bind_library)();
2N/A
2N/A/*
2N/A * Search the list of devices under SVM for the specified device.
2N/A */
2N/Aint
2N/Ainuse_svm(char *slice, nvlist_t *attrs, int *errp)
2N/A{
2N/A struct svm_list *listp;
2N/A int found = 0;
2N/A
2N/A *errp = 0;
2N/A if (slice == NULL) {
2N/A return (found);
2N/A }
2N/A
2N/A (void) mutex_lock(&init_lock);
2N/A if (!initialized) {
2N/A /* dynamically load libmeta */
2N/A if (init_svm()) {
2N/A /*
2N/A * need to initialize the cluster library to
2N/A * avoid seg faults
2N/A */
2N/A (mdl_sdssc_bind_library)();
2N/A
2N/A /* load the SVM cache */
2N/A *errp = load_svm();
2N/A
2N/A if (*errp == 0) {
2N/A /* start a thread to monitor the svm config */
2N/A sysevent_handle_t *shp;
2N/A const char *subclass_list[1];
2N/A /*
2N/A * Only start the svmevent thread if
2N/A * we are not doing an install
2N/A */
2N/A
2N/A if (getenv("_LIBDISKMGT_INSTALL") == NULL) {
2N/A shp = sysevent_bind_handle(
2N/A event_handler);
2N/A if (shp != NULL) {
2N/A subclass_list[0] = EC_SUB_ALL;
2N/A if (sysevent_subscribe_event(
2N/A shp, EC_SVM_CONFIG,
2N/A subclass_list, 1) != 0) {
2N/A *errp = errno;
2N/A }
2N/A } else {
2N/A *errp = errno;
2N/A }
2N/A if (*errp) {
2N/A /*
2N/A * If the sysevent thread fails,
2N/A * log the error but continue
2N/A * on. This failing to start
2N/A * is not catastrophic in
2N/A * particular for short lived
2N/A * consumers of libdiskmgt.
2N/A */
2N/A syslog(LOG_WARNING,
2N/A dgettext(TEXT_DOMAIN,
2N/A "libdiskmgt: sysevent "
2N/A "thread for SVM failed "
2N/A "to start\n"));
2N/A *errp = 0;
2N/A }
2N/A }
2N/A }
2N/A }
2N/A
2N/A if (*errp == 0) {
2N/A initialized = 1;
2N/A }
2N/A }
2N/A (void) mutex_unlock(&init_lock);
2N/A
2N/A (void) rw_rdlock(&svm_lock);
2N/A listp = svm_listp;
2N/A while (listp != NULL) {
2N/A if (strcmp(slice, listp->slice) == 0) {
2N/A libdiskmgt_add_str(attrs, DM_USED_BY, DM_USE_SVM, errp);
2N/A if (strcmp(listp->type, "mdb") == 0 ||
2N/A strcmp(listp->type, "hs") == 0) {
2N/A
2N/A libdiskmgt_add_str(attrs, DM_USED_NAME, listp->type, errp);
2N/A } else {
2N/A char name[MAXPATHLEN];
2N/A (void) snprintf(name, MAXPATHLEN, "%s:%s", listp->type,
2N/A listp->name);
2N/A libdiskmgt_add_str(attrs, DM_USED_NAME, name, errp);
2N/A }
2N/A found = 1;
2N/A break;
2N/A }
2N/A listp = listp->next;
2N/A }
2N/A (void) rw_unlock(&svm_lock);
2N/A
2N/A return (found);
2N/A}
2N/A
2N/Astatic int
2N/Aadd_use_record(char *devname, char *type, char *mname)
2N/A{
2N/A struct svm_list *sp;
2N/A
2N/A /* If prev. record is a dup, skip it. */
2N/A if (svm_listp != NULL && strcmp(svm_listp->slice, devname) == 0 &&
2N/A strcmp(svm_listp->type, type) == 0) {
2N/A return (0);
2N/A }
2N/A
2N/A sp = (struct svm_list *)malloc(sizeof (struct svm_list));
2N/A if (sp == NULL) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if ((sp->slice = strdup(devname)) == NULL) {
2N/A free(sp);
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if ((sp->name = strdup(mname)) == NULL) {
2N/A free(sp->slice);
2N/A free(sp);
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if ((sp->type = strdup(type)) == NULL) {
2N/A free(sp->slice);
2N/A free(sp->name);
2N/A free(sp);
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A sp->next = svm_listp;
2N/A svm_listp = sp;
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Adiskset_info(mdsetname_t *sp)
2N/A{
2N/A md_error_t error = *mdl_mdnullerror;
2N/A md_replicalist_t *replica_list = NULL;
2N/A mdnamelist_t *trans_list = NULL;
2N/A mdnamelist_t *raid_list = NULL;
2N/A mdnamelist_t *stripe_list = NULL;
2N/A mdnamelist_t *sp_list = NULL;
2N/A mdnamelist_t *spare_list = NULL;
2N/A
2N/A if ((mdl_metareplicalist)(sp, MD_BASICNAME_OK, &replica_list, &error)
2N/A >= 0) {
2N/A md_replicalist_t *nlp;
2N/A
2N/A for (nlp = replica_list; nlp != NULL; nlp = nlp->rl_next) {
2N/A if (new_entry(nlp->rl_repp->r_namep->bname, "mdb",
2N/A nlp->rl_repp->r_namep->cname, sp)) {
2N/A (mdl_metafreereplicalist)(replica_list);
2N/A return (ENOMEM);
2N/A }
2N/A }
2N/A (mdl_metafreereplicalist)(replica_list);
2N/A
2N/A } else {
2N/A (mdl_mdclrerror)(&error);
2N/A /* there are no metadb's; that is ok, no need to check the rest */
2N/A return (0);
2N/A }
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A if ((mdl_meta_get_trans_names)(sp, &trans_list, 0, &error) >= 0) {
2N/A mdnamelist_t *nlp;
2N/A
2N/A for (nlp = trans_list; nlp != NULL; nlp = nlp->next) {
2N/A if (new_entry(nlp->namep->bname, "trans", nlp->namep->cname,
2N/A sp)) {
2N/A free_names(trans_list);
2N/A return (ENOMEM);
2N/A }
2N/A }
2N/A
2N/A free_names(trans_list);
2N/A }
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A if ((mdl_meta_get_raid_names)(sp, &raid_list, 0, &error) >= 0) {
2N/A mdnamelist_t *nlp;
2N/A
2N/A for (nlp = raid_list; nlp != NULL; nlp = nlp->next) {
2N/A mdname_t *mdn;
2N/A md_raid_t *raid;
2N/A
2N/A mdn = (mdl_metaname)(&sp, nlp->namep->cname,
2N/A META_DEVICE, &error);
2N/A (mdl_mdclrerror)(&error);
2N/A if (mdn == NULL) {
2N/A continue;
2N/A }
2N/A
2N/A raid = (mdl_meta_get_raid)(sp, mdn, &error);
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A if (raid != NULL) {
2N/A int i;
2N/A
2N/A for (i = 0; i < raid->cols.cols_len; i++) {
2N/A if (new_entry(raid->cols.cols_val[i].colnamep->bname,
2N/A "raid", nlp->namep->cname, sp)) {
2N/A free_names(raid_list);
2N/A return (ENOMEM);
2N/A }
2N/A }
2N/A }
2N/A }
2N/A
2N/A free_names(raid_list);
2N/A }
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A if ((mdl_meta_get_stripe_names)(sp, &stripe_list, 0, &error) >= 0) {
2N/A mdnamelist_t *nlp;
2N/A
2N/A for (nlp = stripe_list; nlp != NULL; nlp = nlp->next) {
2N/A mdname_t *mdn;
2N/A md_stripe_t *stripe;
2N/A
2N/A mdn = (mdl_metaname)(&sp, nlp->namep->cname,
2N/A META_DEVICE, &error);
2N/A (mdl_mdclrerror)(&error);
2N/A if (mdn == NULL) {
2N/A continue;
2N/A }
2N/A
2N/A stripe = (mdl_meta_get_stripe)(sp, mdn, &error);
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A if (stripe != NULL) {
2N/A int i;
2N/A
2N/A for (i = 0; i < stripe->rows.rows_len; i++) {
2N/A md_row_t *rowp;
2N/A int j;
2N/A
2N/A rowp = &stripe->rows.rows_val[i];
2N/A
2N/A for (j = 0; j < rowp->comps.comps_len; j++) {
2N/A md_comp_t *component;
2N/A
2N/A component = &rowp->comps.comps_val[j];
2N/A if (new_entry(component->compnamep->bname, "stripe",
2N/A nlp->namep->cname, sp)) {
2N/A free_names(stripe_list);
2N/A return (ENOMEM);
2N/A }
2N/A }
2N/A }
2N/A }
2N/A }
2N/A
2N/A free_names(stripe_list);
2N/A }
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A if ((mdl_meta_get_sp_names)(sp, &sp_list, 0, &error) >= 0) {
2N/A mdnamelist_t *nlp;
2N/A
2N/A for (nlp = sp_list; nlp != NULL; nlp = nlp->next) {
2N/A mdname_t *mdn;
2N/A md_sp_t *soft_part;
2N/A
2N/A mdn = (mdl_metaname)(&sp, nlp->namep->cname,
2N/A META_DEVICE, &error);
2N/A (mdl_mdclrerror)(&error);
2N/A if (mdn == NULL) {
2N/A continue;
2N/A }
2N/A
2N/A soft_part = (mdl_meta_get_sp)(sp, mdn, &error);
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A if (soft_part != NULL) {
2N/A if (new_entry(soft_part->compnamep->bname, "sp",
2N/A nlp->namep->cname, sp)) {
2N/A free_names(sp_list);
2N/A return (ENOMEM);
2N/A }
2N/A }
2N/A }
2N/A
2N/A free_names(sp_list);
2N/A }
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A if ((mdl_meta_get_hotspare_names)(sp, &spare_list, 0, &error) >= 0) {
2N/A mdnamelist_t *nlp;
2N/A
2N/A for (nlp = spare_list; nlp != NULL; nlp = nlp->next) {
2N/A if (new_entry(nlp->namep->bname, "hs", nlp->namep->cname, sp)) {
2N/A free_names(spare_list);
2N/A return (ENOMEM);
2N/A }
2N/A }
2N/A
2N/A free_names(spare_list);
2N/A }
2N/A
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * SVM uses "drive names" (ctd name without trailing slice) for drives
2N/A * in disksets. Since it massages these names there is no direct correspondence
2N/A * with the slice device names in /dev. So, we need to massage these names
2N/A * back to something we can match on when a slice comes in. We create an
2N/A * entry for each possible slice since we don't know what slices actually
2N/A * exist. Slice 0 & 7 are probably enough, but the user could have
2N/A * repartitioned the drive after they added it to the diskset and removed the
2N/A * mdb.
2N/A */
2N/Astatic int
2N/Adrive_in_diskset(char *dpath, char *setname)
2N/A{
2N/A int i;
2N/A char path[MAXPATHLEN];
2N/A
2N/A (void) strlcpy(path, dpath, sizeof (path));
2N/A if (strncmp(path, "/dev/rdsk/", 10) == 0) {
2N/A /* change rdsk to dsk */
2N/A char *p;
2N/A
2N/A /* start p pointing to r in rdsk */
2N/A for (p = path + 5; *p; p++) {
2N/A *p = *(p + 1);
2N/A }
2N/A } else if (strncmp(path, "/dev/did/rdsk/", 14) == 0) {
2N/A /* change rdsk to dsk */
2N/A char *p;
2N/A
2N/A /* start p pointing to r in rdsk */
2N/A for (p = path + 9; *p; p++) {
2N/A *p = *(p + 1);
2N/A }
2N/A }
2N/A
2N/A for (i = 0; i < 8; i++) {
2N/A char slice[MAXPATHLEN];
2N/A
2N/A (void) snprintf(slice, sizeof (slice), "%ss%d", path, i);
2N/A if (add_use_record(slice, "diskset", setname)) {
2N/A return (ENOMEM);
2N/A }
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic void
2N/Aevent_handler()
2N/A{
2N/A (void) rw_wrlock(&svm_lock);
2N/A free_svm(svm_listp);
2N/A svm_listp = NULL;
2N/A (mdl_metaflushnames)(0);
2N/A (void) load_svm();
2N/A (void) rw_unlock(&svm_lock);
2N/A}
2N/A
2N/Astatic void
2N/Afree_names(mdnamelist_t *nlp)
2N/A{
2N/A mdnamelist_t *p;
2N/A
2N/A for (p = nlp; p != NULL; p = p->next) {
2N/A (mdl_meta_invalidate_name)(p->namep);
2N/A p->namep = NULL;
2N/A }
2N/A (mdl_metafreenamelist)(nlp);
2N/A}
2N/A
2N/A/*
2N/A * Free the list of SVM entries.
2N/A */
2N/Astatic void
2N/Afree_svm(struct svm_list *listp) {
2N/A
2N/A struct svm_list *nextp;
2N/A
2N/A while (listp != NULL) {
2N/A nextp = listp->next;
2N/A free((void *)listp->slice);
2N/A free((void *)listp->name);
2N/A free((void *)listp->type);
2N/A free((void *)listp);
2N/A listp = nextp;
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Try to dynamically link the libmeta functions we need.
2N/A */
2N/Astatic int
2N/Ainit_svm()
2N/A{
2N/A void *lh;
2N/A
2N/A if ((lh = dlopen("/usr/lib/libmeta.so", RTLD_NOW)) == NULL) {
2N/A return (0);
2N/A }
2N/A
2N/A mdl_get_max_sets = (set_t (*)(md_error_t *))dlsym(lh, "get_max_sets");
2N/A
2N/A mdl_mdclrerror = (void(*)(md_error_t *))dlsym(lh, "mdclrerror");
2N/A
2N/A mdl_mdnullerror = (md_error_t *)dlsym(lh, "mdnullerror");
2N/A
2N/A mdl_metaflushnames = (void (*)(int))dlsym(lh, "metaflushnames");
2N/A
2N/A mdl_metaflushsetname = (void (*)(mdsetname_t *))dlsym(lh,
2N/A "metaflushsetname");
2N/A
2N/A mdl_metafreenamelist = (void (*)(mdnamelist_t *))dlsym(lh,
2N/A "metafreenamelist");
2N/A
2N/A mdl_metafreereplicalist = (void (*)(md_replicalist_t *))dlsym(lh,
2N/A "metafreereplicalist");
2N/A
2N/A mdl_metaget_drivedesc = (md_drive_desc *(*)(mdsetname_t *, int,
2N/A md_error_t *))dlsym(lh, "metaget_drivedesc");
2N/A
2N/A mdl_metaname = (mdname_t *(*)(mdsetname_t **, char *,
2N/A meta_device_type_t, md_error_t *))dlsym(lh, "metaname");
2N/A
2N/A mdl_metareplicalist = (int (*)(mdsetname_t *, int, md_replicalist_t **,
2N/A md_error_t *))dlsym(lh, "metareplicalist");
2N/A
2N/A mdl_metasetnosetname = (mdsetname_t *(*)(set_t, md_error_t *))dlsym(lh,
2N/A "metasetnosetname");
2N/A
2N/A mdl_meta_get_hotspare_names = (int (*)(mdsetname_t *, mdnamelist_t **,
2N/A int, md_error_t *))dlsym(lh, "meta_get_hotspare_names");
2N/A
2N/A mdl_meta_get_raid = (md_raid_t *(*)(mdsetname_t *, mdname_t *,
2N/A md_error_t *))dlsym(lh, "meta_get_raid");
2N/A
2N/A mdl_meta_get_raid_names = (int (*)(mdsetname_t *, mdnamelist_t **,
2N/A int, md_error_t *))dlsym(lh, "meta_get_raid_names");
2N/A
2N/A mdl_meta_get_sp = (md_sp_t *(*)(mdsetname_t *, mdname_t *,
2N/A md_error_t *))dlsym(lh, "meta_get_sp");
2N/A
2N/A mdl_meta_get_sp_names = (int (*)(mdsetname_t *, mdnamelist_t **,
2N/A int, md_error_t *))dlsym(lh, "meta_get_sp_names");
2N/A
2N/A mdl_meta_get_stripe = (md_stripe_t *(*)(mdsetname_t *, mdname_t *,
2N/A md_error_t *))dlsym(lh, "meta_get_stripe");
2N/A
2N/A mdl_meta_get_stripe_names = (int (*)(mdsetname_t *, mdnamelist_t **,
2N/A int, md_error_t *))dlsym(lh, "meta_get_stripe_names");
2N/A
2N/A mdl_meta_get_trans_names = (int (*)(mdsetname_t *, mdnamelist_t **,
2N/A int, md_error_t *))dlsym(lh, "meta_get_trans_names");
2N/A
2N/A mdl_meta_invalidate_name = (void (*)(mdname_t *))dlsym(lh,
2N/A "meta_invalidate_name");
2N/A
2N/A mdl_sdssc_bind_library = (void (*)())dlsym(lh, "sdssc_bind_library");
2N/A
2N/A return (1);
2N/A}
2N/A
2N/A/*
2N/A * Create a list of SVM devices
2N/A */
2N/Astatic int
2N/Aload_svm()
2N/A{
2N/A int max_sets;
2N/A md_error_t error = *mdl_mdnullerror;
2N/A int i;
2N/A
2N/A if ((max_sets = (mdl_get_max_sets)(&error)) == 0) {
2N/A return (0);
2N/A }
2N/A
2N/A if (!mdisok(&error)) {
2N/A (mdl_mdclrerror)(&error);
2N/A return (0);
2N/A }
2N/A
2N/A /* for each possible set number, see if we really have a diskset */
2N/A for (i = 0; i < max_sets; i++) {
2N/A mdsetname_t *sp;
2N/A
2N/A if ((sp = (mdl_metasetnosetname)(i, &error)) == NULL) {
2N/A
2N/A if (!mdisok(&error) &&
2N/A mdisrpcerror(&error, RPC_PROGNOTREGISTERED)) {
2N/A /* metad rpc program not registered - no metasets */
2N/A break;
2N/A }
2N/A
2N/A (mdl_mdclrerror)(&error);
2N/A continue;
2N/A }
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A /* pick up drives in disksets with no mdbs/metadevices */
2N/A if (sp->setno != 0) {
2N/A md_drive_desc *dd;
2N/A
2N/A dd = (mdl_metaget_drivedesc)(sp, MD_BASICNAME_OK | PRINT_FAST,
2N/A &error);
2N/A (mdl_mdclrerror)(&error);
2N/A for (; dd != NULL; dd = dd->dd_next) {
2N/A if (drive_in_diskset(dd->dd_dnp->rname, sp->setname)) {
2N/A (mdl_metaflushsetname)(sp);
2N/A return (ENOMEM);
2N/A }
2N/A }
2N/A }
2N/A
2N/A if (diskset_info(sp)) {
2N/A (mdl_metaflushsetname)(sp);
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A (mdl_metaflushsetname)(sp);
2N/A }
2N/A
2N/A (mdl_mdclrerror)(&error);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Anew_entry(char *sname, char *type, char *mname, mdsetname_t *sp)
2N/A{
2N/A mdname_t *mdn;
2N/A md_error_t error = *mdl_mdnullerror;
2N/A
2N/A mdn = (mdl_metaname)(&sp, sname, UNKNOWN, &error);
2N/A if (!mdisok(&error)) {
2N/A (mdl_mdclrerror)(&error);
2N/A return (0);
2N/A }
2N/A
2N/A if (mdn != NULL && (
2N/A mdn->drivenamep->type == MDT_ACCES ||
2N/A mdn->drivenamep->type == MDT_COMP ||
2N/A mdn->drivenamep->type == MDT_FAST_COMP)) {
2N/A
2N/A return (add_use_record(mdn->bname, type, mname));
2N/A }
2N/A
2N/A return (0);
2N/A}