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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*
29 * detach submirrors
30 */
31
32 #include <meta.h>
33
34 #include <sdssc.h>
35
36 /*
37 * print usage message
38 */
39 static void
usage(mdsetname_t * sp,int eval)40 usage(
41 mdsetname_t *sp,
42 int eval
43 )
44 {
45 (void) fprintf(stderr, gettext("\
46 usage: %s [-s setname] [-f] mirror submirror\n\
47 %s [-s setname] [-f] trans\n"),
48 myname, myname);
49 md_exit(sp, eval);
50 }
51
52 /*
53 * detach submirror from mirror
54 */
55 static int
mirror_detach(mdsetname_t ** spp,mdname_t * mirnp,int argc,char * argv[],mdcmdopts_t options,md_error_t * ep)56 mirror_detach(
57 mdsetname_t **spp,
58 mdname_t *mirnp,
59 int argc,
60 char *argv[],
61 mdcmdopts_t options,
62 md_error_t *ep
63 )
64 {
65 mdname_t *submirnp;
66 int c;
67
68 /* reset and parse args */
69 optind = 1;
70 opterr = 1;
71 while ((c = getopt(argc, argv, "s:f")) != -1) {
72 switch (c) {
73 case 's':
74 break;
75
76 case 'f':
77 options |= MDCMD_FORCE;
78 break;
79
80 default:
81 usage(*spp, 1);
82 /*NOTREACHED*/
83 break;
84 }
85 }
86 argc -= optind;
87 argv += optind;
88 if (argc != 2)
89 usage(*spp, 1);
90
91 /* get submirror */
92 if ((submirnp = metaname(spp, argv[1], META_DEVICE, ep)) == NULL)
93 return (-1);
94
95 /* detach submirror */
96 if (meta_mirror_detach(*spp, mirnp, submirnp, options, ep) != 0)
97 return (-1);
98
99 /* update md.cf */
100 if (meta_update_md_cf(*spp, ep) != 0)
101 return (-1);
102
103 /* return success */
104 return (0);
105 }
106
107 /*
108 * detach log from trans
109 */
110 static int
trans_detach(mdsetname_t * sp,mdname_t * transnp,int argc,char * argv[],mdcmdopts_t options,md_error_t * ep)111 trans_detach(
112 mdsetname_t *sp,
113 mdname_t *transnp,
114 int argc,
115 char *argv[],
116 mdcmdopts_t options,
117 md_error_t *ep
118 )
119 {
120 int delayed;
121 int c;
122
123 /* reset and parse args */
124 optind = 1;
125 opterr = 1;
126 while ((c = getopt(argc, argv, "s:f")) != -1) {
127 switch (c) {
128 case 's':
129 break;
130
131 case 'f':
132 options |= MDCMD_FORCE;
133 break;
134
135 default:
136 usage(sp, 1);
137 /*NOTREACHED*/
138 break;
139 }
140 }
141 argc -= optind;
142 argv += optind;
143 if (argc != 1)
144 usage(sp, 1);
145
146 /* detach log */
147 if (meta_trans_detach(sp, transnp, options, &delayed, ep) != 0)
148 return (-1);
149
150 /* update md.cf */
151 if (meta_update_md_cf(sp, ep) != 0)
152 return (-1);
153
154 /* return success */
155 return (0);
156 }
157
158 /*
159 * parse args and doit
160 */
161 int
main(int argc,char * argv[])162 main(
163 int argc,
164 char *argv[]
165 )
166 {
167 char *sname = NULL;
168 mdsetname_t *sp = NULL;
169 mdcmdopts_t options = (MDCMD_PRINT);
170 mdname_t *np;
171 char *miscname;
172 int c;
173 md_error_t status = mdnullerror;
174 md_error_t *ep = &status;
175 int error;
176 bool_t called_thru_rpc = FALSE;
177 char *cp;
178
179
180 /*
181 * Get the locale set up before calling any other routines
182 * with messages to ouput. Just in case we're not in a build
183 * environment, make sure that TEXT_DOMAIN gets set to
184 * something.
185 */
186 #if !defined(TEXT_DOMAIN)
187 #define TEXT_DOMAIN "SYS_TEST"
188 #endif
189 (void) setlocale(LC_ALL, "");
190 (void) textdomain(TEXT_DOMAIN);
191
192 if ((cp = strstr(argv[0], ".rpc_call")) == NULL) {
193 if (sdssc_bind_library() == SDSSC_OKAY)
194 if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY,
195 &error) == SDSSC_PROXY_DONE)
196 exit(error);
197 } else {
198 *cp = '\0'; /* cut off ".rpc_call" */
199 called_thru_rpc = TRUE;
200 }
201
202
203 /* initialize */
204 if (md_init(argc, argv, 0, 1, ep) != 0 ||
205 meta_check_root(ep) != 0) {
206 mde_perror(ep, "");
207 md_exit(sp, 1);
208 }
209
210 /* find set and metadevice first */
211 optind = 1;
212 opterr = 1;
213 while ((c = getopt(argc, argv, "hs:f?")) != -1) {
214 switch (c) {
215 case 'h':
216 usage(sp, 0);
217 break;
218
219 case 's':
220 sname = optarg;
221 break;
222
223 case '?':
224 if (optopt == '?')
225 usage(sp, 0);
226 break;
227 }
228 }
229 if ((argc - optind) <= 0)
230 usage(sp, 1);
231
232 if (sname != NULL) {
233 if ((sp = metasetname(sname, ep)) == NULL) {
234 mde_perror(ep, "");
235 md_exit(sp, 1);
236 }
237 }
238
239 /* Get metadevice name */
240 if (((np = metaname(&sp, argv[optind], META_DEVICE, ep)) == NULL) ||
241 (metachkmeta(np, ep) != 0)) {
242 mde_perror(ep, "");
243 md_exit(sp, 1);
244 }
245 assert(sp != NULL);
246
247 if ((called_thru_rpc == FALSE) &&
248 meta_is_mn_name(&sp, argv[optind], ep)) {
249 /*
250 * If we are dealing with a MN set and we were not
251 * called thru an rpc call, we are just to send this
252 * command string to the master of the set and let it
253 * deal with it.
254 * Note that if sp is NULL, meta_is_mn_name() derives sp
255 * from argv[optind] which is the metadevice arg
256 * If this fails, the master must panic as the mddb may be
257 * inconsistent
258 */
259 int result;
260 result = meta_mn_send_command(sp, argc, argv, MD_DISP_STDERR |
261 MD_PANIC_WHEN_INCONSISTENT, NO_CONTEXT_STRING, ep);
262 /*
263 * The error message has been already been displayed
264 * just exit
265 */
266 md_exit(sp, result);
267 }
268
269 /* grab set lock */
270 if (meta_lock(sp, TRUE, ep)) {
271 mde_perror(ep, "");
272 md_exit(sp, 1);
273 }
274
275 /* check ownership */
276 if (meta_check_ownership(sp, ep) != 0) {
277 mde_perror(ep, "");
278 md_exit(sp, 1);
279 }
280 if ((miscname = metagetmiscname(np, ep)) == NULL) {
281 mde_perror(ep, "");
282 md_exit(sp, 1);
283 }
284
285 /* dispatch based on device type */
286 if (strcmp(miscname, MD_MIRROR) == 0) {
287 if (mirror_detach(&sp, np, argc, argv, options, ep) != 0) {
288 mde_perror(ep, "");
289 md_exit(sp, 1);
290 }
291 } else if (strcmp(miscname, MD_TRANS) == 0) {
292 if (trans_detach(sp, np, argc, argv, options, ep) != 0) {
293 mde_perror(ep, "");
294 md_exit(sp, 1);
295 }
296 } else {
297 md_eprintf(gettext(
298 "%s: invalid metadevice type %s\n"),
299 np->cname, miscname);
300 md_exit(sp, 1);
301 }
302
303 /* return success */
304 md_exit(sp, 0);
305 /*NOTREACHED*/
306 return (0);
307 }
308