Example #1
0
/*
 * 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));
	}
}
Example #2
0
static void
metahalt()
{
	mdsetname_t	*sp;
	md_error_t status = mdnullerror;

	(void) init_metalib();
	if ((sp = metasetname(MD_LOCAL_NAME, &status)) == NULL) {
		return;
	}
	if (meta_lock(sp, TRUE, &status)) {
		return;
	}
	if (metaioctl(MD_HALT, NULL, &status, NULL) != 0) {
		debug_printf("metahalt(): errno %d\n",
			status.info.md_error_info_t_u.sys_error.errnum);
	}
	(void) meta_unlock(sp, &status);
	reset_metalib(&status);
}
Example #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);
}
Example #4
0
/*
 * initialize all devices in set
 */
static int
init_all(
	mdsetname_t	**spp,
	mdcmdopts_t	options,
	bool_t		called_thru_rpc,
	md_error_t	*ep
)
{
	md_tab_t	*tabp = NULL;
	size_t		setlen;
	uint_t		more;
	int		done;
	int		eval = -1;

	/*
	 * Only take the lock if this is not a MN set
	 * We can only enter this code for a MN set if we are the initiator
	 * and in this case, we don't want to take locks.
	 */
	if (meta_is_mn_set((*spp), ep) == 0) {
		/* grab set lock */
		if (meta_lock(*spp, TRUE, ep)) {
			mde_perror(ep, "");
			mdclrerror(ep);
			return (eval);
		}

		/* check for ownership */
		if (meta_check_ownership(*spp, ep) != 0) {
			mde_perror(ep, "");
			mdclrerror(ep);
			return (eval);
		}

		/* lock is held across init_entries */
		options |= MDCMD_NOLOCK;
	}

	/* get md.tab, preen entries */
	if ((tabp = meta_tab_parse(NULL, ep)) == NULL) {
		mde_perror(ep, "");
		mdclrerror(ep);
		return (eval);
	}

	setlen = strlen((*spp)->setname);
	for (more = 0; (more < tabp->nlines); ++more) {
		md_tab_line_t	*linep = &tabp->lines[more];
		char		*cname = linep->cname;
		char		*p;
		size_t		len;

		/* better have args */
		assert((linep->argc > 0) && (linep->argv[0] != NULL));

		/* only do metadevices and hotspare pools in set */
		if (linep->type & TAB_MD_HSP) {
			if ((p = strrchr(cname, '/')) == NULL) {
				len = 0;
			} else {
				len = p - cname;
			}
			if ((len == setlen) &&
			    (strncmp(cname, (*spp)->setname, len) == 0)) {
				linep->flags = DO_AGAIN;
			} else {
				linep->flags = DONT_DO;
			}

		} else {
			linep->flags = DONT_DO;
		}
	}

	eval = 1;

	/* while more devices get made */
	do {
		done = init_entries(spp, tabp, options,
		    MD_IGNORE_STDERR|MD_RETRY_BUSY, called_thru_rpc, ep);
	} while (done > 0);

	/* now do it and report errors */
	if (init_entries(spp, tabp, options, MD_RETRY_BUSY,
	    called_thru_rpc, ep) >= 0)
		eval = 0;	/* success */
	mdclrerror(ep);

	/* cleanup, return success */
out:
	meta_tab_free(tabp);
	return (eval);
}
Example #5
0
/*
 * 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);
}