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 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 */ 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 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