예제 #1
0
void
create_diskset_links()
{
	int		max_sets;
	int		i;
	md_error_t	error = mdnullerror;

	/*
	 * Resolve the function pointers for libsds_sc so that we can
	 * snarf the set records.
	 */
	(void) sdssc_bind_library();
	(void) init_metalib();

	if ((max_sets = get_max_sets(&error)) == 0) {
		debug_printf("create_diskset_links(): get_max_sets failed\n");
		mdclrerror(&error);
		return;
	}

	for (i = 1; i < max_sets; i++) {
		md_set_record	*sr;
		char		setname[MAXPATHLEN];
		char		setnum[MAXPATHLEN];

		if ((sr = metad_getsetbynum(i, &error)) == NULL) {
			mdclrerror(&error);
			continue;
		}

		(void) snprintf(setname, MAXPATHLEN, "/dev/md/%s",
		    sr->sr_setname);
		(void) snprintf(setnum, MAXPATHLEN, "shared/%d", i);
		/*
		 * Ignore failures to create the symlink.  This could
		 * happen because suninstall is restartable so the
		 * symlink might have already been created.
		 */
		(void) symlink(setnum, setname);
	}
}
예제 #2
0
/*
 * For the admin device:
 *	/dev/md/admin -> /devices/pseudo/md@0:admin
 *
 * For metadevice:
 *	/dev/md/dsk/foobar --> /devices/pseudo/md@0:0,100,blk
 *	/dev/md/rdsk/foobar --> /devices/pseudo/md@0:0,100,raw
 *
 * Where 'foobar' is user specified arbitrary name and '100'
 * is the minor number returned by MD_IOCMAKE_DEV ioctl
 *
 */
static int
md_create(di_minor_t minor, di_node_t node)
{
	char mn[MAXNAMELEN + 1];
	char path[PATH_MAX + 1];
	char set_path[PATH_MAX +1];
	char sym_path[PATH_MAX + 1];
	int set = -1, ret;
	char *type, *dir;
	char *device_name;
	dev_t minor_devt = di_minor_devt(minor);
	int key;
	mdsetname_t	*sp = NULL;
	md_error_t ep;

	/*
	 * Initialize sdssc entry points. Don't worry about the return
	 * value here since the interface functions will get initialized
	 * correctly regardless.
	 */
	(void) sdssc_bind_library();

	(void) strcpy(mn, di_minor_name(minor));

	/*
	 * Check whether we are being requested to setup the admin
	 * device link or one of the metadevice links. They need
	 * to be treated differently.
	 */

	if (strcmp(mn, "admin") == 0) {
		/* there is only one admin link and always in /dev/md/admin */
		(void) devfsadm_mklink("md/admin", node, minor, 0);
	} else {
		/*
		 * Extract out the minor components and create the
		 * appropriate links. The node looks like:
		 * md@<set>,<mdev>,<type>
		 * where the <set> number is the named diskset,
		 * <mdev> is the metadevice number, and <type>
		 * is the trailing "blk" or "raw" indication.
		 *
		 * NOTE: when <set> is non-zero, we need to create
		 * under the "shared" directory entry instead of linking
		 * into the top level dsk/rdsk directories.
		 */
		ret = sscanf(mn, "%d,", &set);
		if (ret == 1 && (type = strrchr(mn, ',')) != NULL) {
			type++;
			if (strcmp(type, "blk") == 0) {
				dir = "dsk";
			} else {
				dir = "rdsk";
			}

			(void) memset(&ep, '\0', sizeof (ep));
			if ((device_name = meta_getnmentbydev(set,
			    MD_SIDEWILD, minor_devt, NULL, NULL,
			    &key, &ep)) == NULL) {
				(void) close_admin(&ep);
				return (DEVFSADM_CONTINUE);
			}

			if (set == 0) {
				/* this is a simple md */
				(void) snprintf(path, sizeof (path),
				    "md/%s/%s", dir, basename(device_name));
			} else {
				/* this is a shared md */
				(void) snprintf(path, sizeof (path),
				    "md/shared/%d/%s/%s", set, dir,
				    basename(device_name));

				/*
				 * flush the caches so the next call to
				 * metasetnosetname will get us the
				 * updated cache.
				 */
				metaflushnames(0);
				if ((sp = metasetnosetname(set, &ep))
				    != NULL) {
					(void) snprintf(set_path,
					    sizeof (set_path), "md/shared/%d",
					    sp->setno);
					(void) snprintf(sym_path,
					    sizeof (sym_path), "md/%s",
					    sp->setname);
				}
			}
			(void) devfsadm_mklink(path, node, minor, 0);
			Free(device_name);

			if (sp != NULL) {
				(void) devfsadm_secondary_link(sym_path,
				    set_path, 0);
			}
		}
	}

	(void) close_admin(&ep);
	return (DEVFSADM_CONTINUE);
}
예제 #3
0
int
main(int argc, char **argv)
{
	char		c;
	char		*sname = MD_LOCAL_NAME;
	mddevopts_t	options = 0;
	md_error_t	status = mdnullerror;
	md_error_t	*ep = &status;
	mdsetname_t	*sp = NULL;
	mdsetname_t	*local_sp = NULL;
	char		*argname;
	int		todo = 0;
	int		ret = 0;
	int		md_upgd_stat = 0;
	int		error;
	md_set_desc	*sd;

	/*
	 * Get the locale set up before calling any other routines
	 * with messages to ouput.  Just in case we're not in a build
	 * environment, make sure that TEXT_DOMAIN gets set to
	 * something.
	 */
#if !defined(TEXT_DOMAIN)
#define	TEXT_DOMAIN "SYS_TEST"
#endif
	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);

	if ((sdssc_bind_library() == SDSSC_OKAY) &&
	    (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY,
	    &error) == SDSSC_PROXY_DONE))
		exit(error);

	openlog("metadevadm", LOG_ODELAY, LOG_USER);

	/* initialize */
	if (md_init(argc, argv, 0, 1, ep) != 0 ||
	    meta_check_root(ep) != 0) {
		closelog();
		mde_perror(ep, "");
		md_exit(sp, 1);
	}

	/* parse args */
	optind = 1;
	opterr = 1;
	while ((c = getopt(argc, argv, "vlhnrs:u:")) != -1) {
		switch (c) {
		case 'v':
			options |= DEV_VERBOSE;
			break;
		case 'n':
			options |= DEV_NOACTION;
			break;
		case 'r':
			options |= DEV_RELOAD;
			todo = 1;
			break;
		case 's':
			sname = optarg;
			break;
		case 'u':
			todo = 1;
			options |= DEV_UPDATE;
			argname = optarg;
			if (argname == NULL) {
				usage("metadevadm");
				closelog();
				md_exit(sp, 0);
			}
			break;
		case 'l':
			options |= DEV_LOG;
			break;
		case 'h':
		default:
			usage("metadevadm");
			closelog();
			md_exit(sp, 0);
		}
	}

	if ((sp = metasetname(sname, ep)) == NULL) {
		mde_perror(ep, "");
		closelog();
		md_exit(sp, 1);
	}

	if (!metaislocalset(sp)) {
		if ((sd = metaget_setdesc(sp, ep)) == NULL) {
			mde_perror(ep, "");
			closelog();
			md_exit(sp, 1);
		}
		if (MD_MNSET_DESC(sd)) {
			(void) printf("%s\n", gettext("metadevadm cannot be "
			    "run on multi-owner disksets\n"));
			closelog();
			md_exit(sp, 0);
		}
	}

	if ((options & DEV_VERBOSE) && (todo != 1)) {
		usage("metadevadm");
		closelog();
		md_exit(sp, 0);
	}

	if ((options & DEV_NOACTION) && (todo != 1)) {
		usage("metadevadm");
		closelog();
		md_exit(sp, 0);
	}

	if (todo == 0) {
		usage("metadevadm");
		closelog();
		md_exit(sp, 0);
	}

	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
		mde_perror(ep, "");
		closelog();
		md_exit(local_sp, 1);
	}

	/* lock the local set */
	if (meta_lock(local_sp, TRUE, ep) != 0) {
		mde_perror(ep, "");
		closelog();
		md_exit(local_sp, 1);
	}

	/* grab set lock */
	if (meta_lock(sp, TRUE, ep)) {
		mde_perror(ep, "");
		closelog();
		md_exit(local_sp, 1);
	}

	/* check for ownership */
	if (meta_check_ownership(sp, ep) != 0) {
		/*
		 * If the set is not owned by this node then only update the
		 * local set's replica.
		 */
		options |= DEV_LOCAL_SET;
	}

	/*
	 * check for upgrade. If upgrade in progress then just exit.
	 */
	if (metaioctl(MD_UPGRADE_STAT, &md_upgd_stat, ep, NULL) != 0) {
			mde_perror(ep, "");
			closelog();
			(void) meta_unlock(sp, ep);
			md_exit(local_sp, 1);
	}
	if (md_upgd_stat == 0) {
		ret = meta_fixdevid(sp, options, argname, ep);
		if (ret == METADEVADM_ERR) {
			/*
			 * If the call failed, for a DEV_RELOAD still need to
			 * update the .conf file to provide the latest devid
			 * information so exit later.
			 */
			if (options & DEV_UPDATE) {
				closelog();
				(void) meta_unlock(sp, ep);
				md_exit(local_sp, 1);
			}
		}
	}

	/*
	 * Sync replica list in kernel to replica list in conf files.
	 * This will update driver name and minor number in conf file
	 * if reload was run.  Will update device id in conf file if
	 * update was run.
	 */
	meta_sync_db_locations(sp, ep);
	closelog();
	(void) meta_unlock(sp, ep);
	md_exit(local_sp, ret);
	return (0);
}
예제 #4
0
파일: metad_init.c 프로젝트: alhazred/onarm
/*
 * 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);
}
예제 #5
0
파일: metaclear.c 프로젝트: andreiw/polaris
/*
 * mainline.   crack command line arguments.
 */
int
main(
	int		argc,
	char		*argv[]
)
{
	char		*sname = MD_LOCAL_NAME;
	mdsetname_t	*sp = NULL;
	int		aflag = 0;
	int		pflag = 0;
	int		set_flag = 0;
	mdcmdopts_t	options = (MDCMD_PRINT|MDCMD_DOIT);
	int		c;
	md_error_t	status = mdnullerror;
	md_error_t	*ep = &status;
	int		eval = 1;
	int		error;
	bool_t		called_thru_rpc = FALSE;
	char		*cp;
	int		mnset = FALSE;

	/*
	 * Get the locale set up before calling any other routines
	 * with messages to ouput.  Just in case we're not in a build
	 * environment, make sure that TEXT_DOMAIN gets set to
	 * something.
	 */
#if !defined(TEXT_DOMAIN)
#define	TEXT_DOMAIN "SYS_TEST"
#endif
	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);

	if ((cp = strstr(argv[0], ".rpc_call")) == NULL) {
		if (sdssc_bind_library() == SDSSC_OKAY)
			if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY,
						&error) == SDSSC_PROXY_DONE)
				exit(error);
	} else {
		*cp = '\0'; /* cut off ".rpc_call" */
		called_thru_rpc = TRUE;
	}


	/* initialize */
	if (md_init(argc, argv, 0, 1, ep) != 0 ||
			meta_check_root(ep) != 0)
		goto errout;

	/* parse args */
	optind = 1;
	opterr = 1;
	while ((c = getopt(argc, argv, "hs:afrp?")) != -1) {
		switch (c) {
		case 'h':
			usage(sp, 0);
			break;

		case 's':
			sname = optarg;
			set_flag++;
			break;

		case 'a':
			++aflag;
			options |= MDCMD_FORCE;
			break;

		case 'f':
			options |= MDCMD_FORCE;
			break;

		case 'r':
			options |= MDCMD_RECURSE | MDCMD_FORCE;
			break;
		case 'p':
			++pflag;
			break;
		case '?':
			if (optopt == '?')
				usage(sp, 0);
			/*FALLTHROUGH*/
		default:
			usage(sp, 1);
			break;
		}
	}
	argc -= optind;
	argv += optind;

	/* with mn sets if -a, set name must have been specified by -s */
	if (called_thru_rpc && aflag && !set_flag) {
		md_eprintf(gettext(
		    "-a parameter requires the use of -s in multi-node sets"));
		md_exit(sp, 1);
	}

	/* get set context */
	if ((sp = metasetname(sname, ep)) == NULL) {
		mde_perror(ep, "");
		md_exit(sp, 1);
	}

	if (called_thru_rpc) {
		/* Check if the device is open  on all nodes */
		options |= MDCMD_MN_OPEN_CHECK;
	}

	if (aflag) {	/* clear all devices */
		if (argc != 0)
			usage(sp, 1);

		/*
		 * If a MN set, we will generate a series of individual
		 * metaclear commands which will each grab the set lock.
		 * Therefore do not grab the set lock now.
		 */

		if (!meta_is_mn_set(sp, ep)) {
			/* grab set lock */
			if (meta_lock(sp, TRUE, ep))
				goto errout;

			/* check for ownership */
			if (meta_check_ownership(sp, ep) != 0)
				goto errout;
		} else {
			mnset = TRUE;
		}

		/* reset all devices in set */
		if (meta_reset_all(sp, options, ep) != 0) {
			if (!mnset)
				mde_perror(ep, "");
		} else
			eval = 0;
	} else {
		/*
		 * We are dealing with either a single or multiple names.
		 * The set for the command is either denoted by the -s option
		 * or the set of the first name.
		 */
		if (argc <= 0)
			usage(sp, 1);

		if (meta_is_mn_name(&sp, argv[0], ep))
			mnset = TRUE;
		eval = 0;

		for (; (argc > 0); --argc, ++argv) {
			char		*cname;

			/*
			 * If we are dealing with a MN set and we were not
			 * called thru an rpc call, we are just to send this
			 * command string to the master of the set and let it
			 * deal with it.
			 */
			if (!called_thru_rpc && mnset) {
				/* get the canonical name */
				if (pflag) {
					/*
					 * If -p, set cname to the device
					 * argument.
					 */
					cname = Strdup(argv[0]);
				} else {
					/*
					 * For hotspares and metadevices, set
					 * cname to the full name,
					 * setname/hspxxx or setname/dxxx
					 */
					cname = meta_name_getname(&sp,
					    argv[0], META_DEVICE, ep);
					if (cname == NULL) {
						mde_perror(ep, "");
						eval = 1;
						continue;
					}
				}
				if (meta_mn_send_metaclear_command(sp,
				    cname, options, pflag, ep) != 0) {
					eval = 1;
				}
				Free(cname);
			} else {
				if (pflag) {
					/*
					 * clear all soft partitions on named
					 * devices
					 */
					if (meta_sp_reset_component(sp, argv[0],
					    options, ep) != 0) {
						mde_perror(ep, "");
						eval = 1;
						continue;
					}
				} else {
					/*
					 * get the canonical name and
					 * setup sp if it has been
					 * specified as part of the
					 * metadevice/hsp name param
					 */
					cname = meta_name_getname(&sp,
					    argv[0], META_DEVICE, ep);
					if (cname == NULL) {
						mde_perror(ep, "");
						eval = 1;
						continue;
					}

					/* clear named devices */
					if (clear_name(&sp, cname,
					    options, ep) != 0) {
						mde_perror(ep, "");
						eval = 1;
						Free(cname);
						continue;
					}
					Free(cname);
				}
			}
		}
	}
	/* update md.cf */
	if (meta_update_md_cf(sp, ep) != 0) {
		mde_perror(ep, "");
		eval = 1;
	}
	md_exit(sp, eval);

errout:
	mde_perror(ep, "");
	md_exit(sp, eval);
	/*NOTREACHED*/
	return (eval);
}
예제 #6
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);
}