/* * Is a file system currently mounted on this disk drive? */ int meta_check_drivemounted( mdsetname_t *sp, mddrivename_t *dnp, md_error_t *ep ) { FILE *mfp; struct mnttab m; int rval = 0; char mountp[MNT_LINE_MAX]; char mnt_special[MNT_LINE_MAX]; /* should have a set */ assert(sp != NULL); /* look in mnttab */ if ((mfp = open_mnttab()) == NULL) return (mdsyserror(ep, errno, MNTTAB)); while ((getmntent(mfp, &m) == 0) && (rval == 0)) { char **fstype = skip_these_mntents; int skipit = 0; mdname_t *mnp; if ((m.mnt_special == NULL) || (m.mnt_mountp == NULL)) continue; if (m.mnt_mountp[0] != '/') continue; while (*fstype != NULL) if (strcmp(m.mnt_fstype, *fstype++) == 0) { skipit++; break; } if (skipit == 1) continue; (void) strcpy(mountp, m.mnt_mountp); (void) strcpy(mnt_special, m.mnt_special); if ((mnp = metaname(&sp, mnt_special, LOGICAL_DEVICE, ep)) == NULL) { mdclrerror(ep); continue; } if (strcmp(dnp->cname, mnp->drivenamep->cname) == 0) { rval = mduseerror(ep, MDE_IS_MOUNTED, NODEV64, mountp, dnp->cname); } } /* return success */ return (rval); }
/* * Return the current root filesystem block device name. This is only valid * when root is either a slice, a stripe or a mirror. */ mdname_t * meta_get_current_root_dev( mdsetname_t *sp, md_error_t *ep ) { md_stripe_t *stripep; md_mirror_t *mirrorp; md_row_t *rp; md_comp_t *cp; mdname_t *rootnp; void *curroot; char *miscname; int smi; if ((curroot = meta_get_current_root(ep)) == NULL) return (NULL); if ((rootnp = metaname(&sp, curroot, UNKNOWN, ep)) == NULL) return (NULL); if (metaismeta(rootnp)) { if ((miscname = metagetmiscname(rootnp, ep)) == NULL) return (NULL); if ((strcmp(miscname, MD_MIRROR) == 0) && ((mirrorp = meta_get_mirror(sp, rootnp, ep)) != NULL)) { for (smi = 0; smi < NMIRROR; smi++) { md_submirror_t *mdsp = &mirrorp->submirrors[smi]; rootnp = mdsp->submirnamep; /* skip unused submirrors */ if (rootnp == NULL) { assert(mdsp->state == SMS_UNUSED); continue; } if ((miscname = metagetmiscname(rootnp, ep)) == NULL) { (void) mdmderror(ep, MDE_UNKNOWN_TYPE, meta_getminor(rootnp->dev), rootnp->cname); return (NULL); } break; } } if ((strcmp(miscname, MD_STRIPE) == 0) && ((stripep = meta_get_stripe(sp, rootnp, ep)) != NULL)) { rp = &stripep->rows.rows_val[0]; cp = &rp->comps.comps_val[0]; if (metachkcomp(cp->compnamep, ep) == 0) return (cp->compnamep); } /* Root is not a single stripe metadevice */ (void) mddeverror(ep, MDE_INV_ROOT, rootnp->dev, rootnp->cname); return (NULL); } else return (rootnp); }
/* * clear metadevice or hotspare pool */ static int clear_name( mdsetname_t **spp, char *uname, mdcmdopts_t options, md_error_t *ep ) { /* clear hotspare pool */ if (is_existing_hsp(*spp, uname)) { mdhspname_t *hspnp; /* get hotspare pool name */ if ((hspnp = metahspname(spp, uname, ep)) == NULL) return (-1); assert(*spp != NULL); /* grab set lock */ if (meta_lock(*spp, TRUE, ep)) return (-1); /* check for ownership */ if (meta_check_ownership(*spp, ep) != 0) return (-1); /* clear hotspare pool */ return (meta_hsp_reset(*spp, hspnp, options, ep)); } /* clear metadevice */ else { mdname_t *np; /* check for ownership */ if (meta_check_ownership(*spp, ep) != 0) return (-1); /* get metadevice name */ if (((np = metaname(spp, uname, META_DEVICE, ep)) == NULL) || (metachkmeta(np, ep) != 0)) { return (-1); } assert(*spp != NULL); /* grab set lock */ if (meta_lock(*spp, TRUE, ep)) return (-1); /* clear metadevice */ return (meta_reset_by_name(*spp, np, options, ep)); } }
/* * check whether device is swapped on */ static int meta_check_swapped( mdsetname_t *sp, mdname_t *np, md_error_t *ep ) { struct swaptable *swtp; int nswap; int i; int rval = 0; /* should have a set */ assert(sp != NULL); /* get swap info */ if (get_swapinfo(&swtp, &nswap, ep) != 0) return (-1); /* look for match */ for (i = 0; ((i < nswap) && (rval == 0)); ++i) { mdname_t *snp; if ((snp = metaname(&sp, swtp->swt_ent[i].ste_path, UNKNOWN, ep)) == NULL) { mdclrerror(ep); continue; } if (np->dev == snp->dev) { rval = mddeverror(ep, MDE_IS_SWAPPED, np->dev, np->cname); } else { /* not swap - does it overlap */ rval = meta_check_overlap(snp->cname, np, 0, -1, snp, 0, -1, ep); if (rval != 0) { (void) mdoverlaperror(ep, MDE_OVERLAP_SWAP, np->cname, NULL, snp->cname); } } } free_swapinfo(swtp); /* return success */ return (rval); }
/* * check whether device is a dump device */ static int meta_check_dump( mdsetname_t *sp, mdname_t *np, md_error_t *ep ) { int rval = 0; int dump_fd; char device[MAXPATHLEN]; if ((dump_fd = open("/dev/dump", O_RDONLY)) < 0) return (mdsyserror(ep, errno, "/dev/dump")); if (ioctl(dump_fd, DIOCGETDEV, device) != -1) { mdname_t *dump_np; if ((dump_np = metaname(&sp, device, UNKNOWN, ep)) == NULL) { mdclrerror(ep); (void) close(dump_fd); return (0); } if (np->dev == dump_np->dev) { rval = mddeverror(ep, MDE_IS_DUMP, np->dev, np->cname); } else { /* not a dump device - but does it overlap? */ rval = meta_check_overlap(dump_np->cname, np, 0, -1, dump_np, 0, -1, ep); if (rval != 0) { (void) mdoverlaperror(ep, MDE_OVERLAP_DUMP, np->cname, NULL, dump_np->cname); } } } (void) close(dump_fd); return (rval); }
/* * Is a driver currently swapped on? */ int meta_check_driveswapped( mdsetname_t *sp, mddrivename_t *dnp, md_error_t *ep ) { struct swaptable *swtp; int nswap; int i; int rval = 0; /* should have a set */ assert(sp != NULL); /* get swap info */ if (get_swapinfo(&swtp, &nswap, ep) != 0) return (-1); /* look for match */ for (i = 0; (i < nswap); ++i) { mdname_t *snp; if ((snp = metaname(&sp, swtp->swt_ent[i].ste_path, LOGICAL_DEVICE, ep)) == NULL) { mdclrerror(ep); continue; } if (strcmp(dnp->cname, snp->drivenamep->cname) == 0) { rval = mddeverror(ep, MDE_IS_SWAPPED, NODEV64, dnp->cname); } } free_swapinfo(swtp); /* return success */ return (rval); }
/* * check whether device is mounted */ static int meta_check_mounted( mdsetname_t *sp, mdname_t *np, md_error_t *ep ) { FILE *mfp; struct mnttab m; int rval = 0; char mountp[MNT_LINE_MAX]; char mnt_special[MNT_LINE_MAX]; /* should have a set */ assert(sp != NULL); /* look in mnttab */ if ((mfp = open_mnttab()) == NULL) return (mdsyserror(ep, errno, MNTTAB)); while ((getmntent(mfp, &m) == 0) && (rval == 0)) { char **fstype = skip_these_mntents; int skipit = 0; mdname_t *mnp; if ((m.mnt_special == NULL) || (m.mnt_mountp == NULL)) continue; if (m.mnt_mountp[0] != '/') continue; while (*fstype != NULL) if (strcmp(m.mnt_fstype, *fstype++) == 0) { skipit++; break; } if (skipit == 1) continue; (void) strcpy(mountp, m.mnt_mountp); (void) strcpy(mnt_special, m.mnt_special); if ((mnp = metaname(&sp, mnt_special, UNKNOWN, ep)) == NULL) { mdclrerror(ep); continue; } if (np->dev == mnp->dev) { rval = mduseerror(ep, MDE_IS_MOUNTED, np->dev, mountp, np->cname); } else { /* device isn't in mnttab - does it overlap? */ rval = meta_check_overlap(mnp->cname, np, 0, -1, mnp, 0, -1, ep); if (rval != 0) { (void) mdoverlaperror(ep, MDE_OVERLAP_MOUNTED, np->cname, mountp, mnp->cname); } } } /* return success */ return (rval); }
int get_mdcomponents(char *uname, svm_info_t **svmpp) { svm_info_t *svmp; md_error_t status, *ep; mdname_t *namep; mdnamelist_t *nlp = NULL; mdnamelist_t *p; mdsetname_t *sp = NULL; char *strp = NULL; int rval, cnt; rval = RET_SUCCESS; cnt = 0; status = mdnullerror; ep = &status; svmp = *svmpp; (void) init_metalib(); debug_printf("get_mdcomponents(): Enter unit name %s\n", uname); if (((namep = metaname(&sp, uname, META_DEVICE, ep)) == NULL) || (metachkmeta(namep, ep) != 0)) { debug_printf("get_mdcomponents(): " "metaname or metachkmeta failed\n"); mdclrerror(ep); return (RET_ERROR); } debug_printf("get_mdcomponents(): meta_getdevs %s\n", namep->cname); if ((meta_getdevs(sp, namep, &nlp, ep)) < 0) { debug_printf("get_mdcomponents(): " "comp %s - meta_getdevs failed\n", uname); metafreenamelist(nlp); mdclrerror(ep); return (RET_ERROR); } /* compute the number of devices */ for (p = nlp, cnt = 0; p != NULL; p = p->next, cnt++) ; /* * Need to add n -1 components since slvmp already has space * for one device. */ svmp = (svm_info_t *)realloc(svmp, sizeof (svm_info_t) + (sizeof (char *) * (cnt - 1))); if (svmp == NULL) { debug_printf("get_mdcomponents(): realloc of svmp failed\n"); metafreenamelist(nlp); return (RET_ERROR); } for (p = nlp, cnt = 0; p != NULL; p = p->next, cnt++) { mdname_t *devnp = p->namep; if ((strp = strdup(devnp->cname)) == NULL) { rval = RET_ERROR; break; } svmp->md_comps[cnt] = strp; } /* count is set to the number of devices in the list */ svmp->count = cnt; svmp->root_md = strdup(uname); if (rval == RET_SUCCESS && svmp->root_md != NULL) { debug_printf("get_mdcomponents(): root_md %s count %d \n", svmp->root_md, svmp->count); for (cnt = 0; cnt < svmp->count; cnt++) debug_printf("get_mdcomponents(): %s\n", svmp->md_comps[cnt]); } else { rval = RET_ERROR; svm_free(svmp); svmp = NULL; debug_printf("get_mdcomponents(): malloc failed\n"); } metafreenamelist(nlp); *svmpp = svmp; return (rval); }
/* * 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); }