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 /* 30 * sync metadevices 31 */ 32 33 #include <meta.h> 34 35 #include <sys/lvm/md_mirror.h> 36 37 #include <ctype.h> 38 39 #include <sdssc.h> 40 41 /* 42 * print usage message 43 */ 44 static void 45 usage( 46 mdsetname_t *sp, 47 int eval 48 ) 49 { 50 (void) fprintf(stderr, gettext("\ 51 usage: %s [-s setname] -r [buffer_size]\n\ 52 %s [-s setname] [buffer_size] metadevices...\n\ 53 %s [-s setname] -c metadevices...\n"), 54 myname, myname, myname); 55 md_exit(sp, eval); 56 } 57 58 /* 59 * crack command line arguments. 60 */ 61 int 62 main( 63 int argc, 64 char *argv[] 65 ) 66 { 67 char *sname = NULL; 68 mdsetname_t *sp = NULL; 69 int rflag = 0; 70 int pflag = 0; 71 daddr_t size = 0; 72 int c; 73 md_error_t status = mdnullerror; 74 md_error_t *ep = &status; 75 int rval = 0; 76 int error; 77 md_resync_cmd_t resync_cmd = MD_RESYNC_START; 78 bool_t called_thru_rpc = FALSE; 79 char *cp; 80 int mn_set = FALSE; 81 int cflag = 0; 82 83 /* 84 * Get the locale set up before calling any other routines 85 * with messages to ouput. Just in case we're not in a build 86 * environment, make sure that TEXT_DOMAIN gets set to 87 * something. 88 */ 89 #if !defined(TEXT_DOMAIN) 90 #define TEXT_DOMAIN "SYS_TEST" 91 #endif 92 (void) setlocale(LC_ALL, ""); 93 (void) textdomain(TEXT_DOMAIN); 94 95 if ((cp = strstr(argv[0], ".rpc_call")) == NULL) { 96 if (sdssc_bind_library() == SDSSC_OKAY) 97 if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY, 98 &error) == SDSSC_PROXY_DONE) 99 exit(error); 100 } else { 101 *cp = '\0'; /* cut off ".rpc_call" */ 102 called_thru_rpc = TRUE; 103 } 104 105 106 /* initialize */ 107 if (md_init(argc, argv, 0, 1, ep) != 0 || 108 meta_check_root(ep) != 0) { 109 mde_perror(ep, ""); 110 md_exit(sp, 1); 111 } 112 113 /* parse args */ 114 optind = 1; 115 opterr = 1; 116 while ((c = getopt(argc, argv, "phs:rc?")) != -1) { 117 switch (c) { 118 case 'h': 119 usage(sp, 0); 120 break; 121 122 case 's': 123 sname = optarg; 124 break; 125 126 case 'r': 127 ++rflag; 128 break; 129 130 case 'p': 131 ++pflag; 132 break; 133 134 case 'c': 135 ++cflag; 136 resync_cmd = MD_RESYNC_KILL; 137 break; 138 139 case '?': 140 if (optopt == '?') 141 usage(sp, 0); 142 /*FALLTHROUGH*/ 143 default: 144 usage(sp, 1); 145 break; 146 } 147 } 148 if ((pflag + rflag) > 1) { 149 usage(sp, 1); 150 mde_perror(ep, ""); 151 md_exit(sp, 1); 152 } 153 argc -= optind; 154 argv += optind; 155 156 if (sname != NULL) { 157 if ((sp = metasetname(sname, ep)) == NULL) { 158 mde_perror(ep, ""); 159 md_exit(sp, 1); 160 } 161 } 162 163 /* 164 * look for buffer size. If one is not specified we pass '0' to 165 * the meta_resync_all() call. This uses whatever size has been 166 * configured via md_mirror:md_resync_bufsz 167 * The default value (if not overridden in /etc/system) is 168 * MD_DEF_RESYNC_BUF_SIZE 169 */ 170 if ((argc > 0) && (isdigit(argv[0][0]))) { 171 if ((size = atoi(argv[optind++])) < 0) { 172 md_eprintf(gettext( 173 "illegal buffer size %s\n"), 174 argv[0]); 175 md_exit(sp, 1); 176 } 177 --argc; 178 ++argv; 179 } 180 181 /* sync all devices in set */ 182 if (rflag) { 183 /* get set */ 184 if (argc != 0) 185 usage(sp, 1); 186 if ((sp == NULL) && 187 ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) && 188 (metaget_setdesc(sp, ep) == NULL)) { 189 mde_perror(ep, ""); 190 md_exit(sp, 1); 191 } 192 193 assert(sp != NULL); 194 /* 195 * For a MN set "metasync -r" can only be called by the 196 * initiator. We must not take the set lock for a MN set as 197 * it will only generate individual metasync commands which 198 * will individually take the lock when executing the 199 * individual metasync commands. 200 * Therefore only take the set lock for non MN sets. 201 */ 202 if (meta_is_mn_set(sp, ep) == 0) { 203 /* grab set lock */ 204 if (meta_lock(sp, TRUE, ep)) { 205 mde_perror(ep, ""); 206 md_exit(sp, 1); 207 } 208 209 /* check for ownership */ 210 if (meta_check_ownership(sp, ep) != 0) { 211 mde_perror(ep, ""); 212 md_exit(sp, 1); 213 } 214 } 215 /* resync all metadevices in set */ 216 if (meta_resync_all(sp, size, ep) != 0) { 217 mde_perror(ep, ""); 218 md_exit(sp, 1); 219 } 220 md_exit(sp, 0); 221 } 222 223 /* sync specified metadevices */ 224 if (argc <= 0) 225 usage(sp, 1); 226 227 /* 228 * Note that if sp is NULL, meta_is_mn_name() derives sp 229 * from argv[0] which is the metadevice arg 230 */ 231 if (meta_is_mn_name(&sp, argv[0], ep)) 232 mn_set = TRUE; 233 234 for (; (argc > 0); --argc, ++argv) { 235 mdname_t *np; 236 int result; 237 238 /* get device */ 239 if ((np = metaname(&sp, argv[0], ep)) == NULL) { 240 mde_perror(ep, ""); 241 rval = -1; 242 continue; 243 } 244 assert(sp != NULL); 245 246 /* 247 * If we are not called through an rpc call and the 248 * set associated with the command is an MN set, send 249 * a setsync message to the master of the set and let it 250 * deal with it. 251 */ 252 if (!called_thru_rpc && mn_set) { 253 if ((result = meta_mn_send_setsync(sp, np, size, 254 ep)) != 0) { 255 mde_perror(ep, "Unable to start resync"); 256 md_exit(sp, result); 257 } 258 continue; 259 } 260 261 /* grab set lock */ 262 if (meta_lock(sp, TRUE, ep)) { 263 mde_perror(ep, ""); 264 md_exit(sp, 1); 265 } 266 267 /* check for ownership */ 268 if (meta_check_ownership(sp, ep) != 0) { 269 mde_perror(ep, ""); 270 md_exit(sp, 1); /* no point in continuing */ 271 } 272 273 /* resync or regen (raid only) metadevice */ 274 if (pflag) { 275 /* regen */ 276 if (meta_raid_regen_byname(sp, np, size, ep) != 0) { 277 mde_perror(ep, ""); 278 rval = -1; 279 continue; 280 } 281 } else { 282 if (meta_resync_byname(sp, np, size, ep, resync_cmd) 283 != 0) { 284 mde_perror(ep, ""); 285 rval = -1; 286 continue; 287 } 288 } 289 } 290 291 /* return success */ 292 md_exit(sp, rval); 293 /*NOTREACHED*/ 294 return (rval); 295 } 296