import source from lvm2 2.02.79
[external/device-mapper.git] / lib / format1 / disk-rep.c
1 /*
2  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3  * Copyright (C) 2004-2007 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 "disk-rep.h"
18 #include "xlate.h"
19 #include "filter.h"
20 #include "lvmcache.h"
21
22 #include <fcntl.h>
23
24 #define xx16(v) disk->v = xlate16(disk->v)
25 #define xx32(v) disk->v = xlate32(disk->v)
26 #define xx64(v) disk->v = xlate64(disk->v)
27
28 /*
29  * Functions to perform the endian conversion
30  * between disk and core.  The same code works
31  * both ways of course.
32  */
33 static void _xlate_pvd(struct pv_disk *disk)
34 {
35         xx16(version);
36
37         xx32(pv_on_disk.base);
38         xx32(pv_on_disk.size);
39         xx32(vg_on_disk.base);
40         xx32(vg_on_disk.size);
41         xx32(pv_uuidlist_on_disk.base);
42         xx32(pv_uuidlist_on_disk.size);
43         xx32(lv_on_disk.base);
44         xx32(lv_on_disk.size);
45         xx32(pe_on_disk.base);
46         xx32(pe_on_disk.size);
47
48         xx32(pv_major);
49         xx32(pv_number);
50         xx32(pv_status);
51         xx32(pv_allocatable);
52         xx32(pv_size);
53         xx32(lv_cur);
54         xx32(pe_size);
55         xx32(pe_total);
56         xx32(pe_allocated);
57         xx32(pe_start);
58 }
59
60 static void _xlate_lvd(struct lv_disk *disk)
61 {
62         xx32(lv_access);
63         xx32(lv_status);
64         xx32(lv_open);
65         xx32(lv_dev);
66         xx32(lv_number);
67         xx32(lv_mirror_copies);
68         xx32(lv_recovery);
69         xx32(lv_schedule);
70         xx32(lv_size);
71         xx32(lv_snapshot_minor);
72         xx16(lv_chunk_size);
73         xx16(dummy);
74         xx32(lv_allocated_le);
75         xx32(lv_stripes);
76         xx32(lv_stripesize);
77         xx32(lv_badblock);
78         xx32(lv_allocation);
79         xx32(lv_io_timeout);
80         xx32(lv_read_ahead);
81 }
82
83 static void _xlate_vgd(struct vg_disk *disk)
84 {
85         xx32(vg_number);
86         xx32(vg_access);
87         xx32(vg_status);
88         xx32(lv_max);
89         xx32(lv_cur);
90         xx32(lv_open);
91         xx32(pv_max);
92         xx32(pv_cur);
93         xx32(pv_act);
94         xx32(dummy);
95         xx32(vgda);
96         xx32(pe_size);
97         xx32(pe_total);
98         xx32(pe_allocated);
99         xx32(pvg_total);
100 }
101
102 static void _xlate_extents(struct pe_disk *extents, uint32_t count)
103 {
104         unsigned i;
105
106         for (i = 0; i < count; i++) {
107                 extents[i].lv_num = xlate16(extents[i].lv_num);
108                 extents[i].le_num = xlate16(extents[i].le_num);
109         }
110 }
111
112 /*
113  * Handle both minor metadata formats.
114  */
115 static int _munge_formats(struct pv_disk *pvd)
116 {
117         uint32_t pe_start;
118         unsigned b, e;
119
120         switch (pvd->version) {
121         case 1:
122                 pvd->pe_start = ((pvd->pe_on_disk.base +
123                                   pvd->pe_on_disk.size) >> SECTOR_SHIFT);
124                 break;
125
126         case 2:
127                 pvd->version = 1;
128                 pe_start = pvd->pe_start << SECTOR_SHIFT;
129                 pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
130                 break;
131
132         default:
133                 return 0;
134         }
135
136         /* UUID too long? */
137         if (pvd->pv_uuid[ID_LEN]) {
138                 /* Retain ID_LEN chars from end */
139                 for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
140                         if (!pvd->pv_uuid[e]) {
141                                 e--;
142                                 break;
143                         }
144                 }
145                 for (b = 0; b < ID_LEN; b++) {
146                         pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
147                         /* FIXME Remove all invalid chars */
148                         if (pvd->pv_uuid[b] == '/')
149                                 pvd->pv_uuid[b] = '#';
150                 }
151                 memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
152         }
153
154         /* If UUID is missing, create one */
155         if (pvd->pv_uuid[0] == '\0') {
156                 uuid_from_num((char *)pvd->pv_uuid, pvd->pv_number);
157                 pvd->pv_uuid[ID_LEN] = '\0';
158         }
159
160         return 1;
161 }
162
163 /*
164  * If exported, remove "PV_EXP" from end of VG name
165  */
166 static void _munge_exported_vg(struct pv_disk *pvd)
167 {
168         int l;
169         size_t s;
170
171         /* Return if PV not in a VG */
172         if ((!*pvd->vg_name))
173                 return;
174         /* FIXME also check vgd->status & VG_EXPORTED? */
175
176         l = strlen((char *)pvd->vg_name);
177         s = sizeof(EXPORTED_TAG);
178         if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
179                 pvd->vg_name[l - s + 1] = '\0';
180                 pvd->pv_status |= VG_EXPORTED;
181         }
182 }
183
184 int munge_pvd(struct device *dev, struct pv_disk *pvd)
185 {
186         _xlate_pvd(pvd);
187
188         if (pvd->id[0] != 'H' || pvd->id[1] != 'M') {
189                 log_very_verbose("%s does not have a valid LVM1 PV identifier",
190                                  dev_name(dev));
191                 return 0;
192         }
193
194         if (!_munge_formats(pvd)) {
195                 log_very_verbose("format1: Unknown metadata version %d "
196                                  "found on %s", pvd->version, dev_name(dev));
197                 return 0;
198         }
199
200         /* If VG is exported, set VG name back to the real name */
201         _munge_exported_vg(pvd);
202
203         return 1;
204 }
205
206 static int _read_pvd(struct device *dev, struct pv_disk *pvd)
207 {
208         if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
209                 log_very_verbose("Failed to read PV data from %s",
210                                  dev_name(dev));
211                 return 0;
212         }
213
214         return munge_pvd(dev, pvd);
215 }
216
217 static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
218 {
219         if (!dev_read(dev, pos, sizeof(*disk), disk))
220                 return_0;
221
222         _xlate_lvd(disk);
223
224         return 1;
225 }
226
227 int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
228 {
229         uint64_t pos = pvd->vg_on_disk.base;
230
231         if (!dev_read(dev, pos, sizeof(*vgd), vgd))
232                 return_0;
233
234         _xlate_vgd(vgd);
235
236         if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
237                 return_0;
238                 
239         /* If UUID is missing, create one */
240         if (vgd->vg_uuid[0] == '\0')
241                 uuid_from_num((char *)vgd->vg_uuid, vgd->vg_number);
242
243         return 1;
244 }
245
246 static int _read_uuids(struct disk_list *data)
247 {
248         unsigned num_read = 0;
249         struct uuid_list *ul;
250         char buffer[NAME_LEN] __attribute__((aligned(8)));
251         uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
252         uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
253
254         while (pos < end && num_read < data->vgd.pv_cur) {
255                 if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
256                         return_0;
257
258                 if (!(ul = dm_pool_alloc(data->mem, sizeof(*ul))))
259                         return_0;
260
261                 memcpy(ul->uuid, buffer, NAME_LEN);
262                 ul->uuid[NAME_LEN - 1] = '\0';
263
264                 dm_list_add(&data->uuids, &ul->list);
265
266                 pos += NAME_LEN;
267                 num_read++;
268         }
269
270         return 1;
271 }
272
273 static int _check_lvd(struct lv_disk *lvd)
274 {
275         return !(lvd->lv_name[0] == '\0');
276 }
277
278 static int _read_lvs(struct disk_list *data)
279 {
280         unsigned int i, lvs_read = 0;
281         uint64_t pos;
282         struct lvd_list *ll;
283         struct vg_disk *vgd = &data->vgd;
284
285         for (i = 0; (i < vgd->lv_max) && (lvs_read < vgd->lv_cur); i++) {
286                 pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
287                 ll = dm_pool_alloc(data->mem, sizeof(*ll));
288
289                 if (!ll)
290                         return_0;
291
292                 if (!_read_lvd(data->dev, pos, &ll->lvd))
293                         return_0;
294
295                 if (!_check_lvd(&ll->lvd))
296                         continue;
297
298                 lvs_read++;
299                 dm_list_add(&data->lvds, &ll->list);
300         }
301
302         return 1;
303 }
304
305 static int _read_extents(struct disk_list *data)
306 {
307         size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
308         struct pe_disk *extents = dm_pool_alloc(data->mem, len);
309         uint64_t pos = data->pvd.pe_on_disk.base;
310
311         if (!extents)
312                 return_0;
313
314         if (!dev_read(data->dev, pos, len, extents))
315                 return_0;
316
317         _xlate_extents(extents, data->pvd.pe_total);
318         data->extents = extents;
319
320         return 1;
321 }
322
323 static void __update_lvmcache(const struct format_type *fmt,
324                               struct disk_list *dl,
325                               struct device *dev, const char *vgid,
326                               unsigned exported)
327 {
328         struct lvmcache_info *info;
329         const char *vgname = *((char *)dl->pvd.vg_name) ?
330                              (char *)dl->pvd.vg_name : fmt->orphan_vg_name;
331
332         if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
333                                   vgname, vgid, exported ? EXPORTED_VG : 0))) {
334                 stack;
335                 return;
336         }
337
338         info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
339         dm_list_init(&info->mdas);
340         info->status &= ~CACHE_INVALID;
341 }
342
343 static struct disk_list *__read_disk(const struct format_type *fmt,
344                                      struct device *dev, struct dm_pool *mem,
345                                      const char *vg_name)
346 {
347         struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
348         const char *name = dev_name(dev);
349
350         if (!dl)
351                 return_NULL;
352
353         dl->dev = dev;
354         dl->mem = mem;
355         dm_list_init(&dl->uuids);
356         dm_list_init(&dl->lvds);
357
358         if (!_read_pvd(dev, &dl->pvd))
359                 goto_bad;
360
361         /*
362          * is it an orphan ?
363          */
364         if (!*dl->pvd.vg_name) {
365                 log_very_verbose("%s is not a member of any format1 VG", name);
366
367                 __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
368                 return (vg_name) ? NULL : dl;
369         }
370
371         if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
372                 log_error("Failed to read VG data from PV (%s)", name);
373                 __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
374                 goto bad;
375         }
376
377         if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
378                 log_very_verbose("%s is not a member of the VG %s",
379                                  name, vg_name);
380                 __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
381                 goto bad;
382         }
383
384         __update_lvmcache(fmt, dl, dev, (char *)dl->vgd.vg_uuid,
385                           dl->vgd.vg_status & VG_EXPORTED);
386
387         if (!_read_uuids(dl)) {
388                 log_error("Failed to read PV uuid list from %s", name);
389                 goto bad;
390         }
391
392         if (!_read_lvs(dl)) {
393                 log_error("Failed to read LV's from %s", name);
394                 goto bad;
395         }
396
397         if (!_read_extents(dl)) {
398                 log_error("Failed to read extents from %s", name);
399                 goto bad;
400         }
401
402         log_very_verbose("Found %s in %sVG %s", name,
403                          (dl->vgd.vg_status & VG_EXPORTED) ? "exported " : "",
404                          dl->pvd.vg_name);
405
406         return dl;
407
408       bad:
409         dm_pool_free(dl->mem, dl);
410         return NULL;
411 }
412
413 struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
414                             struct dm_pool *mem, const char *vg_name)
415 {
416         struct disk_list *dl;
417
418         if (!dev_open(dev))
419                 return_NULL;
420
421         dl = __read_disk(fmt, dev, mem, vg_name);
422
423         if (!dev_close(dev))
424                 stack;
425
426         return dl;
427 }
428
429 static void _add_pv_to_list(struct dm_list *head, struct disk_list *data)
430 {
431         struct pv_disk *pvd;
432         struct disk_list *diskl;
433
434         dm_list_iterate_items(diskl, head) {
435                 pvd = &diskl->pvd;
436                 if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid,
437                              sizeof(pvd->pv_uuid))) {
438                         if (!dev_subsystem_part_major(data->dev)) {
439                                 log_very_verbose("Ignoring duplicate PV %s on "
440                                                  "%s", pvd->pv_uuid,
441                                                  dev_name(data->dev));
442                                 return;
443                         }
444                         log_very_verbose("Duplicate PV %s - using %s %s",
445                                          pvd->pv_uuid, dev_subsystem_name(data->dev),
446                                          dev_name(data->dev));
447                         dm_list_del(&diskl->list);
448                         break;
449                 }
450         }
451         dm_list_add(head, &data->list);
452 }
453
454 /*
455  * Build a list of pv_d's structures, allocated from mem.
456  * We keep track of the first object allocated from the pool
457  * so we can free off all the memory if something goes wrong.
458  */
459 int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
460                    struct dev_filter *filter, struct dm_pool *mem,
461                    struct dm_list *head)
462 {
463         struct dev_iter *iter;
464         struct device *dev;
465         struct disk_list *data = NULL;
466         struct lvmcache_vginfo *vginfo;
467         struct lvmcache_info *info;
468
469         /* Fast path if we already saw this VG and cached the list of PVs */
470         if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
471             vginfo->infos.n) {
472                 dm_list_iterate_items(info, &vginfo->infos) {
473                         dev = info->dev;
474                         if (!dev || !(data = read_disk(fmt, dev, mem, vg_name)))
475                                 break;
476                         _add_pv_to_list(head, data);
477                 }
478
479                 /* Did we find the whole VG? */
480                 if (!vg_name || is_orphan_vg(vg_name) ||
481                     (data && *data->pvd.vg_name &&
482                      dm_list_size(head) == data->vgd.pv_cur))
483                         return 1;
484
485                 /* Failed */
486                 dm_list_init(head);
487                 /* vgcache_del(vg_name); */
488         }
489
490         if (!(iter = dev_iter_create(filter, 1))) {
491                 log_error("read_pvs_in_vg: dev_iter_create failed");
492                 return 0;
493         }
494
495         /* Otherwise do a complete scan */
496         for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
497                 if ((data = read_disk(fmt, dev, mem, vg_name))) {
498                         _add_pv_to_list(head, data);
499                 }
500         }
501         dev_iter_destroy(iter);
502
503         if (dm_list_empty(head))
504                 return 0;
505
506         return 1;
507 }
508
509 static int _write_vgd(struct disk_list *data)
510 {
511         struct vg_disk *vgd = &data->vgd;
512         uint64_t pos = data->pvd.vg_on_disk.base;
513
514         log_debug("Writing %s VG metadata to %s at %" PRIu64 " len %" PRIsize_t,
515                   data->pvd.vg_name, dev_name(data->dev), pos, sizeof(*vgd));
516
517         _xlate_vgd(vgd);
518         if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
519                 return_0;
520
521         _xlate_vgd(vgd);
522
523         return 1;
524 }
525
526 static int _write_uuids(struct disk_list *data)
527 {
528         struct uuid_list *ul;
529         uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
530         uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
531
532         dm_list_iterate_items(ul, &data->uuids) {
533                 if (pos >= end) {
534                         log_error("Too many uuids to fit on %s",
535                                   dev_name(data->dev));
536                         return 0;
537                 }
538
539                 log_debug("Writing %s uuidlist to %s at %" PRIu64 " len %d",
540                           data->pvd.vg_name, dev_name(data->dev),
541                           pos, NAME_LEN);
542
543                 if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
544                         return_0;
545
546                 pos += NAME_LEN;
547         }
548
549         return 1;
550 }
551
552 static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
553 {
554         log_debug("Writing %s LV %s metadata to %s at %" PRIu64 " len %"
555                   PRIsize_t, disk->vg_name, disk->lv_name, dev_name(dev),
556                   pos, sizeof(*disk));
557
558         _xlate_lvd(disk);
559         if (!dev_write(dev, pos, sizeof(*disk), disk))
560                 return_0;
561
562         _xlate_lvd(disk);
563
564         return 1;
565 }
566
567 static int _write_lvs(struct disk_list *data)
568 {
569         struct lvd_list *ll;
570         uint64_t pos, offset;
571
572         pos = data->pvd.lv_on_disk.base;
573
574         if (!dev_set(data->dev, pos, data->pvd.lv_on_disk.size, 0)) {
575                 log_error("Couldn't zero lv area on device '%s'",
576                           dev_name(data->dev));
577                 return 0;
578         }
579
580         dm_list_iterate_items(ll, &data->lvds) {
581                 offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
582                 if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
583                         log_error("lv_number %d too large", ll->lvd.lv_number);
584                         return 0;
585                 }
586
587                 if (!_write_lvd(data->dev, pos + offset, &ll->lvd))
588                         return_0;
589         }
590
591         return 1;
592 }
593
594 static int _write_extents(struct disk_list *data)
595 {
596         size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
597         struct pe_disk *extents = data->extents;
598         uint64_t pos = data->pvd.pe_on_disk.base;
599
600         log_debug("Writing %s extents metadata to %s at %" PRIu64 " len %"
601                   PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
602                   pos, len);
603
604         _xlate_extents(extents, data->pvd.pe_total);
605         if (!dev_write(data->dev, pos, len, extents))
606                 return_0;
607
608         _xlate_extents(extents, data->pvd.pe_total);
609
610         return 1;
611 }
612
613 static int _write_pvd(struct disk_list *data)
614 {
615         char *buf;
616         uint64_t pos = data->pvd.pv_on_disk.base;
617         size_t size = data->pvd.pv_on_disk.size;
618
619         if (size < sizeof(struct pv_disk)) {
620                 log_error("Invalid PV structure size.");
621                 return 0;
622         }
623
624         /* Make sure that the gap between the PV structure and
625            the next one is zeroed in order to make non LVM tools
626            happy (idea from AED) */
627         buf = dm_zalloc(size);
628         if (!buf) {
629                 log_error("Couldn't allocate temporary PV buffer.");
630                 return 0;
631         }
632
633         memcpy(buf, &data->pvd, sizeof(struct pv_disk));
634
635         log_debug("Writing %s PV metadata to %s at %" PRIu64 " len %"
636                   PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
637                   pos, size);
638
639         _xlate_pvd((struct pv_disk *) buf);
640         if (!dev_write(data->dev, pos, size, buf)) {
641                 dm_free(buf);
642                 return_0;
643         }
644
645         dm_free(buf);
646         return 1;
647 }
648
649 /*
650  * assumes the device has been opened.
651  */
652 static int __write_all_pvd(const struct format_type *fmt __attribute__((unused)),
653                            struct disk_list *data)
654 {
655         const char *pv_name = dev_name(data->dev);
656
657         if (!_write_pvd(data)) {
658                 log_error("Failed to write PV structure onto %s", pv_name);
659                 return 0;
660         }
661
662         /* vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, fmt); */
663         /*
664          * Stop here for orphan pv's.
665          */
666         if (data->pvd.vg_name[0] == '\0') {
667                 /* if (!test_mode())
668                    vgcache_add(data->pvd.vg_name, NULL, data->dev, fmt); */
669                 return 1;
670         }
671
672         /* if (!test_mode())
673            vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev,
674            fmt); */
675
676         if (!_write_vgd(data)) {
677                 log_error("Failed to write VG data to %s", pv_name);
678                 return 0;
679         }
680
681         if (!_write_uuids(data)) {
682                 log_error("Failed to write PV uuid list to %s", pv_name);
683                 return 0;
684         }
685
686         if (!_write_lvs(data)) {
687                 log_error("Failed to write LV's to %s", pv_name);
688                 return 0;
689         }
690
691         if (!_write_extents(data)) {
692                 log_error("Failed to write extents to %s", pv_name);
693                 return 0;
694         }
695
696         return 1;
697 }
698
699 /*
700  * opens the device and hands to the above fn.
701  */
702 static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
703 {
704         int r;
705
706         if (!dev_open(data->dev))
707                 return_0;
708
709         r = __write_all_pvd(fmt, data);
710
711         if (!dev_close(data->dev))
712                 stack;
713
714         return r;
715 }
716
717 /*
718  * Writes all the given pv's to disk.  Does very
719  * little sanity checking, so make sure correct
720  * data is passed to here.
721  */
722 int write_disks(const struct format_type *fmt, struct dm_list *pvs)
723 {
724         struct disk_list *dl;
725
726         dm_list_iterate_items(dl, pvs) {
727                 if (!(_write_all_pvd(fmt, dl)))
728                         return_0;
729
730                 log_very_verbose("Successfully wrote data to %s",
731                                  dev_name(dl->dev));
732         }
733
734         return 1;
735 }