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.
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.
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]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Just in case we're not in a build environment, make sure that
30 * TEXT_DOMAIN gets set to something.
32 #if !defined(TEXT_DOMAIN)
33 #define TEXT_DOMAIN "SYS_TEST"
37 * change the identity of a metadevice
38 * These are the "do it" functions for the metarename command.
43 #include <sys/lvm/md_rename.h>
46 #define FORCE (0x00000001)
47 #define NOISY (0x00000010)
48 #define NOFLIP (0x00000020)
49 #define DRYRUN (0x00000040)
52 ((op) == MDRNOP_EXCHANGE? "exchange": \
53 (op) == MDRNOP_RENAME? "rename": \
54 (op) == MDRNOP_UNK? "<unknown>": "garbage")
58 * Check if from_np is open
59 * Return 0 if not open, -1 if open
69 if ((rc
= meta_isopen(sp
, from_np
, ep
, (mdcmdopts_t
)0)) < 0) {
75 (void) mdmderror(ep
, MDE_RENAME_BUSY
,
76 meta_getminor(from_np
->dev
),
85 * meta_swap is the common code used by the
86 * meta_rename() and meta_exchange() entry points
93 md_common_t
*from_mdp
,
101 int from_add_flag
= 0;
103 int from_is_fn
, to_is_fn
;
104 bool_t from_has_parent
, to_has_parent
;
107 * What types of devices we have here?
108 * For MDRNOP_RENAME to_mdp is NULL
110 from_is_fn
= (from_mdp
->revision
& MD_FN_META_DEV
);
111 from_has_parent
= MD_HAS_PARENT(from_mdp
->parent
);
113 to_is_fn
= (to_mdp
->revision
& MD_FN_META_DEV
);
114 to_has_parent
= MD_HAS_PARENT(to_mdp
->parent
);
118 * If the device exists a key may already exist so need to find it
119 * otherwise we'll end up adding the key in again which will lead
120 * to an inconsistent n_count for the namespace record.
122 if (from_np
->dev
!= NODEV
) {
123 (void) meta_getnmentbydev(sp
->setno
, MD_SIDEWILD
, from_np
->dev
,
124 NULL
, NULL
, &from_np
->key
, ep
);
127 if (to_np
->dev
!= NODEV
) {
128 (void) meta_getnmentbydev(sp
->setno
, MD_SIDEWILD
, to_np
->dev
,
129 NULL
, NULL
, &to_np
->key
, ep
);
132 if ((from_np
->key
== MD_KEYWILD
) || (from_np
->key
== MD_KEYBAD
)) {
134 * If we are top and revision indicates that we
135 * should have key but we don't then something
138 assert(!from_has_parent
&& !from_is_fn
);
140 if (from_has_parent
|| from_is_fn
) {
145 * So only add the entry if necessary
147 if (add_key_name(sp
, from_np
, NULL
, ep
) != 0) {
155 (void) memset(&txn
, 0, sizeof (txn
));
158 txn
.revision
= MD_RENAME_VERSION
;
160 txn
.from
.mnum
= meta_getminor(from_np
->dev
);
161 txn
.from
.key
= from_np
->key
;
163 if ((to_np
->key
== MD_KEYWILD
) || (to_np
->key
== MD_KEYBAD
)) {
165 * If we are top and revision indicates that we
166 * should have key but we don't then something
169 assert(!to_has_parent
&& !to_is_fn
);
171 if (to_has_parent
|| to_is_fn
) {
176 * So only add the entry if necessary
178 if (add_key_name(sp
, to_np
, NULL
, ep
) != 0) {
181 (void) del_key_name(sp
, from_np
, ep
);
188 txn
.to
.mnum
= meta_getminor(to_np
->dev
);
189 txn
.to
.key
= to_np
->key
;
192 (void) fprintf(stderr
, "\top: %s\n", OP_STR(txn
.op
));
193 (void) fprintf(stderr
, "\trevision: %d, flags: %d\n",
194 txn
.revision
, txn
.flags
);
195 (void) fprintf(stderr
,
196 "\tfrom(mnum,key): %ld, %d\tto: %ld, %d\n",
197 txn
.from
.mnum
, txn
.from
.key
,
198 txn
.to
.mnum
, txn
.to
.key
);
202 if (metaioctl(MD_IOCRENAME
, &txn
, &txn
.mde
, from_np
->cname
) != 0) {
204 (void) del_key_name(sp
, from_np
, ep
);
206 * Attempt removal of device node
208 (void) metaioctl(MD_IOCREM_DEV
, &txn
.from
.mnum
,
212 if (op
== MDRNOP_RENAME
|| to_add_flag
) {
213 (void) del_key_name(sp
, to_np
, ep
);
215 * Attempt removal of device node
217 (void) metaioctl(MD_IOCREM_DEV
, &txn
.to
.mnum
,
221 return (mdstealerror(ep
, &txn
.mde
));
225 * Since now the metadevice can be ref'd in the namespace
226 * by self and by the top device so upon the successful
227 * rename/xchange, we need to check the type and make
228 * necessary adjustment for the device's n_cnt in the namespace
229 * by calling add_key_name/del_key_name to do the tricks
231 if (op
== MDRNOP_RENAME
&& from_has_parent
) {
232 (void) add_key_name(sp
, to_np
, NULL
, ep
);
234 (void) del_self_name(sp
, from_np
->key
, ep
);
237 if (op
== MDRNOP_EXCHANGE
&& from_is_fn
) {
238 (void) add_key_name(sp
, from_np
, NULL
, ep
);
241 /* force the name cache to re-read device state */
242 meta_invalidate_name(from_np
);
243 meta_invalidate_name(to_np
);
249 * rename a metadevice
260 int flags
= (options
& MDCMD_FORCE
)? FORCE
: 0;
263 md_common_t
*from_mdp
;
264 minor_t to_minor
= meta_getminor(to_np
->dev
);
265 md_error_t status
= mdnullerror
;
266 md_error_t
*t_ep
= &status
;
268 /* must have a set */
270 assert(sp
->setno
== MD_MIN2SET(meta_getminor(from_np
->dev
)));
274 if (((p
= getenv("MD_DEBUG")) != NULL
) &&
275 (strstr(p
, "RENAME") != NULL
)) {
278 /* if DOIT is not set, we are in dryrun mode */
279 if ((options
& MDCMD_DOIT
) == 0) {
284 if (metachkmeta(from_np
, ep
) != 0) {
291 if ((from_mdp
= meta_get_unit(sp
, from_np
, ep
)) == NULL
) {
296 if (meta_get_unit(sp
, to_np
, ep
) != NULL
) {
298 (void) mdmderror(ep
, MDE_UNIT_ALREADY_SETUP
,
299 meta_getminor(to_np
->dev
),
307 * The dest device name has been added early on
308 * by meta_init_make_device call so get the entry from
311 if (meta_getnmentbydev(sp
->setno
, MD_SIDEWILD
, to_np
->dev
,
312 NULL
, NULL
, &to_np
->key
, ep
) == NULL
) {
316 /* If FORCE is not set, check if metadevice is open */
317 if (!(flags
& FORCE
)) {
318 if (check_open(sp
, from_np
, ep
) != 0) {
319 (void) del_key_name(sp
, to_np
, t_ep
);
320 (void) metaioctl(MD_IOCREM_DEV
, &to_minor
, t_ep
, NULL
);
326 * All checks are done, now we do the real work.
327 * If we are in dryrun mode, clear the deivce node
330 if (flags
& DRYRUN
) {
331 (void) del_key_name(sp
, to_np
, t_ep
);
332 (void) metaioctl(MD_IOCREM_DEV
, &to_minor
, t_ep
, NULL
);
333 return (0); /* success */
336 if (to_np
->key
== MD_KEYBAD
|| to_np
->key
== MD_KEYWILD
) {
341 rc
= meta_swap(sp
, from_np
, from_mdp
, to_np
, NULL
, MDRNOP_RENAME
,
345 if (options
& MDCMD_PRINT
) {
346 (void) fprintf(stdout
, dgettext(TEXT_DOMAIN
,
347 "%s: has been renamed to %s\n"),
348 from_np
->cname
, to_np
->cname
);
356 * return TRUE if current <from>, <to> ordering would
357 * prevent <from> from being in the role of <self>
360 meta_exchange_need_to_flip(
361 md_common_t
*from_mdp
,
376 if (MD_HAS_PARENT(from_mdp
->parent
)) {
377 if (MD_HAS_PARENT(to_mdp
->parent
)) {
378 if (from_mdp
->parent
==
379 meta_getminor(to_mdp
->namep
->dev
)) {
393 if (MD_HAS_PARENT(to_mdp
->parent
)) {
394 if (to_mdp
->capabilities
& MD_CAN_META_CHILD
) {
405 if (MD_HAS_PARENT(from_mdp
->parent
)) {
406 if (from_mdp
->parent
== meta_getminor(to_mdp
->namep
->dev
)) {
407 if (!(from_mdp
->capabilities
& MD_CAN_META_CHILD
)) {
425 * exchange the names of two metadevices
436 int flags
= (options
& MDCMD_FORCE
)? FORCE
: 0;
437 md_common_t
*from_mdp
, *to_mdp
;
441 /* must have a set */
443 assert(sp
->setno
== MD_MIN2SET(meta_getminor(from_np
->dev
)));
444 assert(sp
->setno
== MD_MIN2SET(meta_getminor(to_np
->dev
)));
446 if (metachkmeta(from_np
, ep
) != 0) {
451 if (metachkmeta(to_np
, ep
) != 0) {
456 if ((options
& MDCMD_DOIT
) == 0) {
460 if ((p
= getenv("MD_DEBUG")) != NULL
) {
461 if ((p2
= strstr(p
, "EXCHANGE=")) != NULL
) {
463 if ((p2
= strchr(p2
, '=')) != NULL
) {
464 if (strcmp((p2
+1), "NOFLIP") == 0) {
468 } else if (strstr(p
, "EXCHANGE") != NULL
) {
473 if ((from_mdp
= meta_get_unit(sp
, from_np
, ep
)) == NULL
) {
478 if ((to_mdp
= meta_get_unit(sp
, to_np
, ep
)) == NULL
) {
485 /* If FORCE is not set, check if metadevice is open */
486 if (!(flags
& FORCE
)) {
487 if (check_open(sp
, from_np
, ep
) != 0) {
493 * All checks are done, now we do the real work.
494 * If we are in dryrun mode, we're done.
496 if (flags
& DRYRUN
) {
497 return (0); /* success */
501 * NOFLIP is used only for debugging; the driver
502 * will catch this and return MDE_RENAME_ORDER, if necessary
504 if (((flags
& NOFLIP
) == 0) &&
505 meta_exchange_need_to_flip(from_mdp
, to_mdp
)) {
506 rc
= meta_swap(sp
, to_np
, to_mdp
, from_np
, from_mdp
,
507 MDRNOP_EXCHANGE
, flags
, ep
);
510 rc
= meta_swap(sp
, from_np
, from_mdp
, to_np
, to_mdp
,
511 MDRNOP_EXCHANGE
, flags
, ep
);
515 if (options
& MDCMD_PRINT
) {
516 (void) fprintf(stdout
, dgettext(TEXT_DOMAIN
,
517 "%s and %s have exchanged identities\n"),
518 from_np
->cname
, to_np
->cname
);