Esempio n. 1
0
/*
 * add the given device to the list of devices to be checked
 */
int
preen_addev(char *devnm)
{
	struct rawdev *rdp;
	int fd;
	struct dk_cinfo dki;
	extern char *strdup();

	if ((fd = open64(devnm, O_RDONLY)) == -1) {
		perror(devnm);
		return (-1);
	}
	if (ioctl(fd, DKIOCINFO, &dki) == -1) {
		perror("DKIOCINFO");
		fprintf(stderr, "device: `%s'\n", devnm);
		(void) close(fd);
		return (-1);
	}
	(void) close(fd);
	if ((rdp = (struct rawdev *)malloc(sizeof (struct rawdev))) == NULL) {
		(void) fprintf(stderr, "out of memory in preenlib\n");
		return (-1);
	}
	if ((rdp->devname = strdup(devnm)) == NULL) {
		(void) fprintf(stderr, "out of memory in preenlib\n");
		return (-1);
	}
	rdp->alldevs = NULL;
	rdp->nxtrd = NULL;

	if (preen_subdev(devnm, &dki, (void *)rdp)) {
		preen_addunit(rdp, dki.dki_dname, NULL, NULL, dki.dki_unit);
	}

	rdp->nxtrd = unchecked;
	unchecked = rdp;
	return (0);
}
Esempio n. 2
0
/*
 * 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);
}