1 /* $NetBSD: flags.c,v 1.1.1.2 2009/12/02 00:26:29 haad Exp $ */
2
3 /*
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
6 *
7 * This file is part of LVM2.
8 *
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18 #include "lib.h"
19 #include "metadata.h"
20 #include "import-export.h"
21 #include "lvm-string.h"
22
23 /*
24 * Bitsets held in the 'status' flags get
25 * converted into arrays of strings.
26 */
27 struct flag {
28 const int mask;
29 const char *description;
30 int kind;
31 };
32
33 static struct flag _vg_flags[] = {
34 {EXPORTED_VG, "EXPORTED", STATUS_FLAG},
35 {RESIZEABLE_VG, "RESIZEABLE", STATUS_FLAG},
36 {PVMOVE, "PVMOVE", STATUS_FLAG},
37 {LVM_READ, "READ", STATUS_FLAG},
38 {LVM_WRITE, "WRITE", STATUS_FLAG},
39 {CLUSTERED, "CLUSTERED", STATUS_FLAG},
40 {SHARED, "SHARED", STATUS_FLAG},
41 {PARTIAL_VG, NULL, 0},
42 {PRECOMMITTED, NULL, 0},
43 {0, NULL, 0}
44 };
45
46 static struct flag _pv_flags[] = {
47 {ALLOCATABLE_PV, "ALLOCATABLE", STATUS_FLAG},
48 {EXPORTED_VG, "EXPORTED", STATUS_FLAG},
49 {MISSING_PV, "MISSING", COMPATIBLE_FLAG},
50 {0, NULL, 0}
51 };
52
53 static struct flag _lv_flags[] = {
54 {LVM_READ, "READ", STATUS_FLAG},
55 {LVM_WRITE, "WRITE", STATUS_FLAG},
56 {FIXED_MINOR, "FIXED_MINOR", STATUS_FLAG},
57 {VISIBLE_LV, "VISIBLE", STATUS_FLAG},
58 {PVMOVE, "PVMOVE", STATUS_FLAG},
59 {LOCKED, "LOCKED", STATUS_FLAG},
60 {MIRROR_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
61 {MIRROR_IMAGE, NULL, 0},
62 {MIRROR_LOG, NULL, 0},
63 {MIRRORED, NULL, 0},
64 {VIRTUAL, NULL, 0},
65 {SNAPSHOT, NULL, 0},
66 {ACTIVATE_EXCL, NULL, 0},
67 {CONVERTING, NULL, 0},
68 {PARTIAL_LV, NULL, 0},
69 {POSTORDER_FLAG, NULL, 0},
70 {VIRTUAL_ORIGIN, NULL, 0},
71 {0, NULL, 0}
72 };
73
_get_flags(int type)74 static struct flag *_get_flags(int type)
75 {
76 switch (type & ~STATUS_FLAG) {
77 case VG_FLAGS:
78 return _vg_flags;
79
80 case PV_FLAGS:
81 return _pv_flags;
82
83 case LV_FLAGS:
84 return _lv_flags;
85 }
86
87 log_error("Unknown flag set requested.");
88 return NULL;
89 }
90
91 /*
92 * Converts a bitset to an array of string values,
93 * using one of the tables defined at the top of
94 * the file.
95 */
print_flags(uint32_t status,int type,char * buffer,size_t size)96 int print_flags(uint32_t status, int type, char *buffer, size_t size)
97 {
98 int f, first = 1;
99 struct flag *flags;
100
101 if (!(flags = _get_flags(type)))
102 return_0;
103
104 if (!emit_to_buffer(&buffer, &size, "["))
105 return 0;
106
107 for (f = 0; flags[f].mask; f++) {
108 if (status & flags[f].mask) {
109 status &= ~flags[f].mask;
110
111 if ((type & STATUS_FLAG) != flags[f].kind)
112 continue;
113
114 /* Internal-only flag? */
115 if (!flags[f].description)
116 continue;
117
118 if (!first) {
119 if (!emit_to_buffer(&buffer, &size, ", "))
120 return 0;
121 } else
122 first = 0;
123
124 if (!emit_to_buffer(&buffer, &size, "\"%s\"",
125 flags[f].description))
126 return 0;
127 }
128 }
129
130 if (!emit_to_buffer(&buffer, &size, "]"))
131 return 0;
132
133 if (status)
134 log_error("Metadata inconsistency: Not all flags successfully "
135 "exported.");
136
137 return 1;
138 }
139
read_flags(uint32_t * status,int type,struct config_value * cv)140 int read_flags(uint32_t *status, int type, struct config_value *cv)
141 {
142 int f;
143 uint32_t s = 0;
144 struct flag *flags;
145
146 if (!(flags = _get_flags(type)))
147 return_0;
148
149 if (cv->type == CFG_EMPTY_ARRAY)
150 goto out;
151
152 while (cv) {
153 if (cv->type != CFG_STRING) {
154 log_error("Status value is not a string.");
155 return 0;
156 }
157
158 for (f = 0; flags[f].description; f++)
159 if (!strcmp(flags[f].description, cv->v.str)) {
160 s |= flags[f].mask;
161 break;
162 }
163
164 if (type == VG_FLAGS && !strcmp(cv->v.str, "PARTIAL")) {
165 /*
166 * Exception: We no longer write this flag out, but it
167 * might be encountered in old backup files, so restore
168 * it in that case. It is never part of live metadata
169 * though, so only vgcfgrestore needs to be concerned
170 * by this case.
171 */
172 s |= PARTIAL_VG;
173 } else if (!flags[f].description && (type & STATUS_FLAG)) {
174 log_error("Unknown status flag '%s'.", cv->v.str);
175 return 0;
176 }
177
178 cv = cv->next;
179 }
180
181 out:
182 *status |= s;
183 return 1;
184 }
185