Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
3 : : * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
4 : : *
5 : : * This file is part of LVM2.
6 : : *
7 : : * This copyrighted material is made available to anyone wishing to use,
8 : : * modify, copy, or redistribute it subject to the terms and conditions
9 : : * of the GNU Lesser General Public License v.2.1.
10 : : *
11 : : * You should have received a copy of the GNU Lesser General Public License
12 : : * along with this program; if not, write to the Free Software Foundation,
13 : : * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 : : */
15 : :
16 : : #include "lib.h"
17 : : #include "format-text.h"
18 : : #include "layout.h"
19 : : #include "label.h"
20 : : #include "xlate.h"
21 : : #include "lvmcache.h"
22 : :
23 : : #include <sys/stat.h>
24 : : #include <fcntl.h>
25 : :
26 : 0 : static int _text_can_handle(struct labeller *l __attribute((unused)),
27 : : void *buf,
28 : : uint64_t sector __attribute((unused)))
29 : : {
30 : 0 : struct label_header *lh = (struct label_header *) buf;
31 : :
32 [ # # ]: 0 : if (!strncmp((char *)lh->type, LVM2_LABEL, sizeof(lh->type)))
33 : 0 : return 1;
34 : :
35 : 0 : return 0;
36 : : }
37 : :
38 : 0 : static int _text_write(struct label *label, void *buf)
39 : : {
40 : 0 : struct label_header *lh = (struct label_header *) buf;
41 : : struct pv_header *pvhdr;
42 : : struct lvmcache_info *info;
43 : : struct disk_locn *pvh_dlocn_xl;
44 : : struct metadata_area *mda;
45 : : struct mda_context *mdac;
46 : : struct data_area_list *da;
47 : : char buffer[64] __attribute((aligned(8)));
48 : : int da1, mda1, mda2;
49 : :
50 : : /* FIXME Move to where label is created */
51 : 0 : strncpy(label->type, LVM2_LABEL, sizeof(label->type));
52 : :
53 : 0 : strncpy((char *)lh->type, label->type, sizeof(label->type));
54 : :
55 : 0 : pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
56 : 0 : info = (struct lvmcache_info *) label->info;
57 : 0 : pvhdr->device_size_xl = xlate64(info->device_size);
58 : 0 : memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id));
59 [ # # ]: 0 : if (!id_write_format((const struct id *)pvhdr->pv_uuid, buffer,
60 : : sizeof(buffer))) {
61 : 0 : stack;
62 : 0 : buffer[0] = '\0';
63 : : }
64 : :
65 : 0 : pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
66 : :
67 : : /* List of data areas (holding PEs) */
68 [ # # ]: 0 : dm_list_iterate_items(da, &info->das) {
69 : 0 : pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
70 : 0 : pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
71 : 0 : pvh_dlocn_xl++;
72 : : }
73 : :
74 : : /* NULL-termination */
75 : 0 : pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
76 : 0 : pvh_dlocn_xl->size = xlate64(UINT64_C(0));
77 : 0 : pvh_dlocn_xl++;
78 : :
79 : : /* List of metadata area header locations */
80 [ # # ]: 0 : dm_list_iterate_items(mda, &info->mdas) {
81 : 0 : mdac = (struct mda_context *) mda->metadata_locn;
82 : :
83 [ # # ]: 0 : if (mdac->area.dev != info->dev)
84 : 0 : continue;
85 : :
86 : 0 : pvh_dlocn_xl->offset = xlate64(mdac->area.start);
87 : 0 : pvh_dlocn_xl->size = xlate64(mdac->area.size);
88 : 0 : pvh_dlocn_xl++;
89 : : }
90 : :
91 : : /* NULL-termination */
92 : 0 : pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
93 : 0 : pvh_dlocn_xl->size = xlate64(UINT64_C(0));
94 : :
95 : : /* Create debug message with da and mda locations */
96 [ # # ][ # # ]: 0 : if (xlate64(pvhdr->disk_areas_xl[0].offset) ||
97 : 0 : xlate64(pvhdr->disk_areas_xl[0].size))
98 : 0 : da1 = 0;
99 : : else
100 : 0 : da1 = -1;
101 : :
102 : 0 : mda1 = da1 + 2;
103 : 0 : mda2 = mda1 + 1;
104 : :
105 [ # # ][ # # ]: 0 : if (!xlate64(pvhdr->disk_areas_xl[mda1].offset) &&
106 : 0 : !xlate64(pvhdr->disk_areas_xl[mda1].size))
107 : 0 : mda1 = mda2 = 0;
108 [ # # ][ # # ]: 0 : else if (!xlate64(pvhdr->disk_areas_xl[mda2].offset) &&
109 : 0 : !xlate64(pvhdr->disk_areas_xl[mda2].size))
110 : 0 : mda2 = 0;
111 : :
112 [ # # ][ # # ]: 0 : log_debug("%s: Preparing PV label header %s size %" PRIu64 " with"
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
113 : : "%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
114 : : "%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
115 : : "%s%.*" PRIu64 "%s%.*" PRIu64 "%s",
116 : : dev_name(info->dev), buffer, info->device_size,
117 : : (da1 > -1) ? " da1 (" : "",
118 : : (da1 > -1) ? 1 : 0,
119 : : (da1 > -1) ? xlate64(pvhdr->disk_areas_xl[da1].offset) >> SECTOR_SHIFT : 0,
120 : : (da1 > -1) ? "s, " : "",
121 : : (da1 > -1) ? 1 : 0,
122 : : (da1 > -1) ? xlate64(pvhdr->disk_areas_xl[da1].size) >> SECTOR_SHIFT : 0,
123 : : (da1 > -1) ? "s)" : "",
124 : : mda1 ? " mda1 (" : "",
125 : : mda1 ? 1 : 0,
126 : : mda1 ? xlate64(pvhdr->disk_areas_xl[mda1].offset) >> SECTOR_SHIFT : 0,
127 : : mda1 ? "s, " : "",
128 : : mda1 ? 1 : 0,
129 : : mda1 ? xlate64(pvhdr->disk_areas_xl[mda1].size) >> SECTOR_SHIFT : 0,
130 : : mda1 ? "s)" : "",
131 : : mda2 ? " mda2 (" : "",
132 : : mda2 ? 1 : 0,
133 : : mda2 ? xlate64(pvhdr->disk_areas_xl[mda2].offset) >> SECTOR_SHIFT : 0,
134 : : mda2 ? "s, " : "",
135 : : mda2 ? 1 : 0,
136 : : mda2 ? xlate64(pvhdr->disk_areas_xl[mda2].size) >> SECTOR_SHIFT : 0,
137 : : mda2 ? "s)" : "");
138 : :
139 [ # # ]: 0 : if (da1 < 0) {
140 : 0 : log_error(INTERNAL_ERROR "%s label header currently requires "
141 : : "a data area.", dev_name(info->dev));
142 : 0 : return 0;
143 : : }
144 : :
145 : 0 : return 1;
146 : : }
147 : :
148 : 0 : int add_da(struct dm_pool *mem, struct dm_list *das,
149 : : uint64_t start, uint64_t size)
150 : : {
151 : : struct data_area_list *dal;
152 : :
153 [ # # ]: 0 : if (!mem) {
154 [ # # ]: 0 : if (!(dal = dm_malloc(sizeof(*dal)))) {
155 : 0 : log_error("struct data_area_list allocation failed");
156 : 0 : return 0;
157 : : }
158 : : } else {
159 [ # # ]: 0 : if (!(dal = dm_pool_alloc(mem, sizeof(*dal)))) {
160 : 0 : log_error("struct data_area_list allocation failed");
161 : 0 : return 0;
162 : : }
163 : : }
164 : :
165 : 0 : dal->disk_locn.offset = start;
166 : 0 : dal->disk_locn.size = size;
167 : :
168 : 0 : dm_list_add(das, &dal->list);
169 : :
170 : 0 : return 1;
171 : : }
172 : :
173 : 0 : void del_das(struct dm_list *das)
174 : : {
175 : : struct dm_list *dah, *tmp;
176 : : struct data_area_list *da;
177 : :
178 [ # # ]: 0 : dm_list_iterate_safe(dah, tmp, das) {
179 : 0 : da = dm_list_item(dah, struct data_area_list);
180 : 0 : dm_list_del(&da->list);
181 : 0 : dm_free(da);
182 : : }
183 : 0 : }
184 : :
185 : 0 : int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *mdas,
186 : : struct device *dev, uint64_t start, uint64_t size)
187 : : {
188 : : /* FIXME List size restricted by pv_header SECTOR_SIZE */
189 : : struct metadata_area *mdal;
190 : 0 : struct mda_lists *mda_lists = (struct mda_lists *) fmt->private;
191 : : struct mda_context *mdac;
192 : :
193 [ # # ]: 0 : if (!mem) {
194 [ # # ]: 0 : if (!(mdal = dm_malloc(sizeof(struct metadata_area)))) {
195 : 0 : log_error("struct mda_list allocation failed");
196 : 0 : return 0;
197 : : }
198 : :
199 [ # # ]: 0 : if (!(mdac = dm_malloc(sizeof(struct mda_context)))) {
200 : 0 : log_error("struct mda_context allocation failed");
201 : 0 : dm_free(mdal);
202 : 0 : return 0;
203 : : }
204 : : } else {
205 [ # # ]: 0 : if (!(mdal = dm_pool_alloc(mem, sizeof(struct metadata_area)))) {
206 : 0 : log_error("struct mda_list allocation failed");
207 : 0 : return 0;
208 : : }
209 : :
210 [ # # ]: 0 : if (!(mdac = dm_pool_alloc(mem, sizeof(struct mda_context)))) {
211 : 0 : log_error("struct mda_context allocation failed");
212 : 0 : return 0;
213 : : }
214 : : }
215 : :
216 : 0 : mdal->ops = mda_lists->raw_ops;
217 : 0 : mdal->metadata_locn = mdac;
218 : :
219 : 0 : mdac->area.dev = dev;
220 : 0 : mdac->area.start = start;
221 : 0 : mdac->area.size = size;
222 : 0 : mdac->free_sectors = UINT64_C(0);
223 : 0 : memset(&mdac->rlocn, 0, sizeof(mdac->rlocn));
224 : :
225 : 0 : dm_list_add(mdas, &mdal->list);
226 : 0 : return 1;
227 : : }
228 : :
229 : 0 : void del_mdas(struct dm_list *mdas)
230 : : {
231 : : struct dm_list *mdah, *tmp;
232 : : struct metadata_area *mda;
233 : :
234 [ # # ]: 0 : dm_list_iterate_safe(mdah, tmp, mdas) {
235 : 0 : mda = dm_list_item(mdah, struct metadata_area);
236 : 0 : dm_free(mda->metadata_locn);
237 : 0 : dm_list_del(&mda->list);
238 : 0 : dm_free(mda);
239 : : }
240 : 0 : }
241 : :
242 : 0 : static int _text_initialise_label(struct labeller *l __attribute((unused)),
243 : : struct label *label)
244 : : {
245 : 0 : strncpy(label->type, LVM2_LABEL, sizeof(label->type));
246 : :
247 : 0 : return 1;
248 : : }
249 : :
250 : 0 : static int _text_read(struct labeller *l, struct device *dev, void *buf,
251 : : struct label **label)
252 : : {
253 : 0 : struct label_header *lh = (struct label_header *) buf;
254 : : struct pv_header *pvhdr;
255 : : struct lvmcache_info *info;
256 : : struct disk_locn *dlocn_xl;
257 : : uint64_t offset;
258 : : struct metadata_area *mda;
259 : : struct id vgid;
260 : : struct mda_context *mdac;
261 : : const char *vgname;
262 : : uint64_t vgstatus;
263 : : char *creation_host;
264 : :
265 : 0 : pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
266 : :
267 [ # # ]: 0 : if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev,
268 : : FMT_TEXT_ORPHAN_VG_NAME,
269 : : FMT_TEXT_ORPHAN_VG_NAME, 0)))
270 : 0 : return_0;
271 : 0 : *label = info->label;
272 : :
273 : 0 : info->device_size = xlate64(pvhdr->device_size_xl);
274 : :
275 [ # # ]: 0 : if (info->das.n)
276 : 0 : del_das(&info->das);
277 : 0 : dm_list_init(&info->das);
278 : :
279 [ # # ]: 0 : if (info->mdas.n)
280 : 0 : del_mdas(&info->mdas);
281 : 0 : dm_list_init(&info->mdas);
282 : :
283 : : /* Data areas holding the PEs */
284 : 0 : dlocn_xl = pvhdr->disk_areas_xl;
285 [ # # ]: 0 : while ((offset = xlate64(dlocn_xl->offset))) {
286 : 0 : add_da(NULL, &info->das, offset,
287 : : xlate64(dlocn_xl->size));
288 : 0 : dlocn_xl++;
289 : : }
290 : :
291 : : /* Metadata area headers */
292 : 0 : dlocn_xl++;
293 [ # # ]: 0 : while ((offset = xlate64(dlocn_xl->offset))) {
294 : 0 : add_mda(info->fmt, NULL, &info->mdas, dev, offset,
295 : : xlate64(dlocn_xl->size));
296 : 0 : dlocn_xl++;
297 : : }
298 : :
299 [ # # ]: 0 : dm_list_iterate_items(mda, &info->mdas) {
300 : 0 : mdac = (struct mda_context *) mda->metadata_locn;
301 [ # # # # ]: 0 : if ((vgname = vgname_from_mda(info->fmt, &mdac->area,
302 : : &vgid, &vgstatus, &creation_host,
303 : : &mdac->free_sectors)) &&
304 : 0 : !lvmcache_update_vgname_and_id(info, vgname,
305 : : (char *) &vgid, vgstatus,
306 : : creation_host))
307 : 0 : return_0;
308 : : }
309 : :
310 : 0 : info->status &= ~CACHE_INVALID;
311 : :
312 : 0 : return 1;
313 : : }
314 : :
315 : 0 : static void _text_destroy_label(struct labeller *l __attribute((unused)),
316 : : struct label *label)
317 : : {
318 : 0 : struct lvmcache_info *info = (struct lvmcache_info *) label->info;
319 : :
320 [ # # ]: 0 : if (info->mdas.n)
321 : 0 : del_mdas(&info->mdas);
322 [ # # ]: 0 : if (info->das.n)
323 : 0 : del_das(&info->das);
324 : 0 : }
325 : :
326 : 3 : static void _fmt_text_destroy(struct labeller *l)
327 : : {
328 : 3 : dm_free(l);
329 : 3 : }
330 : :
331 : : struct label_ops _text_ops = {
332 : : .can_handle = _text_can_handle,
333 : : .write = _text_write,
334 : : .read = _text_read,
335 : : .verify = _text_can_handle,
336 : : .initialise_label = _text_initialise_label,
337 : : .destroy_label = _text_destroy_label,
338 : : .destroy = _fmt_text_destroy,
339 : : };
340 : :
341 : 3 : struct labeller *text_labeller_create(const struct format_type *fmt)
342 : : {
343 : : struct labeller *l;
344 : :
345 [ - + ]: 3 : if (!(l = dm_malloc(sizeof(*l)))) {
346 : 0 : log_error("Couldn't allocate labeller object.");
347 : 0 : return NULL;
348 : : }
349 : :
350 : 3 : l->ops = &_text_ops;
351 : 3 : l->private = (const void *) fmt;
352 : :
353 : 3 : return l;
354 : : }
|