/* * 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)); } }
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); }
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); }
/* * 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); }
/* * 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); }