1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdarg.h> 31 #include <ctype.h> 32 #include <sys/fcntl.h> 33 #include <sys/types.h> 34 #include <devid.h> 35 #include <ftw.h> 36 #include <string.h> 37 #include <mdiox.h> 38 #include <sys/lvm/mdio.h> 39 #include <meta.h> 40 #include <syslog.h> 41 #include <sdssc.h> 42 43 /* 44 * print usage message 45 */ 46 static void 47 usage(char *myname) 48 { 49 (void) fprintf(stderr, gettext( 50 "usage: %s -h\n" 51 " %s [-s setname] -r [-lnv]\n" 52 " %s [-s setname] -u cxtxdx [-lnv]\n"), 53 myname, myname, myname); 54 } 55 56 int 57 main(int argc, char **argv) 58 { 59 char c; 60 char *sname = MD_LOCAL_NAME; 61 mddevopts_t options = 0; 62 md_error_t status = mdnullerror; 63 md_error_t *ep = &status; 64 mdsetname_t *sp = NULL; 65 mdsetname_t *local_sp = NULL; 66 char *argname; 67 int todo = 0; 68 int ret = 0; 69 int md_upgd_stat = 0; 70 int error; 71 md_set_desc *sd; 72 73 /* 74 * Get the locale set up before calling any other routines 75 * with messages to ouput. Just in case we're not in a build 76 * environment, make sure that TEXT_DOMAIN gets set to 77 * something. 78 */ 79 #if !defined(TEXT_DOMAIN) 80 #define TEXT_DOMAIN "SYS_TEST" 81 #endif 82 (void) setlocale(LC_ALL, ""); 83 (void) textdomain(TEXT_DOMAIN); 84 85 if ((sdssc_bind_library() == SDSSC_OKAY) && 86 (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY, 87 &error) == SDSSC_PROXY_DONE)) 88 exit(error); 89 90 openlog("metadevadm", LOG_ODELAY, LOG_USER); 91 92 /* initialize */ 93 if (md_init(argc, argv, 0, 1, ep) != 0 || 94 meta_check_root(ep) != 0) { 95 closelog(); 96 mde_perror(ep, ""); 97 md_exit(sp, 1); 98 } 99 100 /* parse args */ 101 optind = 1; 102 opterr = 1; 103 while ((c = getopt(argc, argv, "vlhnrs:u:")) != -1) { 104 switch (c) { 105 case 'v': 106 options |= DEV_VERBOSE; 107 break; 108 case 'n': 109 options |= DEV_NOACTION; 110 break; 111 case 'r': 112 options |= DEV_RELOAD; 113 todo = 1; 114 break; 115 case 's': 116 sname = optarg; 117 break; 118 case 'u': 119 todo = 1; 120 options |= DEV_UPDATE; 121 argname = optarg; 122 if (argname == NULL) { 123 usage("metadevadm"); 124 closelog(); 125 md_exit(sp, 0); 126 } 127 break; 128 case 'l': 129 options |= DEV_LOG; 130 break; 131 case 'h': 132 default: 133 usage("metadevadm"); 134 closelog(); 135 md_exit(sp, 0); 136 } 137 } 138 139 if ((sp = metasetname(sname, ep)) == NULL) { 140 mde_perror(ep, ""); 141 closelog(); 142 md_exit(sp, 1); 143 } 144 145 if (!metaislocalset(sp)) { 146 if ((sd = metaget_setdesc(sp, ep)) == NULL) { 147 mde_perror(ep, ""); 148 closelog(); 149 md_exit(sp, 1); 150 } 151 if (MD_MNSET_DESC(sd)) { 152 printf("%s\n", gettext("metadevadm cannot be " 153 "run on multi-owner disksets\n")); 154 closelog(); 155 md_exit(sp, 0); 156 } 157 } 158 159 if ((options & DEV_VERBOSE) && (todo != 1)) { 160 usage("metadevadm"); 161 closelog(); 162 md_exit(sp, 0); 163 } 164 165 if ((options & DEV_NOACTION) && (todo != 1)) { 166 usage("metadevadm"); 167 closelog(); 168 md_exit(sp, 0); 169 } 170 171 if (todo == 0) { 172 usage("metadevadm"); 173 closelog(); 174 md_exit(sp, 0); 175 } 176 177 if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) { 178 mde_perror(ep, ""); 179 closelog(); 180 md_exit(local_sp, 1); 181 } 182 183 /* lock the local set */ 184 if (meta_lock(local_sp, TRUE, ep) != 0) { 185 mde_perror(ep, ""); 186 closelog(); 187 md_exit(local_sp, 1); 188 } 189 190 /* grab set lock */ 191 if (meta_lock(sp, TRUE, ep)) { 192 mde_perror(ep, ""); 193 closelog(); 194 md_exit(local_sp, 1); 195 } 196 197 /* check for ownership */ 198 if (meta_check_ownership(sp, ep) != 0) { 199 /* 200 * If the set is not owned by this node then only update the 201 * local set's replica. 202 */ 203 options |= DEV_LOCAL_SET; 204 } 205 206 /* 207 * check for upgrade. If upgrade in progress then just exit. 208 */ 209 if (metaioctl(MD_UPGRADE_STAT, &md_upgd_stat, ep, NULL) != 0) { 210 mde_perror(ep, ""); 211 closelog(); 212 (void) meta_unlock(sp, ep); 213 md_exit(local_sp, 1); 214 } 215 if (md_upgd_stat == 0) { 216 ret = meta_fixdevid(sp, options, argname, ep); 217 if (ret == METADEVADM_ERR) { 218 /* 219 * If the call failed, for a DEV_RELOAD still need to 220 * update the .conf file to provide the latest devid 221 * information so exit later. 222 */ 223 if (options & DEV_UPDATE) { 224 closelog(); 225 (void) meta_unlock(sp, ep); 226 md_exit(local_sp, 1); 227 } 228 } 229 } 230 231 /* 232 * Sync replica list in kernel to replica list in conf files. 233 * This will update driver name and minor number in conf file 234 * if reload was run. Will update device id in conf file if 235 * update was run. 236 */ 237 meta_sync_db_locations(sp, ep); 238 closelog(); 239 (void) meta_unlock(sp, ep); 240 md_exit(local_sp, ret); 241 return (0); 242 } 243