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