Пример #1
0
/*
 * get swap info
 */
static int
get_swapinfo(
	struct swaptable	**swtpp,
	int			*nswap,
	md_error_t		*ep
)
{
	int			i;
	size_t			swtsize;

	*swtpp = NULL;

	/* get number of entries */
	if ((*nswap = swapctl(SC_GETNSWP, NULL)) < 0) {
		return (mdsyserror(ep, errno, "swapctl(SC_GETNSWP)"));
	}

	/* allocate structure */
	swtsize = sizeof ((*swtpp)->swt_n) +
	    ((*nswap) * sizeof ((*swtpp)->swt_ent[0]));
	*swtpp = (struct swaptable *)Zalloc(swtsize);
	(*swtpp)->swt_n = *nswap;
	for (i = 0; (i < (*nswap)); ++i)
		(*swtpp)->swt_ent[i].ste_path = Zalloc(MAXPATHLEN);

	/* get info */
	if (((*nswap) = swapctl(SC_LIST, (*swtpp))) < 0) {
		(void) mdsyserror(ep, errno, "swapctl(SC_LIST)");
		free_swapinfo(*swtpp);
		return (-1);
	}

	/* return success */
	return (0);
}
Пример #2
0
/*
 * steal and convert mherror_t
 */
int
mhstealerror(
	mhd_error_t	*mhep,
	md_error_t	*ep
)
{
	int		rval = -1;

	/* no error */
	if (mhep->errnum == 0) {
		/* assert(mhep->name == NULL); */
		rval = 0;
		goto out;
	}

	/* steal error */
	switch (mhep->errnum) {
	case MHD_E_MAJORITY:
		(void) mderror(ep, MDE_TAKE_OWN, mhep->name);
		break;
	case MHD_E_RESERVED:
		(void) mderror(ep, MDE_RESERVED, mhep->name);
		break;
	default:
		(void) mdsyserror(ep, mhep->errnum, mhep->name);
		break;
	}

	/* cleanup, return success */
out:
	if (mhep->name != NULL)
		Free(mhep->name);
	(void) memset(mhep, 0, sizeof (*mhep));
	return (rval);
}
Пример #3
0
/*
 * Named service entry point: MDRNM_CHECK
 */
intptr_t
stripe_rename_check(
	md_rendelta_t	*delta,
	md_rentxn_t	*rtxnp)
{
	int	err	= 0;

	ASSERT(delta);
	ASSERT(rtxnp);
	ASSERT(delta->unp);
	ASSERT(delta->uip);
	ASSERT((rtxnp->op == MDRNOP_RENAME) || (MDRNOP_EXCHANGE == rtxnp->op));

	if (!delta || !rtxnp || !delta->uip || !delta->unp) {
		(void) mdsyserror(&rtxnp->mde, EINVAL);
		return (EINVAL);
	}

	/* self does additional checks */
	if (delta->old_role == MDRR_SELF) {
		err = stripe_may_renexch_self((ms_unit_t *)delta->unp,
		    delta->uip, rtxnp);
	}
out:
	return (err);
}
Пример #4
0
/*
 * check AUTH_SYS
 */
static int
check_sys(
	struct svc_req		*rqstp,		/* RPC stuff */
	int			amode,		/* R_OK | W_OK */
	md_error_t		*ep		/* returned status */
)
{
	static mutex_t		mx = DEFAULTMUTEX;
	struct authsys_parms	*sys_credp;

	/* for read, anything is OK */
	if (! (amode & W_OK))
		return (0);

	/* single thread (not really needed if daemon stays single threaded) */
	mutex_lock(&mx);

	/* check for remote root or METAD_GID */
	/*LINTED*/
	sys_credp = (struct authsys_parms *)rqstp->rq_clntcred;
	if ((check_gid14(sys_credp->aup_uid) == 0) ||
	    (check_host(rqstp) == 0)) {
		mutex_unlock(&mx);
		return (0);
	}

	/* return failure */
	mutex_unlock(&mx);
	return (mdsyserror(ep, EACCES, "rpc.metad"));
}
Пример #5
0
/*
 * 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);
}
Пример #6
0
/*
 * set filesystem device name in vfstab
 */
int
meta_patch_fsdev(
	char		*fsname,	/* filesystem mount point */
	mdname_t	*fsnp,		/* filesystem device */
	char		*vname,		/* vfstab file name */
	md_error_t	*ep		/* returned error */
)
{
	int		doit = 1;
	int		verbose = 0;
	char		*tvname = NULL;
	int		rval = -1;

	/* check names */
	assert(fsname != NULL);
	if (vname == NULL)
		vname = "/etc/vfstab";

	/* replace lines in vfstab */
	if (meta_patch_vfstab(fsname, fsnp, vname, NULL, doit, verbose, &tvname,
	    ep) != 0) {
		goto out;
	}

	/* rename temp file on top of real one */
	if (rename(tvname, vname) != 0) {
		(void) mdsyserror(ep, errno, vname);
		goto out;
	}
	Free(tvname);
	tvname = NULL;
	rval = 0;

	/* cleanup, return error */
out:
	if (tvname != NULL) {
		if (doit)
			(void) unlink(tvname);
		Free(tvname);
	}
	return (rval);
}
Пример #7
0
/*
 * Return the current root filesystem block device name
 */
void *
meta_get_current_root(
    md_error_t	*ep
)
{
    FILE		*fp;
    struct mnttab	mp;

    if ((fp = open_mnttab()) == NULL) {
        (void) mdsyserror(ep, errno, MNTTAB);
        return (NULL);
    }

    while (getmntent(fp, &mp) == 0) {
        if (strcmp(mp.mnt_mountp, "/") == 0)
            return (mp.mnt_special);
    }
    (void) mderror(ep, MDE_NOROOT, NULL);
    return (NULL);
}
Пример #8
0
/*
 * 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);
}
Пример #9
0
/*
 * patch filesystem lines into vfstab file, return tempfilename
 */
int
meta_patch_vfstab(
	char		*cmpname,	/* filesystem mount point or */
					/* "swap" if updating swap partition */
	mdname_t	*fsnp,		/* filesystem device name */
	char		*vname,		/* vfstab file name */
	char		*old_bdevname,	/* old name of block device, needed */
					/* for deciding which of multiple   */
					/* swap file entries to change	    */
					/* if NULL then not changing swap   */
	int		doit,		/* really patch file */
	int		verbose,	/* show what we're doing */
	char		**tname,	/* returned temp file name */
	md_error_t	*ep		/* returned error */
)
{
	char		*chrname = fsnp->rname;
	char		*blkname = fsnp->bname;
	FILE		*fp = NULL;
	FILE		*tfp = NULL;
	struct stat	sbuf;
	char		buf[512];
	char		cdev[512];
	char		bdev[512];
	char		mntpt[512];
	char		fstype[512];
	char		fsckpass[512];
	char		mntboot[512];
	char		mntopt[512];
	int		gotfs = 0;
	char		*cmpstr = &mntpt[0]; /* compare against mntpnt if fs, */
						/* or fstype if swap */
	char		*char_device = chrname;

	/* check names */
	assert(vname != NULL);
	assert(tname != NULL);

	/* get temp names */
	*tname = NULL;
	*tname = Malloc(strlen(vname) + strlen(".tmp") + 1);
	(void) strcpy(*tname, vname);
	(void) strcat(*tname, ".tmp");

	/* check if going to update swap entry in file */
	/* if so then compare against file system type */
	if ((old_bdevname != NULL) && (strcmp("swap", cmpname) == 0)) {
	    cmpstr = &fstype[0];
	    char_device = &cdev[0];
	}

	/* copy vfstab file, replace filesystem line */
	if ((fp = fopen(vname, "r")) == NULL) {
		(void) mdsyserror(ep, errno, vname);
		goto out;
	}
	if (fstat(fileno(fp), &sbuf) != 0) {
		(void) mdsyserror(ep, errno, vname);
		goto out;
	}
	if (doit) {
		if ((tfp = fopen(*tname, "w")) == NULL) {
			(void) mdsyserror(ep, errno, *tname);
			goto out;
		}
		if (fchmod(fileno(tfp), (sbuf.st_mode & 0777)) != 0) {
			(void) mdsyserror(ep, errno, *tname);
			goto out;
		}
		if (fchown(fileno(tfp), sbuf.st_uid, sbuf.st_gid) != 0) {
			(void) mdsyserror(ep, errno, *tname);
			goto out;
		}
	}
	while (fgets(buf, sizeof (buf), fp) != NULL) {

	    /* check that have all required params from vfstab file  */
	    /* or that the line isnt a comment	*/
	    /* or that the fstype/mntpoint match what was passed in  */
	    /* or that the block device matches if changing swap */
	    /* the last check is needed since there may be multiple  */
	    /* entries of swap in the file, and so the fstype is not */
	    /* a sufficient check */
		if ((sscanf(buf, "%512s %512s %512s %512s %512s %512s %512s",
		    bdev, cdev, mntpt, fstype, fsckpass,
		    mntboot, mntopt) != 7) ||
		    (bdev[0] == '#') || (strcmp(cmpstr, cmpname) != 0) ||
		    ((old_bdevname != NULL) &&
		    (strstr(bdev, old_bdevname) == NULL))) {
			if (doit) {
			    if (fputs(buf, tfp) == EOF) {
				(void) mdsyserror(ep, errno, *tname);
				goto out;
			    }
			}
			continue;
		}

		if (verbose) {
			(void) printf(dgettext(TEXT_DOMAIN,
			    "Delete the following line from %s:\n\n"),
			    vname);
			(void) printf("%s\n", buf);
			(void) printf(
			    dgettext(TEXT_DOMAIN,
			    "Add the following line to %s:\n\n"),
			    vname);
			(void) printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n\n",
				blkname, char_device, mntpt, fstype, fsckpass,
				mntboot, mntopt);
		}
		if (doit) {
		    if (fprintf(tfp, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
			blkname, char_device, mntpt, fstype, fsckpass,
			mntboot, mntopt) == EOF) {
			(void) mdsyserror(ep, errno, *tname);
			goto out;
		    }
		}


		gotfs = 1;
	}
	if (! feof(fp)) {
		(void) mdsyserror(ep, errno, vname);
		goto out;
	}
	if (! gotfs) {
		(void) mderror(ep, MDE_VFSTAB_FILE, vname);
		goto out;
	}
	if (fclose(fp) != 0) {
		(void) mdsyserror(ep, errno, vname);
		goto out;
	}
	fp = NULL;
	if (doit) {
		if ((fflush(tfp) != 0) ||
		    (fsync(fileno(tfp)) != 0) ||
		    (fclose(tfp) != 0)) {
			(void) mdsyserror(ep, errno, *tname);
			goto out;
		}
		tfp = NULL;
	}

	/* return success */
	return (0);

	/* cleanup, return error */
out:
	if (fp != NULL)
		(void) fclose(fp);
	if (tfp != NULL)
		(void) fclose(tfp);
	if (*tname != NULL) {
		(void) unlink(*tname);
		Free(*tname);
	}
	return (-1);
}
Пример #10
0
/*
 * check for overlap
 */
int
meta_check_overlap(
	char		*uname,		/* user supplied name for errors */
	mdname_t	*np1,		/* first comp */
	diskaddr_t	slblk1,		/* first comp - start logical block */
	diskaddr_t	nblks1,		/* first comp - # of blocks */
	mdname_t	*np2,		/* second comp */
	diskaddr_t	slblk2,		/* second comp - start logical block */
	diskaddr_t	nblks2,		/* second comp - # of blocks */
	md_error_t	*ep
)
{
	diskaddr_t	sblk1, sblk2;
	mdvtoc_t	*vtocp1, *vtocp2;
	uint_t		partno1, partno2;
	mdpart_t	*partp1, *partp2;
	int		ret;

	/* verify args */
	if (slblk1 == MD_DISKADDR_ERROR) {
		assert(0);
		return (mdsyserror(ep, EINVAL, np1->cname));
	}
	if (slblk2 == MD_DISKADDR_ERROR) {
		assert(0);
		return (mdsyserror(ep, EINVAL, np2->cname));
	}

	/* check for same drive */
	if ((ret = meta_check_samedrive(np1, np2, ep)) == 0) {
		return (0);			/* not same drive */
	} else if (ret < 0) {
		return (-1);			/* can't tell */
	}

	/* check for overlap */
	if (((vtocp1 = metagetvtoc(np1, FALSE, &partno1, ep)) == NULL) ||
	    ((vtocp2 = metagetvtoc(np2, FALSE, &partno2, ep)) == NULL)) {
		return (-1);			/* can't tell */
	}
	partp1 = &vtocp1->parts[partno1];
	partp2 = &vtocp2->parts[partno2];
	sblk1 = partp1->start + slblk1;
	if (nblks1 == -1)
		nblks1 = partp1->size - slblk1;
	sblk2 = partp2->start + slblk2;
	if (nblks2 == -1)
		nblks2 = partp2->size - slblk2;
	if (((sblk1 >= sblk2) && (sblk1 < (sblk2 + nblks2))) ||
	    ((sblk2 >= sblk1) && (sblk2 < (sblk1 + nblks1)))) {
		if (np1->dev == np2->dev) {	/* slice in use */
			return (mduseerror(ep, MDE_ALREADY, np1->dev,
			    uname, np1->cname));
		}
		if (ret == IDENTICAL_NAME_DEVT)
			return (mduseerror(ep,		/* slice overlaps */
			    MDE_OVERLAP, np1->dev, uname, np1->cname));
		else
			return (mduseerror(ep,		/* same devid */
			    MDE_SAME_DEVID, np1->dev, uname, np2->cname));
	}

	/* return success */
	return (0);				/* no overlap */
}
Пример #11
0
/*
 * 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);
}
Пример #12
0
/*
 * FUNCTION:	meta_replicaslice()
 * INPUT:	dnp	- the name of the drive to check
 * OUTPUT:	slicep	- pointer to slice number
 *		ep	- pointer to an md_error_t structure in which
 *			  to return errors to the caller
 * RETURNS:	int	-  0 - value pointed to by slicep is valid
 *			  -1 - otherwise
 *
 * PURPOSE:	Determine which slice of the specified drive to
 *		reserve, presumably for metadb replica usage.
 *
 * NOTE:	If slicep is NULL, the return code will indicate
 *		whether or not the slice number could be determined
 */
int
meta_replicaslice(
	mddrivename_t	*dnp,
	uint_t		*slicep,
	md_error_t	*ep
)
{
	int		err = 0;
	int		ioctl_return;
	int		fd;
	char		*rname;
	struct dk_geom	geom;

	rname = dnp->rname;
	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
		char	*n;
		int	open_errno;
		size_t	len;

		if (errno != ENOENT)
			return (mdsyserror(ep, errno, rname));

		len = strlen(rname) + 3;
		n = Zalloc(len);
		(void) snprintf(n, len, "%ss0", rname);
		fd = open(n, (O_RDONLY|O_NDELAY), 0);
		open_errno = errno;
		Free(n);
		if (fd < 0) {
			return (mdsyserror(ep, open_errno, rname));
		}
	}

	/*
	 * if our drivenamep points to a device not supporting
	 * DKIOCGGEOM, we have an EFI label.
	 */
	errno = 0;
	ioctl_return = ioctl(fd, DKIOCGGEOM, &geom);
	err = errno;

	(void) close(fd);

	/*
	 * If the DKIOCGGEOM ioctl succeeded, then the device has a
	 * VTOC style label.  In this case, we use slice 7.
	 */
	if (ioctl_return == 0) {
		if (slicep != NULL) {
			*slicep = MD_SLICE7;
		}
		return (0);
	}

	/*
	 * ENOTSUP indicates an EFI style label, in which case slice 7
	 * cannot be used because its minor number is reserved.  In
	 * this case, use slice 6.
	 */
	if (err == ENOTSUP) {
		if (slicep != NULL) {
			*slicep = MD_SLICE6;
		}
		return (0);
	}

	/*
	 * Those are the only two cases we know how to deal with;
	 * either the drivenamep didn't point to a disk, or the ioctl
	 * failed for some other reason.
	 */
	if (err == ENOTTY) {
		return (mddeverror(ep, MDE_NOT_DISK, NODEV, rname));
	}

	return (mdsyserror(ep, err, rname));
}
Пример #13
0
/*
 * save metadevice configuration in md.cf
 */
int
meta_update_md_cf(
	mdsetname_t	*sp,
	md_error_t	*ep
)
{
	char		*name = METACONF;
	char		*tname = METACONFTMP;
	FILE		*tfp = NULL;
	FILE		*mfp = NULL;
	mdprtopts_t	options = PRINT_SHORT | PRINT_FAST;
	struct stat	sbuf;
	char		line[1000];

	/* If this is not the local set, no need to do anything */
	if (!metaislocalset(sp))
		return (0);

	/* open temp file */
	if ((tfp = fopen(tname, "w")) == NULL)
		return (mdsyserror(ep, errno, tname));
	if (stat(name, &sbuf) == 0) {
		(void) fchmod(fileno(tfp), (sbuf.st_mode & 0777));
		(void) fchown(fileno(tfp), sbuf.st_uid, sbuf.st_gid);
	}

	/* dump header */
	if (fputs(dgettext(TEXT_DOMAIN,
	    "# metadevice configuration file\n"
	    "# do not hand edit\n"), tfp) == EOF) {
		(void) mdsyserror(ep, errno, tname);
		goto errout;
	}

	/* dump device configuration */
	if (meta_print_all(sp, tname, NULL, tfp, options, NULL, ep) != 0)
		goto errout;

	/* close and rename file */
	if (fclose(tfp) != 0) {
		(void) mdsyserror(ep, errno, tname);
		goto errout;
	}
	tfp = NULL;

	/*
	 * Renames don't work in the miniroot since tmpfiles are
	 * created in /var/tmp. Hence we copy the data out.
	 */

	if (rename(tname, name) != 0) {
		if (errno == EROFS) {
			if ((tfp = fopen(tname, "r")) == NULL) {
				goto errout;
			}
			if ((mfp = fopen(METACONF, "w+")) == NULL) {
				goto errout;
			}
			while (fgets(line, 1000, tfp) != NULL) {
				if (fputs(line, mfp) == NULL) {
					(void) mdsyserror(ep, errno, METACONF);
					goto errout;
				}
			}
			if (fclose(tfp) != 0) {
				tfp = NULL;
				goto errout;
			}
			tfp = NULL;
			/* delete the tempfile */
			(void) unlink(tname);
			if (fflush(mfp) != 0) {
				goto errout;
			}
			if (fsync(fileno(mfp)) != 0) {
				goto errout;
			}
			if (fclose(mfp) != 0) {
				mfp = NULL;
				goto errout;
			}
			mfp = NULL;
		} else {
			(void) mdsyserror(ep, errno, name);
			goto errout;
		}
	}

	/* success */
	return (0);

	/* cleanup, return error */
errout:
	if (tfp != NULL) {
		(void) fclose(tfp);
		(void) unlink(tname);
	}
	if (mfp != NULL) {
		(void) fclose(mfp);
	}
	return (-1);
}
Пример #14
0
/*
 * setup RPC service
 *
 * if can't authenticate return < 0
 * any other error return > 0
 */
int
svc_init(
	struct svc_req	*rqstp,	/* RPC stuff */
	int		amode,	/* R_OK | W_OK */
	md_error_t	*ep	/* returned status */
)
{
	SVCXPRT		*transp;

	if (sdssc_bind_library() == SDSSC_ERROR) {
		mdsyserror(ep, EACCES, "can't bind to cluster library");
		return (1);
	}

	/*
	 * if we have no rpc service info, we must have been
	 * called recursively from within the daemon
	 */
	if (rqstp == NULL) {
		mdclrerror(ep);
		return (0);		/* OK */
	}

	/*
	 * initialize
	 */
	transp = rqstp->rq_xprt;
	assert(transp != NULL);
	*ep = mdnullerror;

	/*
	 * check credentials
	 */
	switch (rqstp->rq_cred.oa_flavor) {

	/* UNIX flavor */
	case AUTH_SYS:
	{
		if (check_sys(rqstp, amode, ep) != 0)
			return (1);	/* error */
		break;
	}

	/* can't authenticate anything else */
	default:
		svcerr_weakauth(transp);
		return (-1);		/* weak authentication */
	}

	/*
	 * (re)initialize
	 */
	if (md_init_daemon("rpc.metad", ep) != 0)
		return (1);		/* error */

	if (set_snarf(ep))
		return (1);

	sr_validate();

	/* success */
	return (0);
}
Пример #15
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);
}