xref: /titanic_41/usr/src/cmd/lvm/util/metadetach.c (revision 40db2e2b777b79f3dd0d6d9629593a07f86b9c0a)
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
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
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
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
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