1 /* $NetBSD: flags.c,v 1.1.1.1 2008/12/22 00:18:16 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 {0, NULL, 0} 71 }; 72 73 static struct flag *_get_flags(int type) 74 { 75 switch (type & ~STATUS_FLAG) { 76 case VG_FLAGS: 77 return _vg_flags; 78 79 case PV_FLAGS: 80 return _pv_flags; 81 82 case LV_FLAGS: 83 return _lv_flags; 84 } 85 86 log_err("Unknown flag set requested."); 87 return NULL; 88 } 89 90 /* 91 * Converts a bitset to an array of string values, 92 * using one of the tables defined at the top of 93 * the file. 94 */ 95 int print_flags(uint32_t status, int type, char *buffer, size_t size) 96 { 97 int f, first = 1; 98 struct flag *flags; 99 100 if (!(flags = _get_flags(type))) 101 return_0; 102 103 if (!emit_to_buffer(&buffer, &size, "[")) 104 return 0; 105 106 for (f = 0; flags[f].mask; f++) { 107 if (status & flags[f].mask) { 108 status &= ~flags[f].mask; 109 110 if ((type & STATUS_FLAG) != flags[f].kind) 111 continue; 112 113 /* Internal-only flag? */ 114 if (!flags[f].description) 115 continue; 116 117 if (!first) { 118 if (!emit_to_buffer(&buffer, &size, ", ")) 119 return 0; 120 } else 121 first = 0; 122 123 if (!emit_to_buffer(&buffer, &size, "\"%s\"", 124 flags[f].description)) 125 return 0; 126 } 127 } 128 129 if (!emit_to_buffer(&buffer, &size, "]")) 130 return 0; 131 132 if (status) 133 log_error("Metadata inconsistency: Not all flags successfully " 134 "exported."); 135 136 return 1; 137 } 138 139 int read_flags(uint32_t *status, int type, struct config_value *cv) 140 { 141 int f; 142 uint32_t s = 0; 143 struct flag *flags; 144 145 if (!(flags = _get_flags(type))) 146 return_0; 147 148 if (cv->type == CFG_EMPTY_ARRAY) 149 goto out; 150 151 while (cv) { 152 if (cv->type != CFG_STRING) { 153 log_err("Status value is not a string."); 154 return 0; 155 } 156 157 for (f = 0; flags[f].description; f++) 158 if (!strcmp(flags[f].description, cv->v.str)) { 159 s |= flags[f].mask; 160 break; 161 } 162 163 if (type == VG_FLAGS && !strcmp(cv->v.str, "PARTIAL")) { 164 /* 165 * Exception: We no longer write this flag out, but it 166 * might be encountered in old backup files, so restore 167 * it in that case. It is never part of live metadata 168 * though, so only vgcfgrestore needs to be concerned 169 * by this case. 170 */ 171 s |= PARTIAL_VG; 172 } else if (!flags[f].description && (type & STATUS_FLAG)) { 173 log_err("Unknown status flag '%s'.", cv->v.str); 174 return 0; 175 } 176 177 cv = cv->next; 178 } 179 180 out: 181 *status |= s; 182 return 1; 183 } 184