/* * Convert from a devid string to a path. */ static char * devid_to_path(char *devid_str) { ddi_devid_t devid; char *minor; char *path; devid_nmlist_t *list = NULL; int ret; if (devid_str_decode(devid_str, &devid, &minor) != 0) return (NULL); ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); devid_str_free(minor); devid_free(devid); if (ret != 0) return (NULL); if ((path = strdup(list[0].devname)) == NULL) return (NULL); devid_free_nmlist(list); return (path); }
/* * This routine is called from preenlib the first time. It is then * recursively called through preen_subdev. * * The argument passed in (uname) starts with the special device from * /etc/vfstab. Recursive calls pass in the underlying physical device * names. */ void preen_build_devs( char *uname, /* name of metadevice */ struct dk_cinfo *dkiop, /* associated controller info */ void *dp /* magic info */ ) { char *setname = NULL; char *tname = NULL; mdsetname_t *sp; mdname_t *namep; /* metadevice name */ mdnamelist_t *nlp = NULL; /* list of real devices */ mdnamelist_t *p; devid_nmlist_t *nm_list = NULL; md_error_t status = mdnullerror; md_error_t *ep = &status; int ep_valid = 0; /* does ep contain a real error */ struct stat statb; static int md_major = -1; side_t sideno; /* * The rest of the code in this library can't work within a * non-global zone so we just return the top level metadevice back * to be fscked. */ if (getzoneid() != GLOBAL_ZONEID) { preen_addunit(dp, dkiop->dki_dname, NULL, NULL, dkiop->dki_unit); return; } if (stat(uname, &statb) != 0) return; if (md_major == -1 && get_major_from_n2m(MD_MODULE, &md_major) != 0) return; /* * If the path passed in is not a metadevice, then add that * device to the list (preen_addunit) since it has to be a * physical device. */ if (major(statb.st_rdev) != md_major) { preen_addunit(dp, dkiop->dki_dname, NULL, NULL, dkiop->dki_unit); return; } /* * Bind to the cluster library */ if (sdssc_bind_library() == SDSSC_ERROR) return; if (md_init_daemon("fsck", ep) != 0) { ep_valid = 1; goto out; } /* * parse the path name to get the diskset name. */ parse_device(NULL, uname, &tname, &setname); Free(tname); if ((sp = metasetname(setname, ep)) == NULL) { ep_valid = 1; goto out; } /* check for ownership */ if (meta_check_ownership(sp, ep) != 0) { /* * Don't own the set but we are here implies * that this is a clustered proxy device. Simply add * the unit. */ preen_addunit(dp, dkiop->dki_dname, NULL, NULL, dkiop->dki_unit); ep_valid = 1; goto out; } /* * get list of underlying physical devices. */ if ((namep = metaname(&sp, uname, UNKNOWN, ep)) == NULL) { ep_valid = 1; goto out; } if (namep->dev == NODEV64) { goto out; } if (meta_getdevs(sp, namep, &nlp, ep) != 0) { ep_valid = 1; goto out; } if ((sideno = getmyside(sp, ep)) == MD_SIDEWILD) { ep_valid = 1; goto out; } /* gather and add the underlying devs */ for (p = nlp; (p != NULL); p = p->next) { mdname_t *devnp = p->namep; int fd; struct dk_cinfo cinfo; ddi_devid_t md_did; char *devname; char *minor_name = NULL; char mname[MAXPATHLEN]; /* * we don't want to use the rname anymore because * that may have changed. Use the device id information * to find the correct ctd name and open based on that. * If there isn't a devid or we have a did device, then * use the rname. In clustering, it's corrected for us. * If no devid it's at least worth a try. */ if (((md_did = meta_getdidbykey(sp->setno, sideno, devnp->key, ep)) == NULL) || ((minor_name = meta_getdidminorbykey(sp->setno, sideno, devnp->key, ep)) == NULL)) { devname = devnp->rname; if (md_did) Free(md_did); } else { if (strstr(minor_name, ",raw") == NULL) { (void) snprintf(mname, MAXPATHLEN, "%s,raw", minor_name); } else { (void) snprintf(mname, MAXPATHLEN, "%s", minor_name); } /* * We need to make sure we call this with a specific * mname (raw mname) so that we get the exact slice * with the given device id. Otherwise we could try * to open a slice that doesn't really exist. */ if (meta_deviceid_to_nmlist("/dev", md_did, mname, &nm_list) != 0) { (void) mdsyserror(ep, errno, devnp->rname); ep_valid = 1; Free(md_did); Free(minor_name); goto out; } devname = Strdup(nm_list->devname); Free(md_did); Free(minor_name); devid_free_nmlist(nm_list); } /* get device name and (real) cinfo */ if ((fd = open(devname, O_RDONLY, 0)) < 0) { (void) mdsyserror(ep, errno, devname); ep_valid = 1; /* * We need to scan all sub devices even if some fail * since exit here would end up in not finishing fsck * on all devices and prevent us from going into * multiuser mode. */ continue; } if (ioctl(fd, DKIOCINFO, &cinfo) != 0) { (void) mdsyserror(ep, errno, devname); (void) close(fd); ep_valid = 1; /* Continue here too. See comment from before */ continue; } (void) close(fd); /* sd/ssd bug */ /* * preen_subdev fails when the device name has been * resolved to the physical layer. Hence it is added * to preen_addunit. */ if (preen_subdev(devname, &cinfo, dp) != 0) { preen_addunit(dp, cinfo.dki_dname, NULL, NULL, cinfo.dki_unit); } } /* cleanup, if we fail, just add this composite device to the list */ out: if (setname != NULL) Free(setname); if (ep_valid != 0) { mde_perror(&status, ""); mdclrerror(&status); } metafreenamelist(nlp); }